UNPKG

xterm-addon-search-bar

Version:

[![Build Status](https://github.com/yinshuxun/xterm-addon-search-bar/workflows/ci/badge.svg?branch=master&event=push)](https://github.com/yinshuxun/xterm-addon-search-bar/actions) [![Build Status](https://github.com/yinshuxun/xterm-addon-search-bar/workfl

137 lines (120 loc) 4.29 kB
import { ITerminalAddon, Terminal } from 'xterm'; import { ISearchOptions, SearchAddon } from 'xterm-addon-search'; import './index.css'; export interface SearchBarOption extends ISearchOptions { searchAddon: SearchAddon; } const ADDON_MARKER_NAME = 'xterm-search-bar__addon'; export class SearchBarAddon implements ITerminalAddon { private readonly options: Partial<SearchBarOption>; private terminal: Terminal; private readonly searchAddon: SearchAddon; private searchBarElement: HTMLDivElement; private searchKey: string; constructor(options: Partial<SearchBarOption>) { this.options = options || {}; if (this.options && this.options.searchAddon) { this.searchAddon = this.options.searchAddon; } } activate(terminal: Terminal): void { this.terminal = terminal; if (!this.searchAddon) { console.error('Cannot use search bar addon until search addon has been loaded!'); } } dispose() { this.hidden(); } /** * Show the bar in the term * @returns empty * @memberof SearchBarAddon necessary search addon instance */ show() { if (!this.terminal || !this.terminal.element) { return; } if (this.searchBarElement) { this.searchBarElement.style.visibility = 'visible'; (this.searchBarElement.querySelector('input') as HTMLInputElement).select(); return; } this.terminal.element.style.position = 'relative'; const element = document.createElement('div'); element.innerHTML = ` <input type="text" class="search-bar__input" name="search-bar__input"/> <button class="search-bar__btn prev"></button> <button class="search-bar__btn next"></button> <button class="search-bar__btn close"></button> `; element.className = ADDON_MARKER_NAME; const parentElement = <HTMLElement>this.terminal.element.parentElement; this.searchBarElement = element; if (!['relative', 'absoulte', 'fixed'].includes(parentElement.style.position)) { parentElement.style.position = 'relative'; } parentElement.appendChild(this.searchBarElement); this.on('.search-bar__btn.close', 'click', () => { this.hidden(); }); this.on('.search-bar__btn.next', 'click', () => { this.searchAddon.findNext(this.searchKey, { incremental: false }); }); this.on('.search-bar__btn.prev', 'click', () => { this.searchAddon.findPrevious(this.searchKey, { incremental: false }); }); this.on('.search-bar__input', 'keyup', (e: any) => { this.searchKey = (e.target as HTMLInputElement).value; this.searchAddon.findNext(this.searchKey, { incremental: e.key !== `Enter` }); }); (this.searchBarElement.querySelector('input') as HTMLInputElement).select(); } /** * You can manually call close, also can click the close button on the bar * @memberof SearchBarAddon */ hidden() { if (this.searchBarElement && (this.terminal.element as HTMLElement).parentElement) { this.searchBarElement.style.visibility = 'hidden'; } } private on(selector: string, event: string, cb: (e: any) => void) { const parentElement = <HTMLElement>(this.terminal.element as HTMLElement).parentElement; parentElement.addEventListener(event, (e) => { let target = e.target; while (target !== document.querySelector(selector)) { if (target === parentElement) { target = null; break; } target = (target as HTMLElement).parentElement; } if (target === document.querySelector(selector)) { cb.call(this, e); e.stopPropagation(); } }); } /** * You can customize your own style, and then add CSS string template after search bar init * @param {string} newStyle * @memberof SearchBarAddon */ addNewStyle(newStyle: string) { let styleElement = document.getElementById(ADDON_MARKER_NAME) as HTMLStyleElement; if (!styleElement) { styleElement = document.createElement('style'); styleElement.type = 'text/css'; styleElement.id = ADDON_MARKER_NAME; document.getElementsByTagName('head')[0].appendChild(styleElement); } styleElement.appendChild(document.createTextNode(newStyle)); } }