Full Code of madrobby/zepto for AI

main e1ecb3d70b2a cached
68 files
442.4 KB
117.8k tokens
179 symbols
1 requests
Download .txt
Showing preview only (463K chars total). Download the full file or copy to clipboard to get everything.
Repository: madrobby/zepto
Branch: main
Commit: e1ecb3d70b2a
Files: 68
Total size: 442.4 KB

Directory structure:
gitextract_k6qzt7fr/

├── .gitignore
├── .npmignore
├── .travis.yml
├── CONTRIBUTING.md
├── MIT-LICENSE
├── README.md
├── examples/
│   ├── anim.html
│   ├── iphone/
│   │   ├── index.html
│   │   └── iphone.css
│   ├── load_jquery_on_ie.html
│   ├── snow/
│   │   └── index.html
│   └── touch_events.html
├── make
├── package.json
├── script/
│   ├── bootstrap
│   ├── guard
│   ├── lint
│   └── test
├── src/
│   ├── ajax.js
│   ├── amd_layout.js
│   ├── assets.js
│   ├── callbacks.js
│   ├── data.js
│   ├── deferred.js
│   ├── detect.js
│   ├── event.js
│   ├── form.js
│   ├── fx.js
│   ├── fx_methods.js
│   ├── gesture.js
│   ├── ie.js
│   ├── ios3.js
│   ├── selector.js
│   ├── stack.js
│   ├── touch.js
│   └── zepto.js
├── test/
│   ├── ajax.html
│   ├── ajax_deferred.html
│   ├── callbacks.html
│   ├── data.html
│   ├── deferred.html
│   ├── detect.html
│   ├── event.html
│   ├── evidence_runner.js
│   ├── fixtures/
│   │   ├── ajax_load_javascript.js
│   │   ├── ajax_load_selector.html
│   │   ├── ajax_load_selector_javascript.html
│   │   ├── ajax_load_simple.html
│   │   ├── iframe_document.html
│   │   └── zepto.json
│   ├── form.html
│   ├── functional/
│   │   ├── assets.html
│   │   ├── fx.html
│   │   ├── gesture.html
│   │   ├── touch.html
│   │   └── touchcancel.html
│   ├── fx.html
│   ├── ie.html
│   ├── index.html
│   ├── ios3.html
│   ├── runner.js
│   ├── selector.html
│   ├── server.coffee
│   ├── stack.html
│   ├── test.css
│   ├── touch.html
│   └── zepto.html
└── vendor/
    └── evidence.js

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

================================================
FILE: .gitignore
================================================
.DS_Store
dist/
dist/zepto.min.js
dist/zepto.js
pkg
*.swp
docs/*
.jhw-cache
.rbenv-version
public
node_modules
temp/
npm-debug.log

================================================
FILE: .npmignore
================================================
*
!README.md
!MIT-LICENSE
!dist/zepto.js
!dist/zepto.min.js
!src/*.js
src/amd_layout.js


================================================
FILE: .travis.yml
================================================
language: node_js

node_js: '0.10'

sudo: false

script: script/test

notifications:
  campfire:
    template: '%{message} [%{branch}] %{repository}/%{commit} %{author} %{build_url}'
    rooms:
      secure: VR6rWk0YhezBWnD8jPjSD8h/Q83S3NT0F34Au1vswt+/+Ku19S8X44vGVUG+NYdYyhg7uOqUaPN1Jr3KCpdcXgHEpUYiyBGJ8ebltavcjeHYWqK6ghcqgSnbDkifuC7Eu/9LcrOMOXgt+zkXjiVXW3+zyGVDcrs4cQ2vGY2DTYA=


================================================
FILE: CONTRIBUTING.md
================================================
## Contributing to Zepto

**Thanks for helping out!**

In order for your code to make it in, several conditions must be met:

* It's more likely your pull request will make it in if you adhere to **Zepto's
  project goals**. Be sure to read the README in its entirety before setting out
  to code.
* Please talk to the maintainers (@madrobby and @mislav) first if you want
  to write a plugin, those are better kept in their own repositories.
* Fix only ONE thing or have only ONE feature in your pull request. 
  If you have multiple unrelated code updates, please submit a separate pull request for each one.
* **Your pull request must be written in English and be accompanied by a
  detailed description**, ideally something we can use as documentation.
  If you're not fluent in English, try your best and let us know so we'll help!
* Changes to jQuery-based API methods **must match their jQuery counterparts**.
* Please **do not just copy code from jQuery**. Zepto strives for API compatibility,
  but has different goals for code style and size and target platforms.
  In case you do copy code, you must clearly indicate the origin of the code, and
  which license applies to it. However, it is likely your patch will be denied.
* **All code must have tests, and all tests must pass.** See the README on running the test suite.
* Please **also test manually** on as many target platforms you have access to,
  but at least on latest Chrome (desktop) and Firefox (desktop).
  See http://zeptojs.com for a full list of platforms.
* It's required that you follow Zepto's **code style guidelines** (see below)

Whew, now that we have that out of the way thanks again!

## Code style guidelines

* Two spaces "soft tabs" indentation
* Remove any trailing whitespace from the end of lines
* `function name() { }` for named functions
* `function(){ }` for anonymous functions
* No curly braces for single-line control flow statements such as `if` & friends
* Don't write [semicolons that are optional][optional]
* Put a single semicolon _before_ statements that start with `(` or `[`
  (see above article as for why it's needed)
* Use long, descriptive variable and method names
* Use blank lines to separate "paragraphs" of code for readability
* Use comments to describe non-obvious code behavior


  [optional]: http://mislav.uniqpath.com/2010/05/semicolons/


================================================
FILE: MIT-LICENSE
================================================
Copyright (c) 2010-2025 Thomas Fuchs
http://zeptojs.com/

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

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

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


================================================
FILE: README.md
================================================
# Zepto.js – a minimalist JavaScript library

Zepto is a minimalist JavaScript library for modern browsers with a
largely jQuery-compatible API. If you use jQuery, you already know how to use Zepto.

See [zeptojs.com][] for an extended introduction, downloads
and documentation.

Zepto.js is licensed under the terms of the MIT License.

Want to give us money or a tip? Don't.
Instead please donate to [charity: water](http://charitywater.org/).

## Building

[![Build Status](https://secure.travis-ci.org/madrobby/zepto.svg?branch=master)](http://travis-ci.org/madrobby/zepto)

The official site offers a download of the default distribution of Zepto. This
is good for starting out. However, at some point you might want to add some
optional modules and remove some of the default ones you don't need, to keep the
size at a minimum. That's when you need to check out Zepto's source code and use
the build commands.

You will need Node.js installed on your system.

~~~ sh
$ npm install
$ npm run-script dist

# do a custom build
$ MODULES="zepto event data" npm run-script dist

# on Windows
c:\zepto> SET MODULES=zepto event data
c:\zepto> npm run-script dist
~~~

The resulting files are:

1. `dist/zepto.js`
2. `dist/zepto.min.js`

If you install CoffeeScript globally, you can run `make` directly:

~~~ sh
# one-time operation
$ npm install coffee-script --global

$ coffee make dist
$ MODULES="zepto event data ..." ./make dist

# on Windows
c:\zepto> SET MODULES=zepto event data
c:\zepto> coffee make dist
~~~

## Zepto modules

Zepto modules are individual files in the "src/" directory.

<table>
<thead><tr>
  <th>module</th> <th>default</th> <th>description</th>
</tr></thead>
<tbody>
  <tr>
    <th><a href="src/zepto.js#files">zepto</a></th>
    <td>✔</td>
    <td>Core module; contains most methods</td>
  </tr>
  <tr>
    <th><a href="src/event.js#files">event</a></th>
    <td>✔</td>
    <td>Event handling via <code>on()</code> &amp; <code>off()</code></td>
  </tr>
  <tr>
    <th><a href="src/ajax.js#files">ajax</a></th>
    <td>✔</td>
    <td>XMLHttpRequest and JSONP functionality</td>
  </tr>
  <tr>
    <th><a href="src/form.js#files">form</a></th>
    <td>✔</td>
    <td>Serialize &amp; submit web forms</td>
  </tr>
  <tr>
    <th><a href="src/ie.js#files">ie</a></th>
    <td>✔</td>
    <td>Support for Internet Explorer 10+ on the desktop and Windows Phone 8</td>
  </tr>
  <tr>
    <th><a href="src/detect.js#files">detect</a></th>
    <td></td>
    <td>Provides <code>$.os</code> and <code>$.browser</code> information</td>
  </tr>
  <tr>
    <th><a href="src/fx.js#files">fx</a></th>
    <td></td>
    <td>The <code>animate()</code> method</td>
  </tr>
  <tr>
    <th><a href="src/fx_methods.js#files">fx_methods</a></th>
    <td></td>
    <td>
      Animated <code>show</code>, <code>hide</code>, <code>toggle</code>,
      and <code>fade*()</code> methods.
    </td>
  </tr>
  <tr>
    <th><a href="src/assets.js#files">assets</a></th>
    <td></td>
    <td>
      Experimental support for cleaning up iOS memory after removing
      image elements from the DOM.
    </td>
  </tr>
  <tr>
    <th><a href="src/data.js#files">data</a></th>
    <td></td>
    <td>
      A full-blown <code>data()</code> method, capable of storing arbitrary
      objects in memory.
    </td>
  </tr>
  <tr>
    <th><a href="src/deferred.js#files">deferred</a></th>
    <td></td>
    <td>
      Provides <code>$.Deferred</code> promises API.
      Depends on the "callbacks" module.
    </td>
  </tr>
  <tr>
    <th><a href="src/callbacks.js#files">callbacks</a></th>
    <td></td>
    <td>
      Provides <code>$.Callbacks</code> for use in "deferred" module.
    </td>
  </tr>
  <tr>
    <th><a href="src/selector.js#files">selector</a></th>
    <td></td>
    <td>
      Experimental <a href="http://api.jquery.com/category/selectors/jquery-selector-extensions/">jQuery
      CSS extensions</a> support for functionality such as <code>$('div:first')</code> and
      <code>el.is(':visible')</code>.
    </td>
  </tr>
  <tr>
    <th><a href="src/touch.js#files">touch</a></th>
    <td></td>
    <td>
      Fires tap– and swipe–related events on touch devices. This works with both
      `touch` (iOS, Android) and `pointer` events (Windows Phone).
    </td>
  </tr>
  <tr>
    <th><a href="src/gesture.js#files">gesture</a></th>
    <td></td>
    <td>Fires pinch gesture events on touch devices</td>
  </tr>
  <tr>
    <th><a href="src/stack.js#files">stack</a></th>
    <td></td>
    <td>Provides <code>andSelf</code> &amp; <code>end()</code> chaining methods</td>
  </tr>
  <tr>
    <th><a href="src/ios3.js#files">ios3</a></th>
    <td></td>
    <td>
      String.prototype.trim and Array.prototype.reduce methods
      (if they are missing) for compatibility with iOS 3.x.
    </td>
  </tr>
</tbody>
</table>

## Contributing

Please read our [contribution guidelines](https://github.com/madrobby/zepto/blob/master/CONTRIBUTING.md)
for information on how to contribute.

Get in touch:

* @[zeptojs](http://twitter.com/zeptojs)

### Write documentation

Zepto docs are written in Markdown and live in the ["gh-pages" branch][docs].
They are published on [zeptojs.com][zeptojs.com].

You can use GitHub's web interface to make quick changes to documentation for
specific Zepto features
([example: ajaxSettings](https://github.com/madrobby/zepto/blob/gh-pages/ajax/_posts/1900-01-01-Z-ajaxSettings.md)).
This will submit a pull request to us that we can review.

### Report a bug

1. Check if the bug is already fixed in the master branch since the last release.
2. Check [existing issues][issues]. Open a new one, including exact browser &
   platform information. For better formatting of your report, see
   [GitHub-flavored Markdown][mkd].

### Running tests

You will need to install [PhantomJS][phantomjs]. On OS X, that's easy:

~~~ sh
$ brew install phantomjs
~~~

To run the automated tests:

~~~ sh
$ npm test
~~~

To run a test server, which you can hit with your browsers and devices:

~~~ sh
$ npm start
~~~

Go to `http://your-ip-address:3000/` on your browser and follow the
instructions. For your convenience test failures and exceptions will be
reported to the the console you started the test server in (as well as
the browser console if available).

  [zeptojs.com]: http://zeptojs.com
  [issues]: https://github.com/madrobby/zepto/issues
  [docs]: https://github.com/madrobby/zepto/tree/gh-pages#readme
  [mkd]: https://help.github.com/articles/creating-and-highlighting-code-blocks/
  [evidence.js]: https://github.com/tobie/Evidence
  [phantomjs]: http://phantomjs.org/download.html


================================================
FILE: examples/anim.html
================================================
<div style="width:100px;height:100px;border:1px solid black">HELLO WORLD</div>

<script src="../src/zepto.js"></script>
<script src="../src/event.js"></script>
<script src="../src/fx.js"></script>

<script>
  $('div').anim({ rotate: '720deg', opacity: .5 }, 2, 'ease-out')
</script>


================================================
FILE: examples/iphone/index.html
================================================
<!DOCTYPE html>
<html>
    <head>
      <title>iPhone.Zepto</title>
      <link href="iphone.css" media="screen" rel="stylesheet" type="text/css" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
      <meta name="apple-mobile-web-app-capable" content="yes" />
      <meta name="format-detection" content="telephone=no" />
    </head>
    <body>
      <section id="menu">
        <div class="toolbar">
          <h1>Title</h1>
        </div>
        <ul class="menu">
          <li class="arrow"><a href="#menu_1">Menu 1</a></li>
          <li>Menu 1</li>
          <li>Menu 1</li>
          <li>Menu 1</li>
          <li>Menu 1</li>
        </ul>
      </section>
      <section id="menu_1">
        <div class="toolbar">
          <h1>Menu 1</h1>
        </div>
        <ul class="menu">
          <li>SubMenu 1</li>
          <li>SubMenu 2</li>
        </ul>
      </section>
      <script src="../../src/zepto.js"></script>
      <script src="../../src/event.js"></script>
      <script src="../../src/touch.js"></script>
      <script>
        $(document).ready(function(){
          var activate = ('createTouch' in document) ? 'touchstart' : 'click'

          $("body > section").first().addClass("current")

          $("a.back").live(activate, function(event) {
            var current = $(this).attr("href")
            $(".current").removeClass("current").addClass("reverse")
            $(current).addClass("current")
          })

          $(".menu a[href]").live(activate, function(event) {
            var link = $(this), section = link.closest('section'),
              prev_element = "#"+(section.removeClass("current").addClass("reverse").attr("id"))
            $(link.attr("href")).addClass("current")
            $(".current .back").remove()
            $(".current .toolbar").prepend("<a href=\""+prev_element+"\" class=\"back\">Back</a>")
          })
        })
      </script>
    </body>
</html>


================================================
FILE: examples/iphone/iphone.css
================================================
* {
  margin: 0px;
  padding: 0px;
}
.toolbar {
  -webkit-box-sizing: border-box;
  background: #6D84A2 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAArCAIAAAA2QHWOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNpNjCEOgEAQA5v9/9eQaAQCd57L0WXTDSmimXZEse1HnNcIIINZYTPVv7Ac4/EWe7OTsC/ec+nDgcj/dpcH7EXt8up4AfRWcOjLIqWFAAAAAElFTkSuQmCC) repeat-x;
  border-bottom: 1px solid #2D3642;
  height: 45px;
  padding: 10px;
  position: relative;
}
body {
  -webkit-perspective: 800;
  -webkit-text-size-adjust: none;
  -webkit-transform-style: preserve-3d;
  -webkit-user-select: none;
  font-family: Helvetica;
  overflow-x: hidden;
  height: 100%;
  width: 100%;
}

body > section {
  background: #C5CCD3 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAABCAIAAACdaSOZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABdJREFUeNpiPHrmCgMC/GNjYwNSAAEGADdNA3dnzPlQAAAAAElFTkSuQmCC);
  display: block;
  left: 0px;
  position: absolute;
  width: 100%;
  -webkit-transform: translate3d(100%,0%,0%);
  opacity: 0;
  -webkit-transition: all 0.25s ease-in-out;
  -webkit-transform-style: preserve-3d;
  z-index: -10;
}

.reverse {
  -webkit-transform: translate3d(-100%, 0%, 0%);
  opacity: 0;
}

.current {
  -webkit-transform: translate3d(0%,0%, 0%);
  opacity: 1;
  z-index: 1;
}
h1, h2 {
  color: #4C566C;
  font: normal normal bold 18px/normal Helvetica;
  margin: 10px 20px 6px;
  text-shadow: rgba(255, 255, 255, 0.19)
}
body.landscape .toolbar > h1 {
  margin-left: -125px;
  width: 250px;
}

.toolbar > h1 {
  color: white;
  font-size: 20px;
  font-weight: bold;
  height: 40px;
  left: 50%;
  line-height: 1em;
  margin: 1px 0px 0px -75px;
  overflow: hidden;
  position: absolute;
  text-align: center;
  text-overflow: ellipsis;
  text-shadow: rgba(0, 0, 0, 0.398438) 0px -1px 0px;
  top: 10px;
  white-space: nowrap;
  width: 150px;
}

ul {
  background: white;
  border: 1px solid #B4B4B4;
  border-bottom-left-radius: 8px 8px;
  border-bottom-right-radius: 8px 8px;
  border-top-left-radius: 8px 8px;
  border-top-right-radius: 8px 8px;
  color: black;
  font: normal normal bold 17px/normal Helvetica;
  margin: 15px 10px 17px;
  padding: 0px;
}

ul li {
  color: black;
  font-size: 14px;
  border-top: 1px solid #B4B4B4;
  color: #666;
  list-style-type: none;
  padding: 10px;
}

li:first-child, li:first-child a {
  border-top: 0px;
  border-top-left-radius: 8px 8px;
  border-top-right-radius: 8px 8px;
}

ul li.arrow {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUCAYAAAB4d5a9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAKVJREFUeNpi/P//PwOtARMDHcDwsYQFRJSXl8P4dVC6CZvizs5O8i1BsqARid9Ei+BiQ2KDLKumhSU1QNyKxG+hlkXoEQ+yqAPNogpapK5KNIvaKbUIVxKeAsTvkPg5QCxETUukgfgAkqFPgdgBzVKKLIFZoIJmwR1qBRdNLEC2BJQpV9LCAmRL/gBxAtRwqlqAXqzcgRrOQE0LQIBxtNIiBQAEGAA7xCa2yF9zEgAAAABJRU5ErkJggg==);
  background-position: 100% 50%;
  background-repeat: no-repeat;
}

body > .current {
  display: block !important;
}

body.landscape > * {
  min-height: 320px;
}


ul li a, li.img a + a {
  color: black;
  display: block;
  margin: -10px;
  overflow: hidden;
  padding: 12px 10px;
  text-decoration: none;
  text-overflow: ellipsis;
  white-space: nowrap;
}


.button, .back, .cancel, .add {
-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;
background: none;
border-width: 0px 5px;
color: white;
font-family: inherit;
font-size: 12px;
font-weight: bold;
height: 30px;
line-height: 30px;
margin: 0px;
overflow: ;
padding: 0px 3px;
position: absolute;
right: 6px;
text-decoration: none;
text-overflow: ellipsis;
text-shadow: rgba(0, 0, 0, 0.496094) 0px -1px 0px;
top: 8px;
white-space: nowrap;
width: auto;
}

.back {
  -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;
border-width: 0px 8px 0px 14px;
left: 6px;
max-width: 55px;
padding: 0px;
right: auto;
}


================================================
FILE: examples/load_jquery_on_ie.html
================================================
<!DOCTYPE html>
<html>
<head>
  <title>Load jQuery if Zepto is not supported</title>
</head>
<body>
  <h1>Load jQuery if Zepto is not supported</h1>
</body>
<script>document.write('<script src='+('__proto__' in {} ? '../dist/zepto' : 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery')+'.js><\/script>')</script>
<script>
  $('body').append('<p>Hello from '+('Zepto' in window ? 'Zepto' : 'jQuery')+'!</p>')

  $('script').each(function(index,script){
    if (script.src)
      $('<p>&lt;script src="'+script.src+'"&gt;</p>').appendTo('body')
  })
</script>
</html>


================================================
FILE: examples/snow/index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <title>Let it snow with Zepto.js</title>
    <meta name="name" content="content">
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <style>
      body { background: #000; color: #fff; overflow: hidden }
      div { position: absolute; }
    </style>
  </head>
  <body>

  <script src="../../src/zepto.js"></script>
  <script src="../../src/event.js"></script>
  <script src="../../src/fx.js"></script>

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

  <script>
    $(document).ready(function(){
      var i = 100, glyphs = '❄❅❆'.split('')

      function rand(max){ return Math.floor(Math.random()*max) }

      function addFlake(){
        var el = $('<div><div>' + glyphs[rand(glyphs.length)] + '</div></div>')
        $('body').append(el)
        el.css({ left: rand(100)+'%', top: -100-rand(500), fontSize: 20+rand(30) })
        el.anim(
          { translateY: 1500+rand(500)+'px', translateX: 50-rand(100)+'px', rotate: (2e3-rand(4e3))+'deg' },
          6+rand(10),
          'linear',
          function(){
            addFlake()
            el.remove() // garbage collect
          }
        )
      }

      while(i--) addFlake()

      // enable for extra fun
      //window.ondeviceorientation = function(event){
      //  ('alpha' in event) && $('body').css({ '-webkit-transform': 'rotate('+event.alpha+'deg)'})
      //}
    })
  </script>
  </body>
</html>


================================================
FILE: examples/touch_events.html
================================================
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>

<script src="../src/zepto.js"></script>
<script src="../src/event.js"></script>
<script src="../src/touch.js"></script>

<style>
  .delete {
    display: none;
    color: red;
  }
</style>

<ul id=items>
  <li>List item 1 <span class=delete>DELETE</span></li>
  <li>List item 2 <span class=delete>DELETE</span></li>
  <li>List item 3 <span class=delete>DELETE</span></li>
  <li>List item 4 <span class=delete>DELETE</span></li>
</ul>

<script>
$('#items li').swipe(function(){
  $('.delete').hide()
  $('.delete', this).show()
})

$('.delete').tap(function(){
  $(this).parent('li').remove()
})
</script>


================================================
FILE: make
================================================
#!/usr/bin/env coffee
require 'shelljs/make'
fs = require 'fs'

zepto_js  = 'dist/zepto.js'
zepto_min = 'dist/zepto.min.js'
zepto_gz  = 'dist/zepto.min.gz'

port = 3999
root = __dirname + '/'

target.all = ->
  target[zepto_js]()
  target.test()

## TASKS ##

target.test = ->
  test_app = require './test/server'
  server = test_app.listen port
  exec "phantomjs --disk-cache=true test/runner.js 'http://localhost:#{port}/'", (code) ->
    server.close -> exit(code)

target[zepto_js] = ->
  target.build() unless test('-e', zepto_js)

target[zepto_min] = ->
  target.minify() if stale(zepto_min, zepto_js)

target[zepto_gz] = ->
  target.compress() if stale(zepto_gz, zepto_min)

target.dist = ->
  target.build()
  target.minify()
  target.compress()

target.build = ->
  cd __dirname
  mkdir '-p', 'dist'
  modules = (env['MODULES'] || 'zepto event ajax form ie').split(' ')
  module_files = ( "src/#{module}.js" for module in modules )
  intro = "/* Zepto #{describe_version()} - #{modules.join(' ')} - zeptojs.com/license */\n"
  dist = cat(module_files).replace(/^\/[\/*].*$/mg, '').replace(/\n{3,}/g, "\n\n")
  dist = cat('src/amd_layout.js').replace(/YIELD/, -> dist.trim()) unless env['NOAMD']
  (intro + dist).to(zepto_js)
  report_size(zepto_js)

target.minify = ->
  target.build() unless test('-e', zepto_js)
  zepto_code = cat(zepto_js)
  intro = zepto_code.slice(0, zepto_code.indexOf("\n") + 1)
  (intro + minify(zepto_code)).to(zepto_min)
  report_size(zepto_min)

target.compress = ->
  gzip = require('zlib').createGzip()
  inp = fs.createReadStream(zepto_min)
  out = fs.createWriteStream(zepto_gz)
  inp.pipe(gzip).pipe(out)
  out.on 'close', ->
    report_size(zepto_gz)
    factor = fsize(zepto_js) / fsize(zepto_gz)
    echo "compression factor: #{format_number(factor)}"

target.publish = ->
  tag = 'v' + package_version()
  if git_version() == tag
    rm '-f', zepto_js
    env['MODULES'] = env['NOAMD'] = ''
    target.dist()
    res = exec 'npm publish'
    exit res.code
  else
    console.error 'error: latest commit should be tagged with ' + tag
    exit 1

## HELPERS ##

stale = (file, source) ->
  target[source]()
  !test('-e', file) || mtime(file) < mtime(source)

mtime = (file) ->
  fs.statSync(file).mtime.getTime()

fsize = (file) ->
  fs.statSync(file).size

format_number = (size, precision = 1) ->
  factor = Math.pow(10, precision)
  decimal = Math.round(size * factor) % factor
  parseInt(size) + "." + decimal

report_size = (file) ->
  echo "#{file}: #{format_number(fsize(file) / 1024)} KiB"

package_version = ->
  JSON.parse(cat('package.json')).version

git_version = ->
  desc = exec "git --git-dir='#{root + '.git'}' describe --tags HEAD", silent: true
  desc.output.replace(/\s+$/, '') if desc.code is 0

describe_version = ->
  git_version() || package_version()

minify = (source_code) ->
  uglify = require('uglify-js')
  compressor = uglify.Compressor()
  ast = uglify.parse(source_code)
  ast.figure_out_scope()
  ast.compute_char_frequency()
  ast.mangle_names()
  ast = ast.transform(compressor)
  return ast.print_to_string()


================================================
FILE: package.json
================================================
{
    "name": "zepto",
    "version": "1.2.0",
    "main": "dist/zepto.js",
    "homepage": "http://zeptojs.com",
    "scripts": {
        "test": "coffee make test",
        "dist": "coffee make dist",
        "start": "coffee test/server.coffee"
    },
    "repository": "madrobby/zepto",
    "license": "MIT",
    "devDependencies": {
        "uglify-js": "2.4.x",
        "express": "3.1.x",
        "coffee-script": "1.5.x",
        "shelljs": "0.1.x"
    }
}


================================================
FILE: script/bootstrap
================================================
#!/usr/bin/env bash
set -e

npm install

if phantom_version="$(phantomjs --version)"; then
  echo "phantomjs ${phantom_version}"
else
  echo "You should install PhantomJS for \`script/test' to work." >&2
fi


================================================
FILE: script/guard
================================================
#!/bin/sh
if [ -z "$BUNDLE_GEMFILE" ]; then
  export BUNDLE_GEMFILE=shutup
fi

exec guard --no-notify "$@"


================================================
FILE: script/lint
================================================
#!/usr/bin/awk -f

BEGIN { if (length(ARGV) < 2) exit 0 }

/<script/ { script=FILENAME }
/<\/script/ { script="" }

/;\s*$/ && (FILENAME !~ /.html$/ || script == FILENAME) {
  printf("%s:%d: no semicolons, please\n", FILENAME, FNR)
  warns++
}
/\t/ {
  printf("%s:%d: use spaces instead of tabs\n", FILENAME, FNR)
  warns++
}

END { if (warns) exit 1 }


================================================
FILE: script/test
================================================
#!/usr/bin/env bash
set -e

port=3999
test_url="http://localhost:${port}/"

export PATH=node_modules/.bin:"$PATH"

git ls-files \*.js \*.html | grep -v ^vendor/ | xargs script/lint

coffee test/server.coffee $port &
pid=$!

check_test_server() {
  curl -fsI "$test_url" >/dev/null
}

terminate_test_server() {
  kill $pid
}

tries=1
while ! check_test_server; do
  if [ $((tries++)) -eq 20 ]; then
    echo "error: timed out while waiting for test server" >&2
    exit 1
  fi
  sleep .05
done

trap terminate_test_server EXIT

phantomjs --disk-cache=true \
  test/runner.js "$test_url" "$@" \
  2> >(grep -v "CoreText performance note" >&2)


================================================
FILE: src/ajax.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  var jsonpID = +new Date(),
      document = window.document,
      key,
      name,
      rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
      scriptTypeRE = /^(?:text|application)\/javascript/i,
      xmlTypeRE = /^(?:text|application)\/xml/i,
      jsonType = 'application/json',
      htmlType = 'text/html',
      blankRE = /^\s*$/,
      originAnchor = document.createElement('a')

  originAnchor.href = window.location.href

  // trigger a custom event and return false if it was cancelled
  function triggerAndReturn(context, eventName, data) {
    var event = $.Event(eventName)
    $(context).trigger(event, data)
    return !event.isDefaultPrevented()
  }

  // trigger an Ajax "global" event
  function triggerGlobal(settings, context, eventName, data) {
    if (settings.global) return triggerAndReturn(context || document, eventName, data)
  }

  // Number of active Ajax requests
  $.active = 0

  function ajaxStart(settings) {
    if (settings.global && $.active++ === 0) triggerGlobal(settings, null, 'ajaxStart')
  }
  function ajaxStop(settings) {
    if (settings.global && !(--$.active)) triggerGlobal(settings, null, 'ajaxStop')
  }

  // triggers an extra global event "ajaxBeforeSend" that's like "ajaxSend" but cancelable
  function ajaxBeforeSend(xhr, settings) {
    var context = settings.context
    if (settings.beforeSend.call(context, xhr, settings) === false ||
        triggerGlobal(settings, context, 'ajaxBeforeSend', [xhr, settings]) === false)
      return false

    triggerGlobal(settings, context, 'ajaxSend', [xhr, settings])
  }
  function ajaxSuccess(data, xhr, settings, deferred) {
    var context = settings.context, status = 'success'
    settings.success.call(context, data, status, xhr)
    if (deferred) deferred.resolveWith(context, [data, status, xhr])
    triggerGlobal(settings, context, 'ajaxSuccess', [xhr, settings, data])
    ajaxComplete(status, xhr, settings)
  }
  // type: "timeout", "error", "abort", "parsererror"
  function ajaxError(error, type, xhr, settings, deferred) {
    var context = settings.context
    settings.error.call(context, xhr, type, error)
    if (deferred) deferred.rejectWith(context, [xhr, type, error])
    triggerGlobal(settings, context, 'ajaxError', [xhr, settings, error || type])
    ajaxComplete(type, xhr, settings)
  }
  // status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
  function ajaxComplete(status, xhr, settings) {
    var context = settings.context
    settings.complete.call(context, xhr, status)
    triggerGlobal(settings, context, 'ajaxComplete', [xhr, settings])
    ajaxStop(settings)
  }

  function ajaxDataFilter(data, type, settings) {
    if (settings.dataFilter == empty) return data
    var context = settings.context
    return settings.dataFilter.call(context, data, type)
  }

  // Empty function, used as default callback
  function empty() {}

  $.ajaxJSONP = function(options, deferred){
    if (!('type' in options)) return $.ajax(options)

    var _callbackName = options.jsonpCallback,
      callbackName = ($.isFunction(_callbackName) ?
        _callbackName() : _callbackName) || ('Zepto' + (jsonpID++)),
      script = document.createElement('script'),
      originalCallback = window[callbackName],
      responseData,
      abort = function(errorType) {
        $(script).triggerHandler('error', errorType || 'abort')
      },
      xhr = { abort: abort }, abortTimeout

    if (deferred) deferred.promise(xhr)

    $(script).on('load error', function(e, errorType){
      clearTimeout(abortTimeout)
      $(script).off().remove()

      if (e.type == 'error' || !responseData) {
        ajaxError(null, errorType || 'error', xhr, options, deferred)
      } else {
        ajaxSuccess(responseData[0], xhr, options, deferred)
      }

      window[callbackName] = originalCallback
      if (responseData && $.isFunction(originalCallback))
        originalCallback(responseData[0])

      originalCallback = responseData = undefined
    })

    if (ajaxBeforeSend(xhr, options) === false) {
      abort('abort')
      return xhr
    }

    window[callbackName] = function(){
      responseData = arguments
    }

    script.src = options.url.replace(/\?(.+)=\?/, '?$1=' + callbackName)
    document.head.appendChild(script)

    if (options.timeout > 0) abortTimeout = setTimeout(function(){
      abort('timeout')
    }, options.timeout)

    return xhr
  }

  $.ajaxSettings = {
    // Default type of request
    type: 'GET',
    // Callback that is executed before request
    beforeSend: empty,
    // Callback that is executed if the request succeeds
    success: empty,
    // Callback that is executed the the server drops error
    error: empty,
    // Callback that is executed on request complete (both: error and success)
    complete: empty,
    // The context for the callbacks
    context: null,
    // Whether to trigger "global" Ajax events
    global: true,
    // Transport
    xhr: function () {
      return new window.XMLHttpRequest()
    },
    // MIME types mapping
    // IIS returns Javascript as "application/x-javascript"
    accepts: {
      script: 'text/javascript, application/javascript, application/x-javascript',
      json:   jsonType,
      xml:    'application/xml, text/xml',
      html:   htmlType,
      text:   'text/plain'
    },
    // Whether the request is to another domain
    crossDomain: false,
    // Default timeout
    timeout: 0,
    // Whether data should be serialized to string
    processData: true,
    // Whether the browser should be allowed to cache GET responses
    cache: true,
    //Used to handle the raw response data of XMLHttpRequest.
    //This is a pre-filtering function to sanitize the response.
    //The sanitized response should be returned
    dataFilter: empty
  }

  function mimeToDataType(mime) {
    if (mime) mime = mime.split(';', 2)[0]
    return mime && ( mime == htmlType ? 'html' :
      mime == jsonType ? 'json' :
      scriptTypeRE.test(mime) ? 'script' :
      xmlTypeRE.test(mime) && 'xml' ) || 'text'
  }

  function appendQuery(url, query) {
    if (query == '') return url
    return (url + '&' + query).replace(/[&?]{1,2}/, '?')
  }

  // serialize payload and append it to the URL for GET requests
  function serializeData(options) {
    if (options.processData && options.data && $.type(options.data) != "string")
      options.data = $.param(options.data, options.traditional)
    if (options.data && (!options.type || options.type.toUpperCase() == 'GET' || 'jsonp' == options.dataType))
      options.url = appendQuery(options.url, options.data), options.data = undefined
  }

  $.ajax = function(options){
    var settings = $.extend({}, options || {}),
        deferred = $.Deferred && $.Deferred(),
        urlAnchor, hashIndex
    for (key in $.ajaxSettings) if (settings[key] === undefined) settings[key] = $.ajaxSettings[key]

    ajaxStart(settings)

    if (!settings.crossDomain) {
      urlAnchor = document.createElement('a')
      urlAnchor.href = settings.url
      // cleans up URL for .href (IE only), see https://github.com/madrobby/zepto/pull/1049
      urlAnchor.href = urlAnchor.href
      settings.crossDomain = (originAnchor.protocol + '//' + originAnchor.host) !== (urlAnchor.protocol + '//' + urlAnchor.host)
    }

    if (!settings.url) settings.url = window.location.toString()
    if ((hashIndex = settings.url.indexOf('#')) > -1) settings.url = settings.url.slice(0, hashIndex)
    serializeData(settings)

    var dataType = settings.dataType, hasPlaceholder = /\?.+=\?/.test(settings.url)
    if (hasPlaceholder) dataType = 'jsonp'

    if (settings.cache === false || (
         (!options || options.cache !== true) &&
         ('script' == dataType || 'jsonp' == dataType)
        ))
      settings.url = appendQuery(settings.url, '_=' + Date.now())

    if ('jsonp' == dataType) {
      if (!hasPlaceholder)
        settings.url = appendQuery(settings.url,
          settings.jsonp ? (settings.jsonp + '=?') : settings.jsonp === false ? '' : 'callback=?')
      return $.ajaxJSONP(settings, deferred)
    }

    var mime = settings.accepts[dataType],
        headers = { },
        setHeader = function(name, value) { headers[name.toLowerCase()] = [name, value] },
        protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol,
        xhr = settings.xhr(),
        nativeSetHeader = xhr.setRequestHeader,
        abortTimeout

    if (deferred) deferred.promise(xhr)

    if (!settings.crossDomain) setHeader('X-Requested-With', 'XMLHttpRequest')
    setHeader('Accept', mime || '*/*')
    if (mime = settings.mimeType || mime) {
      if (mime.indexOf(',') > -1) mime = mime.split(',', 2)[0]
      xhr.overrideMimeType && xhr.overrideMimeType(mime)
    }
    if (settings.contentType || (settings.contentType !== false && settings.data && settings.type.toUpperCase() != 'GET'))
      setHeader('Content-Type', settings.contentType || 'application/x-www-form-urlencoded')

    if (settings.headers) for (name in settings.headers) setHeader(name, settings.headers[name])
    xhr.setRequestHeader = setHeader

    xhr.onreadystatechange = function(){
      if (xhr.readyState == 4) {
        xhr.onreadystatechange = empty
        clearTimeout(abortTimeout)
        var result, error = false
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 || (xhr.status == 0 && protocol == 'file:')) {
          dataType = dataType || mimeToDataType(settings.mimeType || xhr.getResponseHeader('content-type'))

          if (xhr.responseType == 'arraybuffer' || xhr.responseType == 'blob')
            result = xhr.response
          else {
            result = xhr.responseText

            try {
              // http://perfectionkills.com/global-eval-what-are-the-options/
              // sanitize response accordingly if data filter callback provided
              result = ajaxDataFilter(result, dataType, settings)
              if (dataType == 'script')    (1,eval)(result)
              else if (dataType == 'xml')  result = xhr.responseXML
              else if (dataType == 'json') result = blankRE.test(result) ? null : $.parseJSON(result)
            } catch (e) { error = e }

            if (error) return ajaxError(error, 'parsererror', xhr, settings, deferred)
          }

          ajaxSuccess(result, xhr, settings, deferred)
        } else {
          ajaxError(xhr.statusText || null, xhr.status ? 'error' : 'abort', xhr, settings, deferred)
        }
      }
    }

    if (ajaxBeforeSend(xhr, settings) === false) {
      xhr.abort()
      ajaxError(null, 'abort', xhr, settings, deferred)
      return xhr
    }

    var async = 'async' in settings ? settings.async : true
    xhr.open(settings.type, settings.url, async, settings.username, settings.password)

    if (settings.xhrFields) for (name in settings.xhrFields) xhr[name] = settings.xhrFields[name]

    for (name in headers) nativeSetHeader.apply(xhr, headers[name])

    if (settings.timeout > 0) abortTimeout = setTimeout(function(){
        xhr.onreadystatechange = empty
        xhr.abort()
        ajaxError(null, 'timeout', xhr, settings, deferred)
      }, settings.timeout)

    // avoid sending empty string (#319)
    xhr.send(settings.data ? settings.data : null)
    return xhr
  }

  // handle optional data/success arguments
  function parseArguments(url, data, success, dataType) {
    if ($.isFunction(data)) dataType = success, success = data, data = undefined
    if (!$.isFunction(success)) dataType = success, success = undefined
    return {
      url: url
    , data: data
    , success: success
    , dataType: dataType
    }
  }

  $.get = function(/* url, data, success, dataType */){
    return $.ajax(parseArguments.apply(null, arguments))
  }

  $.post = function(/* url, data, success, dataType */){
    var options = parseArguments.apply(null, arguments)
    options.type = 'POST'
    return $.ajax(options)
  }

  $.getJSON = function(/* url, data, success */){
    var options = parseArguments.apply(null, arguments)
    options.dataType = 'json'
    return $.ajax(options)
  }

  $.fn.load = function(url, data, success){
    if (!this.length) return this
    var self = this, parts = url.split(/\s/), selector,
        options = parseArguments(url, data, success),
        callback = options.success
    if (parts.length > 1) options.url = parts[0], selector = parts[1]
    options.success = function(response){
      self.html(selector ?
        $('<div>').html(response.replace(rscript, "")).find(selector)
        : response)
      callback && callback.apply(self, arguments)
    }
    $.ajax(options)
    return this
  }

  var escape = encodeURIComponent

  function serialize(params, obj, traditional, scope){
    var type, array = $.isArray(obj), hash = $.isPlainObject(obj)
    $.each(obj, function(key, value) {
      type = $.type(value)
      if (scope) key = traditional ? scope :
        scope + '[' + (hash || type == 'object' || type == 'array' ? key : '') + ']'
      // handle data in serializeArray() format
      if (!scope && array) params.add(value.name, value.value)
      // recurse into nested objects
      else if (type == "array" || (!traditional && type == "object"))
        serialize(params, value, traditional, key)
      else params.add(key, value)
    })
  }

  $.param = function(obj, traditional){
    var params = []
    params.add = function(key, value) {
      if ($.isFunction(value)) value = value()
      if (value == null) value = ""
      this.push(escape(key) + '=' + escape(value))
    }
    serialize(params, obj, traditional)
    return params.join('&').replace(/%20/g, '+')
  }
})(Zepto)


