├── README.md ├── example ├── events.html ├── multi-page.html ├── multi-page2.html ├── nested │ └── nested2.html ├── nested1.html ├── programmatic.html ├── simple.html ├── simple2.html └── zepto.min.js ├── min ├── transition.min.css └── transition.min.js └── src ├── transition.css └── transition.js /README.md: -------------------------------------------------------------------------------- 1 | Zepto plugin for Animated CSS Page Transitions 2 | ====================== 3 | 4 | This HTML5 CSS Page Transitions plugin for [Zepto.js](http://zeptojs.com) is similar to [JQuery Mobile page transitions](http://jquerymobile.com/demos/1.2.0/docs/pages/page-navmodel.html), but is standalone, i.e. without all the other widgets and functionality that JQuery Mobile provides. Consequently it is much smaller, at around 13k. 5 | 6 | ## What It Does ## 7 | 8 | In order to support animated transitions between pages the plugin has to hijack regular browser navigation. When you click a link or submit a form the plugin makes an AJAX request to load the new page. It places the body of the loaded page into a new div, and then uses HTML5 CSS transitions to smoothly switch between the two pages. 9 | 10 | ## Example ## 11 | 12 | The above may sound a little complicated, but using the plugin is quite simple. Just include zepto.js and the CSS and JS file from this plugin in your main page (we'll call it simple.html): 13 | 14 | 15 | 16 | 17 | 18 | 19 | Page One 20 | 21 | 22 |

You're Starting On Page One

23 | Flip to page two 24 | 25 | 26 | 27 | Note the `transition="flip"` attribute. You could also have used `data-transition="flip"`, or left the attribute off entirely to use the default transition. Here's the page that it links to (simple2.html): 28 | 29 | 30 | 31 | Page Two 32 | 33 | 34 |

You've Reached Page Two

35 | Now back to page one 36 | 37 | 38 | 39 | Notice that simple2.html doesn't have any links to stylesheets or Javascript files. That's because the head content is thrown away when the page is loaded via AJAX. If you want to run scripts or include styles specific to simple2.html then just include them within its `` tag. 40 | 41 | Also see the multi-page example for including multiple pages in a single HTML file. 42 | 43 | ## Transitions ## 44 | 45 | This plugin includes the following CSS transitions, found in transition.css: 46 | 47 | * spin 48 | * slide 49 | * slideup 50 | * slidedown 51 | * fade 52 | * flip 53 | * pop 54 | 55 | You can create your own CSS transitions in your own CSS file. Just reference them using the `transition="mycustomtransition"` or `data-transition="mycustomtransition"` attribute. 56 | 57 | ## Navigation ## 58 | 59 | Any link can have a `transition` and/or `direction="reverse"` attribute (each of these can also be prefixed by `data-`). Forms may also have these attributes. Other elements like buttons can also trigger page transitions and have the above attributes; just add a `data-href` attribute to them. 60 | 61 | Use the `data-rel="back"` attribute to navigate backwards using the browser history. You can also use javascript, e.g. `history.back()`. Either of these methods (or the browser's back button) will cause the previous transition to play in reverse. The scroll location of the page you're navigating back to is also preserved. 62 | 63 | Any link that has a `rel="external"` attribute will be excluded from using page transitions. Likewise any link or form that has a `data-ajax="false"` or a `target` attribute will also be excluded. 64 | 65 | You can link to HTML files that are not in the same level as the original HTML file, e.g. `href="path/with/slashes.html"`. However this support is provided by replacing links in the loaded HTML and consequently may be slow and incomplete. Avoid using multiple levels of pages when possible. 66 | 67 | You can load pages programmatically, as demonstrated in the programmatic example: 68 | 69 | $(document).transition('to', relativeUrl, transition, reverse); 70 | 71 | The `'to'`, `transition` and `reverse` arguments are optional. 72 | 73 | ## Multiple Pages In One File ## 74 | 75 | To put several pages into one HTML file simply place each one inside its own `
` tag. To link to a page within the file first give each div its own `id` attribute, and then in the link use `href="#pageid"`, where pageid is the value of a page's id attribute. Note that page id's should be unique across your site, not just within a single HTML file. 76 | 77 | When you link to an HTML file containing multiple pages the first page is displayed. To display a page other than the first, append the id of that page as a hash in the URL you load it with. You can see this in action by loading the multiple page example like: 78 | 79 | multi-page.html#two 80 | 81 | When you load a new page the browser's title is replaced with that page's title. You can use the `data-title` attribute to give pages within an HTML file their own title. 82 | 83 | ## Caveats ## 84 | 85 | Because this plugin loads pages using AJAX you can't use the regular `$(document).ready()` function that you may be used to for any page except the first. Instead bind to the `pageinit` event, which will be triggered for each loaded page. If you want to handle the `pageinit` event for the initial page, register your listener in a script tag that comes before including transition.js. You can see this in the events example. 86 | 87 | As mentioned in the example, head content is thrown away when an HTML file is loaded. If you want to run scripts or include styles specific to a HTML file then include them within its `` tag. Put all shared scripts and styles into the original HTML file's head content. 88 | 89 | ## Options ## 90 | 91 | To set the `defaultPageTransition` and/or `domCache` customization options you can use code like the following: 92 | 93 | $(document.body).transition('options', {defaultPageTransition : 'slide', domCache : true}); 94 | 95 | The default for `defaultPageTransition` is `"fade"` and the default for `domCache` is `false`. 96 | 97 | ## Events ## 98 | 99 | This plugin shares many events with [JQuery Mobile](http://jquerymobile.com/demos/1.2.0/docs/api/events.html), although the data passed to the callback function is often different. The events it supports are: 100 | 101 | * `pagebeforeload`: called before a page is about to be loaded via AJAX. The data object passed as the second argument to the callback function includes the following properties: `href`: the URL of the page to load, `element`: the element (if any) that triggered the load, and `back`: whether the load was triggered while navigating backwards. This event may be prevented by the callback. 102 | * `pageload`: called when the page is loaded via AJAX and added to the document, but before it is initialized. The data object passed as the second argument to the callback function includes the same properties as the pagebeforeload event plus the following properties: `xhr`: the Zepto XMLHttpRequest used to load the page, and `textStatus`: the status of the request (if any). This event may not be prevented. 103 | * `pageloadfailed`: called when the page couldn't be loaded via AJAX. The data object passed as the second argument to the callback function includes the same properties as the pagebeforeload event plus the following properties: `xhr`: the Zepto XMLHttpRequest used to load the page, `textStatus`: the status of the request (if any), and `errorThrown`: an exception object or text status. This event may not be prevented. 104 | * `pagebeforechange`: called before switching to a new page. The data object passed as the second argument to the callback function includes the following properties: `toPage`: the URL or hash of the page to change to, and `back`: whether the page change is navigating backwards. This event may be prevented by the callback. Additionally any changes to toPage or back are reflected when changing the page. 105 | * `pagechange`: called after the page change has been fully accomplished, including the transition and show/hide events. The data object passed as the second argument to the callback function is the same as for the pagebeforechange event. This event may not be prevented. 106 | * `pagechangefailed`: called if the page change failed for any reason. The data object passed as the second argument to the callback function is the same as for the pagebeforechange event. This event may not be prevented. 107 | * `pagebeforeshow`: called before a page is shown. The data object passed as the second argument to the callback function is the page about to be shown. This event may not be prevented. 108 | * `pagebeforehide`: called before a page is hidden. The data object passed as the second argument to the callback function is the page about to be hidden. This event may not be prevented. 109 | * `pageshow`: called after a page is shown. The data object passed as the second argument to the callback function is the page that was shown. This event may not be prevented. 110 | * `pagehide`: called after a page is hidden. The data object passed as the second argument to the callback function is the page that was hidden. This event may not be prevented. 111 | * `pageinit`: called when a page is fully initialized, but before it is shown. The data object passed as the second argument to the callback function is the page that was initialized. This event may not be prevented. 112 | * `pageremove`: called before a page is removed from the DOM, which can happen when a new HTML file is loaded and the page is not being cached. The data object passed as the second argument to the callback function is the page that will be removed. This event may be prevented by the callback. 113 | 114 | ## Features ## 115 | 116 | This transition plugin is largely modeled after the JQuery Mobile plugin's design, although it's written from scratch and thus may have its own quirks and bugs not shared by JQuery Mobile. Here are some features that it shares with JQuery Mobile: 117 | 118 | * Ajax navigation with page transitions for links and forms. 119 | * Support for single- or multiple-page templates. 120 | * The `data-href` attribute on non-link elements (like buttons). 121 | * Ignoring links with `rel="external"`, `data-ajax="false"` or the `target` attribute. 122 | * Linking within a multi-page document via `#id` links. Note that unlike JQuery Mobile you don't need to use rel="external" when linking to an HTML file containing multiple pages. 123 | * The `data-rel="back"` and `data-direction="reverse"` (or `direction="reverse"`) attributes for navigating backwards or making it appear that way. 124 | * Caching individual pages via `data-dom-cache="true"`. 125 | * The `defaultPageTransition` and `domCache` configuration options. 126 | 127 | Features that JQuery Mobile provides that this plugin doesn't: 128 | 129 | * Widgets, headers, footers, theming, etc. 130 | * Wide cross-browser support. 131 | * The page loading widget. 132 | * Dialogs and the `data-rel="dialog"` attribute. 133 | * Popups and the `data-role="popup"` attribute. 134 | * The name and signature of Javascript functions. 135 | * Prefetching pages. 136 | * Graceful fallback to the "fade" transition for non-modern browsers. 137 | * Max-scroll and max-width testing to avoid slow transitions. 138 | * Custom transitions. 139 | * The pushState plugin for friendly URLs. 140 | * Use of the `` element for assets in sub-pages with different paths. This plugin instead rewrites URLs when necessary. 141 | * The `data-ajax="false"` attribute on a parent element. 142 | * The `data-url` attribute for linking to sub-pages. 143 | * Most configuration options. 144 | * Large file size :) 145 | * Likely others I missed. 146 | 147 | ## Q & A ## 148 | 149 | 1. Why not use [insert your favorite plugin here] instead? 150 | * It didn't fit my needs (lightweight, uses Zepto.js, decent amount of features). 151 | * I didn't know about it. Feel free to correct my error. 152 | 2. Why doesn't your plugin support [insert your favorite missing feature here]? 153 | * Probably because I didn't need it. Feel free to file an enhancement request and I'll consider it. 154 | 3. I found a bug. 155 | * Please file it and I'll investigate. 156 | -------------------------------------------------------------------------------- /example/events.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 31 | 32 | Page One 33 | 34 | 35 |

You're Starting On Page One

36 |

Events will be logged to your javascript console.

37 | Flip to page two 38 | 39 | -------------------------------------------------------------------------------- /example/multi-page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Page One 7 | 8 | 9 |
10 |

You're Starting On Page One

11 | Spin to local page two 12 |
13 |
14 |

You Reached Page Two, Without Loading Any Data

15 | Slide to load page three 16 |
17 | 18 | -------------------------------------------------------------------------------- /example/multi-page2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | More Pages 7 | 8 | 9 |
10 |

You Ended On Page Three

11 | Go on to the beginning 12 |
13 | 14 | -------------------------------------------------------------------------------- /example/nested/nested2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Nested Page 4 | 5 | 6 |

You've Reached the Nested Page

7 | Now back to the parent page 8 | 9 | -------------------------------------------------------------------------------- /example/nested1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Parent Page 7 | 8 | 9 |

You're Starting On A Parent Page

10 | Flip to nested page 11 | 12 | -------------------------------------------------------------------------------- /example/programmatic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | Page One 18 | 19 | 20 |

You're Starting On Page One

21 |
22 | 31 | 32 |
33 | 34 | -------------------------------------------------------------------------------- /example/simple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Page One 7 | 8 | 9 |

You're Starting On Page One

10 | Flip to page two 11 | 12 | -------------------------------------------------------------------------------- /example/simple2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Page Two 4 | 5 | 6 |

You've Reached Page Two

7 | Now back to page one 8 | 9 | -------------------------------------------------------------------------------- /example/zepto.min.js: -------------------------------------------------------------------------------- 1 | /* Zepto v1.0-1-ga3cab6c - polyfill zepto detect event ajax form fx - zeptojs.com/license */ 2 | (function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?c.fn.concat.apply([],a):a}function O(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function P(a){return a in j?j[a]:j[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function Q(a,b){return typeof b=="number"&&!l[O(a)]?b+"px":b}function R(a){var b,c;return i[a]||(b=h.createElement(a),h.body.appendChild(b),c=k(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),i[a]=c),i[a]}function S(a){return"children"in a?f.call(a.children):c.map(a.childNodes,function(a){if(a.nodeType==1)return a})}function T(c,d,e){for(b in d)e&&(J(d[b])||K(d[b]))?(J(d[b])&&!J(c[b])&&(c[b]={}),K(d[b])&&!K(c[b])&&(c[b]=[]),T(c[b],d[b],e)):d[b]!==a&&(c[b]=d[b])}function U(b,d){return d===a?c(b):c(b).filter(d)}function V(a,b,c,d){return F(b)?b.call(a,c,d):b}function W(a,b,c){c==null?a.removeAttribute(b):a.setAttribute(b,c)}function X(b,c){var d=b.className,e=d&&d.baseVal!==a;if(c===a)return e?d.baseVal:d;e?d.baseVal=c:b.className=c}function Y(a){var b;try{return a?a=="true"||(a=="false"?!1:a=="null"?null:isNaN(b=Number(a))?/^[\[\{]/.test(a)?c.parseJSON(a):a:b):a}catch(d){return a}}function Z(a,b){b(a);for(var c in a.childNodes)Z(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=e.filter,h=window.document,i={},j={},k=h.defaultView.getComputedStyle,l={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},m=/^\s*<(\w+|!)[^>]*>/,n=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,o=/^(?:body|html)$/i,p=["val","css","html","text","data","width","height","offset"],q=["after","prepend","before","append"],r=h.createElement("table"),s=h.createElement("tr"),t={tr:h.createElement("tbody"),tbody:r,thead:r,tfoot:r,td:s,th:s,"*":h.createElement("div")},u=/complete|loaded|interactive/,v=/^\.([\w-]+)$/,w=/^#([\w-]*)$/,x=/^[\w-]+$/,y={},z=y.toString,A={},B,C,D=h.createElement("div");return A.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=D).appendChild(a),d=~A.qsa(e,b).indexOf(a),f&&D.removeChild(a),d},B=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},C=function(a){return g.call(a,function(b,c){return a.indexOf(b)==c})},A.fragment=function(b,d,e){b.replace&&(b=b.replace(n,"<$1>")),d===a&&(d=m.test(b)&&RegExp.$1),d in t||(d="*");var g,h,i=t[d];return i.innerHTML=""+b,h=c.each(f.call(i.childNodes),function(){i.removeChild(this)}),J(e)&&(g=c(h),c.each(e,function(a,b){p.indexOf(a)>-1?g[a](b):g.attr(a,b)})),h},A.Z=function(a,b){return a=a||[],a.__proto__=c.fn,a.selector=b||"",a},A.isZ=function(a){return a instanceof A.Z},A.init=function(b,d){if(!b)return A.Z();if(F(b))return c(h).ready(b);if(A.isZ(b))return b;var e;if(K(b))e=M(b);else if(I(b))e=[J(b)?c.extend({},b):b],b=null;else if(m.test(b))e=A.fragment(b.trim(),RegExp.$1,d),b=null;else{if(d!==a)return c(d).find(b);e=A.qsa(h,b)}return A.Z(e,b)},c=function(a,b){return A.init(a,b)},c.extend=function(a){var b,c=f.call(arguments,1);return typeof a=="boolean"&&(b=a,a=c.shift()),c.forEach(function(c){T(a,c,b)}),a},A.qsa=function(a,b){var c;return H(a)&&w.test(b)?(c=a.getElementById(RegExp.$1))?[c]:[]:a.nodeType!==1&&a.nodeType!==9?[]:f.call(v.test(b)?a.getElementsByClassName(RegExp.$1):x.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.contains=function(a,b){return a!==b&&a.contains(b)},c.type=E,c.isFunction=F,c.isWindow=G,c.isArray=K,c.isPlainObject=J,c.isEmptyObject=function(a){var b;for(b in a)return!1;return!0},c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.camelCase=B,c.trim=function(a){return a.trim()},c.uuid=0,c.support={},c.expr={},c.map=function(a,b){var c,d=[],e,f;if(L(a))for(e=0;e=0?b:b+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){this.parentNode!=null&&this.parentNode.removeChild(this)})},each:function(a){return e.every.call(this,function(b,c){return a.call(b,c,b)!==!1}),this},filter:function(a){return F(a)?this.not(this.not(a)):c(g.call(this,function(b){return A.matches(b,a)}))},add:function(a,b){return c(C(this.concat(c(a,b))))},is:function(a){return this.length>0&&A.matches(this[0],a)},not:function(b){var d=[];if(F(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):L(b)&&F(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},has:function(a){return this.filter(function(){return I(a)?c.contains(this,a):c(this).find(a).size()})},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!I(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!I(a)?a:c(a)},find:function(a){var b,d=this;return typeof a=="object"?b=c(a).filter(function(){var a=this;return e.some.call(d,function(b){return c.contains(b,a)})}):this.length==1?b=c(A.qsa(this[0],a)):b=this.map(function(){return A.qsa(this,a)}),b},closest:function(a,b){var d=this[0],e=!1;typeof a=="object"&&(e=c(a));while(d&&!(e?e.indexOf(d)>=0:A.matches(d,a)))d=d!==b&&!H(d)&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&!H(a)&&b.indexOf(a)<0)return b.push(a),a});return U(b,a)},parent:function(a){return U(C(this.pluck("parentNode")),a)},children:function(a){return U(this.map(function(){return S(this)}),a)},contents:function(){return this.map(function(){return f.call(this.childNodes)})},siblings:function(a){return U(this.map(function(a,b){return g.call(S(b.parentNode),function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return c.map(this,function(b){return b[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),k(this,"").getPropertyValue("display")=="none"&&(this.style.display=R(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){var b=F(a);if(this[0]&&!b)var d=c(a).get(0),e=d.parentNode||this.length>1;return this.each(function(f){c(this).wrapAll(b?a.call(this,f):e?d.cloneNode(!0):d)})},wrapAll:function(a){if(this[0]){c(this[0]).before(a=c(a));var b;while((b=a.children()).length)a=b.first();c(a).append(this)}return this},wrapInner:function(a){var b=F(a);return this.each(function(d){var e=c(this),f=e.contents(),g=b?a.call(this,d):a;f.length?f.wrapAll(g):e.append(g)})},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(b){return this.each(function(){var d=c(this);(b===a?d.css("display")=="none":b)?d.show():d.hide()})},prev:function(a){return c(this.pluck("previousElementSibling")).filter(a||"*")},next:function(a){return c(this.pluck("nextElementSibling")).filter(a||"*")},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(V(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(I(c))for(b in c)W(this,b,c[b]);else W(this,c,V(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&W(this,a)})},prop:function(b,c){return c===a?this[0]&&this[0][b]:this.each(function(a){this[b]=V(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+O(b),c);return d!==null?Y(d):a},val:function(b){return b===a?this[0]&&(this[0].multiple?c(this[0]).find("option").filter(function(a){return this.selected}).pluck("value"):this[0].value):this.each(function(a){this.value=V(this,b,a,this.value)})},offset:function(a){if(a)return this.each(function(b){var d=c(this),e=V(this,a,b,d.offset()),f=d.offsetParent().offset(),g={top:e.top-f.top,left:e.left-f.left};d.css("position")=="static"&&(g.position="relative"),d.css(g)});if(this.length==0)return null;var b=this[0].getBoundingClientRect();return{left:b.left+window.pageXOffset,top:b.top+window.pageYOffset,width:Math.round(b.width),height:Math.round(b.height)}},css:function(a,c){if(arguments.length<2&&typeof a=="string")return this[0]&&(this[0].style[B(a)]||k(this[0],"").getPropertyValue(a));var d="";if(E(a)=="string")!c&&c!==0?this.each(function(){this.style.removeProperty(O(a))}):d=O(a)+":"+Q(a,c);else for(b in a)!a[b]&&a[b]!==0?this.each(function(){this.style.removeProperty(O(b))}):d+=O(b)+":"+Q(b,a[b])+";";return this.each(function(){this.style.cssText+=";"+d})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return e.some.call(this,function(a){return this.test(X(a))},P(a))},addClass:function(a){return this.each(function(b){d=[];var e=X(this),f=V(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&X(this,e+(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return X(this,"");d=X(this),V(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(P(a)," ")}),X(this,d.trim())})},toggleClass:function(b,d){return this.each(function(e){var f=c(this),g=V(this,b,e,X(this));g.split(/\s+/g).forEach(function(b){(d===a?!f.hasClass(b):d)?f.addClass(b):f.removeClass(b)})})},scrollTop:function(){if(!this.length)return;return"scrollTop"in this[0]?this[0].scrollTop:this[0].scrollY},position:function(){if(!this.length)return;var a=this[0],b=this.offsetParent(),d=this.offset(),e=o.test(b[0].nodeName)?{top:0,left:0}:b.offset();return d.top-=parseFloat(c(a).css("margin-top"))||0,d.left-=parseFloat(c(a).css("margin-left"))||0,e.top+=parseFloat(c(b[0]).css("border-top-width"))||0,e.left+=parseFloat(c(b[0]).css("border-left-width"))||0,{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||h.body;while(a&&!o.test(a.nodeName)&&c(a).css("position")=="static")a=a.offsetParent;return a})}},c.fn.detach=c.fn.remove,["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=this[0],g=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?G(f)?f["inner"+g]:H(f)?f.documentElement["offset"+g]:(e=this.offset())&&e[b]:this.each(function(a){f=c(this),f.css(b,V(this,d,a,f[b]()))})}}),q.forEach(function(a,b){var d=b%2;c.fn[a]=function(){var a,e=c.map(arguments,function(b){return a=E(b),a=="object"||a=="array"||b==null?b:A.fragment(b)}),f,g=this.length>1;return e.length<1?this:this.each(function(a,h){f=d?h:h.parentNode,h=b==0?h.nextSibling:b==1?h.firstChild:b==2?h:null,e.forEach(function(a){if(g)a=a.cloneNode(!0);else if(!f)return c(a).remove();Z(f.insertBefore(a,h),function(a){a.nodeName!=null&&a.nodeName.toUpperCase()==="SCRIPT"&&(!a.type||a.type==="text/javascript")&&!a.src&&window.eval.call(window,a.innerHTML)})})})},c.fn[d?a+"To":"insert"+(b?"Before":"After")]=function(b){return c(b)[a](this),this}}),A.Z.prototype=c.fn,A.uniq=C,A.deserializeValue=Y,c.zepto=A,c}();window.Zepto=Zepto,"$"in window||(window.$=Zepto),function(a){function b(a){var b=this.os={},c=this.browser={},d=a.match(/WebKit\/([\d.]+)/),e=a.match(/(Android)\s+([\d.]+)/),f=a.match(/(iPad).*OS\s([\d_]+)/),g=!f&&a.match(/(iPhone\sOS)\s([\d_]+)/),h=a.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),i=h&&a.match(/TouchPad/),j=a.match(/Kindle\/([\d.]+)/),k=a.match(/Silk\/([\d._]+)/),l=a.match(/(BlackBerry).*Version\/([\d.]+)/),m=a.match(/(BB10).*Version\/([\d.]+)/),n=a.match(/(RIM\sTablet\sOS)\s([\d.]+)/),o=a.match(/PlayBook/),p=a.match(/Chrome\/([\d.]+)/)||a.match(/CriOS\/([\d.]+)/),q=a.match(/Firefox\/([\d.]+)/);if(c.webkit=!!d)c.version=d[1];e&&(b.android=!0,b.version=e[2]),g&&(b.ios=b.iphone=!0,b.version=g[2].replace(/_/g,".")),f&&(b.ios=b.ipad=!0,b.version=f[2].replace(/_/g,".")),h&&(b.webos=!0,b.version=h[2]),i&&(b.touchpad=!0),l&&(b.blackberry=!0,b.version=l[2]),m&&(b.bb10=!0,b.version=m[2]),n&&(b.rimtabletos=!0,b.version=n[2]),o&&(c.playbook=!0),j&&(b.kindle=!0,b.version=j[1]),k&&(c.silk=!0,c.version=k[1]),!k&&b.android&&a.match(/Kindle Fire/)&&(c.silk=!0),p&&(c.chrome=!0,c.version=p[1]),q&&(c.firefox=!0,c.version=q[1]),b.tablet=!!(f||o||e&&!a.match(/Mobile/)||q&&a.match(/Tablet/)),b.phone=!b.tablet&&!!(e||g||h||l||m||p&&a.match(/Android/)||p&&a.match(/CriOS\/([\d.]+)/)||q&&a.match(/Mobile/))}b.call(a,navigator.userAgent),a.__detect=b}(Zepto),function(a){function g(a){return a._zid||(a._zid=d++)}function h(a,b,d,e){b=i(b);if(b.ns)var f=j(b.ns);return(c[g(a)]||[]).filter(function(a){return a&&(!b.e||a.e==b.e)&&(!b.ns||f.test(a.ns))&&(!d||g(a.fn)===g(d))&&(!e||a.sel==e)})}function i(a){var b=(""+a).split(".");return{e:b[0],ns:b.slice(1).sort().join(" ")}}function j(a){return new RegExp("(?:^| )"+a.replace(" "," .* ?")+"(?: |$)")}function k(b,c,d){a.type(b)!="string"?a.each(b,d):b.split(/\s/).forEach(function(a){d(a,c)})}function l(a,b){return a.del&&(a.e=="focus"||a.e=="blur")||!!b}function m(a){return f[a]||a}function n(b,d,e,h,j,n){var o=g(b),p=c[o]||(c[o]=[]);k(d,e,function(c,d){var e=i(c);e.fn=d,e.sel=h,e.e in f&&(d=function(b){var c=b.relatedTarget;if(!c||c!==this&&!a.contains(this,c))return e.fn.apply(this,arguments)}),e.del=j&&j(d,c);var g=e.del||d;e.proxy=function(a){var c=g.apply(b,[a].concat(a.data));return c===!1&&(a.preventDefault(),a.stopPropagation()),c},e.i=p.length,p.push(e),b.addEventListener(m(e.e),e.proxy,l(e,n))})}function o(a,b,d,e,f){var i=g(a);k(b||"",d,function(b,d){h(a,b,d,e).forEach(function(b){delete c[i][b.i],a.removeEventListener(m(b.e),b.proxy,l(b,f))})})}function t(b){var c,d={originalEvent:b};for(c in b)!r.test(c)&&b[c]!==undefined&&(d[c]=b[c]);return a.each(s,function(a,c){d[a]=function(){return this[c]=p,b[a].apply(b,arguments)},d[c]=q}),d}function u(a){if(!("defaultPrevented"in a)){a.defaultPrevented=!1;var b=a.preventDefault;a.preventDefault=function(){this.defaultPrevented=!0,b.call(this)}}}var b=a.zepto.qsa,c={},d=1,e={},f={mouseenter:"mouseover",mouseleave:"mouseout"};e.click=e.mousedown=e.mouseup=e.mousemove="MouseEvents",a.event={add:n,remove:o},a.proxy=function(b,c){if(a.isFunction(b)){var d=function(){return b.apply(c,arguments)};return d._zid=g(b),d}if(typeof c=="string")return a.proxy(b[c],b);throw new TypeError("expected function")},a.fn.bind=function(a,b){return this.each(function(){n(this,a,b)})},a.fn.unbind=function(a,b){return this.each(function(){o(this,a,b)})},a.fn.one=function(a,b){return this.each(function(c,d){n(this,a,b,null,function(a,b){return function(){var c=a.apply(d,arguments);return o(d,b,a),c}})})};var p=function(){return!0},q=function(){return!1},r=/^([A-Z]|layer[XY]$)/,s={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};a.fn.delegate=function(b,c,d){return this.each(function(e,f){n(f,c,d,b,function(c){return function(d){var e,g=a(d.target).closest(b,f).get(0);if(g)return e=a.extend(t(d),{currentTarget:g,liveFired:f}),c.apply(g,[e].concat([].slice.call(arguments,1)))}})})},a.fn.undelegate=function(a,b,c){return this.each(function(){o(this,b,c,a)})},a.fn.live=function(b,c){return a(document.body).delegate(this.selector,b,c),this},a.fn.die=function(b,c){return a(document.body).undelegate(this.selector,b,c),this},a.fn.on=function(b,c,d){return!c||a.isFunction(c)?this.bind(b,c||d):this.delegate(c,b,d)},a.fn.off=function(b,c,d){return!c||a.isFunction(c)?this.unbind(b,c||d):this.undelegate(c,b,d)},a.fn.trigger=function(b,c){if(typeof b=="string"||a.isPlainObject(b))b=a.Event(b);return u(b),b.data=c,this.each(function(){"dispatchEvent"in this&&this.dispatchEvent(b)})},a.fn.triggerHandler=function(b,c){var d,e;return this.each(function(f,g){d=t(typeof b=="string"?a.Event(b):b),d.data=c,d.target=g,a.each(h(g,b.type||b),function(a,b){e=b.proxy(d);if(d.isImmediatePropagationStopped())return!1})}),e},"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.trigger(b)}}),["focus","blur"].forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.each(function(){try{this[b]()}catch(a){}}),this}}),a.Event=function(a,b){typeof a!="string"&&(b=a,a=b.type);var c=document.createEvent(e[a]||"Events"),d=!0;if(b)for(var f in b)f=="bubbles"?d=!!b[f]:c[f]=b[f];return c.initEvent(a,d,!0,null,null,null,null,null,null,null,null,null,null,null,null),c.isDefaultPrevented=function(){return this.defaultPrevented},c}}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a=a.split(";",2)[0]),a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){a.processData&&a.data&&$.type(a.data)!="string"&&(a.data=$.param(a.data,a.traditional)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function parseArguments(a,b,c,d){var e=!$.isFunction(b);return{url:a,data:e?b:undefined,success:e?$.isFunction(c)?c:undefined:b,dataType:e?d||c:c}}function serialize(a,b,c,d){var e,f=$.isArray(b);$.each(b,function(b,g){e=$.type(g),d&&(b=c?d:d+"["+(f?"":b)+"]"),!d&&f?a.add(g.name,g.value):e=="array"||!c&&e=="object"?serialize(a,g,c,b):a.add(b,g)})}var jsonpID=0,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){if("type"in a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){clearTimeout(g),$(c).remove(),delete window[b]},e=function(c){d();if(!c||c=="timeout")window[b]=empty;ajaxError(null,c||"abort",f,a)},f={abort:e},g;return ajaxBeforeSend(f,a)===!1?(e("abort"),!1):(window[b]=function(b){d(),ajaxSuccess(b,f,a)},c.onerror=function(){e("error")},c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(g=setTimeout(function(){e("timeout")},a.timeout)),f)}return $.ajax(a)},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host),settings.url||(settings.url=window.location.toString()),serializeData(settings),settings.cache===!1&&(settings.url=appendQuery(settings.url,"_="+Date.now()));var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=settings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.contentType!==!1&&settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){xhr.onreadystatechange=empty,clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:$.parseJSON(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,xhr.status?"error":"abort",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b,c,d){return $.ajax(parseArguments.apply(null,arguments))},$.post=function(a,b,c,d){var e=parseArguments.apply(null,arguments);return e.type="POST",$.ajax(e)},$.getJSON=function(a,b,c){var d=parseArguments.apply(null,arguments);return d.dataType="json",$.ajax(d)},$.fn.load=function(a,b,c){if(!this.length)return this;var d=this,e=a.split(/\s/),f,g=parseArguments(a,b,c),h=g.success;return e.length>1&&(g.url=e[0],f=e[1]),g.success=function(a){d.html(f?$("
").html(a.replace(rscript,"")).find(f):a),h&&h.apply(d,arguments)},$.ajax(g),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace(/%20/g,"+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a,b){function s(a){return t(a.replace(/([a-z])([A-Z])/,"$1-$2"))}function t(a){return a.toLowerCase()}function u(a){return d?d+a:t(a)}var c="",d,e,f,g={Webkit:"webkit",Moz:"",O:"o",ms:"MS"},h=window.document,i=h.createElement("div"),j=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,k,l,m,n,o,p,q,r={};a.each(g,function(a,e){if(i.style[a+"TransitionProperty"]!==b)return c="-"+t(a)+"-",d=e,!1}),k=c+"transform",r[l=c+"transition-property"]=r[m=c+"transition-duration"]=r[n=c+"transition-timing-function"]=r[o=c+"animation-name"]=r[p=c+"animation-duration"]=r[q=c+"animation-timing-function"]="",a.fx={off:d===b&&i.style.transitionProperty===b,speeds:{_default:400,fast:200,slow:600},cssPrefix:c,transitionEnd:u("TransitionEnd"),animationEnd:u("AnimationEnd")},a.fn.animate=function(b,c,d,e){return a.isPlainObject(c)&&(d=c.easing,e=c.complete,c=c.duration),c&&(c=(typeof c=="number"?c:a.fx.speeds[c]||a.fx.speeds._default)/1e3),this.anim(b,c,d,e)},a.fn.anim=function(c,d,e,f){var g,h={},i,t="",u=this,v,w=a.fx.transitionEnd;d===b&&(d=.4),a.fx.off&&(d=0);if(typeof c=="string")h[o]=c,h[p]=d+"s",h[q]=e||"linear",w=a.fx.animationEnd;else{i=[];for(g in c)j.test(g)?t+=g+"("+c[g]+") ":(h[g]=c[g],i.push(s(g)));t&&(h[k]=t,i.push(k)),d>0&&typeof c=="object"&&(h[l]=i.join(", "),h[m]=d+"s",h[n]=e||"linear")}return v=function(b){if(typeof b!="undefined"){if(b.target!==b.currentTarget)return;a(b.target).unbind(w,v)}a(this).css(r),f&&f.call(this)},d>0&&this.bind(w,v),this.size()&&this.get(0).clientLeft,this.css(h),d<=0&&setTimeout(function(){u.each(function(){v.call(this)})},0),this},i=null}(Zepto) -------------------------------------------------------------------------------- /min/transition.min.css: -------------------------------------------------------------------------------- 1 | div.ui-page{position:absolute;width:100%;height:100%;left:0;top:0;}.spin{-webkit-transform:rotate(360deg);-webkit-animation-name:spin;-webkit-animation-duration:1s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-transform:rotate(360deg);-moz-animation-name:spin;-moz-animation-duration:1s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear;} 2 | @-webkit-keyframes spin{from{-webkit-transform:rotate(0deg);}to{-webkit-transform:rotate(360deg);} 3 | }@-moz-keyframes spin{from{-moz-transform:rotate(0deg);}to{-moz-transform:rotate(360deg);} 4 | }.in,.out{-webkit-animation-timing-function:ease-in-out;-webkit-animation-duration:705ms;-moz-animation-timing-function:ease-in-out;-moz-animation-duration:705ms;} 5 | .slide.out{-webkit-transform:translate3d(-100%,0,0);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;} 6 | .slide.in{-webkit-transform:translate3d(0,0,0);-webkit-animation-name:slideinfromright;-moz-transform:translateX(0);-moz-animation-name:slideinfromright;} 7 | .slide.out.reverse{-webkit-transform:translate3d(100%,0,0);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;} 8 | .slide.in.reverse{-webkit-transform:translate3d(0,0,0);-webkit-animation-name:slideinfromleft;-moz-transform:translateX(0);-moz-animation-name:slideinfromleft;} 9 | .slideup.out{-webkit-animation-name:dontmove;-moz-animation-name:dontmove;z-index:0;} 10 | .slideup.in{-webkit-transform:translate3d(0,0,0);-webkit-animation-name:slideinfrombottom;-moz-transform:translateY(0);-moz-animation-name:slideinfrombottom;z-index:10;} 11 | .slideup.in.reverse{z-index:0;-webkit-animation-name:dontmove;-moz-animation-name:dontmove;} 12 | .slideup.out.reverse{-webkit-transform:translate3d(0,100%,0);z-index:10;-webkit-animation-name:slideouttobottom;-moz-transform:translateY(100%);-moz-animation-name:slideouttobottom;} 13 | .slidedown.out{-webkit-animation-name:dontmove;-moz-animation-name:dontmove;z-index:0;} 14 | .slidedown.in{-webkit-transform:translate3d(0,0,0);-webkit-animation-name:slideinfromtop;-moz-transform:translateY(0);-moz-animation-name:slideinfromtop;z-index:10;} 15 | .slidedown.in.reverse{z-index:0;-webkit-animation-name:dontmove;-moz-animation-name:dontmove;} 16 | .slidedown.out.reverse{-webkit-transform:translate3d(0,-100%,0);-moz-transform:translateY(-100%);z-index:10;-webkit-animation-name:slideouttotop;-moz-animation-name:slideouttotop;} 17 | @-webkit-keyframes slideinfromright{from{-webkit-transform:translate3d(100%,0,0);} 18 | to{-webkit-transform:translate3d(0,0,0);}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translate3d(-100%,0,0);} 19 | to{-webkit-transform:translate3d(0,0,0);}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translate3d(0,0,0);} 20 | to{-webkit-transform:translate3d(-100%,0,0);}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translate3d(0,0,0);} 21 | to{-webkit-transform:translate3d(100%,0,0);}}@-webkit-keyframes slideinfromtop{from{-webkit-transform:translate3d(0,-100%,0);} 22 | to{-webkit-transform:translate3d(0,0,0);}}@-webkit-keyframes slideinfrombottom{from{-webkit-transform:translate3d(0,100%,0);} 23 | to{-webkit-transform:translate3d(0,0,0);}}@-webkit-keyframes slideouttobottom{from{-webkit-transform:translate3d(0,0,0);} 24 | to{-webkit-transform:translate3d(0,100%,0);}}@-webkit-keyframes slideouttotop{from{-webkit-transform:translate3d(0,0,0);} 25 | to{-webkit-transform:translate3d(0,-100%,0);}}@-webkit-keyframes fadein{from{opacity:0;} 26 | to{opacity:1;}}@-webkit-keyframes fadeout{from{opacity:1;}to{opacity:0;}}@-moz-keyframes slideinfromright{from{-moz-transform:translateX(100%);} 27 | to{-moz-transform:translateX(0);}}@-moz-keyframes slideinfromleft{from{-moz-transform:translateX(-100%);} 28 | to{-moz-transform:translateX(0);}}@-moz-keyframes slideouttoleft{from{-moz-transform:translateX(0);} 29 | to{-moz-transform:translateX(-100%);}}@-moz-keyframes slideouttoright{from{-moz-transform:translateX(0);} 30 | to{-moz-transform:translateX(100%);}}@-moz-keyframes slideinfromtop{from{-moz-transform:translateY(-100%);} 31 | to{-moz-transform:translateY(0);}}@-moz-keyframes slideinfrombottom{from{-moz-transform:translateY(100%);} 32 | to{-moz-transform:translateY(0);}}@-moz-keyframes slideouttobottom{from{-moz-transform:translateY(0);} 33 | to{-moz-transform:translateY(100%);}}@-moz-keyframes slideouttotop{from{-moz-transform:translateY(0);} 34 | to{-moz-transform:translateY(-100%);}}@-moz-keyframes fadein{from{opacity:0;}to{opacity:1;} 35 | }@-moz-keyframes fadeout{from{opacity:1;}to{opacity:0;}}.fade.out{z-index:0;-webkit-animation-name:fadeout;-moz-animation-name:fadeout;} 36 | .fade.in{opacity:1;z-index:10;-webkit-animation-name:fadein;-moz-animation-name:fadein;} 37 | .viewport-flip{-webkit-perspective:1000;-moz-perspective:1000;position:absolute;} 38 | .ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden;} 39 | .flip{-webkit-animation-duration:.65s;-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-moz-animation-duration:.65s;-moz-backface-visibility:hidden;-moz-transform:translateX(0);} 40 | .flip.out{-webkit-transform:rotateY(-180deg) scale(.8);-webkit-animation-name:flipouttoleft;-moz-transform:rotateY(-180deg) scale(.8);-moz-animation-name:flipouttoleft;} 41 | .flip.in{-webkit-transform:rotateY(0) scale(1);-webkit-animation-name:flipinfromleft;-moz-transform:rotateY(0) scale(1);-moz-animation-name:flipinfromleft;} 42 | .flip.out.reverse{-webkit-transform:rotateY(180deg) scale(.8);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(180deg) scale(.8);-moz-animation-name:flipouttoright;} 43 | .flip.in.reverse{-webkit-transform:rotateY(0) scale(1);-webkit-animation-name:flipinfromright;-moz-transform:rotateY(0) scale(1);-moz-animation-name:flipinfromright;} 44 | @-webkit-keyframes flipinfromright{from{-webkit-transform:rotateY(-180deg) scale(.8);} 45 | to{-webkit-transform:rotateY(0) scale(1);}}@-webkit-keyframes flipinfromleft{from{-webkit-transform:rotateY(180deg) scale(.8);} 46 | to{-webkit-transform:rotateY(0) scale(1);}}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0) scale(1);} 47 | to{-webkit-transform:rotateY(-180deg) scale(.8);}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0) scale(1);} 48 | to{-webkit-transform:rotateY(180deg) scale(.8);}}@-moz-keyframes flipinfromright{from{-moz-transform:rotateY(-180deg) scale(.8);} 49 | to{-moz-transform:rotateY(0) scale(1);}}@-moz-keyframes flipinfromleft{from{-moz-transform:rotateY(180deg) scale(.8);} 50 | to{-moz-transform:rotateY(0) scale(1);}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0) scale(1);} 51 | to{-moz-transform:rotateY(-180deg) scale(.8);}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0) scale(1);} 52 | to{-moz-transform:rotateY(180deg) scale(.8);}}@-webkit-keyframes dontmove{from{opacity:1;} 53 | to{opacity:1;}}@-moz-keyframes dontmove{from{opacity:1;}to{opacity:1;}}.pop{-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%;} 54 | .pop.in{-webkit-transform:scale(1);opacity:1;-webkit-animation-name:popin;z-index:10;-moz-transform:scale(1);-moz-animation-name:popin;} 55 | .pop.in.reverse{z-index:0;-webkit-animation-name:dontmove;-moz-animation-name:dontmove;} 56 | .pop.out.reverse{-webkit-transform:scale(.2);opacity:0;-webkit-animation-name:popout;z-index:10;-moz-transform:scale(.2);-moz-animation-name:popout;} 57 | @-webkit-keyframes popin{from{-webkit-transform:scale(.2);-moz-transform:scale(.2);opacity:0;} 58 | to{-webkit-transform:scale(1);-moz-transform:scale(1);opacity:1;}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);-moz-transform:scale(1);opacity:1;} 59 | to{-webkit-transform:scale(.2);-moz-transform:scale(.2);opacity:0;}} -------------------------------------------------------------------------------- /min/transition.min.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){$(document.body).transition("init").show()}),function(a){function l(a){var b=a.indexOf("?");return b>0&&(a=a.slice(0,b)),a.replace(/[:\.\+\/]/g,"_")}function m(a){if(window.location.hash){var b=n(window.location.pathname,window.location.hash.slice(1));b.length&&(a=a.replace(/(\b(src|href|action))="([^"#:]+)"/gi,'$1="'+b+'$3"'),a=a.replace(/(\b(src|href|action))="(.+\/)?[^\/]+\/\.\.\//gi,'$1="$3'))}return a}function n(a,b){var c="",d=b.lastIndexOf("/");if(-1!=d&&(c=b.slice(0,d+1),"/"==c.charAt(0))){"/"==!a.charAt(0)&&(a="/"+a);var e=1;d=e;do d=c.indexOf("/",d)+1,d>e&&c.slice(0,d)==a.slice(0,d)&&(e=d);while(d>0&&d==e);var f="";d=e;do d=a.indexOf("/",d+1),-1!=d&&(f+="../");while(-1!=d);c=f+c.slice(e)}return c}var b=0,c=!1,d=null,e={},f=window.location.href,g={},h=null,i=[],j=0,k={options:function(b){d=a.extend({defaultPageTransition:"fade",domCache:!1},b)},init:function(k,m,n){c||(c=!0,a(document.body).transition("options",{}),a(window).on("hashchange",function(){var c=h&&h.element||a(document.body);if(!g[window.location.hash]){var e=window.location.hash,f=a("div.ui-page-active").attr("id");f&&(f="#"+f),h&&h.element&&h.element.is("form")&&(e={type:h.element.attr("method")||"get",url:window.location.hash.slice(1),data:h.element.serialize(),dataType:"html",global:!1});var k=null,l=null==h,m=0;if(l)i.length>j&&i[j].to==e?(h=i[j++],l=!1):j>0&&(h=i[--j],l=h?!h.reverse:!0),k=h?h.transition:d.defaultPageTransition,h&&(m=h.top||0,!e&&a(h.from).length&&(e=h.from));else if(h.transition)k=h.transition,i[j++]={to:e,from:f,transition:k,top:a(window).scrollTop()},l=h.reverse;else{k=h.element.attr("transition")||h.element.data("transition")||d.defaultPageTransition;var n=h.element.attr("direction")||h.element.data("direction");"reverse"===n&&(l=!0),i[j++]={to:e,from:f,transition:k,reverse:l,top:a(window).scrollTop()}}c.transition("changePage",e,k,l,m)}h=null}));var o=a('div[data-role="page"]',this);o.length||(this.is("div")?(this.attr("data-role","page"),this.attr("id","_trans_div"+b),o=this):(o=a('
'),this.children().wrapAll(o))),k&&o.trigger("pageload",k);var p=o.first();if(window.location.hash&&(p=a(l(window.location.hash)),!p.length)){p=o.first();var q=p.attr("id"),r=l(e[window.location.hash]||window.location.hash.slice(1));p.attr("id",r),q&&(a('[data-href="#'+q+'"]',o).attr("data-href","#"+r),a('[href="#'+q+'"]',o).attr("href","#"+r))}o.addClass("ui-page"),o.each(function(){a(this).attr("id")||a(this).attr("id","_trans_div"+b),e["#"+a(this).attr("id")]=f,a(this).css("zIndex",b++)}),a("a[href]",o).not("[target]").not('[rel="external"]').not('[data-ajax="false"]').not("[data-href]").transition("hijackLinks"),a("[data-href]",o).transition("hijackLinks"),a("form").not("[target]").not('[data-ajax="false"]').transition("hijackLinks"),n||(n=document.title),o.not("[data-title]").data("title",n),n=p.data("title"),n&&(document.title=n),o.hide();var s=m?a(m):null;return s=s||p,s.addClass("ui-page-active"),o.each(function(){a(this).trigger("pageinit",a(this))}),s},to:function(a,b,c){b=b||d.defaultPageTransition,c||(c=!1),h={transition:b,reverse:c},window.location.hash="#"+a},hijackLinks:function(){return this.each(function(){var b=a(this);if("back"==b.data("rel")){var c=function(a){window.history.back(),a.preventDefault()};return b.on("click",c),b.on("tap",c),void 0}var d=b.attr("data-href")||b.attr("href")||b.attr("action")||"#";if("#"===d.charAt(0)){if(a('a[name="'+d.slice(1)+'"]').length)return g[d]=!0,void 0}else d="#"+d,b.is("a")?b.attr("href",d):b.attr("action")&&b.attr("action",d),b.attr("data-href")&&b.attr("data-href",d);var c;b.is("a")?c=function(){h={element:b}}:b.is("form")?(c=function(a){h={element:b},window.location.href=d,a.preventDefault()},b.on("submit",c)):c=function(){h={element:b},window.location.href=d},b.is("form")||(b.on("click",c),b.on("tap",c))})},changePage:function(b,c,f,g){var h={toPage:b,back:f},i=a.Event("pagebeforechange");if(a(this).trigger(i,h),!i.defaultPrevented){b=h.toPage,f=h.back;var j="string"==typeof b?b:b.url,k=null,m=a("div.ui-page-active"),n=!1;if("string"==typeof b&&"#"===b.charAt(0)){var o=a(l(b));o.length?(a(this).transition("perform",m,o,c,f,g,h),n=!0):!d.domCache&&e[b]?(k=b,b=e[b]):b=b.slice(1)}if(!n){var p={href:j,element:a(this),back:f},i=a.Event("pagebeforeload");a(this).trigger(i,p);var q=a(this);i.defaultPrevented||(a(this).transition("load",b,p,function(b,d,e){var i=a('
');i.html(b),a(document.body).append(i);var j=a(i).transition("init",p,k,e);a(q).transition("perform",m,j,c,f,g,h)}),n=!0)}n||a(this).trigger("pagechangefailed",h)}},load:function(b,c,e){b="string"==typeof b?{url:b,dataType:"html",global:!1}:b,b.url||(b.url=window.location.href),b.success=function(g,h,i){c.xhr=i,c.textStatus=h,f=b.url,d.domCache||a('div[data-role="page"]').not('[data-dom-cache="true"]').addClass("transition-recyclable");var n,j=g.search(/",j),bodyEnd=g.search(/<\/body>/i),l=g.slice(j+1,bodyEnd));var o=k.match(/(.+)<\/title>/im);o&&(n=o[1]),l=m(l),e(l,g,n)},b.error=function(d,e,f){c.xhr=d,c.textStatus=e,c.errorThrown=f,a(this).trigger("pageloadfailed",c),a(this).trigger("pagechangefailed",{toPage:b.url})},a.ajax(b)},perform:function(b,c,e,f,g,h){h.from=b,h.to=c,b.trigger("pagebeforehide",b),c.trigger("pagebeforeshow",c),window.setTimeout(function(){b.addClass(e+" out"),b.removeClass("ui-page-active");var a=c.position();c.css({top:a.top-g}),c.show(),c.addClass(e+" in"),c.addClass("ui-page-active"),f&&(b.addClass("reverse"),c.addClass("reverse"))},1),window.setTimeout(function(){b.removeClass(e+" out"),c.removeClass(e+" in"),b.removeClass("reverse"),c.removeClass("reverse"),c.css({top:0}),window.scrollTo(0,g);var f=c.data("title");f&&(document.title=f),b.trigger("pagehide",b),c.trigger("pageshow",c),a(document).trigger("pagechange",h),a('div[data-role="page"]').hide(),c.show(),d.domCache||(a("div.transition-recyclable").each(function(){var b=a.Event("pageremove");a(this).trigger(b,a(this)),b.defaultPrevented||a(this).remove()}),a('div[data-role="page-container"]').not(function(){return a(this).children().length}).remove())},707)}};a.fn.transition=function(a){if(k[a])return k[a].apply(this,Array.prototype.slice.call(arguments,1));if("object"!=typeof a&&a)throw"Method "+a+" does not exist";return k.to.apply(this,arguments)}}(Zepto); -------------------------------------------------------------------------------- /src/transition.css: -------------------------------------------------------------------------------- 1 | 2 | div.ui-page { 3 | position: absolute; 4 | width: 100%; 5 | height: 100%; 6 | left: 0px; 7 | top: 0px; 8 | } 9 | 10 | /* 11 | * css Extracted from jQuery Mobile Framework 12 | * Copyright (c) jQuery Project 13 | */ 14 | .spin { 15 | -webkit-transform: rotate(360deg); 16 | -webkit-animation-name: spin; 17 | -webkit-animation-duration: 1s; 18 | -webkit-animation-iteration-count: infinite; 19 | -webkit-animation-timing-function: linear; 20 | -moz-transform: rotate(360deg); 21 | -moz-animation-name: spin; 22 | -moz-animation-duration: 1s; 23 | -moz-animation-iteration-count: infinite; 24 | -moz-animation-timing-function: linear; 25 | transform: rotate(360deg); 26 | animation-name: spin; 27 | animation-duration: 1s; 28 | animation-iteration-count: infinite; 29 | animation-timing-function: linear; 30 | } 31 | @-webkit-keyframes spin { 32 | from {-webkit-transform: rotate(0deg);} 33 | to {-webkit-transform: rotate(360deg);} 34 | } 35 | @-moz-keyframes spin { 36 | from {-moz-transform: rotate(0deg);} 37 | to {-moz-transform: rotate(360deg);} 38 | } 39 | @keyframes spin { 40 | from {transform: rotate(0deg);} 41 | to {transform: rotate(360deg);} 42 | } 43 | /* Transitions from jQtouch (with small modifications): http://www.jqtouch.com/ 44 | Built by David Kaneda and maintained by Jonathan Stark. 45 | */ 46 | .in, .out { 47 | -webkit-animation-timing-function: ease-in-out; 48 | -webkit-animation-duration: 705ms; 49 | -moz-animation-timing-function: ease-in-out; 50 | -moz-animation-duration: 705ms; 51 | animation-timing-function: ease-in-out; 52 | animation-duration: 705ms; 53 | } 54 | 55 | 56 | .slide.out { 57 | -webkit-transform: translate3d(-100%,0,0); 58 | -webkit-animation-name: slideouttoleft; 59 | -moz-transform: translateX(-100%); 60 | -moz-animation-name: slideouttoleft; 61 | transform: translateX(-100%); 62 | animation-name: slideouttoleft; 63 | } 64 | 65 | .slide.in { 66 | -webkit-transform: translate3d(0,0,0); 67 | -webkit-animation-name: slideinfromright; 68 | -moz-transform: translateX(0); 69 | -moz-animation-name: slideinfromright; 70 | transform: translateX(0); 71 | animation-name: slideinfromright; 72 | } 73 | 74 | .slide.out.reverse { 75 | -webkit-transform: translate3d(100%,0,0); 76 | -webkit-animation-name: slideouttoright; 77 | -moz-transform: translateX(100%); 78 | -moz-animation-name: slideouttoright; 79 | transform: translateX(100%); 80 | animation-name: slideouttoright; 81 | } 82 | 83 | .slide.in.reverse { 84 | -webkit-transform: translate3d(0,0,0); 85 | -webkit-animation-name: slideinfromleft; 86 | -moz-transform: translateX(0); 87 | -moz-animation-name: slideinfromleft; 88 | transform: translateX(0); 89 | animation-name: slideinfromleft; 90 | } 91 | 92 | .slideup.out { 93 | -webkit-animation-name: dontmove; 94 | -moz-animation-name: dontmove; 95 | animation-name: dontmove; 96 | z-index: 0; 97 | } 98 | 99 | .slideup.in { 100 | -webkit-transform: translate3d(0,0,0); 101 | -webkit-animation-name: slideinfrombottom; 102 | -moz-transform: translateY(0); 103 | -moz-animation-name: slideinfrombottom; 104 | transform: translateY(0); 105 | animation-name: slideinfrombottom; 106 | z-index: 10; 107 | } 108 | 109 | .slideup.in.reverse { 110 | -webkit-animation-name: dontmove; 111 | -moz-animation-name: dontmove; 112 | animation-name: dontmove; 113 | z-index: 0; 114 | } 115 | 116 | .slideup.out.reverse { 117 | -webkit-transform: translate3d(0,100%,0); 118 | -webkit-animation-name: slideouttobottom; 119 | -moz-transform: translateY(100%); 120 | -moz-animation-name: slideouttobottom; 121 | transform: translateY(100%); 122 | animation-name: slideouttobottom; 123 | z-index: 10; 124 | } 125 | 126 | .slidedown.out { 127 | -webkit-animation-name: dontmove; 128 | -moz-animation-name: dontmove; 129 | animation-name: dontmove; 130 | z-index: 0; 131 | } 132 | 133 | .slidedown.in { 134 | -webkit-transform: translate3d(0,0,0); 135 | -webkit-animation-name: slideinfromtop; 136 | -moz-transform: translateY(0); 137 | -moz-animation-name: slideinfromtop; 138 | transform: translateY(0); 139 | animation-name: slideinfromtop; 140 | z-index: 10; 141 | } 142 | 143 | .slidedown.in.reverse { 144 | -webkit-animation-name: dontmove; 145 | -moz-animation-name: dontmove; 146 | animation-name: dontmove; 147 | z-index: 0; 148 | } 149 | 150 | .slidedown.out.reverse { 151 | -webkit-transform: translate3d(0,-100%,0); 152 | -webkit-animation-name: slideouttotop; 153 | -moz-transform: translateY(-100%); 154 | -moz-animation-name: slideouttotop; 155 | transform: translateY(-100%); 156 | animation-name: slideouttotop; 157 | z-index: 10; 158 | } 159 | 160 | @-webkit-keyframes slideinfromright { 161 | from { -webkit-transform: translate3d(100%,0,0); } 162 | to { -webkit-transform: translate3d(0,0,0); } 163 | } 164 | 165 | @-webkit-keyframes slideinfromleft { 166 | from { -webkit-transform: translate3d(-100%,0,0); } 167 | to { -webkit-transform: translate3d(0,0,0); } 168 | } 169 | 170 | @-webkit-keyframes slideouttoleft { 171 | from { -webkit-transform: translate3d(0,0,0); } 172 | to { -webkit-transform: translate3d(-100%,0,0); } 173 | } 174 | 175 | @-webkit-keyframes slideouttoright { 176 | from { -webkit-transform: translate3d(0,0,0); } 177 | to { -webkit-transform: translate3d(100%,0,0); } 178 | } 179 | 180 | @-webkit-keyframes slideinfromtop { 181 | from { -webkit-transform: translate3d(0,-100%,0); } 182 | to { -webkit-transform: translate3d(0,0,0); } 183 | } 184 | 185 | @-webkit-keyframes slideinfrombottom { 186 | from { -webkit-transform: translate3d(0,100%,0); } 187 | to { -webkit-transform: translate3d(0,0,0); } 188 | } 189 | 190 | @-webkit-keyframes slideouttobottom { 191 | from { -webkit-transform: translate3d(0,0,0); } 192 | to { -webkit-transform: translate3d(0,100%,0); } 193 | } 194 | 195 | @-webkit-keyframes slideouttotop { 196 | from { -webkit-transform: translate3d(0,0,0); } 197 | to { -webkit-transform: translate3d(0,-100%,0); } 198 | } 199 | @-webkit-keyframes fadein { 200 | from { opacity: 0; } 201 | to { opacity: 1; } 202 | } 203 | 204 | @-webkit-keyframes fadeout { 205 | from { opacity: 1; } 206 | to { opacity: 0; } 207 | } 208 | 209 | @-moz-keyframes slideinfromright { 210 | from { -moz-transform: translateX(100%); } 211 | to { -moz-transform: translateX(0); } 212 | } 213 | 214 | @-moz-keyframes slideinfromleft { 215 | from { -moz-transform: translateX(-100%); } 216 | to { -moz-transform: translateX(0); } 217 | } 218 | 219 | @-moz-keyframes slideouttoleft { 220 | from { -moz-transform: translateX(0); } 221 | to { -moz-transform: translateX(-100%); } 222 | } 223 | 224 | @-moz-keyframes slideouttoright { 225 | from { -moz-transform: translateX(0); } 226 | to { -moz-transform: translateX(100%); } 227 | } 228 | 229 | @-moz-keyframes slideinfromtop { 230 | from { -moz-transform: translateY(-100%); } 231 | to { -moz-transform: translateY(0); } 232 | } 233 | 234 | @-moz-keyframes slideinfrombottom { 235 | from { -moz-transform: translateY(100%); } 236 | to { -moz-transform: translateY(0); } 237 | } 238 | @-moz-keyframes slideouttobottom { 239 | from { -moz-transform: translateY(0); } 240 | to { -moz-transform: translateY(100%); } 241 | } 242 | 243 | @-moz-keyframes slideouttotop { 244 | from { -moz-transform: translateY(0); } 245 | to { -moz-transform: translateY(-100%); } 246 | } 247 | @-moz-keyframes fadein { 248 | from { opacity: 0; } 249 | to { opacity: 1; } 250 | } 251 | 252 | @-moz-keyframes fadeout { 253 | from { opacity: 1; } 254 | to { opacity: 0; } 255 | } 256 | 257 | @keyframes slideinfromright { 258 | from { transform: translateX(100%); } 259 | to { transform: translateX(0); } 260 | } 261 | 262 | @keyframes slideinfromleft { 263 | from { transform: translateX(-100%); } 264 | to { transform: translateX(0); } 265 | } 266 | 267 | @keyframes slideouttoleft { 268 | from { transform: translateX(0); } 269 | to { transform: translateX(-100%); } 270 | } 271 | 272 | @keyframes slideouttoright { 273 | from { transform: translateX(0); } 274 | to { transform: translateX(100%); } 275 | } 276 | 277 | @keyframes slideinfromtop { 278 | from { transform: translateY(-100%); } 279 | to { transform: translateY(0); } 280 | } 281 | 282 | @keyframes slideinfrombottom { 283 | from { transform: translateY(100%); } 284 | to { transform: translateY(0); } 285 | } 286 | @keyframes slideouttobottom { 287 | from { transform: translateY(0); } 288 | to { transform: translateY(100%); } 289 | } 290 | 291 | @keyframes slideouttotop { 292 | from { transform: translateY(0); } 293 | to { transform: translateY(-100%); } 294 | } 295 | @keyframes fadein { 296 | from { opacity: 0; } 297 | to { opacity: 1; } 298 | } 299 | 300 | @keyframes fadeout { 301 | from { opacity: 1; } 302 | to { opacity: 0; } 303 | } 304 | 305 | .fade.out { 306 | -webkit-animation-name: fadeout; 307 | -moz-animation-name: fadeout; 308 | animation-name: fadeout; 309 | z-index: 0; 310 | } 311 | 312 | .fade.in { 313 | -webkit-animation-name: fadein; 314 | -moz-animation-name: fadein; 315 | animation-name: fadein; 316 | opacity: 1; 317 | z-index: 10; 318 | } 319 | 320 | /* The properties in this rule are only necessary for the 'flip' transition. 321 | * We need specify the perspective to create a projection matrix. This will add 322 | * some depth as the element flips. The depth number represents the distance of 323 | * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate 324 | * value. 325 | */ 326 | .viewport-flip { 327 | -webkit-perspective: 1000; 328 | -moz-perspective: 1000; 329 | perspective: 1000; 330 | position: absolute; 331 | } 332 | 333 | .ui-mobile-viewport-transitioning, 334 | .ui-mobile-viewport-transitioning .ui-page { 335 | width: 100%; 336 | height: 100%; 337 | overflow: hidden; 338 | } 339 | 340 | .flip { 341 | -webkit-animation-duration: .65s; 342 | -webkit-backface-visibility:hidden; 343 | -webkit-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */ 344 | -moz-animation-duration: .65s; 345 | -moz-backface-visibility:hidden; 346 | -moz-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -moz-visibility:hidden is used. */ 347 | animation-duration: .65s; 348 | backface-visibility:hidden; 349 | transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when visibility:hidden is used. */ 350 | } 351 | 352 | .flip.out { 353 | -webkit-transform: rotateY(-180deg) scale(.8); 354 | -webkit-animation-name: flipouttoleft; 355 | -moz-transform: rotateY(-180deg) scale(.8); 356 | -moz-animation-name: flipouttoleft; 357 | transform: rotateY(-180deg) scale(.8); 358 | animation-name: flipouttoleft; 359 | } 360 | 361 | .flip.in { 362 | -webkit-transform: rotateY(0) scale(1); 363 | -webkit-animation-name: flipinfromleft; 364 | -moz-transform: rotateY(0) scale(1); 365 | -moz-animation-name: flipinfromleft; 366 | transform: rotateY(0) scale(1); 367 | animation-name: flipinfromleft; 368 | } 369 | /* Shake it all about */ 370 | 371 | .flip.out.reverse { 372 | -webkit-transform: rotateY(180deg) scale(.8); 373 | -webkit-animation-name: flipouttoright; 374 | -moz-transform: rotateY(180deg) scale(.8); 375 | -moz-animation-name: flipouttoright; 376 | transform: rotateY(180deg) scale(.8); 377 | animation-name: flipouttoright; 378 | } 379 | 380 | .flip.in.reverse { 381 | -webkit-transform: rotateY(0) scale(1); 382 | -webkit-animation-name: flipinfromright; 383 | -moz-transform: rotateY(0) scale(1); 384 | -moz-animation-name: flipinfromright; 385 | transform: rotateY(0) scale(1); 386 | animation-name: flipinfromright; 387 | } 388 | 389 | @-webkit-keyframes flipinfromright { 390 | from { -webkit-transform: rotateY(-180deg) scale(.8); } 391 | to { -webkit-transform: rotateY(0) scale(1); } 392 | } 393 | 394 | @-webkit-keyframes flipinfromleft { 395 | from { -webkit-transform: rotateY(180deg) scale(.8); } 396 | to { -webkit-transform: rotateY(0) scale(1); } 397 | } 398 | 399 | @-webkit-keyframes flipouttoleft { 400 | from { -webkit-transform: rotateY(0) scale(1); } 401 | to { -webkit-transform: rotateY(-180deg) scale(.8); } 402 | } 403 | 404 | @-webkit-keyframes flipouttoright { 405 | from { -webkit-transform: rotateY(0) scale(1); } 406 | to { -webkit-transform: rotateY(180deg) scale(.8); } 407 | } 408 | @-moz-keyframes flipinfromright { 409 | from { -moz-transform: rotateY(-180deg) scale(.8); } 410 | to { -moz-transform: rotateY(0) scale(1); } 411 | } 412 | 413 | @-moz-keyframes flipinfromleft { 414 | from { -moz-transform: rotateY(180deg) scale(.8); } 415 | to { -moz-transform: rotateY(0) scale(1); } 416 | } 417 | 418 | @-moz-keyframes flipouttoleft { 419 | from { -moz-transform: rotateY(0) scale(1); } 420 | to { -moz-transform: rotateY(-180deg) scale(.8); } 421 | } 422 | 423 | @-moz-keyframes flipouttoright { 424 | from { -moz-transform: rotateY(0) scale(1); } 425 | to { -moz-transform: rotateY(180deg) scale(.8); } 426 | } 427 | 428 | @keyframes flipinfromright { 429 | from { transform: rotateY(-180deg) scale(.8); } 430 | to { transform: rotateY(0) scale(1); } 431 | } 432 | 433 | @keyframes flipinfromleft { 434 | from { transform: rotateY(180deg) scale(.8); } 435 | to { transform: rotateY(0) scale(1); } 436 | } 437 | 438 | @keyframes flipouttoleft { 439 | from { transform: rotateY(0) scale(1); } 440 | to { transform: rotateY(-180deg) scale(.8); } 441 | } 442 | 443 | @keyframes flipouttoright { 444 | from { transform: rotateY(0) scale(1); } 445 | to { transform: rotateY(180deg) scale(.8); } 446 | } 447 | 448 | /* Hackish, but reliable. */ 449 | 450 | @-webkit-keyframes dontmove { 451 | from { opacity: 1; } 452 | to { opacity: 1; } 453 | } 454 | @-moz-keyframes dontmove { 455 | from { opacity: 1; } 456 | to { opacity: 1; } 457 | } 458 | @keyframes dontmove { 459 | from { opacity: 1; } 460 | to { opacity: 1; } 461 | } 462 | 463 | .pop { 464 | -webkit-transform-origin: 50% 50%; 465 | -moz-transform-origin: 50% 50%; 466 | transform-origin: 50% 50%; 467 | } 468 | 469 | .pop.in { 470 | -webkit-transform: scale(1); 471 | -webkit-animation-name: popin; 472 | -moz-transform: scale(1); 473 | -moz-animation-name: popin; 474 | transform: scale(1); 475 | animation-name: popin; 476 | opacity: 1; 477 | z-index: 10; 478 | } 479 | 480 | .pop.in.reverse { 481 | -webkit-animation-name: dontmove; 482 | -moz-animation-name: dontmove; 483 | animation-name: dontmove; 484 | z-index: 0; 485 | } 486 | 487 | .pop.out.reverse { 488 | -webkit-transform: scale(.2); 489 | -webkit-animation-name: popout; 490 | -moz-transform: scale(.2); 491 | -moz-animation-name: popout; 492 | transform: scale(.2); 493 | animation-name: popout; 494 | opacity: 0; 495 | z-index: 10; 496 | } 497 | 498 | @-webkit-keyframes popin { 499 | from { 500 | -webkit-transform: scale(.2); 501 | -moz-transform: scale(.2); 502 | transform: scale(.2); 503 | opacity: 0; 504 | } 505 | to { 506 | -webkit-transform: scale(1); 507 | -moz-transform: scale(1); 508 | transform: scale(1); 509 | opacity: 1; 510 | } 511 | } 512 | 513 | @-webkit-keyframes popout { 514 | from { 515 | -webkit-transform: scale(1); 516 | -moz-transform: scale(1); 517 | transform: scale(1); 518 | opacity: 1; 519 | } 520 | to { 521 | -webkit-transform: scale(.2); 522 | -moz-transform: scale(.2); 523 | transform: scale(.2); 524 | opacity: 0; 525 | } 526 | } 527 | 528 | -------------------------------------------------------------------------------- /src/transition.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Transitions: a Zepto plugin for animated page transitions, similar to 3 | * the navigation that JQuery Mobile provides. 4 | * 2012, David Gileadi 5 | * 6 | * Released into the public domain. 7 | * 8 | *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 9 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 10 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 11 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 12 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 14 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | * 16 | * @author gileadis@gmail.com 17 | * @version 1.0.0 18 | * 19 | * @requires 20 | * Zepto JavaScript Library: http://zeptojs.com 21 | */ 22 | 23 | $(document).ready(function() { 24 | 25 | $(document.body).transition('init').show(); 26 | }); 27 | 28 | (function( $ ) { 29 | 30 | var zIndex = 0, 31 | inited = false, 32 | settings = null, 33 | pageUrls = {}, 34 | lastLoadedUrl = window.location.href, 35 | ignoreHash = {}, 36 | action = null, 37 | history = [], 38 | historyPos = 0; 39 | 40 | var methods = { 41 | 42 | options : function(options) { 43 | 44 | settings = $.extend( { 45 | defaultPageTransition : 'fade', 46 | domCache : false 47 | }, options); 48 | }, 49 | 50 | init : function(eventData, targetPage, title) { 51 | 52 | // one-time initialization 53 | if (!inited) { 54 | inited = true; 55 | 56 | $(document.body).transition('options', {}); 57 | 58 | $(window).on('hashchange', function(e) { 59 | var target = (action && action.element) || $(document.body); 60 | if (!ignoreHash[window.location.hash]) { 61 | var to = window.location.hash; 62 | var from = $('div.ui-page-active').attr('id'); 63 | if (from) 64 | from = '#' + from; 65 | if (action && action.element && action.element.is('form')) { 66 | to = { 67 | type: action.element.attr('method') || 'get', 68 | url: window.location.hash.slice(1), 69 | data: action.element.serialize(), 70 | dataType: 'html', 71 | global: false 72 | }; 73 | } 74 | var transition = null; 75 | var back = action == null; 76 | var top = 0; 77 | if (back) { 78 | if (historyPos < history.length && history[historyPos].to == to) { 79 | action = history[historyPos++]; 80 | back = false; 81 | } else if (historyPos > 0) { 82 | action = history[--historyPos]; 83 | back = action ? !action.reverse : true; 84 | } 85 | transition = action ? action.transition : settings.defaultPageTransition; 86 | if (action) { 87 | top = action.top || 0; 88 | if (!to && $(action.from).length) 89 | to = action.from; 90 | } 91 | } else if (action.transition) { 92 | transition = action.transition; 93 | history[historyPos++] = {to: to, from: from, transition: transition, top: $(window).scrollTop()}; 94 | back = action.reverse; 95 | } else { 96 | transition = action.element.attr('transition') || action.element.data('transition') || settings.defaultPageTransition; 97 | var direction = action.element.attr('direction') || action.element.data('direction'); 98 | if (direction === 'reverse') 99 | back = true; 100 | history[historyPos++] = {to: to, from: from, transition: transition, reverse: back, top: $(window).scrollTop()}; 101 | } 102 | target.transition('changePage', to, transition, back, top); 103 | } 104 | action = null; 105 | }); 106 | } 107 | 108 | // create logical pages in divs 109 | var pages = $('div[data-role="page"]', this); 110 | if (!pages.length) { 111 | if (this.is('div')) { 112 | this.attr('data-role', 'page'); 113 | this.attr('id', '_trans_div' + zIndex); 114 | pages = this; 115 | } else { 116 | pages = $('<div data-role="page" id="_trans_div' + zIndex + '" />'); 117 | this.children().wrapAll(pages); 118 | } 119 | } 120 | 121 | if (eventData) 122 | pages.trigger('pageload', eventData); 123 | 124 | // the initial page is special: its id must equal its hash 125 | var initial = pages.first(); 126 | if (window.location.hash) { 127 | initial = $(toId(window.location.hash)); 128 | if (!initial.length) { 129 | // TODO: maybe ajax-load the initial page instead? 130 | initial = pages.first(); 131 | var formerId = initial.attr('id'); 132 | var id = toId(pageUrls[window.location.hash] || window.location.hash.slice(1)); 133 | initial.attr('id', id); 134 | if (formerId) { 135 | // fix all links that pointed to it 136 | $('[data-href="#' + formerId + '"]', pages).attr('data-href', '#' + id); 137 | $('[href="#' + formerId + '"]', pages).attr('href', '#' + id); 138 | } 139 | } 140 | } 141 | 142 | pages.addClass('ui-page'); 143 | pages.each(function() { 144 | if (!$(this).attr('id')) 145 | $(this).attr('id', '_trans_div' + zIndex); 146 | pageUrls['#' + $(this).attr('id')] = lastLoadedUrl; 147 | 148 | $(this).css('zIndex', zIndex++); 149 | }); 150 | 151 | $('a[href]', pages).not('[target]').not('[rel="external"]').not('[data-ajax="false"]').not('[data-href]').transition('hijackLinks'); 152 | $('[data-href]', pages).transition('hijackLinks'); 153 | $('form').not('[target]').not('[data-ajax="false"]').transition('hijackLinks'); 154 | 155 | if (!title) 156 | title = document.title; 157 | pages.not('[data-title]').data('title', title); 158 | title = initial.data('title'); 159 | if (title) 160 | document.title = title; 161 | 162 | pages.hide(); 163 | var active = targetPage ? $(targetPage) : null; 164 | active = active || initial; 165 | active.addClass('ui-page-active'); 166 | 167 | pages.each(function() { 168 | $(this).trigger('pageinit', $(this)); 169 | }); 170 | 171 | return active; 172 | }, 173 | 174 | to : function(page, transition, reverse) { 175 | 176 | transition = transition || settings.defaultPageTransition; 177 | if (!reverse) 178 | reverse = false; 179 | action = {transition: transition, reverse: reverse}; 180 | window.location.hash = '#' + page; 181 | }, 182 | 183 | hijackLinks : function() { 184 | 185 | return this.each(function() { 186 | var el = $(this); 187 | 188 | if (el.data('rel') == 'back') { 189 | var handler = function(e) { 190 | window.history.back(); 191 | e.preventDefault(); 192 | }; 193 | el.on('click', handler); 194 | el.on('tap', handler); 195 | return; 196 | } 197 | 198 | var href = el.attr('data-href') || el.attr('href') || el.attr('action') || "#"; 199 | if (href.charAt(0) === '#') { 200 | // ignore some hash links; this is buggy when navigating backwards 201 | if ($('a[name="' + href.slice(1) + '"]').length) { 202 | ignoreHash[href] = true; 203 | return; 204 | } 205 | } else { 206 | // change all links to be hash links 207 | href = '#' + href; 208 | if (el.is('a')) 209 | el.attr('href', href); 210 | else if (el.attr('action')) 211 | el.attr('action', href); 212 | if (el.attr('data-href')) 213 | el.attr('data-href', href); 214 | } 215 | 216 | var handler; 217 | if (el.is('a')) { 218 | handler = function(e) { 219 | action = {element: el}; 220 | }; 221 | } else if (el.is('form')) { 222 | handler = function(e) { 223 | action = {element: el}; 224 | window.location.href = href; 225 | e.preventDefault(); 226 | } 227 | el.on('submit', handler); 228 | } else { 229 | handler = function(e) { 230 | action = {element: el}; 231 | window.location.href = href; 232 | } 233 | } 234 | 235 | if (!el.is('form')) { 236 | el.on('click', handler); 237 | el.on('tap', handler); 238 | } 239 | }); 240 | }, 241 | 242 | changePage : function(to, transition, back, top) { 243 | 244 | var changeEventData = { toPage: to, back: back }; 245 | var e = $.Event('pagebeforechange'); 246 | $(this).trigger(e, changeEventData); 247 | if (e.defaultPrevented) 248 | return; 249 | else { 250 | to = changeEventData.toPage; 251 | back = changeEventData.back; 252 | } 253 | 254 | var href = typeof to === 'string' ? to : to.url; 255 | var targetPage = null; 256 | var from = $('div.ui-page-active'); 257 | var handled = false; 258 | 259 | if ((typeof to === 'string') && to.charAt(0) === '#') { 260 | var toPage = $(toId(to)); 261 | if (toPage.length) { 262 | $(this).transition('perform', from, toPage, transition, back, top, changeEventData); 263 | handled = true; 264 | } else if (!settings.domCache && pageUrls[to]) { 265 | targetPage = to; 266 | to = pageUrls[to]; 267 | } else 268 | to = to.slice(1); 269 | } 270 | 271 | if (!handled) { 272 | var eventData = {href: href, element: $(this), back: back}; 273 | var e = $.Event('pagebeforeload'); 274 | $(this).trigger(e, eventData); 275 | var el = $(this); 276 | if (!e.defaultPrevented) { 277 | $(this).transition('load', to, eventData, function(body, result, title) { 278 | // add it to the current document 279 | var div = $('<div data-role="page-container" />'); 280 | div.html(body); 281 | $(document.body).append(div); 282 | 283 | var to = $(div).transition('init', eventData, targetPage, title); 284 | $(el).transition('perform', from, to, transition, back, top, changeEventData); 285 | }); 286 | handled = true; 287 | } 288 | } 289 | 290 | if (!handled) 291 | $(this).trigger('pagechangefailed', changeEventData); 292 | }, 293 | 294 | load : function(what, eventData, onSuccess) { 295 | 296 | what = typeof what === 'string' ? {url: what, dataType: 'html', global: false} : what; 297 | if (!what.url) 298 | what.url = window.location.href; 299 | 300 | what.success = function(result, textStatus, xhr) { 301 | eventData.xhr = xhr; 302 | eventData.textStatus = textStatus; 303 | 304 | lastLoadedUrl = what.url; 305 | 306 | // mark everything not just loaded as disposable 307 | if (!settings.domCache) 308 | $('div[data-role="page"]').not('[data-dom-cache="true"]').addClass('transition-recyclable'); 309 | 310 | // extract the body and title from the html 311 | var bodyStart = result.search(/<body/i); 312 | var head = result; 313 | var body = result; 314 | var title; 315 | if (bodyStart != -1) { 316 | head = result.slice(0, bodyStart); 317 | bodyStart = result.indexOf('>', bodyStart); 318 | bodyEnd = result.search(/<\/body>/i); 319 | body = result.slice(bodyStart + 1, bodyEnd); 320 | } 321 | var match = head.match(/<title>(.+)<\/title>/im); 322 | if (match) 323 | title = match[1]; 324 | 325 | // adjust relative links 326 | body = fixLinks(body); 327 | 328 | onSuccess(body, result, title); 329 | }; 330 | what.error = function(xhr, textStatus, errorThrown) { 331 | eventData.xhr = xhr; 332 | eventData.textStatus = textStatus; 333 | eventData.errorThrown = errorThrown; 334 | $(this).trigger('pageloadfailed', eventData); 335 | $(this).trigger('pagechangefailed', {toPage: what.url}); 336 | }; 337 | $.ajax(what); 338 | }, 339 | 340 | perform : function(from, to, transition, back, top, changeEventData) { 341 | 342 | changeEventData.from = from; 343 | changeEventData.to = to; 344 | 345 | from.trigger('pagebeforehide', from); 346 | to.trigger('pagebeforeshow', to); 347 | 348 | window.setTimeout(function() { 349 | from.addClass(transition + ' out'); 350 | from.removeClass('ui-page-active'); 351 | 352 | var pos = to.position(); 353 | to.css({top: pos.top - top}); 354 | 355 | to.show(); 356 | to.addClass(transition + ' in'); 357 | to.addClass('ui-page-active'); 358 | 359 | if (back) { 360 | from.addClass('reverse'); 361 | to.addClass('reverse'); 362 | } 363 | }, 1); 364 | 365 | window.setTimeout(function() { 366 | from.removeClass(transition + ' out'); 367 | to.removeClass(transition + ' in'); 368 | from.removeClass('reverse'); 369 | to.removeClass('reverse'); 370 | 371 | to.css({top: 0}); 372 | window.scrollTo(0, top); 373 | 374 | var title = to.data('title'); 375 | if (title) 376 | document.title = title; 377 | 378 | from.trigger('pagehide', from); 379 | to.trigger('pageshow', to); 380 | 381 | $(document).trigger('pagechange', changeEventData); 382 | 383 | $('div[data-role="page"]').hide(); 384 | to.show(); 385 | 386 | // recycle all recyclable pages and empty divs 387 | if (!settings.domCache) { 388 | $('div.transition-recyclable').each(function() { 389 | var e = $.Event('pageremove'); 390 | $(this).trigger(e, $(this)); 391 | if (!e.defaultPrevented) 392 | $(this).remove(); 393 | }); 394 | $('div[data-role="page-container"]').not(function() {return $(this).children().length}).remove(); 395 | } 396 | }, 707); 397 | } 398 | 399 | }; 400 | 401 | $.fn.transition = function(method) { 402 | 403 | if (methods[method]) 404 | return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); 405 | else if (typeof method === 'object' || !method) 406 | return methods.to.apply(this, arguments); 407 | else 408 | throw 'Method ' + method + ' does not exist'; 409 | }; 410 | 411 | function toId(url) { 412 | var i = url.indexOf('?'); 413 | if (i > 0) 414 | url = url.slice(0, i); 415 | return url.replace(/[:\.\+\/]/g, '_'); 416 | } 417 | 418 | function fixLinks(body) { 419 | 420 | if (window.location.hash) { 421 | var relative = relativePath(window.location.pathname, window.location.hash.slice(1)); 422 | if (relative.length) { 423 | body = body.replace(/(\b(src|href|action))="([^"#:]+)"/gi, '$1="' + relative + '$3"'); 424 | 425 | // fix replaced links in the form of "relative/../" 426 | body = body.replace(/(\b(src|href|action))="(.+\/)?[^\/]+\/\.\.\//gi, '$1="$3'); 427 | } 428 | } 429 | return body; 430 | } 431 | 432 | function relativePath(fromPath, toPath) { 433 | 434 | var relative = ''; 435 | 436 | var slashIndex = toPath.lastIndexOf('/'); 437 | if (slashIndex != -1) { 438 | relative = toPath.slice(0, slashIndex + 1); 439 | if (relative.charAt(0) == '/') { 440 | // strip the common start of paths 441 | if (!fromPath.charAt(0) == '/') 442 | fromPath = '/' + fromPath; 443 | var start = 1; 444 | slashIndex = start; 445 | do { 446 | slashIndex = relative.indexOf('/', slashIndex) + 1; 447 | if (slashIndex > start && relative.slice(0, slashIndex) == fromPath.slice(0, slashIndex)) 448 | start = slashIndex; 449 | } while (slashIndex > 0 && slashIndex == start); 450 | 451 | // make a relative path between them 452 | var back = ''; 453 | slashIndex = start; 454 | do { 455 | slashIndex = fromPath.indexOf('/', slashIndex + 1); 456 | if (slashIndex != -1) 457 | back += '../'; 458 | } while (slashIndex != -1); 459 | 460 | relative = back + relative.slice(start); 461 | } 462 | } 463 | 464 | return relative; 465 | } 466 | 467 | })( Zepto ); --------------------------------------------------------------------------------