UNPKG

framework7

Version:

Full featured mobile HTML framework for building iOS & Android apps

212 lines (210 loc) 6.3 kB
import $ from '../../shared/dom7.js'; import { extend, now, nextTick } from '../../shared/utils.js'; import Modal from '../modal/modal-class.js'; /** @jsx $jsx */ import $jsx from '../../shared/$jsx.js'; class Notification extends Modal { constructor(app, params) { const extendedParams = extend({ on: {} }, app.params.notification, params); // Extends with open/close Modal methods; super(app, extendedParams); const notification = this; notification.app = app; notification.params = extendedParams; const { icon, title, titleRightText, subtitle, text, closeButton, closeTimeout, cssClass, closeOnClick } = notification.params; let $el; if (!notification.params.el) { // Find Element const notificationHtml = notification.render({ icon, title, titleRightText, subtitle, text, closeButton, cssClass }); $el = $(notificationHtml); } else { $el = $(notification.params.el); } if ($el && $el.length > 0 && $el[0].f7Modal) { return $el[0].f7Modal; } if ($el.length === 0) { return notification.destroy(); } extend(notification, { $el, el: $el[0], type: 'notification' }); $el[0].f7Modal = notification; if (closeButton) { $el.find('.notification-close-button').on('click', () => { notification.close(); }); } $el.on('click', e => { if (closeButton && $(e.target).closest('.notification-close-button').length) { return; } notification.emit('local::click notificationClick', notification); if (closeOnClick) notification.close(); }); notification.on('beforeDestroy', () => { $el.off('click'); }); /* Touch Events */ let isTouched; let isMoved; let isScrolling; let touchesDiff; let touchStartTime; let notificationHeight; const touchesStart = {}; function handleTouchStart(e) { if (isTouched) return; isTouched = true; isMoved = false; isScrolling = undefined; touchStartTime = now(); touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX; touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY; } function handleTouchMove(e) { if (!isTouched) return; const pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; const pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; if (typeof isScrolling === 'undefined') { isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) < Math.abs(pageX - touchesStart.x)); } if (isScrolling) { isTouched = false; return; } e.preventDefault(); if (!isMoved) { notification.$el.removeClass('notification-transitioning'); notification.$el.transition(0); notificationHeight = notification.$el[0].offsetHeight / 2; } isMoved = true; touchesDiff = pageY - touchesStart.y; let newTranslate = touchesDiff; if (touchesDiff > 0) { newTranslate = touchesDiff ** 0.8; } notification.$el.transform(`translate3d(0, ${newTranslate}px, 0)`); } function handleTouchEnd() { if (!isTouched || !isMoved) { isTouched = false; isMoved = false; return; } isTouched = false; isMoved = false; if (touchesDiff === 0) { return; } const timeDiff = now() - touchStartTime; notification.$el.transition(''); notification.$el.addClass('notification-transitioning'); notification.$el.transform(''); if (touchesDiff < -10 && timeDiff < 300 || -touchesDiff >= notificationHeight / 1) { notification.close(); } } function attachTouchEvents() { notification.$el.on(app.touchEvents.start, handleTouchStart, { passive: true }); app.on('touchmove:active', handleTouchMove); app.on('touchend:passive', handleTouchEnd); } function detachTouchEvents() { notification.$el.off(app.touchEvents.start, handleTouchStart, { passive: true }); app.off('touchmove:active', handleTouchMove); app.off('touchend:passive', handleTouchEnd); } let timeoutId; function closeOnTimeout() { timeoutId = nextTick(() => { if (isTouched && isMoved) { closeOnTimeout(); return; } notification.close(); }, closeTimeout); } notification.on('open', () => { if (notification.params.swipeToClose) { attachTouchEvents(); } $('.notification.modal-in').each(openedEl => { const notificationInstance = app.notification.get(openedEl); if (openedEl !== notification.el && notificationInstance) { notificationInstance.close(); } }); if (closeTimeout) { closeOnTimeout(); } }); notification.on('close beforeDestroy', () => { if (notification.params.swipeToClose) { detachTouchEvents(); } clearTimeout(timeoutId); }); return notification; } render() { const notification = this; if (notification.params.render) return notification.params.render.call(notification, notification); const { icon, title, titleRightText, subtitle, text, closeButton, cssClass } = notification.params; return $jsx("div", { class: `notification ${icon ? 'notification-with-icon' : ''} ${cssClass || ''}` }, $jsx("div", { class: "notification-header" }, icon && $jsx("div", { class: "notification-icon" }, icon), title && $jsx("div", { class: "notification-title" }, title), titleRightText && $jsx("div", { class: "notification-title-right-text" }, titleRightText), closeButton && $jsx("span", { class: "notification-close-button" })), $jsx("div", { class: "notification-content" }, subtitle && $jsx("div", { class: "notification-subtitle" }, subtitle), text && $jsx("div", { class: "notification-text" }, text))); } } export default Notification;