import {Command, Session} from "../session"; import {config, state} from '../state' import {body_scroll_to, box_scroll_to} from "../utils"; import {getWidgetElement} from "../models/output" import {CommandHandler} from "./base"; const DISPLAY_NONE_TAGS = ['script', 'style']; export class OutputHandler implements CommandHandler { session: Session; accept_command = ['output', 'output_ctl']; private readonly container_parent: JQuery; private readonly container_elem: JQuery; constructor(session: Session, container_elem: JQuery) { this.session = session; this.container_elem = container_elem; this.container_parent = this.container_elem.parent(); } scroll_bottom() { body_scroll_to($('.pywebio'), 'bottom', null,15); }; handle_message(msg: Command) { let output_to_root = false; if (msg.command === 'output') { let elem; try { elem = getWidgetElement(msg.spec); } catch (e) { return console.error(`Handle command error, command: ${msg}, error:${e}`); } let container_elem = $(msg.spec.scope); if (config.outputAnimation && DISPLAY_NONE_TAGS.indexOf(elem[0].tagName.toLowerCase())==-1 && container_elem.length == 1) elem.hide(); if (container_elem.length === 0) return console.error(`Scope '${msg.spec.scope}' not found`); if (!msg.spec.scope || msg.spec.scope === '#pywebio-scope-ROOT') output_to_root = true; if (msg.spec.position === 0) container_elem.prepend(elem); else if (msg.spec.position === -1) container_elem.append(elem); else { for (let con of container_elem) { let pos = $(con.children).eq(msg.spec.position); if (msg.spec.position >= 0) elem.insertBefore(pos); else elem.insertAfter(pos); } } if (config.outputAnimation && DISPLAY_NONE_TAGS.indexOf(elem[0].tagName.toLowerCase())==-1 && container_elem.length == 1) elem.fadeIn(); } else if (msg.command === 'output_ctl') { this.handle_output_ctl(msg); } // 当设置了AutoScrollBottom、并且当前输出输出到页面末尾时,滚动到底部 if (state.AutoScrollBottom && output_to_root) this.scroll_bottom(); }; handle_output_ctl(msg: Command) { if (msg.spec.set_scope !== undefined) { let spec = msg.spec as { set_scope: string, // scope名 container: string, // 此scope的父scope position: number, // 在父scope中创建此scope的位置 0 -> 在父scope的顶部创建, -1 -> 在父scope的尾部创建 if_exist: string // 已经存在 ``name`` scope 时如何操作: `'remove'` 表示先移除旧scope再创建新scope, `'clear'` 表示将旧scope的内容清除,不创建新scope,null/不指定时表示立即返回不进行任何操作 }; let container_elem = $(`${spec.container}`); if (container_elem.length === 0) return console.error(`Scope '${msg.spec.scope}' not found`); let old = $(`#${spec.set_scope}`); if (old.length) { if (spec.if_exist == 'remove') old.remove(); else if (spec.if_exist == 'clear') { old.empty(); return; } else { return; } } let html = `
`; if (spec.position === 0) container_elem.prepend(html); else if (spec.position === -1) container_elem.append(html); else { if (spec.position >= 0) $(`${spec.container}>*`).eq(spec.position).insertBefore(html); else $(`${spec.container}>*`).eq(spec.position).insertAfter(html); } } if (msg.spec.clear !== undefined) { $(msg.spec.clear).empty(); } if (msg.spec.clear_before !== undefined) $(`${msg.spec.clear_before}`).prevAll().remove(); if (msg.spec.clear_after !== undefined) $(`${msg.spec.clear_after}~*`).remove(); if (msg.spec.scroll_to !== undefined) { let target = $(`${msg.spec.scroll_to}`); if (!target.length) { console.error(`Scope ${msg.spec.scroll_to} not found`); } else { body_scroll_to(target, msg.spec.position); } } if (msg.spec.clear_range !== undefined) { if ($(`${msg.spec.clear_range[0]}`).length && $(`${msg.spec.clear_range[1]}`).length) { let removed: HTMLElement[] = []; let valid = false; $(`${msg.spec.clear_range[0]}~*`).each(function () { if (this.id === msg.spec.clear_range[1]) { valid = true; return false; } removed.push(this); // $(this).remove(); }); if (valid) $(removed).remove(); else console.warn(`clear_range not valid: can't find ${msg.spec.clear_range[1]} after ${msg.spec.clear_range[0]}`); } } if (msg.spec.remove !== undefined) $(`${msg.spec.remove}`).remove(); }; }