|
38 | 38 | *
|
39 | 39 | * @type string
|
40 | 40 | **/
|
41 |
| - Mobilebone.VERSION = '2.3.3'; |
| 41 | + Mobilebone.VERSION = '2.4.0'; |
42 | 42 |
|
43 | 43 | /**
|
44 | 44 | * Whether catch attribute of href from element with tag 'a'
|
|
238 | 238 | if (pageOut != null && pageOut.classList) {
|
239 | 239 | // do transition if there are no 'prevent'
|
240 | 240 | if (isPreventOut != true) {
|
| 241 | + pageOut.classList.add(params_out.form); |
| 242 | + // reflow |
| 243 | + pageOut.offsetWidth = pageOut.offsetWidth; |
| 244 | + // go, go, go |
241 | 245 | pageOut.style.display = "block";
|
242 | 246 | pageOut.classList.add("out");
|
243 |
| - pageOut.classList.add(params_out.form); |
244 | 247 | pageOut.classList.remove("in");
|
245 | 248 | // if reverse direction
|
246 | 249 | pageOut.classList[back? "add": "remove"]("reverse");
|
| 250 | + |
247 | 251 | // do fallback every time
|
248 | 252 | var fallback = params_out.fallback;
|
249 | 253 | if (typeof fallback == "string") fallback = params_out.root[fallback];
|
250 | 254 | if (typeof fallback == "function") fallback.call(params_out.root, pageInto, pageOut, options);
|
251 | 255 | }
|
252 | 256 | }
|
| 257 | + |
253 | 258 | if (pageInto != null && pageInto.classList) {
|
254 | 259 | // for title change
|
255 | 260 | var title = params_in.title,
|
|
267 | 272 | // set data-title for first visibie page
|
268 | 273 | pageInto.setAttribute("data-title", document.title);
|
269 | 274 | }
|
270 |
| - // Fastclick may cause slide bug in iOS8, any innerHTML change can fix it! |
271 |
| - // issues #80 |
272 |
| - if (typeof FastClick != "undefined") { |
273 |
| - var mobilebone = document.querySelector("mobilebone"); |
274 |
| - if (mobilebone == null) { |
275 |
| - mobilebone = document.createElement("mobilebone"); |
276 |
| - mobilebone.style.position = "absolute"; |
277 |
| - mobilebone.style.clip = "rect(0 0 0 0)"; |
278 |
| - document.body.appendChild(mobilebone); |
279 |
| - } |
280 |
| - mobilebone.innerHTML = mobilebone.innerHTML.replace('11', '') + '1'; |
281 |
| - } |
282 |
| - |
| 275 | + |
283 | 276 | // delete page with same id when options.remove !== false
|
284 | 277 | var pageid = options.id || pageInto.id;
|
285 | 278 |
|
286 | 279 | if (options.remove !== false && store[pageid] && store[pageid] != pageInto && store[pageid].parentElement) {
|
287 | 280 | store[pageid].parentElement.removeChild(store[pageid]);
|
288 | 281 | delete store[pageid];
|
289 | 282 | }
|
290 |
| - |
| 283 | + |
291 | 284 | // do transition
|
| 285 | + if (pageOut) pageInto.classList.add(params_in.form); |
| 286 | + // iOS bug |
| 287 | + // reflow for fixing issues #80, #86 |
| 288 | + pageInto.offsetWidth = pageInto.offsetWidth; |
| 289 | + // go~ as normal |
292 | 290 | pageInto.style.display = "block";
|
293 | 291 | pageInto.classList.remove("out");
|
294 | 292 | pageInto.classList.add("in");
|
295 |
| - pageOut && pageInto.classList.add(params_in.form); |
296 | 293 | // if reverse direction
|
297 | 294 | pageInto.classList[back? "add": "remove"]("reverse");
|
298 |
| - |
| 295 | + |
299 | 296 | // do callback when come in first time
|
300 | 297 | var onpagefirstinto = params_in.onpagefirstinto;
|
301 | 298 | if (!store[pageid]) {
|
|
339 | 336 | });
|
340 | 337 |
|
341 | 338 | // history
|
342 |
| - var url_push = pageid; |
| 339 | + var url_push = pageid, url_push_replaced = ''; |
343 | 340 | if (url_push && /^#/.test(url_push) == false) {
|
344 | 341 | url_push = "#" + url_push;
|
345 | 342 | }
|
346 |
| - |
347 |
| - if (supportHistory && this.pushStateEnabled && options.history !== false && url_push) { |
| 343 | + url_push_replaced = url_push.replace(/^#/, "#&"); |
| 344 | + |
| 345 | + if (supportHistory && this.pushStateEnabled && options.history !== false && url_push |
| 346 | + // hash should be different |
| 347 | + // can fix issues #79, #87 maybe |
| 348 | + && url_push_replaced != location.hash |
| 349 | + ) { |
348 | 350 | // don't trigger 'popstate' events
|
349 | 351 | history.popstate = false;
|
350 | 352 | // if only pageIn, use 'replaceState'
|
351 | 353 | history[pageOut? "pushState": "replaceState"](null, document.title, url_push.replace(/^#/, "#&"));
|
352 | 354 | }
|
353 |
| - // reset to popable state |
354 |
| - history.popstate = true; |
355 |
| - |
| 355 | + |
356 | 356 | // store page-id, just once
|
357 | 357 | if (!store[pageid]) {
|
358 | 358 | store[pageid] = pageInto;
|
|
363 | 363 |
|
364 | 364 | if (typeof callback == "string") callback = params_in.root[callback];
|
365 | 365 | if (typeof callback == "function") callback.call(params_in.root, pageInto, pageOut, options);
|
| 366 | + |
| 367 | + // Safari do 'popstate' after 'pushState/replaceState' |
| 368 | + // So, we neet setTimeout to avoid excuting 'Mobilebone.transition()' twice |
| 369 | + setTimeout(function() { |
| 370 | + // reset to popable state |
| 371 | + history.popstate = true; |
| 372 | + }, 17); |
366 | 373 | }
|
367 | 374 | };
|
368 | 375 |
|
|
857 | 864 | });
|
858 | 865 | }
|
859 | 866 | }
|
860 |
| - |
| 867 | + // Important: |
| 868 | + // In ios7+, swipe the edge of page will navigate Safari |
| 869 | + // that will trigger 'popstate' events and the page will transition twice |
| 870 | + var isSafari7 = !!navigator.userAgent.match(/safari/i) && !navigator.userAgent.match(/chrome/i) && typeof document.hidden !== "undefined" && !window.chrome; |
| 871 | + if ('ontouchstart' in window == true && isSafari7) { |
| 872 | + document.addEventListener("touchmove", function() { |
| 873 | + history.popstateswipe = true; |
| 874 | + }); |
| 875 | + document.addEventListener("touchend", function() { |
| 876 | + history.popstateswipe = false; |
| 877 | + }); |
| 878 | + } |
| 879 | + |
861 | 880 | // change flag-var for avoiding repeat init
|
862 | 881 | hasInited = true;
|
863 | 882 | };
|
864 | 883 |
|
865 | 884 | /**
|
866 | 885 | * If 'a' element has href, slide auto when tapping~
|
867 | 886 | **/
|
868 |
| - Mobilebone.handleTapEvent = function(event) { |
| 887 | + Mobilebone.handleTapEvent = function(event) { |
869 | 888 | /**
|
870 | 889 | // iscroll(set tap: true) may cause twice tap problem
|
871 | 890 | // which is none of Mobilebone's business
|
|
892 | 911 | var self_page = document.querySelector(".in." + Mobilebone.classPage);
|
893 | 912 |
|
894 | 913 | if (self_page == null || !target) return;
|
895 |
| - |
| 914 | + |
896 | 915 | // optional params for Mobilebone.transition
|
897 | 916 | var options = {
|
898 | 917 | target: target
|
|
946 | 965 | // 3. cros, or not capture (except data-ajax="true")
|
947 | 966 | if (!href) return;
|
948 | 967 |
|
| 968 | + href = href.replace("#&", "#"); |
| 969 | + |
949 | 970 | if (target.getAttribute("href").replace(/#/g, "") === "") {
|
950 | 971 | event.preventDefault();
|
951 | 972 | return;
|
|
1045 | 1066 | * page change when history change
|
1046 | 1067 | **/
|
1047 | 1068 | window.addEventListener("popstate", function() {
|
1048 |
| - |
| 1069 | + if (history.popstateswipe == true) { |
| 1070 | + location.reload(); |
| 1071 | + history.popstateswipe = false; |
| 1072 | + return; |
| 1073 | + } |
1049 | 1074 | if (history.popstate == false) {
|
1050 | 1075 | history.popstate = true;
|
1051 | 1076 | return;
|
|
1086 | 1111 | });
|
1087 | 1112 | }
|
1088 | 1113 | });
|
1089 |
| - |
| 1114 | + |
1090 | 1115 | return Mobilebone;
|
1091 | 1116 | });
|
| 1117 | + |
0 commit comments