diff --git a/README.md b/README.md index d9a412e..59a8b49 100755 --- a/README.md +++ b/README.md @@ -2,21 +2,11 @@ A new web application development framework to make web application development more easier like play bricks ## Documentation -We have English and Chinese versions documents, -Documents in English, please read from [docs](docs/README.md), 中文资料看[这里](docs/cn/README.md) -## Development base on components +We have documents in 3 language -We built web development components which use a options objects as API. -third party can develops their component suply the standard of components API +* [中文](docs/zh/brief.md) +* [日本語](docs/ja/brief.md) +* [English](docs/en/brief.md) -Most front-end development tools only help user to build the front-end UI, and use script to build the app's logic. - -Bricks not only build the UI but also the front-end logic. - -Bricks provide a new mathiciam to description the event fire, and event handler, Bricks use json data to descripts event and it handler, when event fire, according the json data, Bricks dynamicly constructs the event handler. - - -## Dependanance - -[Marked](https://github.com/yumoqing/marked) is a tool for markdown text parser, extends from [MarkedJs marked](https://github.com/markedjs/marked), we extends audio and video link, user can directly use `!v[text](url)` pattern to show a video player, and `!a[text](url)` pattern to show a audio player +NOTE: all the documents was generated by Qwen3-max diff --git a/bricks/.DS_Store b/bricks/.DS_Store index b5aa3f5..07573e0 100755 Binary files a/bricks/.DS_Store and b/bricks/.DS_Store differ diff --git a/bricks/bricks.js b/bricks/bricks.js index a842d33..2bba77c 100644 --- a/bricks/bricks.js +++ b/bricks/bricks.js @@ -1,4 +1,13 @@ var bricks = window.bricks || {}; +bricks.get_current_language=function(){ + var lang = navigator.language.substring(0, 2); + if (bricks.app){ + if (bricks.app.lang) return bricks.app.lang; + bricks.app.lang = lang; + return lang; + } + return; +} bricks.app = null; /* all type of bind action's desc has the following attributes: @@ -231,19 +240,21 @@ bricks.universal_handler = async function(from_widget, widget, desc, event){ bricks.default_popup = function(opts){ var popts = bricks.get_popup_default_options(); bricks.extend(popts, opts); + popts.origin_event = event; return new bricks.Popup(popts); } -bricks.default_popupwindow = function(opts){ +bricks.default_popupwindow = function(opts,event){ var popts = bricks.get_popupwindow_default_options(); bricks.extend(popts, opts); + popts.origin_event = event; return new bricks.PopupWindow(popts); } bricks.buildEventHandler = async function(w, desc, event){ var target; if (desc.target == 'Popup'){ - target = bricks.default_popup(desc.popup_options || {}); + target = bricks.default_popup(desc.popup_options || {}, event); } else if (desc.target == 'PopupWindow') { - target = bricks.default_popupwindow(desc.popup_options || {}); + target = bricks.default_popupwindow(desc.popup_options || {}, event); } else if ( desc.target instanceof bricks.JsWidget ) { target = desc.target; } else { @@ -325,22 +336,11 @@ var _buildWidget = async function(from_widget, target, mode, options, desc){ bricks.debug('options=', options, 'widgetBuild() failed'); return; } - - if (w.parent) { - if (target instanceof bricks.Popup || target instanceof bricks.PopupWindow){ - target.destroy(); - } + if (w instanceof bricks.Popup) { return; } - if (target instanceof bricks.Popup || target instanceof bricks.PopupWindow) { - if (! target.parent){ - bricks.app.add_widget(target); - } - if (desc.popup_options){ - if (desc.popup_options.eventpos){ - target.bind('opened', bricks.relocate_by_eventpos.bind(null, desc.event, target)); - } - } + if (w instanceof bricks.NewWindow) { + return; } if (mode == 'replace'){ target.clear_widgets(); @@ -569,14 +569,15 @@ bricks.App = class extends bricks.Layout { this.lang = this.opts.language; } else { - this.lang = navigator.language; + this.lang = navigator.language.substring(0,2); } this.lang_x = this.observable('lang', this.lang); this.zindex = 10000; this.textList = []; this.i18n = new bricks.I18n(objget(opts, 'i18n', {})); this.session_id = null; - this.tooltip = new bricks.Tooltip({otext:'test',i18n:true, wrap:true}); + this.tooltip = new bricks.Tooltip({otext:'',i18n:true, wrap:true}); + this.tooltip.hide(); this.add_widget(this.tooltip); this._Width = this.dom_element.offsetWidth; this._Height = this.dom_element.offsetHeight; @@ -598,7 +599,10 @@ bricks.App = class extends bricks.Layout { console.log('event=', event); event.preventDefault(); event.stopPropagation() - this.wins_panel = new bricks.WindowsPanel({}) + var opts = bricks.get_popup_default_options(); + opts.auto_open = false; + this.wins_panel = new bricks.WindowsPanel(opts); + this.wins_panel.open(); } get_color(){ return getComputedStyle(this.dom_element).color; @@ -716,7 +720,7 @@ bricks.App = class extends bricks.Layout { return w; } async run(){ - await (this.change_language(this)); + await (this.change_language(this.lang)); var w = await this.build(); this.root = w; if (!w){ diff --git a/bricks/build.sh b/bricks/build.sh index c14d71f..d29f95a 100755 --- a/bricks/build.sh +++ b/bricks/build.sh @@ -11,7 +11,7 @@ SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.js \ llm.js websocket.js datarow.js tabular.js continueaudio.js \ line.js pie.js bar.js gobang.js period.js iconbarpage.js \ keypress.js asr.js webspeech.js countdown.js progressbar.js \ - qaframe.js svg.js videoplayer.js " + qaframe.js svg.js videoplayer.js sctter.js radar.js kline.js heatmap.js map.js" echo ${SOURCES} cat ${SOURCES} > ../dist/bricks.js # uglifyjs --compress --mangle -- ../dist/bricks.js > ../dist/bricks.min.js diff --git a/bricks/css/bricks.css b/bricks/css/bricks.css index 2eb4c43..1813dc4 100755 --- a/bricks/css/bricks.css +++ b/bricks/css/bricks.css @@ -605,3 +605,9 @@ hr { color: #00aaff; background: #f0faff; } + +.mini-window { + width: 50px; + height: 50px; +} + diff --git a/bricks/echartsext.js b/bricks/echartsext.js index 65f896b..77ac65f 100644 --- a/bricks/echartsext.js +++ b/bricks/echartsext.js @@ -22,6 +22,10 @@ bricks.EchartsExt = class extends bricks.VBox { if(!this.idField) this.idField = 'id'; if(!this.nameField) this.nameField = 'name'; if(!this.valueFields) this.valueFields = ['value']; + // === 新增:处理 refresh_period === + this.refresh_period = opts.refresh_period; // 单位:秒 + this._refresh_timer = null; + this.build_title_widget(); this.build_description_widget(); this.holder = new bricks.Filler({}); @@ -33,7 +37,49 @@ bricks.EchartsExt = class extends bricks.VBox { schedule_once(this.render_urldata.bind(this), 0.1); } this.bind('element_resize', this.chart.resize.bind(this.chart)); + // === 启动定时刷新(如果配置了 refresh_period)=== + if (this.refresh_period && this.data_url) { + this.start_auto_refresh(); + } } + // === 启动自动刷新任务 === + start_auto_refresh() { + if (this._refresh_timer) return; // 防止重复启动 + + const doRefresh = () => { + this.render_urldata().then(() => { + // 继续下一轮 + if (this._refresh_timer) { // 检查是否已被取消 + this._refresh_timer = setTimeout(doRefresh, this.refresh_period * 1000); + } + }).catch(err => { + console.error('Auto-refresh failed:', err); + this._refresh_timer = setTimeout(doRefresh, this.refresh_period * 1000); // 失败也重试 + }); + }; + + // 初始延迟后开始第一轮,之后循环 + this._refresh_timer = setTimeout(doRefresh, this.refresh_period * 1000); + } + + // === 停止自动刷新 === + stop_auto_refresh() { + if (this._refresh_timer) { + clearTimeout(this._refresh_timer); + this._refresh_timer = null; + } + } + + // === 覆盖 destroy 方法,清理定时器 === + destroy() { + this.stop_auto_refresh(); // 清理资源 + if (this.chart) { + this.chart.dispose(); + this.chart = null; + } + super.destroy(); + } + pivotify(data){ var series = []; data.forEach(x => { @@ -83,7 +129,6 @@ bricks.EchartsExt = class extends bricks.VBox { this.valueFields = this.get_series(data); data = this.pivotify(data); } - this.chart = echarts.init(this.holder.dom_element); var opts = this.setup_options(data); opts.grid = { left: '3%', diff --git a/bricks/form.js b/bricks/form.js index f97eb79..ece78bc 100644 --- a/bricks/form.js +++ b/bricks/form.js @@ -22,6 +22,11 @@ bricks.FieldGroup = class { this.build_fields(form, dc, fields[i].fields); parent.add_widget(dc); dc = new bricks.DynamicColumn({mobile_cols:2}); + dc.set_id(fields[i].name+'_box'); + if (fields[i].nonuse){ + dc.disabled(true); + dc.hide(); + } } else { var box; if (! form.opts.input_layout || form.opts.input_layout == 'VBox'){ @@ -42,6 +47,11 @@ bricks.FieldGroup = class { height:'auto', i18n:true}); box.add_widget(txt); + box.set_id(fields[i].name + '_box') + if (fields[i].nonuse){ + box.disabled(true); + box.hide(); + } var w = Input.factory(fields[i]); if (w){ box.add_widget(w); @@ -72,6 +82,10 @@ bricks.FormBody = class extends bricks.VScrollPanel { }, ... ] + exclusionfields:[ + [a,b,c], # a,b,c互斥,a enabled,b,c必须disabled + [x,y] # x,y互斥 + ] } */ constructor(form, opts){ @@ -234,7 +248,33 @@ bricks.FormBase = class extends bricks.Layout { } return this.get_formdata(); } - + toggle_disable(field_name, flg){ + var w = bricks.getWidgetById(field_name + '_box', this); + if (! w) return; + w.disabled(flg); + if (flg) w.hide(); + else w.show(); + if (flg) return; + this.exclusionfields.forEach(arr =>{ + if (arr.include(field_name)){ + arr.forEach(x => { + if (x!=field_name){ + var w1 = bricks.getWidgetById(x + '_box', this); + if (w1) { + w1.disabled(true); + w1.hide(); + } + } + }); + } + }); + } + enable_field(field_name){ + this.toggle_disable(field_name, false); + } + disable_field(field_name){ + this.toggle_disable(field_name, true); + } get_formdata(){ var data = new FormData(); var changed = false; @@ -243,6 +283,7 @@ bricks.FormBase = class extends bricks.Layout { continue; } var w = this.name_inputs[name]; + if (w.parent.is_disabled()) continue; var d = w.getValue(); if (w.required && ( d[name] == '' || d[name] === null)){ new bricks.Error({title:'Requirement', message:'required field must input"' + w.label + '"'}) @@ -326,8 +367,19 @@ bricks.Form = class extends bricks.FormBase { toolbar: submit_url: method: + exclussionfields:[ + [a,b,c], + [x,y] + ] fields } + field { + name: + label: + uitype: + nonuse: # 不使用 + ... + } */ constructor(opts){ opts.height = "100%"; diff --git a/bricks/header.tmpl b/bricks/header.tmpl index 81051eb..07fecba 100644 --- a/bricks/header.tmpl +++ b/bricks/header.tmpl @@ -6,7 +6,9 @@ - +{% for mycss in cssfiles() %} + +{% endfor %} + + + + + + + + + + + + +``` + +In this example, a function named `setText` is registered using `bricks.RF.register()`. In the main widget’s `binds`, clicking the `changetext` button invokes this registered function. + +--- + +### event Method + +Binds an event to dispatch another event on a target widget. + +Supported attributes: +* `dispatch_event`: string — the name of the event to trigger +* `params`: object — parameters passed with the dispatched event (accessible via `event.params` in the handler) + +**Example** +```json +{ + "widgettype":"VBox", + "options":{}, + "subwidgets":[ + { + "id":"btn1", + "widgettype":"Button", + "options":{ + "label":"press me" + } + }, + { + "id":"txt1", + "widgettype":"Text", + "options":{ + "otext":"I will dispatch a event when btn1 pressed", + "i18n":true + } + } + ], + "binds":[ + { + "wid":"btn1", + "event":"click", + "actiontype":"event", + "target":"txt1", + "dispatch_event":"gpc" + }, + { + "wid":"txt1", + "event":"gpc", + "actiontype":"script", + "target":"self", + "script":"alert('yield');" + } + ] +} +``` + +In this example, clicking `btn1` triggers the `gpc` event on the `txt1` widget. A second binding listens for the `gpc` event on `txt1` and executes a script to display an alert. + +--- + +## Defining Event Handlers Requiring Confirmation + +Sometimes, an action should only proceed after user confirmation (e.g., deleting data). If the user cancels, the event is not processed. + +**Example** +```json +{ + "id":"insert", + "widgettype":"Button", + "options":{ + "width":"80px", + "i18n":true, + "label":"click me" + }, + "binds":[ + { + "wid":"self", + "event":"click", + "actiontype":"script", + "conform":{ + "title":"conformtest", + "message":"Test user confirmation before event handling. Confirm code?" + }, + "target":"self", + "script":"alert('Confirmed eye contact!')" + } + ] +} +``` + +This example defines a `click` event on a Button handled by a script, but only after showing a confirmation dialog. If the user cancels, the script does not run; if confirmed, it proceeds normally. \ No newline at end of file diff --git a/docs/en/factory.md b/docs/en/factory.md new file mode 100644 index 0000000..10b63cd --- /dev/null +++ b/docs/en/factory.md @@ -0,0 +1,22 @@ +# Factory_ + +## Control Functionality +`Factory_` is a factory class used for registering and retrieving controls (or components), providing a globally unique mechanism for control registration and management. Through this class, custom controls can be dynamically registered, and their corresponding constructor functions or classes can be obtained by name when needed. + +- **Type**: Ordinary control (utility class / manager) +- **Parent Control**: None (native JavaScript class) + +## Initialization Parameters +- The constructor does not accept explicit external parameters. +- During internal initialization, a `widgets_kv` object is created to store the registered control mapping table: + - Initialized with a reserved key `_t_` whose value is `1`, possibly used for version identification or existence checking. + +## Main Events +- This control does not trigger any UI events. +- Provides the following methods as core behavioral interfaces: + - `register(name: string, widget: function/class)` + Binds and registers the specified name `name` with the control class/function `widget`. + - `get(name: string): function/class | null` + Retrieves the registered control by name; returns `null` if not found. + +> Note: This control is typically used as underlying infrastructure within the `bricks` framework, serving as a unified manager for the lifecycle and access points of all visual controls or business components. \ No newline at end of file diff --git a/docs/en/floaticonbar.md b/docs/en/floaticonbar.md new file mode 100644 index 0000000..7a5cfc5 --- /dev/null +++ b/docs/en/floaticonbar.md @@ -0,0 +1,117 @@ +# IconBar + +**Widget Functionality**: Creates an icon toolbar containing multiple clickable SVG icon buttons, supporting selection states and event dispatching. +**Type**: Container widget +**Parent Widget**: `bricks.HBox` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `opts.cheight` | Number | Height of child widgets (in character units), default is `2` | +| `opts.rate` | Number | Scaling factor affecting icon size, default is `1` | +| `opts.margin` | String | Left and right margins between icons, in CSS format (e.g., `'10px'`) | +| `opts.tools` | Array | Array of tool items, each being an object with the following fields:
- `name`: Tool name (used for identification and events)
- `icon`: URL of the SVG icon
- `rate`: Optional scaling ratio for this specific icon
- `dynsize`: Whether to dynamically adjust size (boolean)
- `tip`: Tooltip text (optional) | + +> If `cheight` or `rate` is not provided, default values will be automatically set. + +## Main Events + +| Event Name | Trigger Condition | Payload Data | +|-----------|-------------------|--------------| +| `desc.name` (i.e., `tools[i].name`) | Triggered when a specific icon is clicked; event name equals the `name` field of that icon | Passes the corresponding icon's `desc` object | +| `command` | Triggered on any icon click — a unified event for all icons | Passes the `desc` object of the clicked icon | + +> Events are dispatched via `dispatch`, allowing external components to listen for specific commands or general actions. + +--- + +# IconTextBar + +**Widget Functionality**: Extends `IconBar`. Each tool item is displayed as a combination of "icon + text", suitable for toolbars requiring labeled descriptions. +**Type**: Container widget +**Parent Widget**: `bricks.IconBar` + +## Initialization Parameters + +Inherits all parameters from `IconBar`, with enhanced support for each item in the `tools` array: + +| Parameter | Type | Description | +|---------|------|-------------| +| `opts.tools[i].label` | String | Text label displayed next to the icon | +| `opts.tools[i].tip` | String | Tooltip shown on hover, applied to the entire icon+text container | +| Other parameters same as `IconBar` | —— | Supports `name`, `icon`, `rate`, `dynsize`, etc. | + +> Each tool item is constructed as a horizontal layout (`HBox`), internally composed of `Svg` and `Text` widgets in sequence. + +## Main Events + +Identical to `IconBar`: + +| Event Name | Trigger Condition | Payload Data | +|-----------|-------------------|--------------| +| `desc.name` | Triggered when a tool item is clicked; event name is its `name` | The corresponding `desc` object | +| `command` | Triggered on every icon click | `desc` object of the current item | + +> Events are bound to the overall `HBox`; clicking either the icon or the text triggers the event. + +--- + +# FloatIconBar + +**Widget Functionality**: A floating icon toolbar that initially displays only a "floating icon". On mouse hover, it expands into a full `IconBar`. Commonly used for side-floating toolbars. +**Type**: Container widget +**Parent Widget**: `bricks.HBox` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `opts` | Object | Configuration object passed to the internal `IconBar`, structured like `IconBar`'s `opts.tools` and related options | +| Uses `bricks_resource('imgs/float-out.png')` internally | —— | Fixed icon for the floating button | + +> Actual tool items are defined through the provided `opts`, which are used to construct the internal `IconBar`. + +## Main Events + +Same as the internal `IconBar`: + +| Event Name | Trigger Condition | Payload Data | +|-----------|-------------------|--------------| +| `desc.name` | Triggered when a user clicks an icon in the expanded toolbar | `desc` object of the corresponding icon | +| `command` | Triggered on any icon click in the expanded bar | `desc` object of the clicked icon | + +> Events originate from the embedded `IconBar` instance and are automatically forwarded (transparently passed up). + +Additional behavioral events: +- `mousemove` over the floating icon triggers expansion of the menu +- A `click` anywhere on the page triggers collapse of the menu (via listening on `bricks.Body`) + +--- + +# FloatIconTextBar + +**Widget Functionality**: Floating "icon + text" toolbar, an extended version of `FloatIconBar`. When expanded, it displays tool items with textual labels. +**Type**: Container widget +**Parent Widget**: `bricks.FloatIconBar` + +## Initialization Parameters + +Same as `FloatIconBar`: + +| Parameter | Type | Description | +|---------|------|-------------| +| `opts` | Object | Contains the `tools` array and other configurations, used internally when constructing the `IconTextBar` | + +> Internally calls `build_bar(opts)` to create an `IconTextBar` instance, thus supporting text-related properties such as `label` and `tip`. + +## Main Events + +Same as `IconTextBar`: + +| Event Name | Trigger Condition | Payload Data | +|-----------|-------------------|--------------| +| `desc.name` | Triggered when a tool item in the expanded bar is clicked | `desc` object of the selected item | +| `command` | Triggered on any click within the expanded bar | `desc` object of the current item | + +> All events are emitted by the internal `IconTextBar` instance and automatically bubble up. \ No newline at end of file diff --git a/docs/en/form.md b/docs/en/form.md new file mode 100644 index 0000000..2b92d57 --- /dev/null +++ b/docs/en/form.md @@ -0,0 +1,114 @@ +# InlineForm + +**Control Function**: Embeds a submittable form inline, supporting field input, validation, and toolbar operations (submit, reset, cancel). Suitable for lightweight form embedding scenarios. +**Type**: Ordinary control +**Parent Control**: `bricks.FormBase` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `fields` | Array | Array of form field configurations; each field object includes information such as name, label, and uitype. | +| `height` | String | Optional, default is `"100%"`, sets the height of the control. | +| `width` | String | Optional, default is `"100%"`, sets the width of the control. | +| `overflow` | String | Optional, default is `"auto"`, controls how overflow content is displayed. | + +> Note: All options are passed into the constructor via `opts`. + +## Main Events + +| Event Name | Trigger Condition | Callback Parameters | +|-----------|-------------------|---------------------| +| `submit(data)` | Triggered when the user clicks the "Submit" button and data passes validation. | `data`: FormData object or plain object containing form data. | +| `submited(resp)` | Triggered after the submission request completes (regardless of success or failure). | `resp`: Response object; returned content can be obtained via `await resp.json()`. | +| `cancel` | Triggered when the user clicks the "Cancel" button. | No parameters. | +| `reset` | Triggered when the user clicks the "Reset" button. | No parameters. | +| Custom command event | Triggered when a custom button in the toolbar has an `action` or name defined. | `event.params` contains button information. | + +--- + +# Form + +**Control Function**: A complete form container control that supports title, description, multi-field layout, separation of text and non-text fields, automatic toolbar generation, and configurable submission URL and method. Ideal for full forms in standalone pages or popups. +**Type**: Container control +**Parent Control**: `bricks.FormBase` + +## Initialization Parameters + +| Parameter | Type | Description | +|----------|------|-------------| +| `title` | String | Optional, form title displayed as large text. | +| `description` | String | Optional, form description shown below the title. | +| `fields` | Array | Required, list of field configurations, same structure as InlineForm. | +| `submit_url` | String | Optional, target URL for form submission; if provided, automatically sends HTTP request. | +| `method` | String | Optional, HTTP method, default is `'POST'`. | +| `notoolbar` | Boolean | Optional, default `false`, whether to hide the default toolbar (submit/reset/cancel). | +| `toolbar` | Object | Optional, extends or replaces default toolbar configuration. Structure: `{ tools: [...] }`. | +| `input_layout` | String | Optional, input layout style, supports `"VBox"` (vertical) or `"HBox"` (horizontal), default `"VBox"`. | +| `dataurl` | String | (Reserved) May be used for loading initial data (currently not directly used). | + +## Main Events + +| Event Name | Trigger Condition | Callback Parameters | +|-----------|-------------------|---------------------| +| `submit(data)` | Triggered before form submission, after validation passes. Can be used to intercept or preprocess data. | `data`: Data object or FormData being submitted. | +| `submited(resp)` | Triggered after sending the request to `submit_url`. | `resp`: Response object, usable for handling response results. | +| `cancel` | Triggered when the user clicks the "Cancel" button. | No parameters. | +| `reset` | Triggered when the user clicks the "Reset" button. | No parameters. | +| Custom event | Triggered when a custom button in the toolbar is clicked and has `action` or event name defined. | `event.params` contains button metadata. | + +--- + +# FormBody + +**Control Function**: The main content area used internally by `Form`, responsible for rendering all non-text fields (via `FieldGroup`) and text fields (read-only display). Acts as the container for actual input areas. +**Type**: Container control +**Parent Control**: `bricks.VScrollPanel` + +## Initialization Parameters + +| Parameter | Type | Description | +|----------|------|-------------| +| `form` | Object | The parent form instance, used to access field definitions, name_inputs, and other states. | +| `opts` | Object | Configuration options; automatically sets `width: '100%'` and `height: '100%'`. | + +> Note: This control is typically not created directly by developers, but instantiated internally during `Form` construction. + +## Main Events + +This control does not dispatch events externally, but as a container inherits scrolling capabilities from `VScrollPanel`, primarily used for visual presentation. + +- Does not actively trigger business events. +- Changes in its child controls (e.g., input fields) affect the state of the parent `Form`. + +--- + +# FieldGroup + +**Control Function**: A helper class used to recursively build field groups within a form (supporting nested group structures), organizing fields into dynamic columns (`DynamicColumn`) and input containers (`VBox`/`HBox`) according to layout rules. +**Type**: Ordinary control (logical component) +**Parent Control**: None (base class) + +## Initialization Parameters + +| Parameter | Type | Description | +|----------|------|-------------| +| `opts` | Object | Currently unused, reserved for future extension. | + +> Note: This class is not a UI control and does not directly render DOM elements—it exists solely as a logical building block. + +## Main Events + +This class has no event mechanism and serves only synchronous method calls: + +- `build_fields(form, parent, fields)`: Core method that recursively generates field UI and mounts it to the specified parent container. + +--- + +> ✅ **Summary Notes**: +> +> - `InlineForm` and `Form` are form controls directly usable by users; +> - `FormBody` and `FieldGroup` are internal implementation components, generally not intended for direct use or separate documentation; +> - All form controls share a unified data collection, validation, and submission workflow; +> - Supports file-type fields (file/audio/video), which require `FormData` for automatic recognition; +> - Toolbar supports highly customizable extensions. \ No newline at end of file diff --git a/docs/en/gobang.md b/docs/en/gobang.md new file mode 100644 index 0000000..a0b7568 --- /dev/null +++ b/docs/en/gobang.md @@ -0,0 +1,58 @@ +# GobangPoint + +**Control Functionality:** Represents a single point on a Gomoku (Five in a Row) board. Displays as empty, black stone, or white stone based on its state, and supports mouse hover effects. +**Type:** Ordinary Control +**Parent Control:** `bricks.Image` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|--------|-------------| +| `p_status` | Number | Point status: 0 for empty, 1 for black stone, 2 for white stone | +| `p_x` | Number | Horizontal position, ranging from 1 to 15 | +| `p_y` | Number | Vertical position, ranging from 1 to 15 | +| `tip` | String (optional) | Tooltip text displayed on mouse hover | + +> **Note:** The constructor automatically calls `calc_url()` to generate the corresponding image path based on position and status, then sets the image source via `set_url()`. + +## Main Events + +- **`mouseover`** + Triggered when the mouse enters the control area. Calls `set_current_position(true)` to apply highlight styling for the current coordinate (adds the `curpos` CSS class). + +- **`mouseout`** + Triggered when the mouse leaves the control area. Calls `set_current_position(false)` to remove the highlight style. + +--- + +# Gobang + +**Control Functionality:** Implements a 15×15 Gomoku game interface container responsible for rendering the game board, managing point states, and handling player turn logic. +**Type:** Container Control +**Parent Control:** `bricks.VBox` + +## Initialization Parameters + +No explicit external parameters. Internal initialization includes: + +- Automatically creates a `Filler` placeholder control for adaptive layout +- Creates and renders a 15×15 grid of points using `GobangPoint` +- Binds window resize response to dynamically adjust each cell size, ensuring squares that fully occupy available space + +## Main Events + +- **`element_resize` (bound to `filler`)** + Triggered when the DOM element of `filler` changes size. Calls the `resize_area()` method to recalculate width and height of each cell, ensuring the board scales proportionally within the container. + +### Custom Method Descriptions + +- `render_empty_area()` + Initializes and renders an empty game board by creating a nested structure of `VBox` and `HBox` to arrange 15×15 `GobangPoint` instances, storing them in `this.area[i][j]` for future reference and manipulation. + +- `resize_area()` + Dynamically calculates the size of each cell based on the actual dimensions of the `filler` (taking the smaller dimension divided by 15), then applies uniform width and height styles to all `GobangPoint` instances. + +- `inform_go(party)` + (Currently an empty implementation) Intended to notify a specified party (e.g., `'black'` or `'white'`) to make their move; can be extended for AI integration or online multiplayer functionality. + +> **Note:** This control is registered via `bricks.Factory.register('Gobang', bricks.Gobang);`, allowing it to be used in templates as ``. \ No newline at end of file diff --git a/docs/en/html.md b/docs/en/html.md new file mode 100644 index 0000000..fe5caf5 --- /dev/null +++ b/docs/en/html.md @@ -0,0 +1,21 @@ +# Html + +Control Function: Used to insert custom HTML content into a page. +Type: Ordinary control +Parent Control: `bricks.JsWidget` + +## Initialization Parameters + +- `html` (String) + The HTML string content to be inserted into the control. This content will be set as the `innerHTML` of the control's DOM element. + +Example: +```js +new bricks.Html({ + html: '
This is red text
' +}); +``` + +## Main Events + +No specific events (inherits general events from the parent class, such as `init`, `render`, etc., but this control does not define any specific events). \ No newline at end of file diff --git a/docs/en/iconbarpage.md b/docs/en/iconbarpage.md new file mode 100644 index 0000000..2e60d6e --- /dev/null +++ b/docs/en/iconbarpage.md @@ -0,0 +1,34 @@ +# IconbarPage + +**Widget Functionality**: A page container with an icon toolbar that supports placing the icon-text toolbar (IconTextBar) either at the top or bottom. Clicking a toolbar item dynamically loads and displays the corresponding content component. +**Type**: Container widget +**Parent Widget**: `bricks.VBox` + +## Initialization Parameters + +- `opts`: Configuration object containing the following properties: + - `bar_opts` *(Object)*: Configuration options for the icon toolbar, passed to `bricks.IconTextBar`. + - `margin` *(String | Number)*: External margin of the toolbar. + - `rate` *(Number)*: Proportion this toolbar occupies in the layout. + - `tools` *(Array)*: Array of tool items, each being an object with the following structure: + - `name` *(String)*: Name of the tool, used as an identifier. + - `icon` *(String)*: Class name or path of the icon. + - `label` *(String, optional)*: Text label for the tool. + - `tip` *(String)*: Tooltip shown when hovering over the tool. + - `dynsize` *(Boolean)*: Whether to dynamically resize. + - `rate` *(Number)*: Proportion this tool occupies in the layout. + - `content` *(Object | String)*: Configuration or type name describing the child widget to be loaded, used to dynamically construct the content. + - `bar_at` *(String)*: Specifies the position of the toolbar; valid values are `'top'` or `'bottom'`, default is `'top'`. + +> **Note**: The constructor automatically sets `height: '100%'`. + +## Main Events + +- `command` event: + - **Source**: Triggered by the internal `IconTextBar` instance. + - **Callback parameter**: `event.params` contains the clicked `tool` object. + - **Behavior**: When a user clicks on a tool icon, the `command_handle` method is invoked, which dynamically creates a content component based on `tool.content` and replaces the current content area. + +```javascript +bar.bind('command', this.command_handle.bind(this)) +``` \ No newline at end of file diff --git a/docs/en/iframe.md b/docs/en/iframe.md new file mode 100644 index 0000000..ef838e4 --- /dev/null +++ b/docs/en/iframe.md @@ -0,0 +1,33 @@ +# NewWindow + +## Widget Functionality, Type (Regular or Container Widget), and Parent Widget +- **Widget Functionality**: Opens a new browser window and loads the specified URL. +- **Widget Type**: Regular widget +- **Parent Widget**: `bricks.JsWidget` + +## Initialization Parameters +| Parameter | Type | Required | Description | +|-----------|--------|----------|-------------| +| `url` | string | Yes | The URL of the page to open in the new window. | +| `name` | string | No | The name of the new window (i.e., the second parameter of `window.open`). Defaults to `'_blank'`, which opens a new tab. | + +## Key Events +No key events. This widget immediately executes `window.open()` upon initialization and does not provide any listenable events. + +--- + +# Iframe + +## Widget Functionality, Type (Regular or Container Widget), and Parent Widget +- **Widget Functionality**: Creates an embedded iframe to include another web page within the current page. Supports setting height and automatically loading the specified URL. +- **Widget Type**: Regular widget +- **Parent Widget**: `bricks.Layout` + +## Initialization Parameters +| Parameter | Type | Required | Description | +|-----------|---------------|----------|-------------| +| `url` | string | Yes | The URL of the page to embed in the iframe. | +| `height` | string or number | No | The height of the iframe. Defaults to `'100%'`. | + +## Key Events +No key events. This widget directly sets the `src` attribute in the constructor to load the page and does not define any custom events. \ No newline at end of file diff --git a/docs/en/image.md b/docs/en/image.md new file mode 100644 index 0000000..72b244d --- /dev/null +++ b/docs/en/image.md @@ -0,0 +1,109 @@ +# Image + +## Widget Functionality, Type (Basic or Container Widget), and Parent Widget +A widget used to display images. Supports setting an image URL, a default fallback image for error cases, and exporting the current image content as a Base64 string. +**Type:** Basic Widget +**Parent Widget:** `bricks.JsWidget` + +### Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `url` | String | The image URL; automatically assigned to the `` element's `src` attribute during construction | +| `default_url` | String | Fallback image URL displayed when the original image fails to load | +| `height` | Number (Optional) | Sets the image height (can also be handled by CSS or DOM) | +| `width` | Number (Optional) | Sets the image width (can also be handled by CSS or DOM) | + +> Note: All parameters are passed into the constructor via the `opts` object. + +### Main Events + +No explicit events defined. However, the native `` element's `onerror` event is internally used to handle image loading failures: + +- **`onerror` → Triggers `set_default_url()`** + When image loading fails, automatically switches to the fallback image specified by `default_url`, and removes the error listener to prevent recursive triggering. + +--- + +# Icon + +## Widget Functionality, Type (Basic or Container Widget), and Parent Widget +An icon widget extended from `Image`, supporting size scaling based on character units (`charsize`), dynamic resizing, and layout adaptation. Commonly used for small icons aligned with text in UIs. +**Type:** Basic Widget +**Parent Widget:** `bricks.Image` + +### Initialization Parameters + +| Parameter | Type | Description | +|----------|------|-------------| +| `url` | String | Icon image URL, inherited from `Image` | +| `rate` | Number | Scaling factor, default is `1`; actual size = `charsize * rate` | +| `cwidth` | Number | Occupied character width, default is `1` | +| `cheight` | Number | Occupied character height, default is `1` | +| `dynsize` | Boolean | Whether dynamic sizing is enabled, default is `true`; adjusts size according to `charsize_sizing()` | + +> Note: `charsize` comes from `bricks.app.charsize`, which is a font-based base unit at the application level. + +### Main Events + +No independent events defined. Behavior is primarily triggered through `options_parse()` during initialization or after property changes. + +- **`options_parse()`** + Called during widget initialization to parse and apply size-related options, including setting the URL and adjusting dimensions. + +--- + +# StatedIcon + +## Widget Functionality, Type (Basic or Container Widget), and Parent Widget +A stateful icon widget that switches between different images based on its current state. Suitable for scenarios such as toggle states or multi-state indicators. +**Type:** Basic Widget +**Parent Widget:** `bricks.Icon` (indirectly inherits from `Image`) + +### Initialization Parameters + +| Parameter | Type | Description | +|----------|------|-------------| +| `states` | Array<{state: String, url: String}> | Array of states, each containing a state name and corresponding image URL | +| `state` | String | Initial state name; if not specified, defaults to `states[0].state` | +| `rate`, `cwidth`, `cheight`, `dynsize` | Same as above | Layout and styling parameters inherited from `Icon` | + +> Example: +> ```js +> { +> states: [ +> { state: 'normal', url: 'icon-normal.png' }, +> { state: 'active', url: 'icon-active.png' } +> ], +> state: 'normal' +> } +> ``` + +### Main Events + +- **`set_state(state)`** + Method: Manually sets the current state. The widget searches for the matching state entry and updates the image URL, then re-parses options and re-renders. + - Parameter: `state` — the target state string + - Behavior: Iterates through `this.states`, finds the matching item, and calls `super.options_parse()` to update the view. + +--- + +# BlankIcon + +## Widget Functionality, Type (Basic or Container Widget), and Parent Widget +A blank placeholder icon widget that displays no image, serving only as a transparent spacer with fixed character dimensions. Used for layout alignment or reserving space before dynamic replacement. +**Type:** Basic Widget +**Parent Widget:** `bricks.JsWidget` + +### Initialization Parameters + +| Parameter | Type | Description | +|----------|------|-------------| +| `rate` | Number | Size scaling factor, default is `1`, affects calculation based on `charsize` | +| `cwidth` | Number | Occupied character width, default is `1` | +| `cheight` | Number | Occupied character height, default is `1` | +| `dynsize` | Boolean | Whether dynamic sizing is enabled, default is `true`; controls responsiveness to `charsize_sizing()` | + +### Main Events + +No public events or callbacks. Its core purpose is to maintain consistent sizing behavior with other icons in the UI layout, without loading any image resources. \ No newline at end of file diff --git a/docs/en/input.md b/docs/en/input.md new file mode 100644 index 0000000..38e29e5 --- /dev/null +++ b/docs/en/input.md @@ -0,0 +1,371 @@ +# UiType + +**Functionality**: Base class for all input controls, providing common methods for value getting, setting, resetting, and disabling. +**Type**: Regular control +**Parent Control**: `bricks.Layout` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `name` | string | Control name (required) | +| `value` / `defaultvalue` | any | Default value | +| `required` | boolean | Whether the field is required; default is `false` | + +## Main Events + +- `changed`: Triggered when the control's value changes, carrying key-value data of the current control. +- `blur`: May be dispatched when the control loses focus (implemented by subclasses). + +--- + +# UiHide + +**Functionality**: Hidden field control used to store non-visible data; rendered in DOM as `display: none`. +**Type**: Regular control +**Parent Control**: `UiType` + +## Initialization Parameters + +Inherits from `UiType`, no additional parameters. + +## Main Events + +- `changed`: Triggered when the value changes. + +--- + +# UiStr + +**Functionality**: Single-line text input field supporting alignment, length limits, placeholder, etc. +**Type**: Regular control +**Parent Control**: `UiType` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `align` | string | Text alignment: `left`, `center`, `right` | +| `length` | number | Maximum character count (`maxlength`) | +| `minlength` | number | Minimum character count (`minlength`) | +| `tip` | string | Tooltip message (currently unused) | +| `width` | string | Input width (e.g., `'200px'`) | +| `readonly` | string/boolean | Whether the field is read-only | +| `required` | boolean | Whether it is a required field | +| `placeholder` | string | Placeholder text (supports internationalization) | +| `css` | string | Custom CSS class name | +| `dynsize` | boolean | Whether to dynamically adjust font size; default `true` | +| `cfontsize` | number | Font scaling ratio | + +## Main Events + +- `focus`: Triggered when gaining focus. +- `blur`: Triggered when losing focus. +- `changed`: Triggered when input content changes and passes regex validation. +- `keydown`: Pressing Enter triggers the `blur` event. + +--- + +# UiPassword + +**Functionality**: Password input field, inherits from `UiStr`, with masked input display. +**Type**: Regular control +**Parent Control**: `UiStr` + +## Initialization Parameters + +Same as `UiStr`. + +## Main Events + +Same as `UiStr`. + +--- + +# UiInt + +**Functionality**: Integer input field that automatically restricts input to digits only, right-aligned display. +**Type**: Regular control +**Parent Control**: `UiStr` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `length` | number | Maximum number of digits allowed (optional) | + +## Main Events + +- `changed`: Triggered when a valid integer is entered. +- Value is always returned as an integer (via `parseInt`). + +--- + +# UiFloat + +**Functionality**: Floating-point number input field, supports decimal precision control and step settings. +**Type**: Regular control +**Parent Control**: `UiInt` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `dec_len` | number | Number of decimal places to retain after the decimal point; default is 2 | + +## Main Events + +- `changed`: Triggered when a valid floating-point number is entered. +- Return value is `parseFloat(this.value)`. + +--- + +# UiTel + +**Functionality**: Phone number input field using ``, supports custom pattern validation. +**Type**: Regular control +**Parent Control**: `UiStr` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `pattern` | string | Regular expression string for validating input format | + +## Main Events + +- `changed`: Triggered when input matches the specified pattern. + +--- + +# UiEmail + +**Functionality**: Email input field using ``, supports optional custom pattern validation. +**Type**: Regular control +**Parent Control**: `UiStr` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `pattern` | string | Optional custom regex validation rule | + +## Main Events + +- `changed`: Triggered when input is in valid email format. + +--- + +# UiFile + +**Functionality**: File upload control supporting drag-and-drop upload, click-to-select, file type restrictions, and multiple file selection. +**Type**: Container control +**Parent Control**: `VBox` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `accept` | string | MIME type prefix accepted, e.g., `'image/'`, `'audio/'` | +| `multiple` | boolean | Whether multiple files are allowed | +| `width` | string | Container width; default `'100%'` | + +## Main Events + +- `dragenter` / `dragover` / `dragleave` / `drop`: Drag-and-drop related events for highlighting and receiving files. +- `changed`: Triggered after selecting or dropping files, passing file object(s). +- `input`: Native input change event listener. + +--- + +# UiImage + +**Functionality**: Image upload control supporting drag-and-drop, click-to-upload, camera button, and image preview after upload. +**Type**: Container control +**Parent Control**: `UiFile` + +## Initialization Parameters + +Same as `UiFile`, with default `accept='image/'`. + +## Main Events + +- `changed`: Triggered after file selection or taking a photo, includes File object. +- `shot`: Photo capture complete event dispatched by `SysCamera` and captured here. + +--- + +# UiAudio + +**Functionality**: Audio upload control supporting microphone recording, with playback preview after upload. +**Type**: Container control +**Parent Control**: `UiFile` + +## Initialization Parameters + +Same as `UiFile`, with default `accept='audio/'`. + +## Main Events + +- `changed`: Triggered after file selection or recording completes. +- `record_end`: Event dispatched by `SysAudioRecorder` upon completion of recording. + +--- + +# UiVideo + +**Functionality**: Video upload control supporting camera-based video recording, with playback preview after upload. +**Type**: Container control +**Parent Control**: `UiFile` + +## Initialization Parameters + +Same as `UiFile`, with default `accept='video/'`. + +## Main Events + +- `changed`: Triggered after file selection or recording completes. +- `record_end`: Event dispatched by `SysVideoRecorder` upon completion of video recording. + +--- + +# UiCheck + +**Functionality**: Checkbox control (visually implemented as icon toggle), representing boolean state (`true`/`false`). +**Type**: Regular control +**Parent Control**: `UiType` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `value` | boolean | Initial checked state | + +## Main Events + +- `changed`: Triggered when state toggles, carries `{name: true/false}` data. +- `state_changed`: Icon state change event (from `MultipleStateIcon`). + +--- + +# UiCheckBox + +**Functionality**: Multi-select or single-select group control that generates multiple `UiCheck` + text labels based on data. Supports static data or remote loading. +**Type**: Container control +**Parent Control**: `UiType` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `label` | string | Group title | +| `data` | array | Static option list `[ {text:'', value:''} ]` | +| `dataurl` | string | Remote data URL | +| `method` | string | Request method; default is GET | +| `params` | object | Request parameters | +| `textField` | string | Field name for display; default `'text'` | +| `valueField` | string | Field name for value; default `'value'` | +| `value` / `defaultValue` | string/array | Default selected value (string for single-select, array for multi-select) | + +> Note: If the `multicheck` property exists and is truthy, the control operates in multi-select mode. + +## Main Events + +- `changed`: Triggered when any option's state changes, carries `{name: selectedValue(s)}`. +- Internally binds to `UiCheck`'s `changed` event to update values. + +--- + +# UiDate + +**Functionality**: Date picker using native ``, supports minimum and maximum date constraints. +**Type**: Regular control +**Parent Control**: `UiStr` + +## Initialization Parameters + +| Parameter | Type | Description | +|---------|------|-------------| +| `max_date` | string | Maximum allowed date (format YYYY-MM-DD) | +| `min_date` | string | Minimum allowed date (format YYYY-MM-DD) | + +## Main Events + +- `changed`: Triggered when the date is changed. +- `blur` / `focus`: Focus events supported via parent class. + +--- + +# UiText + +**Functionality**: Multi-line text area (`