123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- import {Command, Session} from "../session";
- import {randomid} from "../utils";
- import {getWidgetElement} from "../models/output"
- import {CommandHandler} from "./base";
- export class PopupHandler implements CommandHandler {
- session: Session;
- accept_command = ['popup', 'close_popup'];
- private body = $('body');
- constructor(session: Session) {
- this.session = session;
- }
- static current_elem: JQuery<HTMLElement> = null; // 当前正在处于显示中的弹窗元素,表示页面的期望状态
- handle_message(msg: Command) {
- if (PopupHandler.current_elem) {
- // @ts-ignore
- PopupHandler.current_elem.modal('hide');
- PopupHandler.current_elem = null;
- }
- if (msg.command == 'popup') {
- // 显示弹窗前,先关闭其他弹窗
- // @ts-ignore
- $('.modal').modal('hide');
- let elem = PopupHandler.get_element(msg.spec);
- this.body.append(elem);
- // 弹窗关闭后就立即销毁
- elem.on('hidden.bs.modal', function (e) {
- elem.remove();
- });
- elem.on('shown.bs.modal', function (e) {
- // 弹窗显示后,有新弹窗出现或当前弹窗被关闭,则立即关闭当前弹窗
- if (elem != PopupHandler.current_elem || !PopupHandler.current_elem) {
- // @ts-ignore
- elem.modal('hide');
- }
- });
- // @ts-ignore
- elem.modal('show');
- PopupHandler.current_elem = elem;
- } else if (msg.command == 'close_popup') {
- // @ts-ignore
- $('.modal').modal('hide');
- PopupHandler.current_elem = null;
- }
- }
- static get_element(spec: { title: string, content: any[], closable: boolean, implicit_close: boolean, size: string }) {
- // https://v4.bootcss.com/docs/components/modal/#options
- const tpl = `<div class="modal fade" {{^implicit_close}}data-backdrop="static"{{/implicit_close}} aria-labelledby="model-id-{{ mid }}" tabindex="-1" role="dialog" aria-hidden="true">
- <div class="modal-dialog modal-dialog-scrollable {{#large}}modal-lg{{/large}} {{#small}}modal-sm{{/small}}" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <h5 class="modal-title" id="model-id-{{ mid }}">{{ title }}</h5>
- {{#closable}}
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span aria-hidden="true">×</span>
- </button>
- {{/closable}}
- </div>
- <div class="modal-body markdown-body">
- {{& content }}
- </div>
- <!--
- <div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
- <button type="button" class="btn btn-primary">Submit</button>
- </div>
- -->
- </div>
- </div>
- </div>`;
- let mid = randomid(10);
- let body_html = '';
- for (let output_item of spec.content) {
- if (typeof output_item === 'object') {
- try {
- let nodes = getWidgetElement(output_item);
- for (let node of nodes)
- body_html += node.outerHTML || '';
- } catch (e) {
- console.error('Get widget html error,', e, output_item);
- }
- } else {
- body_html += output_item;
- }
- }
- if (!spec.closable)
- spec.implicit_close = false;
- let html = Mustache.render(tpl, {
- ...spec, // 字段: content, title, size, implicit_close, closable
- large: spec.size == 'large',
- small: spec.size == 'small',
- mid: mid,
- content: body_html,
- });
- return $(html as string);
- }
- }
|