fullPage.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. function FullPage(options) {
  2. "use strict";
  3. var pageContain = document.getElementById(options.id),
  4. page = pageContain.children,
  5. pagelen = page.length,
  6. iPage = pagelen,
  7. sTime = options.slideTime || 800,
  8. effect = options.effect || {},
  9. indexNow = 0,
  10. browser = {},
  11. pageRange = {},
  12. cubicCurve = {},
  13. pageStyle = [],
  14. mode = [],
  15. modeLen,
  16. navChildren,
  17. SPACE = ' ',
  18. _interval = null,
  19. _isLocked = false,
  20. _isNav = false,
  21. _curve,
  22. _t,
  23. _fix,
  24. init,
  25. setCubic,
  26. trans,
  27. resetAndRun,
  28. onTap,
  29. replaceClass,
  30. goPage,
  31. navChange,
  32. wheelScroll;
  33. if (!page || pagelen === 1) return;
  34. if (options.mode) {
  35. _isNav = options.mode.indexOf('nav:') !== -1;
  36. mode = options.mode.split(',');
  37. modeLen = mode.length;
  38. }
  39. for (_t = 0; _t < pagelen; _t++) {
  40. pageStyle.push(page[_t].style);
  41. }
  42. browser = {
  43. addEventListener : !!window.addEventListener,
  44. gravity : !!window.DeviceOrientationEvent,
  45. touch : ('ontouchstart' in window) ||
  46. window.DocumentTouch && document instanceof DocumentTouch,
  47. version: function() {
  48. var u = navigator.userAgent,
  49. matchVersion = u.indexOf('Android'),
  50. num;
  51. _fix = u.indexOf('QQBrowser') !== -1 ? 200 : 0;
  52. if (matchVersion !== -1) {
  53. num = u.substring(matchVersion + 7, matchVersion + 11).replace(' ', '');
  54. }
  55. return num || 0; //0: not Android device
  56. }(),
  57. cssCore: function(testCss) {
  58. switch (true) {
  59. case testCss.webkitTransition === '':
  60. return 'webkit'; break;
  61. case testCss.MozTransition === '':
  62. return 'Moz'; break;
  63. case testCss.msTransition === '':
  64. return 'ms'; break;
  65. case testCss.OTransition === '':
  66. return 'O'; break;
  67. default:
  68. return '';
  69. }
  70. }(document.createElement('Chriswang').style)
  71. };
  72. function UnitBezier(p1x, p1y, p2x, p2y) {
  73. // pre-calculate the polynomial coefficients
  74. // First and last control points are implied to be (0,0) and (1.0, 1.0)
  75. this.cx = 3.0 * p1x;
  76. this.bx = 3.0 * (p2x - p1x) - this.cx;
  77. this.ax = 1.0 - this.cx -this.bx;
  78. this.cy = 3.0 * p1y;
  79. this.by = 3.0 * (p2y - p1y) - this.cy;
  80. this.ay = 1.0 - this.cy - this.by;
  81. }
  82. UnitBezier.prototype = {
  83. epsilon : 1e-5, // Precision
  84. sampleCurveX : function(t) {
  85. return ((this.ax * t + this.bx) * t + this.cx) * t;
  86. },
  87. sampleCurveY : function(t) {
  88. return ((this.ay * t + this.by) * t + this.cy) * t;
  89. },
  90. sampleCurveDerivativeX : function(t) {
  91. return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx;
  92. },
  93. solveCurveX : function(x, epsilon) {
  94. var t0,
  95. t1,
  96. t2,
  97. x2,
  98. d2,
  99. i;
  100. // First try a few iterations of Newton's method -- normally very fast.
  101. for (t2 = x, i = 0; i < 8; i++) {
  102. x2 = this.sampleCurveX(t2) - x;
  103. if (Math.abs (x2) < epsilon)
  104. return t2;
  105. d2 = this.sampleCurveDerivativeX(t2);
  106. if (Math.abs(d2) < epsilon)
  107. break;
  108. t2 = t2 - x2 / d2;
  109. }
  110. // No solution found - use bi-section
  111. t0 = 0.0;
  112. t1 = 1.0;
  113. t2 = x;
  114. if (t2 < t0) return t0;
  115. if (t2 > t1) return t1;
  116. while (t0 < t1) {
  117. x2 = this.sampleCurveX(t2);
  118. if (Math.abs(x2 - x) < epsilon)
  119. return t2;
  120. if (x > x2) t0 = t2;
  121. else t1 = t2;
  122. t2 = (t1 - t0) * .5 + t0;
  123. }
  124. // Give up
  125. return t2;
  126. },
  127. // Find new T as a function of Y along curve X
  128. solve : function(x, epsilon) {
  129. return this.sampleCurveY( this.solveCurveX(x, epsilon) );
  130. }
  131. }
  132. init = function() {
  133. var i = pagelen;
  134. pageRange = {
  135. X : document.documentElement.clientWidth || window.innerWidth,
  136. Y : document.documentElement.clientHeight || window.innerHeight
  137. }
  138. pageContain.style.height = pageRange.Y + 'px';
  139. }
  140. setCubic = function(a, b, c, d) {
  141. cubicCurve.A = a;
  142. cubicCurve.B = b;
  143. cubicCurve.C = c;
  144. cubicCurve.D = d;
  145. }
  146. if (typeof options.easing === 'string') {
  147. switch (options.easing) {
  148. case 'ease' :
  149. setCubic(0.25, 0.1, 0.25, 1);
  150. break;
  151. case 'linear' :
  152. setCubic(0, 0, 1, 1);
  153. break;
  154. case 'ease-in' :
  155. setCubic(0.42, 0, 1, 1);
  156. break;
  157. case 'ease-out' :
  158. setCubic(0, 0, 0.58, 1);
  159. break;
  160. case 'ease-in-out' :
  161. setCubic(0.42, 0, 0.58, 1);
  162. break;
  163. }
  164. } else {
  165. setCubic(options.easing[0], options.easing[1], options.easing[2], options.easing[3]);
  166. }
  167. if (browser.cssCore !== '') {
  168. while (iPage--) {
  169. pageStyle[iPage][browser.cssCore + 'TransitionTimingFunction'] = 'cubic-bezier('
  170. + cubicCurve.A + ','
  171. + cubicCurve.B + ','
  172. + cubicCurve.C + ','
  173. + cubicCurve.D + ')';
  174. }
  175. trans = function(o, x, y, t) {
  176. var s = o.style,
  177. c = 'translate(' + x +'px,' + y + 'px) translateZ(0)',
  178. a = arguments[4];
  179. if (a.scale) {
  180. c += t === 0 ? ' scale(' + a.scale[0] + ')'
  181. : ' scale(' + a.scale[1] + ')';
  182. }
  183. if (a.rotate) {
  184. c += t === 0 ? ' rotate(' + a.rotate[0] + 'deg)'
  185. : ' rotate(' + a.rotate[1] + 'deg)';
  186. }
  187. s[browser.cssCore + 'TransformOrigin'] = '50% 50%';
  188. s[browser.cssCore + 'Transform'] = c;
  189. }
  190. } else {
  191. // simulate translate for ie9-
  192. // Cubic-bezier : Fn(t) = (3p1-3p2+1)t^3+(3p2-6p1)t^2-3p1t.
  193. _curve = new UnitBezier(cubicCurve.A, cubicCurve.B, cubicCurve.C, cubicCurve.D);
  194. trans = function(o, x, y, t) {
  195. var cs = o.currentStyle,
  196. s = o.style,
  197. cx = parseInt(s.left || cs.left, 10),
  198. cy = parseInt(s.top || cs.top, 10),
  199. dx = x - cx,
  200. dy = y - cy,
  201. ft = +new Date,
  202. end = ft + t,
  203. pos = 0,
  204. e = effect.opacity,
  205. diff;
  206. clearInterval(_interval);
  207. _interval = setInterval(function() {
  208. var _t;
  209. if (+new Date > end) {
  210. _t = e ? 'left:' + x + 'px;top:' + y + 'px;filter:alpha(opacity=' + 100 * e[1] + ');'
  211. : 'left:' + x + 'px;top:' + y + 'px;';
  212. clearInterval(_interval);
  213. } else {
  214. diff = end - new Date;
  215. pos = diff / t;
  216. // fix to cubic-bezier
  217. pos = _curve.solve(1 - pos, UnitBezier.prototype.epsilon);
  218. _t = 'left:' + (cx + dx * pos)
  219. + 'px;top:' + (cy + dy * pos)
  220. + 'px;'
  221. if (e) {
  222. _t += 'filter:alpha(opacity=' + 100 * ( e[1] * pos - e[0] * (1 - pos) )+ ');'
  223. }
  224. }
  225. s.cssText = _t;
  226. }, 13);
  227. }
  228. }
  229. resetAndRun = {
  230. transform : function(o, from, to) {
  231. var rangeNow = 0,
  232. fix = browser.cssCore === ''
  233. && (o['translate'] === 'none' || !o.translate ) ? -50 : _fix;
  234. switch (o['translate']) {
  235. case 'Y' :
  236. rangeNow = to > from ? pageRange.Y : - pageRange.Y;
  237. trans(page[to], 0, rangeNow, 0, o);
  238. break;
  239. case 'X' :
  240. rangeNow = to > from ? pageRange.X : - pageRange.X;
  241. trans(page[to], rangeNow, 0, 0, o);
  242. break;
  243. case 'XY' :
  244. rangeNow = {
  245. X : to > from ? pageRange.X : - pageRange.X,
  246. Y : to > from ? pageRange.Y : - pageRange.Y
  247. }
  248. trans(page[to], rangeNow.X, rangeNow.Y, 0, o);
  249. break;
  250. default:
  251. trans(page[to], 0, 0, 0, o);
  252. break;
  253. }
  254. setTimeout(function() {
  255. trans(page[to], 0, 0, sTime, o);
  256. }, fix + 50);
  257. },
  258. opacity : function(o, from, to) {
  259. var s = page[to].style;
  260. s.opacity = o[0];
  261. setTimeout(function() {
  262. s.opacity = o[1];
  263. }, 70);
  264. }
  265. }
  266. if (browser.addEventListener && browser.touch) {
  267. if (navigator.userAgent.indexOf('Firefox')) {
  268. onTap = function(o, fn) {
  269. o.addEventListener('click', fn, false);
  270. }
  271. } else {
  272. onTap = function (o, fn) {
  273. o.addEventListener('touchstart', fn, false);
  274. if (arguments[2]) {
  275. // if we touch on navBar we should stop scroll
  276. o.addEventListener('touchmove', function(e) {
  277. e.preventDefault();
  278. }, false);
  279. }
  280. }
  281. }
  282. } else {
  283. onTap = function (o, fn) {
  284. o.onclick = fn;
  285. }
  286. }
  287. replaceClass = function(o, cls, tocls) {
  288. var oN = o.className,
  289. arr = [],
  290. len;
  291. if (oN.indexOf(cls) !== -1) {
  292. arr = oN.split(SPACE);
  293. len = arr.length;
  294. while (len--) {
  295. if (arr[len] === cls) {
  296. if (tocls === SPACE || tocls === '') {
  297. arr.splice(len, 1);
  298. } else {
  299. arr[len] = tocls;
  300. }
  301. }
  302. }
  303. if (arr.length) {
  304. o.className = arr.join(SPACE);
  305. } else {
  306. o.removeAttribute('class');
  307. o.removeAttribute('className');
  308. }
  309. }
  310. }
  311. if (_isNav) {
  312. navChange = function(from, to) {
  313. var t = navChildren[to].className;
  314. replaceClass(navChildren[from], 'active', SPACE);
  315. navChildren[to].className = t === '' ? 'active' : t + ' active';
  316. }
  317. }
  318. goPage = function(to) {
  319. var fix = _fix,
  320. indexOld,
  321. _effectNow;
  322. if (_isLocked // make sure translate is already
  323. || to === indexNow // don't translate if thispage
  324. || to >= pagelen // more than max page
  325. || to < 0) return; // less than min page(0)
  326. _isLocked = true;
  327. for (_effectNow in effect) {
  328. resetAndRun[_effectNow](effect[_effectNow], indexNow, to);
  329. }
  330. fix += browser.cssCore === '' ? 20 : 0 ;
  331. indexOld = indexNow;
  332. indexNow = to;
  333. if (_isNav) navChange(indexOld, indexNow);
  334. setTimeout(function() {
  335. // fix for bug in ie6-9 about z-index
  336. page[to].className += ' slide';
  337. }, fix);
  338. setTimeout(function() {
  339. pageStyle[to][browser.cssCore + 'TransitionDuration'] = sTime + 'ms';
  340. }, 20);
  341. setTimeout(function() {
  342. replaceClass(page[indexOld], 'current', '');
  343. replaceClass(page[indexNow], 'slide', 'current');
  344. if (options.callback) {
  345. options.callback(indexNow, page[indexNow]);
  346. }
  347. _isLocked = false;
  348. }, sTime + _fix + 120);
  349. $('video').trigger('pause');
  350. $('audio').trigger('pause');
  351. }
  352. init();
  353. // Tag first page
  354. _t = page[indexNow].className;
  355. page[indexNow].className = _t.indexOf('current') !== -1 ? _t : _t + ' current';
  356. if (browser.addEventListener) {
  357. window.addEventListener('resize', init, false);
  358. } else {
  359. window.onresize = init;
  360. }
  361. // check mode
  362. while (modeLen--) {
  363. (function(m) {
  364. switch (true) {
  365. case m === 'wheel' :
  366. wheelScroll = function(e) {
  367. var direct;
  368. e = e || window.event;
  369. if (e.preventDefault) {
  370. e.preventDefault();
  371. } else {
  372. e.returnValue = false;
  373. }
  374. if (_isLocked) return;
  375. direct = - e.wheelDelta || e.detail;
  376. direct = direct < 0 ? -1 : 1;
  377. goPage(indexNow + direct);
  378. //alert("测试");
  379. }
  380. if (browser.addEventListener) {
  381. document.addEventListener('DOMMouseScroll', wheelScroll, false);
  382. }
  383. window.onmousewheel = document.onmousewheel = wheelScroll;
  384. break;
  385. case m === 'touch' :
  386. if (!browser.touch || !browser.addEventListener) break;
  387. (function() {
  388. var pageIndexMax = pagelen - 1,
  389. scaleStart = effect.transform.scale[0],
  390. scaleDiff = effect.transform.scale[1] - scaleStart,
  391. rotateStart = effect.transform.rotate[0],
  392. rotateDiff = effect.transform.rotate[1] - rotateStart,
  393. opacityStart = effect.opacity[0],
  394. opacityDiff = effect.opacity[1] - opacityStart,
  395. touchEvent = {},
  396. start = {},
  397. delta = {},
  398. isValidMove = false,
  399. prev,
  400. next,
  401. setIndex,
  402. reset,
  403. validReset,
  404. move,
  405. _interval,
  406. _t;
  407. if (effect.transform.translate === 'Y') {
  408. setIndex = function() {
  409. prev = pageStyle[indexNow - 1];
  410. next = pageStyle[indexNow + 1];
  411. if (prev) {
  412. prev[browser.cssCore + 'TransitionDuration'] = '0ms';
  413. prev[browser.cssCore + 'Transform'] = 'translate(0,-' + pageRange.Y + 'px) translateZ(0)';
  414. prev[browser.cssCore + 'TransformOrigin'] = '50% 100%';
  415. page[indexNow - 1].className += ' swipe';
  416. }
  417. if (next) {
  418. next[browser.cssCore + 'TransitionDuration'] = '0ms';
  419. next[browser.cssCore + 'Transform'] = 'translate(0,' + pageRange.Y + 'px) translateZ(0)';
  420. next[browser.cssCore + 'TransformOrigin'] = '50% 0%';
  421. page[indexNow + 1].className += ' swipe';
  422. }
  423. }
  424. move = function (o) {
  425. var pos = Math.abs(o.y / pageRange.Y),
  426. _t = ' scale(' + (scaleStart + scaleDiff * pos)
  427. + ') rotate(' + (rotateStart + rotateDiff * pos) + 'deg)';
  428. if (prev && o.y > 0) {
  429. prev.opacity = (opacityStart + opacityDiff * pos);
  430. prev[browser.cssCore + 'Transform'] = 'translate(0,' + (o.y - pageRange.Y) + 'px) translateZ(0)' + _t;
  431. }
  432. if (next && o.y < 0) {
  433. next.opacity = (opacityStart + opacityDiff * pos);
  434. next[browser.cssCore + 'Transform'] = 'translate(0,' + (pageRange.Y + o.y) + 'px) translateZ(0)' + _t;
  435. }
  436. }
  437. reset = function(s, n) {
  438. var _t = sTime >> 1;
  439. replaceClass(page[indexNow + n], 'swipe', 'slide');
  440. s.opacity = 1;
  441. s[browser.cssCore + 'TransitionDuration'] = _t + 'ms';
  442. s[browser.cssCore + 'Transform'] = 'translate(0,'+ n * pageRange.Y + 'px) translateZ(0)';
  443. setTimeout(function() {
  444. replaceClass(page[indexNow + n], 'slide', '');
  445. setTimeout(function() {
  446. _isLocked = false;
  447. }, 50);
  448. }, _t);
  449. }
  450. validReset = function(s, n) {
  451. var to = indexNow + n,
  452. _t = ~~(sTime / 1.5),
  453. _o = page[indexNow - n];
  454. if (_o) {
  455. replaceClass(_o, 'swipe', '');
  456. }
  457. if (to < 0 || to > pagelen - 1) {
  458. setTimeout(function() {
  459. _isLocked = false;
  460. }, 50);
  461. return;
  462. }
  463. if (_isNav) {
  464. navChange(indexNow, to);
  465. }
  466. s.opacity = 1;
  467. replaceClass(page[to], 'swipe', 'slide');
  468. s[browser.cssCore + 'TransitionDuration'] = _t + 'ms';
  469. s[browser.cssCore + 'Transform'] = 'translate(0,0) translateZ(0)';
  470. setTimeout(function() {
  471. replaceClass(page[indexNow], 'current', '');
  472. replaceClass(page[to], 'slide', 'current');
  473. indexNow = to;
  474. if (options.callback) {
  475. options.callback(indexNow, page[indexNow]);
  476. }
  477. setTimeout(function() {
  478. _isLocked = false;
  479. }, 50)
  480. }, _t);
  481. }
  482. } else {
  483. setIndex = function() {
  484. prev = pageStyle[indexNow - 1];
  485. next = pageStyle[indexNow + 1];
  486. if (prev) {
  487. prev[browser.cssCore + 'TransitionDuration'] = '0ms';
  488. prev[browser.cssCore + 'Transform'] = 'translate(-' + pageRange.X + 'px,0) translateZ(0)';
  489. prev[browser.cssCore + 'TransformOrigin'] = '100% 50%';
  490. page[indexNow - 1].className += ' swipe';
  491. }
  492. if (next) {
  493. next[browser.cssCore + 'TransitionDuration'] = '0ms';
  494. next[browser.cssCore + 'Transform'] = 'translate(' + pageRange.X + 'px,0) translateZ(0)';
  495. next[browser.cssCore + 'TransformOrigin'] = '0 50%';
  496. page[indexNow + 1].className += ' swipe';
  497. }
  498. }
  499. move = function (o) {
  500. var pos = Math.abs(o.x / pageRange.X),
  501. _t = ' scale(' + (scaleStart + scaleDiff * pos)
  502. + ') rotate(' + (rotateStart + rotateDiff * pos) + 'deg)';
  503. if (prev && o.x > 0) {
  504. console.log()
  505. prev.opacity = (opacityStart + opacityDiff * pos);
  506. prev[browser.cssCore + 'Transform'] = 'translate(' + (o.x - pageRange.X) + 'px,0) translateZ(0)' + _t;
  507. }
  508. if (next && o.x < 0) {
  509. next.opacity = (opacityStart + opacityDiff * pos);
  510. next[browser.cssCore + 'Transform'] = 'translate(' + (pageRange.X + o.x) + 'px,0) translateZ(0)' + _t;
  511. }
  512. }
  513. reset = function(s, n) {
  514. var _t = sTime >> 1;
  515. replaceClass(page[indexNow + n], 'swipe', 'slide');
  516. s.opacity = 1;
  517. s[browser.cssCore + 'TransitionDuration'] = _t + 'ms';
  518. s[browser.cssCore + 'Transform'] = 'translate('+ n * pageRange.X + 'px,0) translateZ(0)';
  519. setTimeout(function() {
  520. replaceClass(page[indexNow + n], 'slide', '');
  521. setTimeout(function() {
  522. _isLocked = false;
  523. }, 50);
  524. }, _t);
  525. }
  526. validReset = function(s, n) {
  527. var to = indexNow + n,
  528. _t = ~~(sTime / 1.5),
  529. _o = page[indexNow - n];
  530. if (_o) {
  531. replaceClass(_o, 'swipe', '');
  532. }
  533. if (to < 0 || to > pagelen - 1) {
  534. setTimeout(function() {
  535. _isLocked = false;
  536. }, 50);
  537. return;
  538. }
  539. if (_isNav) {
  540. navChange(indexNow, to);
  541. }
  542. replaceClass(page[to], 'swipe', 'slide');
  543. s.opacity = 1;
  544. s[browser.cssCore + 'TransitionDuration'] = _t + 'ms';
  545. s[browser.cssCore + 'Transform'] = 'translate(0,0) translateZ(0)';
  546. setTimeout(function() {
  547. replaceClass(page[indexNow], 'current', '');
  548. replaceClass(page[to], 'slide', 'current');
  549. indexNow = to;
  550. if (options.callback) {
  551. options.callback(indexNow, page[indexNow]);
  552. }
  553. setTimeout(function() {
  554. _isLocked = false;
  555. }, 50)
  556. }, _t);
  557. }
  558. }
  559. touchEvent = {
  560. start : function(e) {
  561. var touches = e.touches[0];
  562. if (_isLocked) return;
  563. _isLocked = true;
  564. start = {
  565. x : touches.pageX,
  566. y : touches.pageY,
  567. time : +new Date
  568. }
  569. // reset
  570. delta = {};
  571. isValidMove = false;
  572. setIndex();
  573. pageContain.addEventListener('touchmove', touchEvent.move, false);
  574. pageContain.addEventListener('touchend', touchEvent.end, false);
  575. },
  576. move : function(e) {
  577. var touches = e.touches[0];
  578. e.preventDefault();
  579. // ensure swiping with one touch and not pinching
  580. if ( event.touches.length > 1 || event.scale && event.scale !== 1) return
  581. delta = {
  582. x : touches.pageX - start.x,
  583. y : touches.pageY - start.y
  584. }
  585. if (!isValidMove) {
  586. _t = Math.abs(delta.x) > Math.abs(delta.y) ? 'X' : 'Y';
  587. _t = _t === options.effect.transform['translate'] ? true : false;
  588. isValidMove = true;
  589. } else {
  590. if (_t) move(delta);
  591. }
  592. },
  593. end : function(e) {
  594. var touches = e.changedTouches[0],
  595. duration = +new Date - start.time,
  596. abs = {},
  597. nextDiff = 0,
  598. isValidSlide = false;
  599. delta = {
  600. x : touches.pageX - start.x,
  601. y : touches.pageY - start.y
  602. }
  603. abs = {
  604. x : Math.abs(delta.x),
  605. y : Math.abs(delta.y)
  606. }
  607. switch (options.effect.transform['translate']) {
  608. case 'Y' :
  609. isValidSlide =
  610. + duration < 250 && abs.y > 30
  611. || abs.y > pageRange.Y * .3;
  612. nextDiff = delta.y > 0 ? -1 : 1;
  613. break;
  614. case 'X' :
  615. isValidSlide =
  616. + duration < 250 && abs.x > 30
  617. || abs.x > pageRange.X * .3;
  618. nextDiff = delta.x > 0 ? -1 : 1;
  619. break;
  620. default :
  621. isValidSlide =
  622. + duration < 350 && abs.y + abs.x > 50
  623. || abs.y > pageRange.Y * .3
  624. || abs.x > pageRange.X * .3;
  625. nextDiff = abs.x > abs.y ?
  626. delta.x > 0 ? -1 : 1
  627. : delta.y > 0 ? -1 : 1;
  628. break;
  629. }
  630. if (!isValidSlide || !_t) {
  631. if (prev) reset(prev, - 1);
  632. if (next) reset(next, + 1);
  633. } else {
  634. if (nextDiff === -1) {
  635. validReset(prev, -1);
  636. } else {
  637. validReset(next, 1);
  638. }
  639. }
  640. pageContain.removeEventListener('touchmove', touchEvent.move, false);
  641. pageContain.removeEventListener('touchend', touchEvent.end, false);
  642. }
  643. }
  644. pageContain.addEventListener('touchstart', touchEvent.start, false);
  645. }());
  646. break;
  647. case m.indexOf('nav:') !== -1 :
  648. (function() {
  649. var navId = m.split(':')[1],
  650. navObj = document.getElementById(navId),
  651. navLen,
  652. gotoPage,
  653. _t;
  654. navChildren = navObj.children;
  655. navLen = navChildren.length;
  656. _t = navChildren[indexNow].className;
  657. if (!navObj || !navChildren) return;
  658. while (navLen--) {
  659. // set attr for finding specific page
  660. navChildren[navLen].setAttribute('data-page', navLen);
  661. }
  662. if (_t.indexOf('active') === -1) {
  663. navChildren[indexNow].className = _t === '' ? 'active' : _t + ' active';
  664. }
  665. gotoPage = function(e) {
  666. var t;
  667. e = e || window.event;
  668. e = e.target || e.srcElement;
  669. t = e.tagName.toLowerCase();
  670. while (t !== 'li') {
  671. if (t === 'ul') return;
  672. e = e.parentNode;
  673. t = e.tagName.toLowerCase();
  674. }
  675. goPage( + e.getAttribute('data-page') );
  676. }
  677. // bind event to navObj
  678. onTap(navObj, gotoPage, 1);
  679. }());
  680. }
  681. }(mode[modeLen]));
  682. }
  683. return {
  684. thisPage : function() {
  685. return indexNow;
  686. },
  687. go : function(num) {
  688. goPage(num);
  689. },
  690. next : function() {
  691. goPage(indexNow + 1);
  692. },
  693. prev : function() {
  694. goPage(indexNow - 1);
  695. }
  696. }
  697. }