================================================
FILE: src/amd_layout.js
================================================
(function(global, factory) {
  if (typeof define === 'function' && define.amd)
    define(function() { return factory(global) })
  else
    factory(global)
}(window, function(window) {
  YIELD
  return Zepto
}))


================================================
FILE: src/assets.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  var cache = [], timeout

  $.fn.remove = function(){
    return this.each(function(){
      if(this.parentNode){
        if(this.tagName === 'IMG'){
          cache.push(this)
          this.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='
          if (timeout) clearTimeout(timeout)
          timeout = setTimeout(function(){ cache = [] }, 60000)
        }
        this.parentNode.removeChild(this)
      }
    })
  }
})(Zepto)


================================================
FILE: src/callbacks.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  // Create a collection of callbacks to be fired in a sequence, with configurable behaviour
  // Option flags:
  //   - once: Callbacks fired at most one time.
  //   - memory: Remember the most recent context and arguments
  //   - stopOnFalse: Cease iterating over callback list
  //   - unique: Permit adding at most one instance of the same callback
  $.Callbacks = function(options) {
    options = $.extend({}, options)

    var memory, // Last fire value (for non-forgettable lists)
        fired,  // Flag to know if list was already fired
        firing, // Flag to know if list is currently firing
        firingStart, // First callback to fire (used internally by add and fireWith)
        firingLength, // End of the loop when firing
        firingIndex, // Index of currently firing callback (modified by remove if needed)
        list = [], // Actual callback list
        stack = !options.once && [], // Stack of fire calls for repeatable lists
        fire = function(data) {
          memory = options.memory && data
          fired = true
          firingIndex = firingStart || 0
          firingStart = 0
          firingLength = list.length
          firing = true
          for ( ; list && firingIndex < firingLength ; ++firingIndex ) {
            if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse) {
              memory = false
              break
            }
          }
          firing = false
          if (list) {
            if (stack) stack.length && fire(stack.shift())
            else if (memory) list.length = 0
            else Callbacks.disable()
          }
        },

        Callbacks = {
          add: function() {
            if (list) {
              var start = list.length,
                  add = function(args) {
                    $.each(args, function(_, arg){
                      if (typeof arg === "function") {
                        if (!options.unique || !Callbacks.has(arg)) list.push(arg)
                      }
                      else if (arg && arg.length && typeof arg !== 'string') add(arg)
                    })
                  }
              add(arguments)
              if (firing) firingLength = list.length
              else if (memory) {
                firingStart = start
                fire(memory)
              }
            }
            return this
          },
          remove: function() {
            if (list) {
              $.each(arguments, function(_, arg){
                var index
                while ((index = $.inArray(arg, list, index)) > -1) {
                  list.splice(index, 1)
                  // Handle firing indexes
                  if (firing) {
                    if (index <= firingLength) --firingLength
                    if (index <= firingIndex) --firingIndex
                  }
                }
              })
            }
            return this
          },
          has: function(fn) {
            return !!(list && (fn ? $.inArray(fn, list) > -1 : list.length))
          },
          empty: function() {
            firingLength = list.length = 0
            return this
          },
          disable: function() {
            list = stack = memory = undefined
            return this
          },
          disabled: function() {
            return !list
          },
          lock: function() {
            stack = undefined
            if (!memory) Callbacks.disable()
            return this
          },
          locked: function() {
            return !stack
          },
          fireWith: function(context, args) {
            if (list && (!fired || stack)) {
              args = args || []
              args = [context, args.slice ? args.slice() : args]
              if (firing) stack.push(args)
              else fire(args)
            }
            return this
          },
          fire: function() {
            return Callbacks.fireWith(this, arguments)
          },
          fired: function() {
            return !!fired
          }
        }

    return Callbacks
  }
})(Zepto)


================================================
FILE: src/data.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

// The following code is heavily inspired by jQuery's $.fn.data()

;(function($){
  var data = {}, dataAttr = $.fn.data, camelize = $.camelCase,
    exp = $.expando = 'Zepto' + (+new Date()), emptyArray = []

  // Get value from node:
  // 1. first try key as given,
  // 2. then try camelized key,
  // 3. fall back to reading "data-*" attribute.
  function getData(node, name) {
    var id = node[exp], store = id && data[id]
    if (name === undefined) return store || setData(node)
    else {
      if (store) {
        if (name in store) return store[name]
        var camelName = camelize(name)
        if (camelName in store) return store[camelName]
      }
      return dataAttr.call($(node), name)
    }
  }

  // Store value under camelized key on node
  function setData(node, name, value) {
    var id = node[exp] || (node[exp] = ++$.uuid),
      store = data[id] || (data[id] = attributeData(node))
    if (name !== undefined) store[camelize(name)] = value
    return store
  }

  // Read all "data-*" attributes from a node
  function attributeData(node) {
    var store = {}
    $.each(node.attributes || emptyArray, function(i, attr){
      if (attr.name.indexOf('data-') == 0)
        store[camelize(attr.name.replace('data-', ''))] =
          $.zepto.deserializeValue(attr.value)
    })
    return store
  }

  $.fn.data = function(name, value) {
    return value === undefined ?
      // set multiple values via object
      $.isPlainObject(name) ?
        this.each(function(i, node){
          $.each(name, function(key, value){ setData(node, key, value) })
        }) :
        // get value from first element
        (0 in this ? getData(this[0], name) : undefined) :
      // set value on all elements
      this.each(function(){ setData(this, name, value) })
  }

  $.data = function(elem, name, value) {
    return $(elem).data(name, value)
  }

  $.hasData = function(elem) {
    var id = elem[exp], store = id && data[id]
    return store ? !$.isEmptyObject(store) : false
  }

  $.fn.removeData = function(names) {
    if (typeof names == 'string') names = names.split(/\s+/)
    return this.each(function(){
      var id = this[exp], store = id && data[id]
      if (store) $.each(names || store, function(key){
        delete store[names ? camelize(this) : key]
      })
    })
  }

  // Generate extended `remove` and `empty` functions
  ;['remove', 'empty'].forEach(function(methodName){
    var origFn = $.fn[methodName]
    $.fn[methodName] = function() {
      var elements = this.find('*')
      if (methodName === 'remove') elements = elements.add(this)
      elements.removeData()
      return origFn.call(this)
    }
  })
})(Zepto)


================================================
FILE: src/deferred.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.
//
//     Some code (c) 2005, 2013 jQuery Foundation, Inc. and other contributors

;(function($){
  var slice = Array.prototype.slice

  function Deferred(func) {
    var tuples = [
          // action, add listener, listener list, final state
          [ "resolve", "done", $.Callbacks({once:1, memory:1}), "resolved" ],
          [ "reject", "fail", $.Callbacks({once:1, memory:1}), "rejected" ],
          [ "notify", "progress", $.Callbacks({memory:1}) ]
        ],
        state = "pending",
        promise = {
          state: function() {
            return state
          },
          always: function() {
            deferred.done(arguments).fail(arguments)
            return this
          },
          then: function(/* fnDone [, fnFailed [, fnProgress]] */) {
            var fns = arguments
            return Deferred(function(defer){
              $.each(tuples, function(i, tuple){
                var fn = $.isFunction(fns[i]) && fns[i]
                deferred[tuple[1]](function(){
                  var returned = fn && fn.apply(this, arguments)
                  if (returned && $.isFunction(returned.promise)) {
                    returned.promise()
                      .done(defer.resolve)
                      .fail(defer.reject)
                      .progress(defer.notify)
                  } else {
                    var context = this === promise ? defer.promise() : this,
                        values = fn ? [returned] : arguments
                    defer[tuple[0] + "With"](context, values)
                  }
                })
              })
              fns = null
            }).promise()
          },

          promise: function(obj) {
            return obj != null ? $.extend( obj, promise ) : promise
          }
        },
        deferred = {}

    $.each(tuples, function(i, tuple){
      var list = tuple[2],
          stateString = tuple[3]

      promise[tuple[1]] = list.add

      if (stateString) {
        list.add(function(){
          state = stateString
        }, tuples[i^1][2].disable, tuples[2][2].lock)
      }

      deferred[tuple[0]] = function(){
        deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments)
        return this
      }
      deferred[tuple[0] + "With"] = list.fireWith
    })

    promise.promise(deferred)
    if (func) func.call(deferred, deferred)
    return deferred
  }

  $.when = function(sub) {
    var resolveValues = slice.call(arguments),
        len = resolveValues.length,
        i = 0,
        remain = len !== 1 || (sub && $.isFunction(sub.promise)) ? len : 0,
        deferred = remain === 1 ? sub : Deferred(),
        progressValues, progressContexts, resolveContexts,
        updateFn = function(i, ctx, val){
          return function(value){
            ctx[i] = this
            val[i] = arguments.length > 1 ? slice.call(arguments) : value
            if (val === progressValues) {
              deferred.notifyWith(ctx, val)
            } else if (!(--remain)) {
              deferred.resolveWith(ctx, val)
            }
          }
        }

    if (len > 1) {
      progressValues = new Array(len)
      progressContexts = new Array(len)
      resolveContexts = new Array(len)
      for ( ; i < len; ++i ) {
        if (resolveValues[i] && $.isFunction(resolveValues[i].promise)) {
          resolveValues[i].promise()
            .done(updateFn(i, resolveContexts, resolveValues))
            .fail(deferred.reject)
            .progress(updateFn(i, progressContexts, progressValues))
        } else {
          --remain
        }
      }
    }
    if (!remain) deferred.resolveWith(resolveContexts, resolveValues)
    return deferred.promise()
  }

  $.Deferred = Deferred
})(Zepto)


