@pi0/framework7
Version:
Full featured mobile HTML framework for building iOS & Android apps
263 lines (229 loc) • 7.3 kB
JavaScript
import $ from 'dom7';
import Utils from '../../utils/utils';
import Framework7Class from '../../utils/class';
import SwipePanel from './swipe-panel';
class Panel extends Framework7Class {
constructor(app, params = {}) {
super(params, [app]);
const panel = this;
const el = params.el;
const $el = $(el);
if ($el.length === 0) return panel;
if ($el[0].f7Panel) return $el[0].f7Panel;
$el[0].f7Panel = panel;
let { opened, side, effect } = params;
if (typeof opened === 'undefined') opened = $el.hasClass('panel-active');
if (typeof side === 'undefined') side = $el.hasClass('panel-left') ? 'left' : 'right';
if (typeof effect === 'undefined') effect = $el.hasClass('panel-cover') ? 'cover' : 'reveal';
if (!app.panel[side]) {
Utils.extend(app.panel, {
[side]: panel,
});
}
let $backdropEl = $('.panel-backdrop');
if ($backdropEl.length === 0) {
$backdropEl = $('<div class="panel-backdrop"></div>');
$backdropEl.insertBefore($el);
}
let $viewEl;
if (app.root.children('.views').length > 0) {
$viewEl = app.root.children('.views');
} else {
$viewEl = app.root.children('.view').eq(0);
}
Utils.extend(panel, {
app,
side,
effect,
$el,
el: $el[0],
opened,
$backdropEl,
backdropEl: $backdropEl[0],
$viewEl,
viewEl: $viewEl[0],
});
// Install Modules
panel.useModules();
// Init
panel.init();
return panel;
}
init() {
const panel = this;
const app = panel.app;
if (app.params.panel[`${panel.side}Breakpoint`]) {
panel.initBreakpoints();
}
if (process.env.TARGET !== 'desktop') {
if (
(app.params.panel.swipe === panel.side)
||
(app.params.panel.swipe === 'both')
||
(app.params.panel.swipe && app.params.panel.swipe !== panel.side && app.params.panel.swipeCloseOpposite)
) {
panel.initSwipePanel();
}
}
}
setBreakpoint() {
const panel = this;
const app = panel.app;
const { side, $el, $viewEl } = panel;
const breakpoint = app.params.panel[`${side}Breakpoint`];
const wasVisible = $el.hasClass('panel-visible-by-breakpoint');
if (app.width >= breakpoint) {
if (!wasVisible) {
$('html').removeClass(`with-panel-${side}-reveal with-panel-${side}-cover with-panel`);
$el.css('display', '').addClass('panel-visible-by-breakpoint').removeClass('active');
panel.onOpen();
panel.onOpened();
$viewEl.css({
[`margin-${side}`]: `${$el.width()}px`,
});
app.allowPanelOpen = true;
}
} else if (wasVisible) {
$el.css('display', '').removeClass('panel-visible-by-breakpoint active');
panel.onClose();
panel.onClosed();
$viewEl.css({
[`margin-${side}`]: '',
});
}
}
initBreakpoints() {
const panel = this;
const app = panel.app;
panel.resizeHandler = function resizeHandler() {
panel.setBreakpoint();
};
if (app.params.panel[`${panel.side}Breakpoint`]) {
app.on('resize', panel.resizeHandler);
}
panel.setBreakpoint();
return panel;
}
initSwipePanel() {
if (process.env.TARGET !== 'desktop') {
SwipePanel(this);
}
}
destroy() {
let panel = this;
const app = panel.app;
panel.emit('local::beforeDestroy panelBeforeDestroy', panel);
panel.$el.trigger('panel:beforedestroy', panel);
if (panel.resizeHandler) {
app.off('resize', panel.resizeHandler);
}
panel.$el.trigger('panel:destroy', panel);
panel.emit('local::destroy panelDestroy');
delete app.panel[panel.side];
delete panel.el.f7Panel;
Object.keys(panel).forEach((key) => {
delete panel[key];
});
panel = null;
}
open(animate = true) {
const panel = this;
const app = panel.app;
if (!app.panel.allowOpen) return false;
const { side, effect, $el, $backdropEl } = panel;
// Close if some panel is opened
app.panel.close(side === 'left' ? 'right' : 'left', animate);
app.panel.allowOpen = false;
$el[animate ? 'removeClass' : 'addClass']('not-animated');
$el
.css({ display: 'block' })
.addClass('panel-active');
$backdropEl[animate ? 'removeClass' : 'addClass']('not-animated');
$backdropEl.show();
/* eslint no-underscore-dangle: ["error", { "allow": ["_clientLeft"] }] */
panel._clientLeft = $el[0].clientLeft;
$('html').addClass(`with-panel with-panel-${side}-${effect}`);
panel.onOpen();
// Transition End;
const transitionEndTarget = effect === 'reveal' ? $el.nextAll('.view, .views').eq(0) : $el;
function panelTransitionEnd() {
transitionEndTarget.transitionEnd((e) => {
if ($(e.target).is(transitionEndTarget)) {
if ($el.hasClass('panel-active')) {
panel.onOpened();
$backdropEl.css({ display: '' });
} else {
panel.onClosed();
$backdropEl.css({ display: '' });
}
} else panelTransitionEnd();
});
}
if (animate) {
panelTransitionEnd();
} else {
panel.onOpened();
$backdropEl.css({ display: '' });
}
return true;
}
close(animate = true) {
const panel = this;
const app = panel.app;
const { side, effect, $el, $backdropEl } = panel;
if ($el.hasClass('panel-visible-by-breakpoint') || !$el.hasClass('panel-active')) return false;
$el[animate ? 'removeClass' : 'addClass']('not-animated');
$el.removeClass('panel-active');
$backdropEl[animate ? 'removeClass' : 'addClass']('not-animated');
const transitionEndTarget = effect === 'reveal' ? $el.nextAll('.view, .views').eq(0) : $el;
panel.onClose();
app.panel.allowOpen = false;
if (animate) {
transitionEndTarget.transitionEnd(() => {
if ($el.hasClass('panel-active')) return;
$el.css({ display: '' });
$('html').removeClass('with-panel-transitioning');
panel.onClosed();
});
$('html')
.removeClass(`with-panel with-panel-${side}-${effect}`)
.addClass('with-panel-transitioning');
} else {
$el.css({ display: '' });
$el.removeClass('not-animated');
$('html').removeClass(`with-panel with-panel-transitioning with-panel-${side}-${effect}`);
panel.onClosed();
}
return true;
}
onOpen() {
const panel = this;
panel.opened = true;
panel.$el.trigger('panel:open', panel);
panel.emit('local::open panelOpen', panel);
}
onOpened() {
const panel = this;
const app = panel.app;
app.panel.allowOpen = true;
panel.$el.trigger('panel:opened', panel);
panel.emit('local::opened panelOpened', panel);
}
onClose() {
const panel = this;
panel.opened = false;
panel.$el.addClass('panel-closing');
panel.$el.trigger('panel:close', panel);
panel.emit('local::close panelClose', panel);
}
onClosed() {
const panel = this;
const app = panel.app;
app.panel.allowOpen = true;
panel.$el.removeClass('panel-closing');
panel.$el.trigger('panel:closed', panel);
panel.emit('local::closed panelClosed', panel);
}
}
export default Panel;