123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- /**
- * Controls.js
- *
- * @author realor
- */
- import '../lib/codemirror.js'
- import { I18N } from '../i18n/I18N.js'
- class Controls {
- static nextId = 0
- static addText(parent, text, className) {
- const textElem = document.createElement('span')
- I18N.set(textElem, 'innerHTML', text)
- if (className) textElem.className = className
- parent.appendChild(textElem)
- return textElem
- }
- static addTextWithArgs(parent, text, args = [], className) {
- const textElem = document.createElement('span')
- I18N.set(textElem, 'innerHTML', text, ...args)
- if (className) textElem.className = className
- parent.appendChild(textElem)
- return textElem
- }
- static addCode(parent, text, className) {
- const textElem = document.createElement('pre')
- textElem.innerHTML = text
- if (className) textElem.className = className
- parent.appendChild(textElem)
- return textElem
- }
- static addLink(parent, label, url, title, className, action) {
- const linkElem = document.createElement('a')
- parent.appendChild(linkElem)
- if (className) linkElem.className = className
- if (label) I18N.set(linkElem, 'innerHTML', label)
- if (url) linkElem.href = url
- if (title) {
- I18N.set(linkElem, 'title', title)
- I18N.set(linkElem, 'alt', title)
- }
- if (action) {
- linkElem.addEventListener('click', action, false)
- }
- return linkElem
- }
- static addTextField(parent, name, label, value, className) {
- return Controls.addInputField(parent, 'text', name, label, value, className)
- }
- static addNumberField(parent, name, label, value, className) {
- return Controls.addInputField(parent, 'number', name, label, value, className)
- }
- static addPasswordField(parent, name, label, value, className) {
- return Controls.addInputField(parent, 'password', name, label, value, className)
- }
- static addDateField(parent, name, label, value, className) {
- return Controls.addInputField(parent, 'date', name, label, value, className)
- }
- static addColorField(parent, name, label, value, className) {
- return Controls.addInputField(parent, 'color', name, label, value, className)
- }
- static addCheckBoxField(parent, name, label, checked, className) {
- const id = this.getNextId()
- const groupElem = Controls.addField(parent, id, label, className)
- const labelElem = groupElem.childNodes[0]
- const inputElem = document.createElement('input')
- inputElem.id = id
- inputElem.name = name
- inputElem.type = 'checkbox'
- inputElem.checked = Boolean(checked)
- groupElem.insertBefore(inputElem, labelElem)
- return inputElem
- }
- static addInputField(parent, type, name, label, value, className) {
- const id = this.getNextId()
- const groupElem = Controls.addField(parent, id, label, className)
- const inputElem = document.createElement('input')
- inputElem.id = id
- inputElem.name = name
- inputElem.type = type || 'text'
- if (value !== undefined && value !== null) inputElem.value = value
- groupElem.appendChild(inputElem)
- return inputElem
- }
- static addTextAreaField(parent, name, label, value, className) {
- const id = this.getNextId()
- const groupElem = Controls.addField(parent, id, label, className)
- const textAreaElem = document.createElement('textarea')
- textAreaElem.id = id
- textAreaElem.name = name
- if (value) textAreaElem.value = value
- groupElem.appendChild(textAreaElem)
- return textAreaElem
- }
- static addSelectField(parent, name, label, options, value, className) {
- const id = this.getNextId()
- const groupElem = Controls.addField(parent, id, label, className)
- const selectElem = document.createElement('select')
- selectElem.id = id
- selectElem.name = name
- groupElem.appendChild(selectElem)
- if (options) {
- Controls.setSelectOptions(selectElem, options)
- }
- if (value) {
- Controls.setSelectValue(selectElem, value)
- }
- return selectElem
- }
- static setSelectOptions(selectElem, options, value = selectElem.value, create) {
- selectElem.innerHTML = ''
- if (options) {
- for (let i = 0; i < options.length; i++) {
- let option = options[i]
- let optionElem = document.createElement('option')
- if (option instanceof Array) {
- optionElem.value = option[0]
- I18N.set(optionElem, 'innerHTML', option[1])
- } else {
- optionElem.value = option
- I18N.set(optionElem, 'innerHTML', option)
- }
- selectElem.appendChild(optionElem)
- }
- if (value) {
- Controls.setSelectValue(selectElem, value, create)
- }
- }
- }
- static setSelectValue(selectElem, value = selectElem.value, create) {
- let found = false
- for (let option of selectElem.options) {
- if (option.value === value) {
- found = true
- break
- }
- }
- if (found) {
- selectElem.value = value
- } else if (value && create) {
- let optionElem = document.createElement('option')
- optionElem.value = value
- optionElem.innerHTML = value
- selectElem.appendChild(optionElem)
- selectElem.value = value
- } else if (selectElem.options.length > 0) {
- // select first
- selectElem.value = selectElem.options[0].value
- }
- }
- static addRadioButtons(parent, name, label, options, value, className, clickListener) {
- const groupElem = document.createElement('fieldset')
- parent.appendChild(groupElem)
- if (className) groupElem.className = className
- if (label) {
- const legendElem = document.createElement('legend')
- groupElem.appendChild(legendElem)
- I18N.set(legendElem, 'innerHTML', label)
- }
- const id = this.getNextId()
- const hiddenElem = document.createElement('input')
- hiddenElem.type = 'hidden'
- hiddenElem.id = id
- groupElem.appendChild(hiddenElem)
- for (let i = 0; i < options.length; i++) {
- let option = options[i]
- let radioElem = document.createElement('input')
- radioElem.id = id + '_' + i
- radioElem.type = 'radio'
- radioElem.name = name
- radioElem.value = option instanceof Array ? option[0] : option
- if (value === radioElem.value) {
- radioElem.checked = true
- hiddenElem.value = radioElem.value
- }
- radioElem.addEventListener(
- 'click',
- function(event) {
- let elem = event.target || event.srcElement
- hiddenElem.value = elem.value
- if (clickListener) clickListener(event)
- },
- false
- )
- let labelElem = document.createElement('label')
- let spanElem = document.createElement('span')
- I18N.set(spanElem, 'innerHTML', option instanceof Array ? option[1] : option)
- labelElem.htmlFor = radioElem.id
- labelElem.appendChild(radioElem)
- labelElem.appendChild(spanElem)
- groupElem.appendChild(labelElem)
- }
- return hiddenElem
- }
- static addButton(parent, name, label, action, className) {
- const buttonElem = document.createElement('button')
- buttonElem.name = name
- I18N.set(buttonElem, 'innerHTML', label)
- if (className) buttonElem.className = className
- buttonElem.addEventListener('click', event => action(event), false)
- parent.appendChild(buttonElem)
- return buttonElem
- }
- static addImageButton(parent, name, label, action, className) {
- const buttonElem = document.createElement('button')
- buttonElem.name = name
- I18N.set(buttonElem, 'title', label)
- I18N.set(buttonElem, 'alt', label)
- if (className) buttonElem.className = className
- buttonElem.addEventListener('click', event => action(event), false)
- parent.appendChild(buttonElem)
- return buttonElem
- }
- static addCodeEditor(parent, name, label, value = '', options = {}) {
- const id = this.getNextId()
- const groupElem = Controls.addField(parent, id, label, 'code_editor')
- if (options.height) {
- groupElem.style.height = options.height
- }
- const editorElem = document.createElement('div')
- editorElem.id = id
- editorElem.className = 'cm-editor-holder'
- groupElem.appendChild(editorElem)
- const { basicSetup } = CM['@codemirror/basic-setup']
- const { keymap, highlightSpecialChars, highlightActiveLine, drawSelection, EditorView } = CM['@codemirror/view']
- const { lineNumbers, highlightActiveLineGutter } = CM['@codemirror/gutter']
- const { history, historyKeymap } = CM['@codemirror/history']
- const { defaultKeymap } = CM['@codemirror/commands']
- const { bracketMatching } = CM['@codemirror/matchbrackets']
- const { foldGutter, foldKeymap } = CM['@codemirror/fold']
- const { javascript, javascriptLanguage } = CM['@codemirror/lang-javascript']
- const { json, jsonLanguage } = CM['@codemirror/lang-json']
- const { defaultHighlightStyle } = CM['@codemirror/highlight']
- const { searchKeymap, highlightSelectionMatches } = CM['@codemirror/search']
- const { indentOnInput } = CM['@codemirror/language']
- const { EditorState } = CM['@codemirror/state']
- let theme = EditorView.theme({
- '&.cm-focused .cm-cursor': {
- borderLeftColor: '#000',
- borderLeftWidth: '2px'
- },
- '&.cm-focused .cm-matchingBracket': {
- backgroundColor: 'yellow',
- color: 'black'
- },
- '& .ͼa': {
- color: '#444',
- fontWeight: 'bold'
- },
- '& .ͼl': {
- color: '#808080'
- },
- '& .ͼf': {
- color: '#8080e0'
- },
- '& .ͼd': {
- color: '#2020ff'
- },
- '& .ͼb': {
- color: '#008000'
- },
- '& .cm-wrap': {
- height: '100%'
- },
- '& .cm-scroller': {
- overflow: 'auto'
- }
- })
- this.editorView = new EditorView({
- parent: editorElem
- })
- const extensions = [
- lineNumbers(),
- highlightActiveLineGutter(),
- highlightSpecialChars(),
- history(),
- foldGutter(),
- drawSelection(),
- EditorState.allowMultipleSelections.of(true),
- indentOnInput(),
- defaultHighlightStyle.fallback,
- bracketMatching(),
- highlightActiveLine(),
- highlightSelectionMatches(),
- keymap.of([...defaultKeymap, ...searchKeymap, ...historyKeymap, ...foldKeymap]),
- options.language === 'javascript' ? javascript() : json(),
- theme
- ]
- let editorState = EditorState.create({
- doc: value || '',
- extensions: extensions
- })
- this.editorView.setState(editorState)
- return this.editorView
- }
- static addField(parent, id, label, className) {
- const groupElem = document.createElement('div')
- if (className) groupElem.className = className
- parent.appendChild(groupElem)
- const labelElem = document.createElement('label')
- labelElem.htmlFor = id
- I18N.set(labelElem, 'innerHTML', label)
- groupElem.appendChild(labelElem)
- return groupElem
- }
- static addTable(parent, name, columns, className) {
- const tableElem = document.createElement('table')
- parent.appendChild(tableElem)
- tableElem.id = name
- if (className) tableElem.className = className
- const headElem = document.createElement('thead')
- tableElem.appendChild(headElem)
- const bodyElem = document.createElement('tbody')
- tableElem.appendChild(bodyElem)
- const footElem = document.createElement('tfoot')
- tableElem.appendChild(footElem)
- if (columns) {
- const headRowElem = document.createElement('tr')
- headElem.appendChild(headRowElem)
- for (let i = 0; i < columns.length; i++) {
- const headColElem = document.createElement('th')
- headRowElem.appendChild(headColElem)
- I18N.set(headColElem, 'innerHTML', columns[i])
- headColElem.className = 'col_' + i
- }
- }
- return tableElem
- }
- static addTableRow(tableElem) {
- const columns = tableElem.tHead.children[0].children.length
- const bodyElem = tableElem.tBodies[0]
- const rowElem = document.createElement('tr')
- bodyElem.appendChild(rowElem)
- for (let i = 0; i < columns; i++) {
- let colElem = document.createElement('td')
- rowElem.appendChild(colElem)
- }
- return rowElem
- }
- static getNextId() {
- return 'f' + this.nextId++
- }
- }
- export { Controls }
|