================================================
FILE: src/detect.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  function detect(ua, platform){
    var os = this.os = {}, browser = this.browser = {},
      webkit = ua.match(/Web[kK]it[\/]{0,1}([\d.]+)/),
      android = ua.match(/(Android);?[\s\/]+([\d.]+)?/),
      osx = !!ua.match(/\(Macintosh\; Intel /),
      ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
      ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/),
      iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
      webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),
      win = /Win\d{2}|Windows/.test(platform),
      wp = ua.match(/Windows Phone ([\d.]+)/),
      touchpad = webos && ua.match(/TouchPad/),
      kindle = ua.match(/Kindle\/([\d.]+)/),
      silk = ua.match(/Silk\/([\d._]+)/),
      blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/),
      bb10 = ua.match(/(BB10).*Version\/([\d.]+)/),
      rimtabletos = ua.match(/(RIM\sTablet\sOS)\s([\d.]+)/),
      playbook = ua.match(/PlayBook/),
      chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/),
      firefox = ua.match(/Firefox\/([\d.]+)/),
      firefoxos = ua.match(/\((?:Mobile|Tablet); rv:([\d.]+)\).*Firefox\/[\d.]+/),
      ie = ua.match(/MSIE\s([\d.]+)/) || ua.match(/Trident\/[\d](?=[^\?]+).*rv:([0-9.].)/),
      webview = !chrome && ua.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/),
      safari = webview || ua.match(/Version\/([\d.]+)([^S](Safari)|[^M]*(Mobile)[^S]*(Safari))/)

    // Todo: clean this up with a better OS/browser seperation:
    // - discern (more) between multiple browsers on android
    // - decide if kindle fire in silk mode is android or not
    // - Firefox on Android doesn't specify the Android version
    // - possibly devide in os, device and browser hashes

    if (browser.webkit = !!webkit) browser.version = webkit[1]

    if (android) os.android = true, os.version = android[2]
    if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.')
    if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.')
    if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null
    if (wp) os.wp = true, os.version = wp[1]
    if (webos) os.webos = true, os.version = webos[2]
    if (touchpad) os.touchpad = true
    if (blackberry) os.blackberry = true, os.version = blackberry[2]
    if (bb10) os.bb10 = true, os.version = bb10[2]
    if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2]
    if (playbook) browser.playbook = true
    if (kindle) os.kindle = true, os.version = kindle[1]
    if (silk) browser.silk = true, browser.version = silk[1]
    if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true
    if (chrome) browser.chrome = true, browser.version = chrome[1]
    if (firefox) browser.firefox = true, browser.version = firefox[1]
    if (firefoxos) os.firefoxos = true, os.version = firefoxos[1]
    if (ie) browser.ie = true, browser.version = ie[1]
    if (safari && (osx || os.ios || win)) {
      browser.safari = true
      if (!os.ios) browser.version = safari[1]
    }
    if (webview) browser.webview = true

    os.tablet = !!(ipad || playbook || (android && !ua.match(/Mobile/)) ||
      (firefox && ua.match(/Tablet/)) || (ie && !ua.match(/Phone/) && ua.match(/Touch/)))
    os.phone  = !!(!os.tablet && !os.ipod && (android || iphone || webos || blackberry || bb10 ||
      (chrome && ua.match(/Android/)) || (chrome && ua.match(/CriOS\/([\d.]+)/)) ||
      (firefox && ua.match(/Mobile/)) || (ie && ua.match(/Touch/))))
  }

  detect.call($, navigator.userAgent, navigator.platform)
  // make available to unit tests
  $.__detect = detect

})(Zepto)


================================================
FILE: src/event.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  var _zid = 1, undefined,
      slice = Array.prototype.slice,
      isFunction = $.isFunction,
      isString = function(obj){ return typeof obj == 'string' },
      handlers = {},
      specialEvents={},
      focusinSupported = 'onfocusin' in window,
      focus = { focus: 'focusin', blur: 'focusout' },
      hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }

  specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'

  function zid(element) {
    return element._zid || (element._zid = _zid++)
  }
  function findHandlers(element, event, fn, selector) {
    event = parse(event)
    if (event.ns) var matcher = matcherFor(event.ns)
    return (handlers[zid(element)] || []).filter(function(handler) {
      return handler
        && (!event.e  || handler.e == event.e)
        && (!event.ns || matcher.test(handler.ns))
        && (!fn       || zid(handler.fn) === zid(fn))
        && (!selector || handler.sel == selector)
    })
  }
  function parse(event) {
    var parts = ('' + event).split('.')
    return {e: parts[0], ns: parts.slice(1).sort().join(' ')}
  }
  function matcherFor(ns) {
    return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')
  }

  function eventCapture(handler, captureSetting) {
    return handler.del &&
      (!focusinSupported && (handler.e in focus)) ||
      !!captureSetting
  }

  function realEvent(type) {
    return hover[type] || (focusinSupported && focus[type]) || type
  }

  function add(element, events, fn, data, selector, delegator, capture){
    var id = zid(element), set = (handlers[id] || (handlers[id] = []))
    events.split(/\s/).forEach(function(event){
      if (event == 'ready') return $(document).ready(fn)
      var handler   = parse(event)
      handler.fn    = fn
      handler.sel   = selector
      // emulate mouseenter, mouseleave
      if (handler.e in hover) fn = function(e){
        var related = e.relatedTarget
        if (!related || (related !== this && !$.contains(this, related)))
          return handler.fn.apply(this, arguments)
      }
      handler.del   = delegator
      var callback  = delegator || fn
      handler.proxy = function(e){
        e = compatible(e)
        if (e.isImmediatePropagationStopped()) return
        e.data = data
        var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args))
        if (result === false) e.preventDefault(), e.stopPropagation()
        return result
      }
      handler.i = set.length
      set.push(handler)
      if ('addEventListener' in element)
        element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
    })
  }
  function remove(element, events, fn, selector, capture){
    var id = zid(element)
    ;(events || '').split(/\s/).forEach(function(event){
      findHandlers(element, event, fn, selector).forEach(function(handler){
        delete handlers[id][handler.i]
      if ('removeEventListener' in element)
        element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
      })
    })
  }

  $.event = { add: add, remove: remove }

  $.proxy = function(fn, context) {
    var args = (2 in arguments) && slice.call(arguments, 2)
    if (isFunction(fn)) {
      var proxyFn = function(){ return fn.apply(context, args ? args.concat(slice.call(arguments)) : arguments) }
      proxyFn._zid = zid(fn)
      return proxyFn
    } else if (isString(context)) {
      if (args) {
        args.unshift(fn[context], fn)
        return $.proxy.apply(null, args)
      } else {
        return $.proxy(fn[context], fn)
      }
    } else {
      throw new TypeError("expected function")
    }
  }

  $.fn.bind = function(event, data, callback){
    return this.on(event, data, callback)
  }
  $.fn.unbind = function(event, callback){
    return this.off(event, callback)
  }
  $.fn.one = function(event, selector, data, callback){
    return this.on(event, selector, data, callback, 1)
  }

  var returnTrue = function(){return true},
      returnFalse = function(){return false},
      ignoreProperties = /^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,
      eventMethods = {
        preventDefault: 'isDefaultPrevented',
        stopImmediatePropagation: 'isImmediatePropagationStopped',
        stopPropagation: 'isPropagationStopped'
      }

  function compatible(event, source) {
    if (source || !event.isDefaultPrevented) {
      source || (source = event)

      $.each(eventMethods, function(name, predicate) {
        var sourceMethod = source[name]
        event[name] = function(){
          this[predicate] = returnTrue
          return sourceMethod && sourceMethod.apply(source, arguments)
        }
        event[predicate] = returnFalse
      })

      try {
        event.timeStamp || (event.timeStamp = Date.now())
      } catch (ignored) { }

      if (source.defaultPrevented !== undefined ? source.defaultPrevented :
          'returnValue' in source ? source.returnValue === false :
          source.getPreventDefault && source.getPreventDefault())
        event.isDefaultPrevented = returnTrue
    }
    return event
  }

  function createProxy(event) {
    var key, proxy = { originalEvent: event }
    for (key in event)
      if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]

    return compatible(proxy, event)
  }

  $.fn.delegate = function(selector, event, callback){
    return this.on(event, selector, callback)
  }
  $.fn.undelegate = function(selector, event, callback){
    return this.off(event, selector, callback)
  }

  $.fn.live = function(event, callback){
    $(document.body).delegate(this.selector, event, callback)
    return this
  }
  $.fn.die = function(event, callback){
    $(document.body).undelegate(this.selector, event, callback)
    return this
  }

  $.fn.on = function(event, selector, data, callback, one){
    var autoRemove, delegator, $this = this
    if (event && !isString(event)) {
      $.each(event, function(type, fn){
        $this.on(type, selector, data, fn, one)
      })
      return $this
    }

    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = data, data = selector, selector = undefined
    if (callback === undefined || data === false)
      callback = data, data = undefined

    if (callback === false) callback = returnFalse

    return $this.each(function(_, element){
      if (one) autoRemove = function(e){
        remove(element, e.type, callback)
        return callback.apply(this, arguments)
      }

      if (selector) delegator = function(e){
        var evt, match = $(e.target).closest(selector, element).get(0)
        if (match && match !== element) {
          evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
          return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))
        }
      }

      add(element, event, callback, data, selector, delegator || autoRemove)
    })
  }
  $.fn.off = function(event, selector, callback){
    var $this = this
    if (event && !isString(event)) {
      $.each(event, function(type, fn){
        $this.off(type, selector, fn)
      })
      return $this
    }

    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = selector, selector = undefined

    if (callback === false) callback = returnFalse

    return $this.each(function(){
      remove(this, event, callback, selector)
    })
  }

  $.fn.trigger = function(event, args){
    event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
    event._args = args
    return this.each(function(){
      // handle focus(), blur() by calling them directly
      if (event.type in focus && typeof this[event.type] == "function") this[event.type]()
      // items in the collection might not be DOM elements
      else if ('dispatchEvent' in this) this.dispatchEvent(event)
      else $(this).triggerHandler(event, args)
    })
  }

  // triggers event handlers on current element just as if an event occurred,
  // doesn't trigger an actual event, doesn't bubble
  $.fn.triggerHandler = function(event, args){
    var e, result
    this.each(function(i, element){
      e = createProxy(isString(event) ? $.Event(event) : event)
      e._args = args
      e.target = element
      $.each(findHandlers(element, event.type || event), function(i, handler){
        result = handler.proxy(e)
        if (e.isImmediatePropagationStopped()) return false
      })
    })
    return result
  }

  // shortcut methods for `.bind(event, fn)` for each event type
  ;('focusin focusout focus blur load resize scroll unload click dblclick '+
  'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+
  'change select keydown keypress keyup error').split(' ').forEach(function(event) {
    $.fn[event] = function(callback) {
      return (0 in arguments) ?
        this.bind(event, callback) :
        this.trigger(event)
    }
  })

  $.Event = function(type, props) {
    if (!isString(type)) props = type, type = props.type
    var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
    if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
    event.initEvent(type, bubbles, true)
    return compatible(event)
  }

})(Zepto)


================================================
FILE: src/form.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  $.fn.serializeArray = function() {
    var name, type, result = [],
      add = function(value) {
        if (value.forEach) return value.forEach(add)
        result.push({ name: name, value: value })
      }
    if (this[0]) $.each(this[0].elements, function(_, field){
      type = field.type, name = field.name
      if (name && field.nodeName.toLowerCase() != 'fieldset' &&
        !field.disabled && type != 'submit' && type != 'reset' && type != 'button' && type != 'file' &&
        ((type != 'radio' && type != 'checkbox') || field.checked))
          add($(field).val())
    })
    return result
  }

  $.fn.serialize = function(){
    var result = []
    this.serializeArray().forEach(function(elm){
      result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value))
    })
    return result.join('&')
  }

  $.fn.submit = function(callback) {
    if (0 in arguments) this.bind('submit', callback)
    else if (this.length) {
      var event = $.Event('submit')
      this.eq(0).trigger(event)
      if (!event.isDefaultPrevented()) this.get(0).submit()
    }
    return this
  }

})(Zepto)


================================================
FILE: src/fx.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($, undefined){
  var prefix = '', eventPrefix,
    vendors = { Webkit: 'webkit', Moz: '', O: 'o' },
    testEl = document.createElement('div'),
    supportedTransforms = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,
    transform,
    transitionProperty, transitionDuration, transitionTiming, transitionDelay,
    animationName, animationDuration, animationTiming, animationDelay,
    cssReset = {}

  function dasherize(str) { return str.replace(/([A-Z])/g, '-$1').toLowerCase() }
  function normalizeEvent(name) { return eventPrefix ? eventPrefix + name : name.toLowerCase() }

  if (testEl.style.transform === undefined) $.each(vendors, function(vendor, event){
    if (testEl.style[vendor + 'TransitionProperty'] !== undefined) {
      prefix = '-' + vendor.toLowerCase() + '-'
      eventPrefix = event
      return false
    }
  })

  transform = prefix + 'transform'
  cssReset[transitionProperty = prefix + 'transition-property'] =
  cssReset[transitionDuration = prefix + 'transition-duration'] =
  cssReset[transitionDelay    = prefix + 'transition-delay'] =
  cssReset[transitionTiming   = prefix + 'transition-timing-function'] =
  cssReset[animationName      = prefix + 'animation-name'] =
  cssReset[animationDuration  = prefix + 'animation-duration'] =
  cssReset[animationDelay     = prefix + 'animation-delay'] =
  cssReset[animationTiming    = prefix + 'animation-timing-function'] = ''

  $.fx = {
    off: (eventPrefix === undefined && testEl.style.transitionProperty === undefined),
    speeds: { _default: 400, fast: 200, slow: 600 },
    cssPrefix: prefix,
    transitionEnd: normalizeEvent('TransitionEnd'),
    animationEnd: normalizeEvent('AnimationEnd')
  }

  $.fn.animate = function(properties, duration, ease, callback, delay){
    if ($.isFunction(duration))
      callback = duration, ease = undefined, duration = undefined
    if ($.isFunction(ease))
      callback = ease, ease = undefined
    if ($.isPlainObject(duration))
      ease = duration.easing, callback = duration.complete, delay = duration.delay, duration = duration.duration
    if (duration) duration = (typeof duration == 'number' ? duration :
                    ($.fx.speeds[duration] || $.fx.speeds._default)) / 1000
    if (delay) delay = parseFloat(delay) / 1000
    return this.anim(properties, duration, ease, callback, delay)
  }

  $.fn.anim = function(properties, duration, ease, callback, delay){
    var key, cssValues = {}, cssProperties, transforms = '',
        that = this, wrappedCallback, endEvent = $.fx.transitionEnd,
        fired = false

    if (duration === undefined) duration = $.fx.speeds._default / 1000
    if (delay === undefined) delay = 0
    if ($.fx.off) duration = 0

    if (typeof properties == 'string') {
      // keyframe animation
      cssValues[animationName] = properties
      cssValues[animationDuration] = duration + 's'
      cssValues[animationDelay] = delay + 's'
      cssValues[animationTiming] = (ease || 'linear')
      endEvent = $.fx.animationEnd
    } else {
      cssProperties = []
      // CSS transitions
      for (key in properties)
        if (supportedTransforms.test(key)) transforms += key + '(' + properties[key] + ') '
        else cssValues[key] = properties[key], cssProperties.push(dasherize(key))

      if (transforms) cssValues[transform] = transforms, cssProperties.push(transform)
      if (duration > 0 && typeof properties === 'object') {
        cssValues[transitionProperty] = cssProperties.join(', ')
        cssValues[transitionDuration] = duration + 's'
        cssValues[transitionDelay] = delay + 's'
        cssValues[transitionTiming] = (ease || 'linear')
      }
    }

    wrappedCallback = function(event){
      if (typeof event !== 'undefined') {
        if (event.target !== event.currentTarget) return // makes sure the event didn't bubble from "below"
        $(event.target).unbind(endEvent, wrappedCallback)
      } else
        $(this).unbind(endEvent, wrappedCallback) // triggered by setTimeout

      fired = true
      $(this).css(cssReset)
      callback && callback.call(this)
    }
    if (duration > 0){
      this.bind(endEvent, wrappedCallback)
      // transitionEnd is not always firing on older Android phones
      // so make sure it gets fired
      setTimeout(function(){
        if (fired) return
        wrappedCallback.call(that)
      }, ((duration + delay) * 1000) + 25)
    }

    // trigger page reflow so new elements can animate
    this.size() && this.get(0).clientLeft

    this.css(cssValues)

    if (duration <= 0) setTimeout(function() {
      that.each(function(){ wrappedCallback.call(this) })
    }, 0)

    return this
  }

  testEl = null
})(Zepto)


================================================
FILE: src/fx_methods.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($, undefined){
  var document = window.document,
    origShow = $.fn.show, origHide = $.fn.hide, origToggle = $.fn.toggle

  function anim(el, speed, opacity, scale, callback) {
    if (typeof speed == 'function' && !callback) callback = speed, speed = undefined
    var props = { opacity: opacity }
    if (scale) {
      props.scale = scale
      el.css($.fx.cssPrefix + 'transform-origin', '0 0')
    }
    return el.animate(props, speed, null, callback)
  }

  function hide(el, speed, scale, callback) {
    return anim(el, speed, 0, scale, function(){
      origHide.call($(this))
      callback && callback.call(this)
    })
  }

  $.fn.show = function(speed, callback) {
    origShow.call(this)
    if (speed === undefined) speed = 0
    else this.css('opacity', 0)
    return anim(this, speed, 1, '1,1', callback)
  }

  $.fn.hide = function(speed, callback) {
    if (speed === undefined) return origHide.call(this)
    else return hide(this, speed, '0,0', callback)
  }

  $.fn.toggle = function(speed, callback) {
    if (speed === undefined || typeof speed == 'boolean')
      return origToggle.call(this, speed)
    else return this.each(function(){
      var el = $(this)
      el[el.css('display') == 'none' ? 'show' : 'hide'](speed, callback)
    })
  }

  $.fn.fadeTo = function(speed, opacity, callback) {
    return anim(this, speed, opacity, null, callback)
  }

  $.fn.fadeIn = function(speed, callback) {
    var target = this.css('opacity')
    if (target > 0) this.css('opacity', 0)
    else target = 1
    return origShow.call(this).fadeTo(speed, target, callback)
  }

  $.fn.fadeOut = function(speed, callback) {
    return hide(this, speed, null, callback)
  }

  $.fn.fadeToggle = function(speed, callback) {
    return this.each(function(){
      var el = $(this)
      el[
        (el.css('opacity') == 0 || el.css('display') == 'none') ? 'fadeIn' : 'fadeOut'
      ](speed, callback)
    })
  }

})(Zepto)


================================================
FILE: src/gesture.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  if ($.os.ios) {
    var gesture = {}, gestureTimeout

    function parentIfText(node){
      return 'tagName' in node ? node : node.parentNode
    }

    $(document).bind('gesturestart', function(e){
      var now = Date.now(), delta = now - (gesture.last || now)
      gesture.target = parentIfText(e.target)
      gestureTimeout && clearTimeout(gestureTimeout)
      gesture.e1 = e.scale
      gesture.last = now
    }).bind('gesturechange', function(e){
      gesture.e2 = e.scale
    }).bind('gestureend', function(e){
      if (gesture.e2 > 0) {
        Math.abs(gesture.e1 - gesture.e2) != 0 && $(gesture.target).trigger('pinch') &&
          $(gesture.target).trigger('pinch' + (gesture.e1 - gesture.e2 > 0 ? 'In' : 'Out'))
        gesture.e1 = gesture.e2 = gesture.last = 0
      } else if ('last' in gesture) {
        gesture = {}
      }
    })

    ;['pinch', 'pinchIn', 'pinchOut'].forEach(function(m){
      $.fn[m] = function(callback){ return this.bind(m, callback) }
    })
  }
})(Zepto)


================================================
FILE: src/ie.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function(){
  // getComputedStyle shouldn't freak out when called
  // without a valid element as argument
  try {
    getComputedStyle(undefined)
  } catch(e) {
    var nativeGetComputedStyle = getComputedStyle
    window.getComputedStyle = function(element, pseudoElement){
      try {
        return nativeGetComputedStyle(element, pseudoElement)
      } catch(e) {
        return null
      }
    }
  }
})()


================================================
FILE: src/ios3.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function(undefined){
  if (String.prototype.trim === undefined) // fix for iOS 3.2
    String.prototype.trim = function(){ return this.replace(/^\s+|\s+$/g, '') }

  // For iOS 3.x
  // from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
  if (Array.prototype.reduce === undefined)
    Array.prototype.reduce = function(fun){
      if(this === void 0 || this === null) throw new TypeError()
      var t = Object(this), len = t.length >>> 0, k = 0, accumulator
      if(typeof fun != 'function') throw new TypeError()
      if(len == 0 && arguments.length == 1) throw new TypeError()

      if(arguments.length >= 2)
       accumulator = arguments[1]
      else
        do{
          if(k in t){
            accumulator = t[k++]
            break
          }
          if(++k >= len) throw new TypeError()
        } while (true)

      while (k < len){
        if(k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t)
        k++
      }
      return accumulator
    }

})()


================================================
FILE: src/selector.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  var zepto = $.zepto, oldQsa = zepto.qsa, oldMatches = zepto.matches

  function visible(elem){
    elem = $(elem)
    return !!(elem.width() || elem.height()) && elem.css("display") !== "none"
  }

  // Implements a subset from:
  // http://api.jquery.com/category/selectors/jquery-selector-extensions/
  //
  // Each filter function receives the current index, all nodes in the
  // considered set, and a value if there were parentheses. The value
  // of `this` is the node currently being considered. The function returns the
  // resulting node(s), null, or undefined.
  //
  // Complex selectors are not supported:
  //   li:has(label:contains("foo")) + li:has(label:contains("bar"))
  //   ul.inner:first > li
  var filters = $.expr[':'] = {
    visible:  function(){ if (visible(this)) return this },
    hidden:   function(){ if (!visible(this)) return this },
    selected: function(){ if (this.selected) return this },
    checked:  function(){ if (this.checked) return this },
    parent:   function(){ return this.parentNode },
    first:    function(idx){ if (idx === 0) return this },
    last:     function(idx, nodes){ if (idx === nodes.length - 1) return this },
    eq:       function(idx, _, value){ if (idx === value) return this },
    contains: function(idx, _, text){ if ($(this).text().indexOf(text) > -1) return this },
    has:      function(idx, _, sel){ if (zepto.qsa(this, sel).length) return this }
  }

  var filterRe = new RegExp('(.*):(\\w+)(?:\\(([^)]+)\\))?$\\s*'),
      childRe  = /^\s*>/,
      classTag = 'Zepto' + (+new Date())

  function process(sel, fn) {
    // quote the hash in `a[href^=#]` expression
    sel = sel.replace(/=#\]/g, '="#"]')
    var filter, arg, match = filterRe.exec(sel)
    if (match && match[2] in filters) {
      filter = filters[match[2]], arg = match[3]
      sel = match[1]
      if (arg) {
        var num = Number(arg)
        if (isNaN(num)) arg = arg.replace(/^["']|["']$/g, '')
        else arg = num
      }
    }
    return fn(sel, filter, arg)
  }

  zepto.qsa = function(node, selector) {
    return process(selector, function(sel, filter, arg){
      try {
        var taggedParent
        if (!sel && filter) sel = '*'
        else if (childRe.test(sel))
          // support "> *" child queries by tagging the parent node with a
          // unique class and prepending that classname onto the selector
          taggedParent = $(node).addClass(classTag), sel = '.'+classTag+' '+sel

        var nodes = oldQsa(node, sel)
      } catch(e) {
        console.error('error performing selector: %o', selector)
        throw e
      } finally {
        if (taggedParent) taggedParent.removeClass(classTag)
      }
      return !filter ? nodes :
        zepto.uniq($.map(nodes, function(n, i){ return filter.call(n, i, nodes, arg) }))
    })
  }

  zepto.matches = function(node, selector){
    return process(selector, function(sel, filter, arg){
      return (!sel || oldMatches(node, sel)) &&
        (!filter || filter.call(node, null, arg) === node)
    })
  }
})(Zepto)


================================================
FILE: src/stack.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  $.fn.end = function(){
    return this.prevObject || $()
  }

  $.fn.andSelf = function(){
    return this.add(this.prevObject || $())
  }

  'filter,add,not,eq,first,last,find,closest,parents,parent,children,siblings'.split(',').forEach(function(property){
    var fn = $.fn[property]
    $.fn[property] = function(){
      var ret = fn.apply(this, arguments)
      ret.prevObject = this
      return ret
    }
  })
})(Zepto)


================================================
FILE: src/touch.js
================================================
//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

