/** * Tableviews * @param {type} $ * @param {type} window * @param {type} document * @returns {undefined} */ (function($, window, document) { var CLASS_ACTIVE = $.className('active'); var CLASS_SELECTED = $.className('selected'); var CLASS_GRID_VIEW = $.className('grid-view'); var CLASS_RADIO_VIEW = $.className('table-view-radio'); var CLASS_TABLE_VIEW_CELL = $.className('table-view-cell'); var CLASS_COLLAPSE_CONTENT = $.className('collapse-content'); var CLASS_DISABLED = $.className('disabled'); var CLASS_TOGGLE = $.className('switch'); var CLASS_BTN = $.className('btn'); var CLASS_SLIDER_HANDLE = $.className('slider-handle'); var CLASS_SLIDER_LEFT = $.className('slider-left'); var CLASS_SLIDER_RIGHT = $.className('slider-right'); var CLASS_TRANSITIONING = $.className('transitioning'); var SELECTOR_SLIDER_HANDLE = '.' + CLASS_SLIDER_HANDLE; var SELECTOR_SLIDER_LEFT = '.' + CLASS_SLIDER_LEFT; var SELECTOR_SLIDER_RIGHT = '.' + CLASS_SLIDER_RIGHT; var SELECTOR_SELECTED = '.' + CLASS_SELECTED; var SELECTOR_BUTTON = '.' + CLASS_BTN; var overFactor = 0.8; var cell, a; var isMoved = isOpened = openedActions = progress = false; var sliderHandle = sliderActionLeft = sliderActionRight = buttonsLeft = buttonsRight = sliderDirection = sliderRequestAnimationFrame = false; var timer = translateX = lastTranslateX = sliderActionLeftWidth = sliderActionRightWidth = 0; var toggleActive = function(isActive) { if (isActive) { if (a) { a.classList.add(CLASS_ACTIVE); } else if (cell) { cell.classList.add(CLASS_ACTIVE); } } else { timer && timer.cancel(); if (a) { a.classList.remove(CLASS_ACTIVE); } else if (cell) { cell.classList.remove(CLASS_ACTIVE); } } }; var updateTranslate = function() { if (translateX !== lastTranslateX) { if (buttonsRight && buttonsRight.length > 0) { progress = translateX / sliderActionRightWidth; if (translateX < -sliderActionRightWidth) { translateX = -sliderActionRightWidth - Math.pow(-translateX - sliderActionRightWidth, overFactor); } for (var i = 0, len = buttonsRight.length; i < len; i++) { var buttonRight = buttonsRight[i]; if (typeof buttonRight._buttonOffset === 'undefined') { buttonRight._buttonOffset = buttonRight.offsetLeft; } buttonOffset = buttonRight._buttonOffset; setTranslate(buttonRight, (translateX - buttonOffset * (1 + Math.max(progress, -1)))); } } if (buttonsLeft && buttonsLeft.length > 0) { progress = translateX / sliderActionLeftWidth; if (translateX > sliderActionLeftWidth) { translateX = sliderActionLeftWidth + Math.pow(translateX - sliderActionLeftWidth, overFactor); } for (var i = 0, len = buttonsLeft.length; i < len; i++) { var buttonLeft = buttonsLeft[i]; if (typeof buttonLeft._buttonOffset === 'undefined') { buttonLeft._buttonOffset = sliderActionLeftWidth - buttonLeft.offsetLeft - buttonLeft.offsetWidth; } buttonOffset = buttonLeft._buttonOffset; if (buttonsLeft.length > 1) { buttonLeft.style.zIndex = buttonsLeft.length - i; } setTranslate(buttonLeft, (translateX + buttonOffset * (1 - Math.min(progress, 1)))); } } setTranslate(sliderHandle, translateX); lastTranslateX = translateX; } sliderRequestAnimationFrame = requestAnimationFrame(function() { updateTranslate(); }); }; var setTranslate = function(element, x) { if (element) { element.style.webkitTransform = 'translate(' + x + 'px,0)'; } }; window.addEventListener($.EVENT_START, function(event) { if (cell) { toggleActive(false); } cell = a = false; isMoved = isOpened = openedActions = false; var target = event.target; var isDisabled = false; for (; target && target !== document; target = target.parentNode) { if (target.classList) { var classList = target.classList; if ((target.tagName === 'INPUT' && target.type !== 'radio' && target.type !== 'checkbox') || target.tagName === 'BUTTON' || classList.contains(CLASS_TOGGLE) || classList.contains(CLASS_BTN) || classList.contains(CLASS_DISABLED)) { isDisabled = true; } if (classList.contains(CLASS_COLLAPSE_CONTENT)) { //collapse content break; } if (classList.contains(CLASS_TABLE_VIEW_CELL)) { cell = target; //TODO swipe to delete close var selected = cell.parentNode.querySelector(SELECTOR_SELECTED); if (!cell.parentNode.classList.contains(CLASS_RADIO_VIEW) && selected && selected !== cell) { $.swipeoutClose(selected); cell = isDisabled = false; return; } if (!cell.parentNode.classList.contains(CLASS_GRID_VIEW)) { var link = cell.querySelector('a'); if (link && link.parentNode === cell) { //li>a a = link; } } var handle = cell.querySelector(SELECTOR_SLIDER_HANDLE); if (handle) { toggleEvents(cell); event.stopPropagation(); } if (!isDisabled) { if (handle) { if (timer) { timer.cancel(); } timer = $.later(function() { toggleActive(true); }, 100); } else { toggleActive(true); } } break; } } } }); window.addEventListener($.EVENT_MOVE, function(event) { toggleActive(false); }); var handleEvent = { handleEvent: function(event) { switch (event.type) { case 'drag': this.drag(event); break; case 'dragend': this.dragend(event); break; case 'flick': this.flick(event); break; case 'swiperight': this.swiperight(event); break; case 'swipeleft': this.swipeleft(event); break; } }, drag: function(event) { if (!cell) { return; } if (!isMoved) { //init sliderHandle = sliderActionLeft = sliderActionRight = buttonsLeft = buttonsRight = sliderDirection = sliderRequestAnimationFrame = false; sliderHandle = cell.querySelector(SELECTOR_SLIDER_HANDLE); if (sliderHandle) { sliderActionLeft = cell.querySelector(SELECTOR_SLIDER_LEFT); sliderActionRight = cell.querySelector(SELECTOR_SLIDER_RIGHT); if (sliderActionLeft) { sliderActionLeftWidth = sliderActionLeft.offsetWidth; buttonsLeft = sliderActionLeft.querySelectorAll(SELECTOR_BUTTON); } if (sliderActionRight) { sliderActionRightWidth = sliderActionRight.offsetWidth; buttonsRight = sliderActionRight.querySelectorAll(SELECTOR_BUTTON); } cell.classList.remove(CLASS_TRANSITIONING); isOpened = cell.classList.contains(CLASS_SELECTED); if (isOpened) { openedActions = cell.querySelector(SELECTOR_SLIDER_LEFT + SELECTOR_SELECTED) ? 'left' : 'right'; } } } var detail = event.detail; var direction = detail.direction; var angle = detail.angle; if (direction === 'left' && (angle > 150 || angle < -150)) { if (buttonsRight || (buttonsLeft && isOpened)) { //存在右侧按钮或存在左侧按钮且是已打开状态 isMoved = true; } } else if (direction === 'right' && (angle > -30 && angle < 30)) { if (buttonsLeft || (buttonsRight && isOpened)) { //存在左侧按钮或存在右侧按钮且是已打开状态 isMoved = true; } } if (isMoved) { event.stopPropagation(); event.detail.gesture.preventDefault(); var translate = event.detail.deltaX; if (isOpened) { if (openedActions === 'right') { translate = translate - sliderActionRightWidth; } else { translate = translate + sliderActionLeftWidth; } } if ((translate > 0 && !buttonsLeft) || (translate < 0 && !buttonsRight)) { if (!isOpened) { return; } translate = 0; } if (translate < 0) { sliderDirection = 'toLeft'; } else if (translate > 0) { sliderDirection = 'toRight'; } else { if (!sliderDirection) { sliderDirection = 'toLeft'; } } if (!sliderRequestAnimationFrame) { updateTranslate(); } translateX = translate; } }, flick: function(event) { if (isMoved) { event.stopPropagation(); } }, swipeleft: function(event) { if (isMoved) { event.stopPropagation(); } }, swiperight: function(event) { if (isMoved) { event.stopPropagation(); } }, dragend: function(event) { if (!isMoved) { return; } event.stopPropagation(); if (sliderRequestAnimationFrame) { cancelAnimationFrame(sliderRequestAnimationFrame); sliderRequestAnimationFrame = null; } var detail = event.detail; isMoved = false; var action = 'close'; var actionsWidth = sliderDirection === 'toLeft' ? sliderActionRightWidth : sliderActionLeftWidth; var isToggle = detail.swipe || (Math.abs(translateX) > actionsWidth / 2); if (isToggle) { if (!isOpened) { action = 'open'; } else if (detail.direction === 'left' && openedActions === 'right') { action = 'open'; } else if (detail.direction === 'right' && openedActions === 'left') { action = 'open'; } } cell.classList.add(CLASS_TRANSITIONING); var buttons; if (action === 'open') { var newTranslate = sliderDirection === 'toLeft' ? -actionsWidth : actionsWidth; setTranslate(sliderHandle, newTranslate); buttons = sliderDirection === 'toLeft' ? buttonsRight : buttonsLeft; if (typeof buttons !== 'undefined') { var button = null; for (var i = 0; i < buttons.length; i++) { button = buttons[i]; setTranslate(button, newTranslate); } button.parentNode.classList.add(CLASS_SELECTED); cell.classList.add(CLASS_SELECTED); if (!isOpened) { $.trigger(cell, sliderDirection === 'toLeft' ? 'slideleft' : 'slideright'); } } } else { setTranslate(sliderHandle, 0); sliderActionLeft && sliderActionLeft.classList.remove(CLASS_SELECTED); sliderActionRight && sliderActionRight.classList.remove(CLASS_SELECTED); cell.classList.remove(CLASS_SELECTED); } var buttonOffset; if (buttonsLeft && buttonsLeft.length > 0 && buttonsLeft !== buttons) { for (var i = 0, len = buttonsLeft.length; i < len; i++) { var buttonLeft = buttonsLeft[i]; buttonOffset = buttonLeft._buttonOffset; if (typeof buttonOffset === 'undefined') { buttonLeft._buttonOffset = sliderActionLeftWidth - buttonLeft.offsetLeft - buttonLeft.offsetWidth; } setTranslate(buttonLeft, buttonOffset); } } if (buttonsRight && buttonsRight.length > 0 && buttonsRight !== buttons) { for (var i = 0, len = buttonsRight.length; i < len; i++) { var buttonRight = buttonsRight[i]; buttonOffset = buttonRight._buttonOffset; if (typeof buttonOffset === 'undefined') { buttonRight._buttonOffset = buttonRight.offsetLeft; } setTranslate(buttonRight, -buttonOffset); } } } }; function toggleEvents(element, isRemove) { var method = !!isRemove ? 'removeEventListener' : 'addEventListener'; element[method]('drag', handleEvent); element[method]('dragend', handleEvent); element[method]('swiperight', handleEvent); element[method]('swipeleft', handleEvent); element[method]('flick', handleEvent); }; /** * 打开滑动菜单 * @param {Object} el * @param {Object} direction */ $.swipeoutOpen = function(el, direction) { if (!el) return; var classList = el.classList; if (classList.contains(CLASS_SELECTED)) return; if (!direction) { if (el.querySelector(SELECTOR_SLIDER_RIGHT)) { direction = 'right'; } else { direction = 'left'; } } var swipeoutAction = el.querySelector($.classSelector(".slider-" + direction)); if (!swipeoutAction) return; swipeoutAction.classList.add(CLASS_SELECTED); classList.add(CLASS_SELECTED); classList.remove(CLASS_TRANSITIONING); var buttons = swipeoutAction.querySelectorAll(SELECTOR_BUTTON); var swipeoutWidth = swipeoutAction.offsetWidth; var translate = (direction === 'right') ? -swipeoutWidth : swipeoutWidth; var length = buttons.length; var button; for (var i = 0; i < length; i++) { button = buttons[i]; if (direction === 'right') { setTranslate(button, -button.offsetLeft); } else { setTranslate(button, (swipeoutWidth - button.offsetWidth - button.offsetLeft)); } } classList.add(CLASS_TRANSITIONING); for (var i = 0; i < length; i++) { setTranslate(buttons[i], translate); } setTranslate(el.querySelector(SELECTOR_SLIDER_HANDLE), translate); }; /** * 关闭滑动菜单 * @param {Object} el */ $.swipeoutClose = function(el) { if (!el) return; var classList = el.classList; if (!classList.contains(CLASS_SELECTED)) return; var direction = el.querySelector(SELECTOR_SLIDER_RIGHT + SELECTOR_SELECTED) ? 'right' : 'left'; var swipeoutAction = el.querySelector($.classSelector(".slider-" + direction)); if (!swipeoutAction) return; swipeoutAction.classList.remove(CLASS_SELECTED); classList.remove(CLASS_SELECTED); classList.add(CLASS_TRANSITIONING); var buttons = swipeoutAction.querySelectorAll(SELECTOR_BUTTON); var swipeoutWidth = swipeoutAction.offsetWidth; var length = buttons.length; var button; setTranslate(el.querySelector(SELECTOR_SLIDER_HANDLE), 0); for (var i = 0; i < length; i++) { button = buttons[i]; if (direction === 'right') { setTranslate(button, (-button.offsetLeft)); } else { setTranslate(button, (swipeoutWidth - button.offsetWidth - button.offsetLeft)); } } }; window.addEventListener($.EVENT_END, function(event) { //使用touchend来取消高亮,避免一次点击既不触发tap,doubletap,longtap的事件 if (!cell) { return; } toggleActive(false); sliderHandle && toggleEvents(cell, true); }); window.addEventListener($.EVENT_CANCEL, function(event) { //使用touchcancel来取消高亮,避免一次点击既不触发tap,doubletap,longtap的事件 if (!cell) { return; } toggleActive(false); sliderHandle && toggleEvents(cell, true); }); var radioOrCheckboxClick = function(event) { var type = event.target && event.target.type || ''; if (type === 'radio' || type === 'checkbox') { return; } var classList = cell.classList; if (classList.contains($.className('radio'))) { var input = cell.querySelector('input[type=radio]'); if (input) { // input.click(); if (!input.disabled && !input.readOnly) { input.checked = !input.checked; $.trigger(input, 'change'); } } } else if (classList.contains($.className('checkbox'))) { var input = cell.querySelector('input[type=checkbox]'); if (input) { // input.click(); if (!input.disabled && !input.readOnly) { input.checked = !input.checked; $.trigger(input, 'change'); } } } }; //fixed hashchange(android) window.addEventListener($.EVENT_CLICK, function(e) { if (cell && cell.classList.contains($.className('collapse'))) { e.preventDefault(); } }); window.addEventListener('doubletap', function(event) { if (cell) { radioOrCheckboxClick(event); } }); var preventDefaultException = /^(INPUT|TEXTAREA|BUTTON|SELECT)$/; window.addEventListener('tap', function(event) { if (!cell) { return; } var isExpand = false; var classList = cell.classList; var ul = cell.parentNode; if (ul && ul.classList.contains(CLASS_RADIO_VIEW)) { if (classList.contains(CLASS_SELECTED)) { return; } var selected = ul.querySelector('li' + SELECTOR_SELECTED); if (selected) { selected.classList.remove(CLASS_SELECTED); } classList.add(CLASS_SELECTED); $.trigger(cell, 'selected', { el: cell }); return; } if (classList.contains($.className('collapse')) && !cell.parentNode.classList.contains($.className('unfold'))) { if (!preventDefaultException.test(event.target.tagName)) { event.detail.gesture.preventDefault(); } if (!classList.contains(CLASS_ACTIVE)) { //展开时,需要收缩其他同类 var collapse = cell.parentNode.querySelector($.classSelector('.collapse.active')); if (collapse) { collapse.classList.remove(CLASS_ACTIVE); } isExpand = true; } classList.toggle(CLASS_ACTIVE); if (isExpand) { //触发展开事件 $.trigger(cell, 'expand'); //scroll //暂不滚动 // var offsetTop = $.offset(cell).top; // var scrollTop = document.body.scrollTop; // var height = window.innerHeight; // var offsetHeight = cell.offsetHeight; // var cellHeight = (offsetTop - scrollTop + offsetHeight); // if (offsetHeight > height) { // $.scrollTo(offsetTop, 300); // } else if (cellHeight > height) { // $.scrollTo(cellHeight - height + scrollTop, 300); // } } } else { radioOrCheckboxClick(event); } }); })(mui, window, document);