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
[](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> & <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 & 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> & <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><script src="'+script.src+'"></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=?×tamp='+(+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=?×tamp='+(+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=?×tamp='+(+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=?×tamp='+(+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=?×tamp='+(+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)
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
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.