;(function($){
  var touch = {},
    touchTimeout, tapTimeout, swipeTimeout, longTapTimeout,
    longTapDelay = 750,
    gesture,
    down, up, move,
    eventMap,
    initialized = false

  function swipeDirection(x1, x2, y1, y2) {
    return Math.abs(x1 - x2) >=
      Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
  }

  function longTap() {
    longTapTimeout = null
    if (touch.last) {
      touch.el.trigger('longTap')
      touch = {}
    }
  }

  function cancelLongTap() {
    if (longTapTimeout) clearTimeout(longTapTimeout)
    longTapTimeout = null
  }

  function cancelAll() {
    if (touchTimeout) clearTimeout(touchTimeout)
    if (tapTimeout) clearTimeout(tapTimeout)
    if (swipeTimeout) clearTimeout(swipeTimeout)
    if (longTapTimeout) clearTimeout(longTapTimeout)
    touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null
    touch = {}
  }

  function isPrimaryTouch(event){
    return (event.pointerType == 'touch' ||
      event.pointerType == event.MSPOINTER_TYPE_TOUCH)
      && event.isPrimary
  }

  function isPointerEventType(e, type){
    return (e.type == 'pointer'+type ||
      e.type.toLowerCase() == 'mspointer'+type)
  }

  // helper function for tests, so they check for different APIs
  function unregisterTouchEvents(){
    if (!initialized) return
    $(document).off(eventMap.down, down)
      .off(eventMap.up, up)
      .off(eventMap.move, move)
      .off(eventMap.cancel, cancelAll)
    $(window).off('scroll', cancelAll)
    cancelAll()
    initialized = false
  }

  function setup(__eventMap){
    var now, delta, deltaX = 0, deltaY = 0, firstTouch, _isPointerType

    unregisterTouchEvents()

    eventMap = (__eventMap && ('down' in __eventMap)) ? __eventMap :
      ('ontouchstart' in document ?
      { 'down': 'touchstart', 'up': 'touchend',
        'move': 'touchmove', 'cancel': 'touchcancel' } :
      'onpointerdown' in document ?
      { 'down': 'pointerdown', 'up': 'pointerup',
        'move': 'pointermove', 'cancel': 'pointercancel' } :
       'onmspointerdown' in document ?
      { 'down': 'MSPointerDown', 'up': 'MSPointerUp',
        'move': 'MSPointerMove', 'cancel': 'MSPointerCancel' } : false)

    // No API availables for touch events
    if (!eventMap) return

    if ('MSGesture' in window) {
      gesture = new MSGesture()
      gesture.target = document.body

      $(document)
        .bind('MSGestureEnd', function(e){
          var swipeDirectionFromVelocity =
            e.velocityX > 1 ? 'Right' : e.velocityX < -1 ? 'Left' : e.velocityY > 1 ? 'Down' : e.velocityY < -1 ? 'Up' : null
          if (swipeDirectionFromVelocity) {
            touch.el.trigger('swipe')
            touch.el.trigger('swipe'+ swipeDirectionFromVelocity)
          }
        })
    }

    down = function(e){
      if((_isPointerType = isPointerEventType(e, 'down')) &&
        !isPrimaryTouch(e)) return
      firstTouch = _isPointerType ? e : e.touches[0]
      if (e.touches && e.touches.length === 1 && touch.x2) {
        // Clear out touch movement data if we have it sticking around
        // This can occur if touchcancel doesn't fire due to preventDefault, etc.
        touch.x2 = undefined
        touch.y2 = undefined
      }
      now = Date.now()
      delta = now - (touch.last || now)
      touch.el = $('tagName' in firstTouch.target ?
        firstTouch.target : firstTouch.target.parentNode)
      touchTimeout && clearTimeout(touchTimeout)
      touch.x1 = firstTouch.pageX
      touch.y1 = firstTouch.pageY
      if (delta > 0 && delta <= 250) touch.isDoubleTap = true
      touch.last = now
      longTapTimeout = setTimeout(longTap, longTapDelay)
      // adds the current touch contact for IE gesture recognition
      if (gesture && _isPointerType) gesture.addPointer(e.pointerId)
    }

    move = function(e){
      if((_isPointerType = isPointerEventType(e, 'move')) &&
        !isPrimaryTouch(e)) return
      firstTouch = _isPointerType ? e : e.touches[0]
      cancelLongTap()
      touch.x2 = firstTouch.pageX
      touch.y2 = firstTouch.pageY

      deltaX += Math.abs(touch.x1 - touch.x2)
      deltaY += Math.abs(touch.y1 - touch.y2)
    }

    up = function(e){
      if((_isPointerType = isPointerEventType(e, 'up')) &&
        !isPrimaryTouch(e)) return
      cancelLongTap()

      // swipe
      if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
          (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30))

        swipeTimeout = setTimeout(function() {
          if (touch.el){
            touch.el.trigger('swipe')
            touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))
          }
          touch = {}
        }, 0)

      // normal tap
      else if ('last' in touch)
        // don't fire tap when delta position changed by more than 30 pixels,
        // for instance when moving to a point and back to origin
        if (deltaX < 30 && deltaY < 30) {
          // delay by one tick so we can cancel the 'tap' event if 'scroll' fires
          // ('tap' fires before 'scroll')
          tapTimeout = setTimeout(function() {

            // trigger universal 'tap' with the option to cancelTouch()
            // (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
            var event = $.Event('tap')
            event.cancelTouch = cancelAll
            // [by paper] fix -> "TypeError: 'undefined' is not an object (evaluating 'touch.el.trigger'), when double tap
            if (touch.el) touch.el.trigger(event)

            // trigger double tap immediately
            if (touch.isDoubleTap) {
              if (touch.el) touch.el.trigger('doubleTap')
              touch = {}
            }

            // trigger single tap after 250ms of inactivity
            else {
              touchTimeout = setTimeout(function(){
                touchTimeout = null
                if (touch.el) touch.el.trigger('singleTap')
                touch = {}
              }, 250)
            }
          }, 0)
        } else {
          touch = {}
        }
        deltaX = deltaY = 0
    }

    $(document).on(eventMap.up, up)
      .on(eventMap.down, down)
      .on(eventMap.move, move)

    // when the browser window loses focus,
    // for example when a modal dialog is shown,
    // cancel all ongoing events
    $(document).on(eventMap.cancel, cancelAll)

    // scrolling the window indicates intention of the user
    // to scroll, not tap or swipe, so cancel all ongoing events
    $(window).on('scroll', cancelAll)

    initialized = true
  }

  ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown',
    'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(eventName){
    $.fn[eventName] = function(callback){ return this.on(eventName, callback) }
  })

  $.touch = { setup: setup }

  $(document).ready(setup)
})(Zepto)


================================================
FILE: src/zepto.js
================================================
//     Zepto.js
//     (c) 2010-2017 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

var Zepto = (function() {
  var undefined, key, $, classList, emptyArray = [], concat = emptyArray.concat, filter = emptyArray.filter, slice = emptyArray.slice,
    document = window.document,
    elementDisplay = {}, classCache = {},
    cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1,'opacity': 1, 'z-index': 1, 'zoom': 1 },
    fragmentRE = /^\s*<(\w+|!)[^>]*>/,
    singleTagRE = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
    tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
    rootNodeRE = /^(?:body|html)$/i,
    capitalRE = /([A-Z])/g,

    // special attributes that should be get/set via method calls
    methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'],

    adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ],
    table = document.createElement('table'),
    tableRow = document.createElement('tr'),
    containers = {
      'tr': document.createElement('tbody'),
      'tbody': table, 'thead': table, 'tfoot': table,
      'td': tableRow, 'th': tableRow,
      '*': document.createElement('div')
    },
    simpleSelectorRE = /^[\w-]*$/,
    class2type = {},
    toString = class2type.toString,
    zepto = {},
    camelize, uniq,
    tempParent = document.createElement('div'),
    propMap = {
      'tabindex': 'tabIndex',
      'readonly': 'readOnly',
      'for': 'htmlFor',
      'class': 'className',
      'maxlength': 'maxLength',
      'cellspacing': 'cellSpacing',
      'cellpadding': 'cellPadding',
      'rowspan': 'rowSpan',
      'colspan': 'colSpan',
      'usemap': 'useMap',
      'frameborder': 'frameBorder',
      'contenteditable': 'contentEditable'
    },
    isArray = Array.isArray ||
      function(object){ return object instanceof Array }

  zepto.matches = function(element, selector) {
    if (!selector || !element || element.nodeType !== 1) return false
    var matchesSelector = element.matches || element.webkitMatchesSelector ||
                          element.mozMatchesSelector || element.oMatchesSelector ||
                          element.matchesSelector
    if (matchesSelector) return matchesSelector.call(element, selector)
    // fall back to performing a selector:
    var match, parent = element.parentNode, temp = !parent
    if (temp) (parent = tempParent).appendChild(element)
    match = ~zepto.qsa(parent, selector).indexOf(element)
    temp && tempParent.removeChild(element)
    return match
  }

  function type(obj) {
    return obj == null ? String(obj) :
      class2type[toString.call(obj)] || "object"
  }

  function isFunction(value) { return type(value) == "function" }
  function isWindow(obj)     { return obj != null && obj == obj.window }
  function isDocument(obj)   { return obj != null && obj.nodeType == obj.DOCUMENT_NODE }
  function isObject(obj)     { return type(obj) == "object" }
  function isPlainObject(obj) {
    return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype
  }

  function likeArray(obj) {
    var length = !!obj && 'length' in obj && obj.length,
      type = $.type(obj)

    return 'function' != type && !isWindow(obj) && (
      'array' == type || length === 0 ||
        (typeof length == 'number' && length > 0 && (length - 1) in obj)
    )
  }

  function compact(array) { return filter.call(array, function(item){ return item != null }) }
  function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array }
  camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) }
  function dasherize(str) {
    return str.replace(/::/g, '/')
           .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
           .replace(/([a-z\d])([A-Z])/g, '$1_$2')
           .replace(/_/g, '-')
           .toLowerCase()
  }
  uniq = function(array){ return filter.call(array, function(item, idx){ return array.indexOf(item) == idx }) }

  function classRE(name) {
    return name in classCache ?
      classCache[name] : (classCache[name] = new RegExp('(^|\\s)' + name + '(\\s|$)'))
  }

  function maybeAddPx(name, value) {
    return (typeof value == "number" && !cssNumber[dasherize(name)]) ? value + "px" : value
  }

  function defaultDisplay(nodeName) {
    var element, display
    if (!elementDisplay[nodeName]) {
      element = document.createElement(nodeName)
      document.body.appendChild(element)
      display = getComputedStyle(element, '').getPropertyValue("display")
      element.parentNode.removeChild(element)
      display == "none" && (display = "block")
      elementDisplay[nodeName] = display
    }
    return elementDisplay[nodeName]
  }

  function children(element) {
    return 'children' in element ?
      slice.call(element.children) :
      $.map(element.childNodes, function(node){ if (node.nodeType == 1) return node })
  }

  function Z(dom, selector) {
    var i, len = dom ? dom.length : 0
    for (i = 0; i < len; i++) this[i] = dom[i]
    this.length = len
    this.selector = selector || ''
  }

  // `$.zepto.fragment` takes a html string and an optional tag name
  // to generate DOM nodes from the given html string.
  // The generated DOM nodes are returned as an array.
  // This function can be overridden in plugins for example to make
  // it compatible with browsers that don't support the DOM fully.
  zepto.fragment = function(html, name, properties) {
    var dom, nodes, container

    // A special case optimization for a single tag
    if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1))

    if (!dom) {
      if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>")
      if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
      if (!(name in containers)) name = '*'

      container = containers[name]
      container.innerHTML = '' + html
      dom = $.each(slice.call(container.childNodes), function(){
        container.removeChild(this)
      })
    }

    if (isPlainObject(properties)) {
      nodes = $(dom)
      $.each(properties, function(key, value) {
        if (methodAttributes.indexOf(key) > -1) nodes[key](value)
        else nodes.attr(key, value)
      })
    }

    return dom
  }

  // `$.zepto.Z` swaps out the prototype of the given `dom` array
  // of nodes with `$.fn` and thus supplying all the Zepto functions
  // to the array. This method can be overridden in plugins.
  zepto.Z = function(dom, selector) {
    return new Z(dom, selector)
  }

  // `$.zepto.isZ` should return `true` if the given object is a Zepto
  // collection. This method can be overridden in plugins.
  zepto.isZ = function(object) {
    return object instanceof zepto.Z
  }

  // `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and
  // takes a CSS selector and an optional context (and handles various
  // special cases).
  // This method can be overridden in plugins.
  zepto.init = function(selector, context) {
    var dom
    // If nothing given, return an empty Zepto collection
    if (!selector) return zepto.Z()
    // Optimize for string selectors
    else if (typeof selector == 'string') {
      selector = selector.trim()
      // If it's a html fragment, create nodes from it
      // Note: In both Chrome 21 and Firefox 15, DOM error 12
      // is thrown if the fragment doesn't begin with <
      if (selector[0] == '<' && fragmentRE.test(selector))
        dom = zepto.fragment(selector, RegExp.$1, context), selector = null
      // If there's a context, create a collection on that context first, and select
      // nodes from there
      else if (context !== undefined) return $(context).find(selector)
      // If it's a CSS selector, use it to select nodes.
      else dom = zepto.qsa(document, selector)
    }
    // If a function is given, call it when the DOM is ready
    else if (isFunction(selector)) return $(document).ready(selector)
    // If a Zepto collection is given, just return it
    else if (zepto.isZ(selector)) return selector
    else {
      // normalize array if an array of nodes is given
      if (isArray(selector)) dom = compact(selector)
      // Wrap DOM nodes.
      else if (isObject(selector))
        dom = [selector], selector = null
      // If it's a html fragment, create nodes from it
      else if (fragmentRE.test(selector))
        dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
      // If there's a context, create a collection on that context first, and select
      // nodes from there
      else if (context !== undefined) return $(context).find(selector)
      // And last but no least, if it's a CSS selector, use it to select nodes.
      else dom = zepto.qsa(document, selector)
    }
    // create a new Zepto collection from the nodes found
    return zepto.Z(dom, selector)
  }

  // `$` will be the base `Zepto` object. When calling this
  // function just call `$.zepto.init, which makes the implementation
  // details of selecting nodes and creating Zepto collections
  // patchable in plugins.
  $ = function(selector, context){
    return zepto.init(selector, context)
  }

  function extend(target, source, deep) {
    for (key in source)
      if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
        if (isPlainObject(source[key]) && !isPlainObject(target[key]))
          target[key] = {}
        if (isArray(source[key]) && !isArray(target[key]))
          target[key] = []
        extend(target[key], source[key], deep)
      }
      else if (source[key] !== undefined) target[key] = source[key]
  }

  // Copy all but undefined properties from one or more
  // objects to the `target` object.
  $.extend = function(target){
    var deep, args = slice.call(arguments, 1)
    if (typeof target == 'boolean') {
      deep = target
      target = args.shift()
    }
    args.forEach(function(arg){ extend(target, arg, deep) })
    return target
  }

  // `$.zepto.qsa` is Zepto's CSS selector implementation which
  // uses `document.querySelectorAll` and optimizes for some special cases, like `#id`.
  // This method can be overridden in plugins.
  zepto.qsa = function(element, selector){
    var found,
        maybeID = selector[0] == '#',
        maybeClass = !maybeID && selector[0] == '.',
        nameOnly = maybeID || maybeClass ? selector.slice(1) : selector, // Ensure that a 1 char tag name still gets checked
        isSimple = simpleSelectorRE.test(nameOnly)
    return (element.getElementById && isSimple && maybeID) ? // Safari DocumentFragment doesn't have getElementById
      ( (found = element.getElementById(nameOnly)) ? [found] : [] ) :
      (element.nodeType !== 1 && element.nodeType !== 9 && element.nodeType !== 11) ? [] :
      slice.call(
        isSimple && !maybeID && element.getElementsByClassName ? // DocumentFragment doesn't have getElementsByClassName/TagName
          maybeClass ? element.getElementsByClassName(nameOnly) : // If it's simple, it could be a class
          element.getElementsByTagName(selector) : // Or a tag
          element.querySelectorAll(selector) // Or it's not simple, and we need to query all
      )
  }

  function filtered(nodes, selector) {
    return selector == null ? $(nodes) : $(nodes).filter(selector)
  }

  $.contains = document.documentElement.contains ?
    function(parent, node) {
      return parent !== node && parent.contains(node)
    } :
    function(parent, node) {
      while (node && (node = node.parentNode))
        if (node === parent) return true
      return false
    }

  function funcArg(context, arg, idx, payload) {
    return isFunction(arg) ? arg.call(context, idx, payload) : arg
  }

  function setAttribute(node, name, value) {
    value == null ? node.removeAttribute(name) : node.setAttribute(name, value)
  }

  // access className property while respecting SVGAnimatedString
  function className(node, value){
    var klass = node.className || '',
        svg   = klass && klass.baseVal !== undefined

    if (value === undefined) return svg ? klass.baseVal : klass
    svg ? (klass.baseVal = value) : (node.className = value)
  }

  // "true"  => true
  // "false" => false
  // "null"  => null
  // "42"    => 42
  // "42.5"  => 42.5
  // "08"    => "08"
  // JSON    => parse if valid
  // String  => self
  function deserializeValue(value) {
    try {
      return value ?
        value == "true" ||
        ( value == "false" ? false :
          value == "null" ? null :
          +value + "" == value ? +value :
          /^[\[\{]/.test(value) ? $.parseJSON(value) :
          value )
        : value
    } catch(e) {
      return value
    }
  }

  $.type = type
  $.isFunction = isFunction
  $.isWindow = isWindow
  $.isArray = isArray
  $.isPlainObject = isPlainObject

  $.isEmptyObject = function(obj) {
    var name
    for (name in obj) return false
    return true
  }

  $.isNumeric = function(val) {
    var num = Number(val), type = typeof val
    return val != null && type != 'boolean' &&
      (type != 'string' || val.length) &&
      !isNaN(num) && isFinite(num) || false
  }

  $.inArray = function(elem, array, i){
    return emptyArray.indexOf.call(array, elem, i)
  }

  $.camelCase = camelize
  $.trim = function(str) {
    return str == null ? "" : String.prototype.trim.call(str)
  }

  // plugin compatibility
  $.uuid = 0
  $.support = { }
  $.expr = { }
  $.noop = function() {}

  $.map = function(elements, callback){
    var value, values = [], i, key
    if (likeArray(elements))
      for (i = 0; i < elements.length; i++) {
        value = callback(elements[i], i)
        if (value != null) values.push(value)
      }
    else
      for (key in elements) {
        value = callback(elements[key], key)
        if (value != null) values.push(value)
      }
    return flatten(values)
  }

  $.each = function(elements, callback){
    var i, key
    if (likeArray(elements)) {
      for (i = 0; i < elements.length; i++)
        if (callback.call(elements[i], i, elements[i]) === false) return elements
    } else {
      for (key in elements)
        if (callback.call(elements[key], key, elements[key]) === false) return elements
    }

    return elements
  }

  $.grep = function(elements, callback){
    return filter.call(elements, callback)
  }

  if (window.JSON) $.parseJSON = JSON.parse

  // Populate the class2type map
  $.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase()
  })

  // Define methods that will be available on all
  // Zepto collections
  $.fn = {
    constructor: zepto.Z,
    length: 0,

    // Because a collection acts like an array
    // copy over these useful array functions.
    forEach: emptyArray.forEach,
    reduce: emptyArray.reduce,
    push: emptyArray.push,
    sort: emptyArray.sort,
    splice: emptyArray.splice,
    indexOf: emptyArray.indexOf,
    concat: function(){
      var i, value, args = []
      for (i = 0; i < arguments.length; i++) {
        value = arguments[i]
        args[i] = zepto.isZ(value) ? value.toArray() : value
      }
      return concat.apply(zepto.isZ(this) ? this.toArray() : this, args)
    },

    // `map` and `slice` in the jQuery API work differently
    // from their array counterparts
    map: function(fn){
      return $($.map(this, function(el, i){ return fn.call(el, i, el) }))
    },
    slice: function(){
      return $(slice.apply(this, arguments))
    },

    ready: function(callback){
      // don't use "interactive" on IE <= 10 (it can fired premature)
      if (document.readyState === "complete" ||
          (document.readyState !== "loading" && !document.documentElement.doScroll))
        setTimeout(function(){ callback($) }, 0)
      else {
        var handler = function() {
          document.removeEventListener("DOMContentLoaded", handler, false)
          window.removeEventListener("load", handler, false)
          callback($)
        }
        document.addEventListener("DOMContentLoaded", handler, false)
        window.addEventListener("load", handler, false)
      }
      return this
    },
    get: function(idx){
      return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length]
    },
    toArray: function(){ return this.get() },
    size: function(){
      return this.length
    },
    remove: function(){
      return this.each(function(){
        if (this.parentNode != null)
          this.parentNode.removeChild(this)
      })
    },
    each: function(callback){
      emptyArray.every.call(this, function(el, idx){
        return callback.call(el, idx, el) !== false
      })
      return this
    },
    filter: function(selector){
      if (isFunction(selector)) return this.not(this.not(selector))
      return $(filter.call(this, function(element){
        return zepto.matches(element, selector)
      }))
    },
    add: function(selector,context){
      return $(uniq(this.concat($(selector,context))))
    },
    is: function(selector){
      return typeof selector == 'string' ? this.length > 0 && zepto.matches(this[0], selector) : 
          selector && this.selector == selector.selector
    },
    not: function(selector){
      var nodes=[]
      if (isFunction(selector) && selector.call !== undefined)
        this.each(function(idx){
          if (!selector.call(this,idx)) nodes.push(this)
        })
      else {
        var excludes = typeof selector == 'string' ? this.filter(selector) :
          (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector)
        this.forEach(function(el){
          if (excludes.indexOf(el) < 0) nodes.push(el)
        })
      }
      return $(nodes)
    },
    has: function(selector){
      return this.filter(function(){
        return isObject(selector) ?
          $.contains(this, selector) :
          $(this).find(selector).size()
      })
    },
    eq: function(idx){
      return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1)
    },
    first: function(){
      var el = this[0]
      return el && !isObject(el) ? el : $(el)
    },
    last: function(){
      var el = this[this.length - 1]
      return el && !isObject(el) ? el : $(el)
    },
    find: function(selector){
      var result, $this = this
      if (!selector) result = $()
      else if (typeof selector == 'object')
        result = $(selector).filter(function(){
          var node = this
          return emptyArray.some.call($this, function(parent){
            return $.contains(parent, node)
          })
        })
      else if (this.length == 1) result = $(zepto.qsa(this[0], selector))
      else result = this.map(function(){ return zepto.qsa(this, selector) })
      return result
    },
    closest: function(selector, context){
      var nodes = [], collection = typeof selector == 'object' && $(selector)
      this.each(function(_, node){
        while (node && !(collection ? collection.indexOf(node) >= 0 : zepto.matches(node, selector)))
          node = node !== context && !isDocument(node) && node.parentNode
        if (node && nodes.indexOf(node) < 0) nodes.push(node)
      })
      return $(nodes)
    },
    parents: function(selector){
      var ancestors = [], nodes = this
      while (nodes.length > 0)
        nodes = $.map(nodes, function(node){
          if ((node = node.parentNode) && !isDocument(node) && ancestors.indexOf(node) < 0) {
            ancestors.push(node)
            return node
          }
        })
      return filtered(ancestors, selector)
    },
    parent: function(selector){
      return filtered(uniq(this.pluck('parentNode')), selector)
    },
    children: function(selector){
      return filtered(this.map(function(){ return children(this) }), selector)
    },
    contents: function() {
      return this.map(function() { return this.contentDocument || slice.call(this.childNodes) })
    },
    siblings: function(selector){
      return filtered(this.map(function(i, el){
        return filter.call(children(el.parentNode), function(child){ return child!==el })
      }), selector)
    },
    empty: function(){
      return this.each(function(){ this.innerHTML = '' })
    },
    // `pluck` is borrowed from Prototype.js
    pluck: function(property){
      return $.map(this, function(el){ return el[property] })
    },
    show: function(){
      return this.each(function(){
        this.style.display == "none" && (this.style.display = '')
        if (getComputedStyle(this, '').getPropertyValue("display") == "none")
          this.style.display = defaultDisplay(this.nodeName)
      })
    },
    replaceWith: function(newContent){
      return this.before(newContent).remove()
    },
    wrap: function(structure){
      var func = isFunction(structure)
      if (this[0] && !func)
        var dom   = $(structure).get(0),
            clone = dom.parentNode || this.length > 1

      return this.each(function(index){
        $(this).wrapAll(
          func ? structure.call(this, index) :
            clone ? dom.cloneNode(true) : dom
        )
      })
    },
    wrapAll: function(structure){
      if (this[0]) {
        $(this[0]).before(structure = $(structure))
        var children
        // drill down to the inmost element
        while ((children = structure.children()).length) structure = children.first()
        $(structure).append(this)
      }
      return this
    },
    wrapInner: function(structure){
      var func = isFunction(structure)
      return this.each(function(index){
        var self = $(this), contents = self.contents(),
            dom  = func ? structure.call(this, index) : structure
        contents.length ? contents.wrapAll(dom) : self.append(dom)
      })
    },
    unwrap: function(){
      this.parent().each(function(){
        $(this).replaceWith($(this).children())
      })
      return this
    },
    clone: function(){
      return this.map(function(){ return this.cloneNode(true) })
    },
    hide: function(){
      return this.css("display", "none")
    },
    toggle: function(setting){
      return this.each(function(){
        var el = $(this)
        ;(setting === undefined ? el.css("display") == "none" : setting) ? el.show() : el.hide()
      })
    },
    prev: function(selector){ return $(this.pluck('previousElementSibling')).filter(selector || '*') },
    next: function(selector){ return $(this.pluck('nextElementSibling')).filter(selector || '*') },
    html: function(html){
      return 0 in arguments ?
        this.each(function(idx){
          var originHtml = this.innerHTML
          $(this).empty().append( funcArg(this, html, idx, originHtml) )
        }) :
        (0 in this ? this[0].innerHTML : null)
    },
    text: function(text){
      return 0 in arguments ?
        this.each(function(idx){
          var newText = funcArg(this, text, idx, this.textContent)
          this.textContent = newText == null ? '' : ''+newText
        }) :
        (0 in this ? this.pluck('textContent').join("") : null)
    },
    attr: function(name, value){
      var result
      return (typeof name == 'string' && !(1 in arguments)) ?
        (0 in this && this[0].nodeType == 1 && (result = this[0].getAttribute(name)) != null ? result : undefined) :
        this.each(function(idx){
          if (this.nodeType !== 1) return
          if (isObject(name)) for (key in name) setAttribute(this, key, name[key])
          else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)))
        })
    },
    removeAttr: function(name){
      return this.each(function(){ this.nodeType === 1 && name.split(' ').forEach(function(attribute){
        setAttribute(this, attribute)
      }, this)})
    },
    prop: function(name, value){
      name = propMap[name] || name
      return (typeof name == 'string' && !(1 in arguments)) ?
        (this[0] && this[0][name]) :
        this.each(function(idx){
          if (isObject(name)) for (key in name) this[propMap[key] || key] = name[key]
          else this[name] = funcArg(this, value, idx, this[name])
        })
    },
    removeProp: function(name){
      name = propMap[name] || name
      return this.each(function(){ delete this[name] })
    },
    data: function(name, value){
      var attrName = 'data-' + name.replace(capitalRE, '-$1').toLowerCase()

      var data = (1 in arguments) ?
        this.attr(attrName, value) :
        this.attr(attrName)

      return data !== null ? deserializeValue(data) : undefined
    },
    val: function(value){
      if (0 in arguments) {
        if (value == null) value = ""
        return this.each(function(idx){
          this.value = funcArg(this, value, idx, this.value)
        })
      } else {
        return this[0] && (this[0].multiple ?
           $(this[0]).find('option').filter(function(){ return this.selected }).pluck('value') :
           this[0].value)
      }
    },
    offset: function(coordinates){
      if (coordinates) return this.each(function(index){
        var $this = $(this),
            coords = funcArg(this, coordinates, index, $this.offset()),
            parentOffset = $this.offsetParent().offset(),
            props = {
              top:  coords.top  - parentOffset.top,
              left: coords.left - parentOffset.left
            }

        if ($this.css('position') == 'static') props['position'] = 'relative'
        $this.css(props)
      })
      if (!this.length) return null
      if (document.documentElement !== this[0] && !$.contains(document.documentElement, this[0]))
        return {top: 0, left: 0}
      var obj = this[0].getBoundingClientRect()
      return {
        left: obj.left + window.pageXOffset,
        top: obj.top + window.pageYOffset,
        width: Math.round(obj.width),
        height: Math.round(obj.height)
      }
    },
    css: function(property, value){
      if (arguments.length < 2) {
        var element = this[0]
        if (typeof property == 'string') {
          if (!element) return
          return element.style[camelize(property)] || getComputedStyle(element, '').getPropertyValue(property)
        } else if (isArray(property)) {
          if (!element) return
          var props = {}
          var computedStyle = getComputedStyle(element, '')
          $.each(property, function(_, prop){
            props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop))
          })
          return props
        }
      }

      var css = ''
      if (type(property) == 'string') {
        if (!value && value !== 0)
          this.each(function(){ this.style.removeProperty(dasherize(property)) })
        else
          css = dasherize(property) + ":" + maybeAddPx(property, value)
      } else {
        for (key in property)
          if (!property[key] && property[key] !== 0)
            this.each(function(){ this.style.removeProperty(dasherize(key)) })
          else
            css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'
      }

      return this.each(function(){ this.style.cssText += ';' + css })
    },
    index: function(element){
      return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf(this[0])
    },
    hasClass: function(name){
      if (!name) return false
      return emptyArray.some.call(this, function(el){
        return this.test(className(el))
      }, classRE(name))
    },
    addClass: function(name){
      if (!name) return this
      return this.each(function(idx){
        if (!('className' in this)) return
        classList = []
        var cls = className(this), newName = funcArg(this, name, idx, cls)
        newName.split(/\s+/g).forEach(function(klass){
          if (!$(this).hasClass(klass)) classList.push(klass)
        }, this)
        classList.length && className(this, cls + (cls ? " " : "") + classList.join(" "))
      })
    },
    removeClass: function(name){
      return this.each(function(idx){
        if (!('className' in this)) return
        if (name === undefined) return className(this, '')
        classList = className(this)
        funcArg(this, name, idx, classList).split(/\s+/g).forEach(function(klass){
          classList = classList.replace(classRE(klass), " ")
        })
        className(this, classList.trim())
      })
    },
    toggleClass: function(name, when){
      if (!name) return this
      return this.each(function(idx){
        var $this = $(this), names = funcArg(this, name, idx, className(this))
        names.split(/\s+/g).forEach(function(klass){
          (when === undefined ? !$this.hasClass(klass) : when) ?
            $this.addClass(klass) : $this.removeClass(klass)
        })
      })
    },
    scrollTop: function(value){
      if (!this.length) return
      var hasScrollTop = 'scrollTop' in this[0]
      if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset
      return this.each(hasScrollTop ?
        function(){ this.scrollTop = value } :
        function(){ this.scrollTo(this.scrollX, value) })
    },
    scrollLeft: function(value){
      if (!this.length) return
      var hasScrollLeft = 'scrollLeft' in this[0]
      if (value === undefined) return hasScrollLeft ? this[0].scrollLeft : this[0].pageXOffset
      return this.each(hasScrollLeft ?
        function(){ this.scrollLeft = value } :
        function(){ this.scrollTo(value, this.scrollY) })
    },
    position: function() {
      if (!this.length) return

      var elem = this[0],
        // Get *real* offsetParent
        offsetParent = this.offsetParent(),
        // Get correct offsets
        offset       = this.offset(),
        parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset()

      // Subtract element margins
      // note: when an element has margin: auto the offsetLeft and marginLeft
      // are the same in Safari causing offset.left to incorrectly be 0
      offset.top  -= parseFloat( $(elem).css('margin-top') ) || 0
      offset.left -= parseFloat( $(elem).css('margin-left') ) || 0

      // Add offsetParent borders
      parentOffset.top  += parseFloat( $(offsetParent[0]).css('border-top-width') ) || 0
      parentOffset.left += parseFloat( $(offsetParent[0]).css('border-left-width') ) || 0

      // Subtract the two offsets
      return {
        top:  offset.top  - parentOffset.top,
        left: offset.left - parentOffset.left
      }
    },
    offsetParent: function() {
      return this.map(function(){
        var parent = this.offsetParent || document.body
        while (parent && !rootNodeRE.test(parent.nodeName) && $(parent).css("position") == "static")
          parent = parent.offsetParent
        return parent
      })
    }
  }

  // for now
  $.fn.detach = $.fn.remove

  // Generate the `width` and `height` functions
  ;['width', 'height'].forEach(function(dimension){
    var dimensionProperty =
      dimension.replace(/./, function(m){ return m[0].toUpperCase() })

    $.fn[dimension] = function(value){
      var offset, el = this[0]
      if (value === undefined) return isWindow(el) ? el['inner' + dimensionProperty] :
        isDocument(el) ? el.documentElement['scroll' + dimensionProperty] :
        (offset = this.offset()) && offset[dimension]
      else return this.each(function(idx){
        el = $(this)
        el.css(dimension, funcArg(this, value, idx, el[dimension]()))
      })
    }
  })

  function traverseNode(node, fun) {
    fun(node)
    for (var i = 0, len = node.childNodes.length; i < len; i++)
      traverseNode(node.childNodes[i], fun)
  }

  // Generate the `after`, `prepend`, `before`, `append`,
  // `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods.
  adjacencyOperators.forEach(function(operator, operatorIndex) {
    var inside = operatorIndex % 2 //=> prepend, append

    $.fn[operator] = function(){
      // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings
      var argType, nodes = $.map(arguments, function(arg) {
            var arr = []
            argType = type(arg)
            if (argType == "array") {
              arg.forEach(function(el) {
                if (el.nodeType !== undefined) return arr.push(el)
                else if ($.zepto.isZ(el)) return arr = arr.concat(el.get())
                arr = arr.concat(zepto.fragment(el))
              })
              return arr
            }
            return argType == "object" || arg == null ?
              arg : zepto.fragment(arg)
          }),
          parent, copyByClone = this.length > 1
      if (nodes.length < 1) return this

      return this.each(function(_, target){
        parent = inside ? target : target.parentNode

        // convert all methods to a "before" operation
        target = operatorIndex == 0 ? target.nextSibling :
                 operatorIndex == 1 ? target.firstChild :
                 operatorIndex == 2 ? target :
                 null

        var parentInDocument = $.contains(document.documentElement, parent)

        nodes.forEach(function(node){
          if (copyByClone) node = node.cloneNode(true)
          else if (!parent) return $(node).remove()

          parent.insertBefore(node, target)
          if (parentInDocument) traverseNode(node, function(el){
            if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' &&
               (!el.type || el.type === 'text/javascript') && !el.src){
              var target = el.ownerDocument ? el.ownerDocument.defaultView : window
              target['eval'].call(target, el.innerHTML)
            }
          })
        })
      })
    }

    // after    => insertAfter
    // prepend  => prependTo
    // before   => insertBefore
    // append   => appendTo
    $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){
      $(html)[operator](this)
      return this
    }
  })

  zepto.Z.prototype = Z.prototype = $.fn

  // Export internal API functions in the `$.zepto` namespace
  zepto.uniq = uniq
  zepto.deserializeValue = deserializeValue
  $.zepto = zepto

  return $
})()

