framework7
Version:
Full featured mobile HTML framework for building iOS & Android apps
349 lines (328 loc) • 9.42 kB
JavaScript
/* eslint-disable no-underscore-dangle */
import { getWindow, getDocument } from 'ssr-window';
import { extend, nextFrame } from '../../shared/utils.js';
import { getDevice } from '../../shared/get-device.js';
import { getSupport } from '../../shared/get-support.js';
import Framework7Class from '../../shared/class.js';
import EventsClass from '../../shared/events-class.js';
import ConstructorMethods from '../../shared/constructor-methods.js';
import ModalMethods from '../../shared/modal-methods.js';
import $ from '../../shared/dom7.js';
import loadModule from './load-module.js';
import $jsx from '../../shared/$jsx.js';
class Framework7 extends Framework7Class {
constructor(params) {
if (params === void 0) {
params = {};
}
super(params);
// eslint-disable-next-line
if (Framework7.instance && typeof window !== 'undefined') {
throw new Error("Framework7 is already initialized and can't be initialized more than once");
}
const device = getDevice({
userAgent: params.userAgent || undefined
});
const support = getSupport();
const passedParams = extend({}, params);
// App Instance
const app = this;
app.device = device;
app.support = support;
const w = getWindow();
const d = getDocument();
Framework7.instance = app;
// Default
const defaults = {
el: 'body',
theme: 'auto',
routes: [],
name: 'Framework7',
lazyModulesPath: null,
initOnDeviceReady: true,
init: true,
darkMode: undefined,
iosTranslucentBars: true,
iosTranslucentModals: true,
component: undefined,
componentUrl: undefined,
userAgent: null,
url: null,
colors: {
primary: '#007aff',
red: '#ff3b30',
green: '#4cd964',
blue: '#2196f3',
pink: '#ff2d55',
yellow: '#ffcc00',
orange: '#ff9500',
purple: '#9c27b0',
deeppurple: '#673ab7',
lightblue: '#5ac8fa',
teal: '#009688',
lime: '#cddc39',
deeporange: '#ff6b22',
white: '#ffffff',
black: '#000000'
}
};
// Extend defaults with modules params
app.useModulesParams(defaults);
// Extend defaults with passed params
app.params = extend(defaults, params);
extend(app, {
// App Name
name: app.params.name,
// Routes
routes: app.params.routes,
// Theme
theme: function getTheme() {
if (app.params.theme === 'auto') {
if (device.ios) return 'ios';
return 'md';
}
return app.params.theme;
}(),
// Initially passed parameters
passedParams,
online: w.navigator.onLine,
colors: app.params.colors,
darkMode: app.params.darkMode
});
if (params.store) app.params.store = params.store;
// Save Root
if (app.$el && app.$el[0]) {
app.$el[0].f7 = app;
}
// Install Modules
app.useModules();
// Init Store
app.initStore();
// Init
if (app.params.init) {
if (device.cordova && app.params.initOnDeviceReady) {
$(d).on('deviceready', () => {
app.init();
});
} else {
app.init();
}
}
// Return app instance
return app;
}
setColorTheme(color) {
if (!color) return;
const app = this;
app.colors.primary = color;
app.setColors();
}
setColors() {
const app = this;
const document = getDocument();
if (!app.colorsStyleEl) {
app.colorsStyleEl = document.createElement('style');
document.head.prepend(app.colorsStyleEl);
}
app.colorsStyleEl.textContent = app.utils.colorThemeCSSStyles(app.colors);
}
mount(rootEl) {
const app = this;
const window = getWindow();
const document = getDocument();
const $rootEl = $(rootEl || app.params.el).eq(0);
app.$el = $rootEl;
if (app.$el && app.$el[0]) {
app.el = app.$el[0];
app.el.f7 = app;
app.rtl = $rootEl.css('direction') === 'rtl';
}
// Auto Dark Mode
const DARK = '(prefers-color-scheme: dark)';
const LIGHT = '(prefers-color-scheme: light)';
app.mq = {};
if (window.matchMedia) {
app.mq.dark = window.matchMedia(DARK);
app.mq.light = window.matchMedia(LIGHT);
}
app.colorSchemeListener = function colorSchemeListener(_ref) {
let {
matches,
media
} = _ref;
if (!matches) {
return;
}
const html = document.querySelector('html');
if (media === DARK) {
html.classList.add('dark');
app.darkMode = true;
app.emit('darkModeChange', true);
} else if (media === LIGHT) {
html.classList.remove('dark');
app.darkMode = false;
app.emit('darkModeChange', false);
}
};
app.emit('mount');
}
initStore() {
const app = this;
if (typeof app.params.store !== 'undefined' && app.params.store.__store) {
app.store = app.params.store;
} else {
app.store = app.createStore(app.params.store);
}
}
enableAutoDarkMode() {
const window = getWindow();
const document = getDocument();
if (!window.matchMedia) return;
const app = this;
const html = document.querySelector('html');
if (app.mq.dark && app.mq.light) {
app.mq.dark.addEventListener('change', app.colorSchemeListener);
app.mq.light.addEventListener('change', app.colorSchemeListener);
}
if (app.mq.dark && app.mq.dark.matches) {
html.classList.add('dark');
app.darkMode = true;
app.emit('darkModeChange', true);
} else if (app.mq.light && app.mq.light.matches) {
html.classList.remove('dark');
app.darkMode = false;
app.emit('darkModeChange', false);
}
}
disableAutoDarkMode() {
const window = getWindow();
if (!window.matchMedia) return;
const app = this;
if (app.mq.dark) app.mq.dark.removeEventListener('change', app.colorSchemeListener);
if (app.mq.light) app.mq.light.removeEventListener('change', app.colorSchemeListener);
}
setDarkMode(mode) {
const app = this;
if (mode === 'auto') {
app.enableAutoDarkMode();
} else {
app.disableAutoDarkMode();
$('html')[mode ? 'addClass' : 'removeClass']('dark');
app.darkMode = mode;
}
}
initAppComponent(callback) {
const app = this;
app.router.componentLoader(app.params.component, app.params.componentUrl, {
componentOptions: {
el: app.$el[0]
}
}, el => {
app.$el = $(el);
app.$el[0].f7 = app;
app.$elComponent = el.f7Component;
app.el = app.$el[0];
if (callback) callback();
}, () => {});
}
init(rootEl) {
const app = this;
app.setColors();
app.mount(rootEl);
const init = () => {
if (app.initialized) return;
app.$el.addClass('framework7-initializing');
// RTL attr
if (app.rtl) {
$('html').attr('dir', 'rtl');
}
// Auto Dark Mode
if (typeof app.params.darkMode === 'undefined') {
app.darkMode = $('html').hasClass('dark');
} else {
app.setDarkMode(app.params.darkMode);
}
// Watch for online/offline state
const window = getWindow();
window.addEventListener('offline', () => {
app.online = false;
app.emit('offline');
app.emit('connection', false);
});
window.addEventListener('online', () => {
app.online = true;
app.emit('online');
app.emit('connection', true);
});
// Root class
app.$el.addClass('framework7-root');
// Theme class
$('html').removeClass('ios md').addClass(app.theme);
// iOS Translucent
if (app.params.iosTranslucentBars && app.theme === 'ios') {
$('html').addClass('ios-translucent-bars');
}
if (app.params.iosTranslucentModals && app.theme === 'ios') {
$('html').addClass('ios-translucent-modals');
}
// Init class
nextFrame(() => {
app.$el.removeClass('framework7-initializing');
});
// Emit, init other modules
app.initialized = true;
app.emit('init');
};
if (app.params.component || app.params.componentUrl) {
app.initAppComponent(() => {
init();
});
} else {
init();
}
return app;
}
// eslint-disable-next-line
loadModule() {
return Framework7.loadModule(...arguments);
}
// eslint-disable-next-line
loadModules() {
return Framework7.loadModules(...arguments);
}
getVnodeHooks(hook, id) {
const app = this;
if (!app.vnodeHooks || !app.vnodeHooks[hook]) return [];
return app.vnodeHooks[hook][id] || [];
}
// eslint-disable-next-line
get $() {
return $;
}
static get Dom7() {
return $;
}
static get $() {
return $;
}
static get device() {
return getDevice();
}
static get support() {
return getSupport();
}
static get Class() {
return Framework7Class;
}
static get Events() {
return EventsClass;
}
}
Framework7.$jsx = $jsx;
Framework7.ModalMethods = ModalMethods;
Framework7.ConstructorMethods = ConstructorMethods;
Framework7.loadModule = loadModule;
Framework7.loadModules = function loadModules(modules) {
return Promise.all(modules.map(module => Framework7.loadModule(module)));
};
export default Framework7;