[
  {
    "path": ".gitignore",
    "content": ".DS_Store\ndist/\ndist/zepto.min.js\ndist/zepto.js\npkg\n*.swp\ndocs/*\n.jhw-cache\n.rbenv-version\npublic\nnode_modules\ntemp/\nnpm-debug.log"
  },
  {
    "path": ".npmignore",
    "content": "*\n!README.md\n!MIT-LICENSE\n!dist/zepto.js\n!dist/zepto.min.js\n!src/*.js\nsrc/amd_layout.js\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\n\nnode_js: '0.10'\n\nsudo: false\n\nscript: script/test\n\nnotifications:\n  campfire:\n    template: '%{message} [%{branch}] %{repository}/%{commit} %{author} %{build_url}'\n    rooms:\n      secure: VR6rWk0YhezBWnD8jPjSD8h/Q83S3NT0F34Au1vswt+/+Ku19S8X44vGVUG+NYdYyhg7uOqUaPN1Jr3KCpdcXgHEpUYiyBGJ8ebltavcjeHYWqK6ghcqgSnbDkifuC7Eu/9LcrOMOXgt+zkXjiVXW3+zyGVDcrs4cQ2vGY2DTYA=\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Contributing to Zepto\n\n**Thanks for helping out!**\n\nIn order for your code to make it in, several conditions must be met:\n\n* It's more likely your pull request will make it in if you adhere to **Zepto's\n  project goals**. Be sure to read the README in its entirety before setting out\n  to code.\n* Please talk to the maintainers (@madrobby and @mislav) first if you want\n  to write a plugin, those are better kept in their own repositories.\n* Fix only ONE thing or have only ONE feature in your pull request. \n  If you have multiple unrelated code updates, please submit a separate pull request for each one.\n* **Your pull request must be written in English and be accompanied by a\n  detailed description**, ideally something we can use as documentation.\n  If you're not fluent in English, try your best and let us know so we'll help!\n* Changes to jQuery-based API methods **must match their jQuery counterparts**.\n* Please **do not just copy code from jQuery**. Zepto strives for API compatibility,\n  but has different goals for code style and size and target platforms.\n  In case you do copy code, you must clearly indicate the origin of the code, and\n  which license applies to it. However, it is likely your patch will be denied.\n* **All code must have tests, and all tests must pass.** See the README on running the test suite.\n* Please **also test manually** on as many target platforms you have access to,\n  but at least on latest Chrome (desktop) and Firefox (desktop).\n  See http://zeptojs.com for a full list of platforms.\n* It's required that you follow Zepto's **code style guidelines** (see below)\n\nWhew, now that we have that out of the way thanks again!\n\n## Code style guidelines\n\n* Two spaces \"soft tabs\" indentation\n* Remove any trailing whitespace from the end of lines\n* `function name() { }` for named functions\n* `function(){ }` for anonymous functions\n* No curly braces for single-line control flow statements such as `if` & friends\n* Don't write [semicolons that are optional][optional]\n* Put a single semicolon _before_ statements that start with `(` or `[`\n  (see above article as for why it's needed)\n* Use long, descriptive variable and method names\n* Use blank lines to separate \"paragraphs\" of code for readability\n* Use comments to describe non-obvious code behavior\n\n\n  [optional]: http://mislav.uniqpath.com/2010/05/semicolons/\n"
  },
  {
    "path": "MIT-LICENSE",
    "content": "Copyright (c) 2010-2025 Thomas Fuchs\nhttp://zeptojs.com/\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Zepto.js – a minimalist JavaScript library\n\nZepto is a minimalist JavaScript library for modern browsers with a\nlargely jQuery-compatible API. If you use jQuery, you already know how to use Zepto.\n\nSee [zeptojs.com][] for an extended introduction, downloads\nand documentation.\n\nZepto.js is licensed under the terms of the MIT License.\n\nWant to give us money or a tip? Don't.\nInstead please donate to [charity: water](http://charitywater.org/).\n\n## Building\n\n[![Build Status](https://secure.travis-ci.org/madrobby/zepto.svg?branch=master)](http://travis-ci.org/madrobby/zepto)\n\nThe official site offers a download of the default distribution of Zepto. This\nis good for starting out. However, at some point you might want to add some\noptional modules and remove some of the default ones you don't need, to keep the\nsize at a minimum. That's when you need to check out Zepto's source code and use\nthe build commands.\n\nYou will need Node.js installed on your system.\n\n~~~ sh\n$ npm install\n$ npm run-script dist\n\n# do a custom build\n$ MODULES=\"zepto event data\" npm run-script dist\n\n# on Windows\nc:\\zepto> SET MODULES=zepto event data\nc:\\zepto> npm run-script dist\n~~~\n\nThe resulting files are:\n\n1. `dist/zepto.js`\n2. `dist/zepto.min.js`\n\nIf you install CoffeeScript globally, you can run `make` directly:\n\n~~~ sh\n# one-time operation\n$ npm install coffee-script --global\n\n$ coffee make dist\n$ MODULES=\"zepto event data ...\" ./make dist\n\n# on Windows\nc:\\zepto> SET MODULES=zepto event data\nc:\\zepto> coffee make dist\n~~~\n\n## Zepto modules\n\nZepto modules are individual files in the \"src/\" directory.\n\n<table>\n<thead><tr>\n  <th>module</th> <th>default</th> <th>description</th>\n</tr></thead>\n<tbody>\n  <tr>\n    <th><a href=\"src/zepto.js#files\">zepto</a></th>\n    <td>✔</td>\n    <td>Core module; contains most methods</td>\n  </tr>\n  <tr>\n    <th><a href=\"src/event.js#files\">event</a></th>\n    <td>✔</td>\n    <td>Event handling via <code>on()</code> &amp; <code>off()</code></td>\n  </tr>\n  <tr>\n    <th><a href=\"src/ajax.js#files\">ajax</a></th>\n    <td>✔</td>\n    <td>XMLHttpRequest and JSONP functionality</td>\n  </tr>\n  <tr>\n    <th><a href=\"src/form.js#files\">form</a></th>\n    <td>✔</td>\n    <td>Serialize &amp; submit web forms</td>\n  </tr>\n  <tr>\n    <th><a href=\"src/ie.js#files\">ie</a></th>\n    <td>✔</td>\n    <td>Support for Internet Explorer 10+ on the desktop and Windows Phone 8</td>\n  </tr>\n  <tr>\n    <th><a href=\"src/detect.js#files\">detect</a></th>\n    <td></td>\n    <td>Provides <code>$.os</code> and <code>$.browser</code> information</td>\n  </tr>\n  <tr>\n    <th><a href=\"src/fx.js#files\">fx</a></th>\n    <td></td>\n    <td>The <code>animate()</code> method</td>\n  </tr>\n  <tr>\n    <th><a href=\"src/fx_methods.js#files\">fx_methods</a></th>\n    <td></td>\n    <td>\n      Animated <code>show</code>, <code>hide</code>, <code>toggle</code>,\n      and <code>fade*()</code> methods.\n    </td>\n  </tr>\n  <tr>\n    <th><a href=\"src/assets.js#files\">assets</a></th>\n    <td></td>\n    <td>\n      Experimental support for cleaning up iOS memory after removing\n      image elements from the DOM.\n    </td>\n  </tr>\n  <tr>\n    <th><a href=\"src/data.js#files\">data</a></th>\n    <td></td>\n    <td>\n      A full-blown <code>data()</code> method, capable of storing arbitrary\n      objects in memory.\n    </td>\n  </tr>\n  <tr>\n    <th><a href=\"src/deferred.js#files\">deferred</a></th>\n    <td></td>\n    <td>\n      Provides <code>$.Deferred</code> promises API.\n      Depends on the \"callbacks\" module.\n    </td>\n  </tr>\n  <tr>\n    <th><a href=\"src/callbacks.js#files\">callbacks</a></th>\n    <td></td>\n    <td>\n      Provides <code>$.Callbacks</code> for use in \"deferred\" module.\n    </td>\n  </tr>\n  <tr>\n    <th><a href=\"src/selector.js#files\">selector</a></th>\n    <td></td>\n    <td>\n      Experimental <a href=\"http://api.jquery.com/category/selectors/jquery-selector-extensions/\">jQuery\n      CSS extensions</a> support for functionality such as <code>$('div:first')</code> and\n      <code>el.is(':visible')</code>.\n    </td>\n  </tr>\n  <tr>\n    <th><a href=\"src/touch.js#files\">touch</a></th>\n    <td></td>\n    <td>\n      Fires tap– and swipe–related events on touch devices. This works with both\n      `touch` (iOS, Android) and `pointer` events (Windows Phone).\n    </td>\n  </tr>\n  <tr>\n    <th><a href=\"src/gesture.js#files\">gesture</a></th>\n    <td></td>\n    <td>Fires pinch gesture events on touch devices</td>\n  </tr>\n  <tr>\n    <th><a href=\"src/stack.js#files\">stack</a></th>\n    <td></td>\n    <td>Provides <code>andSelf</code> &amp; <code>end()</code> chaining methods</td>\n  </tr>\n  <tr>\n    <th><a href=\"src/ios3.js#files\">ios3</a></th>\n    <td></td>\n    <td>\n      String.prototype.trim and Array.prototype.reduce methods\n      (if they are missing) for compatibility with iOS 3.x.\n    </td>\n  </tr>\n</tbody>\n</table>\n\n## Contributing\n\nPlease read our [contribution guidelines](https://github.com/madrobby/zepto/blob/master/CONTRIBUTING.md)\nfor information on how to contribute.\n\nGet in touch:\n\n* @[zeptojs](http://twitter.com/zeptojs)\n\n### Write documentation\n\nZepto docs are written in Markdown and live in the [\"gh-pages\" branch][docs].\nThey are published on [zeptojs.com][zeptojs.com].\n\nYou can use GitHub's web interface to make quick changes to documentation for\nspecific Zepto features\n([example: ajaxSettings](https://github.com/madrobby/zepto/blob/gh-pages/ajax/_posts/1900-01-01-Z-ajaxSettings.md)).\nThis will submit a pull request to us that we can review.\n\n### Report a bug\n\n1. Check if the bug is already fixed in the master branch since the last release.\n2. Check [existing issues][issues]. Open a new one, including exact browser &\n   platform information. For better formatting of your report, see\n   [GitHub-flavored Markdown][mkd].\n\n### Running tests\n\nYou will need to install [PhantomJS][phantomjs]. On OS X, that's easy:\n\n~~~ sh\n$ brew install phantomjs\n~~~\n\nTo run the automated tests:\n\n~~~ sh\n$ npm test\n~~~\n\nTo run a test server, which you can hit with your browsers and devices:\n\n~~~ sh\n$ npm start\n~~~\n\nGo to `http://your-ip-address:3000/` on your browser and follow the\ninstructions. For your convenience test failures and exceptions will be\nreported to the the console you started the test server in (as well as\nthe browser console if available).\n\n  [zeptojs.com]: http://zeptojs.com\n  [issues]: https://github.com/madrobby/zepto/issues\n  [docs]: https://github.com/madrobby/zepto/tree/gh-pages#readme\n  [mkd]: https://help.github.com/articles/creating-and-highlighting-code-blocks/\n  [evidence.js]: https://github.com/tobie/Evidence\n  [phantomjs]: http://phantomjs.org/download.html\n"
  },
  {
    "path": "examples/anim.html",
    "content": "<div style=\"width:100px;height:100px;border:1px solid black\">HELLO WORLD</div>\n\n<script src=\"../src/zepto.js\"></script>\n<script src=\"../src/event.js\"></script>\n<script src=\"../src/fx.js\"></script>\n\n<script>\n  $('div').anim({ rotate: '720deg', opacity: .5 }, 2, 'ease-out')\n</script>\n"
  },
  {
    "path": "examples/iphone/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n      <title>iPhone.Zepto</title>\n      <link href=\"iphone.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\"/>\n      <meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n      <meta name=\"format-detection\" content=\"telephone=no\" />\n    </head>\n    <body>\n      <section id=\"menu\">\n        <div class=\"toolbar\">\n          <h1>Title</h1>\n        </div>\n        <ul class=\"menu\">\n          <li class=\"arrow\"><a href=\"#menu_1\">Menu 1</a></li>\n          <li>Menu 1</li>\n          <li>Menu 1</li>\n          <li>Menu 1</li>\n          <li>Menu 1</li>\n        </ul>\n      </section>\n      <section id=\"menu_1\">\n        <div class=\"toolbar\">\n          <h1>Menu 1</h1>\n        </div>\n        <ul class=\"menu\">\n          <li>SubMenu 1</li>\n          <li>SubMenu 2</li>\n        </ul>\n      </section>\n      <script src=\"../../src/zepto.js\"></script>\n      <script src=\"../../src/event.js\"></script>\n      <script src=\"../../src/touch.js\"></script>\n      <script>\n        $(document).ready(function(){\n          var activate = ('createTouch' in document) ? 'touchstart' : 'click'\n\n          $(\"body > section\").first().addClass(\"current\")\n\n          $(\"a.back\").live(activate, function(event) {\n            var current = $(this).attr(\"href\")\n            $(\".current\").removeClass(\"current\").addClass(\"reverse\")\n            $(current).addClass(\"current\")\n          })\n\n          $(\".menu a[href]\").live(activate, function(event) {\n            var link = $(this), section = link.closest('section'),\n              prev_element = \"#\"+(section.removeClass(\"current\").addClass(\"reverse\").attr(\"id\"))\n            $(link.attr(\"href\")).addClass(\"current\")\n            $(\".current .back\").remove()\n            $(\".current .toolbar\").prepend(\"<a href=\\\"\"+prev_element+\"\\\" class=\\\"back\\\">Back</a>\")\n          })\n        })\n      </script>\n    </body>\n</html>\n"
  },
  {
    "path": "examples/iphone/iphone.css",
    "content": "* {\n  margin: 0px;\n  padding: 0px;\n}\n.toolbar {\n  -webkit-box-sizing: border-box;\n  background: #6D84A2 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAArCAIAAAA2QHWOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNpNjCEOgEAQA5v9/9eQaAQCd57L0WXTDSmimXZEse1HnNcIIINZYTPVv7Ac4/EWe7OTsC/ec+nDgcj/dpcH7EXt8up4AfRWcOjLIqWFAAAAAElFTkSuQmCC) repeat-x;\n  border-bottom: 1px solid #2D3642;\n  height: 45px;\n  padding: 10px;\n  position: relative;\n}\nbody {\n  -webkit-perspective: 800;\n  -webkit-text-size-adjust: none;\n  -webkit-transform-style: preserve-3d;\n  -webkit-user-select: none;\n  font-family: Helvetica;\n  overflow-x: hidden;\n  height: 100%;\n  width: 100%;\n}\n\nbody > section {\n  background: #C5CCD3 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAABCAIAAACdaSOZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABdJREFUeNpiPHrmCgMC/GNjYwNSAAEGADdNA3dnzPlQAAAAAElFTkSuQmCC);\n  display: block;\n  left: 0px;\n  position: absolute;\n  width: 100%;\n  -webkit-transform: translate3d(100%,0%,0%);\n  opacity: 0;\n  -webkit-transition: all 0.25s ease-in-out;\n  -webkit-transform-style: preserve-3d;\n  z-index: -10;\n}\n\n.reverse {\n  -webkit-transform: translate3d(-100%, 0%, 0%);\n  opacity: 0;\n}\n\n.current {\n  -webkit-transform: translate3d(0%,0%, 0%);\n  opacity: 1;\n  z-index: 1;\n}\nh1, h2 {\n  color: #4C566C;\n  font: normal normal bold 18px/normal Helvetica;\n  margin: 10px 20px 6px;\n  text-shadow: rgba(255, 255, 255, 0.19)\n}\nbody.landscape .toolbar > h1 {\n  margin-left: -125px;\n  width: 250px;\n}\n\n.toolbar > h1 {\n  color: white;\n  font-size: 20px;\n  font-weight: bold;\n  height: 40px;\n  left: 50%;\n  line-height: 1em;\n  margin: 1px 0px 0px -75px;\n  overflow: hidden;\n  position: absolute;\n  text-align: center;\n  text-overflow: ellipsis;\n  text-shadow: rgba(0, 0, 0, 0.398438) 0px -1px 0px;\n  top: 10px;\n  white-space: nowrap;\n  width: 150px;\n}\n\nul {\n  background: white;\n  border: 1px solid #B4B4B4;\n  border-bottom-left-radius: 8px 8px;\n  border-bottom-right-radius: 8px 8px;\n  border-top-left-radius: 8px 8px;\n  border-top-right-radius: 8px 8px;\n  color: black;\n  font: normal normal bold 17px/normal Helvetica;\n  margin: 15px 10px 17px;\n  padding: 0px;\n}\n\nul li {\n  color: black;\n  font-size: 14px;\n  border-top: 1px solid #B4B4B4;\n  color: #666;\n  list-style-type: none;\n  padding: 10px;\n}\n\nli:first-child, li:first-child a {\n  border-top: 0px;\n  border-top-left-radius: 8px 8px;\n  border-top-right-radius: 8px 8px;\n}\n\nul li.arrow {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUCAYAAAB4d5a9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAKVJREFUeNpi/P//PwOtARMDHcDwsYQFRJSXl8P4dVC6CZvizs5O8i1BsqARid9Ei+BiQ2KDLKumhSU1QNyKxG+hlkXoEQ+yqAPNogpapK5KNIvaKbUIVxKeAsTvkPg5QCxETUukgfgAkqFPgdgBzVKKLIFZoIJmwR1qBRdNLEC2BJQpV9LCAmRL/gBxAtRwqlqAXqzcgRrOQE0LQIBxtNIiBQAEGAA7xCa2yF9zEgAAAABJRU5ErkJggg==);\n  background-position: 100% 50%;\n  background-repeat: no-repeat;\n}\n\nbody > .current {\n  display: block !important;\n}\n\nbody.landscape > * {\n  min-height: 320px;\n}\n\n\nul li a, li.img a + a {\n  color: black;\n  display: block;\n  margin: -10px;\n  overflow: hidden;\n  padding: 12px 10px;\n  text-decoration: none;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n\n.button, .back, .cancel, .add {\n-webkit-border-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAeCAIAAACqmwlGAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAatJREFUeNqVlMtKw0AUhqfJSRpTk5Za1FAvxS6sgrVeFrpQdOcT+IpuBVHcuVBQpCDYjeAdkSpavDTGNJkz43FpFZz8DISZ+b75J5tJbWwfMsZuby7rh/vN5v1H+539TMZxPa84v7g0WirTFISQR/t7jdOTcqVaGp+ze50uIfDbL62H3a3NqerMwtIqXF9dnF+dL6+t9/S6hmFqut4luHns80aKpcrxwY43PKK7+f6J2ZVcYTCl6ZIxKuwatEhbpmU72UKjfgCakXFz/TwW7L8QlgIbTNtBwVAgU0g644IGZoycqYVgQGRRLBQFggEpHJUFBI4iUhYIBhSSPooCwUB0zEWiBsERlRsECJSIUlEgOHmDH3TM909FgWBgqe8oCgRrLGGADlcvIDB5A2nfQ7kD6D5J/jn5lZILBoAUQgWVUgDoWi5r8zhUEXgU5nOOVp0sB+0W+f8WEDY9MabpYNUqQ29Pd1Hoi79eA1qkLQIIY5CGIOwUvYHBQr5xdvn4/BSGnS7BstIDhexUbVo3jNarD1Ky5xfftszF+WqPZcKvp5IjfoYRoYHv0/QLHvXjAb8xkEMAAAAASUVORK5CYII=) 0 5 0 5 stretch stretch;\nbackground: none;\nborder-width: 0px 5px;\ncolor: white;\nfont-family: inherit;\nfont-size: 12px;\nfont-weight: bold;\nheight: 30px;\nline-height: 30px;\nmargin: 0px;\noverflow: ;\npadding: 0px 3px;\nposition: absolute;\nright: 6px;\ntext-decoration: none;\ntext-overflow: ellipsis;\ntext-shadow: rgba(0, 0, 0, 0.496094) 0px -1px 0px;\ntop: 8px;\nwhite-space: nowrap;\nwidth: auto;\n}\n\n.back {\n  -webkit-border-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACsAAAAeCAIAAAA6iHCJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAArFJREFUeNrF0mtPE2EQBeB5t9vSRqEUKiAFkasggmC5x3CRECHx8sH/qMHEoKkiMUQTNJIIaAjeiFGUcEsotN22u9vtOzMKogYL39rlyfkBk3NG3HsyC8dLJhOzM8+/fvkcjexAtghRXVN/dXCkvOIcAKhEDMdY+7ESejgeqKpv7x3J9/ogS5hoc33l0YPxju6+YFefSkRwlI311cnQRM/gbd+ZUpfb43CokD2nCv2lFbVvZib9JaUqMUEGTYtNPZ7oHLpZXBJQFIUYSCJkj3A4830lrd3Di2/nVcxYwTSMift3m4LXCovKCYGQIDe8vrJveNQfTE+Fys9f8pdVSSTILeFyF/z/B8uflnSLG+qakRlRQo45XO5DHejJxOtXLzsG7yA7ME2Qe0hw6A+mn4ZqLvY4XR6UCLZAxH8rfFx6Z6BaXVJlSQS7SKSDC+JabGFurrnvBvJ+NXZBYpX4oP9AQ5eietKSAMDuDt4vLkhHfr6/XCKCvZBIjezuLMzPN/XcIhIADPYiZPXFs8lAQ7dwOA8KsL8Dr7/CoDzSDDgJCT2ljI0OOzBGKMVJACGUXU2/3h/Uo5vMDCdBQSRLcn9nox7bEgLsDoDCDKYli4p89ZXFZjJ6Ah3wvlhcb2mqPa1a0jIBhJ1RiPl3wpH4QG+bTGwDo51DKPwHMccS5mBvSzyyCcB2rgB/k5aoqK72xgo9FrbxgsMSulkZOBvwu1O6BjnGhO48p8IZfj1EsPWCR+jSMiCX0pbh9xXsrZCZrW1toOcy6mFMpyA3mNnUwi2NtQoxZwaZwzF9bKhTpHaN+C7KNGQPobTMhBZe7Wyts1iox729RNyOJkeHOj4sf19Z3YgmsraI251X6ve2BYMEIqIlVebjd0rj2la0rrrySkuDU1UhSySiYVrbkbiZ2qv2J5+53J2yzo3SAAAAAElFTkSuQmCC) 0 8 0 14 stretch stretch;\nborder-width: 0px 8px 0px 14px;\nleft: 6px;\nmax-width: 55px;\npadding: 0px;\nright: auto;\n}\n"
  },
  {
    "path": "examples/load_jquery_on_ie.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>Load jQuery if Zepto is not supported</title>\n</head>\n<body>\n  <h1>Load jQuery if Zepto is not supported</h1>\n</body>\n<script>document.write('<script src='+('__proto__' in {} ? '../dist/zepto' : 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery')+'.js><\\/script>')</script>\n<script>\n  $('body').append('<p>Hello from '+('Zepto' in window ? 'Zepto' : 'jQuery')+'!</p>')\n\n  $('script').each(function(index,script){\n    if (script.src)\n      $('<p>&lt;script src=\"'+script.src+'\"&gt;</p>').appendTo('body')\n  })\n</script>\n</html>\n"
  },
  {
    "path": "examples/snow/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Let it snow with Zepto.js</title>\n    <meta name=\"name\" content=\"content\">\n    <meta content=\"text/html; charset=utf-8\" http-equiv=\"Content-Type\">\n    <style>\n      body { background: #000; color: #fff; overflow: hidden }\n      div { position: absolute; }\n    </style>\n  </head>\n  <body>\n\n  <script src=\"../../src/zepto.js\"></script>\n  <script src=\"../../src/event.js\"></script>\n  <script src=\"../../src/fx.js\"></script>\n\n  <a href=\"https://twitter.com/share\" class=\"twitter-share-button\" data-url=\"http://zeptojs.com/let-it-snow\" data-text=\"Let it snow with Zepto.js\" data-via=\"zeptojs\" data-lang=\"en\">Tweet</a>\n  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=\"//platform.twitter.com/widgets.js\";fjs.parentNode.insertBefore(js,fjs);}}(document,\"script\",\"twitter-wjs\")</script>\n\n  <script>\n    $(document).ready(function(){\n      var i = 100, glyphs = '❄❅❆'.split('')\n\n      function rand(max){ return Math.floor(Math.random()*max) }\n\n      function addFlake(){\n        var el = $('<div><div>' + glyphs[rand(glyphs.length)] + '</div></div>')\n        $('body').append(el)\n        el.css({ left: rand(100)+'%', top: -100-rand(500), fontSize: 20+rand(30) })\n        el.anim(\n          { translateY: 1500+rand(500)+'px', translateX: 50-rand(100)+'px', rotate: (2e3-rand(4e3))+'deg' },\n          6+rand(10),\n          'linear',\n          function(){\n            addFlake()\n            el.remove() // garbage collect\n          }\n        )\n      }\n\n      while(i--) addFlake()\n\n      // enable for extra fun\n      //window.ondeviceorientation = function(event){\n      //  ('alpha' in event) && $('body').css({ '-webkit-transform': 'rotate('+event.alpha+'deg)'})\n      //}\n    })\n  </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/touch_events.html",
    "content": "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\"/>\n\n<script src=\"../src/zepto.js\"></script>\n<script src=\"../src/event.js\"></script>\n<script src=\"../src/touch.js\"></script>\n\n<style>\n  .delete {\n    display: none;\n    color: red;\n  }\n</style>\n\n<ul id=items>\n  <li>List item 1 <span class=delete>DELETE</span></li>\n  <li>List item 2 <span class=delete>DELETE</span></li>\n  <li>List item 3 <span class=delete>DELETE</span></li>\n  <li>List item 4 <span class=delete>DELETE</span></li>\n</ul>\n\n<script>\n$('#items li').swipe(function(){\n  $('.delete').hide()\n  $('.delete', this).show()\n})\n\n$('.delete').tap(function(){\n  $(this).parent('li').remove()\n})\n</script>\n"
  },
  {
    "path": "make",
    "content": "#!/usr/bin/env coffee\nrequire 'shelljs/make'\nfs = require 'fs'\n\nzepto_js  = 'dist/zepto.js'\nzepto_min = 'dist/zepto.min.js'\nzepto_gz  = 'dist/zepto.min.gz'\n\nport = 3999\nroot = __dirname + '/'\n\ntarget.all = ->\n  target[zepto_js]()\n  target.test()\n\n## TASKS ##\n\ntarget.test = ->\n  test_app = require './test/server'\n  server = test_app.listen port\n  exec \"phantomjs --disk-cache=true test/runner.js 'http://localhost:#{port}/'\", (code) ->\n    server.close -> exit(code)\n\ntarget[zepto_js] = ->\n  target.build() unless test('-e', zepto_js)\n\ntarget[zepto_min] = ->\n  target.minify() if stale(zepto_min, zepto_js)\n\ntarget[zepto_gz] = ->\n  target.compress() if stale(zepto_gz, zepto_min)\n\ntarget.dist = ->\n  target.build()\n  target.minify()\n  target.compress()\n\ntarget.build = ->\n  cd __dirname\n  mkdir '-p', 'dist'\n  modules = (env['MODULES'] || 'zepto event ajax form ie').split(' ')\n  module_files = ( \"src/#{module}.js\" for module in modules )\n  intro = \"/* Zepto #{describe_version()} - #{modules.join(' ')} - zeptojs.com/license */\\n\"\n  dist = cat(module_files).replace(/^\\/[\\/*].*$/mg, '').replace(/\\n{3,}/g, \"\\n\\n\")\n  dist = cat('src/amd_layout.js').replace(/YIELD/, -> dist.trim()) unless env['NOAMD']\n  (intro + dist).to(zepto_js)\n  report_size(zepto_js)\n\ntarget.minify = ->\n  target.build() unless test('-e', zepto_js)\n  zepto_code = cat(zepto_js)\n  intro = zepto_code.slice(0, zepto_code.indexOf(\"\\n\") + 1)\n  (intro + minify(zepto_code)).to(zepto_min)\n  report_size(zepto_min)\n\ntarget.compress = ->\n  gzip = require('zlib').createGzip()\n  inp = fs.createReadStream(zepto_min)\n  out = fs.createWriteStream(zepto_gz)\n  inp.pipe(gzip).pipe(out)\n  out.on 'close', ->\n    report_size(zepto_gz)\n    factor = fsize(zepto_js) / fsize(zepto_gz)\n    echo \"compression factor: #{format_number(factor)}\"\n\ntarget.publish = ->\n  tag = 'v' + package_version()\n  if git_version() == tag\n    rm '-f', zepto_js\n    env['MODULES'] = env['NOAMD'] = ''\n    target.dist()\n    res = exec 'npm publish'\n    exit res.code\n  else\n    console.error 'error: latest commit should be tagged with ' + tag\n    exit 1\n\n## HELPERS ##\n\nstale = (file, source) ->\n  target[source]()\n  !test('-e', file) || mtime(file) < mtime(source)\n\nmtime = (file) ->\n  fs.statSync(file).mtime.getTime()\n\nfsize = (file) ->\n  fs.statSync(file).size\n\nformat_number = (size, precision = 1) ->\n  factor = Math.pow(10, precision)\n  decimal = Math.round(size * factor) % factor\n  parseInt(size) + \".\" + decimal\n\nreport_size = (file) ->\n  echo \"#{file}: #{format_number(fsize(file) / 1024)} KiB\"\n\npackage_version = ->\n  JSON.parse(cat('package.json')).version\n\ngit_version = ->\n  desc = exec \"git --git-dir='#{root + '.git'}' describe --tags HEAD\", silent: true\n  desc.output.replace(/\\s+$/, '') if desc.code is 0\n\ndescribe_version = ->\n  git_version() || package_version()\n\nminify = (source_code) ->\n  uglify = require('uglify-js')\n  compressor = uglify.Compressor()\n  ast = uglify.parse(source_code)\n  ast.figure_out_scope()\n  ast.compute_char_frequency()\n  ast.mangle_names()\n  ast = ast.transform(compressor)\n  return ast.print_to_string()\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"zepto\",\n    \"version\": \"1.2.0\",\n    \"main\": \"dist/zepto.js\",\n    \"homepage\": \"http://zeptojs.com\",\n    \"scripts\": {\n        \"test\": \"coffee make test\",\n        \"dist\": \"coffee make dist\",\n        \"start\": \"coffee test/server.coffee\"\n    },\n    \"repository\": \"madrobby/zepto\",\n    \"license\": \"MIT\",\n    \"devDependencies\": {\n        \"uglify-js\": \"2.4.x\",\n        \"express\": \"3.1.x\",\n        \"coffee-script\": \"1.5.x\",\n        \"shelljs\": \"0.1.x\"\n    }\n}\n"
  },
  {
    "path": "script/bootstrap",
    "content": "#!/usr/bin/env bash\nset -e\n\nnpm install\n\nif phantom_version=\"$(phantomjs --version)\"; then\n  echo \"phantomjs ${phantom_version}\"\nelse\n  echo \"You should install PhantomJS for \\`script/test' to work.\" >&2\nfi\n"
  },
  {
    "path": "script/guard",
    "content": "#!/bin/sh\nif [ -z \"$BUNDLE_GEMFILE\" ]; then\n  export BUNDLE_GEMFILE=shutup\nfi\n\nexec guard --no-notify \"$@\"\n"
  },
  {
    "path": "script/lint",
    "content": "#!/usr/bin/awk -f\n\nBEGIN { if (length(ARGV) < 2) exit 0 }\n\n/<script/ { script=FILENAME }\n/<\\/script/ { script=\"\" }\n\n/;\\s*$/ && (FILENAME !~ /.html$/ || script == FILENAME) {\n  printf(\"%s:%d: no semicolons, please\\n\", FILENAME, FNR)\n  warns++\n}\n/\\t/ {\n  printf(\"%s:%d: use spaces instead of tabs\\n\", FILENAME, FNR)\n  warns++\n}\n\nEND { if (warns) exit 1 }\n"
  },
  {
    "path": "script/test",
    "content": "#!/usr/bin/env bash\nset -e\n\nport=3999\ntest_url=\"http://localhost:${port}/\"\n\nexport PATH=node_modules/.bin:\"$PATH\"\n\ngit ls-files \\*.js \\*.html | grep -v ^vendor/ | xargs script/lint\n\ncoffee test/server.coffee $port &\npid=$!\n\ncheck_test_server() {\n  curl -fsI \"$test_url\" >/dev/null\n}\n\nterminate_test_server() {\n  kill $pid\n}\n\ntries=1\nwhile ! check_test_server; do\n  if [ $((tries++)) -eq 20 ]; then\n    echo \"error: timed out while waiting for test server\" >&2\n    exit 1\n  fi\n  sleep .05\ndone\n\ntrap terminate_test_server EXIT\n\nphantomjs --disk-cache=true \\\n  test/runner.js \"$test_url\" \"$@\" \\\n  2> >(grep -v \"CoreText performance note\" >&2)\n"
  },
  {
    "path": "src/ajax.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($){\n  var jsonpID = +new Date(),\n      document = window.document,\n      key,\n      name,\n      rscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n      scriptTypeRE = /^(?:text|application)\\/javascript/i,\n      xmlTypeRE = /^(?:text|application)\\/xml/i,\n      jsonType = 'application/json',\n      htmlType = 'text/html',\n      blankRE = /^\\s*$/,\n      originAnchor = document.createElement('a')\n\n  originAnchor.href = window.location.href\n\n  // trigger a custom event and return false if it was cancelled\n  function triggerAndReturn(context, eventName, data) {\n    var event = $.Event(eventName)\n    $(context).trigger(event, data)\n    return !event.isDefaultPrevented()\n  }\n\n  // trigger an Ajax \"global\" event\n  function triggerGlobal(settings, context, eventName, data) {\n    if (settings.global) return triggerAndReturn(context || document, eventName, data)\n  }\n\n  // Number of active Ajax requests\n  $.active = 0\n\n  function ajaxStart(settings) {\n    if (settings.global && $.active++ === 0) triggerGlobal(settings, null, 'ajaxStart')\n  }\n  function ajaxStop(settings) {\n    if (settings.global && !(--$.active)) triggerGlobal(settings, null, 'ajaxStop')\n  }\n\n  // triggers an extra global event \"ajaxBeforeSend\" that's like \"ajaxSend\" but cancelable\n  function ajaxBeforeSend(xhr, settings) {\n    var context = settings.context\n    if (settings.beforeSend.call(context, xhr, settings) === false ||\n        triggerGlobal(settings, context, 'ajaxBeforeSend', [xhr, settings]) === false)\n      return false\n\n    triggerGlobal(settings, context, 'ajaxSend', [xhr, settings])\n  }\n  function ajaxSuccess(data, xhr, settings, deferred) {\n    var context = settings.context, status = 'success'\n    settings.success.call(context, data, status, xhr)\n    if (deferred) deferred.resolveWith(context, [data, status, xhr])\n    triggerGlobal(settings, context, 'ajaxSuccess', [xhr, settings, data])\n    ajaxComplete(status, xhr, settings)\n  }\n  // type: \"timeout\", \"error\", \"abort\", \"parsererror\"\n  function ajaxError(error, type, xhr, settings, deferred) {\n    var context = settings.context\n    settings.error.call(context, xhr, type, error)\n    if (deferred) deferred.rejectWith(context, [xhr, type, error])\n    triggerGlobal(settings, context, 'ajaxError', [xhr, settings, error || type])\n    ajaxComplete(type, xhr, settings)\n  }\n  // status: \"success\", \"notmodified\", \"error\", \"timeout\", \"abort\", \"parsererror\"\n  function ajaxComplete(status, xhr, settings) {\n    var context = settings.context\n    settings.complete.call(context, xhr, status)\n    triggerGlobal(settings, context, 'ajaxComplete', [xhr, settings])\n    ajaxStop(settings)\n  }\n\n  function ajaxDataFilter(data, type, settings) {\n    if (settings.dataFilter == empty) return data\n    var context = settings.context\n    return settings.dataFilter.call(context, data, type)\n  }\n\n  // Empty function, used as default callback\n  function empty() {}\n\n  $.ajaxJSONP = function(options, deferred){\n    if (!('type' in options)) return $.ajax(options)\n\n    var _callbackName = options.jsonpCallback,\n      callbackName = ($.isFunction(_callbackName) ?\n        _callbackName() : _callbackName) || ('Zepto' + (jsonpID++)),\n      script = document.createElement('script'),\n      originalCallback = window[callbackName],\n      responseData,\n      abort = function(errorType) {\n        $(script).triggerHandler('error', errorType || 'abort')\n      },\n      xhr = { abort: abort }, abortTimeout\n\n    if (deferred) deferred.promise(xhr)\n\n    $(script).on('load error', function(e, errorType){\n      clearTimeout(abortTimeout)\n      $(script).off().remove()\n\n      if (e.type == 'error' || !responseData) {\n        ajaxError(null, errorType || 'error', xhr, options, deferred)\n      } else {\n        ajaxSuccess(responseData[0], xhr, options, deferred)\n      }\n\n      window[callbackName] = originalCallback\n      if (responseData && $.isFunction(originalCallback))\n        originalCallback(responseData[0])\n\n      originalCallback = responseData = undefined\n    })\n\n    if (ajaxBeforeSend(xhr, options) === false) {\n      abort('abort')\n      return xhr\n    }\n\n    window[callbackName] = function(){\n      responseData = arguments\n    }\n\n    script.src = options.url.replace(/\\?(.+)=\\?/, '?$1=' + callbackName)\n    document.head.appendChild(script)\n\n    if (options.timeout > 0) abortTimeout = setTimeout(function(){\n      abort('timeout')\n    }, options.timeout)\n\n    return xhr\n  }\n\n  $.ajaxSettings = {\n    // Default type of request\n    type: 'GET',\n    // Callback that is executed before request\n    beforeSend: empty,\n    // Callback that is executed if the request succeeds\n    success: empty,\n    // Callback that is executed the the server drops error\n    error: empty,\n    // Callback that is executed on request complete (both: error and success)\n    complete: empty,\n    // The context for the callbacks\n    context: null,\n    // Whether to trigger \"global\" Ajax events\n    global: true,\n    // Transport\n    xhr: function () {\n      return new window.XMLHttpRequest()\n    },\n    // MIME types mapping\n    // IIS returns Javascript as \"application/x-javascript\"\n    accepts: {\n      script: 'text/javascript, application/javascript, application/x-javascript',\n      json:   jsonType,\n      xml:    'application/xml, text/xml',\n      html:   htmlType,\n      text:   'text/plain'\n    },\n    // Whether the request is to another domain\n    crossDomain: false,\n    // Default timeout\n    timeout: 0,\n    // Whether data should be serialized to string\n    processData: true,\n    // Whether the browser should be allowed to cache GET responses\n    cache: true,\n    //Used to handle the raw response data of XMLHttpRequest.\n    //This is a pre-filtering function to sanitize the response.\n    //The sanitized response should be returned\n    dataFilter: empty\n  }\n\n  function mimeToDataType(mime) {\n    if (mime) mime = mime.split(';', 2)[0]\n    return mime && ( mime == htmlType ? 'html' :\n      mime == jsonType ? 'json' :\n      scriptTypeRE.test(mime) ? 'script' :\n      xmlTypeRE.test(mime) && 'xml' ) || 'text'\n  }\n\n  function appendQuery(url, query) {\n    if (query == '') return url\n    return (url + '&' + query).replace(/[&?]{1,2}/, '?')\n  }\n\n  // serialize payload and append it to the URL for GET requests\n  function serializeData(options) {\n    if (options.processData && options.data && $.type(options.data) != \"string\")\n      options.data = $.param(options.data, options.traditional)\n    if (options.data && (!options.type || options.type.toUpperCase() == 'GET' || 'jsonp' == options.dataType))\n      options.url = appendQuery(options.url, options.data), options.data = undefined\n  }\n\n  $.ajax = function(options){\n    var settings = $.extend({}, options || {}),\n        deferred = $.Deferred && $.Deferred(),\n        urlAnchor, hashIndex\n    for (key in $.ajaxSettings) if (settings[key] === undefined) settings[key] = $.ajaxSettings[key]\n\n    ajaxStart(settings)\n\n    if (!settings.crossDomain) {\n      urlAnchor = document.createElement('a')\n      urlAnchor.href = settings.url\n      // cleans up URL for .href (IE only), see https://github.com/madrobby/zepto/pull/1049\n      urlAnchor.href = urlAnchor.href\n      settings.crossDomain = (originAnchor.protocol + '//' + originAnchor.host) !== (urlAnchor.protocol + '//' + urlAnchor.host)\n    }\n\n    if (!settings.url) settings.url = window.location.toString()\n    if ((hashIndex = settings.url.indexOf('#')) > -1) settings.url = settings.url.slice(0, hashIndex)\n    serializeData(settings)\n\n    var dataType = settings.dataType, hasPlaceholder = /\\?.+=\\?/.test(settings.url)\n    if (hasPlaceholder) dataType = 'jsonp'\n\n    if (settings.cache === false || (\n         (!options || options.cache !== true) &&\n         ('script' == dataType || 'jsonp' == dataType)\n        ))\n      settings.url = appendQuery(settings.url, '_=' + Date.now())\n\n    if ('jsonp' == dataType) {\n      if (!hasPlaceholder)\n        settings.url = appendQuery(settings.url,\n          settings.jsonp ? (settings.jsonp + '=?') : settings.jsonp === false ? '' : 'callback=?')\n      return $.ajaxJSONP(settings, deferred)\n    }\n\n    var mime = settings.accepts[dataType],\n        headers = { },\n        setHeader = function(name, value) { headers[name.toLowerCase()] = [name, value] },\n        protocol = /^([\\w-]+:)\\/\\//.test(settings.url) ? RegExp.$1 : window.location.protocol,\n        xhr = settings.xhr(),\n        nativeSetHeader = xhr.setRequestHeader,\n        abortTimeout\n\n    if (deferred) deferred.promise(xhr)\n\n    if (!settings.crossDomain) setHeader('X-Requested-With', 'XMLHttpRequest')\n    setHeader('Accept', mime || '*/*')\n    if (mime = settings.mimeType || mime) {\n      if (mime.indexOf(',') > -1) mime = mime.split(',', 2)[0]\n      xhr.overrideMimeType && xhr.overrideMimeType(mime)\n    }\n    if (settings.contentType || (settings.contentType !== false && settings.data && settings.type.toUpperCase() != 'GET'))\n      setHeader('Content-Type', settings.contentType || 'application/x-www-form-urlencoded')\n\n    if (settings.headers) for (name in settings.headers) setHeader(name, settings.headers[name])\n    xhr.setRequestHeader = setHeader\n\n    xhr.onreadystatechange = function(){\n      if (xhr.readyState == 4) {\n        xhr.onreadystatechange = empty\n        clearTimeout(abortTimeout)\n        var result, error = false\n        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 || (xhr.status == 0 && protocol == 'file:')) {\n          dataType = dataType || mimeToDataType(settings.mimeType || xhr.getResponseHeader('content-type'))\n\n          if (xhr.responseType == 'arraybuffer' || xhr.responseType == 'blob')\n            result = xhr.response\n          else {\n            result = xhr.responseText\n\n            try {\n              // http://perfectionkills.com/global-eval-what-are-the-options/\n              // sanitize response accordingly if data filter callback provided\n              result = ajaxDataFilter(result, dataType, settings)\n              if (dataType == 'script')    (1,eval)(result)\n              else if (dataType == 'xml')  result = xhr.responseXML\n              else if (dataType == 'json') result = blankRE.test(result) ? null : $.parseJSON(result)\n            } catch (e) { error = e }\n\n            if (error) return ajaxError(error, 'parsererror', xhr, settings, deferred)\n          }\n\n          ajaxSuccess(result, xhr, settings, deferred)\n        } else {\n          ajaxError(xhr.statusText || null, xhr.status ? 'error' : 'abort', xhr, settings, deferred)\n        }\n      }\n    }\n\n    if (ajaxBeforeSend(xhr, settings) === false) {\n      xhr.abort()\n      ajaxError(null, 'abort', xhr, settings, deferred)\n      return xhr\n    }\n\n    var async = 'async' in settings ? settings.async : true\n    xhr.open(settings.type, settings.url, async, settings.username, settings.password)\n\n    if (settings.xhrFields) for (name in settings.xhrFields) xhr[name] = settings.xhrFields[name]\n\n    for (name in headers) nativeSetHeader.apply(xhr, headers[name])\n\n    if (settings.timeout > 0) abortTimeout = setTimeout(function(){\n        xhr.onreadystatechange = empty\n        xhr.abort()\n        ajaxError(null, 'timeout', xhr, settings, deferred)\n      }, settings.timeout)\n\n    // avoid sending empty string (#319)\n    xhr.send(settings.data ? settings.data : null)\n    return xhr\n  }\n\n  // handle optional data/success arguments\n  function parseArguments(url, data, success, dataType) {\n    if ($.isFunction(data)) dataType = success, success = data, data = undefined\n    if (!$.isFunction(success)) dataType = success, success = undefined\n    return {\n      url: url\n    , data: data\n    , success: success\n    , dataType: dataType\n    }\n  }\n\n  $.get = function(/* url, data, success, dataType */){\n    return $.ajax(parseArguments.apply(null, arguments))\n  }\n\n  $.post = function(/* url, data, success, dataType */){\n    var options = parseArguments.apply(null, arguments)\n    options.type = 'POST'\n    return $.ajax(options)\n  }\n\n  $.getJSON = function(/* url, data, success */){\n    var options = parseArguments.apply(null, arguments)\n    options.dataType = 'json'\n    return $.ajax(options)\n  }\n\n  $.fn.load = function(url, data, success){\n    if (!this.length) return this\n    var self = this, parts = url.split(/\\s/), selector,\n        options = parseArguments(url, data, success),\n        callback = options.success\n    if (parts.length > 1) options.url = parts[0], selector = parts[1]\n    options.success = function(response){\n      self.html(selector ?\n        $('<div>').html(response.replace(rscript, \"\")).find(selector)\n        : response)\n      callback && callback.apply(self, arguments)\n    }\n    $.ajax(options)\n    return this\n  }\n\n  var escape = encodeURIComponent\n\n  function serialize(params, obj, traditional, scope){\n    var type, array = $.isArray(obj), hash = $.isPlainObject(obj)\n    $.each(obj, function(key, value) {\n      type = $.type(value)\n      if (scope) key = traditional ? scope :\n        scope + '[' + (hash || type == 'object' || type == 'array' ? key : '') + ']'\n      // handle data in serializeArray() format\n      if (!scope && array) params.add(value.name, value.value)\n      // recurse into nested objects\n      else if (type == \"array\" || (!traditional && type == \"object\"))\n        serialize(params, value, traditional, key)\n      else params.add(key, value)\n    })\n  }\n\n  $.param = function(obj, traditional){\n    var params = []\n    params.add = function(key, value) {\n      if ($.isFunction(value)) value = value()\n      if (value == null) value = \"\"\n      this.push(escape(key) + '=' + escape(value))\n    }\n    serialize(params, obj, traditional)\n    return params.join('&').replace(/%20/g, '+')\n  }\n})(Zepto)\n"
  },
  {
    "path": "src/amd_layout.js",
    "content": "(function(global, factory) {\n  if (typeof define === 'function' && define.amd)\n    define(function() { return factory(global) })\n  else\n    factory(global)\n}(window, function(window) {\n  YIELD\n  return Zepto\n}))\n"
  },
  {
    "path": "src/assets.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($){\n  var cache = [], timeout\n\n  $.fn.remove = function(){\n    return this.each(function(){\n      if(this.parentNode){\n        if(this.tagName === 'IMG'){\n          cache.push(this)\n          this.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='\n          if (timeout) clearTimeout(timeout)\n          timeout = setTimeout(function(){ cache = [] }, 60000)\n        }\n        this.parentNode.removeChild(this)\n      }\n    })\n  }\n})(Zepto)\n"
  },
  {
    "path": "src/callbacks.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($){\n  // Create a collection of callbacks to be fired in a sequence, with configurable behaviour\n  // Option flags:\n  //   - once: Callbacks fired at most one time.\n  //   - memory: Remember the most recent context and arguments\n  //   - stopOnFalse: Cease iterating over callback list\n  //   - unique: Permit adding at most one instance of the same callback\n  $.Callbacks = function(options) {\n    options = $.extend({}, options)\n\n    var memory, // Last fire value (for non-forgettable lists)\n        fired,  // Flag to know if list was already fired\n        firing, // Flag to know if list is currently firing\n        firingStart, // First callback to fire (used internally by add and fireWith)\n        firingLength, // End of the loop when firing\n        firingIndex, // Index of currently firing callback (modified by remove if needed)\n        list = [], // Actual callback list\n        stack = !options.once && [], // Stack of fire calls for repeatable lists\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\n              break\n            }\n          }\n          firing = false\n          if (list) {\n            if (stack) stack.length && fire(stack.shift())\n            else if (memory) list.length = 0\n            else Callbacks.disable()\n          }\n        },\n\n        Callbacks = {\n          add: function() {\n            if (list) {\n              var start = list.length,\n                  add = function(args) {\n                    $.each(args, function(_, arg){\n                      if (typeof arg === \"function\") {\n                        if (!options.unique || !Callbacks.has(arg)) list.push(arg)\n                      }\n                      else if (arg && arg.length && typeof arg !== 'string') add(arg)\n                    })\n                  }\n              add(arguments)\n              if (firing) firingLength = list.length\n              else if (memory) {\n                firingStart = start\n                fire(memory)\n              }\n            }\n            return this\n          },\n          remove: function() {\n            if (list) {\n              $.each(arguments, function(_, arg){\n                var index\n                while ((index = $.inArray(arg, list, index)) > -1) {\n                  list.splice(index, 1)\n                  // Handle firing indexes\n                  if (firing) {\n                    if (index <= firingLength) --firingLength\n                    if (index <= firingIndex) --firingIndex\n                  }\n                }\n              })\n            }\n            return this\n          },\n          has: function(fn) {\n            return !!(list && (fn ? $.inArray(fn, list) > -1 : list.length))\n          },\n          empty: function() {\n            firingLength = list.length = 0\n            return this\n          },\n          disable: function() {\n            list = stack = memory = undefined\n            return this\n          },\n          disabled: function() {\n            return !list\n          },\n          lock: function() {\n            stack = undefined\n            if (!memory) Callbacks.disable()\n            return this\n          },\n          locked: function() {\n            return !stack\n          },\n          fireWith: function(context, args) {\n            if (list && (!fired || stack)) {\n              args = args || []\n              args = [context, args.slice ? args.slice() : args]\n              if (firing) stack.push(args)\n              else fire(args)\n            }\n            return this\n          },\n          fire: function() {\n            return Callbacks.fireWith(this, arguments)\n          },\n          fired: function() {\n            return !!fired\n          }\n        }\n\n    return Callbacks\n  }\n})(Zepto)\n"
  },
  {
    "path": "src/data.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n// The following code is heavily inspired by jQuery's $.fn.data()\n\n;(function($){\n  var data = {}, dataAttr = $.fn.data, camelize = $.camelCase,\n    exp = $.expando = 'Zepto' + (+new Date()), emptyArray = []\n\n  // Get value from node:\n  // 1. first try key as given,\n  // 2. then try camelized key,\n  // 3. fall back to reading \"data-*\" attribute.\n  function getData(node, name) {\n    var id = node[exp], store = id && data[id]\n    if (name === undefined) return store || setData(node)\n    else {\n      if (store) {\n        if (name in store) return store[name]\n        var camelName = camelize(name)\n        if (camelName in store) return store[camelName]\n      }\n      return dataAttr.call($(node), name)\n    }\n  }\n\n  // Store value under camelized key on node\n  function setData(node, name, value) {\n    var id = node[exp] || (node[exp] = ++$.uuid),\n      store = data[id] || (data[id] = attributeData(node))\n    if (name !== undefined) store[camelize(name)] = value\n    return store\n  }\n\n  // Read all \"data-*\" attributes from a node\n  function attributeData(node) {\n    var store = {}\n    $.each(node.attributes || emptyArray, function(i, attr){\n      if (attr.name.indexOf('data-') == 0)\n        store[camelize(attr.name.replace('data-', ''))] =\n          $.zepto.deserializeValue(attr.value)\n    })\n    return store\n  }\n\n  $.fn.data = function(name, value) {\n    return value === undefined ?\n      // set multiple values via object\n      $.isPlainObject(name) ?\n        this.each(function(i, node){\n          $.each(name, function(key, value){ setData(node, key, value) })\n        }) :\n        // get value from first element\n        (0 in this ? getData(this[0], name) : undefined) :\n      // set value on all elements\n      this.each(function(){ setData(this, name, value) })\n  }\n\n  $.data = function(elem, name, value) {\n    return $(elem).data(name, value)\n  }\n\n  $.hasData = function(elem) {\n    var id = elem[exp], store = id && data[id]\n    return store ? !$.isEmptyObject(store) : false\n  }\n\n  $.fn.removeData = function(names) {\n    if (typeof names == 'string') names = names.split(/\\s+/)\n    return this.each(function(){\n      var id = this[exp], store = id && data[id]\n      if (store) $.each(names || store, function(key){\n        delete store[names ? camelize(this) : key]\n      })\n    })\n  }\n\n  // Generate extended `remove` and `empty` functions\n  ;['remove', 'empty'].forEach(function(methodName){\n    var origFn = $.fn[methodName]\n    $.fn[methodName] = function() {\n      var elements = this.find('*')\n      if (methodName === 'remove') elements = elements.add(this)\n      elements.removeData()\n      return origFn.call(this)\n    }\n  })\n})(Zepto)\n"
  },
  {
    "path": "src/deferred.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n//\n//     Some code (c) 2005, 2013 jQuery Foundation, Inc. and other contributors\n\n;(function($){\n  var slice = Array.prototype.slice\n\n  function Deferred(func) {\n    var tuples = [\n          // action, add listener, listener list, final state\n          [ \"resolve\", \"done\", $.Callbacks({once:1, memory:1}), \"resolved\" ],\n          [ \"reject\", \"fail\", $.Callbacks({once:1, memory:1}), \"rejected\" ],\n          [ \"notify\", \"progress\", $.Callbacks({memory:1}) ]\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 [, fnFailed [, fnProgress]] */) {\n            var fns = arguments\n            return Deferred(function(defer){\n              $.each(tuples, function(i, tuple){\n                var fn = $.isFunction(fns[i]) && fns[i]\n                deferred[tuple[1]](function(){\n                  var returned = fn && fn.apply(this, arguments)\n                  if (returned && $.isFunction(returned.promise)) {\n                    returned.promise()\n                      .done(defer.resolve)\n                      .fail(defer.reject)\n                      .progress(defer.notify)\n                  } else {\n                    var context = this === promise ? defer.promise() : this,\n                        values = fn ? [returned] : arguments\n                    defer[tuple[0] + \"With\"](context, values)\n                  }\n                })\n              })\n              fns = null\n            }).promise()\n          },\n\n          promise: function(obj) {\n            return obj != null ? $.extend( obj, promise ) : promise\n          }\n        },\n        deferred = {}\n\n    $.each(tuples, function(i, tuple){\n      var list = tuple[2],\n          stateString = tuple[3]\n\n      promise[tuple[1]] = list.add\n\n      if (stateString) {\n        list.add(function(){\n          state = stateString\n        }, tuples[i^1][2].disable, tuples[2][2].lock)\n      }\n\n      deferred[tuple[0]] = function(){\n        deferred[tuple[0] + \"With\"](this === deferred ? promise : this, arguments)\n        return this\n      }\n      deferred[tuple[0] + \"With\"] = list.fireWith\n    })\n\n    promise.promise(deferred)\n    if (func) func.call(deferred, deferred)\n    return deferred\n  }\n\n  $.when = function(sub) {\n    var resolveValues = slice.call(arguments),\n        len = resolveValues.length,\n        i = 0,\n        remain = len !== 1 || (sub && $.isFunction(sub.promise)) ? len : 0,\n        deferred = remain === 1 ? sub : Deferred(),\n        progressValues, progressContexts, resolveContexts,\n        updateFn = function(i, ctx, val){\n          return function(value){\n            ctx[i] = this\n            val[i] = arguments.length > 1 ? slice.call(arguments) : value\n            if (val === progressValues) {\n              deferred.notifyWith(ctx, val)\n            } else if (!(--remain)) {\n              deferred.resolveWith(ctx, val)\n            }\n          }\n        }\n\n    if (len > 1) {\n      progressValues = new Array(len)\n      progressContexts = new Array(len)\n      resolveContexts = new Array(len)\n      for ( ; i < len; ++i ) {\n        if (resolveValues[i] && $.isFunction(resolveValues[i].promise)) {\n          resolveValues[i].promise()\n            .done(updateFn(i, resolveContexts, resolveValues))\n            .fail(deferred.reject)\n            .progress(updateFn(i, progressContexts, progressValues))\n        } else {\n          --remain\n        }\n      }\n    }\n    if (!remain) deferred.resolveWith(resolveContexts, resolveValues)\n    return deferred.promise()\n  }\n\n  $.Deferred = Deferred\n})(Zepto)\n"
  },
  {
    "path": "src/detect.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($){\n  function detect(ua, platform){\n    var os = this.os = {}, browser = this.browser = {},\n      webkit = ua.match(/Web[kK]it[\\/]{0,1}([\\d.]+)/),\n      android = ua.match(/(Android);?[\\s\\/]+([\\d.]+)?/),\n      osx = !!ua.match(/\\(Macintosh\\; Intel /),\n      ipad = ua.match(/(iPad).*OS\\s([\\d_]+)/),\n      ipod = ua.match(/(iPod)(.*OS\\s([\\d_]+))?/),\n      iphone = !ipad && ua.match(/(iPhone\\sOS)\\s([\\d_]+)/),\n      webos = ua.match(/(webOS|hpwOS)[\\s\\/]([\\d.]+)/),\n      win = /Win\\d{2}|Windows/.test(platform),\n      wp = ua.match(/Windows Phone ([\\d.]+)/),\n      touchpad = webos && ua.match(/TouchPad/),\n      kindle = ua.match(/Kindle\\/([\\d.]+)/),\n      silk = ua.match(/Silk\\/([\\d._]+)/),\n      blackberry = ua.match(/(BlackBerry).*Version\\/([\\d.]+)/),\n      bb10 = ua.match(/(BB10).*Version\\/([\\d.]+)/),\n      rimtabletos = ua.match(/(RIM\\sTablet\\sOS)\\s([\\d.]+)/),\n      playbook = ua.match(/PlayBook/),\n      chrome = ua.match(/Chrome\\/([\\d.]+)/) || ua.match(/CriOS\\/([\\d.]+)/),\n      firefox = ua.match(/Firefox\\/([\\d.]+)/),\n      firefoxos = ua.match(/\\((?:Mobile|Tablet); rv:([\\d.]+)\\).*Firefox\\/[\\d.]+/),\n      ie = ua.match(/MSIE\\s([\\d.]+)/) || ua.match(/Trident\\/[\\d](?=[^\\?]+).*rv:([0-9.].)/),\n      webview = !chrome && ua.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/),\n      safari = webview || ua.match(/Version\\/([\\d.]+)([^S](Safari)|[^M]*(Mobile)[^S]*(Safari))/)\n\n    // Todo: clean this up with a better OS/browser seperation:\n    // - discern (more) between multiple browsers on android\n    // - decide if kindle fire in silk mode is android or not\n    // - Firefox on Android doesn't specify the Android version\n    // - possibly devide in os, device and browser hashes\n\n    if (browser.webkit = !!webkit) browser.version = webkit[1]\n\n    if (android) os.android = true, os.version = android[2]\n    if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.')\n    if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.')\n    if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null\n    if (wp) os.wp = true, os.version = wp[1]\n    if (webos) os.webos = true, os.version = webos[2]\n    if (touchpad) os.touchpad = true\n    if (blackberry) os.blackberry = true, os.version = blackberry[2]\n    if (bb10) os.bb10 = true, os.version = bb10[2]\n    if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2]\n    if (playbook) browser.playbook = true\n    if (kindle) os.kindle = true, os.version = kindle[1]\n    if (silk) browser.silk = true, browser.version = silk[1]\n    if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true\n    if (chrome) browser.chrome = true, browser.version = chrome[1]\n    if (firefox) browser.firefox = true, browser.version = firefox[1]\n    if (firefoxos) os.firefoxos = true, os.version = firefoxos[1]\n    if (ie) browser.ie = true, browser.version = ie[1]\n    if (safari && (osx || os.ios || win)) {\n      browser.safari = true\n      if (!os.ios) browser.version = safari[1]\n    }\n    if (webview) browser.webview = true\n\n    os.tablet = !!(ipad || playbook || (android && !ua.match(/Mobile/)) ||\n      (firefox && ua.match(/Tablet/)) || (ie && !ua.match(/Phone/) && ua.match(/Touch/)))\n    os.phone  = !!(!os.tablet && !os.ipod && (android || iphone || webos || blackberry || bb10 ||\n      (chrome && ua.match(/Android/)) || (chrome && ua.match(/CriOS\\/([\\d.]+)/)) ||\n      (firefox && ua.match(/Mobile/)) || (ie && ua.match(/Touch/))))\n  }\n\n  detect.call($, navigator.userAgent, navigator.platform)\n  // make available to unit tests\n  $.__detect = detect\n\n})(Zepto)\n"
  },
  {
    "path": "src/event.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($){\n  var _zid = 1, undefined,\n      slice = Array.prototype.slice,\n      isFunction = $.isFunction,\n      isString = function(obj){ return typeof obj == 'string' },\n      handlers = {},\n      specialEvents={},\n      focusinSupported = 'onfocusin' in window,\n      focus = { focus: 'focusin', blur: 'focusout' },\n      hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }\n\n  specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'\n\n  function zid(element) {\n    return element._zid || (element._zid = _zid++)\n  }\n  function findHandlers(element, event, fn, selector) {\n    event = parse(event)\n    if (event.ns) var matcher = matcherFor(event.ns)\n    return (handlers[zid(element)] || []).filter(function(handler) {\n      return handler\n        && (!event.e  || handler.e == event.e)\n        && (!event.ns || matcher.test(handler.ns))\n        && (!fn       || zid(handler.fn) === zid(fn))\n        && (!selector || handler.sel == selector)\n    })\n  }\n  function parse(event) {\n    var parts = ('' + event).split('.')\n    return {e: parts[0], ns: parts.slice(1).sort().join(' ')}\n  }\n  function matcherFor(ns) {\n    return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')\n  }\n\n  function eventCapture(handler, captureSetting) {\n    return handler.del &&\n      (!focusinSupported && (handler.e in focus)) ||\n      !!captureSetting\n  }\n\n  function realEvent(type) {\n    return hover[type] || (focusinSupported && focus[type]) || type\n  }\n\n  function add(element, events, fn, data, selector, delegator, capture){\n    var id = zid(element), set = (handlers[id] || (handlers[id] = []))\n    events.split(/\\s/).forEach(function(event){\n      if (event == 'ready') return $(document).ready(fn)\n      var handler   = parse(event)\n      handler.fn    = fn\n      handler.sel   = selector\n      // emulate mouseenter, mouseleave\n      if (handler.e in hover) fn = function(e){\n        var related = e.relatedTarget\n        if (!related || (related !== this && !$.contains(this, related)))\n          return handler.fn.apply(this, arguments)\n      }\n      handler.del   = delegator\n      var callback  = delegator || fn\n      handler.proxy = function(e){\n        e = compatible(e)\n        if (e.isImmediatePropagationStopped()) return\n        e.data = data\n        var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args))\n        if (result === false) e.preventDefault(), e.stopPropagation()\n        return result\n      }\n      handler.i = set.length\n      set.push(handler)\n      if ('addEventListener' in element)\n        element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))\n    })\n  }\n  function remove(element, events, fn, selector, capture){\n    var id = zid(element)\n    ;(events || '').split(/\\s/).forEach(function(event){\n      findHandlers(element, event, fn, selector).forEach(function(handler){\n        delete handlers[id][handler.i]\n      if ('removeEventListener' in element)\n        element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))\n      })\n    })\n  }\n\n  $.event = { add: add, remove: remove }\n\n  $.proxy = function(fn, context) {\n    var args = (2 in arguments) && slice.call(arguments, 2)\n    if (isFunction(fn)) {\n      var proxyFn = function(){ return fn.apply(context, args ? args.concat(slice.call(arguments)) : arguments) }\n      proxyFn._zid = zid(fn)\n      return proxyFn\n    } else if (isString(context)) {\n      if (args) {\n        args.unshift(fn[context], fn)\n        return $.proxy.apply(null, args)\n      } else {\n        return $.proxy(fn[context], fn)\n      }\n    } else {\n      throw new TypeError(\"expected function\")\n    }\n  }\n\n  $.fn.bind = function(event, data, callback){\n    return this.on(event, data, callback)\n  }\n  $.fn.unbind = function(event, callback){\n    return this.off(event, callback)\n  }\n  $.fn.one = function(event, selector, data, callback){\n    return this.on(event, selector, data, callback, 1)\n  }\n\n  var returnTrue = function(){return true},\n      returnFalse = function(){return false},\n      ignoreProperties = /^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,\n      eventMethods = {\n        preventDefault: 'isDefaultPrevented',\n        stopImmediatePropagation: 'isImmediatePropagationStopped',\n        stopPropagation: 'isPropagationStopped'\n      }\n\n  function compatible(event, source) {\n    if (source || !event.isDefaultPrevented) {\n      source || (source = event)\n\n      $.each(eventMethods, function(name, predicate) {\n        var sourceMethod = source[name]\n        event[name] = function(){\n          this[predicate] = returnTrue\n          return sourceMethod && sourceMethod.apply(source, arguments)\n        }\n        event[predicate] = returnFalse\n      })\n\n      try {\n        event.timeStamp || (event.timeStamp = Date.now())\n      } catch (ignored) { }\n\n      if (source.defaultPrevented !== undefined ? source.defaultPrevented :\n          'returnValue' in source ? source.returnValue === false :\n          source.getPreventDefault && source.getPreventDefault())\n        event.isDefaultPrevented = returnTrue\n    }\n    return event\n  }\n\n  function createProxy(event) {\n    var key, proxy = { originalEvent: event }\n    for (key in event)\n      if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]\n\n    return compatible(proxy, event)\n  }\n\n  $.fn.delegate = function(selector, event, callback){\n    return this.on(event, selector, callback)\n  }\n  $.fn.undelegate = function(selector, event, callback){\n    return this.off(event, selector, callback)\n  }\n\n  $.fn.live = function(event, callback){\n    $(document.body).delegate(this.selector, event, callback)\n    return this\n  }\n  $.fn.die = function(event, callback){\n    $(document.body).undelegate(this.selector, event, callback)\n    return this\n  }\n\n  $.fn.on = function(event, selector, data, callback, one){\n    var autoRemove, delegator, $this = this\n    if (event && !isString(event)) {\n      $.each(event, function(type, fn){\n        $this.on(type, selector, data, fn, one)\n      })\n      return $this\n    }\n\n    if (!isString(selector) && !isFunction(callback) && callback !== false)\n      callback = data, data = selector, selector = undefined\n    if (callback === undefined || data === false)\n      callback = data, data = undefined\n\n    if (callback === false) callback = returnFalse\n\n    return $this.each(function(_, element){\n      if (one) autoRemove = function(e){\n        remove(element, e.type, callback)\n        return callback.apply(this, arguments)\n      }\n\n      if (selector) delegator = function(e){\n        var evt, match = $(e.target).closest(selector, element).get(0)\n        if (match && match !== element) {\n          evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})\n          return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))\n        }\n      }\n\n      add(element, event, callback, data, selector, delegator || autoRemove)\n    })\n  }\n  $.fn.off = function(event, selector, callback){\n    var $this = this\n    if (event && !isString(event)) {\n      $.each(event, function(type, fn){\n        $this.off(type, selector, fn)\n      })\n      return $this\n    }\n\n    if (!isString(selector) && !isFunction(callback) && callback !== false)\n      callback = selector, selector = undefined\n\n    if (callback === false) callback = returnFalse\n\n    return $this.each(function(){\n      remove(this, event, callback, selector)\n    })\n  }\n\n  $.fn.trigger = function(event, args){\n    event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)\n    event._args = args\n    return this.each(function(){\n      // handle focus(), blur() by calling them directly\n      if (event.type in focus && typeof this[event.type] == \"function\") this[event.type]()\n      // items in the collection might not be DOM elements\n      else if ('dispatchEvent' in this) this.dispatchEvent(event)\n      else $(this).triggerHandler(event, args)\n    })\n  }\n\n  // triggers event handlers on current element just as if an event occurred,\n  // doesn't trigger an actual event, doesn't bubble\n  $.fn.triggerHandler = function(event, args){\n    var e, result\n    this.each(function(i, element){\n      e = createProxy(isString(event) ? $.Event(event) : event)\n      e._args = args\n      e.target = element\n      $.each(findHandlers(element, event.type || event), function(i, handler){\n        result = handler.proxy(e)\n        if (e.isImmediatePropagationStopped()) return false\n      })\n    })\n    return result\n  }\n\n  // shortcut methods for `.bind(event, fn)` for each event type\n  ;('focusin focusout focus blur load resize scroll unload click dblclick '+\n  'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+\n  'change select keydown keypress keyup error').split(' ').forEach(function(event) {\n    $.fn[event] = function(callback) {\n      return (0 in arguments) ?\n        this.bind(event, callback) :\n        this.trigger(event)\n    }\n  })\n\n  $.Event = function(type, props) {\n    if (!isString(type)) props = type, type = props.type\n    var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true\n    if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])\n    event.initEvent(type, bubbles, true)\n    return compatible(event)\n  }\n\n})(Zepto)\n"
  },
  {
    "path": "src/form.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($){\n  $.fn.serializeArray = function() {\n    var name, type, result = [],\n      add = function(value) {\n        if (value.forEach) return value.forEach(add)\n        result.push({ name: name, value: value })\n      }\n    if (this[0]) $.each(this[0].elements, function(_, field){\n      type = field.type, name = field.name\n      if (name && field.nodeName.toLowerCase() != 'fieldset' &&\n        !field.disabled && type != 'submit' && type != 'reset' && type != 'button' && type != 'file' &&\n        ((type != 'radio' && type != 'checkbox') || field.checked))\n          add($(field).val())\n    })\n    return result\n  }\n\n  $.fn.serialize = function(){\n    var result = []\n    this.serializeArray().forEach(function(elm){\n      result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value))\n    })\n    return result.join('&')\n  }\n\n  $.fn.submit = function(callback) {\n    if (0 in arguments) this.bind('submit', callback)\n    else if (this.length) {\n      var event = $.Event('submit')\n      this.eq(0).trigger(event)\n      if (!event.isDefaultPrevented()) this.get(0).submit()\n    }\n    return this\n  }\n\n})(Zepto)\n"
  },
  {
    "path": "src/fx.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($, undefined){\n  var prefix = '', eventPrefix,\n    vendors = { Webkit: 'webkit', Moz: '', O: 'o' },\n    testEl = document.createElement('div'),\n    supportedTransforms = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,\n    transform,\n    transitionProperty, transitionDuration, transitionTiming, transitionDelay,\n    animationName, animationDuration, animationTiming, animationDelay,\n    cssReset = {}\n\n  function dasherize(str) { return str.replace(/([A-Z])/g, '-$1').toLowerCase() }\n  function normalizeEvent(name) { return eventPrefix ? eventPrefix + name : name.toLowerCase() }\n\n  if (testEl.style.transform === undefined) $.each(vendors, function(vendor, event){\n    if (testEl.style[vendor + 'TransitionProperty'] !== undefined) {\n      prefix = '-' + vendor.toLowerCase() + '-'\n      eventPrefix = event\n      return false\n    }\n  })\n\n  transform = prefix + 'transform'\n  cssReset[transitionProperty = prefix + 'transition-property'] =\n  cssReset[transitionDuration = prefix + 'transition-duration'] =\n  cssReset[transitionDelay    = prefix + 'transition-delay'] =\n  cssReset[transitionTiming   = prefix + 'transition-timing-function'] =\n  cssReset[animationName      = prefix + 'animation-name'] =\n  cssReset[animationDuration  = prefix + 'animation-duration'] =\n  cssReset[animationDelay     = prefix + 'animation-delay'] =\n  cssReset[animationTiming    = prefix + 'animation-timing-function'] = ''\n\n  $.fx = {\n    off: (eventPrefix === undefined && testEl.style.transitionProperty === undefined),\n    speeds: { _default: 400, fast: 200, slow: 600 },\n    cssPrefix: prefix,\n    transitionEnd: normalizeEvent('TransitionEnd'),\n    animationEnd: normalizeEvent('AnimationEnd')\n  }\n\n  $.fn.animate = function(properties, duration, ease, callback, delay){\n    if ($.isFunction(duration))\n      callback = duration, ease = undefined, duration = undefined\n    if ($.isFunction(ease))\n      callback = ease, ease = undefined\n    if ($.isPlainObject(duration))\n      ease = duration.easing, callback = duration.complete, delay = duration.delay, duration = duration.duration\n    if (duration) duration = (typeof duration == 'number' ? duration :\n                    ($.fx.speeds[duration] || $.fx.speeds._default)) / 1000\n    if (delay) delay = parseFloat(delay) / 1000\n    return this.anim(properties, duration, ease, callback, delay)\n  }\n\n  $.fn.anim = function(properties, duration, ease, callback, delay){\n    var key, cssValues = {}, cssProperties, transforms = '',\n        that = this, wrappedCallback, endEvent = $.fx.transitionEnd,\n        fired = false\n\n    if (duration === undefined) duration = $.fx.speeds._default / 1000\n    if (delay === undefined) delay = 0\n    if ($.fx.off) duration = 0\n\n    if (typeof properties == 'string') {\n      // keyframe animation\n      cssValues[animationName] = properties\n      cssValues[animationDuration] = duration + 's'\n      cssValues[animationDelay] = delay + 's'\n      cssValues[animationTiming] = (ease || 'linear')\n      endEvent = $.fx.animationEnd\n    } else {\n      cssProperties = []\n      // CSS transitions\n      for (key in properties)\n        if (supportedTransforms.test(key)) transforms += key + '(' + properties[key] + ') '\n        else cssValues[key] = properties[key], cssProperties.push(dasherize(key))\n\n      if (transforms) cssValues[transform] = transforms, cssProperties.push(transform)\n      if (duration > 0 && typeof properties === 'object') {\n        cssValues[transitionProperty] = cssProperties.join(', ')\n        cssValues[transitionDuration] = duration + 's'\n        cssValues[transitionDelay] = delay + 's'\n        cssValues[transitionTiming] = (ease || 'linear')\n      }\n    }\n\n    wrappedCallback = function(event){\n      if (typeof event !== 'undefined') {\n        if (event.target !== event.currentTarget) return // makes sure the event didn't bubble from \"below\"\n        $(event.target).unbind(endEvent, wrappedCallback)\n      } else\n        $(this).unbind(endEvent, wrappedCallback) // triggered by setTimeout\n\n      fired = true\n      $(this).css(cssReset)\n      callback && callback.call(this)\n    }\n    if (duration > 0){\n      this.bind(endEvent, wrappedCallback)\n      // transitionEnd is not always firing on older Android phones\n      // so make sure it gets fired\n      setTimeout(function(){\n        if (fired) return\n        wrappedCallback.call(that)\n      }, ((duration + delay) * 1000) + 25)\n    }\n\n    // trigger page reflow so new elements can animate\n    this.size() && this.get(0).clientLeft\n\n    this.css(cssValues)\n\n    if (duration <= 0) setTimeout(function() {\n      that.each(function(){ wrappedCallback.call(this) })\n    }, 0)\n\n    return this\n  }\n\n  testEl = null\n})(Zepto)\n"
  },
  {
    "path": "src/fx_methods.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($, undefined){\n  var document = window.document,\n    origShow = $.fn.show, origHide = $.fn.hide, origToggle = $.fn.toggle\n\n  function anim(el, speed, opacity, scale, callback) {\n    if (typeof speed == 'function' && !callback) callback = speed, speed = undefined\n    var props = { opacity: opacity }\n    if (scale) {\n      props.scale = scale\n      el.css($.fx.cssPrefix + 'transform-origin', '0 0')\n    }\n    return el.animate(props, speed, null, callback)\n  }\n\n  function hide(el, speed, scale, callback) {\n    return anim(el, speed, 0, scale, function(){\n      origHide.call($(this))\n      callback && callback.call(this)\n    })\n  }\n\n  $.fn.show = function(speed, callback) {\n    origShow.call(this)\n    if (speed === undefined) speed = 0\n    else this.css('opacity', 0)\n    return anim(this, speed, 1, '1,1', callback)\n  }\n\n  $.fn.hide = function(speed, callback) {\n    if (speed === undefined) return origHide.call(this)\n    else return hide(this, speed, '0,0', callback)\n  }\n\n  $.fn.toggle = function(speed, callback) {\n    if (speed === undefined || typeof speed == 'boolean')\n      return origToggle.call(this, speed)\n    else return this.each(function(){\n      var el = $(this)\n      el[el.css('display') == 'none' ? 'show' : 'hide'](speed, callback)\n    })\n  }\n\n  $.fn.fadeTo = function(speed, opacity, callback) {\n    return anim(this, speed, opacity, null, callback)\n  }\n\n  $.fn.fadeIn = function(speed, callback) {\n    var target = this.css('opacity')\n    if (target > 0) this.css('opacity', 0)\n    else target = 1\n    return origShow.call(this).fadeTo(speed, target, callback)\n  }\n\n  $.fn.fadeOut = function(speed, callback) {\n    return hide(this, speed, null, callback)\n  }\n\n  $.fn.fadeToggle = function(speed, callback) {\n    return this.each(function(){\n      var el = $(this)\n      el[\n        (el.css('opacity') == 0 || el.css('display') == 'none') ? 'fadeIn' : 'fadeOut'\n      ](speed, callback)\n    })\n  }\n\n})(Zepto)\n"
  },
  {
    "path": "src/gesture.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($){\n  if ($.os.ios) {\n    var gesture = {}, gestureTimeout\n\n    function parentIfText(node){\n      return 'tagName' in node ? node : node.parentNode\n    }\n\n    $(document).bind('gesturestart', function(e){\n      var now = Date.now(), delta = now - (gesture.last || now)\n      gesture.target = parentIfText(e.target)\n      gestureTimeout && clearTimeout(gestureTimeout)\n      gesture.e1 = e.scale\n      gesture.last = now\n    }).bind('gesturechange', function(e){\n      gesture.e2 = e.scale\n    }).bind('gestureend', function(e){\n      if (gesture.e2 > 0) {\n        Math.abs(gesture.e1 - gesture.e2) != 0 && $(gesture.target).trigger('pinch') &&\n          $(gesture.target).trigger('pinch' + (gesture.e1 - gesture.e2 > 0 ? 'In' : 'Out'))\n        gesture.e1 = gesture.e2 = gesture.last = 0\n      } else if ('last' in gesture) {\n        gesture = {}\n      }\n    })\n\n    ;['pinch', 'pinchIn', 'pinchOut'].forEach(function(m){\n      $.fn[m] = function(callback){ return this.bind(m, callback) }\n    })\n  }\n})(Zepto)\n"
  },
  {
    "path": "src/ie.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function(){\n  // getComputedStyle shouldn't freak out when called\n  // without a valid element as argument\n  try {\n    getComputedStyle(undefined)\n  } catch(e) {\n    var nativeGetComputedStyle = getComputedStyle\n    window.getComputedStyle = function(element, pseudoElement){\n      try {\n        return nativeGetComputedStyle(element, pseudoElement)\n      } catch(e) {\n        return null\n      }\n    }\n  }\n})()\n"
  },
  {
    "path": "src/ios3.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function(undefined){\n  if (String.prototype.trim === undefined) // fix for iOS 3.2\n    String.prototype.trim = function(){ return this.replace(/^\\s+|\\s+$/g, '') }\n\n  // For iOS 3.x\n  // from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce\n  if (Array.prototype.reduce === undefined)\n    Array.prototype.reduce = function(fun){\n      if(this === void 0 || this === null) throw new TypeError()\n      var t = Object(this), len = t.length >>> 0, k = 0, accumulator\n      if(typeof fun != 'function') throw new TypeError()\n      if(len == 0 && arguments.length == 1) throw new TypeError()\n\n      if(arguments.length >= 2)\n       accumulator = arguments[1]\n      else\n        do{\n          if(k in t){\n            accumulator = t[k++]\n            break\n          }\n          if(++k >= len) throw new TypeError()\n        } while (true)\n\n      while (k < len){\n        if(k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t)\n        k++\n      }\n      return accumulator\n    }\n\n})()\n"
  },
  {
    "path": "src/selector.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($){\n  var zepto = $.zepto, oldQsa = zepto.qsa, oldMatches = zepto.matches\n\n  function visible(elem){\n    elem = $(elem)\n    return !!(elem.width() || elem.height()) && elem.css(\"display\") !== \"none\"\n  }\n\n  // Implements a subset from:\n  // http://api.jquery.com/category/selectors/jquery-selector-extensions/\n  //\n  // Each filter function receives the current index, all nodes in the\n  // considered set, and a value if there were parentheses. The value\n  // of `this` is the node currently being considered. The function returns the\n  // resulting node(s), null, or undefined.\n  //\n  // Complex selectors are not supported:\n  //   li:has(label:contains(\"foo\")) + li:has(label:contains(\"bar\"))\n  //   ul.inner:first > li\n  var filters = $.expr[':'] = {\n    visible:  function(){ if (visible(this)) return this },\n    hidden:   function(){ if (!visible(this)) return this },\n    selected: function(){ if (this.selected) return this },\n    checked:  function(){ if (this.checked) return this },\n    parent:   function(){ return this.parentNode },\n    first:    function(idx){ if (idx === 0) return this },\n    last:     function(idx, nodes){ if (idx === nodes.length - 1) return this },\n    eq:       function(idx, _, value){ if (idx === value) return this },\n    contains: function(idx, _, text){ if ($(this).text().indexOf(text) > -1) return this },\n    has:      function(idx, _, sel){ if (zepto.qsa(this, sel).length) return this }\n  }\n\n  var filterRe = new RegExp('(.*):(\\\\w+)(?:\\\\(([^)]+)\\\\))?$\\\\s*'),\n      childRe  = /^\\s*>/,\n      classTag = 'Zepto' + (+new Date())\n\n  function process(sel, fn) {\n    // quote the hash in `a[href^=#]` expression\n    sel = sel.replace(/=#\\]/g, '=\"#\"]')\n    var filter, arg, match = filterRe.exec(sel)\n    if (match && match[2] in filters) {\n      filter = filters[match[2]], arg = match[3]\n      sel = match[1]\n      if (arg) {\n        var num = Number(arg)\n        if (isNaN(num)) arg = arg.replace(/^[\"']|[\"']$/g, '')\n        else arg = num\n      }\n    }\n    return fn(sel, filter, arg)\n  }\n\n  zepto.qsa = function(node, selector) {\n    return process(selector, function(sel, filter, arg){\n      try {\n        var taggedParent\n        if (!sel && filter) sel = '*'\n        else if (childRe.test(sel))\n          // support \"> *\" child queries by tagging the parent node with a\n          // unique class and prepending that classname onto the selector\n          taggedParent = $(node).addClass(classTag), sel = '.'+classTag+' '+sel\n\n        var nodes = oldQsa(node, sel)\n      } catch(e) {\n        console.error('error performing selector: %o', selector)\n        throw e\n      } finally {\n        if (taggedParent) taggedParent.removeClass(classTag)\n      }\n      return !filter ? nodes :\n        zepto.uniq($.map(nodes, function(n, i){ return filter.call(n, i, nodes, arg) }))\n    })\n  }\n\n  zepto.matches = function(node, selector){\n    return process(selector, function(sel, filter, arg){\n      return (!sel || oldMatches(node, sel)) &&\n        (!filter || filter.call(node, null, arg) === node)\n    })\n  }\n})(Zepto)\n"
  },
  {
    "path": "src/stack.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($){\n  $.fn.end = function(){\n    return this.prevObject || $()\n  }\n\n  $.fn.andSelf = function(){\n    return this.add(this.prevObject || $())\n  }\n\n  'filter,add,not,eq,first,last,find,closest,parents,parent,children,siblings'.split(',').forEach(function(property){\n    var fn = $.fn[property]\n    $.fn[property] = function(){\n      var ret = fn.apply(this, arguments)\n      ret.prevObject = this\n      return ret\n    }\n  })\n})(Zepto)\n"
  },
  {
    "path": "src/touch.js",
    "content": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(function($){\n  var touch = {},\n    touchTimeout, tapTimeout, swipeTimeout, longTapTimeout,\n    longTapDelay = 750,\n    gesture,\n    down, up, move,\n    eventMap,\n    initialized = false\n\n  function swipeDirection(x1, x2, y1, y2) {\n    return Math.abs(x1 - x2) >=\n      Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')\n  }\n\n  function longTap() {\n    longTapTimeout = null\n    if (touch.last) {\n      touch.el.trigger('longTap')\n      touch = {}\n    }\n  }\n\n  function cancelLongTap() {\n    if (longTapTimeout) clearTimeout(longTapTimeout)\n    longTapTimeout = null\n  }\n\n  function cancelAll() {\n    if (touchTimeout) clearTimeout(touchTimeout)\n    if (tapTimeout) clearTimeout(tapTimeout)\n    if (swipeTimeout) clearTimeout(swipeTimeout)\n    if (longTapTimeout) clearTimeout(longTapTimeout)\n    touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null\n    touch = {}\n  }\n\n  function isPrimaryTouch(event){\n    return (event.pointerType == 'touch' ||\n      event.pointerType == event.MSPOINTER_TYPE_TOUCH)\n      && event.isPrimary\n  }\n\n  function isPointerEventType(e, type){\n    return (e.type == 'pointer'+type ||\n      e.type.toLowerCase() == 'mspointer'+type)\n  }\n\n  // helper function for tests, so they check for different APIs\n  function unregisterTouchEvents(){\n    if (!initialized) return\n    $(document).off(eventMap.down, down)\n      .off(eventMap.up, up)\n      .off(eventMap.move, move)\n      .off(eventMap.cancel, cancelAll)\n    $(window).off('scroll', cancelAll)\n    cancelAll()\n    initialized = false\n  }\n\n  function setup(__eventMap){\n    var now, delta, deltaX = 0, deltaY = 0, firstTouch, _isPointerType\n\n    unregisterTouchEvents()\n\n    eventMap = (__eventMap && ('down' in __eventMap)) ? __eventMap :\n      ('ontouchstart' in document ?\n      { 'down': 'touchstart', 'up': 'touchend',\n        'move': 'touchmove', 'cancel': 'touchcancel' } :\n      'onpointerdown' in document ?\n      { 'down': 'pointerdown', 'up': 'pointerup',\n        'move': 'pointermove', 'cancel': 'pointercancel' } :\n       'onmspointerdown' in document ?\n      { 'down': 'MSPointerDown', 'up': 'MSPointerUp',\n        'move': 'MSPointerMove', 'cancel': 'MSPointerCancel' } : false)\n\n    // No API availables for touch events\n    if (!eventMap) return\n\n    if ('MSGesture' in window) {\n      gesture = new MSGesture()\n      gesture.target = document.body\n\n      $(document)\n        .bind('MSGestureEnd', function(e){\n          var swipeDirectionFromVelocity =\n            e.velocityX > 1 ? 'Right' : e.velocityX < -1 ? 'Left' : e.velocityY > 1 ? 'Down' : e.velocityY < -1 ? 'Up' : null\n          if (swipeDirectionFromVelocity) {\n            touch.el.trigger('swipe')\n            touch.el.trigger('swipe'+ swipeDirectionFromVelocity)\n          }\n        })\n    }\n\n    down = function(e){\n      if((_isPointerType = isPointerEventType(e, 'down')) &&\n        !isPrimaryTouch(e)) return\n      firstTouch = _isPointerType ? e : e.touches[0]\n      if (e.touches && e.touches.length === 1 && touch.x2) {\n        // Clear out touch movement data if we have it sticking around\n        // This can occur if touchcancel doesn't fire due to preventDefault, etc.\n        touch.x2 = undefined\n        touch.y2 = undefined\n      }\n      now = Date.now()\n      delta = now - (touch.last || now)\n      touch.el = $('tagName' in firstTouch.target ?\n        firstTouch.target : firstTouch.target.parentNode)\n      touchTimeout && clearTimeout(touchTimeout)\n      touch.x1 = firstTouch.pageX\n      touch.y1 = firstTouch.pageY\n      if (delta > 0 && delta <= 250) touch.isDoubleTap = true\n      touch.last = now\n      longTapTimeout = setTimeout(longTap, longTapDelay)\n      // adds the current touch contact for IE gesture recognition\n      if (gesture && _isPointerType) gesture.addPointer(e.pointerId)\n    }\n\n    move = function(e){\n      if((_isPointerType = isPointerEventType(e, 'move')) &&\n        !isPrimaryTouch(e)) return\n      firstTouch = _isPointerType ? e : e.touches[0]\n      cancelLongTap()\n      touch.x2 = firstTouch.pageX\n      touch.y2 = firstTouch.pageY\n\n      deltaX += Math.abs(touch.x1 - touch.x2)\n      deltaY += Math.abs(touch.y1 - touch.y2)\n    }\n\n    up = function(e){\n      if((_isPointerType = isPointerEventType(e, 'up')) &&\n        !isPrimaryTouch(e)) return\n      cancelLongTap()\n\n      // swipe\n      if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||\n          (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30))\n\n        swipeTimeout = setTimeout(function() {\n          if (touch.el){\n            touch.el.trigger('swipe')\n            touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))\n          }\n          touch = {}\n        }, 0)\n\n      // normal tap\n      else if ('last' in touch)\n        // don't fire tap when delta position changed by more than 30 pixels,\n        // for instance when moving to a point and back to origin\n        if (deltaX < 30 && deltaY < 30) {\n          // delay by one tick so we can cancel the 'tap' event if 'scroll' fires\n          // ('tap' fires before 'scroll')\n          tapTimeout = setTimeout(function() {\n\n            // trigger universal 'tap' with the option to cancelTouch()\n            // (cancelTouch cancels processing of single vs double taps for faster 'tap' response)\n            var event = $.Event('tap')\n            event.cancelTouch = cancelAll\n            // [by paper] fix -> \"TypeError: 'undefined' is not an object (evaluating 'touch.el.trigger'), when double tap\n            if (touch.el) touch.el.trigger(event)\n\n            // trigger double tap immediately\n            if (touch.isDoubleTap) {\n              if (touch.el) touch.el.trigger('doubleTap')\n              touch = {}\n            }\n\n            // trigger single tap after 250ms of inactivity\n            else {\n              touchTimeout = setTimeout(function(){\n                touchTimeout = null\n                if (touch.el) touch.el.trigger('singleTap')\n                touch = {}\n              }, 250)\n            }\n          }, 0)\n        } else {\n          touch = {}\n        }\n        deltaX = deltaY = 0\n    }\n\n    $(document).on(eventMap.up, up)\n      .on(eventMap.down, down)\n      .on(eventMap.move, move)\n\n    // when the browser window loses focus,\n    // for example when a modal dialog is shown,\n    // cancel all ongoing events\n    $(document).on(eventMap.cancel, cancelAll)\n\n    // scrolling the window indicates intention of the user\n    // to scroll, not tap or swipe, so cancel all ongoing events\n    $(window).on('scroll', cancelAll)\n\n    initialized = true\n  }\n\n  ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown',\n    'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(eventName){\n    $.fn[eventName] = function(callback){ return this.on(eventName, callback) }\n  })\n\n  $.touch = { setup: setup }\n\n  $(document).ready(setup)\n})(Zepto)\n"
  },
  {
    "path": "src/zepto.js",
    "content": "//     Zepto.js\n//     (c) 2010-2017 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\nvar Zepto = (function() {\n  var undefined, key, $, classList, emptyArray = [], concat = emptyArray.concat, filter = emptyArray.filter, slice = emptyArray.slice,\n    document = window.document,\n    elementDisplay = {}, classCache = {},\n    cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1,'opacity': 1, 'z-index': 1, 'zoom': 1 },\n    fragmentRE = /^\\s*<(\\w+|!)[^>]*>/,\n    singleTagRE = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\n    tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n    rootNodeRE = /^(?:body|html)$/i,\n    capitalRE = /([A-Z])/g,\n\n    // special attributes that should be get/set via method calls\n    methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'],\n\n    adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ],\n    table = document.createElement('table'),\n    tableRow = document.createElement('tr'),\n    containers = {\n      'tr': document.createElement('tbody'),\n      'tbody': table, 'thead': table, 'tfoot': table,\n      'td': tableRow, 'th': tableRow,\n      '*': document.createElement('div')\n    },\n    simpleSelectorRE = /^[\\w-]*$/,\n    class2type = {},\n    toString = class2type.toString,\n    zepto = {},\n    camelize, uniq,\n    tempParent = document.createElement('div'),\n    propMap = {\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    isArray = Array.isArray ||\n      function(object){ return object instanceof Array }\n\n  zepto.matches = function(element, selector) {\n    if (!selector || !element || element.nodeType !== 1) return false\n    var matchesSelector = element.matches || element.webkitMatchesSelector ||\n                          element.mozMatchesSelector || element.oMatchesSelector ||\n                          element.matchesSelector\n    if (matchesSelector) return matchesSelector.call(element, selector)\n    // fall back to performing a selector:\n    var match, parent = element.parentNode, temp = !parent\n    if (temp) (parent = tempParent).appendChild(element)\n    match = ~zepto.qsa(parent, selector).indexOf(element)\n    temp && tempParent.removeChild(element)\n    return match\n  }\n\n  function type(obj) {\n    return obj == null ? String(obj) :\n      class2type[toString.call(obj)] || \"object\"\n  }\n\n  function isFunction(value) { return type(value) == \"function\" }\n  function isWindow(obj)     { return obj != null && obj == obj.window }\n  function isDocument(obj)   { return obj != null && obj.nodeType == obj.DOCUMENT_NODE }\n  function isObject(obj)     { return type(obj) == \"object\" }\n  function isPlainObject(obj) {\n    return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype\n  }\n\n  function likeArray(obj) {\n    var length = !!obj && 'length' in obj && obj.length,\n      type = $.type(obj)\n\n    return 'function' != type && !isWindow(obj) && (\n      'array' == type || length === 0 ||\n        (typeof length == 'number' && length > 0 && (length - 1) in obj)\n    )\n  }\n\n  function compact(array) { return filter.call(array, function(item){ return item != null }) }\n  function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array }\n  camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) }\n  function dasherize(str) {\n    return str.replace(/::/g, '/')\n           .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')\n           .replace(/([a-z\\d])([A-Z])/g, '$1_$2')\n           .replace(/_/g, '-')\n           .toLowerCase()\n  }\n  uniq = function(array){ return filter.call(array, function(item, idx){ return array.indexOf(item) == idx }) }\n\n  function classRE(name) {\n    return name in classCache ?\n      classCache[name] : (classCache[name] = new RegExp('(^|\\\\s)' + name + '(\\\\s|$)'))\n  }\n\n  function maybeAddPx(name, value) {\n    return (typeof value == \"number\" && !cssNumber[dasherize(name)]) ? value + \"px\" : value\n  }\n\n  function defaultDisplay(nodeName) {\n    var element, display\n    if (!elementDisplay[nodeName]) {\n      element = document.createElement(nodeName)\n      document.body.appendChild(element)\n      display = getComputedStyle(element, '').getPropertyValue(\"display\")\n      element.parentNode.removeChild(element)\n      display == \"none\" && (display = \"block\")\n      elementDisplay[nodeName] = display\n    }\n    return elementDisplay[nodeName]\n  }\n\n  function children(element) {\n    return 'children' in element ?\n      slice.call(element.children) :\n      $.map(element.childNodes, function(node){ if (node.nodeType == 1) return node })\n  }\n\n  function Z(dom, selector) {\n    var i, len = dom ? dom.length : 0\n    for (i = 0; i < len; i++) this[i] = dom[i]\n    this.length = len\n    this.selector = selector || ''\n  }\n\n  // `$.zepto.fragment` takes a html string and an optional tag name\n  // to generate DOM nodes from the given html string.\n  // The generated DOM nodes are returned as an array.\n  // This function can be overridden in plugins for example to make\n  // it compatible with browsers that don't support the DOM fully.\n  zepto.fragment = function(html, name, properties) {\n    var dom, nodes, container\n\n    // A special case optimization for a single tag\n    if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1))\n\n    if (!dom) {\n      if (html.replace) html = html.replace(tagExpanderRE, \"<$1></$2>\")\n      if (name === undefined) name = fragmentRE.test(html) && RegExp.$1\n      if (!(name in containers)) name = '*'\n\n      container = containers[name]\n      container.innerHTML = '' + html\n      dom = $.each(slice.call(container.childNodes), function(){\n        container.removeChild(this)\n      })\n    }\n\n    if (isPlainObject(properties)) {\n      nodes = $(dom)\n      $.each(properties, function(key, value) {\n        if (methodAttributes.indexOf(key) > -1) nodes[key](value)\n        else nodes.attr(key, value)\n      })\n    }\n\n    return dom\n  }\n\n  // `$.zepto.Z` swaps out the prototype of the given `dom` array\n  // of nodes with `$.fn` and thus supplying all the Zepto functions\n  // to the array. This method can be overridden in plugins.\n  zepto.Z = function(dom, selector) {\n    return new Z(dom, selector)\n  }\n\n  // `$.zepto.isZ` should return `true` if the given object is a Zepto\n  // collection. This method can be overridden in plugins.\n  zepto.isZ = function(object) {\n    return object instanceof zepto.Z\n  }\n\n  // `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and\n  // takes a CSS selector and an optional context (and handles various\n  // special cases).\n  // This method can be overridden in plugins.\n  zepto.init = function(selector, context) {\n    var dom\n    // If nothing given, return an empty Zepto collection\n    if (!selector) return zepto.Z()\n    // Optimize for string selectors\n    else if (typeof selector == 'string') {\n      selector = selector.trim()\n      // If it's a html fragment, create nodes from it\n      // Note: In both Chrome 21 and Firefox 15, DOM error 12\n      // is thrown if the fragment doesn't begin with <\n      if (selector[0] == '<' && fragmentRE.test(selector))\n        dom = zepto.fragment(selector, RegExp.$1, context), selector = null\n      // If there's a context, create a collection on that context first, and select\n      // nodes from there\n      else if (context !== undefined) return $(context).find(selector)\n      // If it's a CSS selector, use it to select nodes.\n      else dom = zepto.qsa(document, selector)\n    }\n    // If a function is given, call it when the DOM is ready\n    else if (isFunction(selector)) return $(document).ready(selector)\n    // If a Zepto collection is given, just return it\n    else if (zepto.isZ(selector)) return selector\n    else {\n      // normalize array if an array of nodes is given\n      if (isArray(selector)) dom = compact(selector)\n      // Wrap DOM nodes.\n      else if (isObject(selector))\n        dom = [selector], selector = null\n      // If it's a html fragment, create nodes from it\n      else if (fragmentRE.test(selector))\n        dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null\n      // If there's a context, create a collection on that context first, and select\n      // nodes from there\n      else if (context !== undefined) return $(context).find(selector)\n      // And last but no least, if it's a CSS selector, use it to select nodes.\n      else dom = zepto.qsa(document, selector)\n    }\n    // create a new Zepto collection from the nodes found\n    return zepto.Z(dom, selector)\n  }\n\n  // `$` will be the base `Zepto` object. When calling this\n  // function just call `$.zepto.init, which makes the implementation\n  // details of selecting nodes and creating Zepto collections\n  // patchable in plugins.\n  $ = function(selector, context){\n    return zepto.init(selector, context)\n  }\n\n  function extend(target, source, deep) {\n    for (key in source)\n      if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {\n        if (isPlainObject(source[key]) && !isPlainObject(target[key]))\n          target[key] = {}\n        if (isArray(source[key]) && !isArray(target[key]))\n          target[key] = []\n        extend(target[key], source[key], deep)\n      }\n      else if (source[key] !== undefined) target[key] = source[key]\n  }\n\n  // Copy all but undefined properties from one or more\n  // objects to the `target` object.\n  $.extend = function(target){\n    var deep, args = slice.call(arguments, 1)\n    if (typeof target == 'boolean') {\n      deep = target\n      target = args.shift()\n    }\n    args.forEach(function(arg){ extend(target, arg, deep) })\n    return target\n  }\n\n  // `$.zepto.qsa` is Zepto's CSS selector implementation which\n  // uses `document.querySelectorAll` and optimizes for some special cases, like `#id`.\n  // This method can be overridden in plugins.\n  zepto.qsa = function(element, selector){\n    var found,\n        maybeID = selector[0] == '#',\n        maybeClass = !maybeID && selector[0] == '.',\n        nameOnly = maybeID || maybeClass ? selector.slice(1) : selector, // Ensure that a 1 char tag name still gets checked\n        isSimple = simpleSelectorRE.test(nameOnly)\n    return (element.getElementById && isSimple && maybeID) ? // Safari DocumentFragment doesn't have getElementById\n      ( (found = element.getElementById(nameOnly)) ? [found] : [] ) :\n      (element.nodeType !== 1 && element.nodeType !== 9 && element.nodeType !== 11) ? [] :\n      slice.call(\n        isSimple && !maybeID && element.getElementsByClassName ? // DocumentFragment doesn't have getElementsByClassName/TagName\n          maybeClass ? element.getElementsByClassName(nameOnly) : // If it's simple, it could be a class\n          element.getElementsByTagName(selector) : // Or a tag\n          element.querySelectorAll(selector) // Or it's not simple, and we need to query all\n      )\n  }\n\n  function filtered(nodes, selector) {\n    return selector == null ? $(nodes) : $(nodes).filter(selector)\n  }\n\n  $.contains = document.documentElement.contains ?\n    function(parent, node) {\n      return parent !== node && parent.contains(node)\n    } :\n    function(parent, node) {\n      while (node && (node = node.parentNode))\n        if (node === parent) return true\n      return false\n    }\n\n  function funcArg(context, arg, idx, payload) {\n    return isFunction(arg) ? arg.call(context, idx, payload) : arg\n  }\n\n  function setAttribute(node, name, value) {\n    value == null ? node.removeAttribute(name) : node.setAttribute(name, value)\n  }\n\n  // access className property while respecting SVGAnimatedString\n  function className(node, value){\n    var klass = node.className || '',\n        svg   = klass && klass.baseVal !== undefined\n\n    if (value === undefined) return svg ? klass.baseVal : klass\n    svg ? (klass.baseVal = value) : (node.className = value)\n  }\n\n  // \"true\"  => true\n  // \"false\" => false\n  // \"null\"  => null\n  // \"42\"    => 42\n  // \"42.5\"  => 42.5\n  // \"08\"    => \"08\"\n  // JSON    => parse if valid\n  // String  => self\n  function deserializeValue(value) {\n    try {\n      return value ?\n        value == \"true\" ||\n        ( value == \"false\" ? false :\n          value == \"null\" ? null :\n          +value + \"\" == value ? +value :\n          /^[\\[\\{]/.test(value) ? $.parseJSON(value) :\n          value )\n        : value\n    } catch(e) {\n      return value\n    }\n  }\n\n  $.type = type\n  $.isFunction = isFunction\n  $.isWindow = isWindow\n  $.isArray = isArray\n  $.isPlainObject = isPlainObject\n\n  $.isEmptyObject = function(obj) {\n    var name\n    for (name in obj) return false\n    return true\n  }\n\n  $.isNumeric = function(val) {\n    var num = Number(val), type = typeof val\n    return val != null && type != 'boolean' &&\n      (type != 'string' || val.length) &&\n      !isNaN(num) && isFinite(num) || false\n  }\n\n  $.inArray = function(elem, array, i){\n    return emptyArray.indexOf.call(array, elem, i)\n  }\n\n  $.camelCase = camelize\n  $.trim = function(str) {\n    return str == null ? \"\" : String.prototype.trim.call(str)\n  }\n\n  // plugin compatibility\n  $.uuid = 0\n  $.support = { }\n  $.expr = { }\n  $.noop = function() {}\n\n  $.map = function(elements, callback){\n    var value, values = [], i, key\n    if (likeArray(elements))\n      for (i = 0; i < elements.length; i++) {\n        value = callback(elements[i], i)\n        if (value != null) values.push(value)\n      }\n    else\n      for (key in elements) {\n        value = callback(elements[key], key)\n        if (value != null) values.push(value)\n      }\n    return flatten(values)\n  }\n\n  $.each = function(elements, callback){\n    var i, key\n    if (likeArray(elements)) {\n      for (i = 0; i < elements.length; i++)\n        if (callback.call(elements[i], i, elements[i]) === false) return elements\n    } else {\n      for (key in elements)\n        if (callback.call(elements[key], key, elements[key]) === false) return elements\n    }\n\n    return elements\n  }\n\n  $.grep = function(elements, callback){\n    return filter.call(elements, callback)\n  }\n\n  if (window.JSON) $.parseJSON = JSON.parse\n\n  // Populate the class2type map\n  $.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n    class2type[ \"[object \" + name + \"]\" ] = name.toLowerCase()\n  })\n\n  // Define methods that will be available on all\n  // Zepto collections\n  $.fn = {\n    constructor: zepto.Z,\n    length: 0,\n\n    // Because a collection acts like an array\n    // copy over these useful array functions.\n    forEach: emptyArray.forEach,\n    reduce: emptyArray.reduce,\n    push: emptyArray.push,\n    sort: emptyArray.sort,\n    splice: emptyArray.splice,\n    indexOf: emptyArray.indexOf,\n    concat: function(){\n      var i, value, args = []\n      for (i = 0; i < arguments.length; i++) {\n        value = arguments[i]\n        args[i] = zepto.isZ(value) ? value.toArray() : value\n      }\n      return concat.apply(zepto.isZ(this) ? this.toArray() : this, args)\n    },\n\n    // `map` and `slice` in the jQuery API work differently\n    // from their array counterparts\n    map: function(fn){\n      return $($.map(this, function(el, i){ return fn.call(el, i, el) }))\n    },\n    slice: function(){\n      return $(slice.apply(this, arguments))\n    },\n\n    ready: function(callback){\n      // don't use \"interactive\" on IE <= 10 (it can fired premature)\n      if (document.readyState === \"complete\" ||\n          (document.readyState !== \"loading\" && !document.documentElement.doScroll))\n        setTimeout(function(){ callback($) }, 0)\n      else {\n        var handler = function() {\n          document.removeEventListener(\"DOMContentLoaded\", handler, false)\n          window.removeEventListener(\"load\", handler, false)\n          callback($)\n        }\n        document.addEventListener(\"DOMContentLoaded\", handler, false)\n        window.addEventListener(\"load\", handler, false)\n      }\n      return this\n    },\n    get: function(idx){\n      return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length]\n    },\n    toArray: function(){ return this.get() },\n    size: function(){\n      return this.length\n    },\n    remove: function(){\n      return this.each(function(){\n        if (this.parentNode != null)\n          this.parentNode.removeChild(this)\n      })\n    },\n    each: function(callback){\n      emptyArray.every.call(this, function(el, idx){\n        return callback.call(el, idx, el) !== false\n      })\n      return this\n    },\n    filter: function(selector){\n      if (isFunction(selector)) return this.not(this.not(selector))\n      return $(filter.call(this, function(element){\n        return zepto.matches(element, selector)\n      }))\n    },\n    add: function(selector,context){\n      return $(uniq(this.concat($(selector,context))))\n    },\n    is: function(selector){\n      return typeof selector == 'string' ? this.length > 0 && zepto.matches(this[0], selector) : \n          selector && this.selector == selector.selector\n    },\n    not: function(selector){\n      var nodes=[]\n      if (isFunction(selector) && selector.call !== undefined)\n        this.each(function(idx){\n          if (!selector.call(this,idx)) nodes.push(this)\n        })\n      else {\n        var excludes = typeof selector == 'string' ? this.filter(selector) :\n          (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector)\n        this.forEach(function(el){\n          if (excludes.indexOf(el) < 0) nodes.push(el)\n        })\n      }\n      return $(nodes)\n    },\n    has: function(selector){\n      return this.filter(function(){\n        return isObject(selector) ?\n          $.contains(this, selector) :\n          $(this).find(selector).size()\n      })\n    },\n    eq: function(idx){\n      return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1)\n    },\n    first: function(){\n      var el = this[0]\n      return el && !isObject(el) ? el : $(el)\n    },\n    last: function(){\n      var el = this[this.length - 1]\n      return el && !isObject(el) ? el : $(el)\n    },\n    find: function(selector){\n      var result, $this = this\n      if (!selector) result = $()\n      else if (typeof selector == 'object')\n        result = $(selector).filter(function(){\n          var node = this\n          return emptyArray.some.call($this, function(parent){\n            return $.contains(parent, node)\n          })\n        })\n      else if (this.length == 1) result = $(zepto.qsa(this[0], selector))\n      else result = this.map(function(){ return zepto.qsa(this, selector) })\n      return result\n    },\n    closest: function(selector, context){\n      var nodes = [], collection = typeof selector == 'object' && $(selector)\n      this.each(function(_, node){\n        while (node && !(collection ? collection.indexOf(node) >= 0 : zepto.matches(node, selector)))\n          node = node !== context && !isDocument(node) && node.parentNode\n        if (node && nodes.indexOf(node) < 0) nodes.push(node)\n      })\n      return $(nodes)\n    },\n    parents: function(selector){\n      var ancestors = [], nodes = this\n      while (nodes.length > 0)\n        nodes = $.map(nodes, function(node){\n          if ((node = node.parentNode) && !isDocument(node) && ancestors.indexOf(node) < 0) {\n            ancestors.push(node)\n            return node\n          }\n        })\n      return filtered(ancestors, selector)\n    },\n    parent: function(selector){\n      return filtered(uniq(this.pluck('parentNode')), selector)\n    },\n    children: function(selector){\n      return filtered(this.map(function(){ return children(this) }), selector)\n    },\n    contents: function() {\n      return this.map(function() { return this.contentDocument || slice.call(this.childNodes) })\n    },\n    siblings: function(selector){\n      return filtered(this.map(function(i, el){\n        return filter.call(children(el.parentNode), function(child){ return child!==el })\n      }), selector)\n    },\n    empty: function(){\n      return this.each(function(){ this.innerHTML = '' })\n    },\n    // `pluck` is borrowed from Prototype.js\n    pluck: function(property){\n      return $.map(this, function(el){ return el[property] })\n    },\n    show: function(){\n      return this.each(function(){\n        this.style.display == \"none\" && (this.style.display = '')\n        if (getComputedStyle(this, '').getPropertyValue(\"display\") == \"none\")\n          this.style.display = defaultDisplay(this.nodeName)\n      })\n    },\n    replaceWith: function(newContent){\n      return this.before(newContent).remove()\n    },\n    wrap: function(structure){\n      var func = isFunction(structure)\n      if (this[0] && !func)\n        var dom   = $(structure).get(0),\n            clone = dom.parentNode || this.length > 1\n\n      return this.each(function(index){\n        $(this).wrapAll(\n          func ? structure.call(this, index) :\n            clone ? dom.cloneNode(true) : dom\n        )\n      })\n    },\n    wrapAll: function(structure){\n      if (this[0]) {\n        $(this[0]).before(structure = $(structure))\n        var children\n        // drill down to the inmost element\n        while ((children = structure.children()).length) structure = children.first()\n        $(structure).append(this)\n      }\n      return this\n    },\n    wrapInner: function(structure){\n      var func = isFunction(structure)\n      return this.each(function(index){\n        var self = $(this), contents = self.contents(),\n            dom  = func ? structure.call(this, index) : structure\n        contents.length ? contents.wrapAll(dom) : self.append(dom)\n      })\n    },\n    unwrap: function(){\n      this.parent().each(function(){\n        $(this).replaceWith($(this).children())\n      })\n      return this\n    },\n    clone: function(){\n      return this.map(function(){ return this.cloneNode(true) })\n    },\n    hide: function(){\n      return this.css(\"display\", \"none\")\n    },\n    toggle: function(setting){\n      return this.each(function(){\n        var el = $(this)\n        ;(setting === undefined ? el.css(\"display\") == \"none\" : setting) ? el.show() : el.hide()\n      })\n    },\n    prev: function(selector){ return $(this.pluck('previousElementSibling')).filter(selector || '*') },\n    next: function(selector){ return $(this.pluck('nextElementSibling')).filter(selector || '*') },\n    html: function(html){\n      return 0 in arguments ?\n        this.each(function(idx){\n          var originHtml = this.innerHTML\n          $(this).empty().append( funcArg(this, html, idx, originHtml) )\n        }) :\n        (0 in this ? this[0].innerHTML : null)\n    },\n    text: function(text){\n      return 0 in arguments ?\n        this.each(function(idx){\n          var newText = funcArg(this, text, idx, this.textContent)\n          this.textContent = newText == null ? '' : ''+newText\n        }) :\n        (0 in this ? this.pluck('textContent').join(\"\") : null)\n    },\n    attr: function(name, value){\n      var result\n      return (typeof name == 'string' && !(1 in arguments)) ?\n        (0 in this && this[0].nodeType == 1 && (result = this[0].getAttribute(name)) != null ? result : undefined) :\n        this.each(function(idx){\n          if (this.nodeType !== 1) return\n          if (isObject(name)) for (key in name) setAttribute(this, key, name[key])\n          else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)))\n        })\n    },\n    removeAttr: function(name){\n      return this.each(function(){ this.nodeType === 1 && name.split(' ').forEach(function(attribute){\n        setAttribute(this, attribute)\n      }, this)})\n    },\n    prop: function(name, value){\n      name = propMap[name] || name\n      return (typeof name == 'string' && !(1 in arguments)) ?\n        (this[0] && this[0][name]) :\n        this.each(function(idx){\n          if (isObject(name)) for (key in name) this[propMap[key] || key] = name[key]\n          else this[name] = funcArg(this, value, idx, this[name])\n        })\n    },\n    removeProp: function(name){\n      name = propMap[name] || name\n      return this.each(function(){ delete this[name] })\n    },\n    data: function(name, value){\n      var attrName = 'data-' + name.replace(capitalRE, '-$1').toLowerCase()\n\n      var data = (1 in arguments) ?\n        this.attr(attrName, value) :\n        this.attr(attrName)\n\n      return data !== null ? deserializeValue(data) : undefined\n    },\n    val: function(value){\n      if (0 in arguments) {\n        if (value == null) value = \"\"\n        return this.each(function(idx){\n          this.value = funcArg(this, value, idx, this.value)\n        })\n      } else {\n        return this[0] && (this[0].multiple ?\n           $(this[0]).find('option').filter(function(){ return this.selected }).pluck('value') :\n           this[0].value)\n      }\n    },\n    offset: function(coordinates){\n      if (coordinates) return this.each(function(index){\n        var $this = $(this),\n            coords = funcArg(this, coordinates, index, $this.offset()),\n            parentOffset = $this.offsetParent().offset(),\n            props = {\n              top:  coords.top  - parentOffset.top,\n              left: coords.left - parentOffset.left\n            }\n\n        if ($this.css('position') == 'static') props['position'] = 'relative'\n        $this.css(props)\n      })\n      if (!this.length) return null\n      if (document.documentElement !== this[0] && !$.contains(document.documentElement, this[0]))\n        return {top: 0, left: 0}\n      var obj = this[0].getBoundingClientRect()\n      return {\n        left: obj.left + window.pageXOffset,\n        top: obj.top + window.pageYOffset,\n        width: Math.round(obj.width),\n        height: Math.round(obj.height)\n      }\n    },\n    css: function(property, value){\n      if (arguments.length < 2) {\n        var element = this[0]\n        if (typeof property == 'string') {\n          if (!element) return\n          return element.style[camelize(property)] || getComputedStyle(element, '').getPropertyValue(property)\n        } else if (isArray(property)) {\n          if (!element) return\n          var props = {}\n          var computedStyle = getComputedStyle(element, '')\n          $.each(property, function(_, prop){\n            props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop))\n          })\n          return props\n        }\n      }\n\n      var css = ''\n      if (type(property) == 'string') {\n        if (!value && value !== 0)\n          this.each(function(){ this.style.removeProperty(dasherize(property)) })\n        else\n          css = dasherize(property) + \":\" + maybeAddPx(property, value)\n      } else {\n        for (key in property)\n          if (!property[key] && property[key] !== 0)\n            this.each(function(){ this.style.removeProperty(dasherize(key)) })\n          else\n            css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'\n      }\n\n      return this.each(function(){ this.style.cssText += ';' + css })\n    },\n    index: function(element){\n      return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf(this[0])\n    },\n    hasClass: function(name){\n      if (!name) return false\n      return emptyArray.some.call(this, function(el){\n        return this.test(className(el))\n      }, classRE(name))\n    },\n    addClass: function(name){\n      if (!name) return this\n      return this.each(function(idx){\n        if (!('className' in this)) return\n        classList = []\n        var cls = className(this), newName = funcArg(this, name, idx, cls)\n        newName.split(/\\s+/g).forEach(function(klass){\n          if (!$(this).hasClass(klass)) classList.push(klass)\n        }, this)\n        classList.length && className(this, cls + (cls ? \" \" : \"\") + classList.join(\" \"))\n      })\n    },\n    removeClass: function(name){\n      return this.each(function(idx){\n        if (!('className' in this)) return\n        if (name === undefined) return className(this, '')\n        classList = className(this)\n        funcArg(this, name, idx, classList).split(/\\s+/g).forEach(function(klass){\n          classList = classList.replace(classRE(klass), \" \")\n        })\n        className(this, classList.trim())\n      })\n    },\n    toggleClass: function(name, when){\n      if (!name) return this\n      return this.each(function(idx){\n        var $this = $(this), names = funcArg(this, name, idx, className(this))\n        names.split(/\\s+/g).forEach(function(klass){\n          (when === undefined ? !$this.hasClass(klass) : when) ?\n            $this.addClass(klass) : $this.removeClass(klass)\n        })\n      })\n    },\n    scrollTop: function(value){\n      if (!this.length) return\n      var hasScrollTop = 'scrollTop' in this[0]\n      if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset\n      return this.each(hasScrollTop ?\n        function(){ this.scrollTop = value } :\n        function(){ this.scrollTo(this.scrollX, value) })\n    },\n    scrollLeft: function(value){\n      if (!this.length) return\n      var hasScrollLeft = 'scrollLeft' in this[0]\n      if (value === undefined) return hasScrollLeft ? this[0].scrollLeft : this[0].pageXOffset\n      return this.each(hasScrollLeft ?\n        function(){ this.scrollLeft = value } :\n        function(){ this.scrollTo(value, this.scrollY) })\n    },\n    position: function() {\n      if (!this.length) return\n\n      var elem = this[0],\n        // Get *real* offsetParent\n        offsetParent = this.offsetParent(),\n        // Get correct offsets\n        offset       = this.offset(),\n        parentOffset = rootNodeRE.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( $(elem).css('margin-top') ) || 0\n      offset.left -= parseFloat( $(elem).css('margin-left') ) || 0\n\n      // Add offsetParent borders\n      parentOffset.top  += parseFloat( $(offsetParent[0]).css('border-top-width') ) || 0\n      parentOffset.left += parseFloat( $(offsetParent[0]).css('border-left-width') ) || 0\n\n      // Subtract the two offsets\n      return {\n        top:  offset.top  - parentOffset.top,\n        left: offset.left - parentOffset.left\n      }\n    },\n    offsetParent: function() {\n      return this.map(function(){\n        var parent = this.offsetParent || document.body\n        while (parent && !rootNodeRE.test(parent.nodeName) && $(parent).css(\"position\") == \"static\")\n          parent = parent.offsetParent\n        return parent\n      })\n    }\n  }\n\n  // for now\n  $.fn.detach = $.fn.remove\n\n  // Generate the `width` and `height` functions\n  ;['width', 'height'].forEach(function(dimension){\n    var dimensionProperty =\n      dimension.replace(/./, function(m){ return m[0].toUpperCase() })\n\n    $.fn[dimension] = function(value){\n      var offset, el = this[0]\n      if (value === undefined) return isWindow(el) ? el['inner' + dimensionProperty] :\n        isDocument(el) ? el.documentElement['scroll' + dimensionProperty] :\n        (offset = this.offset()) && offset[dimension]\n      else return this.each(function(idx){\n        el = $(this)\n        el.css(dimension, funcArg(this, value, idx, el[dimension]()))\n      })\n    }\n  })\n\n  function traverseNode(node, fun) {\n    fun(node)\n    for (var i = 0, len = node.childNodes.length; i < len; i++)\n      traverseNode(node.childNodes[i], fun)\n  }\n\n  // Generate the `after`, `prepend`, `before`, `append`,\n  // `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods.\n  adjacencyOperators.forEach(function(operator, operatorIndex) {\n    var inside = operatorIndex % 2 //=> prepend, append\n\n    $.fn[operator] = function(){\n      // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings\n      var argType, nodes = $.map(arguments, function(arg) {\n            var arr = []\n            argType = type(arg)\n            if (argType == \"array\") {\n              arg.forEach(function(el) {\n                if (el.nodeType !== undefined) return arr.push(el)\n                else if ($.zepto.isZ(el)) return arr = arr.concat(el.get())\n                arr = arr.concat(zepto.fragment(el))\n              })\n              return arr\n            }\n            return argType == \"object\" || arg == null ?\n              arg : zepto.fragment(arg)\n          }),\n          parent, copyByClone = this.length > 1\n      if (nodes.length < 1) return this\n\n      return this.each(function(_, target){\n        parent = inside ? target : target.parentNode\n\n        // convert all methods to a \"before\" operation\n        target = operatorIndex == 0 ? target.nextSibling :\n                 operatorIndex == 1 ? target.firstChild :\n                 operatorIndex == 2 ? target :\n                 null\n\n        var parentInDocument = $.contains(document.documentElement, parent)\n\n        nodes.forEach(function(node){\n          if (copyByClone) node = node.cloneNode(true)\n          else if (!parent) return $(node).remove()\n\n          parent.insertBefore(node, target)\n          if (parentInDocument) traverseNode(node, function(el){\n            if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' &&\n               (!el.type || el.type === 'text/javascript') && !el.src){\n              var target = el.ownerDocument ? el.ownerDocument.defaultView : window\n              target['eval'].call(target, el.innerHTML)\n            }\n          })\n        })\n      })\n    }\n\n    // after    => insertAfter\n    // prepend  => prependTo\n    // before   => insertBefore\n    // append   => appendTo\n    $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){\n      $(html)[operator](this)\n      return this\n    }\n  })\n\n  zepto.Z.prototype = Z.prototype = $.fn\n\n  // Export internal API functions in the `$.zepto` namespace\n  zepto.uniq = uniq\n  zepto.deserializeValue = deserializeValue\n  $.zepto = zepto\n\n  return $\n})()\n\n// If `$` is not yet defined, point it to `Zepto`\nwindow.Zepto = Zepto\nwindow.$ === undefined && (window.$ = Zepto)\n"
  },
  {
    "path": "test/ajax.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Ajax unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto event ajax ie')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto Ajax unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n  <div id=\"fixtures\">\n    <div id=\"ajax_load\"></div>\n  </div>\n\n  <script>\n  (function(){\n\n    function deferredResume(t, fn) {\n      setTimeout(function() { t.resume(fn || function(){}) }, 5)\n    }\n\n    function resumeOnAjaxError(t) {\n      $(document).on('ajaxError', function(e, xhr){\n        deferredResume(t, function(){\n          t.assert(false, \"request errored out: \" + xhr.responseText)\n        })\n      })\n    }\n\n    function toArray(list) {\n      if ($.type(list) == \"string\") return list.split(/(?:\\s*,\\s*|\\s+)/)\n      else return list\n    }\n\n    Evidence.Assertions.assertEqualList = function(expected, actual, message) {\n      var expectedList = toArray(expected),\n          actualList   = toArray(actual)\n\n      this._assertExpression(\n        expectedList.join(' ') == actualList.join(' '),\n        message || \"Lists don't match.\",\n        'Expected %o, got %o.', expectedList, actualList\n      )\n    }\n\n    Evidence.Assertions.assertLine = function(line, string, message) {\n      var lines = string.split(\"\\n\")\n\n      this._assertExpression(\n        $.inArray(line, lines) >= 0,\n        message || \"Line not found.\",\n        'Expected line %s in %s.', line, string\n      )\n    }\n\n    Evidence.Assertions.assertLinePattern = function(pattern, string, message) {\n      var lines = string.split(\"\\n\")\n\n      var i, match = false\n      if (lines.length) {\n        for (i = 0; i < lines.length; i++) {\n          if (lines[i].search(pattern) !== -1) {\n            match = true\n            break\n          }\n        }\n      }\n\n      this._assertExpression(\n        match === true,\n        message || \"Pattern not found.\",\n        'Expected pattern %s in %s.', pattern, string\n      )\n    }\n\n    var slice = [].slice\n\n    function CallbackRegistry(t) {\n      this.testCase = t\n      this.called = []\n    }\n    $.extend(CallbackRegistry.prototype, {\n      register: function(name, context, args){\n        this.called.push([name, context, args])\n      },\n      handler: function(name, fn){\n        var that = this\n        return function(){\n          that.register(name, this, slice.call(arguments))\n          if (fn) return fn.apply(this, arguments)\n        }\n      },\n      resumeHandler: function(name, fn){\n        var that = this\n        return this.handler(name, function(){\n          var context = this, args = arguments\n          setTimeout(function(){\n            that.testCase.resume(function(){\n              if (fn) fn.apply(context, args)\n            })\n          }, 5)\n        })\n      },\n      handlers: function(){\n        var that = this, hash = {}\n        $.each(arguments, function(i, name){\n          hash[name] = that.handler(name)\n        })\n        return hash\n      },\n      events: function(){\n        return $.map(this.called, function(item){ return item[0] })\n      },\n      context: function(name){\n        return this.find(name, function(item){ return item[1] })\n      },\n      args: function(name){\n        return this.find(name, function(item){ return item[2] })\n      },\n      target: function(name){\n        var args = this.args(name)\n        return args && args[0].target\n      },\n      find: function(name, fn){\n        var obj\n        $.each(this.called, function(i, item){\n          if (item[0] == name) {\n            obj = fn(item)\n            return false\n          }\n        })\n        return obj\n      }\n    })\n\n    Evidence('ZeptoAjaxTest', {\n\n      setUp: function() {\n        var reg = new CallbackRegistry(this),\n            globals = toArray('ajaxBeforeSend ajaxSend ajaxSuccess ajaxError ajaxComplete')\n\n        $(document).on(reg.handlers.apply(reg, globals))\n        this.reg = reg\n        window.jsonpDummy = $.noop\n      },\n\n      tearDown: function() {\n        $(document).off()\n        for (var key in window)\n          if (/^(Zepto\\d+|blah)$/.test(key) && window[key] === undefined)\n            delete window[key]\n      },\n\n      testAjaxBase: function(t){\n        t.pause()\n        var xhr = $.ajax({\n          url: 'fixtures/ajax_load_simple.html',\n          success:  t.reg.handler('success'),\n          error:    t.reg.handler('error'),\n          complete: t.reg.resumeHandler('complete', function(){\n            t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess complete ajaxComplete', t.reg.events())\n          })\n        })\n        t.assert($.isFunction(xhr.getResponseHeader))\n      },\n\n      testAjaxGet: function(t){\n        t.pause()\n        var xhr = $.get('echo', t.reg.resumeHandler('success', function(response){\n          t.assertIdentical(window, this)\n          t.assertLine(\"GET ?{}\", response)\n          t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())\n        }))\n        t.assertIn('abort', xhr)\n      },\n\n      testAjaxGetWithParams: function(t){\n        t.pause()\n        $.get('echo', { sample: 'data' }, t.reg.resumeHandler('success', function(response){\n          t.assertLine('GET ?{\"sample\":\"data\"}', response)\n          t.assertLine(\"accept: */*\", response)\n        }))\n      },\n\n      testAjaxGetWithParamsAndType: function(t){\n        t.pause()\n        $.get('echo', { sample: 'plain' }, t.reg.resumeHandler('success', function(response){\n          t.assertLine('GET ?{\"sample\":\"plain\"}', response)\n          t.assertLine(\"accept: text/plain\", response)\n        }), 'text')\n      },\n\n      testAjaxGetWithParamsAndTypeNoCallback: function(t){\n        t.pause()\n        $(document).on('ajaxSuccess', function(e, xhr, settings, response){\n          deferredResume(t, function(){\n            t.assertLine('GET ?{\"sample\":\"plain\"}', response)\n            t.assertLine(\"accept: text/plain\", response)\n            t.assertEqualList('ajaxBeforeSend ajaxSend ajaxSuccess ajaxComplete', t.reg.events())\n          })\n        })\n        $.get('echo', { sample: 'plain' }, 'text')\n      },\n\n      testAjaxGetWithParamsAutoParsesJSON: function(t) {\n        t.pause()\n        $.get('json', { sample: 'data' }, t.reg.resumeHandler('success', function(data){\n          t.assertEqual('data', data.query.sample)\n          t.assertEqual('world', data.hello)\n        }))\n      },\n\n      testAjaxGetNoParamsAutoParsesJSON: function(t) {\n        t.pause()\n        $.get('json', t.reg.resumeHandler('success', function(data){\n          t.assertIdentical(0, $.map(data.query).length)\n          t.assertEqual('world', data.hello)\n        }))\n      },\n\n      testAjaxGetNullParamsAutoParsesJSON: function(t) {\n        t.pause()\n        $.get('json', null, t.reg.resumeHandler('success', function(data){\n          t.assertIdentical(0, $.map(data.query).length)\n          t.assertEqual('world', data.hello)\n        }))\n      },\n\n      testAjaxBeforeSendSetRequestHeader: function(t){\n        t.pause()\n        $.ajax({\n          url: 'echo',\n          beforeSend: function(xhr, settings){\n            xhr.setRequestHeader('Accept', 'text/plain')\n            t.assertUndefined(settings.headers)\n          },\n          success: t.reg.resumeHandler('success', function(response){\n            t.assertLine(\"accept: text/plain\", response)\n          })\n        })\n      },\n\n      testAjaxPost: function(t){\n        t.pause()\n        var xhr = $.post('echo', t.reg.resumeHandler('success', function(response){\n          t.assertIdentical(window, this)\n          t.assertLine(\"POST ?{}\", response)\n          t.assertLine(\"accept: */*\", response)\n          t.assertLine('{}', response)\n          t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())\n        }))\n        t.assertIn('abort', xhr)\n      },\n\n      testAjaxPostWithPayloadAndType: function(t) {\n        t.pause()\n        var payload = { sample: 'data' }\n        $.post('echo', payload, t.reg.resumeHandler('success', function(response){\n          t.assertLine(\"content-type: application/x-www-form-urlencoded\", response)\n          t.assertLine(\"accept: text/plain\", response)\n          t.assertLine('{\"sample\":\"data\"}', response)\n        }), 'text')\n      },\n\n      testAjaxPostAutoParsesJSON: function(t) {\n        t.pause()\n        var payload = { sample: 'data' }\n        $.post('create', payload, t.reg.resumeHandler('success', function(data){\n          t.assertEqual('data', data.payload.sample)\n        }))\n      },\n\n      testNumberOfActiveRequests: function(t) {\n        var maxActive = 0, ajaxStarted = 0, ajaxEnded = 0, requestsCompleted = 0\n        t.assertIdentical(0, $.active, 'initial count mismatch')\n        $(document)\n          .on('ajaxStart', function() { ajaxStarted++ })\n          .on('ajaxEnd', function() { ajaxEnded++ })\n          .on('ajaxSend', function() {\n            if ($.active > maxActive) maxActive = $.active\n          })\n          .on('ajaxComplete', function() {\n            if (++requestsCompleted == 3)\n              deferredResume(t, function() {\n                this.assertEqual(3, maxActive)\n                this.assertIdentical(0, $.active)\n              })\n          })\n\n        t.pause()\n        $.ajax({ url: 'echo' })\n        $.ajax({ url: 'echo' })\n        $.ajax({ url: 'echo' })\n      },\n\n      testAjaxJSON: function(t){\n        t.pause()\n        resumeOnAjaxError(t)\n\n        $.ajax({\n          url: 'json',\n          headers: { accept: 'application/json' },\n          success: t.reg.resumeHandler('success', function(data){\n            t.assertEqual('world', data.hello)\n          })\n        })\n      },\n\n      testAjaxDataFilterJSON: function(t){\n        t.pause()\n        resumeOnAjaxError(t)\n\n        $.ajax({\n          url: 'taintedJSON',\n          dataFilter: function(data, type) {\n            if (!data) return\n            return data.replace(/^\\s*while\\(1\\);\\s*/, '')\n          },\n          headers: { accept: 'application/json' },\n          success: t.reg.resumeHandler('success', function(data){\n            t.assertEqual('world', data.hello)\n          })\n        })\n      },\n\n      testAjaxGetJSON: function(t){\n        t.pause()\n        resumeOnAjaxError(t)\n\n        var xhr = $.getJSON(\n          'json',\n          t.reg.resumeHandler('success', function(data){\n            t.assertEqual('world', data.hello)\n            t.assert($.isEmptyObject(data.query))\n            t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())\n          })\n        )\n        t.assertIn('abort', xhr)\n      },\n\n      testAjaxGetJSONWithParams: function(t){\n        t.pause()\n        resumeOnAjaxError(t)\n\n        $.getJSON(\n          'json', { sample: 'data' },\n          t.reg.resumeHandler('success', function(data){\n            t.assertEqual('data', data.query.sample)\n          }),\n          'text' // ignored\n        )\n      },\n\n      testAjaxJSONParserError: function(t){\n        t.pause()\n        $.ajax({\n          url:      'json',\n          dataType: 'json',\n          data:     { invalid: true },\n          success:  t.reg.handler('success'),\n          error:    t.reg.handler('error'),\n          complete: t.reg.resumeHandler('complete', function(){\n            t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())\n            var errorArgs = t.reg.args('error')\n            t.assertEqual('parsererror', errorArgs[1])\n            t.assert(errorArgs[2] instanceof SyntaxError)\n            var globalErrorArgs = t.reg.args('ajaxError')\n            t.assert(globalErrorArgs[3] instanceof SyntaxError)\n            t.assertEqual(0, $('script[src^=slow]').size())\n          })\n        })\n      },\n\n      testAjaxEqualQuestionmarkIsNotAlwaysJSONP: function(t){\n        t.pause()\n        resumeOnAjaxError(t)\n        $.ajax({\n          url: 'echo=?',\n          dataType: 'text',\n          success: t.reg.resumeHandler('success', function(data){\n            t.assertLine('GET ?{}', data)\n            t.assertLine(\"accept: text/plain\", data)\n          })\n        })\n      },\n\n      testAjaxGetJSONP: function(t){\n        t.pause()\n        $.getJSON(\n          'jsonp?callback=?&timestamp='+(+new Date),\n          t.reg.resumeHandler('success', function(data){\n            t.assertEqual('world', data.hello)\n            t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())\n            t.assertEqual(0, $('script[src^=jsonp]').size())\n          })\n        )\n        t.assertEqual(1, $('script[src^=jsonp]').size())\n      },\n\n      testAjaxGetJSONPWithParams: function(t){\n        t.pause()\n        $.getJSON(\n          'jsonp?callback=?&timestamp='+(+new Date),\n          { sample: 'data' },\n          t.reg.resumeHandler('success', function(data){\n            t.assertEqual('data', data.query.sample)\n          })\n        )\n      },\n\n      testAjaxJSONP: function(t){\n        t.pause()\n        var xhr = $.ajaxJSONP({\n          url: 'jsonp?callback=?&timestamp='+(+new Date),\n          success:  t.reg.handler('success'),\n          complete: t.reg.resumeHandler('complete', function(data){\n            var successArgs = t.reg.args('success')\n            t.assertEqual('world', successArgs[0].hello)\n            t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess complete ajaxComplete', t.reg.events())\n            t.assertEqual(0, $('script[src^=jsonp]').size())\n          })\n        })\n        t.assertIn('abort', xhr)\n      },\n\n      testAjaxJSONPBeforeSend: function(t){\n        t.pause()\n        $(document).on('ajaxBeforeSend', function(){ return false })\n\n        $.ajax({\n          url: 'jsonp?callback=?&timestamp='+(+new Date),\n          beforeSend: t.reg.resumeHandler('beforeSend', function(){\n            t.assertEqualList('beforeSend ajaxBeforeSend ajaxError complete ajaxComplete', t.reg.events())\n          }),\n          success:  t.reg.handler('success'),\n          complete: t.reg.handler('complete')\n        })\n      },\n\n      testAjaxGetJSONPErrorCallback: function(t){\n        t.pause()\n        $.ajax({\n          type:     'GET',\n          url:      'fixtures/404.js?timestamp='+(+new Date),\n          dataType: 'jsonp',\n          success:  t.reg.handler('success'),\n          error:    t.reg.handler('error'),\n          complete: t.reg.resumeHandler('complete', function(){\n            t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())\n            t.assertEqual(0, $('script[src^=fixtures]').size())\n          })\n        })\n      },\n\n      testAjaxGetJSONPErrorWithoutCallback: function(t){\n        t.pause()\n        $.ajax({\n          type:     'GET',\n          url:      'fixtures/404.js?timestamp='+(+new Date),\n          dataType: 'jsonp',\n          success:  t.reg.handler('success'),\n          complete: t.reg.resumeHandler('complete', function(){\n            t.assertEqualList('ajaxBeforeSend ajaxSend ajaxError complete ajaxComplete', t.reg.events())\n            t.assertEqual(0, $('script[src^=fixtures]').size())\n          })\n        })\n      },\n\n      testAjaxJSONPTimeout: function(t){\n        t.pause()\n        $.ajax({\n          url:      'slow?timestamp='+(+new Date),\n          dataType: 'jsonp',\n          jsonpCallback: 'jsonpDummy',\n          timeout:  20,\n          success:  t.reg.handler('success'),\n          error:    t.reg.handler('error'),\n          complete: t.reg.resumeHandler('complete', function(){\n            t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())\n            var errorArgs = t.reg.args('error')\n            t.assertEqual('timeout', errorArgs[1])\n            var globalErrorArgs = t.reg.args('ajaxError')\n            t.assertEqual('timeout', globalErrorArgs[3])\n            t.assertEqual(0, $('script[src^=slow]').size())\n          })\n        })\n      },\n\n      testAjaxJSONPAbort: function(t){\n        t.pause()\n        var xhr = $.ajax({\n          url:      'slow?timestamp='+(+new Date),\n          dataType: 'jsonp',\n          jsonpCallback: 'jsonpDummy',\n          timeout:  30,\n          success:  t.reg.handler('success'),\n          error:    t.reg.handler('error'),\n          complete: t.reg.handler('complete')\n        })\n        setTimeout(function(){ xhr.abort() }, 10)\n\n        setTimeout(function(){\n          t.resume(function(){\n            t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())\n            var errorArgs = t.reg.args('error')\n            t.assertEqual('abort', errorArgs[1])\n            var globalErrorArgs = t.reg.args('ajaxError')\n            t.assertEqual('abort', globalErrorArgs[3])\n            t.assertEqual(0, $('script[src^=slow]').size())\n          })\n        }, 50)\n      },\n\n      testAjaxJSONPError: function(t){\n        t.pause()\n        var xhr = $.ajax({\n          url:      'error?timestamp='+(+new Date),\n          dataType: 'jsonp',\n          success:  t.reg.handler('success'),\n          error:    t.reg.handler('error'),\n          complete: t.reg.resumeHandler('complete', function(){\n            t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())\n            var errorArgs = t.reg.args('error')\n            t.assertEqual('error', errorArgs[1])\n            t.assertEqual(0, $('script[src^=error]').size())\n          })\n        })\n      },\n\n      testAjaxJSONPWithDataSupport: function(t) {\n        t.pause()\n        var xhr = $.ajax({\n          url: 'jsonp?callback=?&timestamp='+(+new Date),\n          data: {\n            param1: 'val1',\n            param2: 'val2'\n          },\n          success: t.reg.resumeHandler('success', function(data){\n            t.assertEqual('val1', data.query.param1)\n            t.assertEqual('val2', data.query.param2)\n          })\n        })\n      },\n\n      testAjaxJSONPWithCallbackName: function(t) {\n        var xhr = $.ajax({\n          url: 'jsonp',\n          dataType: 'jsonp',\n          jsonpCallback: 'blah',\n          success: t.reg.resumeHandler('success', function(data){\n            t.assertUndefined(window.blah)\n          })\n        })\n\n        t.assert($.isFunction(window.blah))\n        t.pause()\n      },\n\n      testAjaxJSONPWithCallbackNameAsFunction: function(t) {\n        var xhr = $.ajax({\n          url: 'jsonp',\n          dataType: 'jsonp',\n          jsonpCallback: function(){ return 'blah' },\n          success: t.reg.resumeHandler('success', function(data){\n            t.assertUndefined(window.blah)\n          })\n        })\n\n        t.assert($.isFunction(window.blah))\n        t.pause()\n      },\n\n      testAjaxJSONPWithCallbackNameAndJSONPsetToFalse: function(t) {\n        var xhr = $.ajax({\n          url: 'jsonpBlah',\n          dataType: 'jsonp',\n          jsonp: false,\n          jsonpCallback: 'blah',\n          success: t.reg.resumeHandler('success', function(data){\n            t.assertUndefined(window.blah)\n          })\n        })\n\n        var scriptSrc = $('head script:last-child').attr('src')\n        t.assert(/^jsonpBlah\\?_=[\\d]{13}$/.test(scriptSrc), scriptSrc)\n        t.assert($.isFunction(window.blah))\n        t.pause()\n      },\n\n      testAjaxJSONPWithCallbackNameAsFunctionAndJSONPsetToFalse: function(t) {\n        var xhr = $.ajax({\n          url: 'jsonpBlah',\n          dataType: 'jsonp',\n          jsonp: false,\n          jsonpCallback: function(){ return 'blah' },\n          success: t.reg.resumeHandler('success', function(data){\n            t.assertUndefined(window.blah)\n          })\n        })\n\n        var scriptSrc = $('head script:last-child').attr('src')\n        t.assert(/^jsonpBlah\\?_=[\\d]{13}$/.test(scriptSrc), scriptSrc)\n        t.assert($.isFunction(window.blah))\n        t.pause()\n      },\n\n      testAjaxJSONPWithData: function(t) {\n        t.pause()\n        $.ajax({\n          url: 'jsonp',\n          type: 'post',\n          data: { foo: 'bar' },\n          dataType: 'jsonp',\n          success: t.reg.resumeHandler('success', function(data){\n            t.assertEqual('bar', data.query.foo)\n          })\n        })\n      },\n\n      testNoCacheParam: function(t) {\n        t.pause()\n        var xhr = $.ajax({\n          url:'echo',\n          cache: false,\n          success: t.reg.resumeHandler('success', function(response){\n            // check that the no-cache param (or an element of it) looks like a timestamp\n            t.assertLinePattern(/\"_\":(\\[\".*\",)?\"[\\d]{13}\"/g, response)\n          })\n        })\n      },\n\n      testNoCacheParameterWithParam: function(t) {\n        t.pause()\n        var xhr = $.ajax({\n          url:'echo',\n          data:{ data: 'sample' },\n          cache: false,\n          success: t.reg.resumeHandler('success', function(response){\n            // check that the no-cache param (or an element of it) looks like a timestamp\n            t.assertLinePattern(/\"_\":(\\[\".*\",)?\"[\\d]{13}\"/g, response)\n          })\n        })\n      },\n\n      testNoCacheParameterAlreadyPresent: function(t) {\n        t.pause()\n        var xhr = $.ajax({\n          url:'echo',\n          data:{ _: 'test' },\n          cache: false,\n          success: t.reg.resumeHandler('success', function(response){\n            // check that the no-cache param (or an element of it) looks like a timestamp\n            t.assertLinePattern(/\"_\":(\\[\".*\",)?\"[\\d]{13}\"/g, response)\n          })\n        })\n      },\n\n      testNoCacheParameterAlreadyPresentWithParam: function(t) {\n        t.pause()\n        var xhr = $.ajax({\n          url:'echo',\n          data:{ _: 'test', data: 'sample' },\n          cache: false,\n          success: t.reg.resumeHandler('success', function(response){\n            // check that the no-cache param (or an element of it) looks like a timestamp\n            t.assertLinePattern(/\"_\":(\\[\".*\",)?\"[\\d]{13}\"/g, response)\n          })\n        })\n      },\n\n      testJSONPCacheBustingByDefault: function(t) {\n        $.ajax({\n          url: 'jsonp?callback=?',\n          success: t.reg.resumeHandler('success')\n        })\n\n        var scriptSrc = $('head script:last-child').attr('src')\n        t.assert(/^jsonp\\?callback=Zepto\\d+&_=[\\d]{13}$/.test(scriptSrc), scriptSrc)\n        t.pause()\n      },\n\n      testJSONPCacheBustingDisabled: function(t) {\n        $.ajax({\n          url: 'jsonp?callback=?',\n          cache: true,\n          success: t.reg.resumeHandler('success')\n        })\n\n        var scriptSrc = $('head script:last-child').attr('src')\n        t.assert(/^jsonp\\?callback=Zepto\\d+$/.test(scriptSrc), scriptSrc)\n        t.pause()\n      },\n\n      testBrowserCaching: function(t) {\n        t.pause()\n        resumeOnAjaxError(t)\n        $.ajax({\n          url: 'cached',\n          cache: true,\n          success: function(firstResponse){\n            $.ajax({\n              url: 'cached',\n              cache: true,\n              success: t.reg.resumeHandler('success', function(secondResponse){\n                t.assertEqual(secondResponse, firstResponse)\n              })\n            })\n          }\n        })\n      },\n\n      testAjaxLoad: function(t) {\n        t.pause()\n        var testEl = $('#ajax_load')\n        var el = testEl.load(\n          'fixtures/ajax_load_simple.html',\n          t.reg.resumeHandler('success', function(response, status, xhr){\n            t.assertIdentical(testEl, this)\n            t.assertEqual(\"simple ajax load\\n\", response.replace(/\\r\\n|\\r/,\"\\n\"))\n            t.assertEqual('simple ajax load', testEl.html().trim())\n            t.assertEqual('success', status)\n            t.assertIn('abort', xhr)\n            t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())\n          })\n        )\n        t.assertIdentical(testEl, el)\n      },\n\n      testAjaxLoadWithSelector: function(t) {\n        t.pause()\n        var testEl = $('#ajax_load')\n        testEl.load(\n          'fixtures/ajax_load_selector.html #ajax_load_test_div',\n          t.reg.resumeHandler('success', function(){\n            t.assertEqual(\n              '<div id=\"ajax_load_test_div\">ajax load with selector</div>',\n              testEl.html().trim()\n            )\n          })\n        )\n      },\n\n      testAjaxLoadWithJavaScript: function (t) {\n        var testEl = $('#ajax_load')\n        t.pause()\n        window.testValue = 0\n        testEl.load('fixtures/ajax_load_selector_javascript.html', function(){\n          deferredResume(t, function(){\n            this.assertEqual(window.testValue, 1)\n            delete window.testValue\n          })\n        })\n      },\n\n      testAjaxLoadWithSelectorAndJavaScript: function (t) {\n        var testEl = $('#ajax_load')\n        t.pause()\n        window.testValue = 0\n        testEl.load('fixtures/ajax_load_selector_javascript.html #ajax_load_test_div', function() {\n          deferredResume(t, function(){\n            this.assertEqual(window.testValue, 0)\n            delete window.testValue\n          })\n        })\n      },\n\n      testAjaxWithContext: function(t) {\n        t.pause()\n        var body = $('body')\n        $.ajax({\n          url:        'fixtures/ajax_load_simple.html',\n          context:    body,\n          beforeSend: t.reg.handler('beforeSend'),\n          success:    t.reg.handler('success'),\n          complete:   t.reg.resumeHandler('complete', function(){\n            t.assertIdentical(body, this)\n            t.assertIdentical(body, t.reg.context('beforeSend'))\n            t.assertIdentical(body, t.reg.context('success'))\n            t.assertIdentical(document.body, t.reg.target('ajaxBeforeSend'))\n            t.assertIdentical(document.body, t.reg.target('ajaxSuccess'))\n          })\n        })\n      },\n\n      testAjaxWithContextPlainObject: function(t) {\n        t.pause()\n        var obj = {}\n        $.ajax({\n          url:        'fixtures/ajax_load_simple.html',\n          context:    obj,\n          beforeSend: t.reg.handler('beforeSend'),\n          success:    t.reg.handler('success'),\n          complete:   t.reg.resumeHandler('complete', function(){\n            t.assertIdentical(obj, this)\n            t.assertIdentical(obj, t.reg.context('beforeSend'))\n            t.assertIdentical(obj, t.reg.context('success'))\n            t.assertUndefined(t.reg.target('ajaxBeforeSend'))\n            t.assertUndefined(t.reg.target('ajaxSuccess'))\n          })\n        })\n      },\n\n      testAjaxLoadJavaScript: function (t) {\n        t.pause()\n        window.testValue = 0\n        var xhr = $.ajax({\n          url:'fixtures/ajax_load_javascript.js',\n          success: t.reg.resumeHandler('success', function(response){\n            // check that the javascript has loaded and executed.\n            t.assertEqual(window.testValue, 1)\n            delete window.testValue\n          })\n        })\n      },\n\n      testAjaxBasicAuth: function(t) {\n        t.pause()\n        resumeOnAjaxError(t)\n        $.ajax({\n          url: 'auth?realm=zepto',\n          username: 'zepto',\n          password: 'doge',\n          success: t.reg.resumeHandler('success')\n        })\n      }\n    })\n\n    var OriginalXHR = $.ajaxSettings.xhr\n\n    function MockXHR() {\n      this.headers = []\n      this.responseHeaders = {}\n      MockXHR.last = this\n    }\n    MockXHR.prototype = {\n      open: function(method, url, async) {\n        this.method = method\n        this.url = url\n        this.async = async\n      },\n      setRequestHeader: function(name, value) {\n        if (!this.method) throw \"setRequestHeader() called before open()\"\n        this.headers.push({ name: name, value: value })\n      },\n      getResponseHeader: function(name) {\n        return this.responseHeaders[name]\n      },\n      overrideMimeType: function(type) {\n        this.responseHeaders['content-type'] = type\n      },\n      withCredentials: false,\n      send: function(data) {\n        this.data = data\n      },\n      abort: function() {\n        this.aborted = true\n      },\n      ready: function(readyState, status, responseText, headers) {\n        this.readyState = readyState\n        this.status = status\n        this.responseText = responseText\n        $.extend(this.responseHeaders, headers)\n        this.onreadystatechange()\n      },\n      onreadystatechange: function() {}\n    }\n\n    function matchHeader(name, value) {\n      return function(header) {\n        return header.name == name && (!value || header.value == value)\n      }\n    }\n\n    Evidence('ZeptoAjaxTest2', {\n      setUp: function() {\n        $.ajaxSettings.xhr = function(){ return new MockXHR }\n      },\n\n      tearDown: function() {\n        $.ajaxSettings.xhr = OriginalXHR\n        $(document).off()\n        $.active = 0\n      },\n\n      testTypeDefaultsToGET: function(t) {\n        $.ajax({\n          url: '/foo',\n          beforeSend: function(xhr, settings) {\n            t.assertFalse(settings.crossDomain)\n          }\n        })\n        t.assertEqual('GET', MockXHR.last.method)\n      },\n\n      testURLDefaultsToWindowLocation: function(t) {\n        $.ajax()\n        t.assertEqual(window.location, MockXHR.last.url)\n      },\n\n      testCrossDomainCrossOrigin: function(t) {\n        $.ajax({\n          url: 'http://example.com/foo',\n          beforeSend: function(xhr, settings) {\n            t.assertTrue(settings.crossDomain)\n          }\n        })\n      },\n\n      testCrossDomainSameOrigin: function(t) {\n        $.ajax({\n          url: window.location.href,\n          beforeSend: function(xhr, settings) {\n            t.assertFalse(settings.crossDomain)\n          }\n        })\n      },\n\n      testCrossDomainLeadingSpace: function(t) {\n        $.ajax({\n          url: ' http://example.com/foo',\n          beforeSend: function(xhr, settings) {\n            t.assertTrue(settings.crossDomain)\n          }\n        })\n      },\n\n      testCrossDomainTrippleSlash: function(t) {\n        $.ajax({\n          url: 'http:///example.com/foo',\n          beforeSend: function(xhr, settings) {\n            t.assertTrue(settings.crossDomain)\n          }\n        })\n      },\n\n      testCrossDomainWithQuery: function(t) {\n        $.ajax({\n          url: window.location.href + \"?foo=bar\",\n          beforeSend: function(xhr, settings) {\n            t.assertFalse(settings.crossDomain)\n          }\n        })\n      },\n\n      testCrossDomainDifferentScheme: function(t) {\n        $.ajax({\n          url: \"foo://\" + window.location.host,\n          beforeSend: function(xhr, settings) {\n            t.assertTrue(settings.crossDomain)\n          }\n        })\n      },\n\n      testCrossDomainPeriodInScheme: function(t) {\n        $.ajax({\n          url: \"foo.bar://example.com/foo\",\n          beforeSend: function(xhr, settings) {\n            t.assertTrue(settings.crossDomain)\n          }\n        })\n      },\n\n      testDefaultAcceptHeader: function(t) {\n        $.ajax()\n        t.assert(MockXHR.last.headers.some(matchHeader('Accept', '*/*')))\n      },\n\n      testDataTypeOptionSetsAcceptHeader: function(t) {\n        $.ajax({ dataType: 'json' })\n        t.assert(MockXHR.last.headers.some(matchHeader('Accept', 'application/json')))\n        // verifies overrideMimeType:\n        t.assertEqual('application/json', MockXHR.last.getResponseHeader('content-type'))\n\n        $.ajax({ dataType: 'script' })\n        //check that the head matches all of those required for loading scripts.\n        t.assert(MockXHR.last.headers.some(matchHeader('Accept', 'text/javascript, application/javascript, application/x-javascript')))\n      },\n\n      testMimeTypeOptionOverride: function(t) {\n        $.ajax({ mimeType: 'text/plain' })\n        t.assertEqual('text/plain', MockXHR.last.getResponseHeader('content-type'))\n      },\n\n      testContentTypeOptionSetsContentTypeHeader: function(t) {\n        $.ajax()\n        t.assert(!MockXHR.last.headers.some(matchHeader('Content-Type')))\n\n        $.ajax({ contentType: 'text/html' })\n        t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'text/html')))\n\n        $.ajax({ type: 'POST', data: [], contentType: 'application/x-foo' })\n        t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/x-foo')))\n      },\n\n      testHeadersOptionCanSetContentType: function(t) {\n        $.ajax({ type: 'POST', data: [], headers: { 'Content-Type': 'application/hal+json' }})\n        t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/hal+json')))\n      },\n\n      testContentTypeDefaultsToUrlEncoded: function(t) {\n        $.ajax({ type: 'GET', data: 'x' })\n        t.refute(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/x-www-form-urlencoded')))\n        $.ajax({ type: 'POST', data: 'x' })\n        t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/x-www-form-urlencoded')))\n      },\n\n      testDefaultContentTypeDisabled: function(t) {\n        $.ajax({ type: 'POST', data: {a:1}, contentType: false })\n        t.refute(MockXHR.last.headers.some(matchHeader('Content-Type')))\n      },\n\n      testCustomHeader: function(t) {\n        $.ajax({ headers: {'X-Awesome': 'true'} })\n        t.assert(MockXHR.last.headers.some(matchHeader('X-Requested-With', 'XMLHttpRequest')))\n        t.assert(MockXHR.last.headers.some(matchHeader('X-Awesome', 'true')))\n      },\n\n      testXhrFieldsOptionSetsWithCredentialsProperty: function(t) {\n        var xhr = $.ajax({\n          url: 'http://example.com/foo',\n          xhrFields: { withCredentials: true }\n        })\n        t.assert(xhr.withCredentials)\n      },\n\n      testScriptDataTypeCacheBustByDefault: function(t) {\n        $.ajax({ url: '/', dataType: 'script' })\n        var xhr = MockXHR.last\n        t.assert(/^\\/\\?_=[\\d]{13}$/.test(xhr.url), xhr.url)\n      },\n\n      testScriptDataTypeCacheBustDisable: function(t) {\n        $.ajax({ url: '/', dataType: 'script', cache: true })\n        var xhr = MockXHR.last\n        t.assertEqual('/', xhr.url)\n      },\n\n      testJSONdataType: function(t) {\n        var result = {}\n        $.ajax({ dataType: 'json', success: function(json) {result = json } })\n        MockXHR.last.ready(4, 200, '{\"hello\":\"world\"}')\n        t.assertEqual(\"world\", result.hello)\n      },\n\n      testJSONcontentType: function(t) {\n        var result = {}\n        $.ajax({ success: function(json) {result = json } })\n        MockXHR.last.ready(4, 200, '{\"hello\":\"world\"}', {'content-type': 'application/json'})\n        t.assertEqual(\"world\", result.hello)\n      },\n\n      testJSONResponseBodiesAreNotParsedWhenDataTypeOptionIsJSONButResponseIsEmptyString: function(t) {\n        var result, success = false\n        $.ajax({ dataType: 'json', success: function(json) {result = json; success = true } })\n        MockXHR.last.ready(4, 200, '')\n        t.assert(success)\n        t.assertNull(result)\n      },\n\n      testJSONResponseBodiesAreNotParsedWhenDataTypeOptionIsJSONButResponseIsSingleSpace: function(t) {\n        var result, success = false\n        $.ajax({ dataType: 'json', success: function(json) {result = json; success = true } })\n        MockXHR.last.ready(4, 200, ' ')\n        t.assert(success)\n        t.assertNull(result)\n      },\n\n      testDataIsNotSentAsBodyForGetRequests: function(t) {\n        $.ajax({ type: 'GET', data: {a:'b'} })\n        t.assertNull(MockXHR.last.data)\n      },\n\n      testDataOptionIsConvertedToSerializedForm: function(t) {\n        $.ajax({\n          type: 'POST',\n          data: {hello: 'world', array: [1,2,3], object: { prop1: 'val', prop2: 2 } }\n        })\n        var data = decodeURIComponent(MockXHR.last.data)\n        t.assertEqual('hello=world&array[]=1&array[]=2&array[]=3&object[prop1]=val&object[prop2]=2', data)\n      },\n\n      testDataOptionIsConvertedToSerializedTraditionalForm: function(t) {\n        $.ajax({\n          type: 'POST',\n          data: {hello: 'world', array: [1,2,3], object: { prop1: 'val', prop2: 2 } },\n          traditional: true\n        })\n        var data = decodeURIComponent(MockXHR.last.data)\n        t.assertEqual('hello=world&array=1&array=2&array=3&object=[object+Object]', data)\n      },\n\n      testQueryParamsTraditional: function(t) {\n        $.ajax({\n          url: '/',\n          data: {hello: 'world', array: [1,2,3], object: { prop1: 'val', prop2: 2 } },\n          traditional: true\n        })\n        var url = decodeURIComponent(MockXHR.last.url)\n        t.assertEqual('/?hello=world&array=1&array=2&array=3&object=[object+Object]', url)\n      },\n\n      testProcessDataDisabled: function(t) {\n        var data = { country: 'Ecuador' }\n        $.ajax({\n          data: data,\n          processData: false,\n          type: \"POST\"\n        })\n        t.assertIdentical(data, MockXHR.last.data)\n      },\n\n      testDataIsAppendedToGETURL: function(t) {\n        $.ajax({ url:'test.html', data:'foo=bar' })\n        t.assertEqual('test.html?foo=bar', MockXHR.last.url)\n\n        $.ajax({ url:'test.html', data:'?foo=bar' })\n        t.assertEqual('test.html?foo=bar', MockXHR.last.url)\n\n        $.ajax({ url:'test.html?', data:'foo=bar' })\n        t.assertEqual('test.html?foo=bar', MockXHR.last.url)\n\n        $.ajax({ url:'test.html?baz', data:'foo=bar' })\n        t.assertEqual('test.html?baz&foo=bar', MockXHR.last.url)\n\n        $.ajax({ url:'test.html?bar=baz', data:'foo=bar' })\n        t.assertEqual('test.html?bar=baz&foo=bar', MockXHR.last.url)\n\n        $.ajax({ url:'test.html', data:{foo:'bar'} })\n        t.assertEqual('test.html?foo=bar', MockXHR.last.url)\n      },\n\n      testDataIsAppendedToGETURLWithHashStripped: function(t) {\n        $.ajax({ url:'test.html#?ignore=me', data:'foo=bar' })\n        t.assertEqual('test.html?foo=bar', MockXHR.last.url)\n\n        $.ajax({ url:'test.html?a=b#?ignore=me', data:'foo=bar' })\n        t.assertEqual('test.html?a=b&foo=bar', MockXHR.last.url)\n      },\n\n      testScriptResponseIsEvald: function(t) {\n        var result\n        $.ajax({ success: function(text){ result = text } })\n        MockXHR.last.ready(4, 200, 'this.testValue = 42', {'content-type': 'application/javascript'})\n        t.assertEqual('this.testValue = 42', result)\n        t.assertIdentical(42, window.testValue)\n        delete window.testValue\n      },\n\n      testErrorCallback: function(t) {\n        var successFired = false, xhr, status\n        $.ajax({\n          success: function() { successFired = true },\n          error: function(x, s) { xhr = x, status = s }\n        })\n\n        MockXHR.last.ready(4, 500, '500 Internal Server Error')\n        t.assert(!successFired)\n        t.assertEqual(MockXHR.last, xhr)\n        t.assertEqual('error', status)\n      },\n\n      testErrorCallbackWithInvalidJSON: function(t) {\n        var successFired = false, xhr, status, exception\n        $.ajax({\n          dataType: 'json',\n          succes: function() { successFired = true },\n          error: function(x, s, e) { xhr = x, status = s, exception = e }\n        })\n\n        MockXHR.last.ready(4, 200, '{invalid')\n        t.assert(!successFired)\n        t.assertEqual(MockXHR.last, xhr)\n        t.assertEqual('parsererror', status)\n        t.assert(exception.toString().match(/SyntaxError/))\n      },\n\n      test201ResponseIsSuccess: function(t) {\n        var successFired, errorFired\n        $.ajax({\n          success: function() { successFired = true },\n          error: function() { errorFired = true }\n        })\n\n        MockXHR.last.ready(4, 201, 'Created')\n        t.assert(successFired)\n        t.refute(errorFired)\n      },\n\n      test304ResponseIsSuccess: function(t) {\n        var successFired, errorFired\n        $.ajax({\n          success: function() { successFired = true },\n          error: function() { errorFired = true }\n        })\n\n        MockXHR.last.ready(4, 304, 'Not Modified')\n        t.assert(successFired)\n        t.refute(errorFired)\n      },\n      testXHRParameterInSuccessCallback: function(t) {\n        var body, status, xhr\n        $.ajax({\n          success: function(b, s, x) { body = b, status = s, xhr = x }\n        })\n\n        MockXHR.last.ready(4, 200, 'Hello')\n        t.assertEqual('Hello', body)\n        t.assertEqual('success', status)\n        t.assertEqual(MockXHR.last, xhr)\n\n        body = status = xhr = null\n        $.ajax({\n          dataType: 'json',\n          success: function(b, s, x) { body = b, status = s, xhr = x }\n        })\n\n        MockXHR.last.ready(4, 200, '{\"message\":\"Hello\"}')\n        t.assertEqual('Hello', body.message)\n        t.assertEqual('success', status)\n        t.assertEqual(MockXHR.last, xhr)\n      },\n\n      testBeforeSendCanChangeUrl: function(t) {\n        var xhr = $.ajax({\n          url: 'one',\n          beforeSend: function(x, s) {\n            s.url = 'two'\n          }\n        })\n        t.assertEqual('two', xhr.url)\n      },\n\n      testBeforeSendCanChangeMethod: function(t) {\n        var xhr = $.ajax({\n          type: 'POST',\n          beforeSend: function(x, s) {\n            s.type = 'PUT'\n          }\n        })\n        t.assertEqual('PUT', xhr.method)\n      },\n\n      testBeforeSendCanAccessSerializedPostData: function(t) {\n        var xhr = $.ajax({\n          type: 'POST',\n          data: { a:'b' },\n          beforeSend: function(x, s) {\n            s.data = s.data.toUpperCase()\n          }\n        })\n        t.assertEqual('A=B', xhr.data)\n      },\n\n      testBeforeSendCannotAccessRawQueryParams: function(t) {\n        var url, data\n        $.ajax({\n          url: '/',\n          type: 'GET',\n          data: { a:'b' },\n          beforeSend: function(x, s) {\n            url = s.url\n            data = s.data\n          }\n        })\n        t.assertEqual('/?a=b', url)\n        t.assertUndefined(data)\n      },\n\n      testBeforeSendCannotChangeOrAddHeadersViaObject: function(t) {\n        var xhr = $.ajax({\n          headers: { a:'b', c:'d' },\n          beforeSend: function(x, s) {\n            s.headers['a'] = 'B'\n            s.headers['e'] = 'f'\n          }\n        })\n        t.assert(xhr.headers.some(matchHeader('a', 'b')))\n        t.assert(xhr.headers.some(matchHeader('c', 'd')))\n        t.refute(xhr.headers.some(matchHeader('e', 'f')))\n      },\n\n      testBeforeSendCanChangeAndAddHeadersViaXhr: function(t) {\n        var xhr = $.ajax({\n          headers: { a:'b', c:'d' },\n          beforeSend: function(x, s) {\n            x.setRequestHeader('a', 'B')\n            x.setRequestHeader('e', 'f')\n          }\n        })\n        t.assert(xhr.headers.some(matchHeader('a', 'B')))\n        t.assert(xhr.headers.some(matchHeader('c', 'd')))\n        t.assert(xhr.headers.some(matchHeader('e', 'f')))\n      },\n\n      testBeforeSendAbortCallback: function(t) {\n        var xhr, settings\n        $.ajax({\n          beforeSend: function(x, s) {\n            settings = s, xhr = x\n          }\n        })\n\n        t.assertEqual(MockXHR.last, xhr)\n        t.assertEqual('GET', settings.type)\n      },\n\n      testBeforeSendAbort: function(t) {\n        var xhr\n        $.ajax({ beforeSend: function(x) { xhr = x; return false } })\n\n        t.assert(xhr.aborted)\n      },\n\n      testGlobalBeforeSendAbort: function(t) {\n        $(document).on('ajaxBeforeSend', false)\n        var xhr = $.ajax()\n        t.assert(xhr.aborted)\n      },\n\n      testGlobalAjaxSendCantAbort: function(t) {\n        var xhr\n        $(document).on('ajaxSend', function(e, x) { xhr = x; return false })\n        t.assert($.ajax())\n        t.assert(!xhr.aborted)\n      },\n\n      testCompleteCallback: function(t) {\n        var status, xhr\n        $.ajax({ complete: function(x, s) { status = s, xhr = x } })\n\n        MockXHR.last.ready(4, 200, 'OK')\n        t.assertEqual(MockXHR.last, xhr)\n        t.assertEqual('success', status)\n      },\n\n      testCallbackOrder: function(t) {\n        var order = []\n        $.ajax({\n          beforeSend: function() { order.push('beforeSend') },\n          success: function() { order.push('success') },\n          complete: function() { order.push('complete') }\n        })\n\n        MockXHR.last.ready(4, 200, 'OK')\n        t.assertEqual('beforeSend,success,complete', order.join(','))\n      },\n\n      testGlobalCallbacks: function(t) {\n        var fired = []\n        $(document).on('ajaxStart ajaxBeforeSend ajaxSend ajaxSuccess ajaxError ajaxComplete ajaxStop', function(e) {\n          fired.push(e.type)\n        })\n\n        $.ajax({\n          beforeSend: function() { fired.push('beforeSend') },\n          success:    function() { fired.push('success') },\n          error:      function() { fired.push('error') },\n          complete:   function() { fired.push('complete') }\n        })\n        t.assertEqual('ajaxStart beforeSend ajaxBeforeSend ajaxSend', fired.join(' '))\n\n        fired = []\n        MockXHR.last.ready(4, 200, 'OK')\n        t.assertEqual('success ajaxSuccess complete ajaxComplete ajaxStop', fired.join(' '))\n      },\n\n      testGlobalCallbacksOff: function(t) {\n        var fired = []\n        $(document).on('ajaxStart ajaxBeforeSend ajaxSend ajaxSuccess ajaxError ajaxComplete ajaxStop', function(e) {\n          fired.push(e.type)\n        })\n\n        $.ajax({\n          global:     false,\n          beforeSend: function() { fired.push('beforeSend') },\n          success:    function() { fired.push('success') },\n          error:      function() { fired.push('error') },\n          complete:   function() { fired.push('complete') }\n        })\n        t.assertEqual('beforeSend', fired.join(' '))\n\n        fired = []\n        MockXHR.last.ready(4, 200, 'OK')\n        t.assertEqual('success complete', fired.join(' '))\n      },\n\n      testTimeout: function(t) {\n        var successFired = false, xhr, status, globalStatus\n        t.pause()\n        $(document).on('ajaxError', function (e, x, o, s) {\n          globalStatus = s\n        })\n\n        $.ajax({\n          timeout: 30,\n          success: function() { successFired = true },\n          error: function(x, s) { xhr = x, status = s }\n        })\n\n        setTimeout(function(){\n          t.assertFalse(successFired)\n          t.assertUndefined(status)\n        }, 20)\n\n        setTimeout(function(){\n          t.resume(function(){\n            t.assertFalse(successFired)\n            t.assertTrue(xhr.aborted)\n            t.assertEqual('timeout', status)\n            t.assertEqual('timeout', globalStatus)\n          })\n        }, 40)\n      },\n\n      testAbort: function(t) {\n        var successFired = false, xhr, status, globalStatus\n        t.pause()\n        $(document).on('ajaxError', function (e, x, o, s) {\n          globalStatus = s\n        })\n\n        $.ajax({\n          success: function() { successFired = true },\n          error: function(x, s) { xhr = x, status = s }\n        })\n        MockXHR.last.abort()\n        MockXHR.last.ready(4, 0, 'Aborted')\n\n        setTimeout(function(){\n          t.resume(function(){\n            t.assertFalse(successFired)\n            t.assertTrue(xhr.aborted)\n            t.assertEqual('abort', status)\n            t.assertEqual('abort', globalStatus)\n          })\n        }, 20)\n      },\n\n      testAsyncDefaultsToTrue: function(t) {\n        $.ajax({ url: '/foo' })\n        t.assertTrue(MockXHR.last.async)\n      },\n\n      testAsyncFalse: function(t) {\n        $.ajax({ url: '/foo', async: false })\n        t.assertFalse(MockXHR.last.async)\n      }\n    })\n\n    Evidence('ZeptoAjaxHelperMethodsTest', {\n\n      testParamMethod: function(t) {\n        var result = $.param({ libs: ['jQuery', 'script.aculo.us', 'Prototype', 'Dojo'] })\n        result = decodeURIComponent(result)\n        t.assertEqual(result, \"libs[]=jQuery&libs[]=script.aculo.us&libs[]=Prototype&libs[]=Dojo\")\n\n        result = $.param({ jquery: 'Javascript', rails: 'Ruby', django: 'Python' })\n        result = decodeURIComponent(result)\n        t.assertEqual(result, \"jquery=Javascript&rails=Ruby&django=Python\")\n\n        result = $.param({\n          title: \"Some Countries\",\n          list: ['Ecuador', 'Austria', 'England'],\n          capitals: { ecuador: 'Quito', austria: 'Vienna', GB: { england: 'London', scotland: 'Edinburgh'} }\n        })\n        result = decodeURIComponent(result)\n        t.assertEqual(result, \"title=Some+Countries&list[]=Ecuador&list[]=Austria&list[]=England&capitals[ecuador]=Quito&capitals[austria]=Vienna&capitals[GB][england]=London&capitals[GB][scotland]=Edinburgh\")\n      },\n\n      testParamNullValues: function(t) {\n        t.assertEqual(\"x=&a[b]=&a[c]=\",\n          decodeURIComponent($.param({ x: null, a: { b: null, c: undefined }})))\n        t.assertEqual(\"x=\",\n          decodeURIComponent($.param([{ name: \"x\", value: null }])))\n      },\n\n      testParamFunctionValues: function(t) {\n        t.assertEqual(\"x=&a[b]=B\",\n          decodeURIComponent($.param({ x: function(){}, a: { b: function(){ return \"B\" }}})))\n        t.assertEqual(\"x=&a[b]=B\",\n          decodeURIComponent($.param([{ name: \"x\", value: null }, { name: \"a[b]\", value: function(){ return \"B\" }}])))\n      },\n\n      testParamEscaping: function(t) {\n        var result = $.param({ 'equation[1]': 'bananas+peaches=smoothie' })\n        t.assertEqual(\"equation%5B1%5D=bananas%2Bpeaches%3Dsmoothie\", result)\n      },\n\n      testParamSpaces: function(t) {\n        var result = $.param({ \"foo bar\": \"baz kuux\" })\n        t.assertEqual(\"foo+bar=baz+kuux\", result)\n      },\n\n      testParamComplex: function(t) {\n        var data = {\n          a: ['b', 'c', { d:'e', f:['g','h'] }]\n        }\n        var result = $.param(data)\n        result = decodeURIComponent(result)\n        t.assertEqual(\"a[]=b&a[]=c&a[2][d]=e&a[2][f][]=g&a[2][f][]=h\", result)\n      },\n\n      testParamComplexIssue850: function(t) {\n        var data = {\n          $push: { _:[ { name: 'bob', members:['aaa'] } ] }\n        }\n        var result = $.param(data)\n        result = decodeURIComponent(result)\n        t.assertEqual(\"$push[_][0][name]=bob&$push[_][0][members][]=aaa\", result)\n      },\n\n      testParamComplexNested: function(t) {\n        var data = {\n          x: [\n            [1, { attr1: 2 } ],\n            3,\n            { attr1: 4 },\n            { attr1: 5, attr2: [ 6 ] },\n            [ 7, [8, 9] ],\n            { attr1: { attr2: [ [ 10 ] ] } }\n          ]\n        }\n        var result = $.param(data)\n        result = decodeURIComponent(result)\n        t.assertEqual(\n          [ \"x[0][]=1\"\n          , \"x[0][1][attr1]=2\"\n          , \"x[]=3\"\n          , \"x[2][attr1]=4\"\n          , \"x[3][attr1]=5\"\n          , \"x[3][attr2][]=6\"\n          , \"x[4][]=7\"\n          , \"x[4][1][]=8\"\n          , \"x[4][1][]=9\"\n          , \"x[5][attr1][attr2][0][]=10\"\n          ].join('&'), result)\n      },\n\n      testParamShallow: function(t) {\n        var data = {\n          libs: ['jQuery', 'Prototype', 'Dojo'],\n          nested: { will: 'be ignored' }\n        }\n        var result = $.param(data, true)\n        result = decodeURIComponent(result)\n        t.assertEqual(\"libs=jQuery&libs=Prototype&libs=Dojo&nested=[object+Object]\", result)\n      },\n\n      testParamArray: function(t) {\n        var data = [\n          {name:'country', value:'Ecuador'},\n          {name:'capital', value:'Quito'}\n        ]\n        var result = $.param(data)\n        t.assertEqual(result, \"country=Ecuador&capital=Quito\")\n      }\n\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/ajax_deferred.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Ajax deferred</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto event ajax ie callbacks deferred')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto Ajax deferred</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n  <div id=\"fixtures\">\n  </div>\n\n  <script>\n  (function(){\n\n    function toArray(list) {\n      if ($.type(list) == \"string\") return list.split(/(?:\\s*,\\s*|\\s+)/)\n      else return list\n    }\n\n    Evidence.Assertions.assertEqualList = function(expected, actual, message) {\n      var expectedList = toArray(expected),\n          actualList   = toArray(actual)\n\n      this._assertExpression(\n        expectedList.join(' ') == actualList.join(' '),\n        message || \"Lists don't match.\",\n        'Expected %o, got %o.', expectedList, actualList\n      )\n    }\n\n    var OriginalXHR = $.ajaxSettings.xhr\n\n    function MockXHR() {\n      this.requestHeaders = {}\n      this.responseHeaders = {}\n      MockXHR.last = this\n    }\n    MockXHR.prototype = {\n      open: function(method, url) {\n        this.method = method\n        this.url = url\n      },\n      setRequestHeader: function(name, value) {\n        this.requestHeaders[name.toLowerCase()] = value\n      },\n      getResponseHeader: function(name) {\n        return this.responseHeaders[name]\n      },\n      send: function(data) {\n        this.data = data\n      },\n      abort: function() {\n        this.aborted = true\n      },\n      ready: function(readyState, status, responseText, headers) {\n        this.readyState = readyState\n        this.status = status\n        this.responseText = responseText\n        $.extend(this.responseHeaders, headers)\n        this.onreadystatechange()\n      },\n      onreadystatechange: function() {}\n    }\n\n    Evidence('ZeptoAjaxDeferred', {\n      setUp: function() {\n        $.ajaxSettings.xhr = function(){ return new MockXHR }\n      },\n\n      tearDown: function() {\n        $.ajaxSettings.xhr = OriginalXHR\n        $(document).off()\n        $.active = 0\n\n        for (var key in window)\n          if (/^Zepto\\d+$/.test(key) && window[key] === undefined)\n            delete window[key]\n      },\n\n      testDone: function(t) {\n        var log = []\n\n        var xhr = $.ajax({\n          success: function() { log.push('success') }\n        })\n          .done(function(response, status, gotXhr){\n            t.assertEqual('hello', response)\n            t.assertEqual('success', status)\n            t.assertIdentical(xhr, gotXhr)\n            log.push('done1')\n          })\n          .fail(function(){ log.push('fail') })\n          .always(function(){ log.push('always') })\n          .done(function(){ log.push('done2') })\n\n        xhr.ready(3, 0)\n        t.assertEqual(0, log.length)\n\n        xhr.ready(4, 200, 'hello')\n        t.assertEqualList('success done1 always done2', log)\n\n        xhr.done(function(){ log.push('done3') })\n        t.assertEqualList('success done1 always done2 done3', log)\n      },\n\n      testFail: function(t) {\n        var log = []\n\n        var xhr = $.ajax({\n          error: function() { log.push('error') }\n        })\n          .done(function(){ log.push('done') })\n          .fail(function(gotXhr, status, error){\n            t.assertIdentical(xhr, gotXhr)\n            t.assertEqual('error', status)\n            log.push('fail1')\n          })\n          .always(function(){ log.push('always') })\n          .fail(function(){ log.push('fail2') })\n\n        xhr.ready(3, 0)\n        t.assertEqual(0, log.length)\n\n        xhr.ready(4, 404)\n        t.assertEqualList('error fail1 always fail2', log)\n\n        xhr.fail(function(){ log.push('fail3') })\n        t.assertEqualList('error fail1 always fail2 fail3', log)\n      },\n\n      testAbortInBeforeSend: function(t) {\n        var log = []\n\n        var xhr = $.ajax({\n          beforeSend: function() { return false }\n        })\n\n        xhr.done(function(){ log.push('done') })\n          .fail(function(gotXhr, status, error){\n            t.assertIdentical(xhr, gotXhr)\n            t.assertEqual('abort', status)\n            log.push('fail1')\n          })\n\n        t.assertEqualList('fail1', log)\n      },\n\n      testJSONP: function(t) {\n        var log = []\n        t.pause()\n\n        var xhr = $.ajax({\n          url: 'jsonp',\n          dataType: 'jsonp',\n          success: function() { log.push('success') }\n        })\n          .done(function(){ log.push('done1') })\n          .always(function(){\n            setTimeout(function(){\n              t.resume(function(){\n                t.assertEqualList('success done1', log)\n                xhr.done(function(){ log.push('done2') })\n                t.assertEqualList('success done1 done2', log)\n              })\n            }, 10)\n          })\n\n        t.assertEqual(0, log.length)\n      },\n\n      testJSONPAbortInBeforeSend: function(t) {\n        var log = []\n\n        var xhr = $.ajax({\n          url: 'jsonp',\n          dataType: 'jsonp',\n          beforeSend: function() { return false }\n        })\n\n        xhr.done(function(){ log.push('done') })\n          .fail(function(gotXhr, status, error){\n            t.assertIdentical(xhr, gotXhr)\n            t.assertEqual('abort', status)\n            log.push('fail1')\n          })\n\n        t.assertEqualList('fail1', log)\n      }\n\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/callbacks.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Callbacks unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto callbacks')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto Callbacks unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n\n  <script>\n  (function(){\n    var output = \"\", cb\n    function a() { output += \"A\" }\n    function b() { output += \"B\" }\n    function c() { output += \"C\" }\n    function str(str) { output += str }\n\n    Evidence('ZeptoCallbacksTest', {\n\n      testOptionsAreCopied: function(t) {\n        var options = {\"unique\": true},\n            cb = $.Callbacks(options),\n            count = 0,\n            fn = function() {\n              t.assertTrue(!(count++), \"called once\")\n            }\n        options[\"unique\"] = false\n        cb.add(fn, fn)\n        cb.fire()\n      },\n\n      testFireWithOptionsAreCopied: function(t) {\n        var cb = $.Callbacks({memory:1}),\n            args = [\"hello\"]\n\n        cb.fireWith(null, args)\n        args[0] = \"world\"\n\n        cb.add(function(hello) {\n          t.assertEqual(\"hello\", hello, \"arguments are copied internally\")\n        })\n      },\n\n      testRemoveDeletesAllInstances: function(t) {\n        var cb = $.Callbacks()\n        function fn() {\n          t.fail(\"function wasn't removed\")\n        }\n        cb.add( fn, fn, function() {\n          t.assertTrue(true, \"end of test\")\n        }).remove(fn).fire()\n      },\n\n      testCallbacksHas: function(t) {\n        var cb = $.Callbacks()\n        cb.add(a, b, c)\n        t.assertTrue(cb.has(), \"No arguments to .has() returns whether callback function(s) are attached or not\")\n        t.assertTrue(cb.has(a), \"Check if a specific callback function is in the Callbacks list\" )\n\n        cb.remove(b)\n        t.assertFalse(cb.has(b), \"Remove a specific callback function and make sure its no longer there\" )\n        t.assertTrue(cb.has(a), \"Remove a specific callback function and make sure other callback function is still there\" )\n\n        cb.empty()\n        t.assertFalse(cb.has(), \"Empty list and make sure there are no callback function(s)\" )\n        t.assertFalse(cb.has(a), \"Check for a specific function in an empty() list\" )\n\n        cb.add(a, b, function(){\n          t.assertTrue(cb.has(), \"Check if list has callback function(s) from within a callback function\" )\n          t.assertTrue(cb.has(a), \"Check if list has a specific callback from within a callback function\" )\n        }).fire()\n\n        t.assertTrue(cb.has(), \"Callbacks list has callback function(s) after firing\" )\n\n        cb.disable()\n        t.assertFalse(cb.has(), \"disabled() list has no callback functions (returns false)\" )\n        t.assertFalse(cb.has(a), \"Check for a specific function in a disabled() list\" )\n\n        cb = $.Callbacks({unique:1})\n        cb.add(a)\n        cb.add(a)\n        t.assertTrue(cb.has(), \"Check if unique list has callback function(s) attached\" )\n        cb.lock()\n        t.assertFalse(cb.has(), \"locked() list is empty and returns false\" )\n      },\n\n      testAddStringNoCrash: function(t) {\n        $.Callbacks().add(\"hello world\")\n        t.assertTrue(true, \"no crash adding string\" )\n      },\n\n      testUniqueAddIdenticalFn: function(t) {\n        output = \"X\"\n        $.Callbacks({unique:1}).add(a, function() { output += \"A\" }).fire()\n        t.assertEqual(\"XAA\", output, \"Unique can add different, identical definitions of same function\")\n      },\n\n      testUniqueAddSameFn: function(t) {\n        output = \"X\"\n        $.Callbacks({unique:1}).add(a, a).fire()\n        t.assertEqual(\"XA\", output, \"Unique can not add multiple functions with the same reference\")\n      },\n\n      testUniqueAddSameFnMultiRef: function(t) {\n        var x = a\n        output = \"X\"\n        $.Callbacks({unique:1}).add(a, x).fire()\n        t.assertEqual(\"XA\", output, \"Unique can not add multiple references to the same function\")\n      }\n\n    })\n\n    var configs = {\n      'Undefined': undefined,\n      'Null': null,\n      'Once': {once:1},\n      'Memory': {memory:1},\n      'Unique': {unique:1},\n      'StopOnFalse': {stopOnFalse:1},\n      'OnceMemory': {once:1, memory:1},\n      'OnceUnique': {once:1, unique:1},\n      'OnceStopOnFalse': {once:1, stopOnFalse:1},\n      'MemoryUnique': {memory:1, unique:1},\n      'MemoryStopOnFalse': {memory:1, stopOnFalse:1},\n      'UniqueStopOnFalse': {unique:1, stopOnFalse:1}\n    }\n    var ordering = {\n      \"Undefined\":         \"XABC   X     XABCABCC  X  XBB X   XABA  X   XX\",\n      \"Null\":              \"XABC   X     XABCABCC  X  XBB X   XABA  X   XX\",\n      \"Once\":              \"XABC   X     X         X  X   X   XABA  X   XX\",\n      \"Memory\":            \"XABC   XABC  XABCABCCC XA XBB XB  XABA  XC  XX\",\n      \"Unique\":            \"XABC   X     XABCA     X  XB  X   XAB   X   X\",\n      \"StopOnFalse\":       \"XABC   X     XABCABCC  X  XBB X   XA    X   XX\",\n      \"OnceMemory\":        \"XABC   XABC  X         XA X   XA  XABA  XC  XX\",\n      \"OnceUnique\":        \"XABC   X     X         X  X   X   XAB   X   X\",\n      \"OnceStopOnFalse\":   \"XABC   X     X         X  X   X   XA    X   XX\",\n      \"MemoryUnique\":      \"XABC   XA    XABCA     X  XB  X   XAB   XC  X\",\n      \"MemoryStopOnFalse\": \"XABC   XABC  XABCABCCC XA XBB XB  XA    X   XX\",\n      \"UniqueStopOnFalse\": \"XABC   X     XABCA     X  XB  X   XA    X   X\"\n    }\n\n    $.each(configs, function(name, config) {\n      var results = ordering[name].split(/\\s+/)\n\n      Evidence(\"ZeptoCallbacksTest#\" + name, {\n\n        testBindAndFire: function(t) {\n          output = \"X\", cb = $.Callbacks(config).add(str).fire(\"A\")\n          t.assertEqual(\"XA\", output, \"Basic binding and firing\")\n          t.assertTrue(cb.fired(), \".fired() detects firing\")\n          output = \"X\"\n          cb.disable().add(str)\n          t.assertEqual( \"X\", output, \"Adding a callback after disabling\" )\n          cb.fire(\"A\")\n          t.assertEqual( \"X\", output, \"Firing after disabling\" )\n        },\n\n        testNoEmptyWhileFiring: function(t) {\n          var cb = $.Callbacks(config)\n          cb.add(cb.empty, function() { t.fail(\"not emptied\") }).fire()\n        },\n\n        testNoDisablingWhileFiring: function(t) {\n          var cb = $.Callbacks(config)\n          cb.add(cb.disable, function() { t.fail(\"not disabled\") }).fire()\n        },\n\n        testBindFireWithContextAndArgs: function(t) {\n          output = \"X\"\n          $.Callbacks(config).add(function() {\n            t.assertEqual(window, this, \"Basic binding and firing (context)\" )\n            output += Array.prototype.join.call(arguments, \"\")\n          }).fireWith(window, [ \"A\", \"B\" ])\n          t.assertEqual( \"XAB\", output, \"Basic binding and firing (arguments)\" )\n        },\n\n        testFireWithNoArgs: function(t) {\n          $.Callbacks(config).add(function() {\n            t.assertEqual(window, this, \"fireWith with no arguments (context is window)\")\n            t.assertEqual(0, arguments.length, \"fireWith with no arguments (no arguments)\")\n          }).fireWith()\n        },\n\n        testBindRemoveFire: function(t) {\n          output = \"X\"\n          $.Callbacks(config).add(a, b, c).remove(b, c).fire()\n          t.assertEqual(\"XA\", output)\n        },\n\n        testEmpty: function(t) {\n          output = \"X\"\n          $.Callbacks(config).add(a, b, c).empty().fire()\n          t.assertEqual( \"X\", output, \"Empty\" )\n        },\n\n        testLocking: function(t) {\n          output = \"X\"\n          $.Callbacks(config).add(str).lock().add(str).fire(\"A\").add(str)\n          t.assertEqual(\"X\", output, \"Lock early\")\n        },\n\n        testOrdering: function(t) {\n          output = \"X\", cb = $.Callbacks(config)\n          cb.add(function() {\n            cb.add(c)\n            a()\n          }, b).fire()\n          t.assertEqual( results.shift(), output, \"Proper ordering\" )\n\n          output = \"X\"\n          cb.add(function() {\n            cb.add(c)\n            a()\n          }, b)\n          t.assertEqual(results.shift(), output, \"Add after fire\")\n          output = \"X\"\n          cb.fire()\n          t.assertEqual(results.shift(), output, \"Fire again\")\n\n          output = \"X\", cb = $.Callbacks(config)\n          cb.add(str).fire(\"A\")\n          t.assertEqual(\"XA\", output, \"Multiple fire (first fire)\")\n          output = \"X\"\n          cb.add(str)\n          t.assertEqual(results.shift(), output, \"Multiple fire (first new callback)\")\n          output = \"X\"\n          cb.fire(\"B\")\n          t.assertEqual(results.shift(), output, \"Multiple fire (second fire)\")\n          output = \"X\"\n          cb.add(str)\n          t.assertEqual(results.shift(), output, \"Multiple fire (second new callback)\")\n\n          output = \"X\", cb = $.Callbacks(config).add(a, function() { return false }, b).add(a).fire()\n          t.assertEqual(results.shift(), output, \"Callback returning false\")\n\n          output = \"X\"\n          cb.add(c)\n          t.assertEqual(results.shift(), output, \"Adding a callback after one returned false\")\n\n          output = \"\"\n          function handler() { output += \"X\" }\n          handler.method = function() { output += \"!\" }\n          cb = $.Callbacks(config).add(handler).add(handler).fire()\n          t.assertEqual(results.shift(), output, \"No callback iteration\")\n        }\n\n      })\n\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/data.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Data unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto data ie')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto Data unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n  <div id=\"fixtures\">\n  <div id=\"data_attr\"\n    data-one=\"uno\"\n    data-two=\"due\"\n    data-foo-bar=\"baz\"\n    data-under_score=\"kuuq\"\n    ></div>\n  <div id=\"data_full\" data-mode=\"awesome\"></div>\n  <div id=\"data_obj\" data-mode=\"awesome\"></div>\n  <ol id=\"data_list\">\n    <li data-category=\"arts\"></li>\n    <li data-category=\"science\"></li>\n  </ol>\n  <ol id=\"data_list2\">\n    <li></li>\n    <li></li>\n  </ol>\n  </div>\n\n  <script>\n    Evidence('ZeptoExtendedDataTest', {\n      testEmptyCollection: function(t){\n        var el = $('#does_not_exist')\n        t.assertUndefined(el.data('one'))\n      },\n\n      testAttributeDoesNotExist: function(t){\n        var el = $('#data_attr')\n        t.assertUndefined(el.data('missing'))\n      },\n\n      testReadingAttribute: function(t){\n        var el = $('#data_attr')\n        t.assertEqual('uno', el.data('one'))\n      },\n\n      testCamelized: function(t){\n        var el = $('#data_attr')\n        t.assertEqual('baz', el.data('foo-bar'))\n        t.assertEqual('baz', el.data('fooBar'))\n\n        el.data('fooBar', 'bam')\n        t.assertEqual('bam', el.data('foo-bar'))\n        t.assertEqual('bam', el.data('fooBar'))\n\n        el.data('a-b', 'c')\n        t.assertEqual('c', el.data().aB)\n        t.assertUndefined(el.data()['a-b'])\n      },\n\n      testUnderscore: function(t){\n        var el = $('#data_attr')\n        t.assertEqual('kuuq', el.data('under_score'))\n        t.assertUndefined(el.data('under-score'))\n        t.assertUndefined(el.data('underScore'))\n      },\n\n      testNotChangingAttribute: function(t){\n        var el = $('#data_attr')\n        t.assertEqual('due', el.data('two'))\n        el.data('two', 'changed')\n        t.assertEqual('due', el.attr('data-two'))\n      },\n\n      testExtendedData: function(t){\n        var els = $('#data_attr'),\n          els2 = $('#data_attr'),\n          obj  = { a: 'A', b: 'B' }\n\n        els.data('obj', obj)\n        t.assertIdentical(obj, els.data('obj'))\n        t.assertIdentical(obj, els2.data('obj'))\n\n        els2.data('els', els)\n        t.assertIdentical(els, els.data('els'))\n      },\n\n      testMultipleElements: function(t){\n        var items = $('#data_list li')\n\n        items.data('each', 'mark')\n\n        var values = items.map(function(){ return $(this).data('each') }).get()\n        t.assertEqual('mark, mark', values.join(', '))\n      },\n\n      testFunctionArg: function(t){\n        var els = $('#data_attr')\n\n        var data = \"hello\"\n\n        els.data(\"addio\", function () {\n          data = \"goodbye\"\n        })\n\n        t.assertEqual('hello', data)\n\n        els.data(\"addio\")()\n\n        t.assertEqual('goodbye', data)\n      },\n\n      testAllData: function(t){\n        var el = $('#data_full')\n\n        el.data().samurai = 7\n        el.data('one', 'ichi').data('two', 'ni')\n        el.data('person', {name: 'Kurosawa'})\n\n        var all = el.data()\n        t.assertEqual(7, all.samurai)\n        t.assertEqual('ichi', all.one)\n        t.assertEqual('ni', all.two)\n        t.assertEqual('Kurosawa', all.person.name)\n      },\n\n      testInitialDataFromAttributes: function(t){\n        var el = $('<div data-foo=bar data-foo-bar=baz data-empty data-num=42 />'),\n            store = el.data()\n\n        t.assertEqual('bar', store.foo)\n        t.assertEqual('baz', store.fooBar)\n        t.assertUndefined(store['foo-bar'])\n        t.assertIdentical('', store.empty)\n        t.assertIdentical(42, store.num)\n      },\n\n      testGettingBlanks: function(t){\n        var el = $('#data_attr'),\n            store = el.data()\n\n        store.nil = null\n        store.undef = undefined\n        store.blank = ''\n        store.bool = false\n\n        t.assertNull(el.data('nil'))\n        t.assertUndefined(el.data('undef'))\n        t.assertIdentical('', el.data('blank'))\n        t.assertFalse(el.data('bool'))\n      },\n\n      testRemoveData: function(t){\n        var el = $('<div data-foo=bar />')\n\n        el.data('foo', 'bam').data('bar', 'baz')\n        el.removeData('foo').removeData('bar')\n        t.assertEqual('bar', el.data('foo'))\n        t.assertUndefined(el.data('bar'))\n\n        el.data('uno', 'one').data('due', 'two')\n        el.removeData('uno due')\n        t.assertUndefined(el.data('uno'))\n        t.assertUndefined(el.data('due'))\n\n        el.data('one', 1).data('twoThree', 23)\n        el.removeData(['one', 'two-three'])\n        t.assertUndefined(el.data('one'))\n        t.assertUndefined(el.data('twoThree'))\n      },\n\n      testRemoveAllData: function(t){\n        var el = $('<div data-attr-test=val />')\n\n        el.data('one', { foo: 'bar' })\n        el.data('two', 'two').data('three', 3)\n        el.removeData()\n\n        t.assertEqual('val', el.data('attrTest'))\n        t.assertUndefined(el.data('one'))\n        t.assertUndefined(el.data('two'))\n        t.assertUndefined(el.data('three'))\n      },\n\n      testRemoveDataNoop: function(t){\n        var empty = $(),\n            vanilla = $('<div />')\n\n        t.assertIdentical(empty, empty.removeData('foo'))\n        t.assertIdentical(vanilla, vanilla.removeData('foo'))\n      },\n\n      testRemoveDataOnElementRemoval: function(t){\n        var el = $('<div data-attr-test=val />'),\n          childEl = $('<span />').appendTo(el),\n          elData = { foo: 'bar' }\n\n        el.data('test', elData)\n        childEl.data('test', 1)\n\n        el.remove()\n        t.assertEqual('val', el.data('attrTest'))\n        t.assertUndefined(el.data('test'))\n        t.assertUndefined(childEl.data('test'))\n      },\n\n      testRemoveDataOnElementEmpty: function(t){\n        var el = $('<div data-attr-test=val />'),\n          childEl = $('<span />').appendTo(el),\n          elData = { foo: 'bar' }\n\n        el.data('test', elData)\n        childEl.data('test', 1)\n\n        el.empty()\n        t.assertEqual('val', el.data('attrTest'))\n        t.assertEqual(elData, el.data('test'))\n        t.assertUndefined(childEl.data('test'))\n      },\n\n      testRemoveDataOnElementReplacement: function(t){\n        var el = $('<div data-attr-test=val />'),\n          childEl = $('<span />').appendTo(el),\n          elData = { foo: 'bar' }\n\n        el.data('test', elData)\n        childEl.data('test', 1)\n\n        el.replaceWith('<div />')\n        t.assertEqual('val', el.data('attrTest'))\n        t.assertUndefined(el.data('test'))\n        t.assertUndefined(childEl.data('test'))\n      },\n\n      testRemoveDataOnElementReplacementHtml: function(t){\n        var el = $('<div data-attr-test=val />'),\n          childEl = $('<span />').appendTo(el),\n          wrapper = $('<div />'),\n          elData = { foo: 'bar' }\n\n        el.wrap(wrapper).data('test', elData)\n        childEl.data('test', 1)\n\n        wrapper.html('<b>New content</b>')\n        t.assertEqual('val', el.data('attrTest'))\n        t.assertUndefined(el.data('test'))\n        t.assertUndefined(childEl.data('test'))\n      },\n\n      testKeepDataOnElementDetach: function(t){\n        var el = $('<div data-attr-test=val />'),\n          childEl = $('<span />').appendTo(el),\n          elData = { foo: 'bar' }\n\n        el.data('test', elData)\n        childEl.data('test', 1)\n\n        el.detach()\n        t.assertEqual('val', el.data('attrTest'))\n        t.assertEqual(elData, el.data('test'))\n        t.assertEqual(1, childEl.data('test'))\n      },\n\n      testSettingDataWithObj: function(t){\n          var el = $('#data_obj')\n\n          el.data({\n              'foo': 'bar',\n              'answer': 42,\n              'color': 'blue'\n          })\n\n          var all = el.data()\n\n          t.assertEqual(all.answer, 42)\n          t.assertEqual(all.color, 'blue')\n          t.assertEqual(all.foo, 'bar')\n\n          el.data('foo', 'baz')\n\n          t.assertEqual(all.foo, 'baz')\n          t.assertEqual(all.answer, 42)\n      },\n\n      testSettingDataWithObjOnManyElements: function(t){\n          var items = $('#data_list2 li')\n\n          items.data({\n              'foo': 'bar',\n              'answer': 42,\n              'color': 'purple'\n          })\n\n          var values = items.map(function(){ return $(this).data('foo') }).get()\n          t.assertEqual('bar, bar', values.join(', '))\n\n          var values2 = items.map(function(){ return $(this).data('answer') }).get()\n          t.assertEqual('42, 42', values2.join(', '))\n      },\n\n      testSettingDataOnObjectWithoutAttributes: function(t) {\n        var el = $(window)\n\n        t.assertUndefined(el.data('foo'))\n        el.data('foo', 'bar')\n        t.assertEqual(el.data('foo'), 'bar')\n\n        delete window[$.expando]\n      },\n\n      testDollarData: function(t) {\n        var el = $('<div>')\n        el.data('hello', 'world')\n        t.assertEqual($.data(el, 'hello'), 'world')\n        t.assertEqual($.data(el[0], 'hello'), 'world')\n\n        $.data(el[0], 'hello', 'again')\n        t.assertEqual($.data(el, 'hello'), 'again')\n        t.assertEqual($.data(el[0], 'hello'), 'again')\n      },\n\n      testDollarHasData: function(t) {\n        var el = $('<div>')\n        t.assertFalse($.hasData(el[0]))\n\n        el.data('hello', 'world')\n        t.assertTrue($.hasData(el[0]))\n\n        el.removeData()\n        t.assertFalse($.hasData(el[0]))\n\n        var error\n        try {\n          $.hasData()\n        } catch (e) {\n          error = e\n        }\n        t.assert(error)\n      }\n\n    })\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/deferred.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Deferred unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto callbacks deferred')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto Deferred unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n\n  <script>\n  (function(){\n    var promiseFns = \"resolve reject notify resolveWith rejectWith notifyWith done fail progress always\".split(/\\s+/),\n        deferredFns = \"state always then promise done fail progress\".split(/\\s+/)\n\n    $.each(['', 'WithNew'], function(_, withNew) {\n      var createDeferred = function(fn) {\n        return withNew ? new $.Deferred(fn) : $.Deferred(fn)\n      }\n\n      Evidence('ZeptoDeferredTest' + withNew, {\n\n        testSuccessOnResolve: function(t) {\n          var called = 0\n          createDeferred().resolve().done(function() {\n            t.assertEqual(0, called++)\n            t.assertEqual(\"resolved\", this.state(), \"Deferred is resolved (state)\")\n          }).fail(function() {\n            t.fail(\"Error on resolve\")\n          }).always(function() {\n            t.assertEqual(1, called++)\n          })\n          t.assertEqual(2, called, \"Success and Always handlers called\")\n        },\n\n        testErrorOnReject: function(t) {\n          var called = 0\n          createDeferred().reject().done(function() {\n            t.fail(\"Success on reject\")\n          }).fail(function() {\n            t.assertEqual(0, called++)\n            t.assertEqual( \"rejected\", this.state(), \"Deferred is rejected (state)\" )\n          }).always(function() {\n            t.assertEqual(1, called++)\n          })\n          t.assertEqual(2, called, \"Error and Always handlers called\")\n        },\n\n        testDeferredFnContextIsArg1: function(t) {\n          var called\n          createDeferred(function(defer) {\n            called = true\n            t.assertEqual(defer, this, \"Defer passed as this & first argument\")\n          })\n          t.assertTrue(called, \"Deferred function was called\")\n        },\n\n        testDoneWithResolvedValue: function(t) {\n          var called\n          createDeferred(function(defer) {\n            defer.resolve(\"done\")\n          }).done(function(value) {\n            called = true\n            t.assertEqual(\"done\", value, \"Done() received resolved value\")\n          })\n          t.assertTrue(called, \"Deferred function was called\")\n        },\n\n        testNoDoneOnReject: function(t) {\n          var called = false\n          createDeferred(function(defer) {\n            defer.reject(\"done\")\n          }).done(function(value) {\n            called = true\n            t.fail(\"done() should not be called on error\")\n          })\n          t.assertFalse(called, \"Deferred function was called\")\n        },\n\n        testIsChainable: function(t) {\n          var deferred = createDeferred(), each = $.each\n          // Ensure that each of the following methods are chainable\n          each(promiseFns, function(_, method) {\n            var object = {\n              m: deferred[method]\n            }\n            t.assertEqual(object, object.m(), method + \" is chainable\" )\n          })\n        },\n\n        testFilteringDone: function(t) {\n          var value1, value2, value3,\n              defer = createDeferred(),\n              piped = defer.then(function(a, b) {\n                return a * b\n              })\n          piped.done(function(result) { value3 = result })\n          defer.done(function(a, b) { value1 = a, value2 = b }).resolve(2, 3)\n\n          t.assertEqual(2, value1, \"first resolve value ok\")\n          t.assertEqual(3, value2, \"second resolve value ok\")\n          t.assertEqual(6, value3, \"result of filter ok\")\n\n          createDeferred().reject().then(function() { t.fail(\"then should not be called on reject\") })\n          createDeferred().resolve().then($.noop).done(function(value) {\n            t.assertEqual(undefined, value, \"then done callback can return undefined/null\")\n          })\n        },\n\n        testSamePromise: function(t) {\n          createDeferred(function(defer) {\n            var promise = defer.promise()\n            t.assertEqual(promise, defer.promise(), \"promise is always the same\")\n          })\n        },\n\n        testExtendNonObject: function(t) {\n          createDeferred(function(defer) {\n            var func = function() {},\n                funcPromise = defer.promise(func)\n            t.assertEqual(func, funcPromise, \"non objects get extended\")\n          })\n        },\n\n        testPromiseOnlyFns: function(t) {\n          createDeferred(function(defer) {\n            var promise = defer.promise()\n            $.each(promise, function(key) {\n              var type = typeof promise[key]\n              t.assertEqual(\"function\", type, key + \" is a function (\" + type + \")\")\n              t.assertTrue(deferredFns.indexOf(key) > -1, key + \"() is a promise function\")\n            })\n          })\n        },\n\n        testExtendObjectWithPromiseFns: function(t) {\n          createDeferred(function(defer) {\n            var promise = defer.promise(),\n                func = function() {},\n                funcPromise = defer.promise(func),\n                fns = 0\n            $.each(promise, function(key) {\n              ++fns\n              t.assertEqual(promise[key], func[key], key + \" is the same\")\n            })\n            t.assertEqual(deferredFns.length, fns, \"should have all of the Deferred functions\")\n          })\n        },\n\n        testFilteringReject: function(t) {\n          var value1, value2, value3,\n              defer = createDeferred(),\n              piped = defer.then(null, function(a, b) {\n                return a * b\n              })\n\n          piped.fail(function(result) { value3 = result })\n          defer.fail(function( a, b ) { value1 = a, value2 = b })\n          defer.reject( 2, 3 )\n\n          t.assertEqual(2, value1, \"first reject value ok\")\n          t.assertEqual(3, value2, \"second reject value ok\")\n          t.assertEqual(6, value3, \"result of filter ok\")\n\n          createDeferred().resolve().then(null, function() {\n            t.fail(\"then should not be called on resolve\")\n          })\n\n          createDeferred().reject().then(null, $.noop).fail(function(value) {\n            t.assertEqual(undefined, value, \"then fail callback can return undefined/null\")\n          })\n        },\n\n        testFilteringProgress: function(t) {\n          var value1, value2, value3,\n              defer = createDeferred(),\n              piped = defer.then(null, null, function(a, b) {\n                return a * b\n              })\n\n          piped.progress(function(result) { value3 = result })\n          defer.progress(function(a, b) { value1 = a, value2 = b })\n\n          defer.notify( 2, 3 )\n\n          t.assertEqual(2, value1, \"first progress value ok\")\n          t.assertEqual(3, value2, \"second progress value ok\")\n          t.assertEqual(6, value3, \"result of filter ok\")\n        },\n\n        testThenDeferredDone: function(t) {\n          var value1, value2, value3,\n              defer = createDeferred(),\n              piped = defer.then(function(a, b) {\n                return createDeferred(function(defer) {\n                  defer.reject(a * b)\n                })\n              })\n\n          piped.fail(function(result) { value3 = result })\n          defer.done(function(a, b) { value1 = a, value2 = b })\n          defer.resolve(2, 3)\n\n          t.assertEqual(2, value1, \"first resolve value ok\")\n          t.assertEqual(3, value2, \"second resolve value ok\")\n          t.assertEqual(6, value3, \"result of filter ok\")\n        },\n\n        testThenDeferredFail: function(t) {\n          var value1, value2, value3,\n              defer = createDeferred(),\n              piped = defer.then(null, function(a, b) {\n                return createDeferred(function(defer) {\n                  defer.resolve(a * b)\n                })\n              })\n\n          piped.done(function(result) { value3 = result })\n          defer.fail(function(a, b) { value1 = a, value2 = b })\n          defer.reject(2, 3)\n\n          t.assertEqual(2, value1, \"first reject value ok\")\n          t.assertEqual(3, value2, \"second reject value ok\")\n          t.assertEqual(6, value3, \"result of filter ok\")\n        },\n\n        testThenDeferredProgress: function(t) {\n          var value1, value2, value3,\n            defer = createDeferred(),\n            piped = defer.then(null, null, function(a, b) {\n              return createDeferred(function(defer) {\n                defer.resolve( a * b )\n              })\n            })\n\n          piped.done(function(result) { value3 = result })\n          defer.progress(function(a, b) { value1 = a, value2 = b })\n          defer.notify(2, 3)\n\n          t.assertEqual(2, value1, \"first progress value ok\")\n          t.assertEqual(3, value2, \"second progress value ok\")\n          t.assertEqual(6, value3, \"result of filter ok\")\n        },\n\n        testThenWithContext: function(t) {\n          var defer, piped, defer2, piped2, context = {}\n\n          createDeferred().resolveWith(context, [2]).then(function(value) {\n            return value * 3\n          }).done(function(value) {\n            t.assertEqual(context, this, \"custom context correctly propagated\")\n            t.assertEqual(6, value, \"proper value received\")\n          })\n\n          createDeferred().resolve().then(function() {\n            return createDeferred().resolveWith(context)\n          }).done(function() {\n            t.assertEqual(context, this, \"custom context of returned deferred correctly propagated\")\n          })\n\n          defer = createDeferred()\n          piped = defer.then(function(value) {\n            return value * 3\n          })\n          defer.resolve( 2 )\n\n          piped.done(function(value) {\n            t.assertEqual(piped, this, \"default context gets updated to latest promise in the chain\")\n            t.assertEqual(6, value, \"proper value received\")\n          })\n\n          defer2 = createDeferred()\n          piped2 = defer2.then()\n\n          defer2.resolve(2)\n\n          piped2.done(function(value) {\n            t.assertEqual(piped2, this, \"default context gets updated to latest promise in the chain (without passing function)\")\n            t.assertEqual(2, value, \"proper value received (without passing function)\")\n          })\n        },\n\n        testWhenValueCreatesPromise: function(t) {\n          $.each({\n            \"an empty string\": \"\",\n            \"a non-empty string\": \"some string\",\n            \"zero\": 0,\n            \"a number other than zero\": 1,\n            \"true\": true,\n            \"false\": false,\n            \"null\": null,\n            \"undefined\": undefined,\n            \"a plain object\": {},\n            \"an array\": [ 1, 2, 3 ]\n          }, function(message, value) {\n            t.assertTrue(\n              $.isFunction($.when(value).done(function(resolveValue) {\n                t.assertEqual(window, this, \"Context is the global object with \" + message)\n                t.assertEqual(value, resolveValue, \"Test the promise was resolved with \" + message)\n              }).promise), \"Test \" + message + \" triggers the creation of a new Promise\")\n          })\n        },\n\n        testWhenNoValueCreatesPromise: function(t) {\n          t.assertTrue(\n            $.isFunction($.when().done(function(resolveValue) {\n              t.assertEqual(window, this, \"Context is the global object\")\n              t.assertEqual(undefined, resolveValue, \"Test the promise was resolved with no parameter\")\n            }).promise), \"Test calling when with no parameter triggers the creation of a new Promise\")\n        },\n\n        testWhenPropagatesContext: function(t) {\n          var context = {}, called = false\n          $.when(createDeferred().resolveWith(context)).done(function() {\n              called = true\n              t.assertEqual(context, this, \"when( promise ) propagates context\")\n            })\n          t.assertTrue(called, \"called done() after resolveWith\")\n        },\n\n        testWhenDoneOnlyPromise: function(t) {\n          var cache\n          $.each([1,2,3], function(_, i) {\n            $.when(cache || createDeferred(function() {\n              this.resolve(i)\n            })).done(function(value) {\n              t.assertEqual(1, value, \"Function executed\" + (i > 1 ? \" only once\" : \"\"))\n              cache = value\n            })\n          })\n        },\n\n        testWhenJoined: function(t) {\n          var deferreds = {\n                value: 1,\n                success: createDeferred().resolve(1),\n                error: createDeferred().reject(0),\n                futureSuccess: createDeferred().notify(true),\n                futureError: createDeferred().notify(true),\n                notify: createDeferred().notify(true)\n              },\n              willSucceed = {\n                value: true,\n                success: true,\n                futureSuccess: true\n              },\n              willError = {\n                error: true,\n                futureError: true\n              },\n              willNotify = {\n                futureSuccess: true,\n                futureError: true,\n                notify: true\n              }\n\n          $.each(deferreds, function(id1, defer1) {\n            $.each(deferreds, function(id2, defer2) {\n              var shouldResolve = willSucceed[id1] && willSucceed[id2],\n                  shouldError = willError[id1] || willError[id2],\n                  shouldNotify = willNotify[id1] || willNotify[id2],\n                  expected = shouldResolve ? [1, 1] : [0, undefined],\n                  expectedNotify = shouldNotify && [willNotify[id1], willNotify[id2]],\n                  code = id1 + '/' + id2,\n                  context1 = defer1 && $.isFunction(defer1.promise) ? defer1.promise() : undefined,\n                  context2 = defer2 && $.isFunction(defer2.promise) ? defer2.promise() : undefined\n              $.when(defer1, defer2).done(function(a, b) {\n                if (shouldResolve) {\n                  t.assertEqual(expected[0], a, code + \" => resolve\" )\n                  t.assertEqual(expected[1], b, code + \" => resolve\" )\n                  t.assertIdentical(context1, this[0], code + \" => first context OK\")\n                  t.assertIdentical(context2, this[1], code + \" => second context OK\")\n                } else {\n                  t.fail(code + \" => resolve\")\n                }\n              }).fail(function(a, b) {\n                if (shouldError) {\n                  t.assertIdentical(expected[0], a, code + \" => reject\")\n                  t.assertIdentical(expected[1], b, code + \" => reject\")\n                } else {\n                  t.fail(code + \" => reject\")\n                }\n              }).progress(function(a, b) {\n                t.assertIdentical( expectedNotify[0], a, code + \" => progress\")\n                t.assertIdentical( expectedNotify[1], b, code + \" => progress\")\n                t.assertIdentical(expectedNotify[0] ? context1 : undefined, this[0], code + \" => first context OK\")\n                t.assertIdentical(expectedNotify[1] ? context2 : undefined, this[1], code + \" => second context OK\")\n              })\n            })\n          })\n          deferreds.futureSuccess.resolve(1)\n          deferreds.futureError.reject(0)\n        }\n\n      })\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/detect.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Detect unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto detect ie')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto Detect unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n\n  <script>\n  (function(){\n\n    var UA = {\n      Safari_OSX_7_0_1: \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11\",\n      Safari_OSX_7_0: \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.71 (KHTML, like Gecko) Version/7.0 Safari/537.71\",\n      Safari_OSX_6_0: \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25\",\n      Safari_Windows_NT: \"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27\",\n\n      WebOS_1_4_0_Pre: \"Mozilla/5.0 (webOS/1.4.0; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.1\",\n      WebOS_1_4_0_Pixi: \"Mozilla/5.0 (webOS/1.4.0; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pixi/1.1\",\n      WebOS_1_2_9_Pixi: \"Mozilla/5.0 (webOS/Palm webOS 1.2.9; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pixi/1.0\",\n      WebOS_3_0_0_TouchPad: \"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0\",\n\n      iOS_3_0_iPhone: \"Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/1A542a Safari/419.3\",\n      iOS_4_0_iPhone: \"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7\",\n      iOS_3_1_1_iPod: \"Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1_1 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Mobile/7C145\",\n      iOS_3_2_iPad: \"Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10\",\n      iOS_4_2_iPad: \"Mozilla/5.0 (iPad; U; CPU OS 4_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C134 Safari/6533.18.5\",\n      iOS_4_3_iPhone_Simulator: \"Mozilla/5.0 (iPhone Simulator; U; CPU iPhone OS 4_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F190 Safari/6533.18.5\",\n      iOS_5_0_iPhone: \"Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3\",\n      iOS_5_1_iPad_webView: \"Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/98176\",\n      iOS_6_0_iPad_mini: \"Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A406 Safari/8536.25\",\n      iOS_6_1_iPhone: \"Mozilla/5.0 (iPhone; CPU iPhone OS 6_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B143 Safari/8536.25\",\n\n      iOS_3_2_iPad_2: \"Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10\",\n\n      iOS_7_0_iPhone: \"Mozilla 5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KTHML, like Gecko) Version/7.0 Mobile/11A449d Safari/9537.53\",\n      iOS_7_0_iPhone_Chrome: \"Mozilla 5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/536.26 (KHTM, like Gecko) CriOS/28.0.1500.17 Mobile/11A4449d Safari/8536.25\",\n\n      Android_1_5: \"Mozilla/5.0 (Linux; U; Android 1.5; de-; HTC Magic Build/PLAT-RC33) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1\",\n      Android_2_1: \"Mozilla/5.0 (Linux; U; Android 2.1-update1; en-us; Nexus One Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17 Chrome/4.1.249.1025\",\n      Android_2_3: \"Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/GRK39F) AppleWebKit/533.1 (KTHML, like Gecko) Version/4.0 Mobile Safari/533.1\",\n      Android_2_3_Lenovo_A750: \"Lenovo-A750/S102 Linux/2.6.35.7 Android/2.3 Release/12.12.2011 Browser AppleWebkit533.1 Profile/ Configuration/\",\n      Android_4_1_1: \"Mozilla/5.0 (Linux; Android 4.1.1; Galaxy Nexus Build/JRO03O) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19\",\n      Android_4_1_1_Tablet: \"Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03S) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19\",\n      Android_4_3: \"Mozilla/5.0 (Linux; Android 4.3; Nexus 4 Build/JWR66Y) AppleWebKit/537.36 (KTHML, like Gecko) Chrome/29.0.1547.59 Mobile Safari/537.36\",\n\n      BlackBerry_6_0_0_141: \"Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en-GB) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.141 Mobile Safari/534.1+\",\n      PlayBook_1_0_0: \"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.8+ (KHTML, like Gecko) Version/0.0.1 Safari/534.8+\",\n      PlayBook_2_1_0: \"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+\",\n      BB10: \"Mozilla/5.0 (BB10; Touch) AppleWebKit/537.1+ (KHTML, like Gecko) Version/10.0.0.1337 Mobile Safari/537.1+\",\n\n      Opera_11_51: \"Opera/9.80 (Macintosh; Intel Mac OS X 10.7.1; U; en) Presto/2.9.168 Version/11.51\",\n      Opera_Mobile_Simulator: \"Opera/9.80 (Macintosh; Intel Mac OS X; Opera Mobi/[BUILD_NR]; U; en) Presto/2.7.81 Version/11.00\",\n\n      Kindle: \"Mozilla/5.0 (Linux; U; en-US) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) Version/4.0 Kindle/3.0 (screen 600×800; rotate)\",\n      Silk_1_0_accel: \"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.0.13.328_10008910) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true\",\n      Silk_1_0: \"Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Kindle Fire Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\",\n\n      Chrome_Android_18_0: \"Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19\",\n      Chrome_iOS_19_0: \"Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3\",\n      Chrome_OSX_24_0: \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17\",\n\n      Firefox_13_Tablet: \"Mozilla/5.0 (Android; Tablet; rv:13.0) Gecko/13.0 Firefox/13.0\",\n      Firefox_13_Phone: \"Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0\",\n      Firefox_6_0_2: \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:6.0.2) Gecko/20100101 Firefox/6.0.2\",\n      Firefox_Mobile_Simulator: \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:2.1.1) Gecko/ Firefox/4.0.2pre Fennec/4.0.1\",\n      Firefox_Os_Phone: \"Mozilla/5.0 (Mobile; rv:18.0) Gecko/18.0 Firefox/18.0\",\n      Firefox_Os_Tablet: \"Mozilla/5.0 (Tablet; rv:18.0) Gecko/18.0 Firefox/18.0\",\n\n      Windows_IE_9: \"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\",\n      Windows_IE_9_Compat: \"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)\",\n      Windows_IE_10: \"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)\",\n      Windows_IE_11: \"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko\",\n      Windows_RT_Surface: \"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0; Touch)\",\n      Windows_Phone_8: \"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; HTC; Windows Phone 8X by HTC)\"\n    }\n\n    function detect(ua, platform, callback){\n      if (!callback) callback = platform, platform = \"\"\n      var obj = {}\n      $.__detect.call(obj, ua, platform)\n      callback.call(null, obj.os, obj.browser)\n    }\n\n    Evidence('ZeptoDetectTest', {\n      testSafariOSX: function(t){\n        detect(UA.Safari_OSX_7_0_1, function(os, browser){\n          t.assertUndefined(os.osx)\n          t.assert(!os.ipad)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(browser.safari)\n          t.assertFalse(!!browser.chrome)\n          t.assertEqual(\"7.0.1\",browser.version)\n        })\n        detect(UA.Safari_OSX_7_0, function(os, browser){\n          t.assert(!os.ipad)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(browser.safari)\n          t.assertFalse(!!browser.chrome)\n          t.assertEqual(\"7.0\",browser.version)\n        })\n        detect(UA.Safari_OSX_6_0, function(os, browser){\n          t.assert(!os.ipad)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(browser.safari)\n          t.assertFalse(!!browser.chrome)\n          t.assertEqual(\"6.0\",browser.version)\n        })\n      },\n\n      testSafariWindows: function(t){\n        detect(UA.Safari_Windows_NT, \"Windows\", function(os, browser){\n          t.assertUndefined(os.osx)\n          t.assertUndefined(os.ios)\n          t.assertUndefined(os.wp)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(browser.safari)\n          t.assertFalse(!!browser.chrome)\n          t.assertEqual(\"5.0.4\", browser.version)\n        })\n      },\n\n      testWebOS: function(t){\n        detect(UA.WebOS_1_4_0_Pre, function(os, browser){\n          t.assertTrue(os.webos)\n          t.assert(!os.touchpad)\n          t.assertTrue(browser.webkit)\n          t.assertEqual(\"1.4.0\", os.version)\n        })\n        detect(UA.WebOS_1_4_0_Pixi, function(os){\n          t.assertTrue(os.webos)\n          t.assertEqual(\"1.4.0\", os.version)\n        })\n        detect(UA.WebOS_1_2_9_Pixi, function(os){\n          t.assertTrue(os.webos)\n          t.assertEqual(\"1.2.9\", os.version)\n        })\n        detect(UA.WebOS_3_0_0_TouchPad, function(os){\n          t.assertTrue(os.webos)\n          t.assertTrue(os.touchpad)\n          t.assertEqual(\"3.0.0\", os.version)\n        })\n      },\n\n      testAndroid: function(t){\n        detect(UA.Android_1_5, function(os, browser){\n          t.assertTrue(os.android)\n          t.assertTrue(browser.webkit)\n          t.assertEqual(\"1.5\", os.version)\n          t.assertTrue(os.phone)\n          t.assertFalse(!!browser.safari)\n        })\n        detect(UA.Android_2_1, function(os, browser){\n          t.assertTrue(os.android)\n          t.assertTrue(browser.webkit)\n          t.assertEqual(\"2.1\", os.version)\n          t.assertTrue(os.phone)\n          t.assertFalse(!!browser.safari)\n        })\n        detect(UA.Android_2_3, function(os, browser){\n          t.assertTrue(os.android)\n          t.assertTrue(browser.webkit)\n          t.assertEqual(\"2.3.7\", os.version)\n          t.assertTrue(os.phone)\n          t.assertFalse(!!browser.safari)\n        })\n        detect(UA.Android_2_3_Lenovo_A750, function(os, browser){\n          t.assertTrue(os.android, 'Expected Android')\n          t.assertTrue(browser.webkit, 'Expected WebKit')\n          t.assertEqual(\"2.3\", os.version)\n          // FIXME: Unfortunately we can't detect if it's a phone, as there's\n          // no \"mobile\" in the UA string.\n          // t.assertTrue(os.phone, 'Expected phone')\n          t.assertFalse(!!browser.safari, 'Expected browser to not be Safari')\n        })\n        detect(UA.Android_4_1_1, function(os, browser){\n          t.assertTrue(os.android)\n          t.assertTrue(browser.webkit)\n          t.assertFalse(!!os.ios)\n          t.assertEqual(\"4.1.1\", os.version)\n          t.assertTrue(os.phone)\n          t.assertFalse(!!os.iphone)\n          t.assertTrue(browser.chrome)\n          t.assertFalse(!!browser.safari)\n        })\n        detect(UA.Android_4_1_1_Tablet, function(os, browser){\n          t.assertTrue(os.android)\n          t.assertTrue(browser.webkit)\n          t.assertEqual(\"4.1.1\", os.version)\n          t.assertTrue(os.tablet)\n          t.assertTrue(browser.chrome)\n          t.assertFalse(!!browser.safari)\n        })\n        detect(UA.Android_4_3, function(os, browser){\n          t.assertTrue(os.android)\n          t.assertTrue(browser.webkit)\n          t.assertFalse(!!os.ios)\n          t.assertEqual(\"4.3\", os.version)\n          t.assertTrue(os.phone)\n          t.assertFalse(!!os.iphone)\n          t.assertTrue(browser.chrome)\n          t.assertFalse(!!browser.safari)\n        })\n      },\n\n      testIOS: function(t){\n        detect(UA.iOS_3_0_iPhone, function(os, browser){\n          t.assertTrue(os.ios)\n          t.assertTrue(os.iphone)\n          t.assertTrue(browser.webkit)\n          t.assertEqual(\"3.0\", os.version)\n          t.assertEqual(\"420.1\", browser.version)\n          t.assertTrue(os.phone)\n          t.assertTrue(browser.safari)\n          t.assertFalse(!!os.android)\n          t.assertFalse(!!browser.ie)\n          t.assertFalse(!!browser.firefox)\n          t.assertFalse(!!browser.silk)\n          t.assertFalse(!!browser.chrome)\n          t.assertFalse(!!browser.playbook)\n        })\n        detect(UA.iOS_3_1_1_iPod, function(os, browser){\n          t.assertTrue(os.ios)\n          t.assertUndefined(os.iphone)\n          t.assertTrue(os.ipod)\n          t.assertEqual(\"3.1.1\", os.version)\n          t.assertFalse(!!os.phone)\n          t.assertTrue(browser.safari)\n        })\n        detect(UA.iOS_3_2_iPad, function(os, browser){\n          t.assertTrue(os.ios)\n          t.assertTrue(os.ipad)\n          t.assertFalse(!!os.iphone)\n          t.assertEqual(\"3.2\", os.version)\n          t.assertTrue(os.tablet)\n          t.assertTrue(browser.safari)\n        })\n        detect(UA.iOS_3_2_iPad_2, function(os, browser){\n          t.assertTrue(os.ios)\n          t.assertTrue(os.ipad)\n          t.assert(!os.iphone)\n          t.assertEqual(\"3.2\", os.version)\n          t.assertTrue(os.tablet)\n          t.assertTrue(browser.safari)\n        })\n        detect(UA.iOS_4_0_iPhone, function(os, browser){\n          t.assertTrue(os.ios)\n          t.assertTrue(os.iphone)\n          t.assert(!os.ipad)\n          t.assertEqual(\"4.0\", os.version)\n          t.assertTrue(os.phone)\n          t.assertTrue(browser.safari)\n        })\n        detect(UA.iOS_4_2_iPad, function(os, browser){\n          t.assertTrue(os.ios)\n          t.assertTrue(os.ipad)\n          t.assertEqual(\"4.2\", os.version)\n          t.assertFalse(os.phone)\n          t.assertTrue(os.tablet)\n          t.assertTrue(browser.safari)\n        })\n        detect(UA.iOS_4_3_iPhone_Simulator, function(os, browser){\n          t.assertTrue(os.ios)\n          t.assertTrue(os.iphone)\n          t.assertEqual(\"4.3\", os.version)\n          t.assertTrue(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(browser.safari)\n        })\n        detect(UA.iOS_5_0_iPhone, function(os, browser){\n          t.assert(os.ios)\n          t.assert(os.iphone)\n          t.assertEqual(\"5.0\", os.version)\n          t.assertTrue(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(browser.safari)\n        })\n        detect(UA.iOS_5_1_iPad_webView, function(os, browser){\n          t.assert(os.ios)\n          t.assert(os.ipad)\n          t.assertEqual(\"5.1\", os.version)\n          t.assertTrue(browser.webview)\n          t.assertTrue(browser.safari)\n        })\n        detect(UA.iOS_6_1_iPhone, function(os, browser){\n          t.assert(os.ios)\n          t.assert(os.iphone)\n          t.assertEqual(\"6.1\", os.version)\n          t.assertTrue(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(browser.safari)\n          t.assertFalse(!!browser.webview)\n          t.assertFalse(!!browser.chrome)\n          t.assertFalse(!!browser.firefox)\n        })\n        detect(UA.iOS_6_0_iPad_mini, function(os, browser){\n          t.assert(os.ios)\n          t.assert(os.ipad)\n          t.assertEqual(\"6.0\", os.version)\n          t.assertFalse(os.phone)\n          t.assertTrue(os.tablet)\n          t.assertTrue(browser.safari)\n        })\n        detect(UA.iOS_7_0_iPhone, function(os, browser){\n          t.assert(os.ios)\n          t.assert(os.iphone)\n          t.assertEqual(\"7.0\", os.version)\n          t.assertTrue(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(browser.safari)\n          t.assertFalse(!!browser.chrome)\n          t.assertFalse(!!browser.firefox)\n        })\n        detect(UA.iOS_7_0_iPhone_Chrome, function(os, browser){\n          t.assert(os.ios)\n          t.assert(os.iphone)\n          t.assertEqual(\"7.0\", os.version)\n          t.assertTrue(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertFalse(!!browser.safari)\n          t.assertTrue(browser.chrome)\n          t.assertFalse(!!browser.firefox)\n          t.assertFalse(!!browser.webview)\n        })\n      },\n\n      testBlackBerry: function(t) {\n        detect(UA.BlackBerry_6_0_0_141, function(os, browser){\n          t.assertTrue(os.blackberry)\n          t.assertTrue(browser.webkit)\n          t.assertEqual(\"6.0.0.141\", os.version)\n        }),\n        detect(UA.PlayBook_1_0_0, function(os, browser){\n          t.assertTrue(os.rimtabletos)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(os.tablet)\n          t.assertEqual(\"1.0.0\", os.version)\n        })\n        detect(UA.PlayBook_2_1_0, function(os, browser){\n          t.assertTrue(os.rimtabletos)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(os.tablet)\n          t.assertEqual(\"2.1.0\", os.version)\n        })\n        detect(UA.BB10, function(os, browser){\n          t.assertTrue(os.bb10)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(os.phone)\n          t.assertEqual(\"10.0.0.1337\", os.version)\n        })\n      },\n\n      testKindle: function(t) {\n        detect(UA.Kindle, function(os, browser){\n          t.assertTrue(os.kindle)\n          t.assertTrue(browser.webkit)\n          t.assertEqual(\"3.0\", os.version)\n        })\n\n        detect(UA.Silk_1_0, function(os, browser){\n          t.assertTrue(os.android)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(browser.silk)\n          t.assertEqual(\"2.3.4\", os.version)\n        })\n\n        detect(UA.Silk_1_0_accel, function(os, browser){\n          t.assert(!os.android)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(browser.silk)\n          t.assertEqual(\"1.0.13.328_10008910\", browser.version)\n        })\n      },\n\n      testFirefox: function(t) {\n        detect(UA.Firefox_6_0_2, function(os, browser){\n          t.assertFalse(browser.webkit)\n          t.assertEqual('6.0.2', browser.version)\n\n          t.assertTrue(browser.firefox)\n          t.assertFalse(!!os.firefoxos)\n        })\n\n        detect(UA.Firefox_13_Tablet, function(os, browser){\n          t.assertTrue(browser.firefox)\n          t.assertFalse(browser.webkit)\n          t.assertTrue(os.android)\n          t.assertFalse(os.phone)\n          t.assertTrue(os.tablet)\n          t.assertFalse(!!os.firefoxos)\n        })\n\n        detect(UA.Firefox_13_Phone, function(os, browser){\n          t.assertTrue(browser.firefox)\n          t.assertFalse(browser.webkit)\n          t.assertTrue(os.android)\n          t.assertTrue(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertFalse(!!os.firefoxos)\n        })\n\n        detect(UA.Firefox_Os_Phone, function(os, browser){\n          t.assertTrue(browser.firefox)\n          t.assertFalse(browser.webkit)\n          t.assertTrue(os.firefoxos)\n          t.assertTrue(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertEqual('18.0', os.version)\n        })\n\n        detect(UA.Firefox_Os_Tablet, function(os, browser){\n          t.assertTrue(browser.firefox)\n          t.assertFalse(browser.webkit)\n          t.assertTrue(os.firefoxos)\n          t.assertTrue(os.tablet)\n          t.assertFalse(os.phone)\n          t.assertEqual('18.0', os.version)\n        })\n      },\n\n      testOpera: function(t) {\n        detect(UA.Opera_11_51, function(os, browser){\n          t.assertFalse(browser.webkit)\n          t.assertUndefined(browser.version)\n        })\n      },\n\n      testChrome: function(t) {\n        detect(UA.Chrome_Android_18_0, function(os, browser){\n          t.assertTrue(os.android)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(browser.chrome)\n          t.assertTrue(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertEqual(\"18.0.1025.133\", browser.version)\n        })\n\n        detect(UA.Chrome_iOS_19_0, function(os, browser){\n          t.assertTrue(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(os.ios)\n          t.assertTrue(browser.webkit)\n          t.assertTrue(browser.chrome)\n          t.assertEqual(\"19.0.1084.60\", browser.version)\n        })\n\n        detect(UA.Chrome_OSX_24_0, function(os, browser){\n          t.assertFalse(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(browser.chrome)\n        })\n      },\n\n      testIE: function(t) {\n        detect(UA.Windows_IE_11, function(os, browser){\n          t.assertFalse(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(browser.ie)\n          t.assertEqual(\"11\", browser.version)\n        })\n\n        detect(UA.Windows_IE_10, function(os, browser){\n          t.assertFalse(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(browser.ie)\n          t.assertEqual(\"10.0\", browser.version)\n        })\n\n        detect(UA.Windows_RT_Surface, function(os, browser){\n          t.assertFalse(os.phone)\n          t.assertTrue(os.tablet)\n          t.assertTrue(browser.ie)\n          t.assertEqual(\"10.0\", browser.version)\n        })\n\n        detect(UA.Windows_Phone_8, function(os, browser){\n          t.assertTrue(os.wp)\n          t.assertTrue(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(browser.ie)\n          t.assertEqual(\"10.0\", browser.version)\n        })\n\n        detect(UA.Windows_IE_9, function(os, browser){\n          t.assertFalse(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(browser.ie)\n          t.assertEqual(\"9.0\", browser.version)\n        })\n\n        detect(UA.Windows_IE_9_Compat, function(os, browser){\n          t.assertFalse(os.phone)\n          t.assertFalse(os.tablet)\n          t.assertTrue(browser.ie)\n          t.assertEqual(\"7.0\", browser.version)\n        })\n\n      }\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/event.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Event unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto event ie')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto Event unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n  <div id=\"fixtures\">\n  </div><!-- fixtures -->\n\n  <script>\n  (function(){\n\n    function click(el){\n      var event = document.createEvent('MouseEvents')\n      event.initMouseEvent('click', true, true, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null)\n      $(el).get(0).dispatchEvent(event)\n    }\n\n    Evidence('ProxyTest', {\n      testProxyFnContext: function(t){\n        var a = {name: 'A', fn: function(n, o){ return this.name + n + o }},\n            b = {name: 'B'}\n\n        t.assertEqual('A13', a.fn(1, 3))\n        t.assertEqual('B52', $.proxy(a.fn, b)(5, 2))\n      },\n\n      testProxyInvalidFn: function(t){\n        try {\n          $.proxy(null)\n          t.fail(\"shouldn't be here\")\n        } catch(e) {\n          t.assertEqual('TypeError', e.name)\n          t.assertEqual(\"expected function\", e.message)\n        }\n      },\n\n      testProxyContextName: function(t){\n        var b = {name: 'B', fn: function(n, o){ return this.name + n + o }},\n            oldFn = b.fn\n\n        t.assertEqual('B52', $.proxy(b, 'fn')(5, 2))\n        t.assertIdentical(oldFn, b.fn)\n      },\n\n      testProxyUndefinedProperty: function(t){\n        try {\n          $.proxy({}, 'nonexistent')\n          t.fail(\"shouldn't be here\")\n        } catch(e) {\n          t.assertEqual('TypeError', e.name)\n          t.assertEqual(\"expected function\", e.message)\n        }\n      },\n\n      testProxyAdditionalArguments: function(t){\n        var a = {name: 'A', fn: function(){ return this.name + [].slice.call(arguments).join('') }}\n        t.assertEqual('A123', $.proxy(a.fn, a)(1, 2, 3))\n        t.assertEqual('A456', $.proxy(a.fn, a, 4, 5, 6)())\n        t.assertEqual('A456123', $.proxy(a.fn, a, 4, 5, 6)(1, 2, 3))\n      },\n\n      testProxyContextNameAdditionalArguments: function(t){\n        var a = {name: 'A', fn: function(){ return this.name + [].slice.call(arguments).join('') }}\n        t.assertEqual('A123', $.proxy(a, 'fn')(1, 2, 3))\n        t.assertEqual('A456', $.proxy(a, 'fn', 4, 5, 6)())\n        t.assertEqual('A456123', $.proxy(a, 'fn', 4, 5, 6)(1, 2, 3))\n      },\n\n      testProxyInvalidProperty: function(t){\n        try {\n          $.proxy({num:3}, 'num')\n          t.fail(\"shouldn't be here\")\n        } catch(e) {\n          t.assertEqual('TypeError', e.name)\n          t.assertEqual(\"expected function\", e.message)\n        }\n      }\n    })\n\n    Evidence('EventTest', {\n      setUp: function(){\n        this.el = $('<div />').appendTo('#fixtures')\n      },\n\n      tearDown: function(){\n        this.el.off().remove()\n        $([document, document.body]).off()\n      },\n\n      testProxiedHandlerCanBeUnboundWithOriginal: function(t){\n        var obj = {times:0, fn: function(){ this.times++ }}\n\n        this.el.on('click', $.proxy(obj, 'fn'))\n        click(this.el)\n        t.assertEqual(1, obj.times)\n\n        this.el.off('click', obj.fn)\n        click(this.el)\n        t.assertEqual(1, obj.times)\n      },\n\n      testOneHandlerCanBeUnboundWithOriginal: function(t){\n        var count = 0, fn = function(){ count++ }\n\n        this.el.one('click', fn)\n        this.el.off('click', fn)\n        click(this.el)\n        t.assertEqual(0, count)\n      },\n\n      testOneDelegation: function(t){\n        var context, count = 0\n        $(document).one('click', 'div', function(){ context = this; count++ })\n\n        click(this.el)\n        click(this.el)\n        t.assertEqual(1, count)\n        t.assertIdentical(this.el.get(0), context)\n      },\n\n      testOneWithData: function(t){\n        var obj = {}, gotObj, count = 0\n        $(document).one('click', obj, function(e){ gotObj = e.data; count++ })\n\n        click(this.el)\n        click(this.el)\n        t.assertEqual(1, count)\n        t.assertIdentical(obj, gotObj)\n      },\n\n      testHandlerArity: function(t){\n        var numArgs\n        this.el.on('click', function(){ numArgs = arguments.length })\n\n        click(this.el)\n        t.assertEqual(1, numArgs)\n      },\n\n      testOnWithObject: function(t){\n        var log = []\n        this.el.on({ click: function(){ log.push('a') } }).\n                on({ click: function(){ log.push('b') } }, null)\n\n        click(this.el)\n        t.assertEqual('a b', log.sort().join(' '))\n      },\n\n      testOnWithBlankData: function(t){\n        var log = [], fn = function(e){ log.push(e.data) }\n        this.el\n          .on('click', null, fn)\n          .on('click', undefined, fn)\n\n        click(this.el)\n        t.assertEqual(2, log.length)\n        t.assertIdentical(null, log[0])\n        t.assertIdentical(undefined, log[1])\n      },\n\n      testOffWithObject: function(t){\n        var log = [],\n            fn = function(){ log.push('a') },\n            fn2 = function(){ log.push('b') },\n            fn3 = function(){ log.push('c') }\n\n        this.el.on('click', fn).on('click', fn2).on('click', fn3)\n        click(this.el)\n        t.assertEqual('a b c', log.sort().join(' '))\n\n        this.el.off({ click: fn }).off({ click: fn2 }, null)\n        click(this.el)\n        t.assertEqual('a b c c', log.sort().join(' '))\n      },\n\n      testDelegateEventProperties: function(t){\n        var type, target, currentTarget\n        $(document).on('click', 'div', function(e){\n          type = e.type\n          target = e.target\n          currentTarget = e.currentTarget\n        })\n        click($('<span>').appendTo(this.el))\n        t.assertEqual('click', type)\n        t.assertIdentical(this.el.find('span').get(0), target)\n        t.assertIdentical(this.el.get(0), currentTarget)\n      },\n\n      testDelegateEventTimestamp: function(t){\n        var timestamp\n        $(document).on('click', 'div', function(e){\n          timestamp = e.timeStamp\n        })\n        click($('<span>').appendTo(this.el))\n        t.assert(timestamp > 0, 'timestamp was ' + timestamp)\n      },\n\n      testPreventDefaultWithDelegatedEvent: function(t){\n        var isDefaultPrevented, span = $('<span>').appendTo(this.el)\n\n        span.on('click', function(event){\n          event.preventDefault()\n        })\n        $(document).on('click', 'div', function(event){\n          isDefaultPrevented = event.isDefaultPrevented()\n        })\n\n        click(span)\n        t.assertTrue(isDefaultPrevented, \"isDefaultPrevented() value invalid for delegate proxy\")\n      },\n\n      testEventsOnPlainObjects: function (t){\n        var obj = {},\n          log = [],\n          fn1 = function(){ log.push('a') },\n          fn2 = function(evt, value){ log.push(value)    },\n          fn3 = function(evt, value){ log.push(\"event2\") }\n        $(obj)\n          .on('event', fn1)\n          .on('event', fn2)\n          .on('event2', fn3)\n\n        $(obj).trigger('event', 'b')\n        t.assertEqual('a b', log.join(' '))\n\n        log = []\n        $(obj).trigger('event', 'c')\n        t.assertEqual('a c', log.join(' '))\n\n        log = []\n        $(obj).off('event', fn1)\n        $(obj).trigger('event', 'd')\n        t.assertEqual('d', log.join(' '))\n\n        log = []\n        $(obj).trigger('event2')\n        t.assertEqual('event2', log.join(' '))\n      },\n\n      testHandlerWithoutData: function(t){\n        var gotData\n\n        $(document).on('click', function(event){\n          gotData = event.data\n        })\n        t.assertUndefined(gotData)\n\n        click(this.el)\n        t.assertUndefined(gotData)\n      },\n\n      testHandlerWithData: function(t){\n        var data = {}, gotData, numArgs\n\n        $(document).on('click', data, function(event){\n          gotData = event.data\n          numArgs = arguments.length\n        })\n        t.assertUndefined(gotData)\n\n        click(this.el)\n        t.assertEqual(1, numArgs)\n        t.assertIdentical(data, gotData)\n      },\n      \n      testHandlerWithFunctionAsData: function(t){\n        var data = function () { console.log('foo') },\n            gotData, numArgs\n        \n        $(document).on('click', data, function(event){\n          gotData = event.data\n          numArgs = arguments.length\n        })\n        t.assertUndefined(gotData)\n\n        click(this.el)\n        t.assertEqual(1, numArgs)\n        t.assertIdentical(data, gotData)\n      },\n\n      testDelegatedWithData: function(t){\n        var data = {}, gotData, numArgs\n\n        $(document).on('click', 'div', data, function(event){\n          gotData = event.data\n          numArgs = arguments.length\n        })\n        t.assertUndefined(gotData)\n\n        click(this.el)\n        t.assertEqual(1, numArgs)\n        t.assertIdentical(data, gotData)\n      },\n\n      testTriggerWithData: function(t){\n        var data = {}, gotData\n\n        $(document).on('myevent', data, function(event){\n          gotData = event.data\n        })\n        t.assertUndefined(gotData)\n\n        this.el.trigger('myevent')\n        t.assertIdentical(data, gotData)\n      },\n\n      testDelegateEventMethods: function(t){\n        var methodName,\n            eventMethods = {\n              preventDefault: 'isDefaultPrevented',\n              stopImmediatePropagation: 'isImmediatePropagationStopped',\n              stopPropagation: 'isPropagationStopped'\n            },\n            eventMethodResults = {}\n\n        $(document).on('click', 'div', function(event){\n          $.each(eventMethods, function(methodName, predicate){\n            if (event[methodName]) {\n              event[methodName]()\n              eventMethodResults[predicate] = event[predicate]()\n            } else {\n              console.warn(\"method not available: \", methodName)\n            }\n          })\n        })\n\n        click($('<span>').appendTo(this.el))\n\n        $.each(eventMethodResults, function(predicate, value){\n          t.assertTrue(value, predicate)\n        })\n      },\n\n      testIsDefaultPreventedOnAllEvents: function(t){\n        var isDefaultPrevented\n\n        $(this.el).on('click', function(event){\n          event.preventDefault()\n        })\n        $(document).on('click', function(event){\n          isDefaultPrevented = event.isDefaultPrevented()\n        })\n\n        click(this.el)\n        t.assertTrue(isDefaultPrevented)\n      },\n\n      testIsDefaultPreventedOnOriginalEventAfterDelegate: function(t){\n        var isDefaultPrevented\n\n        this.el.on('click', 'span', function(event){\n          event.preventDefault()\n        })\n        $(document).on('click', function(event){\n          isDefaultPrevented = event.isDefaultPrevented()\n        })\n\n        click($('<span>').appendTo(this.el))\n\n        t.assertTrue(isDefaultPrevented)\n      },\n\n      testStopImmediatePropagation: function(t){\n        var log = ''\n\n        this.el\n          .on('click', function(e){ log += 'A' })\n          .on('click', function(e){ log += 'B'; e.stopImmediatePropagation() })\n          .on('click', function(e){ log += 'C' })\n\n        $(document).on('click', function(e){ log += 'D' })\n\n        click(this.el)\n\n        t.assertEqual('AB', log)\n      },\n\n      testDelegateSelectorLookupDoesNotIncludeParent: function(t){\n        var fired = false\n\n        this.el\n          .addClass('offender')\n          .on('click', '.offender', function(){ fired = true })\n\n        click(this.el)\n\n        t.assertFalse(fired)\n      },\n\n      testFalseLiteralAsCallback: function(t){\n        var event = $.Event('click')\n\n        this.el.on('click', false)\n\n        this.el.trigger(event)\n        t.assertTrue(event.isDefaultPrevented())\n        t.assertTrue(event.isPropagationStopped())\n      },\n\n      testFalseLiteralAsCallbackForShorthand: function(t){\n        var event = $.Event('click')\n\n        this.el.click(false)\n\n        this.el.trigger(event)\n        t.assertTrue(event.isDefaultPrevented())\n        t.assertTrue(event.isPropagationStopped())\n      },\n\n      testUnbindingFalseLiteral: function(t){\n        var event = $.Event('click'), fired\n\n        this.el\n          .on('click', function() { fired = true })\n          .on('click', false)\n          .off('click', false)\n\n        this.el.trigger(event)\n\n        t.assertTrue(fired)\n        t.assertFalse(event.isDefaultPrevented())\n        t.assertFalse(event.isPropagationStopped())\n      },\n\n      testFalseLiteralAsCallbackWithDataArgument: function(t){\n        var event = $.Event('click')\n\n        this.el.on('click', null, false)\n\n        this.el.trigger(event)\n        t.assertTrue(event.isDefaultPrevented())\n        t.assertTrue(event.isPropagationStopped())\n      },\n\n      testFalseLiteralAsCallbackForDelegation: function(t){\n        var span = $('<span>').appendTo(this.el),\n            event = $.Event('click')\n\n        this.el.on('click', 'span', false)\n\n        span.trigger(event)\n        t.assertTrue(event.isDefaultPrevented())\n        t.assertTrue(event.isPropagationStopped())\n      },\n\n      testFalseLiteralAsCallbackForDelegationWithDataArgument: function(t){\n        var span = $('<span>').appendTo(this.el),\n            event = $.Event('click')\n\n        this.el.on('click', 'span', null, false)\n\n        span.trigger(event)\n        t.assertTrue(event.isDefaultPrevented())\n        t.assertTrue(event.isPropagationStopped())\n      }\n\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/evidence_runner.js",
    "content": "(function(){\n  var ConsoleTestRunner = Evidence.AutoRunner.RUNNERS.console,\n      ConsoleTestResult = Evidence.UI.Console.TestResult,\n      AutoRunner = Evidence.AutoRunner,\n      printf = Evidence.UI.printf\n\n  function inherit(superclass, extra) {\n    var klass = function(){\n      this.initialize.apply(this, arguments)\n    }\n    var tmp = function(){}\n    tmp.prototype = superclass.prototype\n    klass.prototype = new tmp()\n    klass.prototype.constructor = klass\n    klass.prototype.initialize = function(){\n      superclass.apply(this, arguments)\n    }\n\n    if (extra) {\n      var methods = extra.call(klass, superclass.prototype)\n      for (var method in methods) klass.prototype[method] = methods[method]\n    }\n    return klass\n  }\n\n  var TestRunner = inherit(ConsoleTestRunner, function(_super) {\n    AutoRunner.RUNNERS.zepto = this\n    return {\n      _makeResult: function() { return new TestResult(this.logger) }\n    }\n  })\n\n  var TestResult = inherit(ConsoleTestResult, function(_super) {\n    return {\n      start: function(t0) {\n        Evidence.TestResult.prototype.start.call(this, t0)\n        this.logger.debug('Started tests.')\n      },\n      stop: function(t1) {\n        _super.stop.call(this, t1)\n        displayResults(this, (t1-this.t0)/1000)\n        checkLeakedGlobals()\n      },\n      pauseTest: function(testcase) {\n        this.logger.debug('Paused testcase ' + testcase + '.')\n      },\n      restartTest: function(testcase) {\n        this.logger.debug('Restarted testcase ' + testcase + '.')\n      },\n      startSuite: function(suite) {\n        this.logger.debug('Started suite ' + suite + '.')\n      },\n      addFailure: function(testcase, reason) {\n        this.logToServer(testcase, reason)\n        _super.addFailure.call(this, testcase, reason)\n      },\n      addError: function(testcase, error) {\n        this.logToServer(testcase, error)\n        _super.addError.call(this, testcase, error)\n      },\n      logToServer: function(testcase, error) {\n        if (location.protocol == 'file:') return\n        var name = testcase.parent.name + '#' + testcase.name,\n            message = error.template ?\n              Evidence.UI.printf(error.template, error.args) + (error.message ? ' ' + error.message : '') :\n              error.message,\n            body = 'name=' + encodeURIComponent(name) + '&' +\n                   'message=' + encodeURIComponent(message) + '&' +\n                   'trace=' + encodeURIComponent(error.stack || '')\n\n        var xhr = new XMLHttpRequest()\n        xhr.open('POST', '/test/log', true)\n        xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')\n        xhr.send(body)\n      }\n    }\n  })\n\n  Evidence.TestCase.prototype.debug = function(message) {\n    this._result.logToServer(this, { message: message })\n  }\n\n  // HACK: force our test runner as default\n  ;(function(){\n    var _super = AutoRunner.prototype.retrieveOptions\n    AutoRunner.prototype.retrieveOptions = function() {\n      var options = _super.call(this)\n      if (!options.runner) options.runner = 'zepto'\n      return options\n    }\n  })()\n\n  function $(id) { return document.getElementById(id) }\n\n  function displayResults(results, seconds) {\n    var container = $('results')\n    if (container) {\n      if (results.failureCount || results.errorCount) {\n        container.className = 'failed'\n        container.innerHTML = printf(\"Finished in %d s. &ndash; <em>%d failures, %d errors</em> (%d assertions)\",\n                                     [seconds, results.failureCount, results.errorCount, results.assertionCount])\n      } else {\n        container.className = 'passed'\n        container.innerHTML = printf(\"Finished in %d s. &ndash; <em>%d tests passed</em> (%d assertions)\",\n                                     [seconds, results.testCount, results.assertionCount])\n      }\n      container.className += ' finished'\n    }\n  }\n\n  var globals = [], expected = ['Zepto', '$', 'Evidence', '_zid', 'jsonpDummy']\n  for (var key in window) globals.push(key)\n\n  function checkLeakedGlobals() {\n    var opera = /^Opera\\b/.test(navigator.userAgent)\n    for (var key in window)\n      if ( globals.indexOf(key) < 0 && expected.indexOf(key) < 0 &&\n          (!opera || typeof window[key] != 'object' || window[key].id != key) &&\n          window.console && console.warn\n          )\n        console.warn(\"unexpected global: \" + key)\n  }\n})()\n"
  },
  {
    "path": "test/fixtures/ajax_load_javascript.js",
    "content": "window.testValue = 1\n"
  },
  {
    "path": "test/fixtures/ajax_load_selector.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>testAjaxLoad</title>\n</head>\n<body>\n<div id=\"ajax_load_test_div\">ajax load with selector</div>\n<div>\n  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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "test/fixtures/ajax_load_selector_javascript.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>testAjaxLoad</title>\n</head>\n<body>\n<div id=\"ajax_load_test_div\">ajax load with selector</div>\n<div>\n  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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n</div>\n<script>\n  window.testValue = 1\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "test/fixtures/ajax_load_simple.html",
    "content": "simple ajax load\n"
  },
  {
    "path": "test/fixtures/iframe_document.html",
    "content": "<b>Hello from iframe!</b>\n"
  },
  {
    "path": "test/fixtures/zepto.json",
    "content": "{\n  \"zepto\": \"awesomeness\"\n}\n"
  },
  {
    "path": "test/form.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Form unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto event form ie')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto Form unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n\n  <div id=\"fixtures\">\n  <form id=\"login_form\" target=\"formtarget\" action=\"./idontexist.html\">\n    <input name=\"email\" value=\"koss@nocorp.me\">\n    <input name=\"password\" value=\"123456\">\n    <input name=\"unchecked_hasValue\" value=\"myValue\" type=\"checkbox\">\n    <input name=\"unchecked_noValue\" type=\"checkbox\">\n    <input name=\"checked_hasValue\" checked value=\"myValue\" type=\"checkbox\">\n    <input name=\"checked_disabled\" checked value=\"ImDisabled\" type=\"checkbox\" disabled>\n    <input name=\"checked_noValue\" checked type=\"checkbox\">\n    <input type=\"text\" id=\"no_name\">\n    <input type=\"file\" name=\"file_upload\">\n\n    <fieldset>\n      <input type=\"radio\" name=\"radio1\" value=\"r1\">\n      <input type=\"radio\" name=\"radio1\" checked value=\"r2\">\n      <input type=\"radio\" name=\"radio1\" value=\"r3\">\n    </fieldset>\n\n    <select name=\"selectbox\">\n      <option value=\"selectopt1\">select1</option>\n      <option value=\"selectopt2\">select2</option>\n      <option value=\"selectopt3\">select3</option>\n    </select>\n\n    <select name=\"users[id][]\" multiple>\n      <option value=\"1\">a</option>\n      <option value=\"2\" selected>b</option>\n      <option value=\"3\" selected>c</option>\n      <option value=\"4\">d</option>\n    </select>\n\n    <div class=\"actions\">\n      <!--\n        The name of the following element can't be \"submit\",\n        as this breaks on IE 10 (the form's \"submit\" method\n        is overwritten by an accessor to the input field\n        with the \"submit\" name). Yes, that's a dumb bug.\n      -->\n      <input type=\"submit\" name=\"submit_button\" value=\"Save\">\n\n      <input type=\"button\" name=\"preview\" value=\"Preview\">\n      <input type=\"reset\" name=\"clear\" value=\"Clear form\">\n      <button name=\"button\">I'm a button</button>\n    </div>\n  </form>\n\n  <iframe name=\"formtarget\"></iframe>\n  </div>\n\n  <script>\n  (function(){\n\n    // TODO: do we really need this function? This should be refactored.\n    var isObjectEquals = function(obj1, obj2){\n      for (var key in obj1)\n        switch(typeof(obj1[key])) {\n          case 'object':\n            if (!isObjectEquals(obj1[key], obj2[key]))\n              return false\n            break\n\n          case 'function':\n            if (typeof(obj2[key]) == 'undefined' ||\n              (obj1[key].toString() != obj2[key].toString()))\n              return false\n            break\n\n          default:\n            if (obj1[key] != obj2[key])\n              return false\n        }\n\n      for (key in obj2)\n        if (typeof(obj1[key]) == 'undefined')\n          return false\n\n      return true\n    }\n\n    Evidence.Assertions.assertEqualObject = function(expected, actual, message) {\n      this._assertExpression(\n        isObjectEquals(expected, actual),\n        message || 'Failed assertion.',\n        'Expected %o, got %o.', expected, actual\n      )\n    }\n\n    Evidence('FormTest', {\n\n      testSerializeArray: function(t){\n        var loginForm = $('#login_form')\n        t.assertEqualObject(\n          [\n              { name: 'email', value: 'koss@nocorp.me' },\n              { name: 'password', value: '123456' },\n              { name: 'checked_hasValue', value: 'myValue' },\n              { name: 'checked_noValue', value: 'on' },\n              { name: 'radio1', value: 'r2' },\n              { name: 'selectbox', value: 'selectopt1' },\n              { name: 'users[id][]', value: '2' },\n              { name: 'users[id][]', value: '3' }\n          ],\n          loginForm.serializeArray()\n        )\n      },\n\n      testSerialize: function(t){\n        var loginForm = $('#login_form')\n        t.assertEqual('email=koss%40nocorp.me&password=123456&checked_hasValue=myValue&checked_noValue=on&radio1=r2&selectbox=selectopt1&users%5Bid%5D%5B%5D=2&users%5Bid%5D%5B%5D=3', loginForm.serialize())\n      },\n\n      testFormSubmit: function(t){\n        var eventTriggered = false\n        $('#login_form').submit(function(event){\n          eventTriggered = true\n          event.preventDefault()\n        })\n        $('#login_form').submit()\n        t.assert(eventTriggered)\n      },\n\n      testFormSubmitBindFalse: function(t){\n        var eventPropagated = false\n        $(document).on('submit', function(){\n          eventPropagated = true\n        })\n\n        try {\n          var form = $('#login_form')\n          form.submit(false)\n          form.submit()\n          t.assertFalse(eventPropagated)\n        } finally {\n          $(document).off('submit')\n        }\n      },\n\n      testSerializeEmptyCollection: function(t){\n        t.assertIdentical(0, $().serializeArray().length)\n        t.assertIdentical(\"\", $().serialize())\n      }\n\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/functional/assets.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Zepto assets functional test</title>\n  <link rel=\"stylesheet\" href=\"../test.css\">\n  <meta name=\"viewport\" content=\"maximum-scale=1,initial-scale=1,user-scalable=0\">\n  <script src=\"../../src/zepto.js\"></script>\n  <script src=\"../../src/ie.js\"></script>\n  <style>\n    #container div {\n      margin: 2px;\n      padding: 2px;\n      display: block;\n      background-color: #ccc;\n    }\n    img {\n      margin: 0;\n      height: 100px;\n      vertical-align: middle;\n    }\n  </style>\n</head>\n<body>\n  <h1>Zepto assets functional test</h1>\n\n  <div id=\"browser\"></div>\n\n  <ul>\n    <li><a href=\"?without\">Run without the assets plugin</a></li>\n    <li><a href=\"?with\">Run with the assets plugin</a></li>\n    <li><a href=\"?\">Stop</a></li>\n  </ul>\n\n  <p>When you run this test without the assets plugin, Mobile Safari will stop loading after on average 8 images (that's on the iPad with 1 MB images). It might also crash.</p>\n  <p><strong>PLEASE NOTE:</strong> You <strong>must restart Safari</strong> between runs (click the home button to return to the home screen, double-click the home button, tap-and-hold the Safari icon, then tap the minus badge).</p>\n\n  <div id=\"container\"></div>\n\n  <script>\n    var prefix = 'http://stuff.vandervossen.net/temporary/zepto_assets_test/sintel-',\n        mode = window.location.search.slice(1),\n        timeout,\n        i\n    if (mode === 'with') {\n      document.write('<script src=\"../src/assets.js\"></s'+'cript>')\n      document.write('RUNNING WITH ASSETS PLUGIN')\n    }\n    if (mode !== '') {\n      i = 1\n      ;(function frame() {\n        $('#image' + (i - 4)).remove()\n        $('#container').prepend('<div>' + i + ': <img id=\"image' + i + '\" src=\"' + prefix + i + '.jpg\"></div>')\n        if (i++ < 51) timeout = setTimeout(frame, 6000)\n      })()\n    }\n\n    $('#browser').text(navigator.userAgent)\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/functional/fx.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"maximum-scale=1,initial-scale=1,user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"../test.css\">\n  <title>Zepto fx functional test</title>\n  <script src=\"../../src/zepto.js\"></script>\n  <script src=\"../../src/event.js\"></script>\n  <script src=\"../../src/fx.js\"></script>\n  <script src=\"../../src/fx_methods.js\"></script>\n  <script src=\"../../src/ie.js\"></script>\n  <style>\n    #fx_test, #fx_test_2  { text-align: center; background: darkred; color: white; font-size: x-large; }\n    #fx_test_2 { background: darkblue; }\n  </style>\n</head>\n<body>\n  <h1>Zepto fx functional</h1>\n\n  <div style=\"width: 280px; height: 180px; background: #ddd; -webkit-user-select: none; margin-bottom: 1em\">\n    <div id=\"fx_test\" style=\"height: 100%; line-height: 170px\">I  ♥ fx</div>\n  </div>\n\n  <div style=\"width: 280px; height: 180px; background: #ddd; -webkit-user-select: none; margin-bottom: 1em\">\n    <div id=\"fx_test_2\" style=\"height: 100%; line-height: 170px\">I  ♥ fx</div>\n  </div>\n\n  <button onclick=\"$('#fx_test').hide('slow')\">Hide</button>\n  <button onclick=\"$('#fx_test').show('slow')\">Show</button>\n  <button onclick=\"$('#fx_test').show()\">Reg. show</button>\n  <button onclick=\"$('#fx_test').toggle('slow')\">Toggle</button>\n  <button onclick=\"$('#fx_test, #fx_test_2').toggle('slow')\">Both: Toggle ('slow')</button>\n  <button onclick=\"$('#fx_test, #fx_test_2').toggle()\">Both: Toggle</button>\n  <br>\n  <button onclick=\"$('#fx_test').fadeIn('slow')\">Fade in</button>\n  <button onclick=\"$('#fx_test').fadeOut('slow')\">Fade out</button>\n  <button onclick=\"$('#fx_test').fadeToggle('slow')\">Fade toggle</button>\n  <button onclick=\"$('#fx_test, #fx_test_2').fadeToggle('slow')\">Both: Fade toggle</button>\n\n  <div id=\"browser\"> </div>\n\n  <script>\n    $('#browser').text(navigator.userAgent)\n    $('#fx_test_2').toggle()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/functional/gesture.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Zepto gesture functional test</title>\n  <meta name=\"viewport\" content=\"maximum-scale=1,initial-scale=1,user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"../test.css\">\n  <script src=\"../../src/zepto.js\"></script>\n  <script src=\"../../src/event.js\"></script>\n  <script src=\"../../src/detect.js\"></script>\n  <script src=\"../../src/gesture.js\"></script>\n  <script src=\"../../src/ie.js\"></script>\n</head>\n<body>\n  <h1>Zepto gestures functional test</h1>\n\n  <div id=\"gesture_test\" style=\"width: 200px; height: 200px; background: #ddd; -webkit-user-select: none\">\n    gesture events test\n  </div>\n\n  <div id=\"browser\"> </div>\n\n  <script>\n    $('#browser').text(navigator.userAgent)\n\n    $('#gesture_test')\n      .pinch(function(){\n        $(this).append(' | pinch!')\n      })\n      .pinchIn(function(){\n        $(this).append(' | pinch in!')\n      })\n      .pinchOut(function(){\n        $(this).append(' | pinch out!')\n      })\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/functional/touch.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Zepto touch functional test</title>\n  <meta name=\"viewport\" content=\"maximum-scale=1,initial-scale=1,user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"../test.css\">\n  <script src=\"../../src/zepto.js\"></script>\n  <script src=\"../../src/event.js\"></script>\n  <script src=\"../../src/ie.js\"></script>\n  <script src=\"../../src/touch.js\"></script>\n</head>\n<body>\n  <h1>Zepto touch functional test</h1>\n\n  <p>\n    Browser supports touch events?\n    <script>document.write('ontouchstart' in window)</script><br>\n\n    Browser supports MS pointer events?\n    <script>document.write(!!navigator.msPointerEnabled)</script>\n  </p>\n\n  <div id=\"touch_test\" style=\"width: 200px; height: 200px; background: #cce; -webkit-user-select: none\">\n    touch events test\n  </div>\n\n  <div id='touch_test_scrollable' style=\"width: 200px; height: 200px; background: #cec; -webkit-user-select: none\">\n    touch events test (scrollable cancel)\n  </div>\n\n  <div id='touch_test_single' style=\"width: 200px; height: 200px; background: #ecc; -webkit-user-select: none\">\n    touch events test (scrollable cancel, single tap only)\n  </div>\n\n  <div id=\"browser\"> </div>\n\n  <script>\n    $('#browser').text(navigator.userAgent)\n\n    /**\n     * #touch_test\n     * Container that captures all touch events.\n     *\n     * Prevents default on touchmove, disabling scrolling.\n     * Captures swipes in all directions.\n     * Captures tap, singleTap (after delay), doubleTap, longTap\n     */\n    $('#touch_test').bind('touchmove', function(e) { e.preventDefault() })\n    listen_to('#touch_test')\n\n    /**\n     * #touch_test_scrollable\n     * Container that allows scrolling while capturing all events except swipes in the direction of scroll\n     *\n     * Captures swipes in non-scrolling directions\n     * Captures tap, singleTap (after delay), doubleTap, longTap\n     */\n    listen_to('#touch_test_scrollable')\n\n    /**\n     * #touch_test_single\n     * Container that allows scrolling and captures only simple, single taps\n     * eg: a button or a tappable list item\n     *\n     * Cancels touch after tap, disabling other touch events (singleTap, doubleTap)\n     * Captures tap\n     */\n    $('#touch_test_single').bind('tap', function(e) {\n      e.cancelTouch()\n    })\n    listen_to('#touch_test_single')\n\n\n\n    function listen_to(el) {\n      $(el).tap(function(){\n        $(this).append(' | tap!')\n      })\n      .doubleTap(function(){\n        $(this).append(' | double tap!')\n      })\n      .swipe(function(){\n        $(this).append(' | swipe!')\n      })\n      .swipeLeft(function(){\n        $(this).append(' | swipe left!')\n      })\n      .swipeRight(function(){\n        $(this).append(' | swipe right!')\n      })\n      .swipeUp(function(){\n        $(this).append(' | swipe up!')\n      })\n      .swipeDown(function(){\n        $(this).append(' | swipe down!')\n      })\n      .longTap(function(){\n        $(this).append(' | long tap!')\n      })\n      .singleTap(function(){\n        $(this).append(' | single tap!')\n      })\n    }\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/functional/touchcancel.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Zepto touch functional test</title>\n  <meta name=\"viewport\" content=\"maximum-scale=1,initial-scale=1,user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"../test.css\">\n  <script src=\"../../src/zepto.js\"></script>\n  <script src=\"../../src/event.js\"></script>\n  <script src=\"../../src/ie.js\"></script>\n  <script src=\"../../src/touch.js\"></script>\n</head>\n<body>\n  <h1>Zepto touch functional test</h1>\n\n  <p>\n    Double-tap and hold until the JavaScript alert occurs. After closing the\n    alert, tap again. Without touchcancel you will see a double tap instead of a tap.\n  </p>\n\n  <div id=\"touch_test\" style=\"width: 200px; height: 200px; background: #ddd\">\n    touch events test\n  </div>\n\n  <div id=\"browser\"> </div>\n\n  <script>\n    $('#browser').text(navigator.userAgent)\n\n    setTimeout(function(){\n      alert(\"Alert! Now tap again, you should see a tap!, not a double tap!\")\n    }, 3000)\n\n    $('body').bind('touchmove', function(e){ e.preventDefault() })\n    $('#touch_test')\n      .tap(function(){\n        $(this).append(' | tap!')\n      })\n      .doubleTap(function(){\n        $(this).append(' | double tap!')\n      })\n      .swipe(function(){\n        $(this).append(' | swipe!')\n      })\n      .swipeLeft(function(){\n        $(this).append(' | swipe left!')\n      })\n      .swipeRight(function(){\n        $(this).append(' | swipe right!')\n      })\n      .swipeUp(function(){\n        $(this).append(' | swipe up!')\n      })\n      .swipeDown(function(){\n        $(this).append(' | swipe down!')\n      })\n\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/fx.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Fx unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto event fx ie')\n    })()\n  </script>\n  <style>\n    @-webkit-keyframes animName {\n      0% {\n        -webkit-transform: rotate(180deg) scale(.8);\n        opacity: 1;\n      }\n      100% {\n        -webkit-transform: rotate(0deg) scale(1) translate3d(80px, 20px, 0);\n        opacity: 0.5;\n      }\n    }\n    @-moz-keyframes animName {\n      from {\n        -moz-transform: rotate(180deg) scale(.8) translate(0, 0);\n        opacity: 1;\n      }\n      to {\n        -moz-transform: rotate(0deg) scale(1) translate(80px, 20px);\n        opacity: 0.5;\n      }\n    }\n     @keyframes animName {\n      from {\n        transform: rotate(180deg) scale(.8) translate(0, 0);\n        opacity: 1;\n      }\n      to {\n        transform: rotate(0deg) scale(1) translate(80px, 20px);\n        opacity: 0.5;\n      }\n    }\n\n    #keyframetest {\n      opacity: 0.5;\n      -webkit-transform: translate3d(80px, 20px, 0);\n      -moz-transform: translate3d(80px, 20px, 0);\n      transform: translate3d(80px, 20px, 0);\n    }\n\n    .fixtures-left {\n      width: 120px;\n      float: left;\n    }\n    .fixtures-right {\n      margin-left: 120px;\n    }\n  </style>\n</head>\n<body>\n  <h1>Zepto Fx unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n\n  <div class=fixtures-left>\n    <div id=\"animtest_1\" style=\"width:40px;height:40px;background:red\"></div>\n    <div id=\"animtest_2\" style=\"width:40px;height:40px;background:red\"></div>\n    <div id=\"durationtest_1\" style=\"width:40px;height:40px;background:red\"></div>\n    <div id=\"durationtest_2\" style=\"width:40px;height:40px;background:red\"></div>\n    <div id=\"delaytest\" style=\"width:40px;height:40px;background:red\"></div>\n  </div>\n  <div class=fixtures-right>\n    <div id=\"durationtest_3\" style=\"width:40px;height:40px;background:red\"></div>\n    <div id=\"callbacktest\" style=\"width:40px;height:40px;background:red\"><div style=\"width:40px;height:40px;background:blue\"></div></div>\n    <div id=\"keyframetest\" style=\"width:40px;height:40px;background:red;\"></div>\n  </div>\n\n  <div id=\"anim_zero_duration_callback_test\"></div>\n\n  <script>\n  (function(){\n\n    function colorToHex (color) {\n      if (color.substr(0, 1) === '#') {\n        return color\n      }\n\n      var digits = /(.*?)rgb\\((\\d+), (\\d+), (\\d+)\\)/.exec( color.toLowerCase() ),\n          red    = parseInt(digits[2]),\n          green  = parseInt(digits[3]),\n          blue   = parseInt(digits[4]),\n          rgb = blue | (green << 8) | (red << 16)\n\n      return digits[1] + '#' + rgb.toString(16)\n    }\n\n    function defer(delay, fn) {\n      setTimeout(fn, delay || 0)\n    }\n\n    function camelize(str) {\n      return str.replace(/-+(.)?/g, function(_, chr){ return chr ? chr.toUpperCase() : '' })\n    }\n\n    var stylePrefix = $.fx.cssPrefix\n\n    Evidence.Assertions.assertStyle = function(expected, object, property, message) {\n      if (/^(transform|transition|animation)/.test(property)) property = stylePrefix + property\n      if (!('nodeName' in object)) object = object.get(0)\n\n      var actual = object.style[camelize(property)],\n        expression = expected instanceof RegExp ? expected.test(actual) : expected === actual\n\n      this._assertExpression(expression, message || 'Failed assertion.',\n        'Expected '+property+' to be '+expected+', got '+actual+'.\\n'+\n        $.fx.stylePrefix +':\\n' +\n        object.style.cssText)\n    }\n\n    Evidence('ZeptoFXTest', {\n\n      testAnimate: function(t){\n        var el = $('#animtest_1'), el2 = $('#animtest_2')\n\n        el.animate({\n          translate3d: '80px, 20px, 100px',\n          rotateZ: '90deg',\n          scale: '0.8',\n          opacity: 0.5,\n          backgroundColor: '#BADA55',\n          backgroundPositionY: '50%'\n        }, 200, 'ease-out')\n\n        el2.animate({\n          translate3d: '80px, 20px, 100px',\n          rotateZ: '-90deg',\n          backgroundColor: '#BADA55'\n        }, {\n          duration: 180,\n          easing: 'ease-out'\n        })\n\n        t.assertStyle('ease-out', el, 'transition-timing-function')\n        t.assertStyle('0.2s', el, 'transition-duration')\n        t.assertStyle(/\\bbackground-color\\b/, el, 'transition-property')\n        t.assertStyle(/\\bbackground-position-y\\b/, el, 'transition-property')\n        t.assertStyle(/\\btransform\\b/, el, 'transition-property')\n        t.assertStyle('0.18s', el2, 'transition-duration')\n\n        t.pause()\n        defer(250, function(){\n          t.resume(function(){\n            t.assertStyle('translate3d(80px, 20px, 100px) rotateZ(90deg) scale(0.8)', el, 'transform')\n            t.assertStyle('0.5', el, 'opacity')\n            t.assertStyle(/^(50%|center)$/, el, 'background-position-y')\n            t.assertEqual('#BADA55', colorToHex(el.get(0).style.backgroundColor).toUpperCase())\n          })\n        })\n      },\n\n      testDuration: function(t){\n        var el1 = $('#durationtest_1').anim({\n          translate3d: '80px, 20px, 100px',\n          rotateZ: '90deg',\n          opacity: 0.5\n        })\n\n        var el2 = $('#durationtest_2').anim({\n          translate3d: '80px, 20px, 100px',\n          rotateZ: '90deg',\n          opacity: 0.5\n        }, 0)\n\n        t.assertStyle('0.4s', el1, 'transition-duration', 'expected default duration')\n        t.assertStyle('', el2, 'transition-duration', 'expected no animation')\n      },\n\n      testDurationString: function(t){\n        var el = $('#durationtest_3').animate({\n          translate3d: '80px, 20px, 100px',\n          rotateZ: '90deg',\n          opacity: 0.5\n        }, 'fast')\n\n        t.assertStyle('0.2s', el, 'transition-duration', 'expected fast duration')\n      },\n\n      testDelay: function(t){\n        var duration = 100, delay = 50,\n          start = new Date().getTime()\n\n        t.pause()\n        var el1 = $('#delaytest').animate({\n          translate3d: '80px, 20px, 100px',\n          rotateZ: '90deg',\n          opacity: 0.5\n        }, {\n          duration: duration,\n          delay: delay,\n          complete: function() {\n            t.resume(function(){\n              var ms = new Date().getTime() - start\n              t.assert(ms >= (duration + delay),\n                'Fired too early (' + ms + ' ms) after having delay')\n            })\n          }\n        })\n\n        t.assertStyle('0.05s', el1, 'transition-delay', 'expected delay to be set')\n      },\n\n      testCallback: function(t){\n        var duration = 250, start = new Date().getTime()\n\n        t.pause()\n        $('#callbacktest').animate({\n          translate3d: '80px, 20px, 100px',\n          rotateZ: '90deg',\n          opacity: 0.5\n        }, duration, 'linear',\n        function(){\n          var context = this\n          t.resume(function(){\n            t.assert($(context).is('#callbacktest'), \"context for callback is wrong\")\n            t.assert((new Date().getTime() - start) >= duration, 'Fired too early')\n            t.assertStyle('', context, 'transition')\n            t.assertStyle('', context, 'transition-property')\n            t.assertStyle('', context, 'transition-timing-function')\n            t.assertStyle('', context, 'transition-duration')\n            t.assertStyle('', context, 'animation-name')\n            t.assertStyle('', context, 'animation-duration')\n          })\n        })\n      },\n\n      testCallbackWithoutEasing: function(t){\n        var duration = 250, start = new Date().getTime()\n\n        t.pause()\n        $('#callbacktest').animate({\n          translate3d: '10px, 20px, 400px',\n          rotateZ: '-90deg',\n          opacity: 0.2\n        }, duration,\n        function(){\n          var context = this\n          t.resume(function(){\n            t.assert($(context).is('#callbacktest'), \"context for callback is wrong\")\n            t.assert((new Date().getTime() - start) >= duration, 'Fired too early')\n            t.assertStyle('', context, 'transition')\n            t.assertStyle('', context, 'transition-property')\n            t.assertStyle('', context, 'transition-timing-function')\n            t.assertStyle('', context, 'transition-duration')\n            t.assertStyle('', context, 'animation-name')\n            t.assertStyle('', context, 'animation-duration')\n          })\n        })\n      },\n\n      testCallbackWithoutEasingAndWithoutDuration: function(t){\n        var duration = 250, start = new Date().getTime()\n\n        t.pause()\n        $('#callbacktest').animate({\n          translate3d: '30px, 220px, 40px',\n          rotateZ: '180deg',\n          opacity: 0.9\n        },\n        function(){\n          var context = this\n          t.resume(function(){\n            t.assert($(context).is('#callbacktest'), \"context for callback is wrong\")\n            t.assert((new Date().getTime() - start) >= duration, 'Fired too early')\n            t.assertStyle('', context, 'transition')\n            t.assertStyle('', context, 'transition-property')\n            t.assertStyle('', context, 'transition-timing-function')\n            t.assertStyle('', context, 'transition-duration')\n            t.assertStyle('', context, 'animation-name')\n            t.assertStyle('', context, 'animation-duration')\n          })\n        })\n      },\n\n      testBubbling: function(t){\n        $('#callbacktest div').anim({ opacity: 0.0 }, 0.1, 'linear')\n\n        var el = $('#anim_zero_duration_callback_test'),\n          callbackCalled = false\n\n        el.anim({ opacity: 0.5 }, 0, 'linear', function () {\n          t.assert($(this).is('#anim_zero_duration_callback_test'), \"context for callback is wrong\")\n          t.assertStyle('0.5', this, 'opacity')\n          callbackCalled = true\n        })\n\n        t.pause()\n        defer(30, function(){\n          t.resume(function(){\n            t.assert(callbackCalled)\n          })\n        })\n      },\n\n      testKeyFrameAnimation: function(t){\n        var el = $('#keyframetest').animate('animName', 200)\n\n        t.assertStyle('animName', el, 'animation-name')\n        t.assertStyle('0.2s',     el, 'animation-duration')\n        t.assertStyle('linear',   el, 'animation-timing-function')\n      },\n\n      testEmptyCollection: function(t){\n        t.assert($(null).animate({opacity:0}))\n      }\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/ie.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Touch unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('ie')\n    })()\n  </script>\n  <style>\n      body {\n          height: 50px;\n      }\n      body:after {\n          content: 'abc';\n      }\n  </style>\n</head>\n<body>\n  <h1>Zepto ie unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n\n  <script>\n    (function(){\n\n      Evidence('getComputedStyle', {\n\n        //Test to check if getComputedStyle does not blow up when no element are provided\n        testGetComputedStyleNoElem: function(t){\n          t.assertEqual(null, getComputedStyle())\n        },\n\n        //Test to check if computed styles for elements are returned correctly\n        testGetComputedStyle: function(t){\n          t.assertEqual('50px', getComputedStyle(document.body).height)\n        },\n\n        //Test to check if computed styles for pseudo-elements are returned correctly\n        //Assertion a bit hacky as IE returns the value in double quotes\n        testGetComputedStylePseudoElem: function(t){\n          t.assert(getComputedStyle(document.body, ':after').content.indexOf('abc') >  -1)\n        }\n\n      })\n    })()\n  </script>\n\n</body>\n</html>\n"
  },
  {
    "path": "test/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto tests</title>\n</head>\n<body>\n  <h1>Zepto tests</h1>\n  <p>\n    This file is provided for manual testing. If there's a test failure,\n    please report the user agent:\n    <b><script>document.write(navigator.userAgent)</script></b>\n  </p>\n  <p>\n    Start a test server with (you'll need to have <a href=\"https://npmjs.org\">npm</a> installed):<br>\n    <br>\n    <b>$ npm install</b> (if you haven't installed dependencies yet)<br>\n    <b>$ npm run-script start</b>\n    <br><br>\n    On your device, go to<br>\n    <b>http://your-ip-address:3000/test</b>\n  </p>\n  <p>\n    To start a test, click or tap it. Use the back button of\n    your browser to return to this index page.\n    Functional tests may require manual interaction.\n  </p>\n\n  <h2>Default modules unit tests</h2>\n  <ul>\n    <li><a href=\"zepto.html\">zepto</a> (core module, test this first!)</li>\n    <li><a href=\"event.html\">event</a></li>\n    <li><a href=\"ajax.html\">ajax</a></li>\n    <li><a href=\"form.html\">form</a></li>\n  </ul>\n\n  <h2>Other modules unit test</h2>\n  <ul>\n    <li><a href=\"fx.html\">fx</a></li>\n    <li><a href=\"detect.html\">detect</a></li>\n    <li><a href=\"data.html\">data</a></li>\n    <li><a href=\"selector.html\">selector</a></li>\n    <li><a href=\"stack.html\">stack</a></li>\n    <li><a href=\"touch.html\">touch</a></li>\n    <li><a href=\"deferred.html\">deferred</a></li>\n    <li><a href=\"ajax_deferred.html\">ajax + deferred</a></li>\n    <li><a href=\"callbacks.html\">callbacks</a></li>\n    <li><a href=\"ios3.html\">ios3</a></li>\n    <li><a href=\"ie.html\">ie</a></li>\n  </ul>\n\n  <h2>Functional tests</h2>\n  <ul>\n    <li><a href=\"functional/assets.html\">assets</a></li>\n    <li><a href=\"functional/fx.html\">fx</a></li>\n    <li><a href=\"functional/gesture.html\">gesture</a></li>\n    <li><a href=\"functional/touch.html\">touch</a></li>\n    <li><a href=\"functional/touchcancel.html\">touchcancel</a></li>\n  </ul>\n\n  <script>\n    // avoid caching\n    (function(){\n      [].slice.apply(document.getElementsByTagName('a')).forEach(function(link){\n        link.href += '?' + (+new Date)\n      })\n    })()\n  </script>\n</body>\n"
  },
  {
    "path": "test/ios3.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto iOS3 unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('ios3 zepto ie')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto iOS3 unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n  <script>\n  (function(){\n\n    Evidence('PolyfillTest', {\n\n      // test to see if we augment String.prototype.trim if not supported natively\n      testTrim: function(t){\n        t.assertEqual(\"blah\", \" blah \".trim())\n        t.assertEqual(\"bl \\n ah\", \" bl \\n ah \".trim())\n      },\n\n      // test to see if we augment Array.prototype.reduceif not supported natively\n      testReduce: function(t){\n        t.assertEqual(\n          10,\n          [0,1,2,3,4].reduce(function(p,c){ return p+c })\n        )\n\n        t.assertEqual(\n          20,\n          [0,1,2,3,4].reduce(function(p,c){ return p+c }, 10)\n        )\n\n        var flattened = [[0,1], [2,3], [4,5]].reduce(function(a,b){\n          return a.concat(b)\n        })\n\n        t.assertEqual(6, flattened.length)\n\n        for(var i=0;i<6;i++) t.assertEqual(i, flattened[i])\n      }\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/runner.js",
    "content": "(function() {\n  var fs = require('fs')\n  var system = require('system')\n  var args = system.args.slice(1)\n\n  var prefix = args.shift() || (\"file://\" + fs.workingDirectory + \"/\")\n\n  var suites\n  if (args.length > 0) {\n    suites = args\n  } else {\n    var modules = 'zepto ajax callbacks data deferred ajax_deferred detect touch event form fx selector stack'.split(/\\s+/)\n    suites = modules.map(function(name) {\n      return \"test/\" + name + \".html\"\n    })\n  }\n\n  var page = require('webpage').create()\n\n  page.onConsoleMessage = function(msg) {\n    console.log(msg)\n  }\n\n  page.onError = function(msg, trace) {\n    console.log('ERROR: ' + msg)\n  }\n\n  function waitFor(testFn, onReady, timeout) {\n    if (timeout == null) {\n      timeout = 30000\n    }\n    var start = new Date()\n    var interval = setInterval(function() {\n      if (testFn()) {\n        clearInterval(interval)\n        onReady()\n      } else if (new Date() - start > timeout) {\n        console.log(\"timed out.\")\n        phantom.exit(1)\n      }\n    }, 100)\n  }\n\n  function loadNextSuite() {\n    if (!suites.length) {\n      phantom.exit()\n    } else {\n      var url = suites.shift() + \"?verbosity=WARN\"\n      if (!/:\\/\\//.test(url)) {\n        url = prefix + url\n      }\n      page.open(url, function(status) {\n        if (status !== \"success\") {\n          console.log(\"failed opening \" + url)\n          return phantom.exit(1)\n        }\n        waitFor(function() {\n          return page.evaluate(function() {\n            var res = document.getElementById('results')\n            if (res) {\n              return /finished/.test(res.className)\n            }\n          })\n        }, function() {\n          var passed = page.evaluate(function() {\n            var res = document.getElementById('results')\n            var paths = location.pathname.split('/')\n            console.log((paths[paths.length - 1] + \" - \") + res.textContent)\n            return /passed/.test(res.className)\n          })\n          if (passed) {\n            loadNextSuite()\n          } else {\n            phantom.exit(1)\n          }\n        })\n      })\n    }\n  }\n\n  loadNextSuite()\n\n}).call(this)\n"
  },
  {
    "path": "test/selector.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Selector unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script src=\"../src/zepto.js\"></script>\n  <script src=\"../src/selector.js\"></script>\n  <script src=\"../src/ie.js\"></script>\n</head>\n<body>\n  <h1>Zepto Selector unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n  <div id=\"fixtures\">\n    <ul id=list><li>one</li><li>two</li></ul>\n    <div class=visibility id=vis>look at me!</div>\n    <div class=visibility id=invis style=\"display:none\">can't see me</div>\n    <ol id=child class=test>\n      <li><span>child1</span></li>\n      <li><span>child2</span>\n        <ul>\n          <li><span>child3</span></li>\n          <li><span>child4</span></li>\n        </ul>\n      </li>\n    </ol>\n  </div><!-- fixtures -->\n\n  <script>\n  (function(){\n    Evidence('SelectorTest', {\n      testFirst: function(t) {\n        var li = $('#list li:first')\n        t.assertEqual(1, li.size())\n        t.assertEqual('one', li.text())\n        t.assertEqual('two', $('#list li:eq(1)').text())\n      },\n      testLast: function(t) {\n        var li = $('#list li:last')\n        t.assertEqual(1, li.size())\n        t.assertEqual('two', li.text())\n      },\n      testParent: function(t) {\n        var list = $('#list li:parent')\n        t.assertEqual(1, list.size())\n        t.assertEqual('list', list.attr('id'))\n      },\n      testContains: function(t) {\n        t.assertEqual('two', $('#list li:contains(\"two\")').text())\n      },\n      testVisibility: function(t) {\n        t.assertEqual('vis', $('.visibility:visible').attr('id'))\n        t.assertEqual('invis', $('.visibility:hidden').attr('id'))\n      },\n      testIs: function(t) {\n        t.assert($('#list').is('ul'))\n        t.assert($('#vis').is(':visible'))\n        t.refute($('#invis').is(':visible'))\n      },\n      testChild: function(t) {\n        var items = $('#child').find('> li'),\n            results = items.map(function(){\n              return $(this).find('> span').text()\n            }).get()\n\n        t.assertEqual('child1 child2', results.join(' '))\n        t.assertEqual('test', $('#child').prop('class'))\n      },\n      testChildHas: function(t) {\n        var items = $('#child').find('> li:has(ul)'),\n            results = items.map(function(){\n              return $(this).find('> span').text()\n            }).get()\n\n        t.assertEqual('child2', results.join(' '))\n      },\n      testEmptyHref: function(t) {\n        var result, el = $('<div><a href=\"#\">one</a><a href=\"#\">two</a></div>')\n        result = el.find('a[href=#]')\n        t.assertEqual('one two', result.map(function(){ return $(this).text() }).get().join(' '))\n      }\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/server.coffee",
    "content": "express = require 'express'\napp     = express()\npath    = require 'path'\n\nmodule.exports = app\n\nproject_root = path.resolve(__dirname, '..')\napp.use express.static(project_root)\napp.use express.static(project_root + 'node_modules/mocha')\napp.use express.static(project_root + 'node_modules/chai')\n\napp.use express.bodyParser()\n\nmime = (req) ->\n  type = req.headers['content-type'] or ''\n  type.split(';')[0]\n\ndump = (obj) ->\n  obj = '' unless obj\n  obj = JSON.stringify(obj) if obj and typeof obj isnt \"string\"\n  obj\n\ncleanTrace = (traceStr) ->\n  trace = traceStr.split(\"\\n\")\n  filtered = []\n  for line in trace\n    if /\\.html:/.test line\n      line = line.replace(/^.+?@/, '')\n      line = line.replace(/http:\\/\\/.+?\\//, '')\n      line = line.replace(/(:\\d+):\\d+$/, '$1')\n      filtered.push line\n  filtered\n\nbrowser = (ua) ->\n  if m = ua.match /(Android .+?);/\n    m[1]\n  else if m = ua.match /(iPhone|iPad|iPod).*?OS ([\\d_]+)/\n    'iOS ' + m[2].replace(/_/g, '.')\n  else if m = ua.match /(Chrome\\/[\\d.]+)/\n    m[1].replace '/', ' '\n  else if m = ua.match /(Safari\\/[\\d.]+)/\n    m[1].replace '/', ' '\n  else if m = ua.match /(Firefox\\/[\\d.]+)/\n    m[1].replace '/', ' '\n  else if m = ua.match /\\bMS(IE [\\d.]+)/\n    m[1]\n  else\n    ua\n\napp.all '/', (req, res) ->\n  res.redirect '/test'\n\napp.all '/test/echo=?', (req, res) ->\n  res.set 'Cache-Control', 'no-cache'\n  res.send \"\"\"\n           #{req.method} ?#{dump(req.query)}\n           content-type: #{mime(req)}\n           accept: #{req.headers['accept']}\n           #{dump(req.body)}\n           \"\"\"\n\napp.get '/test/jsonp', (req, res) ->\n  res.jsonp\n    query: req.query\n    hello: 'world'\n\n# send JSONP response despite callback not being set\napp.get '/test/jsonpBlah', (req, res) ->\n  res.set 'Content-Type', 'text/javascript'\n  res.send 'blah()'\n\napp.get '/test/json', (req, res) ->\n  res.set 'Cache-Control', 'no-cache'\n  expectedType = req.headers['accept']\n  if expectedType is '*/*' or /json/.test expectedType\n    if req.query.invalid\n      res.set 'Content-Type', 'application/json'\n      res.send 'invalidJSON'\n    else\n      res.json\n        query: req.query\n        hello: 'world'\n  else\n    res.send 400, 'FAIL'\n\napp.get '/test/taintedJSON', (req, res) ->\n  res.set 'Content-Type', 'application/json'\n  res.send 'while(1);{\"hello\" : \"world\"}'\n\napp.post '/test/create', (req, res) ->\n  res.json\n    action: 'created'\n    query: req.query\n    payload: req.body\n\napp.all '/test/slow', (req, res) ->\n  setTimeout ->\n    res.jsonp result: 'ok'\n  , 200\n\napp.get '/test/cached', (req, res) ->\n  res.set 'Cache-Control', 'max-age=2'\n  res.set 'Expires', new Date(Date.now() + 2000).toUTCString()\n  now = new Date()\n  res.send now.getTime().toString()\n\napp.get '/test/auth', (req, res) ->\n  if req.headers.authorization is 'Basic emVwdG86ZG9nZQ=='\n    res.send 200\n  else\n    res.set 'WWW-Authenticate', \"Basic realm=\\\"#{req.query.realm}\\\"\"\n    res.send 401\n\napp.post '/test/log', (req, res) ->\n  params = req.body\n  trace = cleanTrace params.trace\n  console.log \"[%s] %s: %s\", browser(req.headers['user-agent']), params.name, params.message\n  console.log trace.join(\"\\n\").replace(/^/mg, '  ') if trace.length\n  res.send 200\n\napp.all '/test/error', (req, res) ->\n  res.send 500, 'BOOM'\n\nif process.argv[1] is __filename\n  port = process.argv[2]\n  unless port\n    port = 3000\n    console.log \"Listening on port #{port}\"\n  app.listen port\n"
  },
  {
    "path": "test/stack.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Stack unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto stack ie')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto Stack unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n  <div id=\"fixtures\">\n\n  <div id=\"end_test\">\n    <div class=\"end_one\"><b><span></span></b></div>\n    <div class=\"end_two\"><b><span>1</span><span>2</span></b></div>\n  </div>\n\n  <div id=\"andself_test\">\n    <div class=\"one\"></div>\n    <div class=\"two\"></div>\n    <div class=\"three\"></div>\n    <div class=\"four\"></div>\n  </div>\n\n  </div><!-- fixtures -->\n\n  <script>\n  (function(){\n\n    Evidence('ZeptoTest', {\n\n      testEnd: function (t) {\n        t.assert($().end().length == 0)\n\n        var $endTest = $('#end_test')\n        var $endTest2 = $('#end_test').find('div').find('span').end().end()\n        t.assertEqual($endTest.length, $endTest2.length)\n        t.assertEqual($endTest.get(0), $endTest2.get(0))\n      },\n\n      testAndSelf: function (t) {\n        var testDiv  = $('#andself_test'),\n            secondEl = $('.two', testDiv),\n            thirdEl  = $('.three', testDiv),\n            nextAndSelf = secondEl.next().andSelf()\n\n        t.assert(secondEl.get(0), nextAndSelf.get(0))\n        t.assert(thirdEl.get(0),  nextAndSelf.get(1))\n      }\n\n    })\n\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/test.css",
    "content": "* {\n  font-family: -apple-system-font, Helvetica, sans-serif;\n}\nbody {\n  padding: 1em;\n}\na:link, a:visited { color: darkblue; }\n#results.failed em { font-style: normal; color: crimson; }\n#results.passed em { font-style: normal; color: darkgreen; }\n#fixtures {\n  position: absolute;\n  top: -10000px;\n  left: -10000px;\n}\n#nav {\n  list-style: none;\n  padding: 0;\n  margin: 2em 0 0 0;\n  font-size: 12px;\n  max-width: 30em;\n}\n#nav a {\n  padding: .8em 1.5em;\n  background: #eee;\n  border-top: 2px solid white;\n  text-decoration: none;\n  text-transform: uppercase;\n  letter-spacing: .1em;\n  display: block;\n  color: #555;\n}\n#nav .current a { background: #ccc; color: black; }\n#nav a:active { background: #555; color: white; }\n\nul {\n  padding: 0;\n}\n\nli {\n  list-style-type: none;\n  padding: 0 0 15px;\n}\n\nli a {\n  font-size: 16px;\n  border: 1px solid darkblue;\n  padding: 3px 10px;\n  text-decoration: none;\n}\nli a:visited {\n  border-color: #888;\n  color: #aaa;\n}\n\n@media only screen and (max-device-width:480px) {\n  body { margin: 7px; font-size: small; }\n  h1 { margin: 0; }\n  h1, #results { text-align: center; }\n  #results { min-height: 3em; }\n  #nav { font-size: 14px; max-width: auto; }\n}\n"
  },
  {
    "path": "test/touch.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Touch unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto event ie touch')\n    })()\n  </script>\n</head>\n<body>\n  <h1>Zepto Touch unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n\n  <style>\n    #test {\n      position: absolute;\n      left: 0;\n      top: 0;\n      width: 100px;\n      height: 50px;\n    }\n  </style>\n\n  <script>\n  (function(){\n    var emitEvent, tests, lastLoaded\n\n    // Fire a simulated touch event.\n    // While it is possible to fire real touch events,\n    // there are cross-browser issues, and this way we\n    // can test touch events in browsers that don't\n    // actually support touch input (like desktop Safari).\n    //\n    // Zepto's touch module only uses the `pageX/Y` and `target`\n    // properties of the first touch in the `touches` TouchList\n    function emitTouchEvent(type, element, x, y) {\n      var event = document.createEvent('Event'),\n        touch = { pageX: x, pageY: y, target: element }\n\n      event.initEvent('touch'+type, true, true)\n      event.touches = [touch]\n\n      element.dispatchEvent(event)\n    }\n\n    // IE 10, Windows Phone 8\n    // MSPointer events, same idea, different implementation.\n    // For compatibility accepts the same arguments as `touchEvent`\n    // (touch event names will be mapped to MSPointer event names)\n    function emitMSPointerEvent(type, element, x, y) {\n      var event = document.createEvent('Event'),\n        eventMap = { start: 'Down', move: 'Move', end: 'Up'}\n\n      event.initEvent('MSPointer'+eventMap[type], true, true)\n      event.pageX = x\n      event.pageY = y\n      event.pointerType = 666\n      event.MSPOINTER_TYPE_TOUCH = 666\n      event.isPrimary = true\n\n      element.dispatchEvent(event)\n    }\n\n    // IE 11\n    // Pointer events, same idea again, yet different implementation.\n    // For compatibility accepts the same arguments as `touchEvent`\n    // (touch event names will be mapped to pointer event names)\n    function emitPointerEvent(type, element, x, y) {\n      var event = document.createEvent('Event'),\n        eventMap = { start: 'down', move: 'move', end: 'up'}\n\n      event.initEvent('pointer'+eventMap[type], true, true)\n      event.pageX = x\n      event.pageY = y\n      event.pointerType = 'touch'\n      event.isPrimary = true\n\n      element.dispatchEvent(event)\n    }\n\n    function down(element, x, y) {\n      emitEvent('start', element, x, y)\n    }\n    function move(element, x,y) {\n      emitEvent('move', element, x, y)\n    }\n    function up(element) {\n      emitEvent('end', element)\n    }\n\n    tests = {\n      setUp: function(){\n        emitEvent = this.emitEvent\n        this.setupTouchLibrary()\n        $('<div id=test>').appendTo('body')\n      },\n\n      tearDown: function(){\n        $('#test').off()\n        $('#test').remove()\n      },\n\n      testTap: function(t){\n        var count = 0, element = $('#test').get(0)\n\n        $('#test').on('tap', function(){\n          count++\n        })\n\n        down(element, 10, 10)\n        up(element)\n\n        t.pause()\n        setTimeout(function(){\n          t.resume(function(){\n            t.assertEqual(1, count)\n          })\n        }, 50)\n      },\n\n      testOnlyOneTouchAPIIsActive: function(t){\n        var count = 0, element = $('#test').get(0)\n\n        $('#test').on('tap', function(){\n          count++\n        })\n\n        emitTouchEvent('start', element, 10, 10)\n        emitPointerEvent('start', element, 10, 10)\n        emitMSPointerEvent('start', element, 10, 10)\n        emitTouchEvent('end', element)\n        emitPointerEvent('end', element)\n        emitMSPointerEvent('end', element)\n\n        t.pause()\n        setTimeout(function(){\n          t.resume(function(){\n            t.assertEqual(1, count)\n          })\n        }, 50)\n      },\n\n      testScrollDoesNotFireTap: function(t){\n        var element = $('#test').get(0), count = 0\n\n        $('#test').on('tap', function () {\n          count++\n        })\n\n        down(element, 0, 0)\n        move(element, 0, 20)\n        move(element, 0, 20)\n        up(element)\n\n        t.pause()\n        setTimeout(function(){\n          t.resume(function(){\n            t.assertEqual(0, count)\n          })\n        }, 50)\n      },\n\n      testSingleTapDoesNotInterfereWithTappingTwice: function(t){\n        var count = 0, element = $('#test').get(0)\n\n        $('#test').on('tap', function(){\n          count++\n        })\n\n        down(element, 10, 10)\n        up(element)\n\n        t.pause()\n        setTimeout(function(){\n          down(element, 10, 10)\n          up(element)\n\n          t.resume(function(){\n            t.pause()\n\n            setTimeout(function(){\n              t.resume(function(){\n                t.assertEqual(2, count)\n              })\n            }, 200)\n          })\n        }, 200)\n      },\n\n      // should be fired if there is one tap within 250ms\n      testSingleTap: function(t){\n        var singleCount = 0, doubleCount = 0, element = $('#test').get(0)\n\n        $('#test').on('singleTap', function(){\n          singleCount++\n        }).on('doubleTap', function(){\n          doubleCount++\n        })\n\n        down(element, 10, 10)\n        up(element)\n\n        t.pause()\n        setTimeout(function(){\n          t.resume(function(){\n            t.assertEqual(1, singleCount)\n            t.assertEqual(0, doubleCount)\n          })\n        }, 300)\n      },\n\n      // should be fired if there are two taps within 250ms\n      testDoubleTap: function(t){\n        var singleCount = 0, doubleCount = 0, element = $('#test').get(0)\n\n        $('#test').on('singleTap', function(){\n          singleCount++\n        }).on('doubleTap', function(){\n          doubleCount++\n        })\n\n        down(element, 10, 10)\n        up(element)\n\n        t.pause()\n        setTimeout(function(){\n          down(element, 12, 12)\n          up(element)\n\n          t.resume(function(){\n            t.pause()\n\n            setTimeout(function(){\n              t.resume(function(){\n                t.assertEqual(0, singleCount)\n                t.assertEqual(1, doubleCount)\n              })\n            }, 100)\n          })\n        }, 100)\n      },\n\n      // should be fired if the finger is down in the same location for >750ms\n      testLongTap: function(t){\n        var count = 0, element = $('#test').get(0)\n\n        $('#test').on('longTap', function(){\n          count++\n        })\n\n        down(element, 10, 10)\n\n        t.pause()\n        setTimeout(function(){\n          up(element)\n\n          t.resume(function(){\n            t.assertEqual(1, count)\n          })\n        }, 900)\n      },\n\n      testLongTapDoesNotFireIfFingerIsMoved: function(t){\n        var count = 0, element = $('#test').get(0)\n\n        $('#test').on('longTap', function(){\n          count++\n        })\n\n        down(element, 10, 10)\n\n        t.pause()\n        setTimeout(function(){\n          move(element, 50, 10)\n          t.resume(function(){\n            t.pause()\n            setTimeout(function(){\n              up(element)\n              t.resume(function(){\n                t.assertEqual(0, count)\n              })\n            }, 450)\n          })\n        }, 450)\n      },\n\n      testSwipe: function(t){\n        var swipeCount = 0, element = $('#test').get(0)\n\n        $('#test').on('swipe', function(){\n          swipeCount++\n        })\n\n        down(element, 10, 10)\n\n        t.pause()\n        setTimeout(function(){\n          move(element, 70, 10)\n          up(element)\n\n          t.resume(function(){\n            t.pause()\n\n            setTimeout(function(){\n              t.resume(function(){\n                t.assertEqual(1, swipeCount)\n              })\n            }, 50)\n          })\n        }, 50)\n      },\n\n      testTapDoNotFireWhenMoveToPointAndBack: function (t) {\n        var tapCount = 0, element = $('#test').get(0)\n\n        $('#test').on('tap', function(){\n          tapCount++\n        })\n        down(element, 10, 10)\n        move(element, 60, 10)\n\n        t.pause()\n        setTimeout(function(){\n          t.resume(function(){\n            move(element, 10, 10)\n            up(element)\n            t.pause()\n            setTimeout(function(){\n              t.resume( function () {\n                t.assertEqual(0, tapCount)\n              })\n            }, 100)\n          })\n        }, 100)\n      }\n\n      // TODO: test swipes in specific directions\n    }\n\n    Evidence('TouchTest', $.extend({\n      setupTouchLibrary: function(){\n        console.info('Setting up touch library for TouchEvent test')\n        $.touch.setup({\n          'down': 'touchstart', 'up': 'touchend',\n          'move': 'touchmove', 'cancel': 'touchcancel'\n        })\n      },\n      emitEvent: emitTouchEvent\n    }, tests))\n\n    Evidence('PointerTest', $.extend({\n      setupTouchLibrary: function(){\n        console.info('Setting up touch library for PointerEvent test')\n        $.touch.setup({\n          'down': 'pointerdown', 'up': 'pointerup',\n          'move': 'pointermove', 'cancel': 'pointercancel'\n        })\n      },\n      emitEvent: emitPointerEvent\n    }, tests))\n\n    Evidence('MSPointerTest', $.extend({\n      setupTouchLibrary: function(){\n        console.info('Setting up touch library for MSPointerEvent test')\n        $.touch.setup({\n          'down': 'MSPointerDown', 'up': 'MSPointerUp',\n          'move': 'MSPointerMove', 'cancel': 'MSPointerCancel'\n        })\n      },\n      emitEvent: emitMSPointerEvent\n    }, tests))\n\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "test/zepto.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n  <link rel=\"stylesheet\" href=\"test.css\">\n  <title>Zepto Core unit tests</title>\n  <script src=\"../vendor/evidence.js\"></script>\n  <script src=\"evidence_runner.js\"></script>\n  <script>\n    // avoid caching\n    (function(){\n      function load(scripts){\n        scripts.split(' ').forEach(function(script){\n          document.write('<script src=\"../src/'+script+'.js?'+(+new Date)+'\"></scr'+'ipt>')\n        })\n      }\n\n      load('zepto event ie')\n    })()\n  </script>\n  <style>\n    #get_style_element {\n      font-size: 48px;\n      color: black;\n    }\n  </style>\n</head>\n<body>\n  <h1>Zepto Core unit tests</h1>\n  <p id=\"results\">\n    Running… see browser console for results\n  </p>\n  <div id=\"fixtures\">\n\n  <div id=\"some_element\"></div>\n  <p>\n    <span class=\"yay\">yay</span>\n    <span></span>\n    <span class=\"nay\" id=\"nay\">nay</span>\n  </p>\n\n  <div id=\"toggle_element\"></div>\n\n  <div id=\"get_style_wrapper\" style=\"font-size: 16px;\">\n    <div id=\"get_style_element\">Derp</div>\n  </div>\n\n  <div class=\"replacewith\">\n    <div class=\"inner first\">Hello</div>\n    <div class=\"inner second\">And</div>\n    <div class=\"inner third\">Goodbye</div>\n  </div>\n\n  <div id=\"attr_1\" data-id=\"someId1\" data-name=\"someName1\"></div>\n  <div id=\"attr_2\" data-id=\"someId2\" data-name=\"someName2\"></div>\n  <div id=\"attr_remove\" data-name=\"boom\"></div>\n  <div id=\"attr_remove_multi\" data-id=\"someId1\" data-name=\"someName1\"></div>\n  <form><input id=\"attr_val\" value=\"Hello World\"></form>\n\n  <div id=\"data_attr\" data-foo=\"bar\" data-foo-bar=\"baz\" data-empty></div>\n\n  <form id=\"attr_with_text_input\">\n  </form>\n\n  <label for=\"prop_test2\" id=\"prop_test1\"></label>\n  <input id=\"prop_test2\" type=\"text\" tabindex=\"-1\" maxlength=\"10\" readonly class=\"propTest\" />\n  <table id=\"prop_test3\" cellspacing=\"10\" cellpadding=\"5\">\n    <tr>\n      <td id=\"prop_test4\" rowspan=\"2\"></td>\n      <td></td>\n    </tr>\n    <tr>\n      <td></td>\n    </tr>\n    <tr>\n      <td id=\"prop_test5\" colspan=\"2\"></td>\n    </tr>\n  </table>\n  <img id=\"prop_test6\" usemap=\"#imgMap\" />\n  <map name=\"imgMap\">\n  </map>\n  <div id=\"prop_test7\" contenteditable=\"true\"></div>\n  <input id=\"prop_test8\" type=\"checkbox\" checked />\n\n  <div class=\"htmltest\" id=\"htmltest1\"></div>\n  <div class=\"htmltest\" id=\"htmltest2\"></div>\n  <div id=\"htmltest3\"></div>\n  <table id=\"htmltest4\"></table>\n\n  <div id=\"texttest1\" class=\"texttest\"><span>Here <strong>is</strong> some text</span></div>\n  <div id=\"texttest2\" class=\"texttest\">And <em>some more</em></div>\n  <div id=\"texttest3\" class=\"texttest\"></div>\n\n  <div id=\"beforeafter_container\"><div id=\"beforeafter\"></div></div>\n  <div id=\"appendtoprependto_container\"><div id=\"appendtoprependto\"></div></div>\n  <div id=\"insertbeforeinsertafter_container\"><div id=\"insertbeforeinsertafter\"></div></div>\n\n  <div id=\"empty_test\">\n    <div id=\"empty_1\"></div>\n    <div id=\"empty_2\"></div>\n    <div id=\"empty_3\"></div>\n    <span id=\"empty_4\">test</span>\n  </div>\n\n  <p id=\"find1\">\n    <span class=\"findme\">1</span>\n    <span class=\"findme\">2</span>\n    <b>3<span class=\"findme\">4</span></b>\n    <span class=\"findme\">5<span>6</span></span>\n  </p>\n\n  <p id=\"find2\">\n    <span>1</span>\n    <span>2</span>\n    <span>3<span>4</span></span>\n    <span>5<span>6</span></span>\n  </p>\n\n  <div id=\"eachtest\">\n    <span></span><b></b><br>\n  </div>\n\n  <div style=\"position:absolute;width:100px;height:50px\" id=\"offset\">test</div>\n\n  <ul id=\"parents\">\n    <li id=\"li1\">\n      <ul id=\"nested\">\n        <li id=\"li2\">one</li>\n        <li>two</li>\n        <li>three</li>\n      </ul>\n      <ul>\n        <li></li>\n      </ul>\n    </li>\n  </ul>\n\n  <ul id=\"childrenTest\">\n    <li class=\"child one\"><a class=\"childOfOne\" href=\"#\">gchild1</a></li>\n    <li class=\"child two\"><a class=\"childOfTwo\" href=\"#\">gchild2</a></li>\n    <li class=\"child three\"><a class=\"childOfThree\" href=\"#\">gchild3</a></li>\n    <li class=\"child four\"><a class=\"childOfFour\" href=\"#\">gchild4</a></li>\n  </ul>\n\n  <ul id=\"contentsTest\">1<span>2</span><span id=\"contentsEmptyTest\"></span></ul>\n\n  <iframe id=\"contentsIframeTest\" src=\"fixtures/iframe_document.html\"></iframe>\n\n  <ul id=\"siblingsTest\">\n    <li class=\"child one\"><span class=\"b\"></span><em></em><b></b></li>\n    <li class=\"child two\"><span class=\"c\"></span><em></em><b></b></li>\n    <li class=\"child three\"><span class=\"d\"></span><em></em><b></b></li>\n    <li class=\"child four\"><span class=\"e\"></span></li>\n  </ul>\n\n  <ul id=\"notTest\">\n    <li class=\"child one\"><span class=\"b\"></span></li>\n    <li class=\"child two\"><span class=\"c\"></span></li>\n    <li class=\"child three\"><span class=\"d\" id=\"notTestExclude\"></span></li>\n    <li class=\"child four\"><span class=\"e\"></span></li>\n  </ul>\n\n  <div id=\"addTest\">\n    <span class=\"add_span\"></span>\n    <span class=\"add_span\"></span>\n    <span class=\"add_span\"></span>\n    <span class=\"add_span_exclude\"></span>\n    <div id=\"addTestDiv\"></div>\n  </div>\n\n  <style>\n    .hidden {\n      display: none;\n    }\n\n    #show_hide_span1,\n    #show_hide_span2 {\n      display: block;\n    }\n\n    #show_hide_div1 {\n      display: inline-block;\n    }\n  </style>\n\n  <div id=\"show_hide_div1\" style=\"display:none\"></div>\n  <div id=\"show_hide_div2\" class=\"hidden\"></div>\n  <div id=\"show_hide_div3\"></div>\n\n  <span id=\"show_hide_span1\" style=\"display:none\"></span>\n  <span id=\"show_hide_span2\" class=\"hidden\"></span>\n  <span id=\"show_hide_span3\"></span>\n\n  <div class=\"filtertest\" id=\"filtertest1\"></div>\n  <div class=\"filtertest\" id=\"filtertest2\"></div>\n\n  <div id=\"delegate_test\"><span class=\"first-level\"><span class=\"second-level\">hi</span></span></div>\n  <div id=\"undelegate_test\"><span class=\"first-level\"><span class=\"second-level\">hi</span></span></div>\n\n  <div id=\"delegate_blur_test\"><input type=\"text\"></div>\n  <div id=\"delegate_focus_test\"><input type=\"text\"></div>\n\n  <div id=\"another_element\"></div>\n\n  <div id=\"namespace_test\"></div>\n\n  <input type=\"text\" id=\"BooleanInput\" required />\n\n  <form id=\"some_form\"></form>\n\n  <div class=\"replace_test_div\">test</div>\n\n  <div id=\"wrap_test\"><span>hi</span><a></a><span>hello</span></div>\n\n  <div id=\"wrapall_test\"><b></b><span>hi</span><span>hello</span><i></i></div>\n\n  <div id=\"wrapinner_test\">1<span>2</span><span id=\"wrapinner_empty_test\"></span></div>\n\n  <div id=\"unwrap_test\">\n    <div class=\"unwrap_one\"><b><span></span></b></div>\n    <div class=\"unwrap_two\"><b><span>1</span><span>2</span></b></div>\n  </div>\n\n  <div id=\"slice_test\">\n    <div class=\"slice1\"></div>\n    <div class=\"slice2\"></div>\n    <div class=\"slice3\"></div>\n  </div>\n\n  <div id=\"eq_test\">\n    <div class=\"eq0\"></div>\n    <div class=\"eq1\"></div>\n    <div class=\"eq2\"></div>\n  </div>\n\n  <div id=\"end_test\">\n    <div class=\"end_one\"><b><span></span></b></div>\n    <div class=\"end_two\"><b><span>1</span><span>2</span></b></div>\n  </div>\n\n  <div id=\"andself_test\">\n    <div class=\"one\"></div>\n    <div class=\"two\"></div>\n    <div class=\"three\"></div>\n    <div class=\"four\"></div>\n  </div>\n\n  <div id=\"index_test\">\n    <div class=\"index0\"></div>\n    <div class=\"index1\"></div>\n  </div>\n\n  <div id=\"trigger_handler\">\n    <form method=\"get\">\n    </form>\n  </div>\n\n  <svg></svg>\n\n  <iframe src=\"fixtures/iframe_document.html\"></iframe>\n\n  <iframe id=\"link_target_iframe\" name=\"link_target_iframe\" width=\"10\" height=\"10\"></iframe>\n  <a id=\"link_that_will_be_prevented\" href=\"fixtures/iframe_document.html\" target=\"link_target_iframe\"></a>\n\n  <div id=\"test_dollar_with_shadow_root\" style=\"display:none;\"></div>\n\n  </div><!-- fixtures -->\n\n  <script>\n  (function(){\n\n    function click(el){\n      var event = document.createEvent('MouseEvents')\n      event.initMouseEvent('click', true, true, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null)\n      el.dispatchEvent(event)\n    }\n\n    function mousedown(el){\n      var event = document.createEvent('MouseEvents')\n      event.initMouseEvent('mousedown', true, true, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null)\n      el.dispatchEvent(event)\n    }\n\n    function outerHTML(node) {\n      return node.outerHTML || (function(n) {\n        var div = document.createElement('div')\n        div.appendChild(n.cloneNode(true))\n        var html = div.innerHTML\n        div = null\n        return html\n      })(node)\n    }\n\n    function testDocumentFragmentOrShadowRootContext($fragment, t) {\n      t.assertLength(1, $fragment)\n      t.assertEqual(Node.DOCUMENT_FRAGMENT_NODE, $fragment.get(0).nodeType)\n\n      var fragment = $fragment[0]\n      var $div = $('<div id=\"child\"><div class=\"inner\"></div></div>')\n\n      t.assertLength(0, $('#child', fragment))\n\n      fragment.appendChild($div[0])\n\n      var expectedElement = fragment.querySelector('#child')\n\n      t.assertLength(1, $('#child', fragment))\n      t.assertEqual($div[0], $('#child', fragment).get(0))\n      t.assertEqual(expectedElement, $('#child', fragment).get(0))\n\n      expectedElement = fragment.querySelector('.inner')\n\n      t.assertLength(1, $('.inner', fragment))\n      t.assertEqual(expectedElement, $('.inner', fragment).get(0))\n\n      var expectedElements = fragment.querySelectorAll('div')\n\n      t.assertLength(2, $('div', fragment))\n      t.assertEqual(expectedElements[0], $('div', fragment).get(0))\n      t.assertEqual(expectedElements[1], $('div', fragment).get(1))\n    }\n\n    var globalVarSetFromReady = \"\"\n    $(document).ready(function(){ globalVarSetFromReady = 'hi!' })\n\n    var globalVarSetFromReady2 = \"\"\n    $(function(){ globalVarSetFromReady2 = 'hi!' })\n\n    var globalVarSetFromReady3 = \"\"\n    $(document).on('ready', function(){ globalVarSetFromReady3 = 'hi!' })\n\n    var globalVarSetFromReady4 = \"\"\n    $(document).on('foo ready bar', function(){ globalVarSetFromReady4 = 'hi!' })\n\n    Evidence.Assertions.assertSame = function(expected, actual, message) {\n      var expectedKeyCount = 0, actualKeyCount = 0, key, passed = true\n      for (key in expected) expectedKeyCount++\n      for (key in actual) actualKeyCount++\n\n      if (expectedKeyCount == actualKeyCount)\n        for (key in expected)\n          passed &= expected[key] == actual[key]\n      else\n        passed = false\n\n      this._assertExpression(passed, message || 'Failed assertion.',\n        'Expected %o to be the same as %o.', actual, expected)\n    }\n\n    Evidence.Assertions.assertLength = function(expected, object, message) {\n      var actual = object.length\n      this._assertExpression(expected === actual, message || 'Failed assertion.',\n        'Expected length %d, got %d.', expected, actual)\n    }\n\n    Evidence.Assertions.assertZeptoCollection = function(expectedLength, object, message) {\n      if (!$.zepto.isZ(object))\n        this._assertExpression(false, message || 'Failed assertion.',\n          'Expected %o to be a Zepto collection.', object)\n      else\n        this.assertLength(expectedLength, object, message)\n    }\n\n    Evidence.Assertions.assertEqualCollection = function(expectedCollection, actualCollection, message) {\n      var expected = expectedCollection, actual = actualCollection,\n          passed = expected.length == actual.length\n\n      if (typeof expected.get == 'function') expected = expected.get()\n      if (typeof actual.get == 'function') actual = actual.get()\n\n      if (passed) for (var i=0; i<expected.length; i++) passed &= expected[i] == actual[i]\n\n      this._assertExpression(passed, message || 'Failed assertion.',\n        'Expected %o, got %o.', expected, actual)\n    }\n\n    Evidence('ZeptoTest', {\n\n      testIsFunction: function(t) {\n        t.assertTrue($.isFunction(function(){}))\n        t.assertTrue($.isFunction(new Function()))\n\n        var f1 = function(){}\n        function f2(){}\n\n        t.assertTrue($.isFunction(f1))\n        t.assertTrue($.isFunction(f2))\n\n        t.assertFalse($.isFunction())\n        t.assertFalse($.isFunction(undefined))\n        t.assertFalse($.isFunction({}))\n        t.assertFalse($.isFunction(new Object()))\n        t.assertFalse($.isFunction(null))\n        t.assertFalse($.isFunction([]))\n        t.assertFalse($.isFunction(1))\n        t.assertFalse($.isFunction('a'))\n        t.assertFalse($.isFunction(new Date()))\n        t.assertFalse($.isFunction(window))\n        t.assertFalse($.isFunction($('body')))\n      },\n\n      testIsPlainObject: function(t) {\n        t.assertTrue($.isPlainObject(new Object()), 'Object is plain object')\n        t.assertTrue($.isPlainObject({}), '{} is plain object')\n        t.assertTrue($.isPlainObject({one : 1}), '{one : 1} is plain object')\n        t.assertTrue($.isPlainObject({one : 1, two: [1,2]}), '{one : 1, two: [1,2]} is plain object')\n\n        t.assertFalse($.isPlainObject(new Array()), 'Array object is not plain object')\n        t.assertFalse($.isPlainObject([]), '[] is not plain object')\n        t.assertFalse($.isPlainObject(null), 'null is not plain object')\n        t.assertFalse($.isPlainObject(), 'undefined is not plain object')\n        t.assertFalse($.isPlainObject(new String()), 'empty String object is not plain object')\n        t.assertFalse($.isPlainObject(new String('moe')), 'String object is not plain object')\n        t.assertFalse($.isPlainObject(''), 'the empty string is not plain object')\n        t.assertFalse($.isPlainObject('moe'), 'a string is not plain object')\n        t.assertFalse($.isPlainObject(new RegExp('test')), 'RegExp object is not plain object')\n        t.assertFalse($.isPlainObject(/test/), 'regex is not plain object')\n        t.assertFalse($.isPlainObject(new Boolean(true)), 'Boolean object is not plain object')\n        t.assertFalse($.isPlainObject(true), 'a boolean is not plain object')\n        t.assertFalse($.isPlainObject(new Number(2)), 'Number object is not plain object')\n        t.assertFalse($.isPlainObject(2), 'a number is not plain object')\n        t.assertFalse($.isPlainObject(new Function()), 'Function object is not plain object')\n        t.assertFalse($.isPlainObject(function() {}), 'a function is not plain object')\n        t.assertFalse($.isPlainObject(new Date()), 'Date object is not plain object')\n\n        t.assertFalse($.isPlainObject(window), 'window is not a plain object')\n        t.assertFalse($.isPlainObject($(\"html\")[0]), 'html node is not a plain object')\n\n        var F = function(){}, obj\n        F.prototype = {'a':1}\n        obj = new F()\n        t.assertFalse($.isPlainObject(obj), 'function with prototype is not a plain object')\n      },\n\n      testIsWindow: function(t){\n        t.assertFalse($.isWindow())\n        t.assertFalse($.isWindow({}))\n        t.assertFalse($.isWindow(document.body))\n        t.assertTrue($.isWindow(window))\n        t.assertTrue($.isWindow($('iframe').get(0).contentWindow))\n      },\n\n      testDollarIsNumeric: function(t){\n        t.assertTrue($.isNumeric( '-10' ))\n        t.assertTrue($.isNumeric( '0' ))\n        t.assertTrue($.isNumeric( 0xFF ))\n        t.assertTrue($.isNumeric( '0xFF' ))\n        t.assertTrue($.isNumeric( '8e5' ))\n        t.assertTrue($.isNumeric( '3.1415' ))\n        t.assertTrue($.isNumeric( +10 ))\n        t.assertTrue($.isNumeric( 0144 ))\n\n        t.assertFalse($.isNumeric( '-0x42' ), '-0x42')\n        t.assertFalse($.isNumeric( '7.2acdgs' ), '7.2acdgs')\n        t.assertFalse($.isNumeric( '' ), 'empty string')\n        t.assertFalse($.isNumeric( {} ), 'empty hash')\n        t.assertFalse($.isNumeric( NaN ), 'NaN')\n        t.assertFalse($.isNumeric( null ), 'null')\n        t.assertFalse($.isNumeric( true ), 'true')\n        t.assertFalse($.isNumeric( Infinity ), 'Infinity')\n        t.assertFalse($.isNumeric( undefined ), 'undefined')\n      },\n\n      // test to see if we augment iOS 3.2 with String#trim()\n      testTrim: function(t){\n        t.assertEqual(\"blah\", \" blah \".trim())\n        t.assertIdentical(\"\", $.trim(undefined))\n        t.assertIdentical(\"\", $.trim(null))\n        t.assertIdentical(\"\", $.trim(\"\"))\n        t.assertIdentical(\"0\", $.trim(0))\n      },\n\n      testCamelCase: function(t){\n        t.assertEqual(\"hello\", $.camelCase(\"hello\"))\n        t.assertEqual(\"HELLO\", $.camelCase(\"HELLO\"))\n        t.assertEqual(\"helloNiceWorld\", $.camelCase(\"hello-nice-world\"))\n        t.assertEqual(\"helloWorld\", $.camelCase(\"helloWorld\"))\n      },\n\n      testExtend: function(t){\n        t.assertSame({}, $.extend({}))\n        t.assertSame(\n          {a: \"b\", c: \"d\", e: \"f\"},\n          $.extend({a: \"1\", e: \"f\"}, {a: \"b\", c: \"d\"})\n        )\n        var obj = {}\n        t.assertIdentical(obj, $.extend(obj, {a: 1}))\n        t.assertEqual(1, obj.a)\n\n        obj = {}\n        t.assertIdentical(obj, $.extend(obj, {a: 1}, {b: 2}))\n        t.assertEqual(2, obj.b)\n\n        // undefined values are not copied over\n        t.assertSame({a:1}, $.extend({a:1}, {b:undefined}))\n\n        // shallow by default\n        obj = $.extend({ a:{b:\"c\"} }, { a:{d:\"e\"} })\n        t.assertSame({d:\"e\"}, obj.a)\n      },\n\n      testExtendDeep: function(t){\n        var obj = { a:{b:\"c\", x:{y:\"z\"}} }\n        $.extend(true, obj, { a:{d:\"e\"} }, { a:{b:\"B\", f:\"g\", x:{q:\"x\"}} })\n\n        t.assertEqual('a', Object.keys(obj).join(','))\n        t.assertEqual('b,d,f,x', Object.keys(obj.a).sort().join(','))\n        t.assertEqual('B', obj.a.b)\n        t.assertEqual('e', obj.a.d)\n        t.assertEqual('g', obj.a.f)\n        t.assertEqual('z', obj.a.x.y)\n        t.assertEqual('x', obj.a.x.q)\n\n        // creates non-existing keys on target object\n        obj = {}\n        $.extend(true, obj, { a:{b:\"c\"} })\n        t.assertEqual('a', Object.keys(obj).join(','))\n        t.assertEqual('c', obj.a.b)\n\n        // skips iterating over DOM elements\n        obj = {}\n        var dom = $('#some_element').get(0)\n        $.extend(true, obj, { element: dom })\n        t.assertIdentical(dom, obj.element)\n\n        // can override DOM element\n        $.extend(true, obj, { element:{a:'b'} })\n        t.assertEqual('b', obj.element.a)\n\n        // deep copy with array\n        obj = {}\n        var initial = { array: [1,2,3,4], object:{a:{b:[\"c\",\"d\"]}} }\n        $.extend(true, obj, initial)\n        t.assertTrue($.isArray(obj.array))\n        t.assertEqual(JSON.stringify(obj), JSON.stringify(initial))\n        t.refuteIdentical(obj, initial)\n        t.refuteIdentical(obj.array, initial.array)\n        t.refuteIdentical(obj.object, initial.object)\n        t.refuteIdentical(obj.object.a, initial.object.a)\n        t.refuteIdentical(obj.object.a.b, initial.object.a.b)\n      },\n\n      testExtensionAPI: function(t) {\n        t.assert('init' in $.zepto)\n        t.assert('fragment' in $.zepto)\n        t.assert('Z' in $.zepto)\n        t.assert('isZ' in $.zepto)\n\n        // redefine Z and log some debug information\n        var oldZ = $.zepto.Z, calls = []\n        $.zepto.Z = function Z(dom, selector) {\n          var value = oldZ(dom, selector)\n          calls.push(dom)\n          return value\n        }\n\n        // now select some stuff\n        var Z1 = $(''), Z2 = $('#find1 .findme')\n\n        // check if $.fn methods are still there\n        t.assert('pluck' in Z1)\n        t.assert('width' in Z2)\n\n        // two calls should be logged\n        t.assertLength(2, calls)\n\n        // restore old Z\n        $.zepto.Z = oldZ\n        var Z3 = $('')\n        t.assertLength(2, calls)\n\n        t.assertFalse($.zepto.isZ())\n        t.assertFalse($.zepto.isZ([]))\n        t.assertTrue($.zepto.isZ($('body')))\n      },\n\n      testDollar: function(t){\n        var expectedElement = document.getElementById('some_element')\n\n        t.assertLength(1, $('#some_element'))\n        t.assertEqual(expectedElement, $('#some_element').get(0))\n        t.assertEqual(expectedElement, $(expectedElement).get(0))\n\n        t.assertLength(4, $('p'))\n        t.assertLength(1, $('p > span.yay'))\n      },\n\n      testDollarUnique: function(t){\n        t.refuteIdentical($('#some_element'), $('#some_element'))\n        t.refuteIdentical($('#nonexistent'), $('#nonexistent'))\n      },\n\n      testDollarWithNil: function(t){\n        t.assertZeptoCollection(0, $(null))\n        t.assertZeptoCollection(0, $(undefined))\n        t.assertZeptoCollection(0, $(false))\n        t.assertZeptoCollection(0, $(''))\n        t.assertZeptoCollection(0, $('#'))\n\n        var Z1 = $(null), Z2 = $(null)\n        t.assert(Z1 !== Z2)\n      },\n\n      testDollarWithNonDOM: function(t){\n        var zepto = $(['a', 'b', 'c'])\n        t.assertZeptoCollection(3, zepto)\n        t.assertEqualCollection(['a', 'b', 'c'], zepto)\n\n        t.assert($({}))\n        t.assertTrue($({ a: true })[0].a)\n\n        // Plain objects wrapped by a Zepto collection\n        // should still refer to the original object\n        // This is required for events on plain objects\n        var plainObject = { a: 1 }\n        $(plainObject).get(0).a = 2\n        t.assertEqual(2, plainObject.a)\n        t.assertEqual(2, $(plainObject).get(0).a)\n      },\n\n      testGetWithoutIndex: function(t){\n        var zepto = $('#find1 .findme')\n        var array = zepto.get()\n        t.assertFalse(zepto === array)\n        t.assertTrue($.isArray(array))\n        t.assertTrue(array.pop === ([]).pop)\n      },\n\n      testGetWithIndex: function(t){\n        var zepto = $('#find1 .findme')\n        t.assertEqual(zepto[0], zepto.get(0))\n        t.assertEqual(zepto[zepto.length - 1], zepto.get(-1))\n        t.assertUndefined(zepto.get(zepto.length))\n      },\n\n      testSize: function(t){\n        t.assertEqual(4, $('#find1 .findme').size())\n      },\n\n      testDollarWithMultipleInstances: function(t){\n        var instance1 = $('#some_element'),\n            instance2 = $('p')\n\n        t.assertLength(1, instance1)\n        t.assertLength(4, instance2)\n        t.refuteIdentical(instance1.get(0), instance2.get(0))\n      },\n\n      testDollarWithArrays: function(t){\n        var element = document.getElementById('some_element')\n\n        var z1 = $([element])\n        t.assertLength(1, z1)\n        t.assertEqual(element, z1.get(0))\n\n        var z2 = $([element, null, undefined])\n        t.assertLength(1, z2)\n        t.assertEqual(element, z2.get(0))\n\n        var z3 = $([null, element, null])\n        t.assertLength(1, z3)\n        t.assertEqual(element, z3.get(0))\n      },\n\n      testDollarWithContext: function(t){\n        // Zepto object\n        var zepto = $('p#find1, #find2')\n        t.assertLength(11, $('span', zepto))\n\n        // DOM Element\n        var domElement = document.getElementById('find1')\n        t.assertLength(4, $('span.findme', domElement))\n\n        // Selector with DOM Element Context\n        var domElement = document.getElementById('find1')\n        t.assertLength(4, $('span.findme', domElement))\n\n        // DOM Element with DOM Element Context\n        t.assertLength(1, $(domElement, domElement))\n      },\n\n      testDollarWithDocument: function(t){\n        var z = $(document)\n        t.assertLength(1, z)\n        t.assertEqual('', z.selector)\n      },\n\n      testDollarWithAppcache: function(t){\n        if ('applicationCache' in window) {\n          var z = $(window.applicationCache)\n          t.assertLength(1, z)\n          t.assertIdentical(window.applicationCache, z.get(0))\n          t.assertEqual('', z.selector)\n        }\n      },\n\n      testDollarWithDocumentFragment: function(t){\n        var documentFragment = $(document.createDocumentFragment())\n        t.assertLength(1, documentFragment)\n        t.assertEqual(Node.DOCUMENT_FRAGMENT_NODE, documentFragment.get(0).nodeType)\n      },\n\n      testDollarWithElementInIframe: function(t){\n        var iframe = $('#fixtures iframe').get(0),\n            iframeWin = iframe.contentWindow,\n            iframeDoc = iframe.contentDocument,\n            iframeBody = iframeDoc.body,\n            iframeEl = $(iframeBody).find('b')\n\n        t.assertIdentical(iframeWin, $(iframeWin).get(0))\n        t.assertIdentical(iframeDoc, $(iframeDoc).get(0))\n        t.assertIdentical(iframeBody, $(iframeBody).get(0))\n        t.assertEqual('B', iframeEl.pluck('tagName').join(','))\n        t.assertEqual('Hello from iframe!', iframeEl.text())\n      },\n\n      testDollarWithFragment: function(t){\n        var fragment = $(\"<div>\")\n        t.assertLength(1, fragment)\n        t.assertEqual(\"<div></div>\", outerHTML(fragment.get(0)))\n        t.assertEqual('', fragment.selector)\n        t.assertNull(fragment.get(0).parentNode)\n\n        fragment = $(\"<div>hello world</div>\")\n        t.assertLength(1, fragment)\n        t.assertEqual(\"<div>hello world</div>\", outerHTML(fragment.get(0)))\n        t.assertEqual('', fragment.selector)\n\n        fragment = $(\"<div>hello</div> <span>world</span>\")\n        t.assertLength(3, fragment)\n        t.assertEqual(\"<div>hello</div>\", outerHTML(fragment.get(0)))\n        t.assertEqual(Node.TEXT_NODE, fragment.get(1).nodeType)\n        t.assertEqual(\"<span>world</span>\", outerHTML(fragment.get(2)))\n        t.assertEqual('', fragment.selector)\n\n        fragment = $(\"<div>\\nhello</div> \\n<span>world</span>\")\n        t.assertLength(3, fragment)\n        t.assertEqual(\"<div>\\nhello</div>\", outerHTML(fragment.get(0)))\n        t.assertEqual(Node.TEXT_NODE, fragment.get(1).nodeType)\n        t.assertEqual(\"<span>world</span>\", outerHTML(fragment.get(2)))\n        t.assertEqual('', fragment.selector)\n\n        fragment = $(\"<div /><div />\")\n        t.assertLength(2, fragment)\n\n        fragment = $(\"<div>hello</div> \")\n        t.assertLength(1, fragment)\n      },\n\n      testDollarFragmentAndProperties: function(t){\n        var el = $('<p id=hi />', {\n          id: 'hello', 'class': 'one two',\n          text: 'world', css: {color: 'red'}\n        })\n\n        t.assertEqual('hello', el.attr('id'))\n        t.assert(el.hasClass('one'))\n        t.assert(el.hasClass('two'))\n        t.assertEqual('world', el.text())\n        t.assertEqual('red', el.css('color'))\n      },\n\n      testDollarNonemptyFragmentAndProperties: function(t){\n        var zepto = $('<a>Goodbye</a>', { text: \"Hello\", href: \"http://zeptojs.com\" })\n        t.assertLength(1, zepto)\n        t.assertEqual('Hello', zepto.text())\n        t.assertEqual('http://zeptojs.com', zepto.attr(\"href\"))\n      },\n\n      testDollarWithTextNode: function(t){\n        var textNode = $(document.createTextNode('hi there'))\n        t.assertLength(1, textNode)\n        t.assertEqual(Node.TEXT_NODE, textNode.get(0).nodeType)\n      },\n\n      testDollarWithCommentInFragment: function(t){\n        var comment = $('<!-- -->')\n        t.assertLength(1, comment)\n        t.assertEqual(Node.COMMENT_NODE, comment.get(0).nodeType)\n      },\n\n      testDollarWithDoctypeInFragment: function(t){\n        t.assertZeptoCollection(0, $('<!DOCTYPE html>'))\n      },\n\n      testNodeCreationViaDollar: function (t) {\n        t.assertEqual('<div></div>', outerHTML($('<div></div>').get(0)))\n        t.assertEqual('<div></div>', outerHTML($('<div/>').get(0)))\n        t.assertEqual('<div><div></div></div>', outerHTML($('<div><div></div></div>').get(0)))\n        t.assertEqual('<div><div></div></div>', outerHTML($('<div><div/></div>').get(0)))\n        t.assertEqual('<div><div></div><div></div></div>', outerHTML($('<div><div></div><div></div></div>').get(0)))\n      },\n\n      testCreateTableCell: function(t) {\n        t.assertEqual('TD', $('<td></td>').pluck('nodeName').join(','))\n      },\n\n      testCreateTableHeaderCell: function(t) {\n        t.assertEqual('TH', $('<th></th>').pluck('nodeName').join(','))\n      },\n\n      testCreateTableRow: function(t) {\n        t.assertEqual('TR', $('<tr></tr>').pluck('nodeName').join(','))\n      },\n\n      testCreateTableHeader: function(t) {\n        t.assertEqual('THEAD', $('<thead></thead>').pluck('nodeName').join(','))\n      },\n\n      testCreateTableBody: function(t) {\n        t.assertEqual('TBODY', $('<tbody></tbody>').pluck('nodeName').join(','))\n      },\n\n      testCreateTableFooter: function(t) {\n        t.assertEqual('TFOOT', $('<tfoot></tfoot>').pluck('nodeName').join(','))\n      },\n\n      testCreateSelectOptgroup: function(t) {\n        t.assertEqual('OPTGROUP', $('<optgroup></optgroup>').pluck('nodeName').join(','))\n      },\n\n      testCreateSelectOption: function(t) {\n        t.assertEqual('OPTION', $('<option></option>').pluck('nodeName').join(','))\n      },\n\n      testReady: function(t){\n        t.assertEqual('hi!', globalVarSetFromReady)\n        t.assertEqual('hi!', globalVarSetFromReady2)\n        t.assertEqual('hi!', globalVarSetFromReady3)\n        t.assertEqual('hi!', globalVarSetFromReady4)\n      },\n\n      testNext: function(t){\n        t.assertEqual('P', $('#some_element').next().get(0).tagName)\n        t.assertEqual('DIV', $('p').next().get(0).tagName)\n\n        t.assertEqual(0, $('span.yay').next('.nay').size())\n        t.assertEqual(1, $('span.yay').next().size())\n        t.assertEqual(1, $('span.yay').next().next('.nay').size())\n      },\n\n      testPrev: function(t){\n        t.assertEqual('H1', $('p').prev().get(0).tagName)\n        t.assertEqual('DIV', $('ul').prev().get(0).tagName)\n\n        t.assertEqual(0, $('span.nay').prev('.yay').size())\n        t.assertEqual(1, $('span.nay').prev().size())\n        t.assertEqual(1, $('span.nay').prev().prev('.yay').size())\n      },\n\n      testEach: function(t){\n        var index, tagnames = []\n        $('#eachtest > *').each(function(idx, el){\n          index = idx\n          t.assertIdentical(el, this)\n          tagnames.push(el.tagName.toUpperCase())\n        })\n        t.assertEqual('SPAN, B, BR', tagnames.join(', '))\n        t.assertEqual(2, index)\n      },\n\n      testEachBreak: function(t){\n        var index, tagnames = []\n        $('#eachtest > *').each(function(idx, el){\n          index = idx\n          t.assertIdentical(el, this)\n          tagnames.push(el.tagName.toUpperCase())\n          if (idx == 1) return false\n        })\n        t.assertEqual('SPAN, B', tagnames.join(', '))\n        t.assertEqual(1, index)\n      },\n\n      testNoop: function(t){\n        t.assertUndefined($.noop())\n      },\n\n      testConcat: function(t){\n        var $collection1 = $('#eachtest > *')\n        var $collection2 = $('#find1 .findme')\n        var $collection3 = $('#some_element, #another_element')\n\n        var result, array = $collection1.toArray().concat($collection2.toArray(), $collection3.toArray())\n\n        result = $collection1.concat($collection2, $collection3.toArray())\n        t.assertEqualCollection(array, result)\n\n        result = $.fn.concat.apply($collection1.toArray(), [$collection2, $collection3.toArray()])\n        t.assertEqualCollection(array, result)\n      },\n\n      testMap: function(t){\n        var results = $('#eachtest > *').map(function(idx, el) {\n          t.assertIdentical(el, this)\n          return idx + ':' + this.nodeName.toUpperCase()\n        })\n        t.assertEqual(3, results.size())\n        t.assertEqual('0:SPAN, 1:B, 2:BR', results.get().join(', '))\n      },\n\n      testDollarMap: function(t){\n        var fruits = ['apples', 'oranges', 'pineapple', 'peach', ['grape', 'melon']]\n        var results = $.map(fruits, function(item, i) {\n          if (item instanceof Array) return item\n          else if (!/apple/.test(item)) return i + ':' + item\n        })\n        t.assertEqual('1:oranges,3:peach,grape,melon', results.join(','))\n      },\n\n      testDollarMapObject: function(t){\n        var fruit = { name: 'banana', taste: 'sweet' }\n        var results = $.map(fruit, function(value, key) {\n          return key + '=' + value\n        })\n        t.assertEqual('name=banana,taste=sweet', results.sort().join(','))\n      },\n\n      testDollarMapArrayLike: function(t){\n        var results\n        results = $.map({ length: 1, a: 'b' }, function(value, key) {\n          return key + '=' + value\n        })\n        t.assertEqual('a=b,length=1', results.sort().join(','))\n\n        results = $.map({ length: 0, a: 'b' }, function(value, key) {\n          return key + '=' + value\n        })\n        t.assertEqual(0, results.length)\n\n        results = $.map(function(){}, function(value, key) {\n          return key + '=' + value\n        })\n        t.assertEqual(0, results.length)\n      },\n\n      testDollarGrep: function(t){\n        var fruits = ['apples', 'oranges', 'pineapple', 'peach']\n        var result = $.grep(fruits, function(name){ return /apple/.test(name) })\n        t.assertEqualCollection(['apples', 'pineapple'], result)\n      },\n\n      testDollarEach: function(t){\n        var array = ['a','b','c'], object = { a: 1, b: 2, c: 3 }, result\n\n        result = []\n        $.each(array, function(idx, val){\n          result.push(idx)\n          result.push(val)\n        })\n        t.assertEqual('0a1b2c', result.join(''))\n\n        result = []\n        $.each(object, function(key, val){\n          result.push(key)\n          result.push(val)\n        })\n        t.assertEqual('a1b2c3', result.join(''))\n\n        result = []\n        $.each(array, function(idx, val){\n          result.push(idx)\n          result.push(val)\n          return idx<1\n        })\n        t.assertEqual('0a1b', result.join(''))\n\n        t.assertEqual('abc', $.each(array, function(){}).join(''))\n      },\n\n      testDollarEachContext: function(t){\n        $.each(['a'], function(key, val) {\n          t.assertEqual(this, val)\n        })\n        $.each({a:'b'}, function(key, val) {\n          t.assertEqual(this, val)\n        })\n      },\n\n      testDollarInArray: function(t) {\n        t.assertIdentical( 0,  $.inArray(1, [1,2,3]) )\n        t.assertIdentical( 1,  $.inArray(2, [1,2,3]) )\n        t.assertIdentical( -1, $.inArray(4, [1,2,3]) )\n        t.assertIdentical( 3,  $.inArray(1, [1,2,3,1], 1) )\n      },\n\n      testDollarParseJSON: function(t) {\n        t.assertSame({a:'b'}, $.parseJSON('{\"a\":\"b\"}'))\n      },\n\n      testDollarWithDocumentFragmentContext: function(t){\n        testDocumentFragmentOrShadowRootContext($(document.createDocumentFragment()), t)\n      },\n\n      testDollarWithShadowRootContext: function(t){\n        if ('createShadowRoot' in document.body) {\n          var $subject = $('#test_dollar_with_shadow_root')\n          t.assertLength(1, $subject)\n          testDocumentFragmentOrShadowRootContext($($subject[0].createShadowRoot()), t)\n        }\n      },\n\n      testEq: function(t){\n        var $els = $('#eq_test div')\n        t.assertZeptoCollection(1, $els.eq(0))\n        t.assertZeptoCollection(1, $els.eq(-1))\n        t.assertEqual($els.eq(-1)[0].className, 'eq2')\n        t.assertUndefined($els.eq(-1).tagName)\n\n        t.assertZeptoCollection(0, $('nonexistent').eq(0))\n      },\n\n      testFirst: function(t){\n        var zepto = $('h1,p')\n        t.assertLength(5, zepto)\n\n        var zepto2 = zepto.first()\n        t.refuteIdentical(zepto, zepto2)\n        t.assertLength(5, zepto)\n\n        t.assertLength(1, zepto2)\n        t.assertEqual('H1', zepto2.get(0).tagName)\n\n        t.assertLength(0, $('nonexistent').first())\n      },\n\n      testFirstNonDOM: function(t){\n        t.assertEqual('a', $(['a', 'b', 'c']).first())\n      },\n\n      testLast: function(t){\n        var zepto = $('h1,p')\n        t.assertLength(5, zepto)\n\n        var zepto2 = zepto.last()\n        t.refuteIdentical(zepto, zepto2)\n        t.assertLength(5, zepto)\n\n        t.assertLength(1, zepto2)\n        t.assertEqual('P', zepto2.get(0).tagName)\n\n        t.assertLength(0, $('nonexistent').last())\n      },\n\n      testLastNonDOM: function(t){\n        t.assertEqual('c', $(['a', 'b', 'c']).last())\n      },\n\n      testPluck: function(t){\n        t.assertEqual('H1DIVDIV', $('h1,div.htmltest').pluck('tagName').join(''))\n      },\n\n      testShow: function(t){\n        $('#show_hide_div1').show()\n        t.assertEqual('inline-block', getComputedStyle($('#show_hide_div1').get(0)).display)\n\n        $('#show_hide_div2').show()\n        t.assertEqual('block', getComputedStyle($('#show_hide_div2').get(0)).display)\n\n        $('#show_hide_div3').show()\n        t.assertEqual('block', getComputedStyle($('#show_hide_div3').get(0)).display)\n\n        $('#show_hide_span1').show()\n        t.assertEqual('block', getComputedStyle($('#show_hide_span1').get(0)).display)\n\n        $('#show_hide_span2').show()\n        t.assertEqual('block', getComputedStyle($('#show_hide_span2').get(0)).display)\n\n        $('#show_hide_span3').show()\n        t.assertEqual('inline', getComputedStyle($('#show_hide_span3').get(0)).display)\n      },\n\n      testHide: function(t){\n        $('#show_hide_div1').hide()\n        t.assertEqual('none', $('#show_hide_div1').get(0).style.display)\n\n        $('#show_hide_div2').hide()\n        t.assertEqual('none', $('#show_hide_div2').get(0).style.display)\n\n        $('#show_hide_div3').hide()\n        t.assertEqual('none', $('#show_hide_div3').get(0).style.display)\n\n        $('#show_hide_span1').hide()\n        t.assertEqual('none', $('#show_hide_span1').get(0).style.display)\n\n        $('#show_hide_span2').hide()\n        t.assertEqual('none', $('#show_hide_span2').get(0).style.display)\n\n        $('#show_hide_span3').hide()\n        t.assertEqual('none', $('#show_hide_span3').get(0).style.display)\n      },\n\n      testToggle: function(t){\n        var el = $('#show_hide_div1').hide(),\n            domStyle = el.get(0).style\n\n        t.assertEqual('none', domStyle.display)\n\n        var result = el.toggle()\n        t.assertIdentical(el, result, 'expected toggle() to return self')\n        t.assertIdentical('', domStyle.display)\n\n        el.toggle()\n        t.assertEqual('none', domStyle.display)\n\n        el.toggle(true)\n        t.assertIdentical('', domStyle.display)\n\n        el.toggle(true)\n        t.assertIdentical('', domStyle.display)\n\n        el.toggle(false)\n        t.assertEqual('none', domStyle.display)\n\n        el.toggle(false)\n        t.assertEqual('none', domStyle.display)\n      },\n\n      testToggleMultiple: function(t){\n        var el1  = $('#show_hide_div1').hide(),\n            el2  = $('#show_hide_div2').show(),\n            both = $('#show_hide_div1, #show_hide_div2')\n\n        both.toggle()\n        t.assertIdentical('', el1.get(0).style.display)\n        t.assertEqual('none', el2.get(0).style.display)\n\n        both.toggle()\n        t.assertEqual('none', el1.get(0).style.display)\n        t.assertEqual('block', el2.get(0).style.display)\n      },\n\n      testOffset: function(t){\n        // TODO\n        t.assertNull($('#doesnotexist').offset())\n        var el = $('#some_element')\n        t.assertIdentical(el, el.offset({}))\n        t.assertSame($('<div>').offset(), {left: 0, top: 0})\n      },\n\n      testOffsetOnHTML: function(t){\n        var offset = $('html').offset()\n        t.assertEqual(offset.left, 0)\n        t.assertEqual(offset.top, 0)\n        t.assert('width' in offset)\n        t.assert('height' in offset)\n      },\n\n      testWidth: function(t){\n        t.assertNull($('#doesnotexist').width())\n        // can't check values here, but make sure it doesn't error out\n        var viewportWidth = $(window).width()\n        t.assert(viewportWidth > 0 || viewportWidth === 0)\n        t.assert($(document).width())\n\n        t.assertIdentical(100, $('#offset').width())\n        $('#offset').width('90px')\n        t.assertIdentical(90, $('#offset').width())\n        $('#offset').width(110)\n        t.assertIdentical(110, $('#offset').width())\n        $('#offset').width(function(i, oldWidth) { return oldWidth + 5 })\n        t.assertIdentical(115, $('#offset').width())\n      },\n\n      testHeight: function(t){\n        t.assertNull($('#doesnotexist').height())\n        // can't check values here, but make sure it doesn't error out\n        var viewportHeight = $(window).height()\n        t.assert(viewportHeight > 0 || viewportHeight === 0)\n        t.assert($(document).height())\n\n        // with a tall element on the page,\n        // the window (viewport) should be shorter than the total\n        // document height\n        $('<div style=\"height:9999px\" id=\"very_high\"></div>').appendTo('body')\n        t.assert(\n          $(window).height() < $(document).height(),\n          \"'window' height was not smaller than 'document' height?\")\n        $('#very_high').remove()\n\n        t.assertIdentical(50, $('#offset').height())\n        $('#offset').height('60px')\n        t.assertIdentical(60, $('#offset').height())\n        $('#offset').height(70)\n        t.assertIdentical(70, $('#offset').height())\n        $('#offset').height(function(i, oldHeight) { return oldHeight + 5 })\n        t.assertIdentical(75, $('#offset').height())\n      },\n\n      testClosest: function(t){\n        var el = $('#li2')\n        t.assertEqualCollection(el, el.closest('li'))\n        t.assertEqualCollection($('#nested'), el.closest('ul'))\n        // with context\n        t.assertEqualCollection($('#nested'), el.closest('ul', $('#li1').get(0)))\n        t.assertLength(0, el.closest('#parents', $('#li1').get(0)))\n        // no ancestor matched\n        t.assertLength(0, el.closest('form'))\n      },\n\n      testClosestMultiple: function(t){\n        var els = $('#parents ul li')\n        var uls = els.closest('ul')\n        t.assertEqualCollection($('#parents ul'), uls)\n        t.assertEqualCollection($('#parents'), uls.closest('#parents'))\n      },\n\n      testClosestWithCollection: function(t){\n        var targets = $('#parents > li')\n        var result = $('#li2').closest(targets)\n        t.assertLength(1, result)\n        t.assertEqual('li1', result.get(0).id)\n\n        t.assertLength(0, $('#li1').closest('#li2'))\n      },\n\n      testClosestWithElement: function(t){\n        var target = $('#li1').get(0)\n        var result = $('#li2').closest(target)\n        t.assertLength(1, result)\n        t.assertIdentical(target, result.get(0))\n\n        t.assertLength(0, $('#li1').closest($('#li2').get(0)))\n      },\n\n      testClosestOnDetached: function(t){\n        var el = $('<div><p><a></a></p></div>'),\n            para = el.children(),\n            link = para.children()\n\n        t.assertEqualCollection(para, link.closest('p'))\n        t.assertEqualCollection(el, link.closest('div'))\n        t.assertEqualCollection(el, el.closest('div'))\n      },\n\n      testContains: function(t){\n        var el1 = $('#li1'), el2 = $('#li2')\n\n        t.assertTrue($.contains(el1.get(0), el2.get(0)))\n        t.assertFalse($.contains(el1.get(0), $('#parents').get(0)))\n      },\n\n      testContainsOnDetached: function(t){\n        var el = $('<div><p><a></a></p></div>'),\n            para = el.children(),\n            link = para.children()\n\n        t.assertTrue($.contains(para.get(0), link.get(0)))\n        t.assertFalse($.contains(document.body, el.get(0)))\n      },\n\n      testParents: function(t){\n        var body = document.body, html = body.parentNode, container = $('#parents'),\n          wrapper = $('#fixtures').get(0)\n        t.assertEqualCollection($([wrapper, body, html]), container.parents())\n\n        var expected = $('#li1 > ul').get()\n        expected.push($('#li1').get(0))\n        expected.push(container.get(0))\n        expected = expected.concat([wrapper, body, html])\n        t.assertEqualCollection($(expected), $('#li1').find('li').parents())\n\n        expected = [$('#nested').get(0), $('#parents').get(0)]\n        t.assertEqualCollection($(expected), $('#li2').parents('ul'))\n      },\n\n      testParentsIframe: function(t){\n        var iframeBody = $('iframe').get(0).contentDocument.body\n        t.assertEqualCollection(\n          [iframeBody, iframeBody.parentNode],\n          $(iframeBody).find('b').first().parents()\n        )\n      },\n\n      testParent: function(t){\n        var el = $('#li1')\n        t.assertEqualCollection($('#parents'), el.parent())\n        t.assertEqualCollection($('#li1 > ul'), el.find('li').parent())\n        t.assertLength(0, $(document.createElement('div')).parent())\n      },\n\n      testParentOnDetached: function(t){\n        t.assertLength(0, $('<ul />').parent())\n      },\n\n      testChildren: function(t){\n        var el=$(\"#childrenTest\"), lis=$(\"li.child\",el)\n\n        //basic form\n        t.assertEqualCollection(lis, el.children())\n        //filtered by selector\n        t.assertEqualCollection(lis.filter(\".two\"), el.children(\".two\"))\n        //children == null\n        t.assertLength(4,lis.children(null))\n        //across multiple parents\n        t.assertEqualCollection(el.find(\"li a\"), lis.children(\"a\"))\n        //chainabilty\n        t.assertEqual(el.find(\"li a.childOfTwo\").text(), lis.children(\".childOfTwo\").text())\n        //non-existent children\n        t.assertLength(0,lis.children(\".childOfTwo\").children())\n      },\n\n      testContents: function(t){\n        var $contents = $(\"#contentsTest\").contents()\n        t.assertLength(3, $contents)\n        t.assertLength(2, $contents.filter('span'))\n        t.assertLength(0, $(\"#contentsEmptyTest\").contents())\n      },\n\n      testIframeContents: function(t){\n        var el = $(\"#contentsIframeTest\")\n        t.assertEqual(\"Hello from iframe!\", el.contents().find(\"b\").first().text())\n      },\n\n      testSiblings: function(t){\n        var el=$(\"#siblingsTest\")\n\n        //basic form\n        t.assertEqualCollection($(\"li.one,li.three,li.four\",el), $(\"li.two\",el).siblings())\n        //filtered by selector\n        t.assertEqualCollection($(\"li.three\",el), $(\"li.two\",el).siblings(\".three\"))\n        //across multiple parents\n        t.assertEqualCollection(el.find(\"li b\"), $(\"li em\",el).siblings(\"b\"))\n        t.assertLength(6,$(\"li span\",el).siblings())\n        //non-existent siblings\n        t.assertLength(0,$(\"li span.e\",el).siblings())\n      },\n\n      testNot: function(t){\n        var el=$(\"#notTest\")\n\n        //selector form\n        t.assertEqualCollection($(\"li.one,li.three,li.four\",el), $(\"li\",el).not(\".two\"))\n        //element or NodeList form\n        t.assertEqualCollection($(\"span.b,span.c,span.e\",el), $(\"span\",el).not(document.getElementById(\"notTestExclude\")))\n        t.assertEqualCollection($(\"li\",el), $(\"li, span\",el).not(document.getElementsByTagName(\"span\")))\n        //function form\n        t.assertEqualCollection($(\"span.b,span.c\",el),$(\"span\",el).not(function(i){\n          var $this=$(this)\n          $this.html(i)\n          return ($this.hasClass(\"d\") || $this.hasClass(\"e\")) ? true : false\n        }))\n        //test the index was passed in properly in previous test\n        t.assertEqual(\"0\",$(\"span.b\",el).text())\n        t.assertEqual(\"1\",$(\"span.c\",el).text())\n      },\n\n      testReplaceWith: function(t) {\n        $('div.first').replaceWith('<h2 id=\"replace_test\">New heading</h2>')\n        t.assertUndefined($('div.first').get(0))\n        t.assert(document.getElementById(\"replace_test\").nodeType)\n        t.assertEqual($('.replacewith h2#replace_test').get(0), document.getElementById(\"replace_test\"))\n\n        $('#replace_test').replaceWith($('.replace_test_div'))\n        t.assertUndefined($('#replace_test').get(0))\n        t.assert(document.getElementsByClassName(\"replace_test_div\")[0].nodeType)\n        t.assertEqual($('.replacewith h2#replace_test').get(0), document.getElementsByClassName(\"replace_test\")[0])\n\n        //Multiple elements\n        $('.replacewith .replace_test_div').replaceWith('<div class=\"inner first\">hi</div><div class=\"inner fourth\">hello</div>')\n        t.assertLength(4,$('.replacewith div'))\n        t.assertEqual(\"inner first\", $('.replacewith div')[0].className)\n        t.assertEqual(\"inner fourth\", $('.replacewith div')[1].className)\n      },\n\n      testReplaceWithFragment: function(t) {\n        var orphanDiv = $(\"<div />\")\n        orphanDiv.replaceWith($(\"<div class='different' />\"))\n        t.assert(!orphanDiv.hasClass('different'))\n      },\n\n      testWrap: function(t) {\n        var el = $('#wrap_test')\n        el.find('span').wrap('<p><i/></p>')\n        t.assertEqual(\n          '<p><i><span>hi</span></i></p><a></a><p><i><span>hello</span></i></p>',\n          el.html()\n        )\n\n        // avoids unnecessary cloning of dom structure for wrapping\n        el = $('<div><a/></div>')\n        var structure = $('<span/>')\n        el.find('a').wrap(structure)\n        t.assertIdentical(structure.get(0), el.find('span').get(0))\n        t.assert(el.find('a').parent().is('span'))\n      },\n\n      testWrapFunction: function(t) {\n        var el = $('<div><b>A</b><b>B</b></div>')\n        el.find('b').wrap(function(index){\n          return '<a class=link' + index + $(this).text() + ' />'\n        })\n        t.assertEqual(\n          '<a class=\"link0A\"><b>A</b></a><a class=\"link1B\"><b>B</b></a>',\n          el.html()\n        )\n      },\n\n      testWrapAll: function(t) {\n        var el = $('#wrapall_test')\n        el.find('span').wrapAll('<p><a/></p>')\n        t.assertEqual(\n          '<b></b><p><a><span>hi</span><span>hello</span></a></p><i></i>',\n          el.html()\n        )\n      },\n\n      testWrapFragment: function(t) {\n        var fragment = $('<div id=\"fragment\" />')\n        fragment.wrapAll('<div id=\"wrap_test\" />')\n        t.assertEqual('wrap_test', fragment.parent().attr('id'))\n        t.assertEqual(0, fragment.children().length)\n\n        fragment = $('<div id=\"fragment\" />')\n        fragment.wrap('<div id=\"wrap_test\" />')\n        t.assertEqual('wrap_test', fragment.parent().attr('id'))\n        t.assertEqual(0, fragment.children().length)\n      },\n\n      testWrapInner: function(t) {\n        var $el = $('#wrapinner_test')\n        $el.wrapInner('<div>')\n        t.assertLength(1, $el.children())\n        t.assertLength(1, $el.children('div'))\n        t.assertLength(3, $el.find('div').contents())\n\n        $el = $('#wrapinner_empty_test')\n        $el.wrapInner('<div>')\n        t.assertLength(1, $el.children())\n        t.assertLength(1, $el.children('div'))\n        t.assertLength(0, $el.find('div').contents())\n      },\n\n      testWrapInnerFunction: function(t) {\n        var el = $('<div><b>A</b><b>B</b></div>')\n        el.find('b').wrapInner(function(index){\n          return '<a class=link' + index + $(this).text() + ' />'\n        })\n        t.assertEqual(\n          '<b><a class=\"link0A\">A</a></b><b><a class=\"link1B\">B</a></b>',\n          el.html()\n        )\n      },\n\n      testUnwrap: function(t){\n        var context=$(\"#unwrap_test\")\n\n        //Element With no siblings\n        $(\".unwrap_one span\",context).unwrap()\n        t.assertLength(1,$(\"b\",context))\n\n        //Element with siblings\n        $(\".unwrap_two span\",context).unwrap()\n        t.assertLength(0,$(\"b\",context))\n        //make sure siblings are unaffected\n        t.assertLength(3,$(\"span\",context))\n        //make sure parents are what they should be\n        t.assertEqual($(\"span\",context).parent().get(0), document.getElementsByClassName(\"unwrap_one\")[0])\n      },\n\n      testUnwrapFragment: function(t){\n        var fragment = $('<div id=outer><div id=inner></div><div id=uninvolved></div></div>'),\n            innerFragment = fragment.find(\"#inner\"),\n            uninvolved = fragment.find(\"#uninvolved\")\n\n        innerFragment.unwrap()\n        t.assertLength(0, innerFragment.parent(), '#inner should be orphan')\n        t.assertLength(0, uninvolved.parent(),    '#uninvolved should be orphan')\n        t.assertLength(0, fragment.children(),    'fragment should be empty')\n      },\n\n      testClone: function(t){\n        var el = $('<div class=sheep><span></span></div>'),\n            el2 = el.clone()\n\n        t.assert(el2.hasClass('sheep'))\n        el2.addClass('black')\n        t.refute(el.hasClass('black'))\n\n        el2.find('span').text('baa')\n        t.assertIdentical('', el.find('span').text())\n      },\n\n      testFind: function(t){\n        var found = $('p#find1').find('span.findme')\n        t.assertLength(4, found)\n        t.assertEqual('1', found.get(0).innerHTML)\n        t.assertEqual('2', found.get(1).innerHTML)\n        t.assertEqual('4', found.get(2).innerHTML)\n        t.assertEqual('5<span>6</span>', found.get(3).innerHTML)\n\n        var found = $('p#find1, #find2').find('span')\n        t.assertLength(11, found)\n      },\n\n      testFindWithCollection: function(t){\n        var targets = $('#find1 span span, #find1 b, #find2 span')\n        var found = $('p#find1').find(targets)\n        t.assertLength(2, found)\n        t.assertEqual('B', found.get(0).tagName)\n        t.assertEqual('6', found.get(1).innerHTML)\n      },\n\n      testFindWithElement: function(t){\n        var target = $('#find1 span span').get(0)\n        var found = $('p#find1').find(target)\n        t.assertLength(1, found)\n        t.assertEqual('6', found.get(0).innerHTML)\n\n        found = $('p#find1').find(document.body)\n        t.assertLength(0, found, \"no elements should have matched\")\n      },\n\n      testFindWithInvalidNode: function(t) {\n        var found = $('<div><a>1</a></div>\\n<div></div>').find('a')\n        t.assertLength(1, found)\n        t.assertEqual('1', found.get(0).innerHTML)\n      },\n\n      testFindWithFalsyValue: function(t){\n        var element = '<div><a>1</a></div>'\n        t.assertZeptoCollection(0, $(element).find(undefined))\n        t.assertZeptoCollection(0, $(element).find(false))\n        t.assertZeptoCollection(0, $(element).find(0))\n        t.assertZeptoCollection(0, $(element).find(''))\n      },\n\n      testFilter: function(t){\n        var found = $('div')\n        t.assertLength(2, found.filter('.filtertest'))\n        t.assertLength(0, found.filter('.doesnotexist'))\n        t.assertLength(1, found.filter('.filtertest').filter(':nth-child(2n)'))\n\n        var nodes = $('<select><option value=1>test1</option><option value=2>test2</option><option value=1>test1</option></select>')\n        t.assertLength(2, nodes.find('option').filter(function(){ return this.value == '1' }))\n\n        var indexes = []\n        nodes.find('option').filter(function(index){ if (this.value=='1') indexes.push(index) })\n        t.assertEqualCollection([0,2], indexes)\n      },\n\n      testFilterWithNonNativeArrayFilter: function(t){\n        var nativeFilter = Array.prototype.filter\n        try {\n          // apply broken filter\n          Array.prototype.filter = function(){ return [] }\n          t.assertLength(2, $('div').filter('.filtertest'))\n        } finally {\n          Array.prototype.filter = nativeFilter\n        }\n      },\n\n      testHas: function(t){\n        var result, el = $('<b id=one><a></a></b><b id=two><i></i></b><b id=three><i></i></b>')\n        result = el.has('a')\n        t.assertEqual('one', result.pluck('id').join(' '))\n        result = el.has('i')\n        t.assertEqual('two three', result.pluck('id').join(' '))\n        result = el.has(el.find('i').get(0))\n        t.assertEqual('two', result.pluck('id').join(' '))\n      },\n\n      testAdd: function(t){\n        var lis=$(\"li\"),spans=$(\"span\"),\n        together=lis.add(\"span\"),\n        duplicates=spans.add(\"span\"),\n        disconnected=$(\"<div></div>\").add(\"<span></span>\"),\n        mainContext=$(\"#addTest\")\n\n        //uniquness of collection\n        t.assertLength(spans.length, duplicates)\n\n        //selector only\n        t.assertLength((lis.length + spans.length), together)\n\n        //selector with context\n        t.assertEqualCollection($(\"span\",mainContext), $(\".add_span\").add(\".add_span_exclude\",mainContext))\n\n        //DOM Element + Chaining test\n        t.assertEqualCollection(mainContext.children(), $(\".add_span\").add(\".add_span_exclude\").add(document.getElementById(\"addTestDiv\")))\n\n        //Disconnected\n        t.assert(!disconnected.get(0).parentNode)\n\n        $(\"#addTestDiv\").append(disconnected)\n        t.assertEqual('<div></div><span></span>', document.getElementById(\"addTestDiv\").innerHTML)\n      },\n\n      testIs: function(t){\n        t.assert($('#find1').is('p'))\n        t.assert($('#li2').is(':first-child'))\n        t.assert(!$('#find1').is('doesnotexist'))\n        t.assert(!$('#find1').is())\n        t.assert($('#find1').is($('#find1')))\n        t.assert(!$('#find1').is($('#find2')))\n\n        t.assert($('#fixtures div').is('#some_element'))\n        t.assert(!$('#doesnotexist').is('p'))\n        t.assert(!$('#doesnotexist').is($('#find1')))\n\n        t.assert(!$(window).is('p'))\n      },\n\n      testIsWithoutParent: function(t){\n        var elem = $('<div id=outOfDOM />')\n        t.assert(elem.is('div'))\n        t.assert(elem.is('#outOfDOM'))\n        t.assert(!elem.is('p'))\n        t.assert(!elem.is())\n      },\n\n      testCSS: function(t){\n        var el = $('#some_element').get(0)\n\n        // single assignments\n        $('#some_element').css('color', '#f00')\n        $('#some_element').css('margin-top', '10px')\n        $('#some_element').css('marginBottom', '5px')\n        $('#some_element').css('left', 42)\n        $('#some_element').css('z-index', 10)\n        $('#some_element').css('fontWeight', 300)\n        $('#some_element').css('border', '1px solid rgba(255,0,0,0)')\n        t.assertEqual('rgb(255, 0, 0)', el.style.color)\n        t.assertEqual('rgba(255, 0, 0, 0)', el.style.borderLeftColor)\n        t.assertEqual('1px', el.style.borderLeftWidth)\n        t.assertEqual('10px', el.style.marginTop)\n        t.assertEqual('5px', el.style.marginBottom)\n        t.assertEqual('42px', el.style.left)\n        t.assertEqual(300, el.style.fontWeight)\n        t.assertEqual(10, el.style.zIndex)\n\n        // read single values, including shorthands\n        t.assertEqual('rgb(255, 0, 0)',\n          $('#some_element').css('color'))\n        t.assertEqual('1px solid rgba(255, 0, 0, 0)',\n          $('#some_element').css('border'))\n\n        // multiple assignments\n        $('#some_element').css({\n          'border': '2px solid #000',\n          'color': 'rgb(0,255,0)',\n          'padding-left': '2px'\n        })\n        t.assertEqual('2px', $('#some_element').css('borderLeftWidth'))\n        t.assertEqual('solid', $('#some_element').css('borderLeftStyle'))\n        t.assertEqual('rgb(0, 0, 0)', $('#some_element').css('borderLeftColor'))\n        t.assertEqual('rgb(0, 255, 0)', $('#some_element').css('color'))\n        t.assertEqual('2px', $('#some_element').css('paddingLeft'))\n        t.assertEqual('2px', $('#some_element').css('border-left-width'))\n        t.assertEqual('solid', $('#some_element').css('border-left-style'))\n        t.assertEqual('rgb(0, 0, 0)', $('#some_element').css('border-left-color'))\n        t.assertEqual('rgb(0, 255, 0)', $('#some_element').css('color'))\n        t.assertEqual('2px', $('#some_element').css('padding-left'))\n\n        // read multiple values, camelCased CSS\n        var arrCamelCss = $('#some_element').css(['borderLeftWidth', 'borderLeftStyle', 'borderLeftColor', 'color'])\n        t.assertEqual('2px', arrCamelCss['borderLeftWidth'])\n        t.assertEqual('solid', arrCamelCss['borderLeftStyle'])\n        t.assertEqual('rgb(0, 0, 0)', arrCamelCss['borderLeftColor'])\n        t.assertEqual('rgb(0, 255, 0)', arrCamelCss['color'])\n        t.assertUndefined(arrCamelCss['paddingLeft'])\n\n        // read multiple values, dashed CSS property names\n        var arrDashedCss = $('#some_element').css(['border-left-width', 'border-left-style', 'border-left-color', 'color'])\n        t.assertEqual('2px', arrDashedCss['border-left-width'])\n        t.assertEqual('solid', arrDashedCss['border-left-style'])\n        t.assertEqual('rgb(0, 0, 0)', arrDashedCss['border-left-color'])\n        t.assertEqual('rgb(0, 255, 0)', arrDashedCss['color'])\n        t.assertUndefined(arrDashedCss['padding-left'])\n\n        // make sure reads from empty Zepto collections just return undefined\n        t.assertUndefined($().css(['border-left-width']))\n\n        var div = $('#get_style_element')\n        t.assertEqual('48px', div.css('font-size'))\n        t.assertEqual('rgb(0, 0, 0)', div.css('color'))\n      },\n\n      testCSSUnset: function (t) {\n        var el = $('#some_element').css({ 'margin-top': '1px', 'margin-bottom': '1px' }),\n            dom = el.get(0)\n\n        el.css('color', '#000')\n        el.css('color', '')\n        t.assertIdentical('', dom.style.color)\n\n        el.css('color', '#000')\n        el.css('color', undefined)\n        t.assertIdentical('', dom.style.color)\n\n        el.css('color', '#000')\n        el.css('color', null)\n        t.assertIdentical('', dom.style.color)\n\n        el.css('color', '#000')\n        el.css({ color: '', 'margin-top': undefined, 'marginBottom': null })\n        t.assertIdentical('', dom.style.color)\n        t.assertIdentical('', dom.style.marginTop)\n        t.assertIdentical('', dom.style.marginBottom)\n      },\n\n      testCSSZeroValue: function (t) {\n        var el = $('#some_element'), dom = el.get(0)\n        el.css('opacity', 0)\n        t.assertIdentical('0', dom.style.opacity)\n\n        el.css('opacity', 1)\n        el.css({ opacity: 0 })\n        t.assertIdentical('0', dom.style.opacity)\n      },\n\n      testCSSOnNonExistingElement: function (t) {\n        var el = $('.some-non-exist-elm')\n        t.assertUndefined(el.css('color'))\n      },\n\n      testCSSBatchSetOnNonExistingElementReturnsSelf: function (t) {\n        var el = $('.some-non-exist-elm')\n        var ret = el.css({\n          'border': '2px solid #000',\n          'color': 'rgb(0,255,0)'\n        })\n        t.assertIdentical(ret, el)\n      },\n\n      testHtml: function(t){\n        var div = $('div.htmltest')\n\n        div.text(undefined)\n        t.assertEqual('', div.html())\n\n        t.assertIdentical(div, div.html('yowza'))\n        t.assertEqual('yowza', document.getElementById('htmltest1').innerHTML)\n        t.assertEqual('yowza', document.getElementById('htmltest2').innerHTML)\n\n        t.assertEqual('yowza', $('div.htmltest').html())\n\n        div.html('')\n        t.assertEqual('', document.getElementById('htmltest2').innerHTML)\n\n        t.assertEqual(\"\", $('#htmltest3').html())\n\n        t.assertNull($('doesnotexist').html())\n\n        div.html('yowza')\n        div.html(function(idx, html){\n          return html.toUpperCase()\n        })\n        t.assertEqual('YOWZA', div.html())\n\n        div.html('<u>a</u><u>b</u><u>c</u>')\n\n        $('u').html(function(idx,html){\n          return idx+html\n        })\n        t.assertEqual('<u>0a</u><u>1b</u><u>2c</u>', div.html())\n\n        var table = $('#htmltest4'),\n          html = '<tbody><tr><td>ok</td></tr></tbody>'\n        table.html('<tbody><tr><td>ok</td></tr></tbody>')\n        t.assertEqual(html, table.html())\n      },\n\n      testText: function(t){\n        // test basics with Zepto-created DOM elements\n        t.assertEqual('',         $('<h1/>').text())\n        t.assertEqual('',         $('<h1/>').text('').text())\n        t.assertEqual('',         $('<h1/>').text(undefined).text())\n        t.assertEqual('',         $('<h1/>').text(null).text())\n        t.assertEqual('false',    $('<h1/>').text(false).text())\n        t.assertEqual('1',        $('<h1/>').text(1).text())\n        t.assertEqual('<b>a</b>', $('<h1/>').text('<b>a</b>').text())\n\n        t.assertEqual('&lt;b&gt;a&lt;/b&gt;',\n          $('<h1/>').text('<b>a</b>').html())\n\n        // now test with some existing DOM elements\n        $('#texttest3').text(undefined)\n        t.assertEqual('', $('#texttest3').text())\n\n        t.assertEqual('Here is some text', $('#texttest1').text())\n        t.assertEqual('And some more', $('#texttest2').text())\n\n        // gets all text of selectors matching\n        t.assertEqual('Here is some textAnd some more', $('div.texttest').text())\n\n        $('div.texttest').text(\"Let's set it\")\n        t.assertEqual(\"Let's set it\", $('#texttest1').text())\n        t.assertEqual(\"Let's set it\", $('#texttest2').text())\n\n        $('#texttest2').text('')\n        t.assertEqual(\"Let's set it\", $('#texttest1').text())\n        t.assertEqual('', $('#texttest2').text())\n      },\n\n      testTextWithFunction: function(t) {\n        var el = $('<div><span>hello</span> <span></span> <span>world</span> <span>again</span></div>'),\n            els = el.find('span')\n\n        els.text(function(idx, oldText){\n          if (idx > 2) return null\n          if (oldText) return oldText.toUpperCase() + ' ' + idx\n        })\n\n        t.assertEqual('HELLO 0', els[0].textContent)\n        t.assertEqual('', els[1].textContent)\n        t.assertEqual('WORLD 2', els[2].textContent)\n        t.assertEqual('', els[3].textContent)\n      },\n\n      testEmpty: function(t) {\n        $('#empty_test').empty()\n\n        t.assertEqual(document.getElementById('empty_1'), null)\n        t.assertEqual(document.getElementById('empty_2'), null)\n        t.assertEqual(document.getElementById('empty_3'), null)\n        t.assertEqual(document.getElementById('empty_4'), null)\n      },\n\n      testAttr: function(t){\n        var els = $('#attr_1, #attr_2')\n\n        t.assertEqual('someId1', els.attr(\"data-id\"))\n        t.assertEqual('someName1', els.attr(\"data-name\"))\n\n        els.attr(\"data-id\",\"someOtherId\")\n        els.attr(\"data-name\",\"someOtherName\")\n\n        t.assertEqual('someOtherId', els.attr(\"data-id\"))\n        t.assertEqual('someOtherName', els.attr(\"data-name\"))\n        t.assertEqual('someOtherId', $('#attr_2').attr('data-id'))\n\n        t.assertUndefined(els.attr(\"nonExistentAttribute\"))\n\n        els.attr(\"data-id\", false)\n        t.assertEqual(\"false\", els.attr(\"data-id\"))\n\n        els.attr(\"data-id\", 0)\n        t.assertEqual(\"0\", els.attr(\"data-id\"))\n\n        els.attr({ 'data-id': 'id', 'data-name': 'name' })\n        t.assertEqual('id', els.attr(\"data-id\"))\n        t.assertEqual('name', els.attr(\"data-name\"))\n        t.assertEqual('id', $('#attr_2').attr('data-id'))\n\n        els.attr('data-id', function(idx,oldvalue){\n          return idx+oldvalue\n        })\n        t.assertEqual('0id', els.attr('data-id'))\n        t.assertEqual('1id', $('#attr_2').attr('data-id'))\n      },\n\n      testAttrSetterErase: function(t){\n        var el = $('<div data-name=\"foo\">')\n        t.assertIdentical(el, el.attr('data-name', undefined), 'setter should return self')\n        t.assertNull(el.get(0).getAttribute('data-name'), 'attribute should be erased')\n        t.assertUndefined(el.attr('data-name'), 'attr should reflect erased attribute')\n      },\n\n      testProp: function(t){\n        var label = $('#prop_test1')\n        var input = $('#prop_test2')\n        var table = $('#prop_test3')\n        var td1 = $('#prop_test4')\n        var td2 = $('#prop_test5')\n        var img = $('#prop_test6')\n        var div = $('#prop_test7')\n        var checkbox = $('#prop_test8')\n\n        t.assertEqual(input.prop('tabindex'), -1)\n        t.assertEqual(input.prop('readonly'), true)\n        t.assertEqual(label.prop('for'), 'prop_test2')\n        t.assertEqual(input.prop('class'), 'propTest')\n        t.assertEqual(input.prop('maxlength'), 10)\n        t.assertEqual(table.prop('cellspacing'), 10)\n        t.assertEqual(table.prop('cellpadding'), 5)\n        t.assertEqual(td1.prop('rowspan'), 2)\n        t.assertEqual(td2.prop('colspan'), 2)\n        t.assertEqual(img.prop('usemap'), '#imgMap')\n        t.assertEqual(div.prop('contenteditable'), 'true')\n\n        checkbox.prop({'class': 'propTest', 'checked': false, 'disabled': true})\n        t.assertEqual(checkbox.prop('class'), 'propTest')\n        t.assertEqual(checkbox.prop('checked'), false)\n        t.assertEqual(checkbox.prop('disabled'), true)\n      },\n\n      testRemoveProp: function(t){\n        var el = $('<span>')\n        el.prop('hello', 'world')\n        t.assertEqual('world', el[0].hello)\n        el.removeProp('hello')\n        t.assertUndefined(el[0].hello)\n      },\n\n      testPropSetterErase: function(t){\n        var input = $('<input readonly>')\n        t.assertIdentical(input, input.prop('readonly', false))\n        t.assertFalse(input.prop('readonly'))\n\n        input.get(0)._foo = 'bar'\n        t.assertIdentical(input, input.prop('_foo', undefined))\n        t.assertUndefined(input.get(0)._foo, 'custom property should be cleared')\n        t.assertUndefined(input.prop('_foo'), 'prop should reflect cleared property')\n      },\n\n      testAttrNoElement: function(t){\n        t.assertUndefined($().attr('yo'))\n        t.assertUndefined($(document.createTextNode('')).attr('yo'))\n        t.assertUndefined($(document.createComment('')).attr('yo'))\n\n        var els = $('<b></b> <i></i>').attr('id', function(i){ return this.nodeName + i })\n        t.assertEqual('B0', els.eq(0).attr('id'))\n        t.assertEqual('I2', els.eq(2).attr('id'))\n        t.assertUndefined(els.eq(1).attr('id'))\n      },\n\n      testAttrEmpty: function(t){\n        var el = $('#data_attr')\n        t.assertIdentical('', el.attr('data-empty'))\n      },\n\n      testAttrOnTextInputField: function(t) {\n        var inputs, values\n\n        // HTML is set here because IE does not reset\n        // values of input fields on page reload\n        document.getElementById('attr_with_text_input').innerHTML =\n          '<input value=\"Default input\">'+\n          '<input type=\"text\" value=\"Text input\">'+\n          '<input type=\"email\" value=\"Email input\">'+\n          '<input type=\"search\" value=\"Search input\">'\n\n        inputs = $('#attr_with_text_input input')\n\n        values = $.map(inputs, function(i){ return $(i).attr('value') })\n        t.assertEqual('Default input, Text input, Email input, Search input', values.join(', '))\n\n        // Only .attr('value', v) changes .attr('value')\n        // rather than .val(v)\n        inputs.attr('value', function(i, value){ return value.replace('input', 'changed') })\n\n        values = $.map(inputs, function(i){ return $(i).attr('value') })\n        t.assertEqual('Default changed, Text changed, Email changed, Search changed', values.join(', '))\n      },\n\n      testAttrNullUnset: function(t){\n        var el = $('<div id=hi>')\n        el.attr('id', null)\n        t.assertUndefined(el.attr('id'))\n\n        el.attr('id', 'hello')\n        el.attr({ id:null })\n        t.assertUndefined(el.attr('id'))\n      },\n\n      testRemoveAttr: function(t) {\n        var el = $('#attr_remove')\n        t.assertEqual('boom', el.attr('data-name'))\n        el.removeAttr('data-name')\n        t.assertUndefined(el.attr('data-name'))\n      },\n\n      testRemoveMultipleAttr: function(t) {\n        var el = $('#attr_remove_multi')\n        t.assertEqual('someId1', el.attr('data-id'))\n        t.assertEqual('someName1', el.attr('data-name'))\n\n        el.removeAttr('data-id data-name')\n        t.assertUndefined(el.attr('data-id'))\n        t.assertUndefined(el.attr('data-name'))\n      },\n\n      testRemoveAttrNoElement: function(t){\n        t.assert($().removeAttr('rel'))\n        t.assert($(document.createTextNode('')).removeAttr('rel'))\n\n        var els = $('<b rel=up></b> <i rel=next></i>')\n        t.assertIdentical(els, els.removeAttr('rel'))\n        t.assertUndefined(els.eq(0).attr('rel'))\n        t.assertUndefined(els.eq(1).attr('rel'))\n        t.assertUndefined(els.eq(2).attr('rel'))\n      },\n\n      testData: function(t) {\n        var el = $('#data_attr')\n        // existing attribute\n        t.assertEqual('bar', el.data('foo'))\n        t.assertEqual('baz', el.data('foo-bar'))\n        t.assertEqual('baz', el.data('fooBar'))\n\n        // camelCase\n        el.data('fooBar', 'bam')\n        t.assertEqual('bam', el.data('fooBar'))\n        t.assertEqual('bam', el.data('foo-bar'))\n\n        // new attribute\n        el.data('fun', 'hello')\n        t.assertEqual('hello', el.attr('data-fun'))\n        t.assertEqual('hello', el.data('fun'))\n\n        // blank values\n        t.assertIdentical('', el.data('empty'))\n        t.assertUndefined(el.data('does-not-exist'))\n      },\n\n      testDataSetterErase: function(t) {\n        var el = $('<div data-name=\"foo\">')\n        t.assertIdentical(el, el.data('name', undefined))\n        t.assertUndefined(el.data('name'))\n      },\n\n      testDataNumberType: function(t){\n        var el = $('<div data-num=42 />')\n        t.assertIdentical(42, el.data('num'))\n\n        t.assertIdentical(42.5,\n          $('<div data-float=42.5 />').data('float'))\n\n        t.assertIdentical(\"08\",\n          $('<div data-notnum=08 />').data('notnum'))\n\n        t.assertIdentical(\"5903509451651483504\",\n          $('<div data-bignum=\"5903509451651483504\" />').data('bignum'))\n      },\n\n      testDataBooleanType: function(t){\n        var el = $('<div data-true=true data-false=false />')\n        t.assertTrue(el.data('true'))\n        t.assertFalse(el.data('false'))\n      },\n\n      testDataNullType: function(t){\n        var el = $('<div data-nil=null />')\n        t.assertNull(el.data('nil'))\n      },\n\n      testDataJsonType: function(t){\n        var el = $('<div data-json=\\'[\"one\", \"two\"]\\' data-invalid=\\'[boom]\\' />')\n        var json = el.data('json')\n        t.assertEqual(2, json.length)\n        t.assertEqual(\"one\", json[0])\n        t.assertEqual(\"two\", json[1])\n        t.assertEqual('[boom]', el.data('invalid'))\n      },\n\n      testVal: function(t) {\n        var input = $('#attr_val')\n\n        // some browsers like IE don't reset input values on reload\n        // which messes up repeated test runs, so set the start value\n        // directly via the DOM API\n        document.getElementById('attr_val').value = 'Hello World'\n\n        t.assertEqual('Hello World', input.val())\n\n        input.val(undefined)\n        t.assertEqual('', input.val())\n\n        input.val(null)\n        t.assertEqual('', input.val())\n\n        input.val('')\n        t.assertEqual('', input.val())\n\n        input.get(0).value = 'Hello again'\n        t.assertEqual('Hello again', input.val())\n\n        input.val(function(i, val){ return val.replace('Hello', 'Bye') })\n        t.assertEqual('Bye again', input.val())\n\n        t.assertUndefined($('non-existent').val())\n\n        var multiple =\n          $('<select multiple><option selected>1</option><option value=2 selected=\"selected\">a</option><option>3</option></select>')\n        t.assertEqualCollection(['1','2'], multiple.val())\n\n        // FIXME\n        // This is the \"approved\" way of de-selecting an option\n        // Unfortunately, this fails on Chrome 29 for Android\n        multiple.find('option')[0].selected = false\n\n        t.assertEqualCollection(['2'], multiple.val(),\n          \"Expected val() to reflect changes to selected options in a <select multiple> element\")\n      },\n\n      testValVsValueAttr: function(t) {\n        var input\n\n        input = $('<input type=\"text\" value=\"Original\">')\n        input.val('By .val(v)')\n        t.assertEqual('Original', input.attr('value'))\n        t.assertEqual('By .val(v)', input.val())\n\n        input.attr('value', 'By .attr(\"value\", v)')\n        t.assertEqual('By .attr(\"value\", v)', input.attr('value'))\n        t.assertEqual('By .val(v)', input.val())\n\n        // .attr('value', v) will change both\n        // without applying .val(v) first\n        input = $('<input type=\"text\" value=\"Original\">')\n        input.attr('value', 'By .attr(\"value\", v)')\n        t.assertEqual('By .attr(\"value\", v)', input.attr('value'))\n        t.assertEqual('By .attr(\"value\", v)', input.val())\n      },\n\n      testChaining: function(t){\n        t.assert(document.getElementById('nay').innerHTML == \"nay\")\n        $('span.nay').css('color', 'red').html('test')\n        t.assert(document.getElementById('nay').innerHTML == \"test\")\n      },\n\n      testCachingForLater: function(t){\n        var one = $('div')\n        var two = $('span')\n\n        t.assert(one.get(0) !== two.get(0))\n      },\n\n      testPlugins: function(t){\n        var el = $('#some_element').get(0)\n\n        $.fn.plugin = function(){\n          return this.each(function(){ this.innerHTML = 'plugin!' })\n        }\n        $('#some_element').plugin()\n        t.assertEqual('plugin!', el.innerHTML)\n\n        // test if existing Zepto objects receive new plugins\n        if ('__proto__' in {}) {\n          var $some_element = $('#some_element')\n          $.fn.anotherplugin = function(){\n            return this.each(function(){ this.innerHTML = 'anotherplugin!' })\n          }\n          t.assert(typeof $some_element.anotherplugin == 'function')\n          $some_element.anotherplugin()\n          t.assertEqual('anotherplugin!', el.innerHTML)\n        } else\n          window.console && console.warn &&\n          console.warn(\"Browser doesn't support __proto__, skipping test of live extension of existing Zepto objects with plugins\")\n      },\n\n      testAppendPrependBeforeAfter: function(t){\n        $('#beforeafter').append('append')\n        $('#beforeafter').prepend('prepend')\n        $('#beforeafter').before('before')\n        $('#beforeafter').after('after')\n\n        t.assertEqual('before<div id=\"beforeafter\">prependappend</div>after', $('#beforeafter_container').html())\n\n        //testing with TextNode as parameter\n        $('#beforeafter_container').html('<div id=\"beforeafter\"></div>')\n\n        function text(contents){\n          return document.createTextNode(contents)\n        }\n\n        $('#beforeafter').append(text('append'))\n        $('#beforeafter').prepend(text('prepend'))\n        $('#beforeafter').before(text('before'))\n        $('#beforeafter').after(text('after'))\n\n        t.assertEqual('before<div id=\"beforeafter\">prependappend</div>after', $('#beforeafter_container').html())\n\n        $('#beforeafter_container').html('<div id=\"beforeafter\"></div>')\n\n        function div(contents){\n          var el = document.createElement('div')\n          el.innerHTML = contents\n          return el\n        }\n\n        $('#beforeafter').append(div('append'))\n        $('#beforeafter').prepend(div('prepend'))\n        $('#beforeafter').before(div('before'))\n        $('#beforeafter').after(div('after'))\n\n        t.assertEqual(\n          '<div>before</div><div id=\"beforeafter\"><div>prepend</div>'+\n          '<div>append</div></div><div>after</div>',\n          $('#beforeafter_container').html()\n        )\n\n        //testing with Zepto object as parameter\n        $('#beforeafter_container').html('<div id=\"beforeafter\"></div>')\n\n        $('#beforeafter').append($(div('append')))\n        $('#beforeafter').prepend($(div('prepend')))\n        $('#beforeafter').before($(div('before')))\n        $('#beforeafter').after($(div('after')))\n\n        t.assertEqual(\n          '<div>before</div><div id=\"beforeafter\"><div>prepend</div>'+\n          '<div>append</div></div><div>after</div>',\n          $('#beforeafter_container').html()\n        )\n\n        //testing with a zepto object of more than one element as parameter\n        $(document.body).append('<div class=\"append\">append1</div><div class=\"append\">append2</div>')\n        $(document.body).append('<div class=\"prepend\">prepend1</div><div class=\"prepend\">prepend2</div>')\n        $(document.body).append('<div class=\"before\">before1</div><div class=\"before\">before2</div>')\n        $(document.body).append('<div class=\"after\">after1</div><div class=\"after\">after2</div>')\n\n        $('#beforeafter_container').html('<div id=\"beforeafter\"></div>')\n\n        $('#beforeafter').append($('.append'))\n        $('#beforeafter').prepend($('.prepend'))\n        $('#beforeafter').before($('.before'))\n        $('#beforeafter').after($('.after'))\n\n        t.assertEqual(\n          '<div class=\"before\">before1</div><div class=\"before\">before2</div><div id=\"beforeafter\"><div class=\"prepend\">prepend1</div><div class=\"prepend\">prepend2</div>'+\n          '<div class=\"append\">append1</div><div class=\"append\">append2</div></div><div class=\"after\">after1</div><div class=\"after\">after2</div>',\n          $('#beforeafter_container').html()\n        )\n\n        //\n\n        var helloWorlds = [], appendContainer1 = $('<div> <div>Hello</div> <div>Hello</div> </div>'),\n            helloDivs = appendContainer1.find('div')\n\n        helloDivs.append(' world!')\n        helloDivs.each(function() { helloWorlds.push($(this).text()) })\n        t.assertEqual('Hello world!,Hello world!', helloWorlds.join(','))\n\n        //\n\n        var spans = [], appendContainer2 = $('<div> <div></div> <div></div> </div>'),\n            appendDivs = appendContainer2.find('div')\n\n        appendDivs.append($('<span>Test</span>'))\n        appendDivs.each(function() { spans.push($(this).html()) })\n        t.assertEqual('<span>Test</span>,<span>Test</span>', spans.join(','))\n      },\n\n      testAppendNull: function(t){\n        var el = $(document.body)\n        t.assertIdentical(el, el.append(null))\n      },\n\n      testBeforeAfterFragment: function(t){\n        var fragment = $('<div class=fragment />')\n        fragment.before('before').after('after')\n        t.assertLength(1, fragment)\n        t.assert(fragment.hasClass('fragment'))\n      },\n\n      testAppendMultipleArguments: function(t){\n        var el = $('<div><span>original</span></div>')\n        el.append(\n          $('<b>one</b>').get(0),\n          $('<b>two</b><b>three</b>').get(),\n          $('<b>four</b><b>five</b>'),\n          '<b>six</b>'\n        )\n        t.assertEqual('original one two three four five six',\n          $.map(el.children(), function(c){ return $(c).text() }).join(' '))\n      },\n\n      testAppendWithArrayParams: function(t){\n        var zpElement = $('<b>five</b>')\n        var multElements = $('<b>six</b><b>seven</b>')\n        var node = document.createElement('b')\n        node.appendChild(document.createTextNode('four'))\n\n        // append elements on this array\n        var arrElements = ['<b>one</b><b>two</b>', '<b>three</b>', node, zpElement, multElements ]\n        var el = $('<div></div>')\n        el.append(arrElements)\n        t.assertEqual('<b>one</b><b>two</b><b>three</b><b>four</b><b>five</b><b>six</b><b>seven</b>', el.html())\n      },\n\n      testAppendToPrependTo: function(t){\n        // testing with Zepto object\n        function div(contents){\n          var el = document.createElement('div')\n          el.innerHTML = contents\n          return el\n        }\n\n        var ap = $(div('appendto'))\n        var pr = $(div('prependto'))\n\n        var ap2 = ap.appendTo($('#appendtoprependto'))\n        var pr2 = pr.prependTo($('#appendtoprependto'))\n\n        // the object returned is the correct one for method chaining\n        t.assertSame(ap, ap2)\n        t.assertSame(pr, pr2)\n\n        t.assertEqual(\n          '<div id=\"appendtoprependto\"><div>prependto</div>'+\n          '<div>appendto</div></div>',\n          $('#appendtoprependto_container').html()\n        )\n\n        // zepto object with more than one element\n        $(document.body).append('<div class=\"appendto\">appendto1</div><div class=\"appendto\">appendto2</div>')\n        $(document.body).append('<div class=\"prependto\">prependto1</div><div class=\"prependto\">prependto2</div>')\n\n        // selector\n\n        // Note that on IE resetting the parent element to be empty will\n        // cause inserted elements to be emptied out, so we have to re-create\n        // them. This is the same behavior as on jQuery.\n        // (Other browsers don't exhibit this problem.)\n        ap = $(div('appendto'))\n        pr = $(div('prependto'))\n\n        $('#appendtoprependto_container').html('<div id=\"appendtoprependto\"></div>')\n        ap.appendTo('#appendtoprependto')\n        pr.prependTo('#appendtoprependto')\n        t.assertEqual(\n          '<div id=\"appendtoprependto\"><div>prependto</div>'+\n          '<div>appendto</div></div>',\n          $('#appendtoprependto_container').html()\n        )\n\n        // reset test elements\n        ap = $(div('appendto'))\n        pr = $(div('prependto'))\n        $('#appendtoprependto_container').html('<div id=\"appendtoprependto\"></div>')\n        $('.appendto').appendTo($('#appendtoprependto'))\n        $('.prependto').prependTo($('#appendtoprependto'))\n\n        t.assertEqual(\n          '<div id=\"appendtoprependto\"><div class=\"prependto\">prependto1</div><div class=\"prependto\">prependto2</div><div class=\"appendto\">appendto1</div><div class=\"appendto\">appendto2</div></div>',\n          $('#appendtoprependto_container').html()\n        )\n      },\n\n      testInsertBeforeInsertAfter: function(t){\n        // testing with Zepto object\n        function div(contents){\n          var el = document.createElement('div')\n          el.innerHTML = contents\n          return el\n        }\n\n        var ib = $(div('insertbefore'))\n        var ia = $(div('insertafter'))\n\n        var ibia = $('#insertbeforeinsertafter')\n        var ib2 = ib.insertBefore(ibia)\n        var ia2 = ia.insertAfter(ibia)\n\n        // test the object returned is correct for method chaining\n        t.assertEqual(\n          '<div>insertbefore</div><div id=\"insertbeforeinsertafter\">'+\n          '</div><div>insertafter</div>',\n          $('#insertbeforeinsertafter_container').html()\n        )\n\n        // testing with a zepto object of more than one element as parameter\n        $(document.body).append('<div class=\"insertbefore\">insertbefore1</div><div class=\"insertbefore\">insertbefore2</div>')\n        $(document.body).append('<div class=\"insertafter\">insertafter1</div><div class=\"insertafter\">insertafter2</div>')\n\n        $('#insertbeforeinsertafter_container').html('<div id=\"insertbeforeinsertafter\"></div>')\n\n        $('.insertbefore').insertBefore($('#insertbeforeinsertafter'))\n        $('.insertafter').insertAfter($('#insertbeforeinsertafter'))\n\n        t.assertEqual(\n          '<div class=\"insertbefore\">insertbefore1</div><div class=\"insertbefore\">insertbefore2</div>'+\n          '<div id=\"insertbeforeinsertafter\"></div><div class=\"insertafter\">insertafter1</div>'+\n          '<div class=\"insertafter\">insertafter2</div>',\n          $('#insertbeforeinsertafter_container').html()\n        )\n\n        // testing with a selector as parameter\n        $('#insertbeforeinsertafter_container').html('<div id=\"insertbeforeinsertafter\"></div>')\n\n        // reset test elements\n        ib = $(div('insertbefore'))\n        ia = $(div('insertafter'))\n        ib.insertBefore('#insertbeforeinsertafter')\n        ia.insertAfter('#insertbeforeinsertafter')\n\n        t.assertEqual(\n          '<div>insertbefore</div><div id=\"insertbeforeinsertafter\">'+\n          '</div><div>insertafter</div>',\n          $('#insertbeforeinsertafter_container').html()\n        )\n      },\n\n      testAppendEval: function (t) {\n        window.someGlobalVariable = 0\n        try {\n          $('#fixtures').append(\n            '<div><b id=\"newByAppend\">Hi</b>' +\n            '<\\script>this.someGlobalVariable += $(\"#newByAppend\").size()<\\/script></div>'\n          )\n          t.assertIdentical(1, window.someGlobalVariable)\n        } finally {\n          delete window.someGlobalVariable\n        }\n      },\n\n      testNoEvalWithSrc: function (t) {\n        try {\n          window.someGlobalVariable = false\n          $('<\\script src=\"remote.js\">window.someGlobalVariable = true<\\/script>').appendTo('body')\n          t.assert(!window.someGlobalVariable, 'expected SCRIPT with src not to be evaled')\n        } finally {\n          delete window.someGlobalVariable\n        }\n      },\n\n      testHtmlEval: function (t) {\n        window.someGlobalVariable = 0\n        try {\n          $('<div>').appendTo('#fixtures').html(\n            '<div><b id=\"newByHtml\">Hi</b>' +\n            '<\\script>this.someGlobalVariable += $(\"#newByHtml\").size()<\\/script></div>'\n          )\n          t.assertIdentical(1, window.someGlobalVariable)\n        } finally {\n          delete window.someGlobalVariable\n        }\n      },\n\n      testPrependEval: function (t) {\n        window.someGlobalVariable = 0\n        try {\n          $('<div>').appendTo('#fixtures').prepend(\n            '<b id=\"newByPrepend\">Hi</b>' +\n            '<\\script>this.someGlobalVariable += $(\"#newByPrepend\").size()<\\/script>'\n          )\n          t.assertIdentical(1, window.someGlobalVariable)\n        } finally {\n          delete window.someGlobalVariable\n        }\n      },\n\n      testAppendTemplateNonEval: function (t) {\n        try {\n          window.someGlobalVariable = true\n          $('<' + 'script type=\"text/template\">window.someGlobalVariable = false</script' + '>').appendTo('body')\n          t.assert(window.someGlobalVariable)\n\n          window.someGlobalVariable = true\n          $('<' + 'script type=\"text/template\">this.someGlobalVariable = false</script' + '>').appendTo('body')\n          t.assert(window.someGlobalVariable)\n        } finally {\n          delete window.someGlobalVariable\n        }\n      },\n\n      testHtmlTemplateNonEval: function (t) {\n        try {\n          window.someGlobalVariable = true\n          $('<div></div>').appendTo('body')\n            .html('<' + 'script type=\"text/template\">window.someGlobalVariable = false</script' + '>')\n          t.assert(window.someGlobalVariable)\n        } finally {\n          delete window.someGlobalVariable\n        }\n      },\n\n      testRemove: function(t) {\n        var el = $('<div>').appendTo(document.body)\n        t.assertLength(1, el.parent())\n        t.assertIdentical(el, el.remove())\n        t.assertLength(0, el.parent())\n        t.assertIdentical(el, el.remove())  //=> ensure an error isn't raised\n      },\n\n      testNotInDocumentNonEval: function (t) {\n        try {\n          window.someGlobalVariable = 0\n          $('<div></div>')\n            .html('<\\script>window.someGlobalVariable += 1<\\/script>')\n            .appendTo('body')\n          t.assertIdentical(1, window.someGlobalVariable)\n        } finally {\n          delete window.someGlobalVariable\n        }\n      },\n\n      testAddRemoveClass: function(t){\n        var el = $('#some_element').get(0)\n\n        $('#some_element').addClass('green')\n        t.assertEqual('green', el.className)\n        $('#some_element').addClass('green')\n        t.assertEqual('green', el.className)\n        $('#some_element').addClass('red')\n        t.assertEqual('green red', el.className)\n        $('#some_element').addClass('blue red')\n        t.assertEqual('green red blue', el.className)\n        $('#some_element').removeClass('green blue')\n        t.assertEqual('red', el.className)\n\n        $('#some_element').attr('class', ' red green blue ')\n        t.assertEqual(' red green blue ', el.className) // sanity check that WebKit doesn't change original input\n        $('#some_element').removeClass('green')\n        t.assertEqual('red blue', el.className)\n\n        //addClass with function argument\n        $('#some_element').addClass(function(idx,classes){\n          //test the value of \"this\"\n          t.assertEqualCollection($('#some_element'), $(this))\n          //test original classes are being passed\n          t.assertEqual('red blue', this.className)\n          return \"green\"\n        })\n        t.assertEqual('red blue green', el.className)\n\n        // addClass with no argument\n        t.assertEqualCollection($('#some_element'), $('#some_element').addClass())\n        t.assertEqual('red blue green', el.className)\n        t.assertEqualCollection($('#some_element'), $('#some_element').addClass(''))\n        t.assertEqual('red blue green', el.className)\n\n        //removeClass with function argument\n        $('#some_element').removeClass(function(idx,classes){\n          //test the value of \"this\"\n          t.assertEqualCollection($('#some_element'), $(this))\n          //test original classes are being passed\n          t.assertEqual('red blue green', this.className)\n          return \"blue\"\n        })\n        t.assertEqual('red green', el.className)\n\n        $('#some_element').removeClass()\n        t.assertEqual('', el.className)\n      },\n\n      testWindowClasses: function(t){\n        // check that window is agnostic to class related functions\n        $(window).removeClass('non-existing-class')\n        t.refute('className' in window)\n        $(window).addClass('some-class')\n        t.refute('className' in window)\n        t.refute($(window).hasClass('some-class'))\n        $(window).toggleClass('some-class')\n        t.refute('className' in window)\n      },\n\n      testHasClass: function(t){\n        var el = $('#some_element')\n        el.addClass('green')\n\n        t.assert(el.hasClass('green'))\n        t.assert(!el.hasClass('orange'))\n\n        el.addClass('orange')\n        t.assert(el.hasClass('green'))\n        t.assert(el.hasClass('orange'))\n\n        el = $(document.body)\n        t.assert(!el.hasClass('orange'), \"body shouldn't have the class\")\n        el = el.add('#some_element')\n        t.assert(el.hasClass('orange'), \"an element in collection has the class\")\n\n        t.assertFalse(el.hasClass())\n        t.assertFalse(el.hasClass(''))\n      },\n\n      testHasClassEmpty: function(t){\n        var z = $('#doesnotexist')\n        t.assertEqual(0, z.size())\n        t.assertFalse(z.hasClass('a'))\n      },\n\n      testToggleClass: function(t){\n        var el = $('#toggle_element').removeClass()\n\n        t.assertIdentical(el, el.toggleClass('green'))\n        t.assertTrue(el.hasClass('green'))\n        t.assertFalse(el.hasClass('orange'))\n\n        el.toggleClass('orange')\n        t.assertTrue(el.hasClass('green'))\n        t.assertTrue(el.hasClass('orange'))\n\n        el.toggleClass('green')\n        t.assertFalse(el.hasClass('green'))\n        t.assertTrue(el.hasClass('orange'))\n\n        el.toggleClass('orange')\n        t.assertFalse(el.hasClass('green'))\n        t.assertFalse(el.hasClass('orange'))\n\n        el.toggleClass('orange green')\n        t.assertTrue(el.hasClass('orange'))\n        t.assertTrue(el.hasClass('green'))\n\n        el.toggleClass('orange green blue')\n        t.assertFalse(el.hasClass('orange'))\n        t.assertFalse(el.hasClass('green'))\n        t.assertTrue(el.hasClass('blue'))\n\n        el.removeClass()\n\n        el.toggleClass('orange', false)\n        t.assertFalse(el.hasClass('orange'))\n        el.toggleClass('orange', false)\n        t.assertFalse(el.hasClass('orange'))\n\n        el.toggleClass('orange', true)\n        t.assertTrue(el.hasClass('orange'))\n        el.toggleClass('orange', true)\n        t.assertTrue(el.hasClass('orange'))\n\n        //function argument\n        el.toggleClass(function(idx,classes){\n          t.assertIdentical(el.get(0), this)\n          //test original classes are being passed\n          t.assertEqual('orange', this.className)\n          return \"brown\"\n        })\n        t.assertTrue(el.hasClass('brown'))\n\n        el.toggleClass(function(idx,classes){\n          return \"yellow\"\n        }, false)\n        t.assertFalse(el.hasClass('yellow'))\n\n        el.toggleClass(function(idx,classes){\n          return \"yellow\"\n        }, true)\n        t.assert(el.hasClass('yellow'))\n\n        // no/empty argument\n        t.assertIdentical(el, el.toggleClass())\n        t.assertEqual('orange brown yellow', el.get(0).className)\n        t.assertIdentical(el, el.toggleClass(''))\n        t.assertEqual('orange brown yellow', el.get(0).className)\n      },\n\n      testClassSVG: function(t){\n        var svg = $('svg')\n        t.assert(!svg.hasClass('foo'))\n        svg.addClass('foo bar')\n        t.assert(svg.hasClass('foo'))\n        t.assert(svg.hasClass('bar'))\n        svg.removeClass('foo')\n        t.assert(!svg.hasClass('foo'))\n        t.assert(svg.hasClass('bar'))\n        svg.toggleClass('bar')\n        t.assert(!svg.hasClass('foo'))\n        t.assert(!svg.hasClass('bar'))\n      },\n\n      testIndex: function(t){\n        t.assertEqual($(\"p > span\").index(\"#nay\"), 2)\n        t.assertEqual($(\"p > span\").index(\".yay\"), 0)\n        t.assertEqual($(\"span\").index(\"span\"), 0)\n        t.assertEqual($(\"span\").index(\"boo\"), -1)\n\n        t.assertEqual($('#index_test > *').eq(-1).index(), 1)\n      },\n\n      testBoolAttr: function (t) {\n        var el = $('#BooleanInput')\n        t.assertEqual('', el.attr('required'))\n        t.assertUndefined(el.attr('non_existant_attr'))\n      },\n\n      testDocumentReady: function (t) {\n        // Check that ready() callback fired and get Zepto as an argument\n        var arg1, arg2, arg3, arg4\n\n        t.pause()\n        $(function (Z1) {\n          arg1 = Z1\n          $(document).ready(function (Z2) {\n            arg2 = Z2\n            $(document).on('ready', function (Z3) {\n              arg3 = Z3\n              $(document).on('foo ready bar', function (Z4) {\n                arg4 = Z4\n                t.resume(function(){\n                  t.assertIdentical(Zepto, arg1)\n                  t.assertIdentical(Zepto, arg2)\n                  t.assertIdentical(Zepto, arg3)\n                  t.assertIdentical(Zepto, arg4)\n                })\n              })\n            })\n          })\n        })\n      },\n\n      testSlice: function (t) {\n        var $els = $(\"#slice_test div\")\n        t.assertEqual($els.slice().length, 3)\n        t.assertEqual(typeof $els.slice().ready, 'function')\n        t.assertEqual($els.slice(-1)[0].className, 'slice3')\n      },\n\n      testScrollTop: function(t) {\n        var $window = $(window), $body = $(document.body)\n        t.assert($window.scrollTop() >= 0)\n        t.assert($body.scrollTop() >= 0)\n\n        t.assertIdentical($window.scrollTop(20), $window)\n        t.assertIdentical($body.scrollTop(20),   $body)\n      },\n\n      testScrollLeft: function(t) {\n        var $window = $(window), $body = $(document.body)\n        t.assert($window.scrollLeft() >= 0)\n        t.assert($body.scrollLeft() >= 0)\n\n        t.assertIdentical($window.scrollLeft(20), $window)\n        t.assertIdentical($body.scrollLeft(20),   $body)\n      },\n\n      testSort: function(t){\n        var els = $(['eight', 'nine', 'ten', 'eleven'])\n        var result = els.sort(function(a,b){ return b.length > a.length ? -1 : 1 })\n        t.assertIdentical(els, result)\n        t.assertEqual(4, result.size())\n        t.assertEqualCollection(['ten', 'nine', 'eight', 'eleven'], result)\n      }\n    })\n\n    Evidence('EventTest', {\n      tearDown: function(){\n        $('*').unbind()\n      },\n\n      testBind: function(t){\n        var counter = 0\n        $(document.body).bind('click', function(){ counter++ })\n        click($('#some_element').get(0))\n        t.assertEqual(1, counter)\n\n        counter = 0\n        $('#some_element').bind('click mousedown', function(){ counter++ })\n        click($('#some_element').get(0))\n        mousedown($('#some_element').get(0))\n        t.assertEqual(3, counter) // 1 = body click, 2 = element click, 3 = element mousedown\n      },\n\n      testBindWithObject: function(t){\n        var counter = 0, keyCounter = 0, el = $('#some_element'),\n          eventData = {\n            click: function(){ counter++ },\n            keypress: function(){ keyCounter++ }\n          }\n\n        $(document.body).bind(eventData)\n\n        el.trigger('click')\n        el.trigger('click')\n        t.assertEqual(2, counter)\n        el.trigger('keypress')\n        t.assertEqual(1, keyCounter)\n\n        $(document.body).unbind({ keypress: eventData.keypress })\n\n        el.trigger('click')\n        t.assertEqual(3, counter)\n        el.trigger('keypress')\n        t.assertEqual(1, keyCounter)\n      },\n\n      testBindContext: function(t){\n        var context, handler = function(){\n          context = $(this)\n        }\n        $('#empty_test').bind(\"click\",handler)\n        $('#empty_test').bind(\"mousedown\",handler)\n        click($('#empty_test').get(0))\n        t.assertEqualCollection($('#empty_test'), context)\n        context = null\n        mousedown($('#empty_test').get(0))\n        t.assertEqualCollection($('#empty_test'), context)\n      },\n\n      testBindWithCustomArgument: function(t) {\n        var data, numArgs, counter = 0,\n            handler = function(ev, arg) {\n              numArgs = arguments.length,\n              data = ev.data\n              counter = arg.counter\n            }\n\n        $('#some_element').bind('custom', handler)\n        $('#some_element').trigger('custom', { counter: 10 })\n        t.assertEqual(10, counter)\n        t.assertEqual(2, numArgs)\n        t.assertUndefined(data)\n      },\n\n      testBindPreventDefault: function (t) {\n        var link = $('<a href=\"#\"></a>'),\n            prevented = false\n\n        link\n          .appendTo('body')\n          .bind('click', function () {\n            return false\n          })\n          .bind('click', function (e) {\n            prevented = e.isDefaultPrevented()\n          })\n          .trigger('click')\n\n        t.assert(prevented)\n      },\n\n      testCreateEventObject: function(t){\n        var e = $.Event('custom')\n        t.assertEqual('custom', e.type)\n\n        var e2 = new $.Event('custom')\n        t.assertEqual('custom', e2.type)\n\n        var e3 = $.Event('custom', {customKey: 'customValue'})\n        t.assertEqual('custom', e3.type)\n        t.assertEqual('customValue', e3.customKey)\n\n        var e4 = $.Event('custom', {bubbles: false})\n        t.assertFalse(e4.bubbles)\n\n        var e5 = $.Event({ type: 'keyup', keyCode: 40 })\n        t.assertEqual('keyup', e5.type)\n        t.assertEqual(40, e5.keyCode)\n      },\n\n      testTriggerObject: function(t){\n        var el = $('#some_element'),\n            eventType, eventCode\n\n        el.on('keyup', function(e){\n          eventType = e.type\n          eventCode = e.keyCode\n        })\n        el.trigger({ type: 'keyup', keyCode: 40 })\n\n        t.assertEqual('keyup', eventType)\n        t.assertEqual(40, eventCode)\n      },\n\n      testTriggerEventObject: function(t){\n        var data, counter = 0,\n            customEventKey = 0\n\n        var handler = function(ev,customData) {\n          data = ev.data\n          counter = customData.counter\n          customEventKey = ev.customKey\n        }\n\n        var customEventObject = $.Event('custom', { customKey: 20 })\n\n        $('#some_element').bind('custom', handler)\n        $('#some_element').trigger(customEventObject, { counter: 10 })\n\n        t.assertEqual(10, counter)\n        t.assertEqual(20, customEventKey)\n        t.assertUndefined(data)\n      },\n\n      testTriggerEventCancelled: function(t){\n        var event = $.Event('custom'),\n          element = $('<div/>'),\n          isDefaultPrevented = false\n\n        t.refute(event.isDefaultPrevented())\n\n        element.bind('custom', function(e){\n          e.preventDefault()\n          isDefaultPrevented = e.isDefaultPrevented()\n        })\n\n        element.trigger(event)\n\n        t.assertTrue(event.isDefaultPrevented())\n        t.assertTrue(isDefaultPrevented)\n      },\n\n      testTriggerHandler: function(t){\n        t.assertUndefined($('doesnotexist').triggerHandler('submit'))\n\n        var form = $('#trigger_handler form').get(0)\n        $('#trigger_handler').bind('submit', function(e) {\n          t.fail(\"triggerHandler shouldn't bubble\")\n        })\n\n        var executed = []\n        $(form).bind('submit', function(e) {\n          executed.push(\"1\")\n          t.assertEqual(form, e.target)\n          return 1\n        })\n        $(form).bind('submit', function(e) {\n          executed.push(\"2\")\n          t.assertEqual(form, e.target)\n          e.stopImmediatePropagation()\n          return 2\n        })\n        $(form).bind('submit', function(e) {\n          t.fail(\"triggerHandler shouldn't continue after stopImmediatePropagation\")\n        })\n        t.assertIdentical(2, $(form).triggerHandler('submit'))\n        t.assertEqual('1 2', executed.join(' '))\n      },\n\n      testUnbind: function(t){\n        var counter = 0, el = $('#another_element').get(0)\n        var handler = function(){ counter++ }\n        $('#another_element').bind('click mousedown', handler)\n        click(el)\n        mousedown(el)\n        t.assertEqual(2, counter)\n\n        $('#another_element').unbind('click', handler)\n        click(el)\n        t.assertEqual(2, counter)\n        mousedown(el)\n        t.assertEqual(3, counter)\n\n        $('#another_element').unbind('mousedown')\n        mousedown(el)\n        t.assertEqual(3, counter)\n\n        $('#another_element').bind('click mousedown', handler)\n        click(el)\n        mousedown(el)\n        t.assertEqual(5, counter)\n\n        $('#another_element').unbind()\n        click(el)\n        mousedown(el)\n        t.assertEqual(5, counter)\n      },\n\n      testUnbindWithNamespace: function(t){\n        var count = 0\n        $(\"#namespace_test\").bind(\"click.bar\", function() { count++ })\n        $(\"#namespace_test\").bind(\"click.foo\", function() { count++ })\n        $(\"#namespace_test\").bind(\"mousedown.foo.bar\", function() { count++ })\n\n        $(\"#namespace_test\").trigger(\"click\")\n        t.assertEqual(2, count)\n\n        $(\"#namespace_test\").unbind(\"click.baz\")\n        $(\"#namespace_test\").trigger(\"click\")\n        t.assertEqual(4, count)\n\n        $(\"#namespace_test\").unbind(\"click.foo\")\n        $(\"#namespace_test\").trigger(\"click\")\n        t.assertEqual(5, count)\n\n        $(\"#namespace_test\").trigger(\"mousedown\")\n        t.assertEqual(6, count)\n\n        $(\"#namespace_test\").unbind(\".bar\")\n        $(\"#namespace_test\").trigger(\"click\").trigger(\"mousedown\")\n        t.assertEqual(6, count)\n      },\n\n      testDelegate: function(t){\n        var counter = 0, pcounter = 0\n        $(document.body).delegate('#some_element', 'click', function(){ counter++ })\n        $('p').delegate('span.yay', 'click', function(){ counter++ })\n        $(document.body).delegate('p', 'click', function(){ pcounter++ })\n\n        click($('#some_element').get(0))\n        t.assertEqual(1, counter)\n\n        click($('span.yay').get(0))\n        t.assertEqual(2, counter)\n\n        click($('span.nay').get(0))\n        t.assertEqual(2, counter)\n\n        click($('p').get(0))\n        t.assertEqual(3, pcounter)\n      },\n\n      testDelegateBlurFocus: function(t) {\n        var counter = 0\n        $('#delegate_blur_test').delegate('input', 'blur', function(){ counter++ })\n\n        $('#delegate_blur_test').find('input').focus()\n        $('#delegate_blur_test').find('input').blur()\n        t.assertEqual(1, counter)\n\n        $('#delegate_blur_test').find('input').focus()\n        $('#delegate_blur_test').find('input').blur()\n        t.assertEqual(2, counter)\n\n        $('#delegate_focus_test').delegate('input', 'focus', function(){ counter++ })\n\n        $('#delegate_focus_test').find('input').focus()\n        $('#delegate_focus_test').find('input').blur()\n        t.assertEqual(3, counter)\n\n        $('#delegate_focus_test').find('input').focus()\n        $('#delegate_focus_test').find('input').blur()\n        t.assertEqual(4, counter)\n      },\n\n      testDelegateNamespacedBlurFocus: function(t) {\n        var counter = 0\n        $('#delegate_blur_test').delegate('input', 'blur.namespace_test', function(){ counter++ })\n\n        $('#delegate_blur_test').find('input').focus()\n        $('#delegate_blur_test').find('input').blur()\n        t.assertEqual(1, counter)\n\n        $('#delegate_blur_test').find('input').focus()\n        $('#delegate_blur_test').find('input').blur()\n        t.assertEqual(2, counter)\n\n        $('#delegate_focus_test').delegate('input', 'focus.namespace_test', function(){ counter++ })\n\n        $('#delegate_focus_test').find('input').focus()\n        $('#delegate_focus_test').find('input').blur()\n        t.assertEqual(3, counter)\n\n        $('#delegate_focus_test').find('input').focus()\n        $('#delegate_focus_test').find('input').blur()\n        t.assertEqual(4, counter)\n      },\n\n      testUndelegateNamespacedBlurFocus: function(t) {\n        var el, counter = 0\n\n        el = $('#delegate_blur_test')\n\n        el.delegate('input', 'blur.test', function(){ counter++ })\n        el.find('input').focus().blur()\n        t.assertEqual(1, counter, 'expected handler to be triggered')\n\n        el.undelegate('input', '.test')\n        el.find('input').focus().blur()\n        t.assertEqual(1, counter, 'expected handler to unbind')\n\n        el = $('#delegate_focus_test')\n\n        el.delegate('input', 'focus.test', function(){ counter++ })\n        el.find('input').focus().blur()\n        t.assertEqual(2, counter, 'expected handler to be triggered')\n\n        el.undelegate('input', '.test')\n        el.find('input').focus().blur()\n        t.assertEqual(2, counter, 'expected handler to unbind')\n      },\n\n      testDelegateReturnFalse: function(t){\n        $(document.body).delegate('#link_that_will_be_prevented', 'click', function(){\n          return false\n        })\n\n        var event = $.Event('click')\n        $('#link_that_will_be_prevented').trigger(event)\n\n        t.assertTrue(event.isDefaultPrevented())\n\n        t.pause()\n        setTimeout(function(){\n          t.resume(function(){\n            var text = $('#link_target_iframe')[0].contentDocument.body.textContent\n            t.assert(!text.match(/Hello from iframe/))\n          })\n        }, 500)\n      },\n\n      testDelegateReturnValueShouldntPreventDefault: function(t){\n        $(document.body).delegate('#link_that_will_be_prevented', 'click', function(){\n        })\n\n        var event = $.Event('click')\n        $('#link_that_will_be_prevented').trigger(event)\n\n        t.assertFalse(event.isDefaultPrevented())\n\n        t.pause()\n        setTimeout(function(){\n          t.resume(function(){\n            var text = $('#link_target_iframe')[0].contentDocument.body.textContent\n            t.assert(text.match(/Hello from iframe/))\n          })\n        }, 500)\n      },\n\n      testDelegateWithObject: function(t){\n        var counter = 0, received, el = $('p').first(),\n          eventData = {\n            click: function(){ counter++ },\n            custom: function(e, arg){ received = arg }\n          }\n\n        $(document.body).delegate('p', eventData)\n\n        el.trigger('click')\n        t.assertEqual(1, counter)\n        el.trigger('click')\n        t.assertEqual(2, counter)\n        el.trigger('custom', 'boo')\n        t.assertEqual('boo', received)\n\n        $(document.body).undelegate('p', {custom: eventData.custom})\n\n        el.trigger('click')\n        t.assertEqual(3, counter)\n        el.trigger('custom', 'bam')\n        t.assertEqual('boo', received)\n      },\n\n      testDelegateWithCustomArgument: function(t) {\n        var received\n        $(document).delegate('#some_element', 'custom', function(e, arg, more){ received = arg + more })\n        $('p').delegate('span.yay', 'custom', function(e, arg){ received = arg })\n        $(document).delegate('p', 'custom', function(e, arg){ received = arg })\n\n        $('#some_element').trigger('custom', 'one')\n        t.assertEqual('oneundefined', received)\n        $('#some_element').trigger('custom', ['one', 'two'])\n        t.assertEqual('onetwo', received)\n\n        $('span.yay').trigger('custom', 'boom')\n        t.assertEqual('boom', received)\n        $('span.yay').trigger('custom', ['bam', 'boom'])\n        t.assertEqual('bam', received)\n\n        $('span.nay').trigger('custom', 'noes')\n        t.assertEqual('noes', received)\n\n        $('p').first().trigger('custom', 'para')\n        t.assertEqual('para', received)\n      },\n\n      testDelegateEventProxy: function(t){\n        var content\n        $('div#delegate_test').delegate('span.second-level', 'click', function(e){\n          t.assertEqual($('span.second-level').get(0), this)\n          t.assertEqual($('span.second-level').get(0), e.currentTarget)\n          t.refuteEqual($('span.second-level').get(0), e.originalEvent.currentTarget)\n          t.assertEqual($('div#delegate_test').get(0), e.liveFired)\n          content = $(this).html()\n        })\n        click($('span.second-level').get(0))\n        t.assertEqual('hi', content)\n\n        var fired = false\n        if (window.location.hash.length) window.location.hash = ''\n        $('div#delegate_test').html('<a href=\"#foo\"></a>')\n        $('div#delegate_test').delegate('a', 'click', function(e){\n          e.preventDefault()\n          fired = true\n        })\n        click($('div#delegate_test a').get(0))\n        t.assert(fired)\n        t.refuteEqual('#foo', window.location.hash)\n\n        fired = false\n        if (window.location.hash.length) window.location.hash = ''\n        $('div#delegate_test').html('<a href=\"#bar\"></a>')\n        $('div#delegate_test a').trigger('click')\n        t.assert(fired)\n        t.refuteEqual('#bar', window.location.hash)\n      },\n\n      testUndelegate: function(t){\n        var count = 0, handler = function() { count++ }\n        $(\"#undelegate_test\").bind(\"click mousedown\", handler)\n        $(\"#undelegate_test\").delegate(\"span.first-level\", \"click mousedown\", handler)\n        $(\"#undelegate_test\").delegate(\"span.second-level\", \"click mousedown\", handler)\n        $(\"#undelegate_test span.second-level\").trigger(\"click\")\n        t.assertEqual(3, count)\n\n        $(\"#undelegate_test\").undelegate(\"span.second-level\", \"click\", handler)\n        $(\"#undelegate_test span.second-level\").trigger(\"click\")\n        t.assertEqual(5, count)\n\n        $(\"#undelegate_test\").undelegate(\"span.first-level\")\n        $(\"#undelegate_test span.second-level\").trigger(\"click\")\n        t.assertEqual(6, count)\n\n        $(\"#undelegate_test\").unbind(\"click\")\n        $(\"#undelegate_test span.second-level\").trigger(\"click\")\n        t.assertEqual(6, count)\n\n        $(\"#undelegate_test span.second-level\").trigger(\"mousedown\")\n        t.assertEqual(8, count)\n\n        $(\"#undelegate_test\").undelegate()\n        $(\"#undelegate_test span.second-level\").trigger(\"mousedown\")\n        t.assertEqual(8, count)\n      },\n\n      testLive: function(t){\n        var counter = 0\n        $('p.live').live('click', function(){ counter++ })\n\n        $(document.body).append('<p class=\"live\" id=\"live_1\"></p>')\n        $(document.body).append('<p class=\"live\" id=\"live_2\"></p>')\n\n        click($('#live_1').get(0))\n        click($('#live_2').get(0))\n\n        $('p.live').remove()\n        $(document.body).append('<p class=\"live\" id=\"live_this_test\"></p>')\n\n        $('p.live').live('click', function(){\n          t.assertEqual(document.getElementById('live_this_test'), this)\n        })\n        click($('#live_this_test').get(0))\n\n        t.assertEqual(3, counter)\n      },\n\n      testDie: function(t){\n        var count = 0, handler = function() { count++ }\n        $(\"#another_element\").live(\"click mousedown\", handler)\n        $(\"#another_element\").trigger(\"click\")\n        t.assertEqual(1, count)\n\n        $(\"#another_element\").die(\"click\", handler)\n        $(\"#another_element\").trigger(\"click\")\n        t.assertEqual(1, count)\n\n        $(\"#another_element\").trigger(\"mousedown\")\n        t.assertEqual(2, count)\n\n        $(\"#another_element\").die()\n        $(\"#another_element\").trigger(\"mousedown\")\n        t.assertEqual(2, count)\n      },\n\n      testOn: function(t){\n        var el = $('#some_element'), node = el.get(0), ret,\n          bindTriggered = 0, delegateTriggered = 0\n\n        ret = el.on('click', function(e){\n          bindTriggered++\n          t.assertIdentical(node, this)\n        })\n          .on({ click: function(){bindTriggered++} })\n        t.assertIdentical(el, ret)\n\n        ret = $(document.body).on('click', 'div', function(e){\n          delegateTriggered++\n          t.assertIdentical(node, this)\n        })\n          .on({ click: function(){delegateTriggered++} }, '*[id^=some]')\n        t.assertIdentical(document.body, ret.get(0))\n\n        click(node)\n        t.assertEqual(2, bindTriggered, \"bind handlers\")\n        t.assertEqual(2, delegateTriggered, \"delegate handlers\")\n      },\n\n      testOnReturnFalse: function(t){\n        var el = $('#some_element')\n\n        el.on('click', function(){\n          setTimeout(function(){\n            t.resume(function(){})\n          }, 10)\n          t.assert(true, \"should have been called\")\n          return false\n        })\n        $(document.body).on('click', function(){\n          t.refute(true, \"the event should have been stopped\")\n        })\n\n        t.pause()\n        click(el.get(0))\n      },\n\n      testOff: function(t){\n        var el = $('#some_element'), bindTriggered = 0, delegateTriggered = 0,\n          handler = function(){ bindTriggered++ }\n\n        el.bind('click', handler).bind('click', function(){ bindTriggered++ })\n        el.live('click', function(){ delegateTriggered++ })\n\n        click(el.get(0))\n        t.assertEqual(2, bindTriggered, \"bind handlers before unbind\")\n        t.assertEqual(1, delegateTriggered, \"delegate handlers before unbind\")\n\n        el.off('click', handler)\n        $(document.body).off('click', '#some_element')\n\n        click(el.get(0))\n        t.assertEqual(3, bindTriggered, \"bind handlers\")\n        t.assertEqual(1, delegateTriggered, \"delegate handlers\")\n      },\n\n      testOne: function(t){\n        var counter = 0, context, received, el = $('#some_element')\n        $(document.body).one('click', function(e, arg, more){\n          context = this\n          counter++\n          received = arg + more\n          t.assertIn('preventDefault', e)\n          return false\n        })\n\n        var evt = $.Event('click')\n        el.trigger(evt, ['one', 'two'])\n        t.assertEqual(1, counter)\n        t.assertEqual('onetwo', received)\n        t.assertIdentical(document.body, context)\n        t.assertTrue(evt.isDefaultPrevented())\n\n        el.trigger('click')\n        t.assertEqual(1, counter, \"the event handler didn't unbind itself\")\n      },\n\n      testOneWithObject: function(t){\n        var counter = 0, el = $('#some_element')\n        $(document.body).one({\n          click: function() { counter++ },\n          custom: function() { counter-- }\n        })\n\n        el.trigger('click')\n        t.assertEqual(1, counter)\n        el.trigger('click')\n        t.assertEqual(1, counter)\n\n        el.trigger('custom')\n        t.assertEqual(0, counter)\n        el.trigger('custom')\n        t.assertEqual(0, counter)\n      },\n\n      testDOMEventWrappers: function(t){\n        var events = ('blur focus focusin focusout load resize scroll unload click dblclick '+\n          'mousedown mouseup mousemove mouseover mouseout '+\n          'change select keydown keypress keyup error').split(' ')\n\n        var el = $('#another_element'), count = 0\n\n        events.forEach(function(event){\n          t.assertTrue($.isFunction(el[event]), 'event type: ' + event)\n        })\n\n        el.click(function(){ count++ })\n        click(el.get(0))\n\n        t.assertEqual(1, count)\n      },\n\n      testCustomEvents: function (t) {\n        var el = $(document.body)\n\n        el.bind('custom', function(evt, a, b) {\n          t.assertEqual(a, 1)\n          t.assertEqual(b, 2)\n          el.unbind()\n        })\n        el.trigger('custom', [1, 2])\n\n        el.bind('custom', function(evt, a) {\n          t.assertEqual(a, 1)\n          el.unbind()\n        })\n        el.trigger('custom', 1)\n\n        var eventData = {z: 1}\n        el.bind('custom', function(evt, a) {\n          t.assertEqual(a, eventData)\n          el.unbind()\n        })\n        el.trigger('custom', eventData)\n      },\n\n      testSpecialEvent: function (t) {\n        var clickEvent     = $.Event('click'),\n            mouseDownEvent = $.Event('mousedown'),\n            mouseUpEvent   = $.Event('mouseup'),\n            mouseMoveEvent = $.Event('mousemove'),\n            submitEvent    = $.Event('submit')\n\n        t.assertEqual(MouseEvent, clickEvent.constructor)\n        t.assertEqual(MouseEvent, mouseDownEvent.constructor)\n        t.assertEqual(MouseEvent, mouseUpEvent.constructor)\n        t.assertEqual(MouseEvent, mouseMoveEvent.constructor)\n        t.assertEqual(Event,      submitEvent.constructor)\n      }\n    })\n  })()\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "vendor/evidence.js",
    "content": "/*  evidence.js, version 0.6\n *\n *  Copyright (c) 2009 Tobie Langel (http://tobielangel.com)\n *\n *  evidence.js is freely distributable under the terms of an MIT-style license.\n *--------------------------------------------------------------------------*/\n\n(function(global) {\n  var originalEvidence = global.Evidence,\n      originalOnload   = global.onload;\n\n  function Evidence() {\n    TestCase.extend.apply(TestCase, arguments);\n  }\n\n  function noConflict() {\n    global.Evidence = originalEvidence;\n    return Evidence;\n  }\n\n  Evidence.noConflict = noConflict;\n  Evidence.VERSION    = '0.6';\n\nvar FILE_REGEXP = /.*?\\/(\\w+\\.html)(.*)/;\n\nfunction getNameFromFile() {\n  return (global.location || '').toString().replace(FILE_REGEXP, '$1');\n}\n\nfunction chain(subclass, superclass) {\n  function Subclass() {}\n  Subclass.prototype = superclass.prototype;\n  subclass.prototype = new Subclass();\n  subclass.prototype.constructor = subclass;\n  return subclass;\n}\n\nfunction defer(block, context) {\n  if ('setTimeout' in global) {\n    window.setTimeout(function() {\n      block.call(context);\n    }, 10);\n  } else {\n    block.call(context);\n  }\n}\nfunction AssertionSkippedError(message) {\n  this.message = message;\n}\n\nAssertionSkippedError.displayName = 'AssertionSkippedError';\n\n(function(p) {\n  p.name = 'AssertionSkippedError';\n})(AssertionSkippedError.prototype);\nEvidence.AssertionSkippedError = AssertionSkippedError;\nfunction AssertionFailedError(message, template, args) {\n  this.message = message;\n  this.template = template || '';\n  this.args = args;\n}\n\nAssertionFailedError.displayName = 'AssertionFailedError';\n\n(function(p) {\n  p.name = 'AssertionFailedError';\n})(AssertionFailedError.prototype);\nEvidence.AssertionFailedError = AssertionFailedError;\nfunction AssertionMessage(message, template, args) {\n  this.message = message.replace(/%/g, '%%');\n  this.template = template || '';\n  this.args = args;\n}\n\nAssertionMessage.displayName = 'AssertionMessage';\n\n(function(p) {\n  function toString() {\n    return UI.printf(this.message + this.template, this.args);\n  }\n  p.toString = toString;\n})(AssertionMessage.prototype);\nEvidence.AssertionMessage = AssertionMessage;\n\nvar Assertions = (function() {\n  function _assertExpression(expression, message, template) {\n    /*for (var i=0; i < 100000; i++) {\n      (function(){})()\n    }*/\n    if (expression) {\n      this.addAssertion();\n    } else {\n      var args = Array.prototype.slice.call(arguments, 3);\n      throw new AssertionFailedError(message, template, args);\n    }\n  }\n\n  function skip(message) {\n    throw new AssertionSkippedError(message || 'Skipped!');\n  }\n\n  function fail(message) {\n    this._assertExpression(false, message || 'Flunked!');\n  }\n\n  function assert(test, message) {\n    this._assertExpression(\n      !!test,\n      message || 'Failed assertion.',\n      'Expected %o to evaluate to true.', test\n    );\n  }\n\n  function refute(test, message) {\n    this._assertExpression(\n      !test,\n      message || 'Failed refutation.',\n      'Expected %o to evaluate to false.', test\n    );\n  }\n\n  function assertTrue(test, message) {\n    this._assertExpression(\n      (test === true),\n      message || 'Failed assertion.',\n      'Expected %o to be true.', test\n    );\n  }\n\n  function refuteTrue(test, message) {\n    this._assertExpression(\n      (test !== true),\n      message || 'Failed refutation.',\n      'Expected %o to not be true.', test\n    );\n  }\n\n  function assertNull(test, message) {\n    this._assertExpression(\n      (test === null),\n      message || 'Failed assertion.',\n      'Expected %o to be null.', test\n    );\n  }\n\n  function refuteNull(test, message) {\n    this._assertExpression(\n      (test !== null),\n      message || 'Failed refutation.',\n      'Expected %o to not be null.', test\n    );\n  }\n\n  function assertUndefined(test, message) {\n    this._assertExpression(\n      (typeof test === 'undefined'),\n      message || 'Failed assertion.',\n      'Expected %o to be undefined.', test\n    );\n  }\n\n  function refuteUndefined(test, message) {\n    this._assertExpression(\n      (typeof test !== 'undefined'),\n      message || 'Failed refutation.',\n      'Expected %o to not be undefined.', test\n    );\n  }\n\n  function assertFalse(test, message) {\n    this._assertExpression(\n      (test === false),\n      message || 'Failed assertion.',\n      'Expected %o to be false.', test\n    );\n  }\n\n  function refuteFalse(test, message) {\n    this._assertExpression(\n      (test !== false),\n      message || 'Failed refutation.',\n      'Expected %o to not be false.', test\n    );\n  }\n\n  function assertEqual(expected, actual, message) {\n    this._assertExpression(\n      (expected == actual),\n      message || 'Failed assertion.',\n      'Expected %o to be == to %o.', actual, expected\n    );\n  }\n\n  function refuteEqual(expected, actual, message) {\n    this._assertExpression(\n      (expected != actual),\n      message || 'Failed refutation.',\n      'Expected %o to be != to %o.', actual, expected\n    );\n  }\n\n  function assertIdentical(expected, actual, message) {\n    this._assertExpression(\n      (expected === actual),\n      message || 'Failed assertion.',\n      'Expected %o to be === to %o.', actual, expected\n    );\n  }\n\n  function refuteIdentical(expected, actual, message) {\n    this._assertExpression(\n      (expected !== actual),\n      message || 'Failed refutation.',\n      'Expected %o to be !== to %o.', actual, expected\n    );\n  }\n\n  function assertIn(property, object, message) {\n    this._assertExpression(\n      (property in object),\n      message || 'Failed assertion.',\n      'Expected \"%s\" to be a property of %o.', property, object\n    );\n  }\n\n  function refuteIn(property, object, message) {\n    this._assertExpression(\n      !(property in object),\n      message || 'Failed refutation.',\n      'Expected \"%s\" to not be a property of %o.', property, object\n    );\n  }\n\n  return {\n    _assertExpression: _assertExpression,\n    skip: skip,\n    assert: assert,\n    refute: refute,\n    assertNot: refute,\n    assertTrue: assertTrue,\n    assertNull: assertNull,\n    assertUndefined: assertUndefined,\n    assertFalse: assertFalse,\n    assertIdentical: assertIdentical,\n    refuteIdentical: refuteIdentical,\n    assertEqual: assertEqual,\n    refuteEqual: refuteEqual,\n    assertIn: assertIn,\n    refuteIn: refuteIn,\n    fail: fail,\n    flunk: fail\n  };\n})();\n  Evidence.Assertions = Assertions;\nfunction TestCase(methodName) {\n  this._methodName = methodName;\n  this.name = methodName;\n}\n\n(function() {\n  function extend(name, methods) {\n    function TestCaseSubclass(methodName) {\n      TestCase.call(this, methodName);\n    }\n\n    if (!methods) {\n      methods = name;\n      name = getNameFromFile();\n    }\n\n    chain(TestCaseSubclass, this);\n    TestCaseSubclass.displayName = name;\n    TestCaseSubclass.extend = extend;\n\n    for(var prop in methods) {\n      TestCaseSubclass.prototype[prop] = methods[prop];\n    }\n    TestCase.subclasses.push(TestCaseSubclass);\n    return TestCaseSubclass;\n  }\n\n  function AssertionsMixin() {}\n  AssertionsMixin.prototype = Assertions;\n  TestCase.prototype = new AssertionsMixin();\n  TestCase.constructor = TestCase;\n\n  TestCase.displayName = 'TestCase';\n  TestCase.extend      = extend;\n  TestCase.subclasses  = [];\n  TestCase.defaultTimeout = 10000;\n})();\n\n(function(p) {\n  function run(result) {\n    if (result) { this._result = result; }\n    try {\n      if (this._nextAssertions) {\n        this._result.restartTest(this);\n        this._nextAssertions(this);\n      } else {\n        /*this._globalProperties = objectKeys(global);*/\n        this._result.startTest(this);\n        this.setUp(this);\n        this[this._methodName](this);\n      }\n    } catch(e) {\n      this._filterException(e);\n    } finally {\n      if (this._paused) {\n        this._result.pauseTest(this);\n      } else {\n        try {\n          this.tearDown(this);\n        } catch(e) {\n          this._filterException(e);\n        } finally {\n          this._nextAssertions = null;\n          this._result.stopTest(this);\n          defer(function() {\n            this.parent.next();\n          }, this);\n        }\n      }\n    }\n  }\n\n  function _filterException(e) {\n    var name = e.name;\n    switch(name) {\n      case 'AssertionFailedError':\n        this._result.addFailure(this, e);\n        break;\n      case 'AssertionSkippedError':\n        this._result.addSkip(this, e);\n        break;\n      default:\n        this._result.addError(this, e + ('stack' in e ? \"\\n\"+e.stack : ''));\n    }\n  }\n\n  function pause(assertions) {\n    this._paused = true;\n    var self = this;\n    if (assertions) { this._nextAssertions = assertions; }\n    self._timeoutId = global.setTimeout(function() {\n      self.resume(function() {\n        self.fail('Test timed out. Testing was not resumed after being paused.');\n      });\n    }, TestCase.defaultTimeout);\n  }\n\n  function resume(assertions) {\n    if (this._paused) { // avoid race conditions\n      this._paused = false;\n      global.clearTimeout(this._timeoutId);\n      if (assertions) { this._nextAssertions = assertions; }\n      this.run();\n    }\n  }\n\n  function size() {\n    return 1;\n  }\n\n  function toString() {\n    return this.constructor.displayName + '#' + this.name;\n  }\n\n  function addAssertion() {\n    this._result.addAssertion();\n  }\n\n  p.run              = run;\n  p.addAssertion     = addAssertion;\n  p._filterException = _filterException;\n  p.pause            = pause;\n  p.resume           = resume;\n  p.size             = size;\n  p.toString         = toString;\n  p.setUp            = function() {};\n  p.tearDown         = function() {};\n})(TestCase.prototype);\n  Evidence.TestCase = TestCase;\nfunction TestSuite(name, tests) {\n  this.name = name;\n  this._tests = [];\n  if (tests) {\n    this.push.apply(this, tests);\n  }\n}\n\nTestSuite.displayName = 'TestSuite';\n\n(function(p) {\n  function run(result) {\n    this._index = 0;\n    this._result = result;\n    result.startSuite(this);\n    this.next();\n    return result;\n  }\n\n  function next() {\n    var next = this._tests[this._index];\n    if (next) {\n      this._index++;\n      next.run(this._result);\n    } else {\n      this._result.stopSuite(this);\n      if (this.parent) {\n        this.parent.next();\n      } else {\n        this._result.stop(new Date());\n      }\n    }\n  }\n\n  function push() {\n    for (var i = 0, length = arguments.length; i < length; i++) {\n      var test = arguments[i];\n      test.parent = this;\n      this._tests.push(test);\n    }\n  }\n\n  function addTest(test) {\n    test.parent = this;\n    this._tests.push(test);\n  }\n\n  function addTests(tests) {\n    for (var i = 0, length = tests.length; i < length; i++) {\n      this.addTest(tests[i]);\n    }\n  }\n\n  function size() {\n    var tests  = this._tests,\n        length = tests.length,\n        sum    = 0;\n\n    for (var i = 0; i < length; i++) {\n      sum += tests[i].size();\n    }\n    return sum;\n  }\n\n  function isEmpty() {\n    return this.size() === 0;\n  }\n\n  function toString() {\n    return this.name;\n  }\n  p.run  = run;\n  p.next = next;\n  p.push = push;\n  p.size = size;\n  p.isEmpty = isEmpty;\n  p.toString = toString;\n})(TestSuite.prototype);\n  Evidence.TestSuite = TestSuite;\nfunction TestRunner() {\n}\n\nTestRunner.displayName = 'TestRunner';\n\n(function(p) {\n  function run(suite) {\n    suite.parent = null;\n    var result = this._makeResult();\n    result.start(new Date());\n    suite.run(result);\n    return result;\n  }\n\n  function _makeResult() {\n    return new TestResult();\n  }\n\n  p.run = run;\n  p._makeResult = _makeResult;\n})(TestRunner.prototype);\n  Evidence.TestRunner = TestRunner;\nfunction TestLoader() {\n}\n\nTestLoader.displayName = 'TestLoader';\n\n(function(p) {\n  function loadTestsFromTestCase(testcaseClass) {\n    var suite = new TestSuite(testcaseClass.displayName),\n        props = this.getTestCaseNames(testcaseClass);\n    for (var i=0; i < props.length; i++) {\n      suite.push(new testcaseClass(props[i]));\n    }\n    return suite;\n  }\n\n  function loadTestsFromTestCases(testcases) {\n    var suite = new TestSuite(getNameFromFile());\n    for (var i = 0; i < testcases.length; i++) {\n      var testcase = testcases[i];\n      var subSuite = defaultLoader.loadTestsFromTestCase(testcase);\n      if (!subSuite.isEmpty()) { suite.push(subSuite); }\n    }\n    return suite;\n  }\n\n  function getTestCaseNames(testcaseClass) {\n    var results = [],\n        proto = testcaseClass.prototype,\n        prefix = this.testMethodPrefix;\n\n    for (var property in proto) {\n      if (property.indexOf(prefix) === 0) {\n        results.push(property);\n      }\n    }\n    return results.sort();\n  }\n\n  function loadRegisteredTestCases() {\n    return loadTestsFromTestCases(TestCase.subclasses);\n  }\n\n  p.loadTestsFromTestCase = loadTestsFromTestCase;\n  p.loadRegisteredTestCases = loadRegisteredTestCases;\n  p.loadTestsFromTestCases = loadTestsFromTestCases;\n  p.testMethodPrefix = 'test';\n  p.getTestCaseNames = getTestCaseNames;\n\n})(TestLoader.prototype);\n  Evidence.TestLoader = TestLoader;\nfunction AutoRunner() {\n  if (global.console && global.console.log) {\n    this.logger = Logger;\n  } else if (Object.prototype.toString.call(global.environment) === '[object Environment]' && global.print) {\n    this.logger = CommandLineLogger;\n  } else {\n    this.logger = PopupLogger;\n  }\n  this.autoRun   = true;\n  this.verbosity = Logger.INFO;\n  this.runner    = ConsoleTestRunner;\n}\n\n(function() {\n  function run(options) {\n    var autoRunner = new this();\n    options = options || autoRunner.retrieveOptions();\n    autoRunner.processOptions(options);\n    if (autoRunner.autoRun) { autoRunner.run() };\n  }\n\n  AutoRunner.run = run;\n  AutoRunner.displayName = 'AutoRunner';\n  AutoRunner.LOGGERS = {\n    console:      Logger,\n    popup:        PopupLogger,\n    command_line: CommandLineLogger\n  };\n\n  AutoRunner.RUNNERS = {\n    console: ConsoleTestRunner\n  };\n})();\n\n(function(p) {\n  function run() {\n    var logger = new this.logger(this.verbosity),\n        runner = new this.runner(logger),\n        suite = defaultLoader.loadRegisteredTestCases();\n    if (suite._tests.length <= 1) {\n      suite = suite._tests[0];\n    }\n    return runner.run(suite);\n  }\n\n  function processQueryString(str) {\n    var results = {};\n    str = (str + '').match(/^(?:[^?#]*\\?)([^#]+?)(?:#.*)?$/);\n    str = str && str[1];\n\n    if (!str) { return results; }\n\n    var pairs = str.split('&'),\n        length = pairs.length;\n    if (!length) { return results; }\n\n    for (var i = 0; i < length; i++) {\n      var pair  = pairs[i].split('='),\n          key   = decodeURIComponent(pair[0]),\n          value = pair[1];\n      value = value ? decodeURIComponent(value) : true;\n      results[key] = value;\n    }\n    return results;\n  }\n\n  function processArguments(args) { // RHINO\n    var results = {};\n\n    for (var i = 0; i < args.length; i++) {\n      var arg = args[i];\n      if (arg.indexOf('-') === 0) {\n        var value = args[i + 1];\n        if (value && value.indexOf('-') !== 0) {\n          i++;\n        } else {\n          value = true;\n        }\n        results[arg.substr(1)] = value;\n      }\n    }\n    return results;\n  }\n\n  function retrieveOptions() {\n    if (global.location) {\n      return this.processQueryString(global.location);\n    }\n    if (global.arguments) {\n      return this.processArguments(global.arguments);\n    }\n    return {};\n  }\n\n  function processOptions(options) {\n    for(var key in options) {\n      var value = options[key];\n      switch(key) {\n        case 'timeout':\n          TestCase.defaultTimeout = global.parseFloat(value) * 1000;\n          break;\n        case 'run':\n          this.autoRun = value === 'false' ? false : true;\n          break;\n        case 'logger':\n          this.logger = AutoRunner.LOGGERS[value];\n          break;\n        case 'verbosity':\n          var i = global.parseInt(value);\n          this.verbosity = global.isNaN(i) ? Logger[value] : i;\n          break;\n        case 'runner':\n          this.runner = AutoRunner.RUNNERS[value];\n          break;\n      }\n    }\n  }\n\n  p.run = run;\n  p.processQueryString = processQueryString;\n  p.processArguments = processArguments;\n  p.retrieveOptions = retrieveOptions;\n  p.processOptions = processOptions;\n})(AutoRunner.prototype);\n  Evidence.AutoRunner = AutoRunner;\nfunction TestResult() {\n  this.testCount      = 0;\n  this.assertionCount = 0;\n  this.skipCount      = 0;\n  this.skips          = [];\n  this.failureCount   = 0;\n  this.failures       = [];\n  this.errors         = [];\n  this.errorCount     = 0;\n  this.testCount      = 0;\n}\n\nTestResult.displayName = 'TestResult';\n\n(function(p) {\n  function addAssertion() {\n    this.assertionCount++;\n  }\n\n  function addSkip(testcase, reason) {\n    this.skipCount++;\n    this.skips.push(reason);\n  }\n\n  function addFailure(testcase, reason) {\n    this.failureCount++;\n    this.failures.push(reason);\n  }\n\n  function addError(testcase, error) {\n    this.errorCount++;\n    this.errors.push(error);\n  }\n\n  function startTest(testcase) {\n    this.testCount++;\n  }\n\n  function stopTest(testcase) {}\n\n  function pauseTest(testcase) {}\n\n  function restartTest(testcase) {}\n\n  function startSuite(suite) {}\n\n  function stopSuite(suite) {}\n\n  function start(t0) {\n    this.t0 = t0;\n  }\n\n  function stop(t1) {\n    this.t1 = t1;\n  }\n\n  function toString() {\n    return this.testCount      + ' tests, ' +\n           this.assertionCount + ' assertions, ' +\n           this.failureCount   + ' failures, ' +\n           this.errorCount     + ' errors, ' +\n           this.skipCount      + ' skips';\n  }\n\n  p.addAssertion  = addAssertion;\n  p.addSkip       = addSkip;\n  p.addFailure    = addFailure;\n  p.addError      = addError;\n  p.startTest     = startTest;\n  p.stopTest      = stopTest;\n  p.pauseTest     = pauseTest;\n  p.restartTest   = restartTest;\n  p.startSuite    = startSuite;\n  p.stopSuite     = stopSuite;\n  p.start         = start;\n  p.stop          = stop;\n  p.toString      = toString;\n})(TestResult.prototype);\n  Evidence.TestResult = TestResult;\nvar Console = {};\n\nfunction Logger(level) {\n  if (typeof level !== 'undefined') {\n    this.level = level;\n  }\n}\n\nLogger.displayName = 'Logger';\nLogger.LEVELS = ['NOTSET', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL'];\nLogger.CRITICAL = 5;\nLogger.ERROR    = 4;\nLogger.WARN     = 3;\nLogger.INFO     = 2;\nLogger.DEBUG    = 1;\nLogger.NOTSET   = 0;\n\n(function(p) {\n  function critical(template, params) {\n    this.log(Logger.CRITICAL, template, params);\n  }\n\n  function error(template, params) {\n    this.log(Logger.ERROR, template, params);\n  }\n\n  function warn(template, params) {\n    this.log(Logger.WARN, template, params);\n  }\n\n  function info(template, params) {\n    this.log(Logger.INFO, template, params);\n  }\n\n  function debug(template, params) {\n    this.log(Logger.DEBUG, template, params);\n  }\n\n  function log(level, template, params) {\n    level = level || Logger.NOTSET;\n    var c = global.console;\n\n    var method = Logger.LEVELS[level].toLowerCase();\n    if (method === 'critical') { method = 'error'; }\n    method = (method in c) ? method : 'log';\n\n    if (level >= this.level) {\n      if (params) {\n        params = params.slice(0);\n        params.unshift(template);\n        c[method].apply(c, params);\n      } else {\n        c[method](template);\n      }\n    }\n  }\n\n  p.log      = log;\n  p.critical = critical;\n  p.error    = error;\n  p.warn     = warn;\n  p.info     = info;\n  p.debug    = debug;\n  p.level    = 0;\n})(Logger.prototype);\nConsole.Logger = Logger;\nfunction PopupLogger(level) {\n  Logger.call(this, level);\n}\n\nchain(PopupLogger, Logger);\nPopupLogger.displayName = 'PopupLogger';\n\n(function(p) {\n  var BASIC_STYLES = 'color: #333; background-color: #fff; font-family: monospace; border-bottom: 1px solid #ccc;';\n  var STYLES = {\n    WARN:     'color: #000; background-color: #fc6;',\n    ERROR:    'color: #f00; background-color: #fcc;',\n    CRITICAL: 'color: #fff; background-color: #000;'\n  };\n\n  function _cleanup(html) {\n    return html.replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&').replace(/[\\n\\r]+/, '<br />');\n  }\n\n  function _makePopup() {\n    var popup = global.open('','popup','height=400,width=400');\n    var doc = popup.document;\n    doc.write('<!doctype html>\\\n               <html lang=\"en\">\\\n                 <head>\\\n                   <meta charset=\"utf-8\">\\\n                   <title>Console</title>\\\n                 </head>\\\n                 <body><div id=\"evidence_console\"></div></body>\\\n               </html>');\n    doc.close();\n    popup.focus();\n    return popup;\n  }\n\n  function _appendLine(level, msg) {\n    this.popup = this.popup || this._makePopup();\n    var levelName = Logger.LEVELS[level];\n\n    var html = '<div style=\"';\n    html += BASIC_STYLES;\n    html += STYLES[levelName] || '';\n    html += '\">';\n    if (level > Logger.INFO) {\n      html += '<span style=\"font-weight: bold;\">';\n      html += levelName;\n      html += ':</span> ';\n    }\n    html += _cleanup(msg);\n    html += '</div>';\n    var doc = this.popup.document,\n        div = doc.createElement('div');\n    div.innerHTML = html;\n    html = div.firstChild;\n    div = null;\n    doc.getElementById('evidence_console').appendChild(html);\n  }\n\n  function log(level, msg, params) {\n    level = level || Logger.NOTSET;\n    if (level >= this.level) {\n      if (params) {\n        msg = UI.printf(msg, params);\n      }\n      this._appendLine(level, msg);\n    }\n  }\n\n  p.log = log;\n  p._makePopup = _makePopup;\n  p._appendLine = _appendLine;\n})(PopupLogger.prototype);\nConsole.PopupLogger = PopupLogger;\nfunction CommandLineLogger(level) {\n  Logger.call(this, level);\n}\n\nchain(CommandLineLogger, Logger);\nCommandLineLogger.displayName = 'CommandLineLogger';\n\n(function(p) {\n\n  function log(level, msg, params) {\n    level = level || Logger.NOTSET;\n    if (level >= this.level) {\n      var prefix = '';\n      if (level > Logger.INFO) {\n        prefix = Logger.LEVELS[level]+ ': ';\n      }\n      if (params) {\n        msg = UI.printf(msg, params);\n      }\n      global.print(prefix + msg);\n    }\n  }\n\n  p.log = log;\n})(CommandLineLogger.prototype);\nConsole.CommandLineLogger = CommandLineLogger;\nfunction ConsoleTestRunner(logger) {\n  TestRunner.call(this);\n  this.logger = logger;\n}\n\nchain(ConsoleTestRunner, TestRunner);\nConsoleTestRunner.displayName = 'ConsoleTestRunner';\n\n(function(p) {\n  function _makeResult() {\n    return new ConsoleTestResult(this.logger);\n  }\n\n  p._makeResult = _makeResult;\n})(ConsoleTestRunner.prototype);\nConsole.TestRunner = ConsoleTestRunner;\nfunction ConsoleTestResult(logger) {\n  TestResult.call(this);\n  this.logger = logger;\n}\n\nchain(ConsoleTestResult, TestResult);\nConsoleTestResult.displayName = 'ConsoleTestResult';\n\n(function(p) {\n  var _super = TestResult.prototype;\n\n  function addAssertion() {\n    this.assertionCount++;\n  }\n\n  function addSkip(testcase, msg) {\n    _super.addSkip.call(this, testcase, msg);\n    this.logger.warn('Skipping testcase ' + testcase + ': ' + msg.message);\n  }\n\n  function addFailure(testcase, msg) {\n    _super.addFailure.call(this, testcase, msg);\n    this.logger.error(testcase + ': ' + msg.message + ' ' + msg.template, msg.args);\n  }\n\n  function addError(testcase, error) {\n    _super.addError.call(this, testcase, error);\n    this.logger.error(testcase + ' threw an error. ' + error);\n  }\n\n  function startTest(testcase) {\n    _super.startTest.call(this, testcase);\n    this.logger.debug('Started testcase ' + testcase + '.');\n  }\n\n  function stopTest(testcase) {\n    this.logger.debug('Completed testcase ' + testcase + '.');\n  }\n\n  function pauseTest(testcase) {\n    this.logger.info('Paused testcase ' + testcase + '.');\n  }\n\n  function restartTest(testcase) {\n    this.logger.info('Restarted testcase ' + testcase + '.');\n  }\n\n  function startSuite(suite) {\n    this.logger.info('Started suite ' + suite + '.');\n  }\n\n  function stopSuite(suite) {\n    this.logger.info('Completed suite ' + suite + '.');\n  }\n\n  function start(t0) {\n    _super.start.call(this, t0);\n    this.logger.info('Started tests.');\n  }\n\n  function stop(t1) {\n    _super.stop.call(this, t1);\n    this.logger.info('Completed tests in ' + ((t1 - this.t0)/1000) + 's.');\n    this.logger.info(this.toString() + '.');\n  }\n\n  p.addAssertion  = addAssertion;\n  p.addSkip       = addSkip;\n  p.addFailure    = addFailure;\n  p.addError      = addError;\n  p.startTest     = startTest;\n  p.stopTest      = stopTest;\n  p.pauseTest     = pauseTest;\n  p.restartTest   = restartTest;\n  p.startSuite    = startSuite;\n  p.stopSuite     = stopSuite;\n  p.start         = start;\n  p.stop          = stop;\n})(ConsoleTestResult.prototype);\n\n\nConsole.TestResult = ConsoleTestResult;\nvar UI = (function() {\n  function printf(template, args, inspector) {\n    var parts = [], m,\n        regexp = /(^%|.%)([a-zA-Z])/,\n        args = args.slice(0); // clone args\n\n    inspector = inspector || String;\n\n    if (template.length <= 0) {\n      return '';\n    }\n    while (m = regexp.exec(template)) {\n      var match = m[0], index = m.index, type, arg;\n\n      if (match.indexOf('%%') === 0) {\n        parts.push(template.substr(0, index));\n        parts.push(match.substr(1));\n      } else {\n        parts.push(template.substr(0, match.indexOf('%' === 0) ? index + 1 : index));\n        type = m[2];\n        arg = args.shift();\n        arg = inspector(arg, type);\n        parts.push(arg);\n      }\n      template = template.substr(index + match.length);\n    }\n    parts.push(template);\n    return parts.join('');\n  }\n\n   return {\n     printf: printf,\n     Console: Console\n   };\n})();\n  Evidence.UI = UI;\n\n  var defaultLoader = new TestLoader();\n  Evidence.defaultLoader = defaultLoader;\n\n  global.Evidence = Evidence;\n\n  if (global.location) {\n    global.onload = function() {\n      if (typeof originalOnload === 'function') {\n        originalOnload.call(global);\n      }\n      AutoRunner.run();\n    };\n  } else if (global.arguments) {\n    var runtime = java.lang.Runtime.getRuntime();\n    var thread = new java.lang.Thread(function() {\n      AutoRunner.run();\n    });\n    runtime.addShutdownHook(thread);\n  }\n\n})(this);\n"
  }
]