mui.offcanvas.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /**
  2. * off-canvas
  3. * @param {type} $
  4. * @param {type} window
  5. * @param {type} document
  6. * @param {type} action
  7. * @returns {undefined}
  8. */
  9. (function($, window, document, name) {
  10. var CLASS_OFF_CANVAS_LEFT = $.className('off-canvas-left');
  11. var CLASS_OFF_CANVAS_RIGHT = $.className('off-canvas-right');
  12. var CLASS_ACTION_BACKDROP = $.className('off-canvas-backdrop');
  13. var CLASS_OFF_CANVAS_WRAP = $.className('off-canvas-wrap');
  14. var CLASS_SLIDE_IN = $.className('slide-in');
  15. var CLASS_ACTIVE = $.className('active');
  16. var CLASS_TRANSITIONING = $.className('transitioning');
  17. var SELECTOR_INNER_WRAP = $.classSelector('.inner-wrap');
  18. var OffCanvas = $.Class.extend({
  19. init: function(element, options) {
  20. this.wrapper = this.element = element;
  21. this.scroller = this.wrapper.querySelector(SELECTOR_INNER_WRAP);
  22. this.classList = this.wrapper.classList;
  23. if (this.scroller) {
  24. this.options = $.extend(true, {
  25. dragThresholdX: 10,
  26. scale: 0.8,
  27. opacity: 0.1,
  28. preventDefaultException: {
  29. tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|VIDEO)$/
  30. },
  31. }, options);
  32. document.body.classList.add($.className('fullscreen')); //fullscreen
  33. this.refresh();
  34. this.initEvent();
  35. }
  36. },
  37. _preventDefaultException: function(el, exceptions) {
  38. for (var i in exceptions) {
  39. if (exceptions[i].test(el[i])) {
  40. return true;
  41. }
  42. }
  43. return false;
  44. },
  45. refresh: function(offCanvas) {
  46. // offCanvas && !offCanvas.classList.contains(CLASS_ACTIVE) && this.classList.remove(CLASS_ACTIVE);
  47. this.slideIn = this.classList.contains(CLASS_SLIDE_IN);
  48. this.scalable = this.classList.contains($.className('scalable')) && !this.slideIn;
  49. this.scroller = this.wrapper.querySelector(SELECTOR_INNER_WRAP);
  50. // !offCanvas && this.scroller.classList.remove(CLASS_TRANSITIONING);
  51. // !offCanvas && this.scroller.setAttribute('style', '');
  52. this.offCanvasLefts = this.wrapper.querySelectorAll('.' + CLASS_OFF_CANVAS_LEFT);
  53. this.offCanvasRights = this.wrapper.querySelectorAll('.' + CLASS_OFF_CANVAS_RIGHT);
  54. if (offCanvas) {
  55. if (offCanvas.classList.contains(CLASS_OFF_CANVAS_LEFT)) {
  56. this.offCanvasLeft = offCanvas;
  57. } else if (offCanvas.classList.contains(CLASS_OFF_CANVAS_RIGHT)) {
  58. this.offCanvasRight = offCanvas;
  59. }
  60. } else {
  61. this.offCanvasRight = this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_RIGHT);
  62. this.offCanvasLeft = this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_LEFT);
  63. }
  64. this.offCanvasRightWidth = this.offCanvasLeftWidth = 0;
  65. this.offCanvasLeftSlideIn = this.offCanvasRightSlideIn = false;
  66. if (this.offCanvasRight) {
  67. this.offCanvasRightWidth = this.offCanvasRight.offsetWidth;
  68. this.offCanvasRightSlideIn = this.slideIn && (this.offCanvasRight.parentNode === this.wrapper);
  69. // this.offCanvasRight.classList.remove(CLASS_TRANSITIONING);
  70. // this.offCanvasRight.classList.remove(CLASS_ACTIVE);
  71. // this.offCanvasRight.setAttribute('style', '');
  72. }
  73. if (this.offCanvasLeft) {
  74. this.offCanvasLeftWidth = this.offCanvasLeft.offsetWidth;
  75. this.offCanvasLeftSlideIn = this.slideIn && (this.offCanvasLeft.parentNode === this.wrapper);
  76. // this.offCanvasLeft.classList.remove(CLASS_TRANSITIONING);
  77. // this.offCanvasLeft.classList.remove(CLASS_ACTIVE);
  78. // this.offCanvasLeft.setAttribute('style', '');
  79. }
  80. this.backdrop = this.scroller.querySelector('.' + CLASS_ACTION_BACKDROP);
  81. this.options.dragThresholdX = this.options.dragThresholdX || 10;
  82. this.visible = false;
  83. this.startX = null;
  84. this.lastX = null;
  85. this.offsetX = null;
  86. this.lastTranslateX = null;
  87. },
  88. handleEvent: function(e) {
  89. switch (e.type) {
  90. case $.EVENT_START:
  91. e.target && !this._preventDefaultException(e.target, this.options.preventDefaultException) && e.preventDefault();
  92. break;
  93. case 'webkitTransitionEnd': //有个bug需要处理,需要考虑假设没有触发webkitTransitionEnd的情况
  94. if (e.target === this.scroller) {
  95. this._dispatchEvent();
  96. }
  97. break;
  98. case 'drag':
  99. var detail = e.detail;
  100. if (!this.startX) {
  101. this.startX = detail.center.x;
  102. this.lastX = this.startX;
  103. } else {
  104. this.lastX = detail.center.x;
  105. }
  106. if (!this.isDragging && Math.abs(this.lastX - this.startX) > this.options.dragThresholdX && (detail.direction === 'left' || (detail.direction === 'right'))) {
  107. if (this.slideIn) {
  108. this.scroller = this.wrapper.querySelector(SELECTOR_INNER_WRAP);
  109. if (this.classList.contains(CLASS_ACTIVE)) {
  110. if (this.offCanvasRight && this.offCanvasRight.classList.contains(CLASS_ACTIVE)) {
  111. this.offCanvas = this.offCanvasRight;
  112. this.offCanvasWidth = this.offCanvasRightWidth;
  113. } else {
  114. this.offCanvas = this.offCanvasLeft;
  115. this.offCanvasWidth = this.offCanvasLeftWidth;
  116. }
  117. } else {
  118. if (detail.direction === 'left' && this.offCanvasRight) {
  119. this.offCanvas = this.offCanvasRight;
  120. this.offCanvasWidth = this.offCanvasRightWidth;
  121. } else if (detail.direction === 'right' && this.offCanvasLeft) {
  122. this.offCanvas = this.offCanvasLeft;
  123. this.offCanvasWidth = this.offCanvasLeftWidth;
  124. } else {
  125. this.scroller = null;
  126. }
  127. }
  128. } else {
  129. if (this.classList.contains(CLASS_ACTIVE)) {
  130. if (detail.direction === 'left') {
  131. this.offCanvas = this.offCanvasLeft;
  132. this.offCanvasWidth = this.offCanvasLeftWidth;
  133. } else {
  134. this.offCanvas = this.offCanvasRight;
  135. this.offCanvasWidth = this.offCanvasRightWidth;
  136. }
  137. } else {
  138. if (detail.direction === 'right') {
  139. this.offCanvas = this.offCanvasLeft;
  140. this.offCanvasWidth = this.offCanvasLeftWidth;
  141. } else {
  142. this.offCanvas = this.offCanvasRight;
  143. this.offCanvasWidth = this.offCanvasRightWidth;
  144. }
  145. }
  146. }
  147. if (this.offCanvas && this.scroller) {
  148. this.startX = this.lastX;
  149. this.isDragging = true;
  150. $.gestures.session.lockDirection = true; //锁定方向
  151. $.gestures.session.startDirection = detail.direction;
  152. this.offCanvas.classList.remove(CLASS_TRANSITIONING);
  153. this.scroller.classList.remove(CLASS_TRANSITIONING);
  154. this.offsetX = this.getTranslateX();
  155. this._initOffCanvasVisible();
  156. }
  157. }
  158. if (this.isDragging) {
  159. this.updateTranslate(this.offsetX + (this.lastX - this.startX));
  160. detail.gesture.preventDefault();
  161. e.stopPropagation();
  162. }
  163. break;
  164. case 'dragend':
  165. if (this.isDragging) {
  166. var detail = e.detail;
  167. var direction = detail.direction;
  168. this.isDragging = false;
  169. this.offCanvas.classList.add(CLASS_TRANSITIONING);
  170. this.scroller.classList.add(CLASS_TRANSITIONING);
  171. var ratio = 0;
  172. var x = this.getTranslateX();
  173. if (!this.slideIn) {
  174. if (x >= 0) {
  175. ratio = (this.offCanvasLeftWidth && (x / this.offCanvasLeftWidth)) || 0;
  176. } else {
  177. ratio = (this.offCanvasRightWidth && (x / this.offCanvasRightWidth)) || 0;
  178. }
  179. if (ratio === 0) {
  180. this.openPercentage(0);
  181. this._dispatchEvent(); //此处不触发webkitTransitionEnd,所以手动dispatch
  182. return;
  183. }
  184. if (direction === 'right' && ratio >= 0 && (ratio >= 0.5 || detail.swipe)) { //右滑打开
  185. this.openPercentage(100);
  186. } else if (direction === 'right' && ratio < 0 && (ratio > -0.5 || detail.swipe)) { //右滑关闭
  187. this.openPercentage(0);
  188. } else if (direction === 'right' && ratio > 0 && ratio < 0.5) { //右滑还原关闭
  189. this.openPercentage(0);
  190. } else if (direction === 'right' && ratio < 0.5) { //右滑还原打开
  191. this.openPercentage(-100);
  192. } else if (direction === 'left' && ratio <= 0 && (ratio <= -0.5 || detail.swipe)) { //左滑打开
  193. this.openPercentage(-100);
  194. } else if (direction === 'left' && ratio > 0 && (ratio <= 0.5 || detail.swipe)) { //左滑关闭
  195. this.openPercentage(0);
  196. } else if (direction === 'left' && ratio < 0 && ratio >= -0.5) { //左滑还原关闭
  197. this.openPercentage(0);
  198. } else if (direction === 'left' && ratio > 0.5) { //左滑还原打开
  199. this.openPercentage(100);
  200. } else { //默认关闭
  201. this.openPercentage(0);
  202. }
  203. if (ratio === 1 || ratio === -1) { //此处不触发webkitTransitionEnd,所以手动dispatch
  204. this._dispatchEvent();
  205. }
  206. } else {
  207. if (x >= 0) {
  208. ratio = (this.offCanvasRightWidth && (x / this.offCanvasRightWidth)) || 0;
  209. } else {
  210. ratio = (this.offCanvasLeftWidth && (x / this.offCanvasLeftWidth)) || 0;
  211. }
  212. if (direction === 'right' && ratio <= 0 && (ratio >= -0.5 || detail.swipe)) { //右滑打开
  213. this.openPercentage(100);
  214. } else if (direction === 'right' && ratio > 0 && (ratio >= 0.5 || detail.swipe)) { //右滑关闭
  215. this.openPercentage(0);
  216. } else if (direction === 'right' && ratio <= -0.5) { //右滑还原关闭
  217. this.openPercentage(0);
  218. } else if (direction === 'right' && ratio > 0 && ratio <= 0.5) { //右滑还原打开
  219. this.openPercentage(-100);
  220. } else if (direction === 'left' && ratio >= 0 && (ratio <= 0.5 || detail.swipe)) { //左滑打开
  221. this.openPercentage(-100);
  222. } else if (direction === 'left' && ratio < 0 && (ratio <= -0.5 || detail.swipe)) { //左滑关闭
  223. this.openPercentage(0);
  224. } else if (direction === 'left' && ratio >= 0.5) { //左滑还原关闭
  225. this.openPercentage(0);
  226. } else if (direction === 'left' && ratio >= -0.5 && ratio < 0) { //左滑还原打开
  227. this.openPercentage(100);
  228. } else {
  229. this.openPercentage(0);
  230. }
  231. if (ratio === 1 || ratio === -1 || ratio === 0) {
  232. this._dispatchEvent();
  233. return;
  234. }
  235. }
  236. }
  237. break;
  238. }
  239. },
  240. _dispatchEvent: function() {
  241. if (this.classList.contains(CLASS_ACTIVE)) {
  242. $.trigger(this.wrapper, 'shown', this);
  243. } else {
  244. $.trigger(this.wrapper, 'hidden', this);
  245. }
  246. },
  247. _initOffCanvasVisible: function() {
  248. if (!this.visible) {
  249. this.visible = true;
  250. if (this.offCanvasLeft) {
  251. this.offCanvasLeft.style.visibility = 'visible';
  252. }
  253. if (this.offCanvasRight) {
  254. this.offCanvasRight.style.visibility = 'visible';
  255. }
  256. }
  257. },
  258. initEvent: function() {
  259. var self = this;
  260. if (self.backdrop) {
  261. self.backdrop.addEventListener('tap', function(e) {
  262. self.close();
  263. e.detail.gesture.preventDefault();
  264. });
  265. }
  266. if (this.classList.contains($.className('draggable'))) {
  267. this.wrapper.addEventListener($.EVENT_START, this); //临时处理
  268. this.wrapper.addEventListener('drag', this);
  269. this.wrapper.addEventListener('dragend', this);
  270. }
  271. this.wrapper.addEventListener('webkitTransitionEnd', this);
  272. },
  273. openPercentage: function(percentage) {
  274. var p = percentage / 100;
  275. if (!this.slideIn) {
  276. if (this.offCanvasLeft && percentage >= 0) {
  277. this.updateTranslate(this.offCanvasLeftWidth * p);
  278. this.offCanvasLeft.classList[p !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  279. } else if (this.offCanvasRight && percentage <= 0) {
  280. this.updateTranslate(this.offCanvasRightWidth * p);
  281. this.offCanvasRight.classList[p !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  282. }
  283. this.classList[p !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  284. } else {
  285. if (this.offCanvasLeft && percentage >= 0) {
  286. p = p === 0 ? -1 : 0;
  287. this.updateTranslate(this.offCanvasLeftWidth * p);
  288. this.offCanvasLeft.classList[percentage !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  289. } else if (this.offCanvasRight && percentage <= 0) {
  290. p = p === 0 ? 1 : 0;
  291. this.updateTranslate(this.offCanvasRightWidth * p);
  292. this.offCanvasRight.classList[percentage !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  293. }
  294. this.classList[percentage !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  295. }
  296. },
  297. updateTranslate: function(x) {
  298. if (x !== this.lastTranslateX) {
  299. if (!this.slideIn) {
  300. if ((!this.offCanvasLeft && x > 0) || (!this.offCanvasRight && x < 0)) {
  301. this.setTranslateX(0);
  302. return;
  303. }
  304. if (this.leftShowing && x > this.offCanvasLeftWidth) {
  305. this.setTranslateX(this.offCanvasLeftWidth);
  306. return;
  307. }
  308. if (this.rightShowing && x < -this.offCanvasRightWidth) {
  309. this.setTranslateX(-this.offCanvasRightWidth);
  310. return;
  311. }
  312. this.setTranslateX(x);
  313. if (x >= 0) {
  314. this.leftShowing = true;
  315. this.rightShowing = false;
  316. if (x > 0) {
  317. if (this.offCanvasLeft) {
  318. $.each(this.offCanvasLefts, function(index, offCanvas) {
  319. if (offCanvas === this.offCanvasLeft) {
  320. this.offCanvasLeft.style.zIndex = 0;
  321. } else {
  322. offCanvas.style.zIndex = -1;
  323. }
  324. }.bind(this));
  325. }
  326. if (this.offCanvasRight) {
  327. this.offCanvasRight.style.zIndex = -1;
  328. }
  329. }
  330. } else {
  331. this.rightShowing = true;
  332. this.leftShowing = false;
  333. if (this.offCanvasRight) {
  334. $.each(this.offCanvasRights, function(index, offCanvas) {
  335. if (offCanvas === this.offCanvasRight) {
  336. offCanvas.style.zIndex = 0;
  337. } else {
  338. offCanvas.style.zIndex = -1;
  339. }
  340. }.bind(this));
  341. }
  342. if (this.offCanvasLeft) {
  343. this.offCanvasLeft.style.zIndex = -1;
  344. }
  345. }
  346. } else {
  347. if (this.offCanvas.classList.contains(CLASS_OFF_CANVAS_RIGHT)) {
  348. if (x < 0) {
  349. this.setTranslateX(0);
  350. return;
  351. }
  352. if (x > this.offCanvasRightWidth) {
  353. this.setTranslateX(this.offCanvasRightWidth);
  354. return;
  355. }
  356. } else {
  357. if (x > 0) {
  358. this.setTranslateX(0);
  359. return;
  360. }
  361. if (x < -this.offCanvasLeftWidth) {
  362. this.setTranslateX(-this.offCanvasLeftWidth);
  363. return;
  364. }
  365. }
  366. this.setTranslateX(x);
  367. }
  368. this.lastTranslateX = x;
  369. }
  370. },
  371. setTranslateX: $.animationFrame(function(x) {
  372. if (this.scroller) {
  373. if (this.scalable && this.offCanvas.parentNode === this.wrapper) {
  374. var percent = Math.abs(x) / this.offCanvasWidth;
  375. var zoomOutScale = 1 - (1 - this.options.scale) * percent;
  376. var zoomInScale = this.options.scale + (1 - this.options.scale) * percent;
  377. var zoomOutOpacity = 1 - (1 - this.options.opacity) * percent;
  378. var zoomInOpacity = this.options.opacity + (1 - this.options.opacity) * percent;
  379. if (this.offCanvas.classList.contains(CLASS_OFF_CANVAS_LEFT)) {
  380. this.offCanvas.style.webkitTransformOrigin = '-100%';
  381. this.scroller.style.webkitTransformOrigin = 'left';
  382. } else {
  383. this.offCanvas.style.webkitTransformOrigin = '200%';
  384. this.scroller.style.webkitTransformOrigin = 'right';
  385. }
  386. this.offCanvas.style.opacity = zoomInOpacity;
  387. this.offCanvas.style.webkitTransform = 'translate3d(0,0,0) scale(' + zoomInScale + ')';
  388. this.scroller.style.webkitTransform = 'translate3d(' + x + 'px,0,0) scale(' + zoomOutScale + ')';
  389. } else {
  390. if (this.slideIn) {
  391. this.offCanvas.style.webkitTransform = 'translate3d(' + x + 'px,0,0)';
  392. } else {
  393. this.scroller.style.webkitTransform = 'translate3d(' + x + 'px,0,0)';
  394. }
  395. }
  396. }
  397. }),
  398. getTranslateX: function() {
  399. if (this.offCanvas) {
  400. var scroller = this.slideIn ? this.offCanvas : this.scroller;
  401. var result = $.parseTranslateMatrix($.getStyles(scroller, 'webkitTransform'));
  402. return (result && result.x) || 0;
  403. }
  404. return 0;
  405. },
  406. isShown: function(direction) {
  407. var shown = false;
  408. if (!this.slideIn) {
  409. var x = this.getTranslateX();
  410. if (direction === 'right') {
  411. shown = this.classList.contains(CLASS_ACTIVE) && x < 0;
  412. } else if (direction === 'left') {
  413. shown = this.classList.contains(CLASS_ACTIVE) && x > 0;
  414. } else {
  415. shown = this.classList.contains(CLASS_ACTIVE) && x !== 0;
  416. }
  417. } else {
  418. if (direction === 'left') {
  419. shown = this.classList.contains(CLASS_ACTIVE) && this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_LEFT + '.' + CLASS_ACTIVE);
  420. } else if (direction === 'right') {
  421. shown = this.classList.contains(CLASS_ACTIVE) && this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_RIGHT + '.' + CLASS_ACTIVE);
  422. } else {
  423. shown = this.classList.contains(CLASS_ACTIVE) && (this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_LEFT + '.' + CLASS_ACTIVE) || this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_RIGHT + '.' + CLASS_ACTIVE));
  424. }
  425. }
  426. return shown;
  427. },
  428. close: function() {
  429. this._initOffCanvasVisible();
  430. this.offCanvas = this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_RIGHT + '.' + CLASS_ACTIVE) || this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_LEFT + '.' + CLASS_ACTIVE);
  431. this.offCanvasWidth = this.offCanvas.offsetWidth;
  432. if (this.scroller) {
  433. this.offCanvas.offsetHeight;
  434. this.offCanvas.classList.add(CLASS_TRANSITIONING);
  435. this.scroller.classList.add(CLASS_TRANSITIONING);
  436. this.openPercentage(0);
  437. }
  438. },
  439. show: function(direction) {
  440. this._initOffCanvasVisible();
  441. if (this.isShown(direction)) {
  442. return false;
  443. }
  444. if (!direction) {
  445. direction = this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_RIGHT) ? 'right' : 'left';
  446. }
  447. if (direction === 'right') {
  448. this.offCanvas = this.offCanvasRight;
  449. this.offCanvasWidth = this.offCanvasRightWidth;
  450. } else {
  451. this.offCanvas = this.offCanvasLeft;
  452. this.offCanvasWidth = this.offCanvasLeftWidth;
  453. }
  454. if (this.scroller) {
  455. this.offCanvas.offsetHeight;
  456. this.offCanvas.classList.add(CLASS_TRANSITIONING);
  457. this.scroller.classList.add(CLASS_TRANSITIONING);
  458. this.openPercentage(direction === 'left' ? 100 : -100);
  459. }
  460. return true;
  461. },
  462. toggle: function(directionOrOffCanvas) {
  463. var direction = directionOrOffCanvas;
  464. if (directionOrOffCanvas && directionOrOffCanvas.classList) {
  465. direction = directionOrOffCanvas.classList.contains(CLASS_OFF_CANVAS_LEFT) ? 'left' : 'right';
  466. this.refresh(directionOrOffCanvas);
  467. }
  468. if (!this.show(direction)) {
  469. this.close();
  470. }
  471. }
  472. });
  473. //hash to offcanvas
  474. var findOffCanvasContainer = function(target) {
  475. parentNode = target.parentNode;
  476. if (parentNode) {
  477. if (parentNode.classList.contains(CLASS_OFF_CANVAS_WRAP)) {
  478. return parentNode;
  479. } else {
  480. parentNode = parentNode.parentNode;
  481. if (parentNode.classList.contains(CLASS_OFF_CANVAS_WRAP)) {
  482. return parentNode;
  483. }
  484. }
  485. }
  486. };
  487. var handle = function(event, target) {
  488. if (target.tagName === 'A' && target.hash) {
  489. var offcanvas = document.getElementById(target.hash.replace('#', ''));
  490. if (offcanvas) {
  491. var container = findOffCanvasContainer(offcanvas);
  492. if (container) {
  493. $.targets._container = container;
  494. return offcanvas;
  495. }
  496. }
  497. }
  498. return false;
  499. };
  500. $.registerTarget({
  501. name: name,
  502. index: 60,
  503. handle: handle,
  504. target: false,
  505. isReset: false,
  506. isContinue: true
  507. });
  508. window.addEventListener('tap', function(e) {
  509. if (!$.targets.offcanvas) {
  510. return;
  511. }
  512. //TODO 此处类型的代码后续考虑统一优化(target机制),现在的实现费力不讨好
  513. var target = e.target;
  514. for (; target && target !== document; target = target.parentNode) {
  515. if (target.tagName === 'A' && target.hash && target.hash === ('#' + $.targets.offcanvas.id)) {
  516. e.detail && e.detail.gesture && e.detail.gesture.preventDefault(); //fixed hashchange
  517. $($.targets._container).offCanvas().toggle($.targets.offcanvas);
  518. $.targets.offcanvas = $.targets._container = null;
  519. break;
  520. }
  521. }
  522. });
  523. $.fn.offCanvas = function(options) {
  524. var offCanvasApis = [];
  525. this.each(function() {
  526. var offCanvasApi = null;
  527. var self = this;
  528. //hack old version
  529. if (!self.classList.contains(CLASS_OFF_CANVAS_WRAP)) {
  530. self = findOffCanvasContainer(self);
  531. }
  532. var id = self.getAttribute('data-offCanvas');
  533. if (!id) {
  534. id = ++$.uuid;
  535. $.data[id] = offCanvasApi = new OffCanvas(self, options);
  536. self.setAttribute('data-offCanvas', id);
  537. } else {
  538. offCanvasApi = $.data[id];
  539. }
  540. if (options === 'show' || options === 'close' || options === 'toggle') {
  541. offCanvasApi.toggle();
  542. }
  543. offCanvasApis.push(offCanvasApi);
  544. });
  545. return offCanvasApis.length === 1 ? offCanvasApis[0] : offCanvasApis;
  546. };
  547. $.ready(function() {
  548. $($.classSelector('.off-canvas-wrap')).offCanvas();
  549. });
  550. })(mui, window, document, 'offcanvas');