// If `$` is not yet defined, point it to `Zepto`
window.Zepto = Zepto
window.$ === undefined && (window.$ = Zepto)


================================================
FILE: test/ajax.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <link rel="stylesheet" href="test.css">
  <title>Zepto Ajax unit tests</title>
  <script src="../vendor/evidence.js"></script>
  <script src="evidence_runner.js"></script>
  <script>
    // avoid caching
    (function(){
      function load(scripts){
        scripts.split(' ').forEach(function(script){
          document.write('<script src="../src/'+script+'.js?'+(+new Date)+'"></scr'+'ipt>')
        })
      }

      load('zepto event ajax ie')
    })()
  </script>
</head>
<body>
  <h1>Zepto Ajax unit tests</h1>
  <p id="results">
    Running… see browser console for results
  </p>
  <div id="fixtures">
    <div id="ajax_load"></div>
  </div>

  <script>
  (function(){

    function deferredResume(t, fn) {
      setTimeout(function() { t.resume(fn || function(){}) }, 5)
    }

    function resumeOnAjaxError(t) {
      $(document).on('ajaxError', function(e, xhr){
        deferredResume(t, function(){
          t.assert(false, "request errored out: " + xhr.responseText)
        })
      })
    }

    function toArray(list) {
      if ($.type(list) == "string") return list.split(/(?:\s*,\s*|\s+)/)
      else return list
    }

    Evidence.Assertions.assertEqualList = function(expected, actual, message) {
      var expectedList = toArray(expected),
          actualList   = toArray(actual)

      this._assertExpression(
        expectedList.join(' ') == actualList.join(' '),
        message || "Lists don't match.",
        'Expected %o, got %o.', expectedList, actualList
      )
    }

    Evidence.Assertions.assertLine = function(line, string, message) {
      var lines = string.split("\n")

      this._assertExpression(
        $.inArray(line, lines) >= 0,
        message || "Line not found.",
        'Expected line %s in %s.', line, string
      )
    }

    Evidence.Assertions.assertLinePattern = function(pattern, string, message) {
      var lines = string.split("\n")

      var i, match = false
      if (lines.length) {
        for (i = 0; i < lines.length; i++) {
          if (lines[i].search(pattern) !== -1) {
            match = true
            break
          }
        }
      }

      this._assertExpression(
        match === true,
        message || "Pattern not found.",
        'Expected pattern %s in %s.', pattern, string
      )
    }

    var slice = [].slice

    function CallbackRegistry(t) {
      this.testCase = t
      this.called = []
    }
    $.extend(CallbackRegistry.prototype, {
      register: function(name, context, args){
        this.called.push([name, context, args])
      },
      handler: function(name, fn){
        var that = this
        return function(){
          that.register(name, this, slice.call(arguments))
          if (fn) return fn.apply(this, arguments)
        }
      },
      resumeHandler: function(name, fn){
        var that = this
        return this.handler(name, function(){
          var context = this, args = arguments
          setTimeout(function(){
            that.testCase.resume(function(){
              if (fn) fn.apply(context, args)
            })
          }, 5)
        })
      },
      handlers: function(){
        var that = this, hash = {}
        $.each(arguments, function(i, name){
          hash[name] = that.handler(name)
        })
        return hash
      },
      events: function(){
        return $.map(this.called, function(item){ return item[0] })
      },
      context: function(name){
        return this.find(name, function(item){ return item[1] })
      },
      args: function(name){
        return this.find(name, function(item){ return item[2] })
      },
      target: function(name){
        var args = this.args(name)
        return args && args[0].target
      },
      find: function(name, fn){
        var obj
        $.each(this.called, function(i, item){
          if (item[0] == name) {
            obj = fn(item)
            return false
          }
        })
        return obj
      }
    })

    Evidence('ZeptoAjaxTest', {

      setUp: function() {
        var reg = new CallbackRegistry(this),
            globals = toArray('ajaxBeforeSend ajaxSend ajaxSuccess ajaxError ajaxComplete')

        $(document).on(reg.handlers.apply(reg, globals))
        this.reg = reg
        window.jsonpDummy = $.noop
      },

      tearDown: function() {
        $(document).off()
        for (var key in window)
          if (/^(Zepto\d+|blah)$/.test(key) && window[key] === undefined)
            delete window[key]
      },

      testAjaxBase: function(t){
        t.pause()
        var xhr = $.ajax({
          url: 'fixtures/ajax_load_simple.html',
          success:  t.reg.handler('success'),
          error:    t.reg.handler('error'),
          complete: t.reg.resumeHandler('complete', function(){
            t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess complete ajaxComplete', t.reg.events())
          })
        })
        t.assert($.isFunction(xhr.getResponseHeader))
      },

      testAjaxGet: function(t){
        t.pause()
        var xhr = $.get('echo', t.reg.resumeHandler('success', function(response){
          t.assertIdentical(window, this)
          t.assertLine("GET ?{}", response)
          t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())
        }))
        t.assertIn('abort', xhr)
      },

      testAjaxGetWithParams: function(t){
        t.pause()
        $.get('echo', { sample: 'data' }, t.reg.resumeHandler('success', function(response){
          t.assertLine('GET ?{"sample":"data"}', response)
          t.assertLine("accept: */*", response)
        }))
      },

      testAjaxGetWithParamsAndType: function(t){
        t.pause()
        $.get('echo', { sample: 'plain' }, t.reg.resumeHandler('success', function(response){
          t.assertLine('GET ?{"sample":"plain"}', response)
          t.assertLine("accept: text/plain", response)
        }), 'text')
      },

      testAjaxGetWithParamsAndTypeNoCallback: function(t){
        t.pause()
        $(document).on('ajaxSuccess', function(e, xhr, settings, response){
          deferredResume(t, function(){
            t.assertLine('GET ?{"sample":"plain"}', response)
            t.assertLine("accept: text/plain", response)
            t.assertEqualList('ajaxBeforeSend ajaxSend ajaxSuccess ajaxComplete', t.reg.events())
          })
        })
        $.get('echo', { sample: 'plain' }, 'text')
      },

      testAjaxGetWithParamsAutoParsesJSON: function(t) {
        t.pause()
        $.get('json', { sample: 'data' }, t.reg.resumeHandler('success', function(data){
          t.assertEqual('data', data.query.sample)
          t.assertEqual('world', data.hello)
        }))
      },

      testAjaxGetNoParamsAutoParsesJSON: function(t) {
        t.pause()
        $.get('json', t.reg.resumeHandler('success', function(data){
          t.assertIdentical(0, $.map(data.query).length)
          t.assertEqual('world', data.hello)
        }))
      },

      testAjaxGetNullParamsAutoParsesJSON: function(t) {
        t.pause()
        $.get('json', null, t.reg.resumeHandler('success', function(data){
          t.assertIdentical(0, $.map(data.query).length)
          t.assertEqual('world', data.hello)
        }))
      },

      testAjaxBeforeSendSetRequestHeader: function(t){
        t.pause()
        $.ajax({
          url: 'echo',
          beforeSend: function(xhr, settings){
            xhr.setRequestHeader('Accept', 'text/plain')
            t.assertUndefined(settings.headers)
          },
          success: t.reg.resumeHandler('success', function(response){
            t.assertLine("accept: text/plain", response)
          })
        })
      },

      testAjaxPost: function(t){
        t.pause()
        var xhr = $.post('echo', t.reg.resumeHandler('success', function(response){
          t.assertIdentical(window, this)
          t.assertLine("POST ?{}", response)
          t.assertLine("accept: */*", response)
          t.assertLine('{}', response)
          t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())
        }))
        t.assertIn('abort', xhr)
      },

      testAjaxPostWithPayloadAndType: function(t) {
        t.pause()
        var payload = { sample: 'data' }
        $.post('echo', payload, t.reg.resumeHandler('success', function(response){
          t.assertLine("content-type: application/x-www-form-urlencoded", response)
          t.assertLine("accept: text/plain", response)
          t.assertLine('{"sample":"data"}', response)
        }), 'text')
      },

      testAjaxPostAutoParsesJSON: function(t) {
        t.pause()
        var payload = { sample: 'data' }
        $.post('create', payload, t.reg.resumeHandler('success', function(data){
          t.assertEqual('data', data.payload.sample)
        }))
      },

      testNumberOfActiveRequests: function(t) {
        var maxActive = 0, ajaxStarted = 0, ajaxEnded = 0, requestsCompleted = 0
        t.assertIdentical(0, $.active, 'initial count mismatch')
        $(document)
          .on('ajaxStart', function() { ajaxStarted++ })
          .on('ajaxEnd', function() { ajaxEnded++ })
          .on('ajaxSend', function() {
            if ($.active > maxActive) maxActive = $.active
          })
          .on('ajaxComplete', function() {
            if (++requestsCompleted == 3)
              deferredResume(t, function() {
                this.assertEqual(3, maxActive)
                this.assertIdentical(0, $.active)
              })
          })

        t.pause()
        $.ajax({ url: 'echo' })
        $.ajax({ url: 'echo' })
        $.ajax({ url: 'echo' })
      },

      testAjaxJSON: function(t){
        t.pause()
        resumeOnAjaxError(t)

        $.ajax({
          url: 'json',
          headers: { accept: 'application/json' },
          success: t.reg.resumeHandler('success', function(data){
            t.assertEqual('world', data.hello)
          })
        })
      },

      testAjaxDataFilterJSON: function(t){
        t.pause()
        resumeOnAjaxError(t)

        $.ajax({
          url: 'taintedJSON',
          dataFilter: function(data, type) {
            if (!data) return
            return data.replace(/^\s*while\(1\);\s*/, '')
          },
          headers: { accept: 'application/json' },
          success: t.reg.resumeHandler('success', function(data){
            t.assertEqual('world', data.hello)
          })
        })
      },

      testAjaxGetJSON: function(t){
        t.pause()
        resumeOnAjaxError(t)

        var xhr = $.getJSON(
          'json',
          t.reg.resumeHandler('success', function(data){
            t.assertEqual('world', data.hello)
            t.assert($.isEmptyObject(data.query))
            t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())
          })
        )
        t.assertIn('abort', xhr)
      },

      testAjaxGetJSONWithParams: function(t){
        t.pause()
        resumeOnAjaxError(t)

        $.getJSON(
          'json', { sample: 'data' },
          t.reg.resumeHandler('success', function(data){
            t.assertEqual('data', data.query.sample)
          }),
          'text' // ignored
        )
      },

      testAjaxJSONParserError: function(t){
        t.pause()
        $.ajax({
          url:      'json',
          dataType: 'json',
          data:     { invalid: true },
          success:  t.reg.handler('success'),
          error:    t.reg.handler('error'),
          complete: t.reg.resumeHandler('complete', function(){
            t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())
            var errorArgs = t.reg.args('error')
            t.assertEqual('parsererror', errorArgs[1])
            t.assert(errorArgs[2] instanceof SyntaxError)
            var globalErrorArgs = t.reg.args('ajaxError')
            t.assert(globalErrorArgs[3] instanceof SyntaxError)
            t.assertEqual(0, $('script[src^=slow]').size())
          })
        })
      },

      testAjaxEqualQuestionmarkIsNotAlwaysJSONP: function(t){
        t.pause()
        resumeOnAjaxError(t)
        $.ajax({
          url: 'echo=?',
          dataType: 'text',
          success: t.reg.resumeHandler('success', function(data){
            t.assertLine('GET ?{}', data)
            t.assertLine("accept: text/plain", data)
          })
        })
      },

      testAjaxGetJSONP: function(t){
        t.pause()
        $.getJSON(
          'jsonp?callback=?&timestamp='+(+new Date),
          t.reg.resumeHandler('success', function(data){
            t.assertEqual('world', data.hello)
            t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())
            t.assertEqual(0, $('script[src^=jsonp]').size())
          })
        )
        t.assertEqual(1, $('script[src^=jsonp]').size())
      },

      testAjaxGetJSONPWithParams: function(t){
        t.pause()
        $.getJSON(
          'jsonp?callback=?&timestamp='+(+new Date),
          { sample: 'data' },
          t.reg.resumeHandler('success', function(data){
            t.assertEqual('data', data.query.sample)
          })
        )
      },

      testAjaxJSONP: function(t){
        t.pause()
        var xhr = $.ajaxJSONP({
          url: 'jsonp?callback=?&timestamp='+(+new Date),
          success:  t.reg.handler('success'),
          complete: t.reg.resumeHandler('complete', function(data){
            var successArgs = t.reg.args('success')
            t.assertEqual('world', successArgs[0].hello)
            t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess complete ajaxComplete', t.reg.events())
            t.assertEqual(0, $('script[src^=jsonp]').size())
          })
        })
        t.assertIn('abort', xhr)
      },

      testAjaxJSONPBeforeSend: function(t){
        t.pause()
        $(document).on('ajaxBeforeSend', function(){ return false })

        $.ajax({
          url: 'jsonp?callback=?&timestamp='+(+new Date),
          beforeSend: t.reg.resumeHandler('beforeSend', function(){
            t.assertEqualList('beforeSend ajaxBeforeSend ajaxError complete ajaxComplete', t.reg.events())
          }),
          success:  t.reg.handler('success'),
          complete: t.reg.handler('complete')
        })
      },

      testAjaxGetJSONPErrorCallback: function(t){
        t.pause()
        $.ajax({
          type:     'GET',
          url:      'fixtures/404.js?timestamp='+(+new Date),
          dataType: 'jsonp',
          success:  t.reg.handler('success'),
          error:    t.reg.handler('error'),
          complete: t.reg.resumeHandler('complete', function(){
            t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())
            t.assertEqual(0, $('script[src^=fixtures]').size())
          })
        })
      },

      testAjaxGetJSONPErrorWithoutCallback: function(t){
        t.pause()
        $.ajax({
          type:     'GET',
          url:      'fixtures/404.js?timestamp='+(+new Date),
          dataType: 'jsonp',
          success:  t.reg.handler('success'),
          complete: t.reg.resumeHandler('complete', function(){
            t.assertEqualList('ajaxBeforeSend ajaxSend ajaxError complete ajaxComplete', t.reg.events())
            t.assertEqual(0, $('script[src^=fixtures]').size())
          })
        })
      },

      testAjaxJSONPTimeout: function(t){
        t.pause()
        $.ajax({
          url:      'slow?timestamp='+(+new Date),
          dataType: 'jsonp',
          jsonpCallback: 'jsonpDummy',
          timeout:  20,
          success:  t.reg.handler('success'),
          error:    t.reg.handler('error'),
          complete: t.reg.resumeHandler('complete', function(){
            t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())
            var errorArgs = t.reg.args('error')
            t.assertEqual('timeout', errorArgs[1])
            var globalErrorArgs = t.reg.args('ajaxError')
            t.assertEqual('timeout', globalErrorArgs[3])
            t.assertEqual(0, $('script[src^=slow]').size())
          })
        })
      },

      testAjaxJSONPAbort: function(t){
        t.pause()
        var xhr = $.ajax({
          url:      'slow?timestamp='+(+new Date),
          dataType: 'jsonp',
          jsonpCallback: 'jsonpDummy',
          timeout:  30,
          success:  t.reg.handler('success'),
          error:    t.reg.handler('error'),
          complete: t.reg.handler('complete')
        })
        setTimeout(function(){ xhr.abort() }, 10)

        setTimeout(function(){
          t.resume(function(){
            t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())
            var errorArgs = t.reg.args('error')
            t.assertEqual('abort', errorArgs[1])
            var globalErrorArgs = t.reg.args('ajaxError')
            t.assertEqual('abort', globalErrorArgs[3])
            t.assertEqual(0, $('script[src^=slow]').size())
          })
        }, 50)
      },

      testAjaxJSONPError: function(t){
        t.pause()
        var xhr = $.ajax({
          url:      'error?timestamp='+(+new Date),
          dataType: 'jsonp',
          success:  t.reg.handler('success'),
          error:    t.reg.handler('error'),
          complete: t.reg.resumeHandler('complete', function(){
            t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())
            var errorArgs = t.reg.args('error')
            t.assertEqual('error', errorArgs[1])
            t.assertEqual(0, $('script[src^=error]').size())
          })
        })
      },

      testAjaxJSONPWithDataSupport: function(t) {
        t.pause()
        var xhr = $.ajax({
          url: 'jsonp?callback=?&timestamp='+(+new Date),
          data: {
            param1: 'val1',
            param2: 'val2'
          },
          success: t.reg.resumeHandler('success', function(data){
            t.assertEqual('val1', data.query.param1)
            t.assertEqual('val2', data.query.param2)
          })
        })
      },

      testAjaxJSONPWithCallbackName: function(t) {
        var xhr = $.ajax({
          url: 'jsonp',
          dataType: 'jsonp',
          jsonpCallback: 'blah',
          success: t.reg.resumeHandler('success', function(data){
            t.assertUndefined(window.blah)
          })
        })

        t.assert($.isFunction(window.blah))
        t.pause()
      },

      testAjaxJSONPWithCallbackNameAsFunction: function(t) {
        var xhr = $.ajax({
          url: 'jsonp',
          dataType: 'jsonp',
          jsonpCallback: function(){ return 'blah' },
          success: t.reg.resumeHandler('success', function(data){
            t.assertUndefined(window.blah)
          })
        })

        t.assert($.isFunction(window.blah))
        t.pause()
      },

      testAjaxJSONPWithCallbackNameAndJSONPsetToFalse: function(t) {
        var xhr = $.ajax({
          url: 'jsonpBlah',
          dataType: 'jsonp',
          jsonp: false,
          jsonpCallback: 'blah',
          success: t.reg.resumeHandler('success', function(data){
            t.assertUndefined(window.blah)
          })
        })

        var scriptSrc = $('head script:last-child').attr('src')
        t.assert(/^jsonpBlah\?_=[\d]{13}$/.test(scriptSrc), scriptSrc)
        t.assert($.isFunction(window.blah))
        t.pause()
      },

      testAjaxJSONPWithCallbackNameAsFunctionAndJSONPsetToFalse: function(t) {
        var xhr = $.ajax({
          url: 'jsonpBlah',
          dataType: 'jsonp',
          jsonp: false,
          jsonpCallback: function(){ return 'blah' },
          success: t.reg.resumeHandler('success', function(data){
            t.assertUndefined(window.blah)
          })
        })

        var scriptSrc = $('head script:last-child').attr('src')
        t.assert(/^jsonpBlah\?_=[\d]{13}$/.test(scriptSrc), scriptSrc)
        t.assert($.isFunction(window.blah))
        t.pause()
      },

      testAjaxJSONPWithData: function(t) {
        t.pause()
        $.ajax({
          url: 'jsonp',
          type: 'post',
          data: { foo: 'bar' },
          dataType: 'jsonp',
          success: t.reg.resumeHandler('success', function(data){
            t.assertEqual('bar', data.query.foo)
          })
        })
      },

      testNoCacheParam: function(t) {
        t.pause()
        var xhr = $.ajax({
          url:'echo',
          cache: false,
          success: t.reg.resumeHandler('success', function(response){
            // check that the no-cache param (or an element of it) looks like a timestamp
            t.assertLinePattern(/"_":(\[".*",)?"[\d]{13}"/g, response)
          })
        })
      },

      testNoCacheParameterWithParam: function(t) {
        t.pause()
        var xhr = $.ajax({
          url:'echo',
          data:{ data: 'sample' },
          cache: false,
          success: t.reg.resumeHandler('success', function(response){
            // check that the no-cache param (or an element of it) looks like a timestamp
            t.assertLinePattern(/"_":(\[".*",)?"[\d]{13}"/g, response)
          })
        })
      },

      testNoCacheParameterAlreadyPresent: function(t) {
        t.pause()
        var xhr = $.ajax({
          url:'echo',
          data:{ _: 'test' },
          cache: false,
          success: t.reg.resumeHandler('success', function(response){
            // check that the no-cache param (or an element of it) looks like a timestamp
            t.assertLinePattern(/"_":(\[".*",)?"[\d]{13}"/g, response)
          })
        })
      },

      testNoCacheParameterAlreadyPresentWithParam: function(t) {
        t.pause()
        var xhr = $.ajax({
          url:'echo',
          data:{ _: 'test', data: 'sample' },
          cache: false,
          success: t.reg.resumeHandler('success', function(response){
            // check that the no-cache param (or an element of it) looks like a timestamp
            t.assertLinePattern(/"_":(\[".*",)?"[\d]{13}"/g, response)
          })
        })
      },

      testJSONPCacheBustingByDefault: function(t) {
        $.ajax({
          url: 'jsonp?callback=?',
          success: t.reg.resumeHandler('success')
        })

        var scriptSrc = $('head script:last-child').attr('src')
        t.assert(/^jsonp\?callback=Zepto\d+&_=[\d]{13}$/.test(scriptSrc), scriptSrc)
        t.pause()
      },

      testJSONPCacheBustingDisabled: function(t) {
        $.ajax({
          url: 'jsonp?callback=?',
          cache: true,
          success: t.reg.resumeHandler('success')
        })

        var scriptSrc = $('head script:last-child').attr('src')
        t.assert(/^jsonp\?callback=Zepto\d+$/.test(scriptSrc), scriptSrc)
        t.pause()
      },

      testBrowserCaching: function(t) {
        t.pause()
        resumeOnAjaxError(t)
        $.ajax({
          url: 'cached',
          cache: true,
          success: function(firstResponse){
            $.ajax({
              url: 'cached',
              cache: true,
              success: t.reg.resumeHandler('success', function(secondResponse){
                t.assertEqual(secondResponse, firstResponse)
              })
            })
          }
        })
      },

      testAjaxLoad: function(t) {
        t.pause()
        var testEl = $('#ajax_load')
        var el = testEl.load(
          'fixtures/ajax_load_simple.html',
          t.reg.resumeHandler('success', function(response, status, xhr){
            t.assertIdentical(testEl, this)
            t.assertEqual("simple ajax load\n", response.replace(/\r\n|\r/,"\n"))
            t.assertEqual('simple ajax load', testEl.html().trim())
            t.assertEqual('success', status)
            t.assertIn('abort', xhr)
            t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())
          })
        )
        t.assertIdentical(testEl, el)
      },

      testAjaxLoadWithSelector: function(t) {
        t.pause()
        var testEl = $('#ajax_load')
        testEl.load(
          'fixtures/ajax_load_selector.html #ajax_load_test_div',
          t.reg.resumeHandler('success', function(){
            t.assertEqual(
              '<div id="ajax_load_test_div">ajax load with selector</div>',
              testEl.html().trim()
            )
          })
        )
      },

      testAjaxLoadWithJavaScript: function (t) {
        var testEl = $('#ajax_load')
        t.pause()
        window.testValue = 0
        testEl.load('fixtures/ajax_load_selector_javascript.html', function(){
          deferredResume(t, function(){
            this.assertEqual(window.testValue, 1)
            delete window.testValue
          })
        })
      },

      testAjaxLoadWithSelectorAndJavaScript: function (t) {
        var testEl = $('#ajax_load')
        t.pause()
        window.testValue = 0
        testEl.load('fixtures/ajax_load_selector_javascript.html #ajax_load_test_div', function() {
          deferredResume(t, function(){
            this.assertEqual(window.testValue, 0)
            delete window.testValue
          })
        })
      },

      testAjaxWithContext: function(t) {
        t.pause()
        var body = $('body')
        $.ajax({
          url:        'fixtures/ajax_load_simple.html',
          context:    body,
          beforeSend: t.reg.handler('beforeSend'),
          success:    t.reg.handler('success'),
          complete:   t.reg.resumeHandler('complete', function(){
            t.assertIdentical(body, this)
            t.assertIdentical(body, t.reg.context('beforeSend'))
            t.assertIdentical(body, t.reg.context('success'))
            t.assertIdentical(document.body, t.reg.target('ajaxBeforeSend'))
            t.assertIdentical(document.body, t.reg.target('ajaxSuccess'))
          })
        })
      },

      testAjaxWithContextPlainObject: function(t) {
        t.pause()
        var obj = {}
        $.ajax({
          url:        'fixtures/ajax_load_simple.html',
          context:    obj,
          beforeSend: t.reg.handler('beforeSend'),
          success:    t.reg.handler('success'),
          complete:   t.reg.resumeHandler('complete', function(){
            t.assertIdentical(obj, this)
            t.assertIdentical(obj, t.reg.context('beforeSend'))
            t.assertIdentical(obj, t.reg.context('success'))
            t.assertUndefined(t.reg.target('ajaxBeforeSend'))
            t.assertUndefined(t.reg.target('ajaxSuccess'))
          })
        })
      },

      testAjaxLoadJavaScript: function (t) {
        t.pause()
        window.testValue = 0
        var xhr = $.ajax({
          url:'fixtures/ajax_load_javascript.js',
          success: t.reg.resumeHandler('success', function(response){
            // check that the javascript has loaded and executed.
            t.assertEqual(window.testValue, 1)
            delete window.testValue
          })
        })
      },

      testAjaxBasicAuth: function(t) {
        t.pause()
        resumeOnAjaxError(t)
        $.ajax({
          url: 'auth?realm=zepto',
          username: 'zepto',
          password: 'doge',
          success: t.reg.resumeHandler('success')
        })
      }
    })

    var OriginalXHR = $.ajaxSettings.xhr

    function MockXHR() {
      this.headers = []
      this.responseHeaders = {}
      MockXHR.last = this
    }
    MockXHR.prototype = {
      open: function(method, url, async) {
        this.method = method
        this.url = url
        this.async = async
      },
      setRequestHeader: function(name, value) {
        if (!this.method) throw "setRequestHeader() called before open()"
        this.headers.push({ name: name, value: value })
      },
      getResponseHeader: function(name) {
        return this.responseHeaders[name]
      },
      overrideMimeType: function(type) {
        this.responseHeaders['content-type'] = type
      },
      withCredentials: false,
      send: function(data) {
        this.data = data
      },
      abort: function() {
        this.aborted = true
      },
      ready: function(readyState, status, responseText, headers) {
        this.readyState = readyState
        this.status = status
        this.responseText = responseText
        $.extend(this.responseHeaders, headers)
        this.onreadystatechange()
      },
      onreadystatechange: function() {}
    }

    function matchHeader(name, value) {
      return function(header) {
        return header.name == name && (!value || header.value == value)
      }
    }

    Evidence('ZeptoAjaxTest2', {
      setUp: function() {
        $.ajaxSettings.xhr = function(){ return new MockXHR }
      },

      tearDown: function() {
        $.ajaxSettings.xhr = OriginalXHR
        $(document).off()
        $.active = 0
      },

      testTypeDefaultsToGET: function(t) {
        $.ajax({
          url: '/foo',
          beforeSend: function(xhr, settings) {
            t.assertFalse(settings.crossDomain)
          }
        })
        t.assertEqual('GET', MockXHR.last.method)
      },

      testURLDefaultsToWindowLocation: function(t) {
        $.ajax()
        t.assertEqual(window.location, MockXHR.last.url)
      },

      testCrossDomainCrossOrigin: function(t) {
        $.ajax({
          url: 'http://example.com/foo',
          beforeSend: function(xhr, settings) {
            t.assertTrue(settings.crossDomain)
          }
        })
      },

      testCrossDomainSameOrigin: function(t) {
        $.ajax({
          url: window.location.href,
          beforeSend: function(xhr, settings) {
            t.assertFalse(settings.crossDomain)
          }
        })
      },

      testCrossDomainLeadingSpace: function(t) {
        $.ajax({
          url: ' http://example.com/foo',
          beforeSend: function(xhr, settings) {
            t.assertTrue(settings.crossDomain)
          }
        })
      },

      testCrossDomainTrippleSlash: function(t) {
        $.ajax({
          url: 'http:///example.com/foo',
          beforeSend: function(xhr, settings) {
            t.assertTrue(settings.crossDomain)
          }
        })
      },

      testCrossDomainWithQuery: function(t) {
        $.ajax({
          url: window.location.href + "?foo=bar",
          beforeSend: function(xhr, settings) {
            t.assertFalse(settings.crossDomain)
          }
        })
      },

      testCrossDomainDifferentScheme: function(t) {
        $.ajax({
          url: "foo://" + window.location.host,
          beforeSend: function(xhr, settings) {
            t.assertTrue(settings.crossDomain)
          }
        })
      },

      testCrossDomainPeriodInScheme: function(t) {
        $.ajax({
          url: "foo.bar://example.com/foo",
          beforeSend: function(xhr, settings) {
            t.assertTrue(settings.crossDomain)
          }
        })
      },

      testDefaultAcceptHeader: function(t) {
        $.ajax()
        t.assert(MockXHR.last.headers.some(matchHeader('Accept', '*/*')))
      },

      testDataTypeOptionSetsAcceptHeader: function(t) {
        $.ajax({ dataType: 'json' })
        t.assert(MockXHR.last.headers.some(matchHeader('Accept', 'application/json')))
        // verifies overrideMimeType:
        t.assertEqual('application/json', MockXHR.last.getResponseHeader('content-type'))

        $.ajax({ dataType: 'script' })
        //check that the head matches all of those required for loading scripts.
        t.assert(MockXHR.last.headers.some(matchHeader('Accept', 'text/javascript, application/javascript, application/x-javascript')))
      },

      testMimeTypeOptionOverride: function(t) {
        $.ajax({ mimeType: 'text/plain' })
        t.assertEqual('text/plain', MockXHR.last.getResponseHeader('content-type'))
      },

      testContentTypeOptionSetsContentTypeHeader: function(t) {
        $.ajax()
        t.assert(!MockXHR.last.headers.some(matchHeader('Content-Type')))

        $.ajax({ contentType: 'text/html' })
        t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'text/html')))

        $.ajax({ type: 'POST', data: [], contentType: 'application/x-foo' })
        t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/x-foo')))
      },

      testHeadersOptionCanSetContentType: function(t) {
        $.ajax({ type: 'POST', data: [], headers: { 'Content-Type': 'application/hal+json' }})
        t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/hal+json')))
      },

      testContentTypeDefaultsToUrlEncoded: function(t) {
        $.ajax({ type: 'GET', data: 'x' })
        t.refute(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/x-www-form-urlencoded')))
        $.ajax({ type: 'POST', data: 'x' })
        t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/x-www-form-urlencoded')))
      },

      testDefaultContentTypeDisabled: function(t) {
        $.ajax({ type: 'POST', data: {a:1}, contentType: false })
        t.refute(MockXHR.last.headers.some(matchHeader('Content-Type')))
      },

      testCustomHeader: function(t) {
        $.ajax({ headers: {'X-Awesome': 'true'} })
        t.assert(MockXHR.last.headers.some(matchHeader('X-Requested-With', 'XMLHttpRequest')))
        t.assert(MockXHR.last.headers.some(matchHeader('X-Awesome', 'true')))
      },

      testXhrFieldsOptionSetsWithCredentialsProperty: function(t) {
        var xhr = $.ajax({
          url: 'http://example.com/foo',
          xhrFields: { withCredentials: true }
        })
        t.assert(xhr.withCredentials)
      },

      testScriptDataTypeCacheBustByDefault: function(t) {
        $.ajax({ url: '/', dataType: 'script' })
        var xhr = MockXHR.last
        t.assert(/^\/\?_=[\d]{13}$/.test(xhr.url), xhr.url)
      },

      testScriptDataTypeCacheBustDisable: function(t) {
        $.ajax({ url: '/', dataType: 'script', cache: true })
        var xhr = MockXHR.last
        t.assertEqual('/', xhr.url)
      },

      testJSONdataType: function(t) {
        var result = {}
        $.ajax({ dataType: 'json', success: function(json) {result = json } })
        MockXHR.last.ready(4, 200, '{"hello":"world"}')
        t.assertEqual("world", result.hello)
      },

      testJSONcontentType: function(t) {
        var result = {}
        $.ajax({ success: function(json) {result = json } })
        MockXHR.last.ready(4, 200, '{"hello":"world"}', {'content-type': 'application/json'})
        t.assertEqual("world", result.hello)
      },

      testJSONResponseBodiesAreNotParsedWhenDataTypeOptionIsJSONButResponseIsEmptyString: function(t) {
        var result, success = false
        $.ajax({ dataType: 'json', success: function(json) {result = json; success = true } })
        MockXHR.last.ready(4, 200, '')
        t.assert(success)
        t.assertNull(result)
      },

      testJSONResponseBodiesAreNotParsedWhenDataTypeOptionIsJSONButResponseIsSingleSpace: function(t) {
        var result, success = false
        $.ajax({ dataType: 'json', success: function(json) {result = json; success = true } })
        MockXHR.last.ready(4, 200, ' ')
        t.assert(success)
        t.assertNull(result)
      },

      testDataIsNotSentAsBodyForGetRequests: function(t) {
        $.ajax({ type: 'GET', data: {a:'b'} })
        t.assertNull(MockXHR.last.data)
      },

      testDataOptionIsConvertedToSerializedForm: function(t) {
        $.ajax({
          type: 'POST',
          data: {hello: 'world', array: [1,2,3], object: { prop1: 'val', prop2: 2 } }
        })
        var data = decodeURIComponent(MockXHR.last.data)
        t.assertEqual('hello=world&array[]=1&array[]=2&array[]=3&object[prop1]=val&object[prop2]=2', data)
      },

      testDataOptionIsConvertedToSerializedTraditionalForm: function(t) {
        $.ajax({
          type: 'POST',
          data: {hello: 'world', array: [1,2,3], object: { prop1: 'val', prop2: 2 } },
          traditional: true
        })
        var data = decodeURIComponent(MockXHR.last.data)
        t.assertEqual('hello=world&array=1&array=2&array=3&object=[object+Object]', data)
      },

      testQueryParamsTraditional: function(t) {
        $.ajax({
          url: '/',
          data: {hello: 'world', array: [1,2,3], object: { prop1: 'val', prop2: 2 } },
          traditional: true
        })
        var url = decodeURIComponent(MockXHR.last.url)
        t.assertEqual('/?hello=world&array=1&array=2&array=3&object=[object+Object]', url)
      },

      testProcessDataDisabled: function(t) {
        var data = { country: 'Ecuador' }
        $.ajax({
          data: data,
          processData: false,
          type: "POST"
        })
        t.assertIdentical(data, MockXHR.last.data)
      },

      testDataIsAppendedToGETURL: function(t) {
        $.ajax({ url:'test.html', data:'foo=bar' })
        t.assertEqual('test.html?foo=bar', MockXHR.last.url)

        $.ajax({ url:'test.html', data:'?foo=bar' })
        t.assertEqual('test.html?foo=bar', MockXHR.last.url)

        $.ajax({ url:'test.html?', data:'foo=bar' })
        t.assertEqual('test.html?foo=bar', MockXHR.last.url)

        $.ajax({ url:'test.html?baz', data:'foo=bar' })
        t.assertEqual('test.html?baz&foo=bar', MockXHR.last.url)

        $.ajax({ url:'test.html?bar=baz', data:'foo=bar' })
        t.assertEqual('test.html?bar=baz&foo=bar', MockXHR.last.url)

        $.ajax({ url:'test.html', data:{foo:'bar'} })
        t.assertEqual('test.html?foo=bar', MockXHR.last.url)
      },

      testDataIsAppendedToGETURLWithHashStripped: function(t) {
        $.ajax({ url:'test.html#?ignore=me', data:'foo=bar' })
        t.assertEqual('test.html?foo=bar', MockXHR.last.url)

        $.ajax({ url:'test.html?a=b#?ignore=me', data:'foo=bar' })
        t.assertEqual('test.html?a=b&foo=bar', MockXHR.last.url)
      },

      testScriptResponseIsEvald: function(t) {
        var result
        $.ajax({ success: function(text){ result = text } })
        MockXHR.last.ready(4, 200, 'this.testValue = 42', {'content-type': 'application/javascript'})
        t.assertEqual('this.testValue = 42', result)
        t.assertIdentical(42, window.testValue)
        delete window.testValue
      },

      testErrorCallback: function(t) {
        var successFired = false, xhr, status
        $.ajax({
          success: function() { successFired = true },
          error: function(x, s) { xhr = x, status = s }
        })

        MockXHR.last.ready(4, 500, '500 Internal Server Error')
        t.assert(!successFired)
        t.assertEqual(MockXHR.last, xhr)
        t.assertEqual('error', status)
      },

      testErrorCallbackWithInvalidJSON: function(t) {
        var successFired = false, xhr, status, exception
        $.ajax({
          dataType: 'json',
          succes: function() { successFired = true },
          error: function(x, s, e) { xhr = x, status = s, exception = e }
        })

        MockXHR.last.ready(4, 200, '{invalid')
        t.assert(!successFired)
        t.assertEqual(MockXHR.last, xhr)
        t.assertEqual('parsererror', status)
        t.assert(exception.toString().match(/SyntaxError/))
      },

      test201ResponseIsSuccess: function(t) {
        var successFired, errorFired
        $.ajax({
          success: function() { successFired = true },
          error: function() { errorFired = true }
        })

        MockXHR.last.ready(4, 201, 'Created')
        t.assert(successFired)
        t.refute(errorFired)
      },

      test304ResponseIsSuccess: function(t) {
        var successFired, errorFired
        $.ajax({
          success: function() { successFired = true },
          error: function() { errorFired = true }
        })

        MockXHR.last.ready(4, 304, 'Not Modified')
        t.assert(successFired)
        t.refute(errorFired)
      },
      testXHRParameterInSuccessCallback: function(t) {
        var body, status, xhr
        $.ajax({
          success: function(b, s, x) { body = b, status = s, xhr = x }
        })

        MockXHR.last.ready(4, 200, 'Hello')
        t.assertEqual('Hello', body)
        t.assertEqual('success', status)
        t.assertEqual(MockXHR.last, xhr)

        body = status = xhr = null
        $.ajax({
          dataType: 'json',
          success: function(b, s, x) { body = b, status = s, xhr = x }
        })

        MockXHR.last.ready(4, 200, '{"message":"Hello"}')
        t.assertEqual('Hello', body.message)
        t.assertEqual('success', status)
        t.assertEqual(MockXHR.last, xhr)
      },

      testBeforeSendCanChangeUrl: function(t) {
        var xhr = $.ajax({
          url: 'one',
          beforeSend: function(x, s) {
            s.url = 'two'
          }
        })
        t.assertEqual('two', xhr.url)
      },

      testBeforeSendCanChangeMethod: function(t) {
        var xhr = $.ajax({
          type: 'POST',
          beforeSend: function(x, s) {
            s.type = 'PUT'
          }
        })
        t.assertEqual('PUT', xhr.method)
      },

      testBeforeSendCanAccessSerializedPostData: function(t) {
        var xhr = $.ajax({
          type: 'POST',
          data: { a:'b' },
          beforeSend: function(x, s) {
            s.data = s.data.toUpperCase()
          }
        })
        t.assertEqual('A=B', xhr.data)
      },

      testBeforeSendCannotAccessRawQueryParams: function(t) {
        var url, data
        $.ajax({
          url: '/',
          type: 'GET',
          data: { a:'b' },
          beforeSend: function(x, s) {
            url = s.url
            data = s.data
          }
        })
        t.assertEqual('/?a=b', url)
        t.assertUndefined(data)
      },

      testBeforeSendCannotChangeOrAddHeadersViaObject: function(t) {
        var xhr = $.ajax({
          headers: { a:'b', c:'d' },
          beforeSend: function(x, s) {
            s.headers['a'] = 'B'
            s.headers['e'] = 'f'
          }
        })
        t.assert(xhr.headers.some(matchHeader('a', 'b')))
        t.assert(xhr.headers.some(matchHeader('c', 'd')))
        t.refute(xhr.headers.some(matchHeader('e', 'f')))
      },

      testBeforeSendCanChangeAndAddHeadersViaXhr: function(t) {
        var xhr = $.ajax({
          headers: { a:'b', c:'d' },
          beforeSend: function(x, s) {
            x.setRequestHeader('a', 'B')
            x.setRequestHeader('e', 'f')
          }
        })
        t.assert(xhr.headers.some(matchHeader('a', 'B')))
        t.assert(xhr.headers.some(matchHeader('c', 'd')))
        t.assert(xhr.headers.some(matchHeader('e', 'f')))
      },

      testBeforeSendAbortCallback: function(t) {
        var xhr, settings
        $.ajax({
          beforeSend: function(x, s) {
            settings = s, xhr = x
          }
        })

        t.assertEqual(MockXHR.last, xhr)
        t.assertEqual('GET', settings.type)
      },

      testBeforeSendAbort: function(t) {
        var xhr
        $.ajax({ beforeSend: function(x) { xhr = x; return false } })

        t.assert(xhr.aborted)
      },

      testGlobalBeforeSendAbort: function(t) {
        $(document).on('ajaxBeforeSend', false)
        var xhr = $.ajax()
        t.assert(xhr.aborted)
      },

      testGlobalAjaxSendCantAbort: function(t) {
        var xhr
        $(document).on('ajaxSend', function(e, x) { xhr = x; return false })
        t.assert($.ajax())
        t.assert(!xhr.aborted)
      },

      testCompleteCallback: function(t) {
        var status, xhr
        $.ajax({ complete: function(x, s) { status = s, xhr = x } })

        MockXHR.last.ready(4, 200, 'OK')
        t.assertEqual(MockXHR.last, xhr)
        t.assertEqual('success', status)
      },

      testCallbackOrder: function(t) {
        var order = []
        $.ajax({
          beforeSend: function() { order.push('beforeSend') },
          success: function() { order.push('success') },
          complete: function() { order.push('complete') }
        })

        MockXHR.last.ready(4, 200, 'OK')
        t.assertEqual('beforeSend,success,complete', order.join(','))
      },

      testGlobalCallbacks: function(t) {
        var fired = []
        $(document).on('ajaxStart ajaxBeforeSend ajaxSend ajaxSuccess ajaxError ajaxComplete ajaxStop', function(e) {
          fired.push(e.type)
        })

        $.ajax({
          beforeSend: function() { fired.push('beforeSend') },
          success:    function() { fired.push('success') },
          error:      function() { fired.push('error') },
          complete:   function() { fired.push('complete') }
        })
        t.assertEqual('ajaxStart beforeSend ajaxBeforeSend ajaxSend', fired.join(' '))

        fired = []
        MockXHR.last.ready(4, 200, 'OK')
        t.assertEqual('success ajaxSuccess complete ajaxComplete ajaxStop', fired.join(' '))
      },

      testGlobalCallbacksOff: function(t) {
        var fired = []
        $(document).on('ajaxStart ajaxBeforeSend ajaxSend ajaxSuccess ajaxError ajaxComplete ajaxStop', function(e) {
          fired.push(e.type)
        })

        $.ajax({
          global:     false,
          beforeSend: function() { fired.push('beforeSend') },
          success:    function() { fired.push('success') },
          error:      function() { fired.push('error') },
          complete:   function() { fired.push('complete') }
        })
        t.assertEqual('beforeSend', fired.join(' '))

        fired = []
        MockXHR.last.ready(4, 200, 'OK')
        t.assertEqual('success complete', fired.join(' '))
      },

      testTimeout: function(t) {
        var successFired = false, xhr, status, globalStatus
        t.pause()
        $(document).on('ajaxError', function (e, x, o, s) {
          globalStatus = s
        })

        $.ajax({
          timeout: 30,
          success: function() { successFired = true },
          error: function(x, s) { xhr = x, status = s }
        })

        setTimeout(function(){
          t.assertFalse(successFired)
          t.assertUndefined(status)
        }, 20)

        setTimeout(function(){
          t.resume(function(){
            t.assertFalse(successFired)
            t.assertTrue(xhr.aborted)
            t.assertEqual('timeout', status)
            t.assertEqual('timeout', globalStatus)
          })
        }, 40)
      },

      testAbort: function(t) {
        var successFired = false, xhr, status, globalStatus
        t.pause()
        $(document).on('ajaxError', function (e, x, o, s) {
          globalStatus = s
        })

        $.ajax({
          success: function() { successFired = true },
          error: function(x, s) { xhr = x, status = s }
        })
        MockXHR.last.abort()
        MockXHR.last.ready(4, 0, 'Aborted')

        setTimeout(function(){
          t.resume(function(){
            t.assertFalse(successFired)
            t.assertTrue(xhr.aborted)
            t.assertEqual('abort', status)
            t.assertEqual('abort', globalStatus)
          })
        }, 20)
      },

      testAsyncDefaultsToTrue: function(t) {
        $.ajax({ url: '/foo' })
        t.assertTrue(MockXHR.last.async)
      },

      testAsyncFalse: function(t) {
        $.ajax({ url: '/foo', async: false })
        t.assertFalse(MockXHR.last.async)
      }
    })

    Evidence('ZeptoAjaxHelperMethodsTest', {

      testParamMethod: function(t) {
        var result = $.param({ libs: ['jQuery', 'script.aculo.us', 'Prototype', 'Dojo'] })
        result = decodeURIComponent(result)
        t.assertEqual(result, "libs[]=jQuery&libs[]=script.aculo.us&libs[]=Prototype&libs[]=Dojo")

        result = $.param({ jquery: 'Javascript', rails: 'Ruby', django: 'Python' })
        result = decodeURIComponent(result)
        t.assertEqual(result, "jquery=Javascript&rails=Ruby&django=Python")

        result = $.param({
          title: "Some Countries",
          list: ['Ecuador', 'Austria', 'England'],
          capitals: { ecuador: 'Quito', austria: 'Vienna', GB: { england: 'London', scotland: 'Edinburgh'} }
        })
        result = decodeURIComponent(result)
        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")
      },

      testParamNullValues: function(t) {
        t.assertEqual("x=&a[b]=&a[c]=",
          decodeURIComponent($.param({ x: null, a: { b: null, c: undefined }})))
        t.assertEqual("x=",
          decodeURIComponent($.param([{ name: "x", value: null }])))
      },

      testParamFunctionValues: function(t) {
        t.assertEqual("x=&a[b]=B",
          decodeURIComponent($.param({ x: function(){}, a: { b: function(){ return "B" }}})))
        t.assertEqual("x=&a[b]=B",
          decodeURIComponent($.param([{ name: "x", value: null }, { name: "a[b]", value: function(){ return "B" }}])))
      },

      testParamEscaping: function(t) {
        var result = $.param({ 'equation[1]': 'bananas+peaches=smoothie' })
        t.assertEqual("equation%5B1%5D=bananas%2Bpeaches%3Dsmoothie", result)
      },

      testParamSpaces: function(t) {
        var result = $.param({ "foo bar": "baz kuux" })
        t.assertEqual("foo+bar=baz+kuux", result)
      },

      testParamComplex: function(t) {
        var data = {
          a: ['b', 'c', { d:'e', f:['g','h'] }]
        }
        var result = $.param(data)
        result = decodeURIComponent(result)
        t.assertEqual("a[]=b&a[]=c&a[2][d]=e&a[2][f][]=g&a[2][f][]=h", result)
      },

      testParamComplexIssue850: function(t) {
        var data = {
          $push: { _:[ { name: 'bob', members:['aaa'] } ] }
        }
        var result = $.param(data)
        result = decodeURIComponent(result)
        t.assertEqual("$push[_][0][name]=bob&$push[_][0][members][]=aaa", result)
      },

      testParamComplexNested: function(t) {
        var data = {
          x: [
            [1, { attr1: 2 } ],
            3,
            { attr1: 4 },
            { attr1: 5, attr2: [ 6 ] },
            [ 7, [8, 9] ],
            { attr1: { attr2: [ [ 10 ] ] } }
          ]
        }
        var result = $.param(data)
        result = decodeURIComponent(result)
        t.assertEqual(
          [ "x[0][]=1"
          , "x[0][1][attr1]=2"
          , "x[]=3"
          , "x[2][attr1]=4"
          , "x[3][attr1]=5"
          , "x[3][attr2][]=6"
          , "x[4][]=7"
          , "x[4][1][]=8"
          , "x[4][1][]=9"
          , "x[5][attr1][attr2][0][]=10"
          ].join('&'), result)
      },

      testParamShallow: function(t) {
        var data = {
          libs: ['jQuery', 'Prototype', 'Dojo'],
          nested: { will: 'be ignored' }
        }
        var result = $.param(data, true)
        result = decodeURIComponent(result)
        t.assertEqual("libs=jQuery&libs=Prototype&libs=Dojo&nested=[object+Object]", result)
      },

      testParamArray: function(t) {
        var data = [
          {name:'country', value:'Ecuador'},
          {name:'capital', value:'Quito'}
        ]
        var result = $.param(data)
        t.assertEqual(result, "country=Ecuador&capital=Quito")
      }

    })
  })()
  </script>
