framework7
Version:
Full featured mobile HTML framework for building iOS & Android apps
165 lines (162 loc) • 5.3 kB
JavaScript
import $ from '../../shared/dom7.js';
import { extend, now, nextTick, deleteProps } from '../../shared/utils.js';
import Framework7Class from '../../shared/class.js';
import { getSupport } from '../../shared/get-support.js';
class Toggle extends Framework7Class {
constructor(app, params) {
if (params === void 0) {
params = {};
}
super(params, [app]);
const toggle = this;
const support = getSupport();
const defaults = {};
// Extend defaults with modules params
toggle.useModulesParams(defaults);
toggle.params = extend(defaults, params);
const el = toggle.params.el;
if (!el) return toggle;
const $el = $(el);
if ($el.length === 0) return toggle;
if ($el[0].f7Toggle) return $el[0].f7Toggle;
const $inputEl = $el.children('input[type="checkbox"]');
extend(toggle, {
app,
$el,
el: $el[0],
$inputEl,
inputEl: $inputEl[0],
disabled: $el.hasClass('disabled') || $inputEl.hasClass('disabled') || $inputEl.attr('disabled') || $inputEl[0].disabled
});
Object.defineProperty(toggle, 'checked', {
enumerable: true,
configurable: true,
set(checked) {
if (!toggle || typeof toggle.$inputEl === 'undefined') return;
if (toggle.checked === checked) return;
$inputEl[0].checked = checked;
toggle.$inputEl.trigger('change');
},
get() {
return $inputEl[0].checked;
}
});
$el[0].f7Toggle = toggle;
let isTouched;
const touchesStart = {};
let isScrolling;
let touchesDiff;
let toggleWidth;
let touchStartTime;
let touchStartChecked;
function handleTouchStart(e) {
if (isTouched || toggle.disabled) return;
touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
touchesDiff = 0;
isTouched = true;
isScrolling = undefined;
touchStartTime = now();
touchStartChecked = toggle.checked;
toggleWidth = $el[0].offsetWidth;
nextTick(() => {
if (isTouched) {
$el.addClass('toggle-active-state');
}
});
}
function handleTouchMove(e) {
if (!isTouched || toggle.disabled) return;
const pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
const pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
const inverter = app.rtl ? -1 : 1;
if (typeof isScrolling === 'undefined') {
isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
}
if (isScrolling) {
isTouched = false;
return;
}
e.preventDefault();
touchesDiff = pageX - touchesStart.x;
let changed;
if (touchesDiff * inverter < 0 && Math.abs(touchesDiff) > toggleWidth / 3 && touchStartChecked) {
changed = true;
}
if (touchesDiff * inverter > 0 && Math.abs(touchesDiff) > toggleWidth / 3 && !touchStartChecked) {
changed = true;
}
if (changed) {
touchesStart.x = pageX;
toggle.checked = !touchStartChecked;
touchStartChecked = !touchStartChecked;
}
}
function handleTouchEnd() {
if (!isTouched || toggle.disabled) {
if (isScrolling) $el.removeClass('toggle-active-state');
isTouched = false;
return;
}
const inverter = app.rtl ? -1 : 1;
isTouched = false;
$el.removeClass('toggle-active-state');
let changed;
if (now() - touchStartTime < 300) {
if (touchesDiff * inverter < 0 && touchStartChecked) {
changed = true;
}
if (touchesDiff * inverter > 0 && !touchStartChecked) {
changed = true;
}
if (changed) {
toggle.checked = !touchStartChecked;
}
}
}
function handleInputChange() {
toggle.$el.trigger('toggle:change');
toggle.emit('local::change toggleChange', toggle);
}
toggle.attachEvents = function attachEvents() {
const passive = support.passiveListener ? {
passive: true
} : false;
$el.on(app.touchEvents.start, handleTouchStart, passive);
app.on('touchmove', handleTouchMove);
app.on('touchend:passive', handleTouchEnd);
toggle.$inputEl.on('change', handleInputChange);
};
toggle.detachEvents = function detachEvents() {
const passive = support.passiveListener ? {
passive: true
} : false;
$el.off(app.touchEvents.start, handleTouchStart, passive);
app.off('touchmove', handleTouchMove);
app.off('touchend:passive', handleTouchEnd);
toggle.$inputEl.off('change', handleInputChange);
};
// Install Modules
toggle.useModules();
// Init
toggle.init();
}
toggle() {
const toggle = this;
toggle.checked = !toggle.checked;
}
init() {
const toggle = this;
toggle.attachEvents();
}
destroy() {
let toggle = this;
toggle.$el.trigger('toggle:beforedestroy');
toggle.emit('local::beforeDestroy toggleBeforeDestroy', toggle);
delete toggle.$el[0].f7Toggle;
toggle.detachEvents();
deleteProps(toggle);
toggle = null;
}
}
export default Toggle;