/KitJs/src/labs/iScroll/iscroll.js

https://github.com/wuxq/KitJs · JavaScript · 666 lines · 524 code · 98 blank · 44 comment · 169 complexity · c38a4facfd10d222394e65ebec2bd699 MD5 · raw file

  1. /**
  2. * @ignore
  3. * Find more about the scrolling function at
  4. * http://cubiq.org/iscroll
  5. *
  6. * Copyright (c) 2010 Matteo Spinelli, http://cubiq.org/
  7. * Released under MIT license
  8. * http://cubiq.org/dropbox/mit-license.txt
  9. *
  10. * Version 3.7.1 - Last updated: 2010.10.08
  11. *
  12. */
  13. (function() {
  14. function iScroll(el, options) {
  15. var that = this, i;
  16. that.element = typeof el == 'object' ? el : document.getElementById(el);
  17. that.wrapper = that.element.parentNode;
  18. that.element.style.webkitTransitionProperty = '-webkit-transform';
  19. that.element.style.webkitTransitionTimingFunction = 'cubic-bezier(0,0,0.25,1)';
  20. that.element.style.webkitTransitionDuration = '0';
  21. that.element.style.webkitTransform = translateOpen + '0,0' + translateClose;
  22. // Default options
  23. that.options = {
  24. bounce : has3d,
  25. momentum : has3d,
  26. checkDOMChanges : true,
  27. topOnDOMChanges : false,
  28. hScrollbar : has3d,
  29. vScrollbar : has3d,
  30. fadeScrollbar : isIthing || !isTouch,
  31. shrinkScrollbar : isIthing || !isTouch,
  32. desktopCompatibility : false,
  33. overflow : 'auto',
  34. snap : false,
  35. bounceLock : false,
  36. scrollbarColor : 'rgba(0,0,0,0.5)',
  37. onScrollEnd : function() {
  38. }
  39. };
  40. // User defined options
  41. if( typeof options == 'object') {
  42. for(i in options) {
  43. that.options[i] = options[i];
  44. }
  45. }
  46. if(that.options.desktopCompatibility) {
  47. that.options.overflow = 'hidden';
  48. }
  49. that.onScrollEnd = that.options.onScrollEnd;
  50. delete that.options.onScrollEnd;
  51. that.wrapper.style.overflow = that.options.overflow;
  52. that.refresh();
  53. window.addEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', that, false);
  54. if(isTouch || that.options.desktopCompatibility) {
  55. that.element.addEventListener(START_EVENT, that, false);
  56. that.element.addEventListener(MOVE_EVENT, that, false);
  57. that.element.addEventListener(END_EVENT, that, false);
  58. }
  59. if(that.options.checkDOMChanges) {
  60. that.element.addEventListener('DOMSubtreeModified', that, false);
  61. }
  62. }
  63. iScroll.prototype = {
  64. x : 0,
  65. y : 0,
  66. enabled : true,
  67. handleEvent : function(e) {
  68. var that = this;
  69. switch (e.type) {
  70. case START_EVENT:
  71. that.touchStart(e);
  72. break;
  73. case MOVE_EVENT:
  74. that.touchMove(e);
  75. break;
  76. case END_EVENT:
  77. that.touchEnd(e);
  78. break;
  79. case 'webkitTransitionEnd':
  80. that.transitionEnd();
  81. break;
  82. case 'orientationchange':
  83. case 'resize':
  84. that.refresh();
  85. break;
  86. case 'DOMSubtreeModified':
  87. that.onDOMModified(e);
  88. break;
  89. }
  90. },
  91. onDOMModified : function(e) {
  92. var that = this;
  93. // (Hopefully) execute onDOMModified only once
  94. if(e.target.parentNode != that.element) {
  95. return;
  96. }
  97. setTimeout(function() {
  98. that.refresh();
  99. }, 0);
  100. if(that.options.topOnDOMChanges && (that.x != 0 || that.y != 0)) {
  101. that.scrollTo(0, 0, '0');
  102. }
  103. },
  104. refresh : function() {
  105. var that = this, resetX = that.x, resetY = that.y, snap;
  106. that.scrollWidth = that.wrapper.clientWidth;
  107. that.scrollHeight = that.wrapper.clientHeight;
  108. that.scrollerWidth = that.element.offsetWidth;
  109. that.scrollerHeight = that.element.offsetHeight;
  110. that.maxScrollX = that.scrollWidth - that.scrollerWidth;
  111. that.maxScrollY = that.scrollHeight - that.scrollerHeight;
  112. that.directionX = 0;
  113. that.directionY = 0;
  114. if(that.scrollX) {
  115. if(that.maxScrollX >= 0) {
  116. resetX = 0;
  117. } else if(that.x < that.maxScrollX) {
  118. resetX = that.maxScrollX;
  119. }
  120. }
  121. if(that.scrollY) {
  122. if(that.maxScrollY >= 0) {
  123. resetY = 0;
  124. } else if(that.y < that.maxScrollY) {
  125. resetY = that.maxScrollY;
  126. }
  127. }
  128. // Snap
  129. if(that.options.snap) {
  130. that.maxPageX = -Math.floor(that.maxScrollX / that.scrollWidth);
  131. that.maxPageY = -Math.floor(that.maxScrollY / that.scrollHeight);
  132. snap = that.snap(resetX, resetY);
  133. resetX = snap.x;
  134. resetY = snap.y;
  135. }
  136. if(resetX != that.x || resetY != that.y) {
  137. that.setTransitionTime('0');
  138. that.setPosition(resetX, resetY, true);
  139. }
  140. that.scrollX = that.scrollerWidth > that.scrollWidth;
  141. that.scrollY = !that.options.bounceLock && !that.scrollX || that.scrollerHeight > that.scrollHeight;
  142. // Update horizontal scrollbar
  143. if(that.options.hScrollbar && that.scrollX) {
  144. that.scrollBarX = that.scrollBarX || new scrollbar('horizontal', that.wrapper, that.options.fadeScrollbar, that.options.shrinkScrollbar, that.options.scrollbarColor);
  145. that.scrollBarX.init(that.scrollWidth, that.scrollerWidth);
  146. } else if(that.scrollBarX) {
  147. that.scrollBarX = that.scrollBarX.remove();
  148. }
  149. // Update vertical scrollbar
  150. if(that.options.vScrollbar && that.scrollY && that.scrollerHeight > that.scrollHeight) {
  151. that.scrollBarY = that.scrollBarY || new scrollbar('vertical', that.wrapper, that.options.fadeScrollbar, that.options.shrinkScrollbar, that.options.scrollbarColor);
  152. that.scrollBarY.init(that.scrollHeight, that.scrollerHeight);
  153. } else if(that.scrollBarY) {
  154. that.scrollBarY = that.scrollBarY.remove();
  155. }
  156. },
  157. setPosition : function(x, y, hideScrollBars) {
  158. var that = this;
  159. that.x = x;
  160. that.y = y;
  161. that.element.style.webkitTransform = translateOpen + that.x + 'px,' + that.y + 'px' + translateClose;
  162. // Move the scrollbars
  163. if(!hideScrollBars) {
  164. if(that.scrollBarX) {
  165. that.scrollBarX.setPosition(that.x);
  166. }
  167. if(that.scrollBarY) {
  168. that.scrollBarY.setPosition(that.y);
  169. }
  170. }
  171. },
  172. setTransitionTime : function(time) {
  173. var that = this;
  174. time = time || '0';
  175. that.element.style.webkitTransitionDuration = time;
  176. if(that.scrollBarX) {
  177. that.scrollBarX.bar.style.webkitTransitionDuration = time;
  178. that.scrollBarX.wrapper.style.webkitTransitionDuration = has3d && that.options.fadeScrollbar ? '300ms' : '0';
  179. }
  180. if(that.scrollBarY) {
  181. that.scrollBarY.bar.style.webkitTransitionDuration = time;
  182. that.scrollBarY.wrapper.style.webkitTransitionDuration = has3d && that.options.fadeScrollbar ? '300ms' : '0';
  183. }
  184. },
  185. touchStart : function(e) {
  186. var that = this, matrix;
  187. if(!that.enabled) {
  188. return;
  189. }
  190. e.preventDefault();
  191. e.stopPropagation();
  192. that.scrolling = true;
  193. // This is probably not needed, but may be useful if iScroll is used in conjuction with other frameworks
  194. that.moved = false;
  195. that.distX = 0;
  196. that.distY = 0;
  197. that.setTransitionTime('0');
  198. // Check if the scroller is really where it should be
  199. if(that.options.momentum || that.options.snap) {
  200. matrix = new WebKitCSSMatrix(window.getComputedStyle(that.element).webkitTransform);
  201. if(matrix.e != that.x || matrix.f != that.y) {
  202. document.removeEventListener('webkitTransitionEnd', that, false);
  203. that.setPosition(matrix.e, matrix.f);
  204. that.moved = true;
  205. }
  206. }
  207. that.touchStartX = isTouch ? e.changedTouches[0].pageX : e.pageX;
  208. that.scrollStartX = that.x;
  209. that.touchStartY = isTouch ? e.changedTouches[0].pageY : e.pageY;
  210. that.scrollStartY = that.y;
  211. that.scrollStartTime = e.timeStamp;
  212. that.directionX = 0;
  213. that.directionY = 0;
  214. },
  215. touchMove : function(e) {
  216. if(!this.scrolling) {
  217. return;
  218. }
  219. var that = this, pageX = isTouch ? e.changedTouches[0].pageX : e.pageX, pageY = isTouch ? e.changedTouches[0].pageY : e.pageY, leftDelta = that.scrollX ? pageX - that.touchStartX : 0, topDelta = that.scrollY ? pageY - that.touchStartY : 0, newX = that.x + leftDelta, newY = that.y + topDelta;
  220. //e.preventDefault();
  221. e.stopPropagation();
  222. // Stopping propagation just saves some cpu cycles (I presume)
  223. that.touchStartX = pageX;
  224. that.touchStartY = pageY;
  225. // Slow down if outside of the boundaries
  226. if(newX >= 0 || newX < that.maxScrollX) {
  227. newX = that.options.bounce ? Math.round(that.x + leftDelta / 3) : (newX >= 0 || that.maxScrollX >= 0) ? 0 : that.maxScrollX;
  228. }
  229. if(newY >= 0 || newY < that.maxScrollY) {
  230. newY = that.options.bounce ? Math.round(that.y + topDelta / 3) : (newY >= 0 || that.maxScrollY >= 0) ? 0 : that.maxScrollY;
  231. }
  232. if(that.distX + that.distY > 5) {// 5 pixels threshold
  233. // Lock scroll direction
  234. if(that.distX - 3 > that.distY) {
  235. newY = that.y;
  236. topDelta = 0;
  237. } else if(that.distY - 3 > that.distX) {
  238. newX = that.x;
  239. leftDelta = 0;
  240. }
  241. that.setPosition(newX, newY);
  242. that.moved = true;
  243. that.directionX = leftDelta > 0 ? -1 : 1;
  244. that.directionY = topDelta > 0 ? -1 : 1;
  245. } else {
  246. that.distX += Math.abs(leftDelta);
  247. that.distY += Math.abs(topDelta);
  248. // that.dist+= Math.abs(leftDelta) + Math.abs(topDelta);
  249. }
  250. },
  251. touchEnd : function(e) {
  252. if(!this.scrolling) {
  253. return;
  254. }
  255. var that = this, time = e.timeStamp - that.scrollStartTime, point = isTouch ? e.changedTouches[0] : e, target, ev, momentumX, momentumY, newDuration = 0, newPositionX = that.x, newPositionY = that.y, snap;
  256. that.scrolling = false;
  257. if(!that.moved) {
  258. that.resetPosition();
  259. if(isTouch) {
  260. // Find the last touched element
  261. target = point.target;
  262. while(target.nodeType != 1) {
  263. target = target.parentNode;
  264. }
  265. // Create the fake event
  266. ev = document.createEvent('MouseEvents');
  267. ev.initMouseEvent('click', true, true, e.view, 1, point.screenX, point.screenY, point.clientX, point.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 0, null);
  268. ev._fake = true;
  269. target.dispatchEvent(ev);
  270. }
  271. return;
  272. }
  273. if(!that.options.snap && time > 250) {// Prevent slingshot effect
  274. that.resetPosition();
  275. return;
  276. }
  277. if(that.options.momentum) {
  278. momentumX = that.scrollX === true ? that.momentum(that.x - that.scrollStartX, time, that.options.bounce ? -that.x + that.scrollWidth / 5 : -that.x, that.options.bounce ? that.x + that.scrollerWidth - that.scrollWidth + that.scrollWidth / 5 : that.x + that.scrollerWidth - that.scrollWidth) : {
  279. dist : 0,
  280. time : 0
  281. };
  282. momentumY = that.scrollY === true ? that.momentum(that.y - that.scrollStartY, time, that.options.bounce ? -that.y + that.scrollHeight / 5 : -that.y, that.options.bounce ? (that.maxScrollY < 0 ? that.y + that.scrollerHeight - that.scrollHeight : 0) + that.scrollHeight / 5 : that.y + that.scrollerHeight - that.scrollHeight) : {
  283. dist : 0,
  284. time : 0
  285. };
  286. newDuration = Math.max(Math.max(momentumX.time, momentumY.time), 1);
  287. // The minimum animation length must be 1ms
  288. newPositionX = that.x + momentumX.dist;
  289. newPositionY = that.y + momentumY.dist;
  290. }
  291. if(that.options.snap) {
  292. snap = that.snap(newPositionX, newPositionY);
  293. newPositionX = snap.x;
  294. newPositionY = snap.y;
  295. newDuration = Math.max(snap.time, newDuration);
  296. }
  297. that.scrollTo(newPositionX, newPositionY, newDuration + 'ms');
  298. },
  299. transitionEnd : function() {
  300. var that = this;
  301. document.removeEventListener('webkitTransitionEnd', that, false);
  302. that.resetPosition();
  303. },
  304. resetPosition : function() {
  305. var that = this, resetX = that.x, resetY = that.y;
  306. if(that.x >= 0) {
  307. resetX = 0;
  308. } else if(that.x < that.maxScrollX) {
  309. resetX = that.maxScrollX;
  310. }
  311. if(that.y >= 0 || that.maxScrollY > 0) {
  312. resetY = 0;
  313. } else if(that.y < that.maxScrollY) {
  314. resetY = that.maxScrollY;
  315. }
  316. if(resetX != that.x || resetY != that.y) {
  317. that.scrollTo(resetX, resetY);
  318. } else {
  319. if(that.moved) {
  320. that.onScrollEnd();
  321. // Execute custom code on scroll end
  322. that.moved = false;
  323. }
  324. // Hide the scrollbars
  325. if(that.scrollBarX) {
  326. that.scrollBarX.hide();
  327. }
  328. if(that.scrollBarY) {
  329. that.scrollBarY.hide();
  330. }
  331. }
  332. },
  333. snap : function(x, y) {
  334. var that = this, time;
  335. if(that.directionX > 0) {
  336. x = Math.floor(x / that.scrollWidth);
  337. } else if(that.directionX < 0) {
  338. x = Math.ceil(x / that.scrollWidth);
  339. } else {
  340. x = Math.round(x / that.scrollWidth);
  341. }
  342. that.pageX = -x;
  343. x = x * that.scrollWidth;
  344. if(x > 0) {
  345. x = that.pageX = 0;
  346. } else if(x < that.maxScrollX) {
  347. that.pageX = that.maxPageX;
  348. x = that.maxScrollX;
  349. }
  350. if(that.directionY > 0) {
  351. y = Math.floor(y / that.scrollHeight);
  352. } else if(that.directionY < 0) {
  353. y = Math.ceil(y / that.scrollHeight);
  354. } else {
  355. y = Math.round(y / that.scrollHeight);
  356. }
  357. that.pageY = -y;
  358. y = y * that.scrollHeight;
  359. if(y > 0) {
  360. y = that.pageY = 0;
  361. } else if(y < that.maxScrollY) {
  362. that.pageY = that.maxPageY;
  363. y = that.maxScrollY;
  364. }
  365. // Snap with constant speed (proportional duration)
  366. time = Math.round(Math.max(Math.abs(that.x - x) / that.scrollWidth * 500, Math.abs(that.y - y) / that.scrollHeight * 500));
  367. return {
  368. x : x,
  369. y : y,
  370. time : time
  371. };
  372. },
  373. scrollTo : function(destX, destY, runtime) {
  374. var that = this;
  375. if(that.x == destX && that.y == destY) {
  376. that.resetPosition();
  377. return;
  378. }
  379. that.moved = true;
  380. that.setTransitionTime(runtime || '350ms');
  381. that.setPosition(destX, destY);
  382. if(runtime === '0' || runtime == '0s' || runtime == '0ms') {
  383. that.resetPosition();
  384. } else {
  385. document.addEventListener('webkitTransitionEnd', that, false);
  386. // At the end of the transition check if we are still inside of the boundaries
  387. }
  388. },
  389. scrollToPage : function(pageX, pageY, runtime) {
  390. var that = this, snap;
  391. if(!that.options.snap) {
  392. that.pageX = -Math.round(that.x / that.scrollWidth);
  393. that.pageY = -Math.round(that.y / that.scrollHeight);
  394. }
  395. if(pageX == 'next') {
  396. pageX = ++that.pageX;
  397. } else if(pageX == 'prev') {
  398. pageX = --that.pageX;
  399. }
  400. if(pageY == 'next') {
  401. pageY = ++that.pageY;
  402. } else if(pageY == 'prev') {
  403. pageY = --that.pageY;
  404. }
  405. pageX = -pageX * that.scrollWidth;
  406. pageY = -pageY * that.scrollHeight;
  407. snap = that.snap(pageX, pageY);
  408. pageX = snap.x;
  409. pageY = snap.y;
  410. that.scrollTo(pageX, pageY, runtime || '500ms');
  411. },
  412. scrollToElement : function(el, runtime) {
  413. el = typeof el == 'object' ? el : this.element.querySelector(el);
  414. if(!el) {
  415. return;
  416. }
  417. var that = this, x = that.scrollX ? -el.offsetLeft : 0, y = that.scrollY ? -el.offsetTop : 0;
  418. if(x >= 0) {
  419. x = 0;
  420. } else if(x < that.maxScrollX) {
  421. x = that.maxScrollX;
  422. }
  423. if(y >= 0) {
  424. y = 0;
  425. } else if(y < that.maxScrollY) {
  426. y = that.maxScrollY;
  427. }
  428. that.scrollTo(x, y, runtime);
  429. },
  430. momentum : function(dist, time, maxDistUpper, maxDistLower) {
  431. var friction = 2.5, deceleration = 1.2, speed = Math.abs(dist) / time * 1000, newDist = speed * speed / friction / 1000, newTime = 0;
  432. // Proportinally reduce speed if we are outside of the boundaries
  433. if(dist > 0 && newDist > maxDistUpper) {
  434. speed = speed * maxDistUpper / newDist / friction;
  435. newDist = maxDistUpper;
  436. } else if(dist < 0 && newDist > maxDistLower) {
  437. speed = speed * maxDistLower / newDist / friction;
  438. newDist = maxDistLower;
  439. }
  440. newDist = newDist * (dist < 0 ? -1 : 1);
  441. newTime = speed / deceleration;
  442. return {
  443. dist : Math.round(newDist),
  444. time : Math.round(newTime)
  445. };
  446. },
  447. destroy : function(full) {
  448. var that = this;
  449. window.removeEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', that, false);
  450. that.element.removeEventListener(START_EVENT, that, false);
  451. that.element.removeEventListener(MOVE_EVENT, that, false);
  452. that.element.removeEventListener(END_EVENT, that, false);
  453. document.removeEventListener('webkitTransitionEnd', that, false);
  454. if(that.options.checkDOMChanges) {
  455. that.element.removeEventListener('DOMSubtreeModified', that, false);
  456. }
  457. if(that.scrollBarX) {
  458. that.scrollBarX = that.scrollBarX.remove();
  459. }
  460. if(that.scrollBarY) {
  461. that.scrollBarY = that.scrollBarY.remove();
  462. }
  463. if(full) {
  464. that.wrapper.parentNode.removeChild(that.wrapper);
  465. }
  466. return null;
  467. }
  468. };
  469. function scrollbar(dir, wrapper, fade, shrink, color) {
  470. var that = this, doc = document;
  471. that.dir = dir;
  472. that.fade = fade;
  473. that.shrink = shrink;
  474. that.uid = ++uid;
  475. // Create main scrollbar
  476. that.bar = doc.createElement('div');
  477. that.bar.style.cssText = 'position:absolute;top:0;left:0;-webkit-transition-timing-function:cubic-bezier(0,0,0.25,1);pointer-events:none;-webkit-transition-duration:0;-webkit-transition-delay:0;-webkit-transition-property:-webkit-transform;z-index:10;background:' + color + ';' + '-webkit-transform:' + translateOpen + '0,0' + translateClose + ';' + (dir == 'horizontal' ? '-webkit-border-radius:3px 2px;min-width:6px;min-height:5px' : '-webkit-border-radius:2px 3px;min-width:5px;min-height:6px');
  478. // Create scrollbar wrapper
  479. that.wrapper = doc.createElement('div');
  480. that.wrapper.style.cssText = '-webkit-mask:-webkit-canvas(scrollbar' + that.uid + that.dir + ');position:absolute;z-index:10;pointer-events:none;overflow:hidden;opacity:0;-webkit-transition-duration:' + ( fade ? '300ms' : '0') + ';-webkit-transition-delay:0;-webkit-transition-property:opacity;' + (that.dir == 'horizontal' ? 'bottom:2px;left:2px;right:7px;height:5px' : 'top:2px;right:2px;bottom:7px;width:5px;');
  481. // Add scrollbar to the DOM
  482. that.wrapper.appendChild(that.bar);
  483. wrapper.appendChild(that.wrapper);
  484. }
  485. scrollbar.prototype = {
  486. init : function(scroll, size) {
  487. var that = this, doc = document, pi = Math.PI, ctx;
  488. // Create scrollbar mask
  489. if(that.dir == 'horizontal') {
  490. if(that.maxSize != that.wrapper.offsetWidth) {
  491. that.maxSize = that.wrapper.offsetWidth;
  492. ctx = doc.getCSSCanvasContext("2d", "scrollbar" + that.uid + that.dir, that.maxSize, 5);
  493. ctx.fillStyle = "rgb(0,0,0)";
  494. ctx.beginPath();
  495. ctx.arc(2.5, 2.5, 2.5, pi / 2, -pi / 2, false);
  496. ctx.lineTo(that.maxSize - 2.5, 0);
  497. ctx.arc(that.maxSize - 2.5, 2.5, 2.5, -pi / 2, pi / 2, false);
  498. ctx.closePath();
  499. ctx.fill();
  500. }
  501. } else {
  502. if(that.maxSize != that.wrapper.offsetHeight) {
  503. that.maxSize = that.wrapper.offsetHeight;
  504. ctx = doc.getCSSCanvasContext("2d", "scrollbar" + that.uid + that.dir, 5, that.maxSize);
  505. ctx.fillStyle = "rgb(0,0,0)";
  506. ctx.beginPath();
  507. ctx.arc(2.5, 2.5, 2.5, pi, 0, false);
  508. ctx.lineTo(5, that.maxSize - 2.5);
  509. ctx.arc(2.5, that.maxSize - 2.5, 2.5, 0, pi, false);
  510. ctx.closePath();
  511. ctx.fill();
  512. }
  513. }
  514. that.size = Math.max(Math.round(that.maxSize * that.maxSize / size), 6);
  515. that.maxScroll = that.maxSize - that.size;
  516. that.toWrapperProp = that.maxScroll / (scroll - size);
  517. that.bar.style[that.dir == 'horizontal' ? 'width' : 'height'] = that.size + 'px';
  518. },
  519. setPosition : function(pos) {
  520. var that = this;
  521. if(that.wrapper.style.opacity != '1') {
  522. that.show();
  523. }
  524. pos = Math.round(that.toWrapperProp * pos);
  525. if(pos < 0) {
  526. pos = that.shrink ? pos + pos * 3 : 0;
  527. if(that.size + pos < 7) {
  528. pos = -that.size + 6;
  529. }
  530. } else if(pos > that.maxScroll) {
  531. pos = that.shrink ? pos + (pos - that.maxScroll) * 3 : that.maxScroll;
  532. if(that.size + that.maxScroll - pos < 7) {
  533. pos = that.size + that.maxScroll - 6;
  534. }
  535. }
  536. pos = that.dir == 'horizontal' ? translateOpen + pos + 'px,0' + translateClose : translateOpen + '0,' + pos + 'px' + translateClose;
  537. that.bar.style.webkitTransform = pos;
  538. },
  539. show : function() {
  540. if(has3d) {
  541. this.wrapper.style.webkitTransitionDelay = '0';
  542. }
  543. this.wrapper.style.opacity = '1';
  544. },
  545. hide : function() {
  546. if(has3d) {
  547. this.wrapper.style.webkitTransitionDelay = '350ms';
  548. }
  549. this.wrapper.style.opacity = '0';
  550. },
  551. remove : function() {
  552. this.wrapper.parentNode.removeChild(this.wrapper);
  553. return null;
  554. }
  555. };
  556. // Is translate3d compatible?
  557. var has3d = ('WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix()),
  558. // Device sniffing
  559. isIthing = (/iphone|ipad/gi).test(navigator.appVersion), isTouch = ('ontouchstart' in window),
  560. // Event sniffing
  561. START_EVENT = isTouch ? 'touchstart' : 'mousedown', MOVE_EVENT = isTouch ? 'touchmove' : 'mousemove', END_EVENT = isTouch ? 'touchend' : 'mouseup',
  562. // Translate3d helper
  563. translateOpen = 'translate' + ( has3d ? '3d(' : '('), translateClose = has3d ? ',0)' : ')',
  564. // Unique ID
  565. uid = 0;
  566. // Expose iScroll to the world
  567. $kit.iScroll = iScroll;
  568. })();