@wiajs/ui
Version:
wia app ui packages
344 lines (338 loc) • 13.2 kB
JavaScript
/**
* 实现底部弹出菜单,支持js 内置button,自动创建 菜单,如:
* _actions = new Actions($.app, {
* buttons: [
// First group
[
{
text: '新建费用',
icon: '<i class="icon wiaicon iconicon_add"></i>',
onClick: function () {
$.app.dialog.alert('Button1 clicked');
},
},
{
text: '选取费用',
icon: '<i class="icon wiaicon iconsanheng"></i>',
},
],
// Second group
[
{
text: '取消',
color: 'red',
},
],
],
}
或者 使用页面模式,如页面html:
<!-- Actions 背景透明蒙版 -->
<div class="actions-backdrop"></div>
<!-- Actions Menu -->
<div class="actions-modal" style="display: none;">
<div class="actions-group">
<div name="btnNewFee" class="actions-button">
<div class="actions-button-media">
<i class="icon wiaicon iconicon_add"></i>
</div>
<div class="actions-button-text">新建费用</div>
</div>
<div name="btnSelFee" class="actions-button">
<div class="actions-button-media">
<i class="icon wiaicon iconsanheng"></i>
</div>
<div class="actions-button-text">选取费用</div>
</div>
</div>
<div class="actions-group">
<div class="actions-button color-red">
<div class="actions-button-text">取消</div>
</div>
</div>
</div>
代码里面则无需定义 button,按传统方式控制:
_actions = new Actions($.app, {
el: '.actions-modal',
backdropEl: '.actions-backdrop',
moveToRoot: false, // 不移到root层
});
传统方式,比较直观,容易控制页面样式,内置button方式,页面简单。
建议使用 传统方式,控制起来灵活。
*/ /* eslint indent: ["off"] */ import { Utils, Modal } from '@wiajs/core';
const defs = {
convertToPopover: true,
forceToPopover: false,
backdrop: true,
backdropEl: undefined,
closeByBackdropClick: true,
closeByOutsideClick: true,
closeOnEscape: false,
render: null,
renderPopover: null,
moveToRoot: true
};
let Actions = class Actions extends Modal {
constructor(app, params){
const extendedParams = Utils.extend({
on: {}
}, defs, params);
// Extends with open/close Modal methods;
super(app, extendedParams);
const actions = this;
actions.params = extendedParams;
// Buttons
let groups;
if (actions.params.buttons) {
groups = actions.params.buttons;
if (!Array.isArray(groups[0])) groups = [
groups
];
}
actions.groups = groups;
// Find Element
let $el;
if (actions.params.el) {
$el = $(actions.params.el).eq(0);
} else if (actions.params.content) {
$el = $(actions.params.content).filter((elIndex, node)=>node.nodeType === 1).eq(0);
} else if (actions.params.buttons) {
if (actions.params.convertToPopover) {
actions.popoverHtml = actions.renderPopover();
}
actions.actionsHtml = actions.render();
}
if ($el && $el.length > 0 && $el[0].f7Modal) {
return $el[0].f7Modal;
}
if ($el && $el.length === 0 && !(actions.actionsHtml || actions.popoverHtml)) {
return actions.destroy();
}
// Backdrop,半透明蒙版
let $backdropEl;
if (actions.params.backdrop && actions.params.backdropEl) {
$backdropEl = $(actions.params.backdropEl);
} else if (actions.params.backdrop) {
$backdropEl = app.root.children('.actions-backdrop');
if ($backdropEl.length === 0) {
$backdropEl = $('<div class="actions-backdrop"></div>');
app.root.append($backdropEl);
}
}
const originalOpen = actions.open;
const originalClose = actions.close;
let popover;
function buttonOnClick(e) {
const $buttonEl = $(this);
let buttonIndex;
let groupIndex;
if ($buttonEl.hasClass('list-button') || $buttonEl.hasClass('item-link')) {
buttonIndex = $buttonEl.parents('li').index();
groupIndex = $buttonEl.parents('.list').index();
} else {
buttonIndex = $buttonEl.index();
groupIndex = $buttonEl.parents('.actions-group').index();
}
if (typeof groups !== 'undefined') {
const button = groups[groupIndex][buttonIndex];
if (button.onClick) button.onClick(actions, e);
if (actions.params.onClick) actions.params.onClick(actions, e);
if (button.close !== false) actions.close(); // 除非设置为不关闭,否则自动关闭
}
}
actions.open = function(animate) {
let convertToPopover = false;
const { targetEl, targetX, targetY, targetWidth, targetHeight } = actions.params;
if (actions.params.convertToPopover && (targetEl || targetX !== undefined && targetY !== undefined)) {
// Popover
if (actions.params.forceToPopover || app.device.ios && app.device.ipad || app.width >= 768 || app.device.desktop && app.theme === 'pc') {
convertToPopover = true;
}
}
if (convertToPopover && actions.popoverHtml) {
popover = app.popover.create({
content: actions.popoverHtml,
backdrop: actions.params.backdrop,
targetEl,
targetX,
targetY,
targetWidth,
targetHeight
});
popover.open(animate);
popover.once('popoverOpened', ()=>{
popover.$el.find('.list-button, .item-link').each((groupIndex, buttonEl)=>{
$(buttonEl).on('click', buttonOnClick);
});
});
popover.once('popoverClosed', ()=>{
popover.$el.find('.list-button, .item-link').each((groupIndex, buttonEl)=>{
$(buttonEl).off('click', buttonOnClick);
});
Utils.nextTick(()=>{
popover.destroy();
popover = undefined;
});
});
} else {
actions.$el = actions.actionsHtml ? $(actions.actionsHtml) : actions.$el;
actions.$el[0].f7Modal = actions;
if (actions.groups) {
actions.$el.find('.actions-button').each((groupIndex, buttonEl)=>{
const btn = $(buttonEl);
btn.click(buttonOnClick);
});
actions.once('actionsClosed', ()=>{
actions.$el.find('.actions-button').each((groupIndex, buttonEl)=>{
const btn = $(buttonEl);
btn.off('click', buttonOnClick);
});
});
}
actions.el = actions.$el[0];
originalOpen.call(actions, animate);
}
return actions;
};
actions.close = function close(animate) {
if (popover) {
popover.close(animate);
} else {
originalClose.call(actions, animate);
}
return actions;
};
Utils.extend(actions, {
app,
$el,
el: $el ? $el[0] : undefined,
$backdropEl,
backdropEl: $backdropEl && $backdropEl[0],
type: 'actions'
});
// 背景蒙片层被点击
function handleClick(e) {
const target = e.target;
const $target = $(target);
const keyboardOpened = !app.device.desktop && app.device.cordova && (window.Keyboard && window.Keyboard.isVisible || window.cordova.plugins && window.cordova.plugins.Keyboard && window.cordova.plugins.Keyboard.isVisible);
if (keyboardOpened) return;
// 不使用 组件内置创建 buttons
if (!groups || $target.closest(actions.el).length === 0) {
if (actions.params.closeByBackdropClick && actions.params.backdrop && actions.backdropEl && actions.backdropEl === target) {
actions.close();
} else if (actions.params.closeByOutsideClick) {
actions.close();
}
}
}
function onKeyDown(e) {
const keyCode = e.keyCode;
if (keyCode === 27 && actions.params.closeOnEscape) {
actions.close();
}
}
if (actions.params.closeOnEscape) {
actions.on('open', ()=>{
$(document).on('keydown', onKeyDown);
});
actions.on('close', ()=>{
$(document).off('keydown', onKeyDown);
});
}
actions.on('opened', ()=>{
if (actions.params.closeByBackdropClick || actions.params.closeByOutsideClick) {
app.on('click', handleClick);
}
});
actions.on('close', ()=>{
if (actions.params.closeByBackdropClick || actions.params.closeByOutsideClick) {
app.off('click', handleClick);
}
});
if ($el) {
$el[0].f7Modal = actions;
}
return actions;
}
render() {
const actions = this;
if (actions.params.render) return actions.params.render.call(actions, actions);
const { groups } = actions;
return `
<div class="actions-modal${actions.params.grid ? ' actions-grid' : ''}">
${groups.map((group)=>`<div class="actions-group">
${group.map((button)=>{
const buttonClasses = [
`actions-${button.label ? 'label' : 'button'}`
];
const { color, bg, bold, disabled, label, text, icon } = button;
if (color) buttonClasses.push(`color-${color}`);
if (bg) buttonClasses.push(`bg-color-${bg}`);
if (bold) buttonClasses.push('actions-button-bold');
if (disabled) buttonClasses.push('disabled');
if (label) {
return `<div class="${buttonClasses.join(' ')}">${text}</div>`;
}
return `
<div class="${buttonClasses.join(' ')}">
${icon ? `<div class="actions-button-media">${icon}</div>` : ''}
<div class="actions-button-text">${text}</div>
</div>`.trim();
}).join('')}
</div>`).join('')}
</div>
`.trim();
}
renderPopover() {
const actions = this;
if (actions.params.renderPopover) return actions.params.renderPopover.call(actions, actions);
const { groups } = actions;
return `
<div class="popover popover-from-actions">
<div class="popover-inner">
${groups.map((group)=>`
<div class="list">
<ul>
${group.map((button)=>{
const itemClasses = [];
const { color, bg, bold, disabled, label, text, icon } = button;
if (color) itemClasses.push(`color-${color}`);
if (bg) itemClasses.push(`bg-color-${bg}`);
if (bold) itemClasses.push('popover-from-actions-bold');
if (disabled) itemClasses.push('disabled');
if (label) {
itemClasses.push('popover-from-actions-label');
return `<li class="${itemClasses.join(' ')}">${text}</li>`;
}
if (icon) {
itemClasses.push('item-link item-content');
return `
<li>
<a class="${itemClasses.join(' ')}">
<div class="item-media">
${icon}
</div>
<div class="item-inner">
<div class="item-title">
${text}
</div>
</div>
</a>
</li>
`;
}
itemClasses.push('list-button');
return `
<li>
<a class="${itemClasses.join(' ')}">${text}</a>
</li>
`;
}).join('')}
</ul>
</div>
`).join('')}
</div>
</div>
`.trim();
}
};
export default Actions;