</body>
</html>


================================================
FILE: test/ajax_deferred.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <link rel="stylesheet" href="test.css">
  <title>Zepto Ajax deferred</title>
  <script src="../vendor/evidence.js"></script>
  <script src="evidence_runner.js"></script>
  <script>
    // avoid caching
    (function(){
      function load(scripts){
        scripts.split(' ').forEach(function(script){
          document.write('<script src="../src/'+script+'.js?'+(+new Date)+'"></scr'+'ipt>')
        })
      }

      load('zepto event ajax ie callbacks deferred')
    })()
  </script>
</head>
<body>
  <h1>Zepto Ajax deferred</h1>
  <p id="results">
    Running… see browser console for results
  </p>
  <div id="fixtures">
  </div>

  <script>
  (function(){

    function toArray(list) {
      if ($.type(list) == "string") return list.split(/(?:\s*,\s*|\s+)/)
      else return list
    }

    Evidence.Assertions.assertEqualList = function(expected, actual, message) {
      var expectedList = toArray(expected),
          actualList   = toArray(actual)

      this._assertExpression(
        expectedList.join(' ') == actualList.join(' '),
        message || "Lists don't match.",
        'Expected %o, got %o.', expectedList, actualList
      )
    }

    var OriginalXHR = $.ajaxSettings.xhr

    function MockXHR() {
      this.requestHeaders = {}
      this.responseHeaders = {}
      MockXHR.last = this
    }
    MockXHR.prototype = {
      open: function(method, url) {
        this.method = method
        this.url = url
      },
      setRequestHeader: function(name, value) {
        this.requestHeaders[name.toLowerCase()] = value
      },
      getResponseHeader: function(name) {
        return this.responseHeaders[name]
      },
      send: function(data) {
        this.data = data
      },
      abort: function() {
        this.aborted = true
      },
      ready: function(readyState, status, responseText, headers) {
        this.readyState = readyState
        this.status = status
        this.responseText = responseText
        $.extend(this.responseHeaders, headers)
        this.onreadystatechange()
      },
      onreadystatechange: function() {}
    }

    Evidence('ZeptoAjaxDeferred', {
      setUp: function() {
        $.ajaxSettings.xhr = function(){ return new MockXHR }
      },

      tearDown: function() {
        $.ajaxSettings.xhr = OriginalXHR
        $(document).off()
        $.active = 0

        for (var key in window)
          if (/^Zepto\d+$/.test(key) && window[key] === undefined)
            delete window[key]
      },

      testDone: function(t) {
        var log = []

        var xhr = $.ajax({
          success: function() { log.push('success') }
        })
          .done(function(response, status, gotXhr){
            t.assertEqual('hello', response)
            t.assertEqual('success', status)
            t.assertIdentical(xhr, gotXhr)
            log.push('done1')
          })
          .fail(function(){ log.push('fail') })
          .always(function(){ log.push('always') })
          .done(function(){ log.push('done2') })

        xhr.ready(3, 0)
        t.assertEqual(0, log.length)

        xhr.ready(4, 200, 'hello')
        t.assertEqualList('success done1 always done2', log)

        xhr.done(function(){ log.push('done3') })
        t.assertEqualList('success done1 always done2 done3', log)
      },

      testFail: function(t) {
        var log = []

        var xhr = $.ajax({
          error: function() { log.push('error') }
        })
          .done(function(){ log.push('done') })
          .fail(function(gotXhr, status, error){
            t.assertIdentical(xhr, gotXhr)
            t.assertEqual('error', status)
            log.push('fail1')
          })
          .always(function(){ log.push('always') })
          .fail(function(){ log.push('fail2') })

        xhr.ready(3, 0)
        t.assertEqual(0, log.length)

        xhr.ready(4, 404)
        t.assertEqualList('error fail1 always fail2', log)

        xhr.fail(function(){ log.push('fail3') })
        t.assertEqualList('error fail1 always fail2 fail3', log)
      },

      testAbortInBeforeSend: function(t) {
        var log = []

        var xhr = $.ajax({
          beforeSend: function() { return false }
        })

        xhr.done(function(){ log.push('done') })
          .fail(function(gotXhr, status, error){
            t.assertIdentical(xhr, gotXhr)
            t.assertEqual('abort', status)
            log.push('fail1')
          })

        t.assertEqualList('fail1', log)
      },

      testJSONP: function(t) {
        var log = []
        t.pause()

        var xhr = $.ajax({
          url: 'jsonp',
          dataType: 'jsonp',
          success: function() { log.push('success') }
        })
          .done(function(){ log.push('done1') })
          .always(function(){
            setTimeout(function(){
              t.resume(function(){
                t.assertEqualList('success done1', log)
                xhr.done(function(){ log.push('done2') })
                t.assertEqualList('success done1 done2', log)
              })
            }, 10)
          })

        t.assertEqual(0, log.length)
      },

      testJSONPAbortInBeforeSend: function(t) {
        var log = []

        var xhr = $.ajax({
          url: 'jsonp',
          dataType: 'jsonp',
          beforeSend: function() { return false }
        })

        xhr.done(function(){ log.push('done') })
          .fail(function(gotXhr, status, error){
            t.assertIdentical(xhr, gotXhr)
            t.assertEqual('abort', status)
            log.push('fail1')
          })

        t.assertEqualList('fail1', log)
      }

    })
  })()
  </script>
