diff --git a/bricks/form.js b/bricks/form.js index c90dcdb..6c7fa5c 100644 --- a/bricks/form.js +++ b/bricks/form.js @@ -80,7 +80,7 @@ bricks.FormBody = class extends bricks.VScrollPanel { this.form = form; this.name_inputs = {}; this.fg = new bricks.FieldGroup({}); - this.fg.build_fields(form, this, form.opts.fields) + this.fg.build_fields(form, this, form.nontextfields) } create(){ this.dom_element = this._create('form'); @@ -308,8 +308,48 @@ bricks.Form = class extends bricks.FormBase { this.set_css('vcontainer'); var filler = new bricks.Filler({}); this.add_widget(filler); + this.nontextfields = []; + this.textfields = []; + this.fields.forEach((f) => { + if (f.uitype == 'text'){ + this.textfields.push(f); + } else { + this.nontextfields.push(f); + } + }); this.body = new bricks.FormBody(this, opts); - filler.add_widget(this.body); + if (this.textfields.length > 0){ + var tp; + var tp_options = { + height: "100%", + tab_pos: "top", + items:[ + { + "name":"form", + "label":"Form", + "content":this.body + } + ] + }; + this.textfields.forEach((f) => { + var txtw = new bricks.UiText({ + name:f.name, + width:"100%", + height:"100%", + value:f.value + }); + tp_options.items.push({ + name:f.name, + label:f.label, + content:txtw + }); + this.name_inputs[f.name] = txtw; + }); + tp = new bricks.TabPanel(tp_options); + filler.add_widget(tp); + } else { + filler.add_widget(this.body); + } if (! opts.notoolbar) this.build_toolbar(this); } diff --git a/bricks/input.js b/bricks/input.js index d47870f..0b6d7cf 100644 --- a/bricks/input.js +++ b/bricks/input.js @@ -816,6 +816,7 @@ bricks.UiText =class extends bricks.UiType { this.uitype='text'; this.build(); this.charsize_sizing(); + this.bind('keydown', this.key_handle.bind(this)) } create(){ this.dom_element = this._create('textarea'); @@ -846,6 +847,87 @@ bricks.UiText =class extends bricks.UiType { var v = this.opts.value || this.opts.defaultvalue||''; this.setValue(v); } + key_handle(e){ + switch(e.key){ + case 'Tab': + e.preventDefault(); // 阻止默认Tab行为 + var erase = false + if (e.shiftKey) erase = true; + this.handle_tab_indent(erase); + break; + case 'Enter': + e.preventDefault(); // 阻止默认Tab行为 + this.handle_enter(); + default: + break; + } + } + handle_enter(){ + var editor = this.dom_element; + const cursorPos = editor.selectionStart; + const value = editor.value; + const before = value.substring(0, cursorPos); + const after = value.substring(cursorPos); + editor.value = before + '\n' + after; + editor.selectionStart = editor.selectionEnd = cursorPos + 1; + } + handle_tab_indent(erase){ + /* erase == true : delete tabspace + else + add tabspace + */ + var editor = this.dom_element; + const cursorPos = editor.selectionStart; + const value = editor.value; + + // 获取光标所在行的开始位置 + const beforeCursor = value.substring(0, cursorPos); + const lastLineStart = beforeCursor.lastIndexOf("\n") + 1; // 上一行的结束位置 + const currentLineStart = lastLineStart; // 当前行的开始位置 + + // 获取当前行的文本 + const currentLine = value.substring(currentLineStart, value.indexOf("\n", currentLineStart) !== -1 ? value.indexOf("\n", currentLineStart) : undefined); + + // 判断当前行的缩进(获取行首的空格数) + const leadingSpaces = currentLine.match(/^\s*/)[0]; + const spacesCount = leadingSpaces.length; + + // 设置插入的空格数量(确保每次按Tab后光标前总是4个空格的缩进) + let indentationCount = 0; + if (spacesCount % 4 === 0) { + indentationCount = 4; // 如果已经是4的倍数,插入4个空格 + } else if (spacesCount % 4 === 1) { + indentationCount = 3; // 如果有1个空格,插入3个空格 + } else if (spacesCount % 4 === 2) { + indentationCount = 2; // 如果有2个空格,插入2个空格 + } else if (spacesCount % 4 === 3) { + indentationCount = 1; // 如果有3个空格,插入1个空格 + } + + // 处理Tab键按下 + if (!erase){ + // 根据光标前的空格数动态插入合适数量的空格 + const before = value.substring(0, cursorPos); + const after = value.substring(cursorPos); + + const indentation = ' '.repeat(indentationCount); // 生成合适数量的空格 + + // 更新文本框的值,插入缩进 + editor.value = before + indentation + after; + + // 更新光标位置(将光标移到插入的缩进后面) + editor.selectionStart = editor.selectionEnd = cursorPos + indentationCount; + } else { + // 处理Shift + Tab(减少缩进) + // 如果当前行有4个空格的缩进,删除它 + if (spacesCount >= 4) { + const before = value.substring(0, cursorPos - 4); + const after = value.substring(cursorPos); + editor.value = before + after; + editor.selectionStart = editor.selectionEnd = cursorPos - 4; + } + } + } } bricks.UiCode =class extends bricks.UiType { diff --git a/bricks/tab.js b/bricks/tab.js index 30424dd..8174ce0 100644 --- a/bricks/tab.js +++ b/bricks/tab.js @@ -93,7 +93,11 @@ bricks.TabPanel = class extends bricks.Layout { return; } try { - w = await bricks.widgetBuild(items[i].content, this, {}); + if (items[i].content instanceof bricks.JsWidget){ + w = items[i].content; + } else { + w = await bricks.widgetBuild(items[i].content, this, {}); + } if (! w){ bricks.debug('TabPanel():create content error', items[i].content); return;