mui_app_rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +34 -0
  3. data/app/assets/fonts/mui.ttf +0 -0
  4. data/app/assets/javascripts/mui_app_rails/actions.js +26 -0
  5. data/app/assets/javascripts/mui_app_rails/ajax.plugin.js +3 -0
  6. data/app/assets/javascripts/mui_app_rails/input.plugin.js +232 -0
  7. data/app/assets/javascripts/mui_app_rails/modals.js +37 -0
  8. data/app/assets/javascripts/mui_app_rails/mui.active.js +30 -0
  9. data/app/assets/javascripts/mui_app_rails/mui.ajax.5+.js +27 -0
  10. data/app/assets/javascripts/mui_app_rails/mui.ajax.js +277 -0
  11. data/app/assets/javascripts/mui_app_rails/mui.animation.js +39 -0
  12. data/app/assets/javascripts/mui_app_rails/mui.animationframe.js +72 -0
  13. data/app/assets/javascripts/mui_app_rails/mui.back.5+.js +108 -0
  14. data/app/assets/javascripts/mui_app_rails/mui.back.js +56 -0
  15. data/app/assets/javascripts/mui_app_rails/mui.class.js +40 -0
  16. data/app/assets/javascripts/mui_app_rails/mui.class.scroll.js +894 -0
  17. data/app/assets/javascripts/mui_app_rails/mui.class.scroll.pullrefresh.js +150 -0
  18. data/app/assets/javascripts/mui_app_rails/mui.class.scroll.slider.js +361 -0
  19. data/app/assets/javascripts/mui_app_rails/mui.class.scroll.slider.old.js +332 -0
  20. data/app/assets/javascripts/mui_app_rails/mui.detect.5+.js +18 -0
  21. data/app/assets/javascripts/mui_app_rails/mui.detect.js +50 -0
  22. data/app/assets/javascripts/mui_app_rails/mui.dialog.alert.js +27 -0
  23. data/app/assets/javascripts/mui_app_rails/mui.dialog.confirm.js +27 -0
  24. data/app/assets/javascripts/mui_app_rails/mui.dialog.prompt.js +33 -0
  25. data/app/assets/javascripts/mui_app_rails/mui.dialog.toast.js +20 -0
  26. data/app/assets/javascripts/mui_app_rails/mui.event.js +160 -0
  27. data/app/assets/javascripts/mui_app_rails/mui.fixed.animation.js +22 -0
  28. data/app/assets/javascripts/mui_app_rails/mui.fixed.classlist.js +50 -0
  29. data/app/assets/javascripts/mui_app_rails/mui.fixed.fastclick.js +64 -0
  30. data/app/assets/javascripts/mui_app_rails/mui.fixed.js +40 -0
  31. data/app/assets/javascripts/mui_app_rails/mui.fixed.keyboard.js +56 -0
  32. data/app/assets/javascripts/mui_app_rails/mui.gestures.drag.js +48 -0
  33. data/app/assets/javascripts/mui_app_rails/mui.gestures.flick.js +30 -0
  34. data/app/assets/javascripts/mui_app_rails/mui.gestures.hold.js +41 -0
  35. data/app/assets/javascripts/mui_app_rails/mui.gestures.js +207 -0
  36. data/app/assets/javascripts/mui_app_rails/mui.gestures.longtap.js +43 -0
  37. data/app/assets/javascripts/mui_app_rails/mui.gestures.swipe.js +29 -0
  38. data/app/assets/javascripts/mui_app_rails/mui.gestures.tap.js +40 -0
  39. data/app/assets/javascripts/mui_app_rails/mui.init.5+.js +441 -0
  40. data/app/assets/javascripts/mui_app_rails/mui.init.js +100 -0
  41. data/app/assets/javascripts/mui_app_rails/mui.init.pullrefresh.js +57 -0
  42. data/app/assets/javascripts/mui_app_rails/mui.js +396 -0
  43. data/app/assets/javascripts/mui_app_rails/mui.jsonp.js +108 -0
  44. data/app/assets/javascripts/mui_app_rails/mui.layout.js +22 -0
  45. data/app/assets/javascripts/mui_app_rails/mui.namespace.js +35 -0
  46. data/app/assets/javascripts/mui_app_rails/mui.number.js +93 -0
  47. data/app/assets/javascripts/mui_app_rails/mui.offcanvas.js +497 -0
  48. data/app/assets/javascripts/mui_app_rails/mui.pullrefresh.js +157 -0
  49. data/app/assets/javascripts/mui_app_rails/mui.target.js +58 -0
  50. data/app/assets/javascripts/mui_app_rails/mui.view.js +172 -0
  51. data/app/assets/javascripts/mui_app_rails/popovers.js +278 -0
  52. data/app/assets/javascripts/mui_app_rails/pullrefresh.5+.js +238 -0
  53. data/app/assets/javascripts/mui_app_rails/push.js +479 -0
  54. data/app/assets/javascripts/mui_app_rails/segmented-controllers.js +99 -0
  55. data/app/assets/javascripts/mui_app_rails/sliders.js +362 -0
  56. data/app/assets/javascripts/mui_app_rails/switches.js +165 -0
  57. data/app/assets/javascripts/mui_app_rails/tableviews.js +512 -0
  58. data/app/assets/javascripts/mui_app_rails.js +1 -0
  59. data/app/assets/stylesheets/mui_app_rails/badges.scss +88 -0
  60. data/app/assets/stylesheets/mui_app_rails/bars.scss +312 -0
  61. data/app/assets/stylesheets/mui_app_rails/base.scss +196 -0
  62. data/app/assets/stylesheets/mui_app_rails/buttons.scss +205 -0
  63. data/app/assets/stylesheets/mui_app_rails/cards.scss +62 -0
  64. data/app/assets/stylesheets/mui_app_rails/forms.scss +452 -0
  65. data/app/assets/stylesheets/mui_app_rails/fullscreen.scss +35 -0
  66. data/app/assets/stylesheets/mui_app_rails/grid.scss +75 -0
  67. data/app/assets/stylesheets/mui_app_rails/hack.scss +14 -0
  68. data/app/assets/stylesheets/mui_app_rails/icon.scss +170 -0
  69. data/app/assets/stylesheets/mui_app_rails/iscroll.scss +43 -0
  70. data/app/assets/stylesheets/mui_app_rails/loadings.scss +111 -0
  71. data/app/assets/stylesheets/mui_app_rails/mixins.scss +212 -0
  72. data/app/assets/stylesheets/mui_app_rails/modals.scss +34 -0
  73. data/app/assets/stylesheets/mui_app_rails/mui.scss +46 -0
  74. data/app/assets/stylesheets/mui_app_rails/normalize.scss +425 -0
  75. data/app/assets/stylesheets/mui_app_rails/number.scss +70 -0
  76. data/app/assets/stylesheets/mui_app_rails/off-canvas.scss +84 -0
  77. data/app/assets/stylesheets/mui_app_rails/os.scss +12 -0
  78. data/app/assets/stylesheets/mui_app_rails/pagination.scss +155 -0
  79. data/app/assets/stylesheets/mui_app_rails/popovers.scss +198 -0
  80. data/app/assets/stylesheets/mui_app_rails/pullrefreshs.scss +98 -0
  81. data/app/assets/stylesheets/mui_app_rails/push.scss +63 -0
  82. data/app/assets/stylesheets/mui_app_rails/scroll.scss +95 -0
  83. data/app/assets/stylesheets/mui_app_rails/segmented-controls.scss +150 -0
  84. data/app/assets/stylesheets/mui_app_rails/slider-cell.scss +20 -0
  85. data/app/assets/stylesheets/mui_app_rails/sliders.scss +133 -0
  86. data/app/assets/stylesheets/mui_app_rails/switches.scss +115 -0
  87. data/app/assets/stylesheets/mui_app_rails/table-views.scss +482 -0
  88. data/app/assets/stylesheets/mui_app_rails/toast.scss +16 -0
  89. data/app/assets/stylesheets/mui_app_rails/type.scss +23 -0
  90. data/app/assets/stylesheets/mui_app_rails/variables.scss +64 -0
  91. data/app/assets/stylesheets/mui_app_rails.css +3 -0
  92. data/lib/mui_app_rails/engine.rb +5 -0
  93. data/lib/mui_app_rails/version.rb +3 -0
  94. data/lib/mui_app_rails.rb +5 -0
  95. metadata +179 -0