</body>
</html>


================================================
FILE: test/callbacks.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <link rel="stylesheet" href="test.css">
  <title>Zepto Callbacks unit tests</title>
  <script src="../vendor/evidence.js"></script>
  <script src="evidence_runner.js"></script>
  <script>
    // avoid caching
    (function(){
      function load(scripts){
        scripts.split(' ').forEach(function(script){
          document.write('<script src="../src/'+script+'.js?'+(+new Date)+'"></scr'+'ipt>')
        })
      }

      load('zepto callbacks')
    })()
  </script>
</head>
<body>
  <h1>Zepto Callbacks unit tests</h1>
  <p id="results">
    Running… see browser console for results
  </p>

  <script>
  (function(){
    var output = "", cb
    function a() { output += "A" }
    function b() { output += "B" }
    function c() { output += "C" }
    function str(str) { output += str }

    Evidence('ZeptoCallbacksTest', {

      testOptionsAreCopied: function(t) {
        var options = {"unique": true},
            cb = $.Callbacks(options),
            count = 0,
            fn = function() {
              t.assertTrue(!(count++), "called once")
            }
        options["unique"] = false
        cb.add(fn, fn)
        cb.fire()
      },

      testFireWithOptionsAreCopied: function(t) {
        var cb = $.Callbacks({memory:1}),
            args = ["hello"]

        cb.fireWith(null, args)
        args[0] = "world"

        cb.add(function(hello) {
          t.assertEqual("hello", hello, "arguments are copied internally")
        })
      },

      testRemoveDeletesAllInstances: function(t) {
        var cb = $.Callbacks()
        function fn() {
          t.fail("function wasn't removed")
        }
        cb.add( fn, fn, function() {
          t.assertTrue(true, "end of test")
        }).remove(fn).fire()
      },

      testCallbacksHas: function(t) {
        var cb = $.Callbacks()
        cb.add(a, b, c)
        t.assertTrue(cb.has(), "No arguments to .has() returns whether callback function(s) are attached or not")
        t.assertTrue(cb.has(a), "Check if a specific callback function is in the Callbacks list" )

        cb.remove(b)
        t.assertFalse(cb.has(b), "Remove a specific callback function and make sure its no longer there" )
        t.assertTrue(cb.has(a), "Remove a specific callback function and make sure other callback function is still there" )

        cb.empty()
        t.assertFalse(cb.has(), "Empty list and make sure there are no callback function(s)" )
        t.assertFalse(cb.has(a), "Check for a specific function in an empty() list" )

        cb.add(a, b, function(){
          t.assertTrue(cb.has(), "Check if list has callback function(s) from within a callback function" )
          t.assertTrue(cb.has(a), "Check if list has a specific callback from within a callback function" )
        }).fire()

        t.assertTrue(cb.has(), "Callbacks list has callback function(s) after firing" )

        cb.disable()
        t.assertFalse(cb.has(), "disabled() list has no callback functions (returns false)" )
        t.assertFalse(cb.has(a), "Check for a specific function in a disabled() list" )

        cb = $.Callbacks({unique:1})
        cb.add(a)
        cb.add(a)
        t.assertTrue(cb.has(), "Check if unique list has callback function(s) attached" )
        cb.lock()
        t.assertFalse(cb.has(), "locked() list is empty and returns false" )
      },

      testAddStringNoCrash: function(t) {
        $.Callbacks().add("hello world")
        t.assertTrue(true, "no crash adding string" )
      },

      testUniqueAddIdenticalFn: function(t) {
        output = "X"
        $.Callbacks({unique:1}).add(a, function() { output += "A" }).fire()
        t.assertEqual("XAA", output, "Unique can add different, identical definitions of same function")
      },

      testUniqueAddSameFn: function(t) {
        output = "X"
        $.Callbacks({unique:1}).add(a, a).fire()
        t.assertEqual("XA", output, "Unique can not add multiple functions with the same reference")
      },

      testUniqueAddSameFnMultiRef: function(t) {
        var x = a
        output = "X"
        $.Callbacks({unique:1}).add(a, x).fire()
        t.assertEqual("XA", output, "Unique can not add multiple references to the same function")
      }

    })

    var configs = {
      'Undefined': undefined,
      'Null': null,
      'Once': {once:1},
      'Memory': {memory:1},
      'Unique': {unique:1},
      'StopOnFalse': {stopOnFalse:1},
      'OnceMemory': {once:1, memory:1},
      'OnceUnique': {once:1, unique:1},
      'OnceStopOnFalse': {once:1, stopOnFalse:1},
      'MemoryUnique': {memory:1, unique:1},
      'MemoryStopOnFalse': {memory:1, stopOnFalse:1},
      'UniqueStopOnFalse': {unique:1, stopOnFalse:1}
    }
    var ordering = {
      "Undefined":         "XABC   X     XABCABCC  X  XBB X   XABA  X   XX",
      "Null":              "XABC   X     XABCABCC  X  XBB X   XABA  X   XX",
      "Once":              "XABC   X     X         X  X   X   XABA  X   XX",
      "Memory":            "XABC   XABC  XABCABCCC XA XBB XB  XABA  XC  XX",
      "Unique":            "XABC   X     XABCA     X  XB  X   XAB   X   X",
      "StopOnFalse":       "XABC   X     XABCABCC  X  XBB X   XA    X   XX",
      "OnceMemory":        "XABC   XABC  X         XA X   XA  XABA  XC  XX",
      "OnceUnique":        "XABC   X     X         X  X   X   XAB   X   X",
      "OnceStopOnFalse":   "XABC   X     X         X  X   X   XA    X   XX",
      "MemoryUnique":      "XABC   XA    XABCA     X  XB  X   XAB   XC  X",
      "MemoryStopOnFalse": "XABC   XABC  XABCABCCC XA XBB XB  XA    X   XX",
      "UniqueStopOnFalse": "XABC   X     XABCA     X  XB  X   XA    X   X"
    }

    $.each(configs, function(name, config) {
      var results = ordering[name].split(/\s+/)

      Evidence("ZeptoCallbacksTest#" + name, {

        testBindAndFire: function(t) {
          output = "X", cb = $.Callbacks(config).add(str).fire("A")
          t.assertEqual("XA", output, "Basic binding and firing")
          t.assertTrue(cb.fired(), ".fired() detects firing")
          output = "X"
          cb.disable().add(str)
          t.assertEqual( "X", output, "Adding a callback after disabling" )
          cb.fire("A")
          t.assertEqual( "X", output, "Firing after disabling" )
        },

        testNoEmptyWhileFiring: function(t) {
          var cb = $.Callbacks(config)
          cb.add(cb.empty, function() { t.fail("not emptied") }).fire()
        },

        testNoDisablingWhileFiring: function(t) {
          var cb = $.Callbacks(config)
          cb.add(cb.disable, function() { t.fail("not disabled") }).fire()
        },

        testBindFireWithContextAndArgs: function(t) {
          output = "X"
          $.Callbacks(config).add(function() {
            t.assertEqual(window, this, "Basic binding and firing (context)" )
            output += Array.prototype.join.call(arguments, "")
          }).fireWith(window, [ "A", "B" ])
          t.assertEqual( "XAB", output, "Basic binding and firing (arguments)" )
        },

        testFireWithNoArgs: function(t) {
          $.Callbacks(config).add(function() {
            t.assertEqual(window, this, "fireWith with no arguments (context is window)")
            t.assertEqual(0, arguments.length, "fireWith with no arguments (no arguments)")
          }).fireWith()
        },

        testBindRemoveFire: function(t) {
          output = "X"
          $.Callbacks(config).add(a, b, c).remove(b, c).fire()
          t.assertEqual("XA", output)
        },

        testEmpty: function(t) {
          output = "X"
          $.Callbacks(config).add(a, b, c).empty().fire()
          t.assertEqual( "X", output, "Empty" )
        },

        testLocking: function(t) {
          output = "X"
          $.Callbacks(config).add(str).lock().add(str).fire("A").add(str)
          t.assertEqual("X", output, "Lock early")
        },

        testOrdering: function(t) {
          output = "X", cb = $.Callbacks(config)
          cb.add(function() {
            cb.add(c)
            a()
          }, b).fire()
          t.assertEqual( results.shift(), output, "Proper ordering" )

          output = "X"
          cb.add(function() {
            cb.add(c)
            a()
          }, b)
          t.assertEqual(results.shift(), output, "Add after fire")
          output = "X"
          cb.fire()
          t.assertEqual(results.shift(), output, "Fire again")

          output = "X", cb = $.Callbacks(config)
          cb.add(str).fire("A")
          t.assertEqual("XA", output, "Multiple fire (first fire)")
          output = "X"
          cb.add(str)
          t.assertEqual(results.shift(), output, "Multiple fire (first new callback)")
          output = "X"
          cb.fire("B")
          t.assertEqual(results.shift(), output, "Multiple fire (second fire)")
          output = "X"
          cb.add(str)
          t.assertEqual(results.shift(), output, "Multiple fire (second new callback)")

          output = "X", cb = $.Callbacks(config).add(a, function() { return false }, b).add(a).fire()
          t.assertEqual(results.shift(), output, "Callback returning false")

          output = "X"
          cb.add(c)
          t.assertEqual(results.shift(), output, "Adding a callback after one returned false")

          output = ""
          function handler() { output += "X" }
          handler.method = function() { output += "!" }
          cb = $.Callbacks(config).add(handler).add(handler).fire()
          t.assertEqual(results.shift(), output, "No callback iteration")
        }

      })

    })
  })()
  </script>
</body>
</html>


================================================
FILE: test/data.html
================================================
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <link rel="stylesheet" href="test.css">
  <title>Zepto Data unit tests</title>
  <script src="../vendor/evidence.js"></script>
  <script src="evidence_runner.js"></script>
  <script>
    // avoid caching
    (function(){
      function load(scripts){
        scripts.split(' ').forEach(function(script){
          document.write('<script src="../src/'+script+'.js?'+(+new Date)+'"></scr'+'ipt>')
        })
      }

      load('zepto data ie')
    })()
  </script>
</head>
<body>
  <h1>Zepto Data unit tests</h1>
  <p id="results">
    Running… see browser console for results
  </p>
  <div id="fixtures">
  <div id="data_attr"
    data-one="uno"
    data-two="due"
    data-foo-bar="baz"
    data-under_score="kuuq"
    ></div>
  <div id="data_full" data-mode="awesome"></div>
  <div id="data_obj" data-mode="awesome"></div>
  <ol id="data_list">
    <li data-category="arts"></li>
    <li data-category="science"></li>
  </ol>
  <ol id="data_list2">
    <li></li>
    <li></li>
  </ol>
  </div>

  <script>
    Evidence('ZeptoExtendedDataTest', {
      testEmptyCollection: function(t){
        var el = $('#does_not_exist')
        t.assertUndefined(el.data('one'))
      },

      testAttributeDoesNotExist: function(t){
        var el = $('#data_attr')
        t.assertUndefined(el.data('missing'))
      },

      testReadingAttribute: function(t){
        var el = $('#data_attr')
        t.assertEqual('uno', el.data('one'))
      },

      testCamelized: function(t){
        var el = $('#data_attr')
        t.assertEqual('baz', el.data('foo-bar'))
        t.assertEqual('baz', el.data('fooBar'))

        el.data('fooBar', 'bam')
        t.assertEqual('bam', el.data('foo-bar'))
        t.assertEqual('bam', el.data('fooBar'))

        el.data('a-b', 'c')
        t.assertEqual('c', el.data().aB)
        t.assertUndefined(el.data()['a-b'])
      },

      testUnderscore: function(t){
        var el = $('#data_attr')
        t.assertEqual('kuuq', el.data('under_score'))
        t.assertUndefined(el.data('under-score'))
        t.assertUndefined(el.data('underScore'))
      },

      testNotChangingAttribute: function(t){
        var el = $('#data_attr')
        t.assertEqual('due', el.data('two'))
        el.data('two', 'changed')
        t.assertEqual('due', el.attr('data-two'))
      },

      testExtendedData: function(t){
        var els = $('#data_attr'),
          els2 = $('#data_attr'),
          obj  = { a: 'A', b: 'B' }

        els.data('obj', obj)
        t.assertIdentical(obj, els.data('obj'))
        t.assertIdentical(obj, els2.data('obj'))

        els2.data('els', els)
        t.assertIdentical(els, els.data('els'))
      },

      testMultipleElements: function(t){
        var items = $('#data_list li')

        items.data('each', 'mark')

        var values = items.map(function(){ return $(this).data('each') }).get()
        t.assertEqual('mark, mark', values.join(', '))
      },

      testFunctionArg: function(t){
        var els = $('#data_attr')

        var data = "hello"

        els.data("addio", function () {
          data = "goodbye"
        })

        t.assertEqual('hello', data)

        els.data("addio")()

        t.assertEqual('goodbye', data)
      },

      testAllData: function(t){
        var el = $('#data_full')

        el.data().samurai = 7
        el.data('one', 'ichi').data('two', 'ni')
        el.data('person', {name: 'Kurosawa'})

        var all = el.data()
        t.assertEqual(7, all.samurai)
        t.assertEqual('ichi', all.one)
        t.assertEqual('ni', all.two)
        t.assertEqual('Kurosawa', all.person.name)
      },

      testInitialDataFromAttributes: function(t){
        var el = $('<div data-foo=bar data-foo-bar=baz data-empty data-num=42 />'),
            store = el.data()

        t.assertEqual('bar', store.foo)
        t.assertEqual('baz', store.fooBar)
        t.assertUndefined(store['foo-bar'])
        t.assertIdentical('', store.empty)
        t.assertIdentical(42, store.num)
      },

      testGettingBlanks: function(t){
        var el = $('#data_attr'),
            store = el.data()

        store.nil = null
        store.undef = undefined
        store.blank = ''
        store.bool = false

        t.assertNull(el.data('nil'))
        t.assertUndefined(el.data('undef'))
        t.assertIdentical('', el.data('blank'))
        t.assertFalse(el.data('bool'))
      },

      testRemoveData: function(t){
        var el = $('<div data-foo=bar />')

        el.data('foo', 'bam').data('bar', 'baz')
        el.removeData('foo').removeData('bar')
        t.assertEqual('bar', el.data('foo'))
        t.assertUndefined(el.data('bar'))

        el.data('uno', 'one').data('due', 'two')
        el.removeData('uno due')
        t.assertUndefined(el.data('uno'))
        t.assertUndefined(el.data('due'))

        el.data('one', 1).data('twoThree', 23)
        el.removeData(['one', 'two-three'])
        t.assertUndefined(el.data('one'))
        t.assertUndefined(el.data('twoThree'))
      },

      testRemoveAllData: function(t){
        var el = $('<div data-attr-test=val />')

        el.data('one', { foo: 'bar' })
        el.data('two', 'two').data('three', 3)
        el.removeData()

        t.assertEqual('val', el.data('attrTest'))
        t.assertUndefined(el.data('one'))
        t.assertUndefined(el.data('two'))
        t.assertUndefined(el.data('three'))
      },

      testRemoveDataNoop: function(t){
        var empty = $(),
            vanilla = $('<div />')

        t.assertIdentical(empty, empty.removeData('foo'))
        t.assertIdentical(vanilla, vanilla.removeData('foo'))
      },

      testRemoveDataOnElementRemoval: function(t){
        var el = $('<div data-attr-test=val />'),
          childEl = $('<span />').appendTo(el),
          elData = { foo: 'bar' }

        el.data('test', elData)
        childEl.data('test', 1)

        el.remove()
        t.assertEqual('val', el.data('attrTest'))
        t.assertUndefined(el.data('test'))
        t.assertUndefined(childEl.data('test'))
      },

      testRemoveDataOnElementEmpty: function(t){
        var el = $('<div data-attr-test=val />'),
          childEl = $('<span />').appendTo(el),
          elData = { foo: 'bar' }

        el.data('test', elData)
        childEl.data('test', 1)

        el.empty()
        t.assertEqual('val', el.data('attrTest'))
        t.assertEqual(elData, el.data('test'))
        t.assertUndefined(childEl.data('test'))
      },

      testRemoveDataOnElementReplacement: function(t){
        var el = $('<div data-attr-test=val />'),
          childEl = $('<span />').appendTo(el),
          elData = { foo: 'bar' }

        el.data('test', elData)
  
Download .txt
gitextract_k6qzt7fr/

├── .gitignore
├── .npmignore
├── .travis.yml
├── CONTRIBUTING.md
├── MIT-LICENSE
├── README.md
├── examples/
│   ├── anim.html
│   ├── iphone/
│   │   ├── index.html
│   │   └── iphone.css
│   ├── load_jquery_on_ie.html
│   ├── snow/
│   │   └── index.html
│   └── touch_events.html
├── make
├── package.json
├── script/
│   ├── bootstrap
│   ├── guard
│   ├── lint
│   └── test
├── src/
│   ├── ajax.js
│   ├── amd_layout.js
│   ├── assets.js
│   ├── callbacks.js
│   ├── data.js
│   ├── deferred.js
│   ├── detect.js
│   ├── event.js
│   ├── form.js
│   ├── fx.js
│   ├── fx_methods.js
│   ├── gesture.js
│   ├── ie.js
│   ├── ios3.js
│   ├── selector.js
│   ├── stack.js
│   ├── touch.js
│   └── zepto.js
├── test/
│   ├── ajax.html
│   ├── ajax_deferred.html
│   ├── callbacks.html
│   ├── data.html
│   ├── deferred.html
│   ├── detect.html
│   ├── event.html
│   ├── evidence_runner.js
│   ├── fixtures/
│   │   ├── ajax_load_javascript.js
│   │   ├── ajax_load_selector.html
│   │   ├── ajax_load_selector_javascript.html
│   │   ├── ajax_load_simple.html
│   │   ├── iframe_document.html
│   │   └── zepto.json
│   ├── form.html
│   ├── functional/
│   │   ├── assets.html
│   │   ├── fx.html
│   │   ├── gesture.html
│   │   ├── touch.html
│   │   └── touchcancel.html
│   ├── fx.html
│   ├── ie.html
│   ├── index.html
│   ├── ios3.html
│   ├── runner.js
│   ├── selector.html
│   ├── server.coffee
│   ├── stack.html
│   ├── test.css
│   ├── touch.html
│   └── zepto.html
└── vendor/
    └── evidence.js
Download .txt
SYMBOL INDEX (179 symbols across 14 files)

FILE: src/ajax.js
  function triggerAndReturn (line 21) | function triggerAndReturn(context, eventName, data) {
  function triggerGlobal (line 28) | function triggerGlobal(settings, context, eventName, data) {
  function ajaxStart (line 35) | function ajaxStart(settings) {
  function ajaxStop (line 38) | function ajaxStop(settings) {
  function ajaxBeforeSend (line 43) | function ajaxBeforeSend(xhr, settings) {
  function ajaxSuccess (line 51) | function ajaxSuccess(data, xhr, settings, deferred) {
  function ajaxError (line 59) | function ajaxError(error, type, xhr, settings, deferred) {
  function ajaxComplete (line 67) | function ajaxComplete(status, xhr, settings) {
  function ajaxDataFilter (line 74) | function ajaxDataFilter(data, type, settings) {
  function empty (line 81) | function empty() {}
  function mimeToDataType (line 177) | function mimeToDataType(mime) {
  function appendQuery (line 185) | function appendQuery(url, query) {
  function serializeData (line 191) | function serializeData(options) {
  function parseArguments (line 313) | function parseArguments(url, data, success, dataType) {
  function serialize (line 358) | function serialize(params, obj, traditional, scope){

FILE: src/data.js
  function getData (line 15) | function getData(node, name) {
  function setData (line 29) | function setData(node, name, value) {
  function attributeData (line 37) | function attributeData(node) {

FILE: src/deferred.js
  function Deferred (line 10) | function Deferred(func) {

FILE: src/detect.js
  function detect (line 6) | function detect(ua, platform){

FILE: src/event.js
  function zid (line 18) | function zid(element) {
  function findHandlers (line 21) | function findHandlers(element, event, fn, selector) {
  function parse (line 32) | function parse(event) {
  function matcherFor (line 36) | function matcherFor(ns) {
  function eventCapture (line 40) | function eventCapture(handler, captureSetting) {
  function realEvent (line 46) | function realEvent(type) {
  function add (line 50) | function add(element, events, fn, data, selector, delegator, capture){
  function remove (line 79) | function remove(element, events, fn, selector, capture){
  function compatible (line 129) | function compatible(event, source) {
  function createProxy (line 154) | function createProxy(event) {

FILE: src/fx.js
  function dasherize (line 15) | function dasherize(str) { return str.replace(/([A-Z])/g, '-$1').toLowerC...
  function normalizeEvent (line 16) | function normalizeEvent(name) { return eventPrefix ? eventPrefix + name ...

FILE: src/fx_methods.js
  function anim (line 9) | function anim(el, speed, opacity, scale, callback) {
  function hide (line 19) | function hide(el, speed, scale, callback) {

FILE: src/gesture.js
  function parentIfText (line 9) | function parentIfText(node){

FILE: src/selector.js
  function visible (line 8) | function visible(elem){
  function process (line 41) | function process(sel, fn) {

FILE: src/touch.js
  function swipeDirection (line 14) | function swipeDirection(x1, x2, y1, y2) {
  function longTap (line 19) | function longTap() {
  function cancelLongTap (line 27) | function cancelLongTap() {
  function cancelAll (line 32) | function cancelAll() {
  function isPrimaryTouch (line 41) | function isPrimaryTouch(event){
  function isPointerEventType (line 47) | function isPointerEventType(e, type){
  function unregisterTouchEvents (line 53) | function unregisterTouchEvents(){
  function setup (line 64) | function setup(__eventMap){

FILE: src/zepto.js
  function type (line 65) | function type(obj) {
  function isFunction (line 70) | function isFunction(value) { return type(value) == "function" }
  function isWindow (line 71) | function isWindow(obj)     { return obj != null && obj == obj.window }
  function isDocument (line 72) | function isDocument(obj)   { return obj != null && obj.nodeType == obj.D...
  function isObject (line 73) | function isObject(obj)     { return type(obj) == "object" }
  function isPlainObject (line 74) | function isPlainObject(obj) {
  function likeArray (line 78) | function likeArray(obj) {
  function compact (line 88) | function compact(array) { return filter.call(array, function(item){ retu...
  function flatten (line 89) | function flatten(array) { return array.length > 0 ? $.fn.concat.apply([]...
  function dasherize (line 91) | function dasherize(str) {
  function classRE (line 100) | function classRE(name) {
  function maybeAddPx (line 105) | function maybeAddPx(name, value) {
  function defaultDisplay (line 109) | function defaultDisplay(nodeName) {
  function children (line 122) | function children(element) {
  function Z (line 128) | function Z(dom, selector) {
  function extend (line 235) | function extend(target, source, deep) {
  function filtered (line 279) | function filtered(nodes, selector) {
  function funcArg (line 293) | function funcArg(context, arg, idx, payload) {
  function setAttribute (line 297) | function setAttribute(node, name, value) {
  function className (line 302) | function className(node, value){
  function deserializeValue (line 318) | function deserializeValue(value) {
  function traverseNode (line 871) | function traverseNode(node, fun) {

FILE: test/evidence_runner.js
  function inherit (line 7) | function inherit(superclass, extra) {
  function $ (line 93) | function $(id) { return document.getElementById(id) }
  function displayResults (line 95) | function displayResults(results, seconds) {
  function checkLeakedGlobals (line 114) | function checkLeakedGlobals() {

FILE: test/runner.js
  function waitFor (line 28) | function waitFor(testFn, onReady, timeout) {
  function loadNextSuite (line 44) | function loadNextSuite() {

FILE: vendor/evidence.js
  function Evidence (line 12) | function Evidence() {
  function noConflict (line 16) | function noConflict() {
  function getNameFromFile (line 26) | function getNameFromFile() {
  function chain (line 30) | function chain(subclass, superclass) {
  function defer (line 38) | function defer(block, context) {
  function AssertionSkippedError (line 47) | function AssertionSkippedError(message) {
  function AssertionFailedError (line 57) | function AssertionFailedError(message, template, args) {
  function AssertionMessage (line 69) | function AssertionMessage(message, template, args) {
  function toString (line 78) | function toString() {
  function _assertExpression (line 86) | function _assertExpression(expression, message, template) {
  function skip (line 98) | function skip(message) {
  function fail (line 102) | function fail(message) {
  function assert (line 106) | function assert(test, message) {
  function refute (line 114) | function refute(test, message) {
  function assertTrue (line 122) | function assertTrue(test, message) {
  function refuteTrue (line 130) | function refuteTrue(test, message) {
  function assertNull (line 138) | function assertNull(test, message) {
  function refuteNull (line 146) | function refuteNull(test, message) {
  function assertUndefined (line 154) | function assertUndefined(test, message) {
  function refuteUndefined (line 162) | function refuteUndefined(test, message) {
  function assertFalse (line 170) | function assertFalse(test, message) {
  function refuteFalse (line 178) | function refuteFalse(test, message) {
  function assertEqual (line 186) | function assertEqual(expected, actual, message) {
  function refuteEqual (line 194) | function refuteEqual(expected, actual, message) {
  function assertIdentical (line 202) | function assertIdentical(expected, actual, message) {
  function refuteIdentical (line 210) | function refuteIdentical(expected, actual, message) {
  function assertIn (line 218) | function assertIn(property, object, message) {
  function refuteIn (line 226) | function refuteIn(property, object, message) {
  function TestCase (line 255) | function TestCase(methodName) {
  function extend (line 261) | function extend(name, methods) {
  function AssertionsMixin (line 282) | function AssertionsMixin() {}
  function run (line 294) | function run(result) {
  function _filterException (line 327) | function _filterException(e) {
  function pause (line 341) | function pause(assertions) {
  function resume (line 352) | function resume(assertions) {
  function size (line 361) | function size() {
  function toString (line 365) | function toString() {
  function addAssertion (line 369) | function addAssertion() {
  function TestSuite (line 384) | function TestSuite(name, tests) {
  function run (line 395) | function run(result) {
  function next (line 403) | function next() {
  function push (line 418) | function push() {
  function addTest (line 426) | function addTest(test) {
  function addTests (line 431) | function addTests(tests) {
  function size (line 437) | function size() {
  function isEmpty (line 448) | function isEmpty() {
  function toString (line 452) | function toString() {
  function TestRunner (line 463) | function TestRunner() {
  function run (line 469) | function run(suite) {
  function _makeResult (line 477) | function _makeResult() {
  function TestLoader (line 485) | function TestLoader() {
  function loadTestsFromTestCase (line 491) | function loadTestsFromTestCase(testcaseClass) {
  function loadTestsFromTestCases (line 500) | function loadTestsFromTestCases(testcases) {
  function getTestCaseNames (line 510) | function getTestCaseNames(testcaseClass) {
  function loadRegisteredTestCases (line 523) | function loadRegisteredTestCases() {
  function AutoRunner (line 535) | function AutoRunner() {
  function run (line 549) | function run(options) {
  function run (line 570) | function run() {
  function processQueryString (line 580) | function processQueryString(str) {
  function processArguments (line 601) | function processArguments(args) { // RHINO
  function retrieveOptions (line 619) | function retrieveOptions() {
  function processOptions (line 629) | function processOptions(options) {
  function TestResult (line 660) | function TestResult() {
  function addAssertion (line 675) | function addAssertion() {
  function addSkip (line 679) | function addSkip(testcase, reason) {
  function addFailure (line 684) | function addFailure(testcase, reason) {
  function addError (line 689) | function addError(testcase, error) {
  function startTest (line 694) | function startTest(testcase) {
  function stopTest (line 698) | function stopTest(testcase) {}
  function pauseTest (line 700) | function pauseTest(testcase) {}
  function restartTest (line 702) | function restartTest(testcase) {}
  function startSuite (line 704) | function startSuite(suite) {}
  function stopSuite (line 706) | function stopSuite(suite) {}
  function start (line 708) | function start(t0) {
  function stop (line 712) | function stop(t1) {
  function toString (line 716) | function toString() {
  function Logger (line 741) | function Logger(level) {
  function critical (line 757) | function critical(template, params) {
  function error (line 761) | function error(template, params) {
  function warn (line 765) | function warn(template, params) {
  function info (line 769) | function info(template, params) {
  function debug (line 773) | function debug(template, params) {
  function log (line 777) | function log(level, template, params) {
  function PopupLogger (line 805) | function PopupLogger(level) {
  function _cleanup (line 820) | function _cleanup(html) {
  function _makePopup (line 824) | function _makePopup() {
  function _appendLine (line 840) | function _appendLine(level, msg) {
  function log (line 863) | function log(level, msg, params) {
  function CommandLineLogger (line 878) | function CommandLineLogger(level) {
  function log (line 887) | function log(level, msg, params) {
  function ConsoleTestRunner (line 904) | function ConsoleTestRunner(logger) {
  function _makeResult (line 913) | function _makeResult() {
  function ConsoleTestResult (line 920) | function ConsoleTestResult(logger) {
  function addAssertion (line 931) | function addAssertion() {
  function addSkip (line 935) | function addSkip(testcase, msg) {
  function addFailure (line 940) | function addFailure(testcase, msg) {
  function addError (line 945) | function addError(testcase, error) {
  function startTest (line 950) | function startTest(testcase) {
  function stopTest (line 955) | function stopTest(testcase) {
  function pauseTest (line 959) | function pauseTest(testcase) {
  function restartTest (line 963) | function restartTest(testcase) {
  function startSuite (line 967) | function startSuite(suite) {
  function stopSuite (line 971) | function stopSuite(suite) {
  function start (line 975) | function start(t0) {
  function stop (line 980) | function stop(t1) {
  function printf (line 1003) | function printf(template, args, inspector) {
Condensed preview — 68 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (473K chars).
[
  {
    "path": ".gitignore",
    "chars": 130,
    "preview": ".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"
  },
  {
    "path": ".npmignore",
    "chars": 88,
    "preview": "*\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",
    "chars": 381,
    "preview": "language: node_js\n\nnode_js: '0.10'\n\nsudo: false\n\nscript: script/test\n\nnotifications:\n  campfire:\n    template: '%{messag"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2362,
    "preview": "## Contributing to Zepto\n\n**Thanks for helping out!**\n\nIn order for your code to make it in, several conditions must be "
  },
  {
    "path": "MIT-LICENSE",
    "chars": 1081,
    "preview": "Copyright (c) 2010-2025 Thomas Fuchs\nhttp://zeptojs.com/\n\nPermission is hereby granted, free of charge, to any person ob"
  },
  {
    "path": "README.md",
    "chars": 6618,
    "preview": "# Zepto.js – a minimalist JavaScript library\n\nZepto is a minimalist JavaScript library for modern browsers with a\nlargel"
  },
  {
    "path": "examples/anim.html",
    "chars": 283,
    "preview": "<div style=\"width:100px;height:100px;border:1px solid black\">HELLO WORLD</div>\n\n<script src=\"../src/zepto.js\"></script>\n"
  },
  {
    "path": "examples/iphone/index.html",
    "chars": 1991,
    "preview": "<!DOCTYPE html>\n<html>\n    <head>\n      <title>iPhone.Zepto</title>\n      <link href=\"iphone.css\" media=\"screen\" rel=\"st"
  },
  {
    "path": "examples/iphone/iphone.css",
    "chars": 5603,
    "preview": "* {\n  margin: 0px;\n  padding: 0px;\n}\n.toolbar {\n  -webkit-box-sizing: border-box;\n  background: #6D84A2 url(data:image/p"
  },
  {
    "path": "examples/load_jquery_on_ie.html",
    "chars": 575,
    "preview": "<!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"
  },
  {
    "path": "examples/snow/index.html",
    "chars": 1829,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Let it snow with Zepto.js</title>\n    <meta name=\"name\" content=\"content\">\n  "
  },
  {
    "path": "examples/touch_events.html",
    "chars": 714,
    "preview": "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\"/>\n\n<script src"
  },
  {
    "path": "make",
    "chars": 3090,
    "preview": "#!/usr/bin/env coffee\nrequire 'shelljs/make'\nfs = require 'fs'\n\nzepto_js  = 'dist/zepto.js'\nzepto_min = 'dist/zepto.min."
  },
  {
    "path": "package.json",
    "chars": 465,
    "preview": "{\n    \"name\": \"zepto\",\n    \"version\": \"1.2.0\",\n    \"main\": \"dist/zepto.js\",\n    \"homepage\": \"http://zeptojs.com\",\n    \"s"
  },
  {
    "path": "script/bootstrap",
    "chars": 207,
    "preview": "#!/usr/bin/env bash\nset -e\n\nnpm install\n\nif phantom_version=\"$(phantomjs --version)\"; then\n  echo \"phantomjs ${phantom_v"
  },
  {
    "path": "script/guard",
    "chars": 107,
    "preview": "#!/bin/sh\nif [ -z \"$BUNDLE_GEMFILE\" ]; then\n  export BUNDLE_GEMFILE=shutup\nfi\n\nexec guard --no-notify \"$@\"\n"
  },
  {
    "path": "script/lint",
    "chars": 353,
    "preview": "#!/usr/bin/awk -f\n\nBEGIN { if (length(ARGV) < 2) exit 0 }\n\n/<script/ { script=FILENAME }\n/<\\/script/ { script=\"\" }\n\n/;\\s"
  },
  {
    "path": "script/test",
    "chars": 641,
    "preview": "#!/usr/bin/env bash\nset -e\n\nport=3999\ntest_url=\"http://localhost:${port}/\"\n\nexport PATH=node_modules/.bin:\"$PATH\"\n\ngit l"
  },
  {
    "path": "src/ajax.js",
    "chars": 13843,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/amd_layout.js",
    "chars": 212,
    "preview": "(function(global, factory) {\n  if (typeof define === 'function' && define.amd)\n    define(function() { return factory(gl"
  },
  {
    "path": "src/assets.js",
    "chars": 581,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/callbacks.js",
    "chars": 4208,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/data.js",
    "chars": 2789,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n// T"
  },
  {
    "path": "src/deferred.js",
    "chars": 3846,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n//\n//"
  },
  {
    "path": "src/detect.js",
    "chars": 3754,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/event.js",
    "chars": 9588,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/form.js",
    "chars": 1253,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/fx.js",
    "chars": 4843,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/fx_methods.js",
    "chars": 2066,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/gesture.js",
    "chars": 1138,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/ie.js",
    "chars": 530,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/ios3.js",
    "chars": 1140,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/selector.js",
    "chars": 3187,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/stack.js",
    "chars": 560,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/touch.js",
    "chars": 7006,
    "preview": "//     Zepto.js\n//     (c) 2010-2016 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\n;(fu"
  },
  {
    "path": "src/zepto.js",
    "chars": 34346,
    "preview": "//     Zepto.js\n//     (c) 2010-2017 Thomas Fuchs\n//     Zepto.js may be freely distributed under the MIT license.\n\nvar "
  },
  {
    "path": "test/ajax.html",
    "chars": 51396,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/ajax_deferred.html",
    "chars": 5778,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/callbacks.html",
    "chars": 9715,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/data.html",
    "chars": 9999,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/deferred.html",
    "chars": 15715,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/detect.html",
    "chars": 22635,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/event.html",
    "chars": 13714,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/evidence_runner.js",
    "chars": 4381,
    "preview": "(function(){\n  var ConsoleTestRunner = Evidence.AutoRunner.RUNNERS.console,\n      ConsoleTestResult = Evidence.UI.Consol"
  },
  {
    "path": "test/fixtures/ajax_load_javascript.js",
    "chars": 21,
    "preview": "window.testValue = 1\n"
  },
  {
    "path": "test/fixtures/ajax_load_selector.html",
    "chars": 637,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>testAjaxLoad</title>\n</head>\n<body>\n<div id=\"ajax_load_t"
  },
  {
    "path": "test/fixtures/ajax_load_selector_javascript.html",
    "chars": 679,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>testAjaxLoad</title>\n</head>\n<body>\n<div id=\"ajax_load_t"
  },
  {
    "path": "test/fixtures/ajax_load_simple.html",
    "chars": 17,
    "preview": "simple ajax load\n"
  },
  {
    "path": "test/fixtures/iframe_document.html",
    "chars": 26,
    "preview": "<b>Hello from iframe!</b>\n"
  },
  {
    "path": "test/fixtures/zepto.json",
    "chars": 29,
    "preview": "{\n  \"zepto\": \"awesomeness\"\n}\n"
  },
  {
    "path": "test/form.html",
    "chars": 5349,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/functional/assets.html",
    "chars": 1923,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Zepto assets functional test</title>\n  <link rel=\"styles"
  },
  {
    "path": "test/functional/fx.html",
    "chars": 1922,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"maximum-scale=1,initial-scale=1,"
  },
  {
    "path": "test/functional/gesture.html",
    "chars": 1012,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Zepto gesture functional test</title>\n  <meta name=\"view"
  },
  {
    "path": "test/functional/touch.html",
    "chars": 3079,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Zepto touch functional test</title>\n  <meta name=\"viewpo"
  },
  {
    "path": "test/functional/touchcancel.html",
    "chars": 1597,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Zepto touch functional test</title>\n  <meta name=\"viewpo"
  },
  {
    "path": "test/fx.html",
    "chars": 10662,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/ie.html",
    "chars": 1673,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/index.html",
    "chars": 2285,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/ios3.html",
    "chars": 1605,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/runner.js",
    "chars": 2129,
    "preview": "(function() {\n  var fs = require('fs')\n  var system = require('system')\n  var args = system.args.slice(1)\n\n  var prefix "
  },
  {
    "path": "test/selector.html",
    "chars": 2932,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/server.coffee",
    "chars": 3391,
    "preview": "express = require 'express'\napp     = express()\npath    = require 'path'\n\nmodule.exports = app\n\nproject_root = path.reso"
  },
  {
    "path": "test/stack.html",
    "chars": 1828,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/test.css",
    "chars": 1185,
    "preview": "* {\n  font-family: -apple-system-font, Helvetica, sans-serif;\n}\nbody {\n  padding: 1em;\n}\na:link, a:visited { color: dark"
  },
  {
    "path": "test/touch.html",
    "chars": 9924,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "test/zepto.html",
    "chars": 118352,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale"
  },
  {
    "path": "vendor/evidence.js",
    "chars": 25995,
    "preview": "/*  evidence.js, version 0.6\n *\n *  Copyright (c) 2009 Tobie Langel (http://tobielangel.com)\n *\n *  evidence.js is freel"
  }
]

About this extraction

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

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

Copied to clipboard!