@@ -0,0 +1,238 @@
1
+ /**
2
+ * pullRefresh 5+
3
+ * @param {type} $
4
+ * @returns {undefined}
5
+ */
6
+ (function($, document) {
7
+ if (!($.os.plus && $.os.android)) { //仅在android的5+版本使用
8
+ return;
9
+ }
10
+ var CLASS_PLUS_PULLREFRESH = $.className('plus-pullrefresh');
11
+ var CLASS_VISIBILITY = $.className('visibility');
12
+ var CLASS_HIDDEN = $.className('hidden');
13
+ var CLASS_BLOCK = $.className('block');
14
+
15
+ var PlusPullRefresh = $.Class.extend({
16
+ init: function(element, options) {
17
+ this.element = element;
18
+ this.options = options;
19
+ this.wrapper = this.scroller = element;
20
+ this._init();
21
+ this._initPulldownRefreshEvent();
22
+ },
23
+ _init: function() {
24
+ var self = this;
25
+ // document.addEventListener('plusscrollbottom', this);
26
+ window.addEventListener('dragup', self);
27
+ self.scrollInterval = window.setInterval(function() {
28
+ if (self.isScroll && !self.loading) {
29
+ if (window.pageYOffset + window.innerHeight + 10 >= document.documentElement.scrollHeight) {
30
+ self.isScroll = false; //放在这里是因为快速滚动的话,有可能检测时,还没到底,所以只要有滚动,没到底之前一直检测高度变化
31
+ if (self.bottomPocket) {
32
+ self.pullupLoading();
33
+ }
34
+ }
35
+ }
36
+ }, 100);
37
+ },
38
+ _initPulldownRefreshEvent: function() {
39
+ var self = this;
40
+ if (self.topPocket && self.options.webviewId) {
41
+ $.plusReady(function() {
42
+ var webview = plus.webview.getWebviewById(self.options.webviewId);
43
+ if (!webview) {
44
+ return;
45
+ }
46
+ self.options.webview = webview;
47
+ var downOptions = self.options.down;
48
+ var height = downOptions.height;
49
+ webview.addEventListener("dragBounce", function(e) {
50
+ if (!self.pulldown) {
51
+ self._initPulldownRefresh();
52
+ } else {
53
+ self.pullPocket.classList.add(CLASS_BLOCK);
54
+ }
55
+ switch (e.status) {
56
+ case "beforeChangeOffset": //下拉可刷新状态
57
+ self._setCaption(downOptions.contentdown);
58
+ break;
59
+ case "afterChangeOffset": //松开可刷新状态
60
+ self._setCaption(downOptions.contentover);
61
+ break;
62
+ case "dragEndAfterChangeOffset": //正在刷新状态
63
+ //执行下拉刷新所在webview的回调函数
64
+ webview.evalJS("mui&&mui.options.pullRefresh.down.callback()");
65
+ self._setCaption(downOptions.contentrefresh);
66
+ break;
67
+ default:
68
+ break;
69
+ }
70
+ }, false);
71
+ webview.setBounce({
72
+ position: {
73
+ top: height * 2 + 'px'
74
+ },
75
+ changeoffset: {
76
+ top: height + 'px'
77
+ }
78
+ });
79
+ });
80
+ }
81
+ },
82
+ handleEvent: function(e) {
83
+ var self = this;
84
+ if (self.stopped) {
85
+ return;
86
+ }
87
+ //5+的plusscrollbottom当页面内容较少时,不触发
88
+ // if (e.type === 'plusscrollbottom') {
89
+ // if (this.bottomPocket) {
90
+ // this.pullupLoading();
91
+ // }
92
+ // }
93
+ self.isScroll = false;
94
+ if (e.type === 'dragup') {
95
+ self.isScroll = true;
96
+ setTimeout(function() {
97
+ self.isScroll = false;
98
+ }, 1000);
99
+ }
100
+ }
101
+ }).extend($.extend({
102
+ setStopped: function(stopped) { //该方法是子页面调用的
103
+ this.stopped = !!stopped;
104
+ //TODO 此处需要设置当前webview的bounce为none,目前5+有BUG
105
+ var webview = plus.webview.currentWebview();
106
+ if (this.stopped) {
107
+ webview.setStyle({
108
+ bounce: 'none'
109
+ });
110
+ webview.setBounce({
111
+ position: {
112
+ top: 'none'
113
+ }
114
+ });
115
+ } else {
116
+ var height = this.options.down.height;
117
+ webview.setStyle({
118
+ bounce: 'vertical'
119
+ });
120
+ webview.setBounce({
121
+ position: {
122
+ top: height * 2 + 'px'
123
+ },
124
+ changeoffset: {
125
+ top: height + 'px'
126
+ }
127
+ });
128
+ }
129
+ },
130
+ pulldownLoading: function() {
131
+ //TODO
132
+ throw new Error('暂不支持');
133
+ },
134
+ endPulldownToRefresh: function() { //该方法是子页面调用的
135
+ var webview = plus.webview.currentWebview();
136
+ webview.parent().evalJS("mui&&mui(document.querySelector('.mui-content')).pullRefresh('" + JSON.stringify({
137
+ webviewId: webview.id
138
+ }) + "')._endPulldownToRefresh()");
139
+ },
140
+ _endPulldownToRefresh: function() { //该方法是父页面调用的
141
+ var self = this;
142
+ if (self.topPocket && self.options.webview) {
143
+ self.options.webview.endPullToRefresh(); //下拉刷新所在webview回弹
144
+ self.loading = false;
145
+ self._setCaption(self.options.down.contentdown, true);
146
+ setTimeout(function() {
147
+ self.loading || self.topPocket.classList.remove(CLASS_BLOCK);
148
+ }, 350);
149
+ }
150
+ },
151
+ pullupLoading: function(callback) {
152
+ var self = this;
153
+ if (self.isLoading) return;
154
+ self.isLoading = true;
155
+ if (self.pulldown !== false) {
156
+ self._initPullupRefresh();
157
+ } else {
158
+ this.pullPocket.classList.add(CLASS_BLOCK);
159
+ }
160
+ setTimeout(function() {
161
+ self.pullLoading.classList.add(CLASS_VISIBILITY);
162
+ self.pullLoading.classList.remove(CLASS_HIDDEN);
163
+ self.pullCaption.innerHTML = ''; //修正5+里边第一次加载时,文字显示的bug(还会显示出来个“多”,猜测应该是渲染问题导致的)
164
+ self.pullCaption.innerHTML = self.options.up.contentrefresh;
165
+ callback = callback || self.options.up.callback;
166
+ callback && callback.call(self);
167
+ }, 300);
168
+ },
169
+ endPullupToRefresh: function(finished) {
170
+ var self = this;
171
+ if (self.pullLoading) {
172
+ self.pullLoading.classList.remove(CLASS_VISIBILITY);
173
+ self.pullLoading.classList.add(CLASS_HIDDEN);
174
+ self.isLoading = false;
175
+ if (finished) {
176
+ self.finished = true;
177
+ self.pullCaption.innerHTML = self.options.up.contentnomore;
178
+ // self.bottomPocket.classList.remove(CLASS_BLOCK);
179
+ // self.bottomPocket.classList.add(CLASS_HIDDEN);
180
+ // document.removeEventListener('plusscrollbottom', self);
181
+ window.removeEventListener('dragup', self);
182
+ } else { //初始化时隐藏,后续不再隐藏
183
+ self.pullCaption.innerHTML = self.options.up.contentdown;
184
+ // setTimeout(function() {
185
+ // self.loading || self.bottomPocket.classList.remove(CLASS_BLOCK);
186
+ // }, 350);
187
+ }
188
+ }
189
+ },
190
+ scrollTo: function(x, y, time) {
191
+ $.scrollTo(x, y, time);
192
+ },
193
+ refresh: function(isReset) {
194
+ if (isReset && this.finished) {
195
+ if (this.pulldown !== false) {
196
+ this._initPullupRefresh();
197
+ }
198
+ this.bottomPocket.classList.remove(CLASS_HIDDEN);
199
+ this.pullCaption.innerHTML = this.options.up.contentdown;
200
+ window.addEventListener('dragup', this);
201
+ this.finished = false;
202
+ }
203
+ }
204
+ }, $.PullRefresh));
205
+
206
+ //override h5 pullRefresh
207
+ $.fn.pullRefresh = function(options) {
208
+ var self;
209
+ if (this.length === 0) {
210
+ self = document.createElement('div');
211
+ self.className = 'mui-content';
212
+ document.body.appendChild(self);
213
+ } else {
214
+ self = this[0];
215
+ }
216
+ //一个父需要支持多个子下拉刷新
217
+ options = options || {}
218
+ if (typeof options === 'string') {
219
+ options = $.parseJSON(options);
220
+ };
221
+ !options.webviewId && (options.webviewId = (plus.webview.currentWebview().id || plus.webview.currentWebview().getURL()));
222
+ var pullRefreshApi = null;
223
+ var attrWebviewId = options.webviewId && options.webviewId.replace(/\//g, "_"); //替换所有"/"
224
+ var id = self.getAttribute('data-pullrefresh-plus-' + attrWebviewId);
225
+ if (!id) { //避免重复初始化5+ pullrefresh
226
+ id = ++$.uuid;
227
+ self.setAttribute('data-pullrefresh-plus-' + attrWebviewId, id);
228
+ document.body.classList.add(CLASS_PLUS_PULLREFRESH);
229
+ $.data[id] = pullRefreshApi = new PlusPullRefresh(self, options);
230
+ } else {
231
+ pullRefreshApi = $.data[id];
232
+ }
233
+ if (options.up && options.up.auto) { //如果设置了auto,则自动上拉一次
234
+ pullRefreshApi.pullupLoading();
235
+ }
236
+ return pullRefreshApi;
237
+ };
238
+ })(mui, document);
@@ -0,0 +1,479 @@
1
+ /* ========================================================================
2
+ * Mui: push.js v1.0.0
3
+ * ======================================================================== */
4
+
5
+ /* global _gaq: true */
6
+
7
+ !(function () {
8
+ 'use strict';
9
+
10
+ var noop = function () {};
11
+
12
+
13
+ // Pushstate caching
14
+ // ==================
15
+
16
+ var isScrolling;
17
+ var maxCacheLength = 20;
18
+ var cacheMapping = sessionStorage;
19
+ var domCache = {};
20
+ // Change these to unquoted camelcase in the next major version bump
21
+ var transitionMap = {
22
+ 'slide-in' : 'slide-out',
23
+ 'slide-out' : 'slide-in',
24
+ fade : 'fade'
25
+ };
26
+
27
+ var bars = {
28
+ bartab : '.bar-tab',
29
+ barnav : '.bar-nav',
30
+ barfooter : '.bar-footer',
31
+ barheadersecondary : '.bar-header-secondary'
32
+ };
33
+
34
+ var cacheReplace = function (data, updates) {
35
+ PUSH.id = data.id;
36
+ if (updates) {
37
+ data = getCached(data.id);
38
+ }
39
+ cacheMapping[data.id] = JSON.stringify(data);
40
+ window.history.replaceState(data.id, data.title, data.url);
41
+ domCache[data.id] = document.body.cloneNode(true);
42
+ };
43
+
44
+ var cachePush = function () {
45
+ var id = PUSH.id;
46
+
47
+ var cacheForwardStack = JSON.parse(cacheMapping.cacheForwardStack || '[]');
48
+ var cacheBackStack = JSON.parse(cacheMapping.cacheBackStack || '[]');
49
+
50
+ cacheBackStack.push(id);
51
+
52
+ while (cacheForwardStack.length) {
53
+ delete cacheMapping[cacheForwardStack.shift()];
54
+ }
55
+ while (cacheBackStack.length > maxCacheLength) {
56
+ delete cacheMapping[cacheBackStack.shift()];
57
+ }
58
+
59
+ window.history.pushState(null, '', cacheMapping[PUSH.id].url);
60
+
61
+ cacheMapping.cacheForwardStack = JSON.stringify(cacheForwardStack);
62
+ cacheMapping.cacheBackStack = JSON.stringify(cacheBackStack);
63
+ };
64
+
65
+ var cachePop = function (id, direction) {
66
+ var forward = direction === 'forward';
67
+ var cacheForwardStack = JSON.parse(cacheMapping.cacheForwardStack || '[]');
68
+ var cacheBackStack = JSON.parse(cacheMapping.cacheBackStack || '[]');
69
+ var pushStack = forward ? cacheBackStack : cacheForwardStack;
70
+ var popStack = forward ? cacheForwardStack : cacheBackStack;
71
+
72
+ if (PUSH.id) {
73
+ pushStack.push(PUSH.id);
74
+ }
75
+ popStack.pop();
76
+
77
+ cacheMapping.cacheForwardStack = JSON.stringify(cacheForwardStack);
78
+ cacheMapping.cacheBackStack = JSON.stringify(cacheBackStack);
79
+ };
80
+
81
+ var getCached = function (id) {
82
+ return JSON.parse(cacheMapping[id] || null) || {};
83
+ };
84
+
85
+ var getTarget = function (e) {
86
+ var target = findTarget(e.target);
87
+
88
+ if (!target ||
89
+ e.which > 1 ||
90
+ e.metaKey ||
91
+ e.ctrlKey ||
92
+ isScrolling ||
93
+ location.protocol !== target.protocol ||
94
+ location.host !== target.host ||
95
+ !target.hash && /#/.test(target.href) ||
96
+ target.hash && target.href.replace(target.hash, '') === location.href.replace(location.hash, '') ||
97
+ target.getAttribute('data-ignore') === 'push') { return; }
98
+
99
+ return target;
100
+ };
101
+
102
+
103
+ // Main event handlers (touchend, popstate)
104
+ // ==========================================
105
+
106
+ var touchend = function (e) {
107
+ var target = getTarget(e);
108
+
109
+ if (!target) {
110
+ return;
111
+ }
112
+
113
+ e.preventDefault();
114
+
115
+ PUSH({
116
+ url : target.href,
117
+ hash : target.hash,
118
+ timeout : target.getAttribute('data-timeout'),
119
+ transition : target.getAttribute('data-transition')
120
+ });
121
+ };
122
+
123
+ var popstate = function (e) {
124
+ var key;
125
+ var barElement;
126
+ var activeObj;
127
+ var activeDom;
128
+ var direction;
129
+ var transition;
130
+ var transitionFrom;
131
+ var transitionFromObj;
132
+ var id = e.state;
133
+
134
+ if (!id || !cacheMapping[id]) {
135
+ return;
136
+ }
137
+
138
+ direction = PUSH.id < id ? 'forward' : 'back';
139
+
140
+ cachePop(id, direction);
141
+
142
+ activeObj = getCached(id);
143
+ activeDom = domCache[id];
144
+
145
+ if (activeObj.title) {
146
+ document.title = activeObj.title;
147
+ }
148
+
149
+ if (direction === 'back') {
150
+ transitionFrom = JSON.parse(direction === 'back' ? cacheMapping.cacheForwardStack : cacheMapping.cacheBackStack);
151
+ transitionFromObj = getCached(transitionFrom[transitionFrom.length - 1]);
152
+ } else {
153
+ transitionFromObj = activeObj;
154
+ }
155
+
156
+ if (direction === 'back' && !transitionFromObj.id) {
157
+ return (PUSH.id = id);
158
+ }
159
+
160
+ transition = direction === 'back' ? transitionMap[transitionFromObj.transition] : transitionFromObj.transition;
161
+
162
+ if (!activeDom) {
163
+ return PUSH({
164
+ id : activeObj.id,
165
+ url : activeObj.url,
166
+ title : activeObj.title,
167
+ timeout : activeObj.timeout,
168
+ transition : transition,
169
+ ignorePush : true
170
+ });
171
+ }
172
+
173
+ if (transitionFromObj.transition) {
174
+ activeObj = extendWithDom(activeObj, '.content', activeDom.cloneNode(true));
175
+ for (key in bars) {
176
+ if (bars.hasOwnProperty(key)) {
177
+ barElement = document.querySelector(bars[key]);
178
+ if (activeObj[key]) {
179
+ swapContent(activeObj[key], barElement);
180
+ } else if (barElement) {
181
+ barElement.parentNode.removeChild(barElement);
182
+ }
183
+ }
184
+ }
185
+ }
186
+
187
+ swapContent(
188
+ (activeObj.contents || activeDom).cloneNode(true),
189
+ document.querySelector('.content'),
190
+ transition
191
+ );
192
+
193
+ PUSH.id = id;
194
+
195
+ document.body.offsetHeight; // force reflow to prevent scroll
196
+ };
197
+
198
+
199
+ // Core PUSH functionality
200
+ // =======================
201
+
202
+ var PUSH = function (options) {
203
+ var key;
204
+ var xhr = PUSH.xhr;
205
+
206
+ options.container = options.container || options.transition ? document.querySelector('.content') : document.body;
207
+
208
+ for (key in bars) {
209
+ if (bars.hasOwnProperty(key)) {
210
+ options[key] = options[key] || document.querySelector(bars[key]);
211
+ }
212
+ }
213
+
214
+ if (xhr && xhr.readyState < 4) {
215
+ xhr.onreadystatechange = noop;
216
+ xhr.abort();
217
+ }
218
+
219
+ xhr = new XMLHttpRequest();
220
+ xhr.open('GET', options.url, true);
221
+ xhr.setRequestHeader('X-PUSH', 'true');
222
+
223
+ xhr.onreadystatechange = function () {
224
+ if (options._timeout) {
225
+ clearTimeout(options._timeout);
226
+ }
227
+ if (xhr.readyState === 4) {
228
+ xhr.status === 200 ? success(xhr, options) : failure(options.url);
229
+ }
230
+ };
231
+
232
+ if (!PUSH.id) {
233
+ cacheReplace({
234
+ id : +new Date(),
235
+ url : window.location.href,
236
+ title : document.title,
237
+ timeout : options.timeout,
238
+ transition : options.transition
239
+ });
240
+ }
241
+
242
+ if (options.timeout) {
243
+ options._timeout = setTimeout(function () { xhr.abort('timeout'); }, options.timeout);
244
+ }
245
+
246
+ xhr.send();
247
+
248
+ if (xhr.readyState && !options.ignorePush) {
249
+ cachePush();
250
+ }
251
+ };
252
+
253
+
254
+ // Main XHR handlers
255
+ // =================
256
+
257
+ var success = function (xhr, options) {
258
+ var key;
259
+ var barElement;
260
+ var data = parseXHR(xhr, options);
261
+
262
+ if (!data.contents) {
263
+ return locationReplace(options.url);
264
+ }
265
+
266
+ if (data.title) {
267
+ document.title = data.title;
268
+ }
269
+
270
+ if (options.transition) {
271
+ for (key in bars) {
272
+ if (bars.hasOwnProperty(key)) {
273
+ barElement = document.querySelector(bars[key]);
274
+ if (data[key]) {
275
+ swapContent(data[key], barElement);
276
+ } else if (barElement) {
277
+ barElement.parentNode.removeChild(barElement);
278
+ }
279
+ }
280
+ }
281
+ }
282
+
283
+ swapContent(data.contents, options.container, options.transition, function () {
284
+ cacheReplace({
285
+ id : options.id || +new Date(),
286
+ url : data.url,
287
+ title : data.title,
288
+ timeout : options.timeout,
289
+ transition : options.transition
290
+ }, options.id);
291
+ triggerStateChange();
292
+ });
293
+
294
+ if (!options.ignorePush && window._gaq) {
295
+ _gaq.push(['_trackPageview']); // google analytics
296
+ }
297
+ if (!options.hash) {
298
+ return;
299
+ }
300
+ };
301
+
302
+ var failure = function (url) {
303
+ throw new Error('Could not get: ' + url);
304
+ };
305
+
306
+
307
+ // PUSH helpers
308
+ // ============
309
+
310
+ var swapContent = function (swap, container, transition, complete) {
311
+ var enter;
312
+ var containerDirection;
313
+ var swapDirection;
314
+
315
+ if (!transition) {
316
+ if (container) {
317
+ container.innerHTML = swap.innerHTML;
318
+ } else if (swap.classList.contains('content')) {
319
+ document.body.appendChild(swap);
320
+ } else {
321
+ document.body.insertBefore(swap, document.querySelector('.content'));
322
+ }
323
+ } else {
324
+ enter = /in$/.test(transition);
325
+
326
+ if (transition === 'fade') {
327
+ container.classList.add('in');
328
+ container.classList.add('fade');
329
+ swap.classList.add('fade');
330
+ }
331
+
332
+ if (/slide/.test(transition)) {
333
+ swap.classList.add('sliding-in', enter ? 'right' : 'left');
334
+ swap.classList.add('sliding');
335
+ container.classList.add('sliding');
336
+ }
337
+
338
+ container.parentNode.insertBefore(swap, container);
339
+ }
340
+
341
+ if (!transition) {
342
+ complete && complete();
343
+ }
344
+
345
+ if (transition === 'fade') {
346
+ container.offsetWidth; // force reflow
347
+ container.classList.remove('in');
348
+ var fadeContainerEnd = function () {
349
+ container.removeEventListener('webkitTransitionEnd', fadeContainerEnd);
350
+ swap.classList.add('in');
351
+ swap.addEventListener('webkitTransitionEnd', fadeSwapEnd);
352
+ };
353
+ var fadeSwapEnd = function () {
354
+ swap.removeEventListener('webkitTransitionEnd', fadeSwapEnd);
355
+ container.parentNode.removeChild(container);
356
+ swap.classList.remove('fade');
357
+ swap.classList.remove('in');
358
+ complete && complete();
359
+ };
360
+ container.addEventListener('webkitTransitionEnd', fadeContainerEnd);
361
+
362
+ }
363
+
364
+ if (/slide/.test(transition)) {
365
+ var slideEnd = function () {
366
+ swap.removeEventListener('webkitTransitionEnd', slideEnd);
367
+ swap.classList.remove('sliding', 'sliding-in');
368
+ swap.classList.remove(swapDirection);
369
+ container.parentNode.removeChild(container);
370
+ complete && complete();
371
+ };
372
+
373
+ container.offsetWidth; // force reflow
374
+ swapDirection = enter ? 'right' : 'left';
375
+ containerDirection = enter ? 'left' : 'right';
376
+ container.classList.add(containerDirection);
377
+ swap.classList.remove(swapDirection);
378
+ swap.addEventListener('webkitTransitionEnd', slideEnd);
379
+ }
380
+ };
381
+
382
+ var triggerStateChange = function () {
383
+ var e = new CustomEvent('push', {
384
+ detail: { state: getCached(PUSH.id) },
385
+ bubbles: true,
386
+ cancelable: true
387
+ });
388
+
389
+ window.dispatchEvent(e);
390
+ };
391
+
392
+ var findTarget = function (target) {
393
+ var i;
394
+ var toggles = document.querySelectorAll('a');
395
+
396
+ for (; target && target !== document; target = target.parentNode) {
397
+ for (i = toggles.length; i--;) {
398
+ if (toggles[i] === target) {
399
+ return target;
400
+ }
401
+ }
402
+ }
403
+ };
404
+
405
+ var locationReplace = function (url) {
406
+ window.history.replaceState(null, '', '#');
407
+ window.location.replace(url);
408
+ };
409
+
410
+ var extendWithDom = function (obj, fragment, dom) {
411
+ var i;
412
+ var result = {};
413
+
414
+ for (i in obj) {
415
+ if (obj.hasOwnProperty(i)) {
416
+ result[i] = obj[i];
417
+ }
418
+ }
419
+
420
+ Object.keys(bars).forEach(function (key) {
421
+ var el = dom.querySelector(bars[key]);
422
+ if (el) {
423
+ el.parentNode.removeChild(el);
424
+ }
425
+ result[key] = el;
426
+ });
427
+
428
+ result.contents = dom.querySelector(fragment);
429
+
430
+ return result;
431
+ };
432
+
433
+ var parseXHR = function (xhr, options) {
434
+ var head;
435
+ var body;
436
+ var data = {};
437
+ var responseText = xhr.responseText;
438
+
439
+ data.url = options.url;
440
+
441
+ if (!responseText) {
442
+ return data;
443
+ }
444
+
445
+ if (/<html/i.test(responseText)) {
446
+ head = document.createElement('div');
447
+ body = document.createElement('div');
448
+ head.innerHTML = responseText.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0];
449
+ body.innerHTML = responseText.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0];
450
+ } else {
451
+ head = body = document.createElement('div');
452
+ head.innerHTML = responseText;
453
+ }
454
+
455
+ data.title = head.querySelector('title');
456
+ var text = 'innerText' in data.title ? 'innerText' : 'textContent';
457
+ data.title = data.title && data.title[text].trim();
458
+
459
+ if (options.transition) {
460
+ data = extendWithDom(data, '.content', body);
461
+ } else {
462
+ data.contents = body;
463
+ }
464
+
465
+ return data;
466
+ };
467
+
468
+
469
+ // Attach PUSH event handlers
470
+ // ==========================
471
+
472
+ window.addEventListener('touchstart', function () { isScrolling = false; });
473
+ window.addEventListener('touchmove', function () { isScrolling = true; });
474
+ window.addEventListener('touchend', touchend);
475
+ window.addEventListener('click', function (e) { if (getTarget(e)) {e.preventDefault();} });
476
+ window.addEventListener('popstate', popstate);
477
+ window.PUSH = PUSH;
478
+
479
+ }());