Merge branch 'main' of git.kaiyuancloud.cn:yumoqing/bricks
2
3parties/xterm-addon-fit.js
Normal file
@ -0,0 +1,2 @@
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(window,function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=function(){function e(){}return e.prototype.activate=function(e){this._terminal=e},e.prototype.dispose=function(){},e.prototype.fit=function(){var e=this.proposeDimensions();if(e&&this._terminal){var t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}},e.prototype.proposeDimensions=function(){if(this._terminal&&this._terminal.element&&this._terminal.element.parentElement){var e=this._terminal._core,t=window.getComputedStyle(this._terminal.element.parentElement),r=parseInt(t.getPropertyValue("height")),n=Math.max(0,parseInt(t.getPropertyValue("width"))),o=window.getComputedStyle(this._terminal.element),i=r-(parseInt(o.getPropertyValue("padding-top"))+parseInt(o.getPropertyValue("padding-bottom"))),a=n-(parseInt(o.getPropertyValue("padding-right"))+parseInt(o.getPropertyValue("padding-left")))-e.viewport.scrollBarWidth;return{cols:Math.max(2,Math.floor(a/e._renderService.dimensions.actualCellWidth)),rows:Math.max(1,Math.floor(i/e._renderService.dimensions.actualCellHeight))}}},e}();t.FitAddon=n}])});
|
||||
//# sourceMappingURL=xterm-addon-fit.js.map
|
75
bricks/asr.js
Normal file
@ -0,0 +1,75 @@
|
||||
var bricks = window.bricks || {};
|
||||
bricks.ASRClient = class extends bricks.VBox {
|
||||
/*
|
||||
options:
|
||||
{
|
||||
start_icon:record.png,
|
||||
stop_icon:stop.png
|
||||
ws_url:
|
||||
icon_options
|
||||
ws_params:
|
||||
}
|
||||
event:
|
||||
start: start recording, no params
|
||||
stop: stop recording, no params
|
||||
transtext: recognised text, params={
|
||||
"content":
|
||||
"speaker":
|
||||
"start":
|
||||
"end":
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
var icon_options = this.icon_options || {};
|
||||
icon_options.url = this.start_icon || bricks_resource('imgs/start_recording.png');
|
||||
this.icon = new bricks.Icon(icon_options);
|
||||
this.status = 'stop';
|
||||
this.icon.bind('click', this.toggle_button.bind(this));
|
||||
this.add_widget(this.icon);
|
||||
this.socket = new WebSocket(this.ws_url);
|
||||
this.socket.onmessage = this.response_data.bind(this);
|
||||
this.bind('transtext', this.response_log.bind(this));
|
||||
}
|
||||
response_log(event){
|
||||
console.log('response data=', event.params);
|
||||
}
|
||||
toggle_button(){
|
||||
if (this.status == 'stop'){
|
||||
this.icon.set_url(this.start_icon||bricks_resource('imgs/stop_recording.png'));
|
||||
this.status = 'start';
|
||||
this.start_recording();
|
||||
} else {
|
||||
this.icon.set_url(this.stop_icon||bricks_resource('imgs/start_recording.png'));
|
||||
this.status = 'stop';
|
||||
this.stop_recording();
|
||||
}
|
||||
}
|
||||
async start_recording() {
|
||||
this.stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||
this.mediaRecorder = new MediaRecorder(this.stream);
|
||||
this.mediaRecorder.ondataavailable = (event) => {
|
||||
if (event.data.size > 0) {
|
||||
// 将音频数据通过 WebSocket 发送到服务器
|
||||
blobToBase64(event.data).then((b64str) => {
|
||||
var d = objcopy(this.ws_params);
|
||||
d.type = 'audiobuffer';
|
||||
d.data = b64str;
|
||||
this.socket.send(JSON.stringify(d));
|
||||
}).catch((error) => {
|
||||
console.log('Error', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
this.mediaRecorder.start(1000); // 每 1 秒发送一次数据
|
||||
}
|
||||
stop_recording(){
|
||||
this.mediaRecorder.stop();
|
||||
}
|
||||
response_data(event){
|
||||
var d = JSON.parse(event.data);
|
||||
this.dispatch('transtext', d);
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('ASRClient', bricks.ASRClient);
|
71
bricks/audio.js
Executable file → Normal file
@ -26,7 +26,7 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
||||
this.audio = this._create('audio');
|
||||
this.audio.controls = true;
|
||||
if (this.opts.autoplay){
|
||||
this.audio.addEventListener('canplay', this.play_audio.bind(this));
|
||||
this.audio.addEventListener('canplay', this.play.bind(this));
|
||||
}
|
||||
this.audio.style.width = "100%"
|
||||
this.dom_element.appendChild(this.audio);
|
||||
@ -34,6 +34,58 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
||||
this.set_source(this.url);
|
||||
}
|
||||
}
|
||||
|
||||
set_stream_urls(response){
|
||||
async function* dyn_urls(response) {
|
||||
const reader = response.body.getReader();
|
||||
var value;
|
||||
var done;
|
||||
while (true){
|
||||
done, value = await reader.read();
|
||||
if (value.done){
|
||||
console.log('done=', done, 'value=', value);
|
||||
break;
|
||||
}
|
||||
let result = '';
|
||||
for (let i = 0; i < value.value.length; i++) {
|
||||
result += String.fromCharCode(value.value[i]);
|
||||
}
|
||||
console.log('audio set url=', result);
|
||||
yield result;
|
||||
}
|
||||
}
|
||||
this.url_generator = dyn_urls(response);
|
||||
this.srcList = [];
|
||||
schedule_once(this.load_queue_url.bind(this), 0.1);
|
||||
}
|
||||
async load_queue_url(){
|
||||
while (true){
|
||||
var d = await this.url_generator.next();
|
||||
if (d.done){
|
||||
return;
|
||||
}
|
||||
this.srcList.push({played:false, url:d.value});
|
||||
if (this.srcList.length < 2 ){
|
||||
await this.play_srclist();
|
||||
this.audio.addEventListener('ended',
|
||||
this.play_srclist.bind(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
async play_srclist(evnet){
|
||||
if (event && ! this.audio.ended){
|
||||
return;
|
||||
}
|
||||
for (var i=0;i<this.srcList.length;i++){
|
||||
if (!this.srcList[i].played){
|
||||
console.log('playit', i, this.srcList[i]);
|
||||
this.set_url(this.srcList[i].url);
|
||||
this.srcList[i].played = true;
|
||||
await this.play();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
set_source(url){
|
||||
if (! this.source){
|
||||
this.source = this._create('source');
|
||||
@ -49,14 +101,14 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
||||
// 播放音频
|
||||
this.audio.play();
|
||||
}
|
||||
play(){
|
||||
this.audio.play();
|
||||
async play(){
|
||||
await this.audio.play();
|
||||
}
|
||||
toggle_play(){
|
||||
async toggle_play(){
|
||||
if (this.audio.paused){
|
||||
this.audio.play();
|
||||
await this.audio.play();
|
||||
} else {
|
||||
this.audio.pause();
|
||||
await this.audio.pause();
|
||||
}
|
||||
}
|
||||
set_url(url){
|
||||
@ -81,6 +133,7 @@ bricks.AudioRecorder = class extends bricks.HBox {
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.set_css('clickable');
|
||||
this.start_icon = opts.start_icon || bricks_resource('imgs/start_recording.png');
|
||||
this.stop_icon = opts.stop_icon || bricks_resource('imgs/stop_recording.png');
|
||||
this.rec_btn = new bricks.Icon({
|
||||
@ -97,7 +150,7 @@ bricks.AudioRecorder = class extends bricks.HBox {
|
||||
width:'120px'
|
||||
});
|
||||
this.upload_url = opts.upload_url;
|
||||
this.rec_btn.bind('click', this.rec_btn_pressed.bind(this))
|
||||
this.bind('click', this.rec_btn_pressed.bind(this))
|
||||
this.URL = window.URL||webkitURL;
|
||||
this.rec = null;
|
||||
this.wave = null;
|
||||
@ -105,7 +158,9 @@ bricks.AudioRecorder = class extends bricks.HBox {
|
||||
this.add_widget(this.rec_btn);
|
||||
this.add_widget(this.rec_time);
|
||||
this.recordData = null;
|
||||
this.bind('record_ended', this.upload.bind(this));
|
||||
if (this.upload_url){
|
||||
this.bind('record_ended', this.upload.bind(this));
|
||||
}
|
||||
}
|
||||
rec_btn_pressed(){
|
||||
bricks.debug(this.rec_btn.url, ':url:', this.start_icon, this.stop_icon);
|
||||
|
@ -7,10 +7,8 @@ bricks.ChartBar = class extends bricks.EchartsExt {
|
||||
data_params,
|
||||
method,
|
||||
data,
|
||||
line_options,
|
||||
nameField,
|
||||
valueField
|
||||
serieField:
|
||||
valueFields
|
||||
}
|
||||
*/
|
||||
values_from_data(data, name){
|
||||
|
0
bricks/baseKnowledge.txt
Executable file → Normal file
@ -32,3 +32,25 @@ bricks.UpStreaming = class extends bricks.JsWidget {
|
||||
this.stream_ctlr = controller;
|
||||
}
|
||||
}
|
||||
|
||||
bricks.down_streaming = async function*(response) {
|
||||
if (! response){
|
||||
return;
|
||||
}
|
||||
const reader = response.body.getReader();
|
||||
var value;
|
||||
var t = 0;
|
||||
while (true){
|
||||
done, value = await reader.read();
|
||||
if (value.done){
|
||||
break;
|
||||
}
|
||||
let result = '';
|
||||
for (let i = 0; i < value.value.length; i++) {
|
||||
result += String.fromCharCode(value.value[i]);
|
||||
}
|
||||
console.log('audio set url=', result);
|
||||
yield result;
|
||||
}
|
||||
}
|
||||
|
||||
|
230
bricks/bricks.js
Executable file → Normal file
@ -48,9 +48,20 @@ params:
|
||||
*/
|
||||
|
||||
bricks.uuid = function(){
|
||||
var d = crypto.randomUUID();
|
||||
var lst = d.split('-');
|
||||
return lst.join('');
|
||||
try{
|
||||
var d = crypto.randomUUID();
|
||||
var lst = d.split('-');
|
||||
return lst.join('');
|
||||
} catch(e) {
|
||||
const vv = '1234567890qwertyuiopasdfghjklzxcvbnm';
|
||||
var ret = '';
|
||||
for (var i=0;i<30;i++){
|
||||
var j = parseInt(Math.random() * vv.length);
|
||||
ret = ret + vv[j];
|
||||
}
|
||||
console.log('uuid() return', ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bricks.deviceid = function(appname){
|
||||
@ -124,26 +135,40 @@ bricks.widgetBuild = async function(desc, widget, data){
|
||||
var klassname = desc.widgettype;
|
||||
var base_url = widget.baseURI;
|
||||
while (klassname == 'urlwidget'){
|
||||
if (data){
|
||||
desc = bricks.apply_data(desc, data);
|
||||
}
|
||||
let url = bricks.absurl(desc.options.url, widget);
|
||||
base_url = url;
|
||||
let method = desc.options.method || 'GET';
|
||||
let opts = desc.options.params || {};
|
||||
var jc = new bricks.HttpJson();
|
||||
var desc1 = await jc.httpcall(url, { "method":method, "params":opts});
|
||||
if (!desc1) return;
|
||||
desc = desc1;
|
||||
klassname = desc.widgettype;
|
||||
}
|
||||
if (data){
|
||||
desc = bricks.apply_data(desc, data);
|
||||
}
|
||||
if (!desc.widgettype){
|
||||
console.log('widgettype is null', desc);
|
||||
return null;
|
||||
}
|
||||
let klass = bricks.Factory.get(desc.widgettype);
|
||||
if (! klass){
|
||||
bricks.debug('widgetBuild():',desc.widgettype, 'not registered', bricks.Factory.widgets_kw);
|
||||
console.log('widgetBuild():',
|
||||
desc.widgettype,
|
||||
'not registered',
|
||||
bricks.Factory.widgets_kw);
|
||||
return null;
|
||||
}
|
||||
var options = desc.options || {};
|
||||
options.baseURI = base_url;
|
||||
let w = new klass(options);
|
||||
if (! w){
|
||||
console.log('w is null');
|
||||
}
|
||||
if (desc.id){
|
||||
w.set_id(desc.id);
|
||||
}
|
||||
@ -203,14 +228,34 @@ bricks.universal_handler = async function(from_widget, widget, desc, event){
|
||||
'desc=', desc,
|
||||
event);
|
||||
}
|
||||
bricks.default_popup = function(opts){
|
||||
var popts = bricks.get_popup_default_options();
|
||||
bricks.extend(popts, opts);
|
||||
return new bricks.Popup(popts);
|
||||
}
|
||||
bricks.default_popupwindow = function(opts){
|
||||
var popts = bricks.get_popupwindow_default_options();
|
||||
bricks.extend(popts, opts);
|
||||
return new bricks.PopupWindow(popts);
|
||||
}
|
||||
bricks.buildEventHandler = async function(w, desc, event){
|
||||
var target = bricks.getWidgetById(desc.target, w);
|
||||
var target;
|
||||
if (desc.target == 'Popup'){
|
||||
target = bricks.default_popup(desc.popup_options || {});
|
||||
} else if (desc.target == 'PopupWindow') {
|
||||
target = bricks.default_popupwindow(desc.popup_options || {});
|
||||
} else if ( desc.target instanceof bricks.JsWidget ) {
|
||||
target = desc.target;
|
||||
} else {
|
||||
target = bricks.getWidgetById(desc.target, w);
|
||||
}
|
||||
if (! target){
|
||||
bricks.debug('target miss desc=', desc, 'w=', w);
|
||||
return null
|
||||
}
|
||||
var rtdata = {};
|
||||
|
||||
desc.event_params = event.params || {} ;
|
||||
desc.event = event;
|
||||
if (desc.rtdata) rtdata = desc.rtdata;
|
||||
else if (desc.datawidget){
|
||||
var data_desc = {
|
||||
@ -221,9 +266,6 @@ bricks.buildEventHandler = async function(w, desc, event){
|
||||
}
|
||||
rtdata = await bricks.getRealtimeData(w, data_desc);
|
||||
}
|
||||
if (typeof event.params == typeof {}){
|
||||
rtdata = bricks.extend(rtdata, event.params);
|
||||
}
|
||||
switch (desc.actiontype){
|
||||
case 'urlwidget':
|
||||
return bricks.buildUrlwidgetHandler(w, target, rtdata, desc);
|
||||
@ -269,70 +311,80 @@ bricks.getRealtimeData = async function(w, desc){
|
||||
return null;
|
||||
}
|
||||
|
||||
var _buildWidget = async function(from_widget, target, mode, options){
|
||||
bricks.debug('target=', target, 'mode=', mode, 'options=', options);
|
||||
var w = await (bricks.widgetBuild(options, from_widget));
|
||||
if (!w){
|
||||
bricks.debug('options=', options, 'widgetBuild() failed');
|
||||
return;
|
||||
}
|
||||
var _buildWidget = async function(from_widget, target, mode, options, desc){
|
||||
bricks.debug('target=', target, 'mode=', mode, 'options=', options);
|
||||
var w = await (bricks.widgetBuild(options, from_widget));
|
||||
if (!w){
|
||||
bricks.debug('options=', options, 'widgetBuild() failed');
|
||||
return;
|
||||
}
|
||||
|
||||
if (w.parent) return;
|
||||
|
||||
if (mode == 'replace'){
|
||||
target.clear_widgets();
|
||||
target.add_widget(w);
|
||||
} else if (mode == 'insert'){
|
||||
target.add_widget(w, 0);
|
||||
} else {
|
||||
target.add_widget(w);
|
||||
if (w.parent) {
|
||||
if (target instanceof bricks.Popup || target instanceof bricks.PopupWindow){
|
||||
target.destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (target instanceof bricks.Popup || target instanceof bricks.PopupWindow) {
|
||||
if (! target.parent){
|
||||
bricks.app.add_widget(target);
|
||||
}
|
||||
console.log('target=', target);
|
||||
if (desc.popup_options.eventpos){
|
||||
target.bind('opened', bricks.relocate_by_eventpos.bind(null, desc.event, target));
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == 'replace'){
|
||||
target.clear_widgets();
|
||||
target.add_widget(w);
|
||||
} else if (mode == 'insert'){
|
||||
target.add_widget(w, 0);
|
||||
} else {
|
||||
target.add_widget(w);
|
||||
}
|
||||
if (target instanceof bricks.Popup || target instanceof bricks.PopupWindow) {
|
||||
target.open();
|
||||
}
|
||||
}
|
||||
|
||||
bricks.buildUrlwidgetHandler = function(w, target, rtdata, desc){
|
||||
var f = async function(target, mode, options){
|
||||
bricks.debug('target=', target, 'mode=', mode, 'options=', options);
|
||||
var w = await (bricks.widgetBuild(options, w));
|
||||
if (!w){
|
||||
bricks.debug('options=', options, 'widgetBuild() failed');
|
||||
return;
|
||||
}
|
||||
if (mode == 'replace'){
|
||||
target.clear_widgets();
|
||||
target.add_widget(w);
|
||||
} else if (mode == 'insert'){
|
||||
target.add_widget(w, 0);
|
||||
} else {
|
||||
target.add_widget(w);
|
||||
}
|
||||
}
|
||||
var options = objcopy(desc.options||{});
|
||||
var params = options.params || {};
|
||||
options = bricks.apply_data(options, rtdata);
|
||||
options.params = bricks.extend(params, rtdata);
|
||||
if (desc.event_params instanceof FormData){
|
||||
var params = desc.event_params;
|
||||
for ( const [key, value] of Object.entries(rtdata)){
|
||||
params.append(key, value);
|
||||
}
|
||||
options = bricks.apply_data(options, rtdata);
|
||||
for ( const [key, value] of Object.entries(options.params||{})){
|
||||
params.append(key, value);
|
||||
}
|
||||
options.params = params;
|
||||
options.method = "POST";
|
||||
} else {
|
||||
rtdata = bricks.extend(rtdata, desc.event_params);
|
||||
options = bricks.apply_data(options, rtdata);
|
||||
if (desc.params_mapping){
|
||||
rtdata = bricks.map(rtdata, desc.params_mapping.mapping, desc.params_mapping.need_others);
|
||||
}
|
||||
options.params = bricks.extend(params, rtdata);
|
||||
}
|
||||
|
||||
var opts = {
|
||||
"widgettype":"urlwidget",
|
||||
"options":options
|
||||
}
|
||||
return _buildWidget.bind(w, target, target, desc.mode || 'replace', opts);
|
||||
return _buildWidget.bind(null, w, target, desc.mode || 'replace', opts, desc);
|
||||
}
|
||||
bricks.buildBricksHandler = function(w, target, rtdata, desc){
|
||||
var f = async function(target, mode, options){
|
||||
bricks.debug('target=', target, 'mode=', mode, 'options=', options);
|
||||
var w = await (bricks.widgetBuild(options, wa));
|
||||
if (!w){
|
||||
bricks.debug('options=', options, 'widgetBuild() failed');
|
||||
return;
|
||||
}
|
||||
if (mode == 'replace'){
|
||||
target.clear_widgets();
|
||||
}
|
||||
target.add_widget(w);
|
||||
}
|
||||
var options = objcopy(desc.options||{});
|
||||
rtdata = bricks.extend(rtdata, inputdata2dic(desc.event_params));
|
||||
if (desc.params_mapping){
|
||||
rtdata = bricks.map(rtdata, desc.params_mapping.mapping, desc.params_mapping.need_others);
|
||||
}
|
||||
options = bricks.apply_data(options, rtdata);
|
||||
return _buildWidget.bind(w, target, target, desc.mode || 'replace', options);
|
||||
return _buildWidget.bind(w, target, target, desc.mode || 'replace', options, desc);
|
||||
}
|
||||
bricks.buildRegisterFunctionHandler = function(w, target, rtdata, desc){
|
||||
var f = bricks.RF.get(desc.rfname);
|
||||
@ -340,6 +392,9 @@ bricks.buildRegisterFunctionHandler = function(w, target, rtdata, desc){
|
||||
bricks.debug('rfname:', desc.rfname, 'not registed', desc);
|
||||
return null;
|
||||
}
|
||||
if (desc.params_mapping){
|
||||
rtdata = bricks.map(rtdata, desc.params_mapping.mapping, desc.params_mapping.need_others);
|
||||
}
|
||||
var params = {};
|
||||
if (desc.params){
|
||||
bricks.extend(params, desc.params);
|
||||
@ -347,6 +402,7 @@ bricks.buildRegisterFunctionHandler = function(w, target, rtdata, desc){
|
||||
if (rtdata){
|
||||
bricks.extend(params, rtdata);
|
||||
}
|
||||
bricks.extend(params, inputdata2dic(desc.event_params));
|
||||
params = bricks.apply_data(params, rtdata);
|
||||
return f.bind(target, params);
|
||||
}
|
||||
@ -359,6 +415,10 @@ bricks.buildMethodHandler = function(w, target, rtdata, desc){
|
||||
var params = {};
|
||||
bricks.extend(params, desc.params)
|
||||
bricks.extend(params, rtdata);
|
||||
bricks.extend(params, inputdata2dic(desc.event_params));
|
||||
if (desc.params_mapping){
|
||||
rtdata = bricks.map(rtdata, desc.params_mapping.mapping, desc.params_mapping.need_others);
|
||||
}
|
||||
params = bricks.apply_data(params, rtdata);
|
||||
return f.bind(target, params);
|
||||
}
|
||||
@ -366,6 +426,10 @@ bricks.buildScriptHandler = function(w, target, rtdata, desc){
|
||||
var params = {};
|
||||
bricks.extend(params, desc.params)
|
||||
bricks.extend(params, rtdata);
|
||||
bricks.extend(params, inputdata2dic(desc.event_params));
|
||||
if (desc.params_mapping){
|
||||
rtdata = bricks.map(rtdata, desc.params_mapping.mapping, desc.params_mapping.need_others);
|
||||
}
|
||||
params = bricks.apply_data(params, rtdata);
|
||||
var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
|
||||
var f = new AsyncFunction('params', 'event', desc.script);
|
||||
@ -379,6 +443,7 @@ bricks.buildDispatchEventHandler = function(w, target, rtdata, desc){
|
||||
var params = {};
|
||||
bricks.extend(params, desc.params)
|
||||
bricks.extend(params, rtdata);
|
||||
bricks.extend(params, inputdata2dic(desc.event_params));
|
||||
params = bricks.apply_data(params, rtdata);
|
||||
return f.bind(target, desc.dispatch_event, params);
|
||||
}
|
||||
@ -405,7 +470,7 @@ bricks.getWidgetById = function(id, from_widget){
|
||||
el = bricks.app.root.dom_element;
|
||||
continue;
|
||||
}
|
||||
if (ids[i]=='app'){
|
||||
if (ids[i]=='app' || ids[i] == 'body'){
|
||||
return bricks.app;
|
||||
}
|
||||
if (ids[i] == 'window'){
|
||||
@ -444,6 +509,7 @@ bricks.App = class extends bricks.Layout {
|
||||
/*
|
||||
opts = {
|
||||
appname:
|
||||
debug:false, true, 'server'
|
||||
login_url:
|
||||
"charsize:
|
||||
"language":
|
||||
@ -460,10 +526,11 @@ bricks.App = class extends bricks.Layout {
|
||||
*/
|
||||
super(opts);
|
||||
bricks.app = this;
|
||||
this.docks = [];
|
||||
bricks.bug = opts.debug || false;
|
||||
bricks.Body = this;
|
||||
this.deviceid = bricks.deviceid(opts.appname || 'appname');
|
||||
this.login_url = opts.login_url;
|
||||
this.login_url = opts.login_url || '/rbac/userpassword_login.ui';
|
||||
this.charsize = this.opts.charsize || 20;
|
||||
this.keyevent_blocked = false;
|
||||
this.char_size = this.observable('charsize', this.charsize);
|
||||
@ -482,8 +549,53 @@ bricks.App = class extends bricks.Layout {
|
||||
this.add_widget(this.tooltip);
|
||||
this._Width = this.dom_element.offsetWidth;
|
||||
this._Height = this.dom_element.offsetHeight;
|
||||
this.video_stream = null;
|
||||
this.audio_stream = null;
|
||||
this.video_devices = null
|
||||
this.vpos = null;
|
||||
document.addEventListener('keydown', this.key_down_action.bind(this));
|
||||
this.screen_orient = window.screen.orientation.type;
|
||||
window.screen.orientation.addEventListener('change', () => {
|
||||
this.screen_orient = window.screen.orientation.type;
|
||||
this.bind('orient_changed', this.screen_orient);
|
||||
});
|
||||
}
|
||||
async getCameras() {
|
||||
try {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
this.video_devices = devices.filter(device => device.kind === 'videoinput');
|
||||
} catch (error) {
|
||||
console.error('获取摄像头数量出错:', error);
|
||||
}
|
||||
}
|
||||
async start_camera(vpos) {
|
||||
if (typeof(vpos) == 'undefined') vpos = 0;
|
||||
if (this.video_devices === null){
|
||||
await this.getCameras();
|
||||
}
|
||||
if (vpos == this.vpos) return;
|
||||
this.vpos = vpos;
|
||||
if (this.video_stream){
|
||||
this.video_stream.getTracks().forEach(track => {
|
||||
track.stop();
|
||||
});
|
||||
}
|
||||
if (navigator.mediaDevices.getUserMedia) {
|
||||
var x = { deviceId: this.video_devices[vpos].deviceId };
|
||||
this.video_stream = await navigator.mediaDevices.getUserMedia({ video: x });
|
||||
} else {
|
||||
console.log("Webcam access is not supported in this browser.");
|
||||
}
|
||||
}
|
||||
async start_mic() {
|
||||
if (this.audio_stream) return;
|
||||
if (navigator.mediaDevices.getUserMedia) {
|
||||
this.audio_stream = navigator.mediaDevices.getUserMedia({ audio: true });
|
||||
} else {
|
||||
console.log("mic access is not supported in this browser.");
|
||||
this.stream = null;
|
||||
}
|
||||
}
|
||||
new_zindex(){
|
||||
const v = this.zindex;
|
||||
this.zindex = v + 1;
|
||||
|
@ -1,14 +1,15 @@
|
||||
SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.js \
|
||||
i18n.js widget.js layout.js bricks.js image.js html.js \
|
||||
jsoncall.js myoperator.js scroll.js menu.js popup.js modal.js running.js \
|
||||
i18n.js widget.js layout.js bricks.js image.js html.js splitter.js \
|
||||
jsoncall.js myoperator.js scroll.js menu.js popup.js camera.js modal.js running.js \
|
||||
markdown_viewer.js video.js audio.js toolbar.js tab.js \
|
||||
input.js registerfunction.js button.js accordion.js dataviewer.js \
|
||||
tree.js multiple_state_image.js dynamiccolumn.js form.js message.js conform.js \
|
||||
paging.js datagrid.js iframe.js cols.js echartsext.js \
|
||||
floaticonbar.js miniform.js wterm.js dynamicaccordion.js \
|
||||
binstreaming.js streaming_audio.js vadtext.js rtc.js \
|
||||
binstreaming.js streaming_audio.js vadtext.js rtc.js docxviewer.js \
|
||||
llm_dialog.js llm.js websocket.js datarow.js tabular.js \
|
||||
line.js pie.js bar.js gobang.js "
|
||||
line.js pie.js bar.js gobang.js period.js iconbarpage.js \
|
||||
keypress.js asr.js webspeech.js countdown.js progressbar.js "
|
||||
echo ${SOURCES}
|
||||
cat ${SOURCES} > ../dist/bricks.js
|
||||
# uglifyjs --compress --mangle -- ../dist/bricks.js > ../dist/bricks.min.js
|
||||
@ -38,4 +39,5 @@ cp -a ../examples/* ../dist/examples
|
||||
cp -a ../3parties/* ../dist/3parties
|
||||
cp -a ../docs/* ../dist/docs
|
||||
cp *.tmpl ../dist
|
||||
cp -a ../dist /tmp
|
||||
echo "Finished ..."
|
||||
|
99
bricks/camera.js
Normal file
@ -0,0 +1,99 @@
|
||||
var bricks = window.bricks || {}
|
||||
bricks.Camera = class extends bricks.Popup {
|
||||
/*
|
||||
{
|
||||
fps:60
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
opts.fps = opts.fps || 60;
|
||||
opts.auto_dismiss = false;
|
||||
super(opts);
|
||||
this.stream = null;
|
||||
this.video = document.createElement('video');
|
||||
var filler = new bricks.Filler({});
|
||||
var hbox = new bricks.HBox({
|
||||
cheight:3
|
||||
});
|
||||
this.cur_camera_id = 0;
|
||||
this.add_widget(filler);
|
||||
this.add_widget(hbox);
|
||||
var shot_btn = new bricks.Icon({
|
||||
url:bricks_resource('imgs/camera.png'),
|
||||
margin: '10px',
|
||||
tip:'Take a picture',
|
||||
rate:2.5
|
||||
});
|
||||
var switch_btn = new bricks.Icon({
|
||||
url:bricks_resource('imgs/switch-camera.png'),
|
||||
tip:'switch camera',
|
||||
margin: '10px',
|
||||
rate:1.5
|
||||
});
|
||||
var del_btn = new bricks.Icon({
|
||||
url:bricks_resource('imgs/delete.png'),
|
||||
tip:'canel it',
|
||||
margin: '10px',
|
||||
rate:1.5
|
||||
})
|
||||
del_btn.bind('click', this.dismiss.bind(this));
|
||||
shot_btn.bind('click', this.take_picture.bind(this));
|
||||
switch_btn.bind('click', this.switch_camera.bind(this, switch_btn));
|
||||
this.imgw = new bricks.Image({
|
||||
width:'100%'
|
||||
});
|
||||
hbox.add_widget(switch_btn);
|
||||
hbox.add_widget(shot_btn);
|
||||
hbox.add_widget(new bricks.Filler({}));
|
||||
hbox.add_widget(del_btn);
|
||||
filler.add_widget(this.imgw);
|
||||
this.task_period = 1 / this.fps;
|
||||
schedule_once(this.startCamera.bind(this), 0.1);
|
||||
}
|
||||
async switch_camera(btn, event){
|
||||
if (bricks.app.video_devices.length < 2){
|
||||
btn.disabled(true);
|
||||
return;
|
||||
}
|
||||
var vpos = bricks.app.vpos;
|
||||
vpos += 1;
|
||||
if (vpos >= bricks.app.video_devices.length){
|
||||
vpos = 0;
|
||||
}
|
||||
this.startCamera(vpos);
|
||||
}
|
||||
async startCamera(vpos) {
|
||||
await bricks.app.start_camera(vpos);
|
||||
this.stream = bricks.app.video_stream;
|
||||
this.video.srcObject = this.stream;
|
||||
this.video.play();
|
||||
this.show_cnt = 1;
|
||||
this.task = schedule_once(this.show_picture.bind(this), this.task_period);
|
||||
}
|
||||
show_picture(){
|
||||
if (this.task_period == 0){
|
||||
return;
|
||||
}
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.height = this.video.videoHeight;
|
||||
canvas.width = this.video.videoWidth;
|
||||
const context = canvas.getContext('2d');
|
||||
context.drawImage(this.video, 0, 0);
|
||||
this.imgw.set_url(canvas.toDataURL('image/jpeg'));
|
||||
this.task = schedule_once(this.show_picture.bind(this), this.task_period);
|
||||
this.show_cnt += 1;
|
||||
}
|
||||
take_picture(event){
|
||||
event.stopPropagation();
|
||||
if (this.task){
|
||||
task.cancel();
|
||||
this.task = null;
|
||||
}
|
||||
this.task_period = 0;
|
||||
this.task = null;
|
||||
var d = this.imgw.base64();
|
||||
this.dispatch('shot', d);
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('Camera', bricks.Camera);
|
@ -55,6 +55,7 @@ bricks.Cols = class extends bricks.VBox {
|
||||
}
|
||||
|
||||
async handle_click(rw, event){
|
||||
event.stopPropagation();
|
||||
var orev = null;
|
||||
if (this.select_record){
|
||||
orev = this.select_record;
|
||||
@ -64,6 +65,8 @@ bricks.Cols = class extends bricks.VBox {
|
||||
}
|
||||
this.select_record = rw;
|
||||
this.select_record.set_css('selected_record');
|
||||
console.log('record data=', rw.user_data);
|
||||
this.dispatch('record_click', rw.user_data);
|
||||
}
|
||||
async dataHandle(d){
|
||||
var data = d.rows;
|
||||
@ -71,18 +74,20 @@ bricks.Cols = class extends bricks.VBox {
|
||||
if (!data){
|
||||
return;
|
||||
}
|
||||
if (! this.loader.is_max_page(page)){
|
||||
var rev = ! this.loader.is_max_page(page);
|
||||
if (rev){
|
||||
data.reverse();
|
||||
}
|
||||
for (var i=0;i<data.length;i++){
|
||||
var d = data[i];
|
||||
var w = await bricks.widgetBuild(this.record_view, this.main, d);
|
||||
var r = data[i];
|
||||
var w = await bricks.widgetBuild(this.record_view, this.main, r);
|
||||
w.user_data = r;
|
||||
w.bind('click', this.handle_click.bind(this, w));
|
||||
w.set_attribute('data-page', page);
|
||||
if (this.loader.is_max_page(page)){
|
||||
this.main.add_widget(w);
|
||||
} else {
|
||||
if (rev){
|
||||
this.main.add_widget(w, 0);
|
||||
} else {
|
||||
this.main.add_widget(w);
|
||||
}
|
||||
}
|
||||
if (d.delete_page){
|
||||
@ -93,11 +98,11 @@ bricks.Cols = class extends bricks.VBox {
|
||||
var items = this.dom_element.querySelectorAll('[data-page="' + page + '"]');
|
||||
for (var i=0;i<items.length;i++) {
|
||||
var w = items[i].bricks_widget;
|
||||
this.container.remove_widget(w);
|
||||
this.main.remove_widget(w);
|
||||
}
|
||||
}
|
||||
async load_first_page(params){
|
||||
var p = bricks.extend({}, this.params);
|
||||
var p = bricks.extend({}, this.data_params);
|
||||
if (params){
|
||||
p = bricks.extend(p, params);
|
||||
}
|
||||
@ -112,14 +117,14 @@ bricks.Cols = class extends bricks.VBox {
|
||||
this.main = new bricks.DynamicColumn({
|
||||
width:"100%",
|
||||
col_cwidth:this.col_cwidth,
|
||||
mobile_cols:this.mobile_cols,
|
||||
mobile_cols:2});
|
||||
mobile_cols:this.mobile_cols || 2
|
||||
});
|
||||
this.container.add_widget(this.main);
|
||||
var d = await this.loader.loadData(p);
|
||||
if (d){
|
||||
this.dataHandle(d);
|
||||
var total = this.container.dom_element.scrollHeight - this.container.dom_element.clientHeight;
|
||||
this.container.dom_element.scrollTop = d.pos_rate * total;
|
||||
// this.container.dom_element.scrollTop = d.pos_rate * total;
|
||||
} else {
|
||||
bricks.debug(this.loader, 'load previous page error');
|
||||
}
|
||||
@ -163,12 +168,12 @@ bricks.Cols = class extends bricks.VBox {
|
||||
if (d){
|
||||
this.dataHandle(d);
|
||||
var total = this.container.dom_element.scrollHeight - this.container.dom_element.clientHeight;
|
||||
this.container.dom_element.scrollTop = d.pos_rate * total;
|
||||
// this.container.dom_element.scrollTop = d.pos_rate * total;
|
||||
} else {
|
||||
bricks.debug(this.loader, 'load next page error');
|
||||
console.log(this.loader, 'load next page error');
|
||||
}
|
||||
} catch (e){
|
||||
bricks.debug('error happened', e);
|
||||
console.log('error happened', e);
|
||||
}
|
||||
this.loading = false;
|
||||
running.dismiss();
|
||||
|
@ -1,13 +1,29 @@
|
||||
var bricks = window.bricks || {};
|
||||
bricks.Conform = class extends bricks.Message {
|
||||
bricks.Conform = class extends bricks.PopupWindow {
|
||||
constructor(opts){
|
||||
opts.auto_open = true;
|
||||
opts.auto_close = false;
|
||||
opts.timeout = 0;
|
||||
opts.auto_open = true;
|
||||
super(opts);
|
||||
this.create_toolbar();
|
||||
this.create_conform();
|
||||
}
|
||||
create_toolbar(){
|
||||
create_conform(){
|
||||
var w = new bricks.VBox({width:'100%', height: '100%'});
|
||||
this.create_message(w);
|
||||
this.create_toolbar(w);
|
||||
this.add_widget(w);
|
||||
}
|
||||
create_message(widget){
|
||||
var w = new bricks.Filler();
|
||||
widget.add_widget(w);
|
||||
var w1 = new bricks.VScrollPanel({});
|
||||
w.add_widget(w1);
|
||||
var t = new bricks.Text({otext:this.opts.message,
|
||||
wrap:true,
|
||||
halign:'middle',
|
||||
i18n:true});
|
||||
w1.add_widget(t);
|
||||
}
|
||||
create_toolbar(widget){
|
||||
var desc = {
|
||||
tools:[
|
||||
bricks.extend({
|
||||
@ -26,7 +42,7 @@ bricks.Conform = class extends bricks.Message {
|
||||
w.bind('conform', this.conform_hndl.bind(this));
|
||||
w.bind('discard', this.discard_hndl.bind(this));
|
||||
if (!w) return;
|
||||
this.message_w.add_widget(w);
|
||||
widget.add_widget(w);
|
||||
}
|
||||
conform_hndl(event){
|
||||
this.dismiss();
|
||||
|
76
bricks/countdown.js
Normal file
@ -0,0 +1,76 @@
|
||||
var bricks = window.bricks || {};
|
||||
|
||||
bricks.Countdown = class extends bricks.VBox {
|
||||
/*
|
||||
options:
|
||||
limit_time: 01:00:00
|
||||
text_rate:
|
||||
event:
|
||||
timeout
|
||||
timeout event is fired after the countdown time is over.
|
||||
method:
|
||||
start
|
||||
start method is to start the countdown, step is 1 secord
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
var parts = opts.limit_time.split(':');
|
||||
var hours, minutes, seconds;
|
||||
switch(parts.length){
|
||||
case 0:
|
||||
hours = 0;
|
||||
minutes = 0;
|
||||
seconds = 0;
|
||||
break;
|
||||
case 1:
|
||||
hours = 0;
|
||||
minutes = 0;
|
||||
seconds = parseInt(parts[0])
|
||||
break;
|
||||
case 2:
|
||||
hours = 0;
|
||||
minutes = 0;
|
||||
seconds = parseInt(parts[0])
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
hours = parseInt(parts[0]);
|
||||
minutes = parseInt(parts[1]);
|
||||
seconds = parseInt(parts[2])
|
||||
break;
|
||||
}
|
||||
this.seconds = hours * 3600 + minutes * 60 + seconds;
|
||||
this.text_w = new bricks.Text({
|
||||
text:this.limit_time,
|
||||
rate:this.text_rate
|
||||
});
|
||||
this.add_widget(this.text_w);
|
||||
}
|
||||
start(){
|
||||
schedule_once(this.time_down_second.bind(this), 1)
|
||||
}
|
||||
formatTime(seconds) {
|
||||
let hrs = Math.floor(seconds / 3600);
|
||||
let mins = Math.floor((seconds % 3600) / 60);
|
||||
let secs = seconds % 60;
|
||||
|
||||
return [
|
||||
hrs.toString().padStart(2, '0'),
|
||||
mins.toString().padStart(2, '0'),
|
||||
secs.toString().padStart(2, '0')
|
||||
].join(':');
|
||||
}
|
||||
time_down_second(){
|
||||
if (this.seconds < 1){
|
||||
this.dispatch('timeout');
|
||||
return;
|
||||
}
|
||||
var h, m, s;
|
||||
this.seconds -= 1;
|
||||
var ts = formatTime(this.seconds);
|
||||
this.text_w.set_text(ts);
|
||||
schedule_once(this.time_down_second.bind(this), 1)
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('Countdown', bricks.Countdown);
|
@ -6,10 +6,26 @@ body {
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow-x: auto; /* 允许内容超出容器显示 */
|
||||
background-color: #b5e5e5;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box!important;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 1px;
|
||||
background-color: #8a8a8a;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.flexbox {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
.curpos {
|
||||
border-radius: 30%;
|
||||
background-color: #f5f5f5;
|
||||
@ -21,6 +37,14 @@ body {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #888888;
|
||||
}
|
||||
.subcard {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
.clickable {
|
||||
color: #40cc40;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.video-in-video {
|
||||
position: relative;
|
||||
}
|
||||
@ -46,6 +70,34 @@ body {
|
||||
grid-gap: 1px;
|
||||
}
|
||||
|
||||
.resizebox {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: darkblue;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
cursor: se-resize; /* 改变鼠标指针样式 */
|
||||
}
|
||||
.popup {
|
||||
display: none;
|
||||
position: absolute;
|
||||
box-sizing: border-box; /* 包括边框在内计算宽度和高度 */
|
||||
color: #111111;
|
||||
background-color: #f1f1f1;
|
||||
border: 1px solid #c1c1c1;
|
||||
border-radius: 5px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.titlebar {
|
||||
background-color: #d8d8c8;
|
||||
}
|
||||
|
||||
.toppopup {
|
||||
box-shadow: 10px 5px 10px #000, 0 -5px 5px #fff;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display:none;
|
||||
position: absolute;
|
||||
@ -108,7 +160,7 @@ body {
|
||||
}
|
||||
|
||||
.scroll {
|
||||
overflow:scroll;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.vcontainer {
|
||||
@ -138,7 +190,7 @@ body {
|
||||
.filler, .hfiller, .vfiller {
|
||||
flex: auto;
|
||||
flex-grow: 1;
|
||||
overflow:hidden;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.vfiller .vbox:last-child {
|
||||
@ -210,16 +262,8 @@ body {
|
||||
|
||||
.multicolumns {
|
||||
column-width: 340px;
|
||||
colomn-gap: 10px';
|
||||
overflow-x:none;
|
||||
}
|
||||
|
||||
.popup {
|
||||
display: none;
|
||||
position: absolution;
|
||||
box-sizing: border-box; /* 包括边框在内计算宽度和高度 */
|
||||
background-color: #f1f1f1;
|
||||
border: 1px solid #c1c1c1;
|
||||
colomn-gap: 10px;
|
||||
overflow-x: none;
|
||||
}
|
||||
|
||||
.selected_record {
|
||||
@ -271,6 +315,11 @@ body {
|
||||
height: 50px;
|
||||
background-color: blue;
|
||||
}
|
||||
.childrensize {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.datagrid-row {
|
||||
flex:0 0 150px;
|
||||
display: flex;
|
||||
@ -334,14 +383,22 @@ body {
|
||||
overflow: auto;
|
||||
}
|
||||
.tabular-header-row {
|
||||
background-color: #dddddd;
|
||||
position: sticky;
|
||||
display: flex;
|
||||
top: 0;
|
||||
width: auto;
|
||||
position: sticky;
|
||||
background-color: #dddddd;
|
||||
min-width: 0;
|
||||
min-width: fit-content;
|
||||
flex-wrap: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tabular-row {
|
||||
width: auto;
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
min-width: 0;
|
||||
min-width: fit-content;
|
||||
flex-wrap: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tabular-row:nth-child(odd) {
|
||||
background-color: #5dfdfd;
|
||||
@ -350,10 +407,10 @@ body {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.tabular-row-selected {
|
||||
background-color: #ef0000;
|
||||
color: #ef0000;
|
||||
}
|
||||
.tabular-row-content {
|
||||
padding: 10px;
|
||||
padding: 2;
|
||||
}
|
||||
.tabular-cell {
|
||||
border: 1px solid #ccc;
|
||||
@ -365,6 +422,7 @@ body {
|
||||
margin-left: 5px;
|
||||
margin-right: auto;
|
||||
margin-bottom: 10px;
|
||||
padding: 3px;
|
||||
background-color:#fefedd;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 0;
|
||||
@ -387,3 +445,19 @@ body {
|
||||
.llm_title {
|
||||
background-color:#eeeeee;
|
||||
}
|
||||
.progress-container {
|
||||
width: 80%;
|
||||
background-color: #ddd;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.progress-bar {
|
||||
height: 30px;
|
||||
width: 0%;
|
||||
background-color: #4CAF50;
|
||||
text-align: center;
|
||||
color: white;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ bricks.DataRow = class extends bricks.HBox {
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.set_style('width', 'auto');
|
||||
this.record_w = null;
|
||||
}
|
||||
render_header(){
|
||||
@ -30,13 +29,17 @@ bricks.DataRow = class extends bricks.HBox {
|
||||
this.render(false);
|
||||
}
|
||||
render(header){
|
||||
this.build_toolbar(header);
|
||||
// this.build_toolbar(header);
|
||||
if (this.checkField){
|
||||
var w;
|
||||
if (header){
|
||||
w = new bricks.BlankIcon({});
|
||||
} else {
|
||||
w = new bricks.UiCheck({name:this.checkField,value:this.user_data[this.checkField]});
|
||||
var v = 0
|
||||
if (this.user_data){
|
||||
v = this.user_data[this.checkField];
|
||||
}
|
||||
w = new bricks.UiCheck({name:this.checkField,value:v});
|
||||
w.bind('changed', this.get_check_state.bind(this));
|
||||
}
|
||||
this.add_widget(w);
|
||||
@ -87,6 +90,7 @@ bricks.DataRow = class extends bricks.HBox {
|
||||
}
|
||||
build_fields(header, cw){
|
||||
this.record_w = new bricks.HBox({height:'auto'});
|
||||
this.record_w.set_css('childrensize');
|
||||
this.add_widget(this.record_w);
|
||||
this._build_fields(header, this.record_w);
|
||||
}
|
||||
@ -108,7 +112,7 @@ bricks.DataRow = class extends bricks.HBox {
|
||||
continue;
|
||||
}
|
||||
var opts = bricks.extend({
|
||||
margin:'3px'
|
||||
margin:'1px'
|
||||
}, f);
|
||||
if (header || ! this.user_data){
|
||||
opts.value = f.label || f.name;
|
||||
@ -116,10 +120,7 @@ bricks.DataRow = class extends bricks.HBox {
|
||||
opts.user_data = this.user_data;
|
||||
opts.value = opts.tip = this.user_data[f.name];
|
||||
}
|
||||
var cwidth = cwidths[f.name];
|
||||
if (cwidth){
|
||||
opts.cwidth = cwidth;
|
||||
}
|
||||
opts.cwidth = cwidths[f.name] ||f.cwidth || 10;
|
||||
var f = bricks.get_ViewBuilder(f.uitype);
|
||||
if (!f) f = bricks.get_ViewBuilder('str');
|
||||
var w = f(opts);
|
||||
|
@ -138,7 +138,7 @@ bricks.DataViewer = class extends bricks.VBox {
|
||||
}
|
||||
if (this.toolbar){
|
||||
this.toolbar.tools.forEach(t => {
|
||||
if (! edit_names.incloudes(t.name)){
|
||||
if (! edit_names.includes(t.name)){
|
||||
tbdesc.tools.push(t);
|
||||
}
|
||||
});
|
||||
@ -168,12 +168,13 @@ bricks.DataViewer = class extends bricks.VBox {
|
||||
this.delete_record(this.select_row);
|
||||
return;
|
||||
}
|
||||
var d = {
|
||||
tabular:this,
|
||||
row:this.select_row,
|
||||
data:row.user_data
|
||||
var data = null;
|
||||
if (this.select_row){
|
||||
var r = this.select_row;
|
||||
var data = r.user_data;
|
||||
}
|
||||
this.dispathc(t.name. d);
|
||||
console.log(tdesc.name, 'clicked ==================', tdesc.name, data)
|
||||
this.dispatch(tdesc.name, data);
|
||||
}
|
||||
get_edit_fields(){
|
||||
var fs = this.row_options.fields;
|
||||
@ -193,7 +194,8 @@ bricks.DataViewer = class extends bricks.VBox {
|
||||
this.dispatch('row_check_changed', event.params.user_data);
|
||||
}
|
||||
async renew_record_view(form, row){
|
||||
var d = form.getValue();
|
||||
var d = form._getValue();
|
||||
d = form._getValue();
|
||||
var record = bricks.extend(row.user_data, d);
|
||||
row.renew(record);
|
||||
}
|
||||
@ -215,6 +217,11 @@ bricks.DataViewer = class extends bricks.VBox {
|
||||
fs.push(this.fields[i]);
|
||||
}
|
||||
var f = new bricks.ModalForm({
|
||||
"widget":this,
|
||||
"archor":"cc",
|
||||
"movable":true,
|
||||
"resizable":true,
|
||||
"archor":"cc",
|
||||
"width":"90%",
|
||||
"height":"70%",
|
||||
"submit_url":this.editable.new_data_url,
|
||||
@ -225,10 +232,10 @@ bricks.DataViewer = class extends bricks.VBox {
|
||||
}
|
||||
async add_record_finish(f, event){
|
||||
f.dismiss();
|
||||
this.render();
|
||||
var resp = event.params;
|
||||
var desc = await resp.json();
|
||||
var w = await bricks.widgetBuild(desc);
|
||||
this.render();
|
||||
}
|
||||
update_record(){
|
||||
var record = this.select_row.user_data;
|
||||
@ -239,6 +246,10 @@ bricks.DataViewer = class extends bricks.VBox {
|
||||
fields.push(f);
|
||||
}
|
||||
var f = new bricks.ModalForm({
|
||||
"widget":this,
|
||||
"movable":true,
|
||||
"resizable":true,
|
||||
"archor":"cc",
|
||||
"width":"90%",
|
||||
"height":"70%",
|
||||
"submit_url":this.editable.update_data_url+'?id=' + record.id,
|
||||
@ -251,15 +262,15 @@ bricks.DataViewer = class extends bricks.VBox {
|
||||
f.dismiss();
|
||||
}
|
||||
async update_record_finish(form, event){
|
||||
await this.renew_record_view(form, this.select_row);
|
||||
var resp = event.params;
|
||||
var desc = await resp.json();
|
||||
var w = await bricks.widgetBuild(desc);
|
||||
if (desc.widgettype == 'Message'){
|
||||
await this.renew_record_view(form, this.select_row);
|
||||
}
|
||||
}
|
||||
delete_record(row, record){
|
||||
var conform_w = new bricks.Conform({
|
||||
cwidth:16,
|
||||
cheight:9,
|
||||
target:this,
|
||||
title:'Delete conform',
|
||||
message:'Are you sure to delete is record?'
|
||||
@ -315,8 +326,8 @@ bricks.DataViewer = class extends bricks.VBox {
|
||||
var d = await this.loader.loadNextPage();
|
||||
if (d){
|
||||
this.dataHandle(d);
|
||||
var total = this.scrollpanel.dom_element.scrollHeight - this.scrollpanel.dom_element.clientHeight;
|
||||
this.scrollpanel.dom_element.scrollTop = d.pos_rate * total;
|
||||
// var total = this.scrollpanel.dom_element.scrollHeight - this.scrollpanel.dom_element.clientHeight;
|
||||
// this.scrollpanel.dom_element.scrollTop = d.pos_rate * total;
|
||||
} else {
|
||||
bricks.debug(this.loader, 'load next page error');
|
||||
}
|
||||
|
119
bricks/docxviewer.js
Normal file
@ -0,0 +1,119 @@
|
||||
/* need mammoth module
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.2/mammoth.browser.min.js"></script>
|
||||
*/
|
||||
var bricks = window.bricks || {};
|
||||
|
||||
bricks.DOCXviewer = class extends bricks.VBox {
|
||||
/*
|
||||
url:
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.bind('on_parent', this.set_url.bind(this));
|
||||
// schedule_once(this.set_url.bind(this, this.url), 0.2);
|
||||
}
|
||||
async set_url(url){
|
||||
var container = this.dom_element
|
||||
var hab = new bricks.HttpArrayBuffer();
|
||||
var ab = await hab.get(this.url);
|
||||
var result = await mammoth.convertToHtml({ arrayBuffer: ab });
|
||||
container.innerHTML = result.value;
|
||||
}
|
||||
}
|
||||
|
||||
function extractBodyContent(htmlString) {
|
||||
// 正则表达式匹配<body>和</body>之间的内容
|
||||
const regex = /<body[^>]*>([\s\S]*?)<\/body>/i;
|
||||
const matches = htmlString.match(regex);
|
||||
return matches ? matches[1] : null; // 如果匹配到,返回匹配的内容,否则返回null
|
||||
}
|
||||
|
||||
bricks.EXCELviewer = class extends bricks.VBox {
|
||||
constructor(opts){
|
||||
opts.height = "100%",
|
||||
super(opts);
|
||||
this.sheets_w = new bricks.HBox({cheight:3, width:'100%'});
|
||||
this.sheets_w.set_css('scroll');
|
||||
this.cur_sheetname = null;
|
||||
this.container = new bricks.Filler({});
|
||||
this.add_widget(this.container);
|
||||
this.add_widget(this.sheets_w);
|
||||
this.bind('on_parent', this.set_url.bind(this));
|
||||
}
|
||||
async set_url(url){
|
||||
this.sheets_w.clear_widgets();
|
||||
var hab = new bricks.HttpArrayBuffer();
|
||||
var ab = await hab.get(this.url);
|
||||
const data = new Uint8Array(ab);
|
||||
this.workbook = XLSX.read(data, {type: 'array'});
|
||||
this.workbook.SheetNames.forEach((sheetname, index) => {
|
||||
var w = new bricks.Text({text:sheetname, wrap:false});
|
||||
w.set_css('clickable');
|
||||
w.set_style('padding', '10px');
|
||||
w.bind('click', this.show_sheet_by_name.bind(this, sheetname, w));
|
||||
this.sheets_w.add_widget(w);
|
||||
if (index==0){
|
||||
this.show_sheet_by_name(this.workbook.SheetNames[0], w);
|
||||
}
|
||||
});
|
||||
}
|
||||
show_sheet_by_name(sheetname, tw){
|
||||
if (this.cur_sheetname == sheetname) return;
|
||||
this.sheets_w.children.forEach(c => c.set_css('selected', true));
|
||||
tw.set_css('selected');
|
||||
const x = new bricks.VScrollPanel({width: '100%', height: '100%'});
|
||||
const sheet = this.workbook.Sheets[sheetname];
|
||||
// const html = extractBodyContent(XLSX.utils.sheet_to_html(sheet));
|
||||
const html = XLSX.utils.sheet_to_html(sheet);
|
||||
x.dom_element.innerHTML = html;
|
||||
this.container.clear_widgets();
|
||||
this.container.add_widget(x);
|
||||
this.cur_sheetname = sheetname;
|
||||
}
|
||||
}
|
||||
|
||||
bricks.PDFviewer = class extends bricks.VBox {
|
||||
/*
|
||||
url:
|
||||
*/
|
||||
constructor(opts){
|
||||
opts.width = '100%';
|
||||
super(opts);
|
||||
this.bind('on_parent', this.set_url.bind(this));
|
||||
}
|
||||
async set_url(url){
|
||||
var container = this.dom_element
|
||||
var hab = new bricks.HttpArrayBuffer();
|
||||
var ab = await hab.get(this.url);
|
||||
const task = pdfjsLib.getDocument({ data: ab });
|
||||
task.promise.then((pdf) => {
|
||||
this.pdf = pdf;
|
||||
for (let i = 1; i <= this.pdf.numPages; i++) {
|
||||
this.pdf.getPage(i).then((page) => {
|
||||
this.add_page_content(page);
|
||||
});
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log('error');
|
||||
})
|
||||
}
|
||||
add_page_content(page){
|
||||
const scale = 1.5;
|
||||
const viewport = page.getViewport({ scale });
|
||||
const canvas = document.createElement('canvas');
|
||||
const context = canvas.getContext('2d');
|
||||
canvas.height = viewport.height;
|
||||
canvas.width = viewport.width;
|
||||
page.render({ canvasContext: context, viewport });
|
||||
var w = new bricks.JsWidget();
|
||||
w.dom_element.appendChild(canvas);
|
||||
this.add_widget(w);
|
||||
if (i < this.pdf.numPages){
|
||||
w = new bricks.Splitter();
|
||||
this.add_widget(w)
|
||||
}
|
||||
}
|
||||
}
|
||||
bricks.Factory.register('DOCXviewer', bricks.DOCXviewer);
|
||||
bricks.Factory.register('EXCELviewer', bricks.EXCELviewer);
|
||||
bricks.Factory.register('PDFviewer', bricks.PDFviewer);
|
@ -30,21 +30,19 @@ bricks.DynamicColumn = class extends bricks.Layout {
|
||||
var cw;
|
||||
var cols;
|
||||
var gap;
|
||||
var width = this.get_width();
|
||||
if (this.col_cwidth){
|
||||
cw = bricks.app.charsize * this.col_cwidth;
|
||||
} else {
|
||||
cw = this.col_width;
|
||||
}
|
||||
gap = bricks.app.charsize * (this.col_cgap || 0.1);
|
||||
if (width > 0){
|
||||
if (bricks.is_mobile() && (width < this.get_height())){
|
||||
cols = this.mobile_cols || 1;
|
||||
} else {
|
||||
cols = (width + gap) / (cw + gap)
|
||||
}
|
||||
cols = Math.floor(width/cw);
|
||||
var width = bricks.app.screenWidth();
|
||||
var height = bricks.app.screenHeight();
|
||||
if (bricks.is_mobile() && width < height){
|
||||
cols = this.mobile_cols;
|
||||
cw = (width - (cols - 1) * gap) / cols;
|
||||
console.log('====mobile==cols=', cols, '====');
|
||||
} else {
|
||||
if (this.col_cwidth){
|
||||
cw = bricks.app.charsize * this.col_cwidth;
|
||||
} else {
|
||||
cw = this.col_width;
|
||||
}
|
||||
}
|
||||
this.dom_element.style.gridTemplateColumns = "repeat(auto-fill, minmax(" + cw + "px, 1fr))";
|
||||
this.set_style('gap', gap + 'px');
|
||||
|
@ -83,6 +83,7 @@ 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%',
|
||||
|
0
bricks/factory.js
Executable file → Normal file
@ -20,10 +20,22 @@ bricks.IconBar = class extends bricks.HBox {
|
||||
if (! opts.cheight){
|
||||
opts.cheight = 2;
|
||||
}
|
||||
if (! opts.rate){
|
||||
opts.rate = 1;
|
||||
}
|
||||
super(opts);
|
||||
this.set_css('childrensize');
|
||||
this.height_int = 0;
|
||||
var tools = this.opts.tools;
|
||||
for (var i=0;i<tools.length;i++){
|
||||
var w = this.build_item(tools[i]);
|
||||
var opts_i = bricks.extend({}, tools[i]);
|
||||
if (!opts_i.rate){
|
||||
opts_i.rate = this.rate;
|
||||
}
|
||||
opts_i.cheight = opts.cheight;
|
||||
opts_i.cwidth = opts.cheight;
|
||||
opts_i.dynsize = true;
|
||||
var w = this.build_item(opts_i);
|
||||
w.set_style('margin-left', this.opts.margin || '10px');
|
||||
w.set_style('margin-right', this.opts.margin || '10px');
|
||||
if (tools[i].name){
|
||||
@ -37,27 +49,27 @@ bricks.IconBar = class extends bricks.HBox {
|
||||
}
|
||||
build_item(opts){
|
||||
var rate = opts.rate || this.opts.rate || 1;
|
||||
var h = bricks.app.charsize * rate;
|
||||
var h = bricks.app.charsize * rate * opts.cheight;
|
||||
if (this.height_int < h){
|
||||
this.height_int = h;
|
||||
}
|
||||
if (opts.name == 'blankicon'){
|
||||
return new bricks.BlankIcon({
|
||||
rate:rate,
|
||||
cheight:opts.cheight,
|
||||
cwidth:opts.cwidth,
|
||||
dynsize:opts.dynsize||true
|
||||
});
|
||||
}
|
||||
var opts1 = bricks.extend({}, opts);
|
||||
opts1.url = opts.icon;
|
||||
opts1.rate = opts.rate || rate;
|
||||
opts1.dynsize = opts.dynsize||true;
|
||||
var w = new bricks.Icon(opts1);
|
||||
w.bind('click', this.regen_event.bind(this, opts1));
|
||||
opts.url = opts.icon;
|
||||
var w = new bricks.Icon(opts);
|
||||
w.bind('click', this.regen_event.bind(this, opts));
|
||||
return w;
|
||||
}
|
||||
regen_event(desc, event){
|
||||
this.dispatch(desc.name, desc);
|
||||
this.dispatch('command', desc);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ bricks.FormBase = class extends bricks.Layout {
|
||||
w.reset();
|
||||
}
|
||||
}
|
||||
getValue(){
|
||||
_getValue(){
|
||||
var data = {};
|
||||
for (var name in this.name_inputs){
|
||||
if (! this.name_inputs.hasOwnProperty(name)){
|
||||
@ -195,6 +195,14 @@ bricks.FormBase = class extends bricks.Layout {
|
||||
}
|
||||
return data;
|
||||
}
|
||||
getValue(){
|
||||
if (this.data) {
|
||||
var ret = this.data;
|
||||
this.data = null;
|
||||
return ret;
|
||||
}
|
||||
return this.get_formdata();
|
||||
}
|
||||
get_formdata(){
|
||||
var data = new FormData();
|
||||
for (var name in this.name_inputs){
|
||||
@ -204,37 +212,35 @@ bricks.FormBase = class extends bricks.Layout {
|
||||
var w = this.name_inputs[name];
|
||||
var d = w.getValue();
|
||||
if (w.required && ( d[name] == '' || d[name] === null)){
|
||||
bricks.debug('data=', data, 'd=', d);
|
||||
new bricks.Error({title:'Requirement', message:'required field must input"' + w.label + '"'})
|
||||
w.focus();
|
||||
return;
|
||||
}
|
||||
if (bricks.need_formdata_fields.includes(w.uitype)){
|
||||
var files = w.get_files();
|
||||
for (var i=0;i<files.length;i++){
|
||||
// data.append(name, w.fileContents[i].body, w.fileContents[i].filename);
|
||||
data.append(name, files[i]);
|
||||
}
|
||||
} else {
|
||||
data.append(name, d[name]);
|
||||
if (d[name] === null){
|
||||
continue;
|
||||
}
|
||||
w.set_formdata(data);
|
||||
}
|
||||
this.data = data;
|
||||
return data;
|
||||
}
|
||||
async validation(){
|
||||
var running = new bricks.Running({target:this});
|
||||
try {
|
||||
var data;
|
||||
data = this.get_formdata();
|
||||
/*
|
||||
if (this.need_formdata){
|
||||
data = this.get_formdata();
|
||||
} else {
|
||||
data = this.getValue();
|
||||
}
|
||||
*/
|
||||
if (! data) {
|
||||
running.dismiss();
|
||||
return;
|
||||
}
|
||||
data = bricks.delete_null_values(data);
|
||||
// data = bricks.delete_null_values(data);
|
||||
this.dispatch('submit', data);
|
||||
if (this.submit_url){
|
||||
var rc = new bricks.HttpResponse();
|
||||
|
@ -4,34 +4,37 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="/bricks/3parties/xterm.css" />
|
||||
<link href="/bricks/3parties/video-js.css" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="/bricks/css/bricks.css">
|
||||
<link rel="stylesheet" href="{{entire_url('/bricks/3parties/xterm.css')}}" />
|
||||
<link href="{{entire_url('/bricks/3parties/video-js.css')}}" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="{{entire_url('/bricks/css/bricks.css')}}">
|
||||
<link rel="stylesheet", href="{{entire_url('/css/myapp.css')}}">
|
||||
</head>
|
||||
<body>
|
||||
<!--
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/js-docx-viewer/dist/css/docxviewer.min.css">
|
||||
<script src="//cdn.bootcdn.net/ajax/libs/eruda/2.3.3/eruda.js"></script>
|
||||
<script>eruda.init();</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.7/dist/bundle.min.js"></script>
|
||||
<script src="https://unpkg.com/docx-js@3.2.0/lib/docx.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.14.305/pdf.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.2/mammoth.browser.min.js"></script>
|
||||
-->
|
||||
<script type="text/javascript" src="https://registry.npmmirror.com/echarts/5.5.1/files/dist/echarts.min.js"></script>
|
||||
|
||||
<script src="/bricks/3parties/marked.min.js"></script>
|
||||
<script src="/bricks/3parties/xterm.js"></script>
|
||||
<script src="/bricks/3parties/video.min.js"></script>
|
||||
<script src="{{entire_url('/bricks/3parties/marked.min.js')}}"></script>
|
||||
<script src="{{entire_url('/bricks/3parties/xterm.js')}}"></script>
|
||||
<script src="{{entire_url('/bricks/3parties/xterm-addon-fit.js')}}"></script>
|
||||
<script src="{{entire_url('/bricks/3parties/video.min.js')}}"></script>
|
||||
<!---
|
||||
<link href="https://unpkg.com/video.js@6/dist/video-js.css" rel="stylesheet">
|
||||
<script src="https://unpkg.com/video.js@6/dist/video.js"></script></head>
|
||||
--->
|
||||
|
||||
<script src="/bricks/3parties/recorder.wav.min.js"></script>
|
||||
<script src="/bricks/bricks.js"></script>
|
||||
<script src="{{entire_url('/bricks/3parties/recorder.wav.min.js')}}"></script>
|
||||
<script src="{{entire_url('/bricks/bricks.js')}}"></script>
|
||||
<script src="{{entire_url('/js/myapp.js')}}"></script>
|
||||
<script>
|
||||
/*
|
||||
if (bricks.is_mobile()){
|
||||
alert('wh=' + window.innerWidth + ':' + window.innerHeight);
|
||||
}
|
||||
*/
|
||||
const opts = {
|
||||
"widget":
|
||||
|
0
bricks/i18n.js
Executable file → Normal file
55
bricks/iconbarpage.js
Normal file
@ -0,0 +1,55 @@
|
||||
var bricks = window.bricks || {};
|
||||
bricks.IconbarPage = class extends bricks.VBox {
|
||||
/*
|
||||
opts={
|
||||
bar_opts:
|
||||
bar_at: top or bottom
|
||||
}
|
||||
bar_opts:{
|
||||
margin:
|
||||
rate:
|
||||
tools:
|
||||
}
|
||||
tools = [
|
||||
tool, ...
|
||||
]
|
||||
tool = {
|
||||
name:
|
||||
icon:
|
||||
label: optional
|
||||
tip,
|
||||
dynsize
|
||||
rate:
|
||||
context:
|
||||
}
|
||||
*/
|
||||
|
||||
constructor(opts){
|
||||
opts.height = '100%'
|
||||
opts.bar_at = opts.bar_at || 'top';
|
||||
super(opts);
|
||||
var bar = new bricks.IconTextBar(this.bar_opts);
|
||||
this.content = new bricks.Filler({});
|
||||
if (this.bar_at == 'top'){
|
||||
this.add_widget(bar);
|
||||
this.add_widget(this.content);
|
||||
} else {
|
||||
this.add_widget(this.content);
|
||||
this.add_widget(bar);
|
||||
}
|
||||
bar.bind('command', this.command_handle.bind(this))
|
||||
schedule_once(this.show_content.bind(this, this.bar_opts.tools[0]), 0.1);
|
||||
}
|
||||
async command_handle(event){
|
||||
var tool = event.params;
|
||||
await this.show_content(tool);
|
||||
}
|
||||
async show_content(tool){
|
||||
var w = await bricks.widgetBuild(tool.content, this);
|
||||
if (w && ! w.parent) {
|
||||
this.content.add_widget(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('IconbarPage', bricks.IconbarPage);
|
@ -1,6 +1,7 @@
|
||||
var bricks = window.bricks || {};
|
||||
bricks.Iframe = class extends bricks.Layout {
|
||||
constructor(opts){
|
||||
opts.height = opts.height || '100%';
|
||||
super(opts);
|
||||
this.dom_element.src = opts.url;
|
||||
}
|
||||
@ -9,4 +10,12 @@ bricks.Iframe = class extends bricks.Layout {
|
||||
}
|
||||
}
|
||||
|
||||
bricks.NewWindow = class extends bricks.JsWidget {
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
window.open(opts.url);
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('NewWindow', bricks.NewWindow);
|
||||
bricks.Factory.register('Iframe', bricks.Iframe);
|
||||
|
3
bricks/image.js
Executable file → Normal file
@ -46,8 +46,7 @@ bricks.Image = class extends bricks.JsWidget {
|
||||
|
||||
// 获取画布数据并转换为 base64
|
||||
var dataURL = canvas.toDataURL('image/png'); // 可以根据需要修改图像格式
|
||||
dataURL = this.removeBase64Header(dataURL);
|
||||
console.log(dataURL);
|
||||
// dataURL = this.removeBase64Header(dataURL);
|
||||
return dataURL;
|
||||
}
|
||||
set_url(url){
|
||||
|
BIN
bricks/imgs/app.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
bricks/imgs/app_delete.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
bricks/imgs/app_fullscreen.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
bricks/imgs/app_minimax.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
bricks/imgs/camera.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
bricks/imgs/dislike.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
bricks/imgs/input.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
bricks/imgs/left-bottom-triangle.png
Normal file
After Width: | Height: | Size: 8.0 KiB |
BIN
bricks/imgs/left-top-triangle.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 12 KiB |
BIN
bricks/imgs/right-bottom-triangle.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
bricks/imgs/right-top-triangle.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
bricks/imgs/search.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
bricks/imgs/switch-camera.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
bricks/imgs/tag.png
Normal file
After Width: | Height: | Size: 15 KiB |
203
bricks/input.js
Executable file → Normal file
@ -17,6 +17,9 @@ bricks.UiType =class extends bricks.Layout {
|
||||
}
|
||||
return o;
|
||||
}
|
||||
set_formdata(formdata){
|
||||
formdata.append(this.name, this.resultValue());
|
||||
}
|
||||
resultValue(){
|
||||
return this.value;
|
||||
}
|
||||
@ -46,6 +49,47 @@ bricks.UiType =class extends bricks.Layout {
|
||||
}
|
||||
}
|
||||
|
||||
bricks.UiAudioRecorder = class extends bricks.AudioRecorder {
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.uitype = 'audiorecorder';
|
||||
this.name = this.opts.name;
|
||||
this.required = opts.required || false;
|
||||
this.value = opts.value || opts.defaultvalue||'';
|
||||
this.bind('record_ended', this.getValue.bind(this));
|
||||
}
|
||||
|
||||
getValue(){
|
||||
var o = {}
|
||||
this.value = this.recordData.data;
|
||||
o[this.name] = this.value;
|
||||
return o;
|
||||
}
|
||||
set_formdata(formdata){
|
||||
formdata.append(this.name, this.value, 'record.wav');
|
||||
}
|
||||
resultValue(){
|
||||
return this.value;
|
||||
}
|
||||
focus(){
|
||||
this.dom_element.focus();
|
||||
}
|
||||
reset(){
|
||||
}
|
||||
setValue(v){
|
||||
return;
|
||||
}
|
||||
set_disabled(f){
|
||||
this.dom_element.disabled = f;
|
||||
}
|
||||
set_readonly(f){
|
||||
this.dom_element.readOnly = f;
|
||||
}
|
||||
set_required(f){
|
||||
this.dom_element.required = f;
|
||||
this.required = f;
|
||||
}
|
||||
}
|
||||
bricks.UiAudioText = class extends bricks.UiType {
|
||||
/*
|
||||
{
|
||||
@ -70,10 +114,12 @@ bricks.UiAudioText = class extends bricks.UiType {
|
||||
clear_text(){
|
||||
this.text_w.setValue('');
|
||||
}
|
||||
getValue(){
|
||||
return this.text_w.getValue();
|
||||
resultValue(){
|
||||
this.value = this.text_w.resultValue();
|
||||
return this.value;
|
||||
}
|
||||
setValue(v){
|
||||
this.value = v;
|
||||
this.text_w.setValue(v);
|
||||
}
|
||||
set_result_text(event){
|
||||
@ -203,6 +249,105 @@ bricks.UiStr =class extends bricks.UiType {
|
||||
}
|
||||
}
|
||||
|
||||
bricks.UiSearch = class extends bricks.HBox {
|
||||
/*
|
||||
search_url:
|
||||
valueField
|
||||
textField
|
||||
select_event
|
||||
popup_options
|
||||
value,
|
||||
text
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.uitype = 'search';
|
||||
var inputdesc = {
|
||||
name:this.name,
|
||||
value:this.text,
|
||||
readonly:true
|
||||
}
|
||||
this.str_in = new bricks.UiStr(inputdesc);
|
||||
this.search_icon = new bricks.Icon({
|
||||
url:bricks_resource('imgs/search.png'),
|
||||
rate:1.5
|
||||
});
|
||||
this.str_in.set_css('filler');
|
||||
this.search_icon.set_css('clickable');
|
||||
this.search_icon.bind('click', this.open_search_window.bind(this));
|
||||
this.add_widget(this.str_in);
|
||||
this.add_widget(this.search_icon);
|
||||
}
|
||||
async open_search_window(event){
|
||||
var desc = {
|
||||
"widgettype":"urlwidget",
|
||||
"options":{
|
||||
"url":this.search_url
|
||||
}
|
||||
}
|
||||
var w = await bricks.widgetBuild(desc, this);
|
||||
var tabular = null;
|
||||
for (var i=0;i<w.children.length;i++){
|
||||
if (w.children[i] instanceof bricks.Tabular){
|
||||
tabular = w.children[i];
|
||||
}
|
||||
}
|
||||
if (!tabular){
|
||||
console.log('tubular not found is w');
|
||||
return;
|
||||
}
|
||||
var win = bricks.default_popupwindow(this.popup_options||{});
|
||||
win.add_widget(w);
|
||||
win.open();
|
||||
tabular.bind(this.search_event, this.set_data.bind(this));
|
||||
tabular.bind(this.search_event, win.dismiss.bind(win));
|
||||
}
|
||||
set_data(event){
|
||||
var d = event.params;
|
||||
this.value = d[this.valueField];
|
||||
this.str_in.setValue(d[this.textField])
|
||||
}
|
||||
getValue(){
|
||||
var o = {}
|
||||
o[this.name] = this.resultValue();
|
||||
var d = this.getUserData();
|
||||
if (d){
|
||||
o = bricks.extend(o, d);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
set_formdata(formdata){
|
||||
formdata.append(this.name, this.resultValue());
|
||||
}
|
||||
resultValue(){
|
||||
return this.value;
|
||||
}
|
||||
focus(){
|
||||
this.str_in.dom_element.focus();
|
||||
}
|
||||
reset(){
|
||||
var v = this.opts.value||this.opts.defaultvalue|| '';
|
||||
this.setValue(v);
|
||||
this.str_in.setValue(this.opts.text||'');
|
||||
}
|
||||
setValue(v, t){
|
||||
if (! v)
|
||||
v = '';
|
||||
this.vlaue = v;
|
||||
this.str_in.setValue(t);
|
||||
}
|
||||
set_disabled(f){
|
||||
this.dom_element.disabled = f;
|
||||
}
|
||||
set_readonly(f){
|
||||
this.dom_element.readOnly = f;
|
||||
}
|
||||
set_required(f){
|
||||
this.dom_element.required = f;
|
||||
this.required = f;
|
||||
}
|
||||
|
||||
}
|
||||
bricks.UiPassword =class extends bricks.UiStr {
|
||||
/*
|
||||
{
|
||||
@ -265,6 +410,7 @@ bricks.UiFloat =class extends bricks.UiInt {
|
||||
this.dom_element.step = step;
|
||||
}
|
||||
resultValue(){
|
||||
super.resultValue();
|
||||
return parseFloat(this.value);
|
||||
}
|
||||
setValue(v){
|
||||
@ -331,7 +477,7 @@ bricks.UiFile =class extends bricks.UiStr {
|
||||
return this.dom_element.files;
|
||||
}
|
||||
resultValue(){
|
||||
return this.get_files();
|
||||
return this.get_files()[0];
|
||||
}
|
||||
setValue(v){
|
||||
return;
|
||||
@ -344,6 +490,12 @@ bricks.UiImage =class extends bricks.VBox {
|
||||
opts.name = opts.name || 'image';
|
||||
super(opts);
|
||||
this.uitype='image';
|
||||
this.camera_w = new bricks.Icon({
|
||||
url:bricks_resource('imgs/camera.png'),
|
||||
tip:'use cemera to take a picture',
|
||||
rate:2});
|
||||
this.add_widget(this.camera_w);
|
||||
this.camera_w.bind('click', this.take_photo.bind(this));
|
||||
this.bind('drop', this.dropHandle.bind(this));
|
||||
this.input = document.createElement('input');
|
||||
this.input.type = 'file';
|
||||
@ -354,6 +506,27 @@ bricks.UiImage =class extends bricks.VBox {
|
||||
this.dom_element.appendChild(this.input);
|
||||
this.imgw = null;
|
||||
}
|
||||
take_photo(event){
|
||||
event.stopPropagation();
|
||||
var camera = new bricks.Camera({
|
||||
"archor":"cc",
|
||||
"auto_open":true,
|
||||
"height":"90%",
|
||||
"width":"90%"
|
||||
});
|
||||
camera.bind('shot', this.accept_photo.bind(this, camera));
|
||||
}
|
||||
accept_photo(camera, event){
|
||||
camera.dismiss();
|
||||
if (this.imgw){
|
||||
this.remove_widget(this.imgw);
|
||||
}
|
||||
this.imgw = new bricks.Image({
|
||||
url:event.params,
|
||||
width:'100%'
|
||||
});
|
||||
this.add_widget(this.imgw);
|
||||
}
|
||||
handleFileSelect(event){
|
||||
const file = event.target.files[0];
|
||||
this.show_image(file);
|
||||
@ -367,7 +540,11 @@ bricks.UiImage =class extends bricks.VBox {
|
||||
show_image(file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
this.clear_widgets();
|
||||
if (this.imgw){
|
||||
this.remove_widget(this.imgw);
|
||||
}
|
||||
this.value = e.target.result;
|
||||
console.log('this.value=', this.value);
|
||||
this.imgw = new bricks.Image({
|
||||
url:e.target.result,
|
||||
width:'100%'
|
||||
@ -376,10 +553,22 @@ bricks.UiImage =class extends bricks.VBox {
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
set_formdata(fd){
|
||||
// fd.append(this.name, this.resultValue(), 'test.png');
|
||||
fd.append(this.name, this.resultValue());
|
||||
}
|
||||
resultValue(){
|
||||
if (this.imgw){
|
||||
this.value = this.imgw.base64();
|
||||
return this.value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
getValue(){
|
||||
var ret = {}
|
||||
if (this.imgw){
|
||||
ret[this.name] = this.imgw.base64()
|
||||
// ret[this.name] = this.imgw.base64()
|
||||
ret[this.name] = this.value;
|
||||
} else {
|
||||
ret[this.name] = null;
|
||||
}
|
||||
@ -718,7 +907,7 @@ bricks.UiCode =class extends bricks.UiType {
|
||||
e.removeChild(e.firstChild);
|
||||
}
|
||||
var v = this.opts.value || this.opts.defaultvalue || null;
|
||||
if (!v && ! this.opts.nullable){
|
||||
if (!v && ! this.opts.nullable && data.length > 0){
|
||||
v = data[0][this.opts.valueField]
|
||||
}
|
||||
if (this.opts.nullable){
|
||||
@ -861,6 +1050,7 @@ bricks.UiVideo =class extends bricks.UiStr {
|
||||
}
|
||||
}
|
||||
var Input = new bricks._Input();
|
||||
Input.register('UiAudioRecorder', 'audiorecorder', bricks.UiAudioRecorder);
|
||||
Input.register('UiStr', 'str', bricks.UiStr);
|
||||
Input.register('UiHide', 'hide', bricks.UiHide);
|
||||
Input.register('UiTel', 'tel', bricks.UiTel);
|
||||
@ -878,3 +1068,4 @@ Input.register('UiPassword', 'password', bricks.UiPassword);
|
||||
Input.register('UiAudio', 'audio', bricks.UiAudio);
|
||||
Input.register('UiVideo', 'video', bricks.UiVideo);
|
||||
Input.register('UiAudioText', 'audiotext', bricks.UiAudioText);
|
||||
Input.register('UiSearch', 'search', bricks.UiSearch);
|
||||
|
131
bricks/jsoncall.js
Executable file → Normal file
@ -44,9 +44,9 @@ bricks.HttpText = class {
|
||||
};
|
||||
bricks.extend(this.headers, headers);
|
||||
var width=0, height=0;
|
||||
var is_mobile = 0
|
||||
var is_mobile = '0'
|
||||
if (bricks.is_mobile()){
|
||||
is_mobile = 1;
|
||||
is_mobile = '1';
|
||||
}
|
||||
if (bricks.app) {
|
||||
width = bricks.app.screenWidth();
|
||||
@ -77,8 +77,6 @@ bricks.HttpText = class {
|
||||
return await resp.text();
|
||||
}
|
||||
add_own_params(params){
|
||||
if (! params)
|
||||
params = {};
|
||||
var session = bricks.app.get_session();
|
||||
if (params instanceof FormData){
|
||||
for ( const [key, value] of Object.entries(this.params)){
|
||||
@ -89,6 +87,8 @@ bricks.HttpText = class {
|
||||
}
|
||||
return params;
|
||||
}
|
||||
if (! params)
|
||||
params = {};
|
||||
var p = bricks.extend({}, this.params);
|
||||
p = bricks.extend(p, params);
|
||||
if (session){
|
||||
@ -102,46 +102,66 @@ bricks.HttpText = class {
|
||||
}
|
||||
return Object.assign(this.headers, headers);
|
||||
}
|
||||
async httpcall(url, {method='GET', headers=null, params=null}={}){
|
||||
async bricks_fetch(url, {method='GET', headers=null, params=null}={}){
|
||||
url = this.url_parse(url);
|
||||
var data = this.add_own_params(params);
|
||||
var header = this.add_own_headers(headers);
|
||||
var _params = {
|
||||
method:method
|
||||
}
|
||||
// _params.headers = headers;
|
||||
if (method == 'GET' || method == 'HEAD') {
|
||||
let pstr = url_params(data);
|
||||
url = url + '?' + pstr;
|
||||
if (data instanceof FormData){
|
||||
method = 'POST';
|
||||
_params.body = data;
|
||||
} else {
|
||||
if (data instanceof FormData){
|
||||
_params.body = data;
|
||||
if (method == 'GET' || method == 'HEAD') {
|
||||
let pstr = url_params(data);
|
||||
url = url + '?' + pstr;
|
||||
} else {
|
||||
_params.body = JSON.stringify(data);
|
||||
}
|
||||
}
|
||||
const fetchResult = await fetch(url, _params);
|
||||
var result=null;
|
||||
result = await this.get_result_data(fetchResult);
|
||||
if (fetchResult.ok){
|
||||
var ck = objget(fetchResult.headers, 'Set-Cookie');
|
||||
if (ck){
|
||||
var session = ck.split(';')[0];
|
||||
bricks.app.save_session(session);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return await fetch(url, _params);
|
||||
}
|
||||
async httpcall(url, opts){
|
||||
const fetchResult = await this.bricks_fetch(url, {
|
||||
method: opts.method,
|
||||
headers: opts.headers,
|
||||
params: opts.params});
|
||||
if (fetchResult.status == 401 && bricks.app.login_url){
|
||||
console.log('go to login')
|
||||
return await this.withLoginInfo(url, _params);
|
||||
}
|
||||
const resp_error = {
|
||||
"type":"Error",
|
||||
"message":result.message || 'Something went wrong',
|
||||
"data":result.data || '',
|
||||
"code":result.code || ''
|
||||
};
|
||||
error.info = resp_error;
|
||||
return error;
|
||||
if (fetchResult.status == 403){
|
||||
var w = new bricks.Error({
|
||||
"title":"access error",
|
||||
"auto_open":true,
|
||||
"message":"you are forbidden to access it",
|
||||
"archor":"cc",
|
||||
"cheight":10,
|
||||
"cwidth":16,
|
||||
"timeout":5
|
||||
});
|
||||
return null;
|
||||
}
|
||||
if (! fetchResult.ok){
|
||||
var w = new bricks.Error({
|
||||
"title":"access error",
|
||||
"auto_open":true,
|
||||
"message":"server return error with error code" + fetchResult.status,
|
||||
"archor":"cc",
|
||||
"cheight":10,
|
||||
"cwidth":16,
|
||||
"timeout":5
|
||||
});
|
||||
return null;
|
||||
}
|
||||
var result = await this.get_result_data(fetchResult);
|
||||
var ck = objget(fetchResult.headers, 'Set-Cookie');
|
||||
if (ck){
|
||||
var session = ck.split(';')[0];
|
||||
bricks.app.save_session(session);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
async withLoginInfo(url, params){
|
||||
var get_login_info = function(e){
|
||||
@ -149,50 +169,13 @@ bricks.HttpText = class {
|
||||
return e.target.getValue();
|
||||
}
|
||||
var w = await bricks.widgetBuild({
|
||||
"id":"login_form",
|
||||
"widgettype":"urlwidget",
|
||||
"options":{
|
||||
"url":bricks.app.login_url
|
||||
}
|
||||
});
|
||||
var login_info = await new Promise((resolve, reject, w) => {
|
||||
w.bind('submit', (event) => {
|
||||
resolve(event.target.getValue());
|
||||
event.target.dismiss();
|
||||
});
|
||||
w.bind('discard', (event) => {
|
||||
resolve(null);
|
||||
event.target.dismiss()
|
||||
});
|
||||
});
|
||||
if (login_info){
|
||||
this.set_authorization_header(params, lgin_info);
|
||||
const fetchResult = await fetch(url, params);
|
||||
var result=null;
|
||||
result = await this.get_result_data(fetchResult);
|
||||
if (fetchResult.ok){
|
||||
return result;
|
||||
}
|
||||
if (fetchResult.status == 401){
|
||||
return await this.withLoginInfo(url, params);
|
||||
}
|
||||
}
|
||||
const resp_error = {
|
||||
"type":"Error",
|
||||
"message":result.message || 'Something went wrong',
|
||||
"data":result.data || '',
|
||||
"code":result.code || ''
|
||||
};
|
||||
const error = new Error();
|
||||
error.info = resp_error;
|
||||
return error;
|
||||
return null;
|
||||
}
|
||||
set_authorization_header(params, lgin_info){
|
||||
var auth = 'password' + '::' + login_info.user + '::' + login_info.password;
|
||||
var rsa = bricks.app.rsa;
|
||||
var code = rsa.encrypt(auth);
|
||||
self.header.authorization = btoa(code)
|
||||
}
|
||||
async get(url, {headers=null, params=null}={}){
|
||||
return await this.httpcall(url, {
|
||||
method:'GET',
|
||||
@ -209,6 +192,18 @@ bricks.HttpText = class {
|
||||
}
|
||||
}
|
||||
|
||||
bricks.HttpArrayBuffer = class extends bricks.HttpText {
|
||||
async get_result_data(resp){
|
||||
return await resp.arrayBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
bricks.HttpBin = class extends bricks.HttpText {
|
||||
async get_result_data(resp){
|
||||
return await resp.blob();
|
||||
}
|
||||
}
|
||||
|
||||
bricks.HttpResponse = class extends bricks.HttpText {
|
||||
async get_result_data(resp){
|
||||
return resp;
|
||||
|
18
bricks/keypress.js
Normal file
@ -0,0 +1,18 @@
|
||||
var bricks = window.bricks || {};
|
||||
|
||||
bricks.KeyPress = class extends bricks.VBox {
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
bricks.app.bind('keydown', this.key_handler.bind(this));
|
||||
}
|
||||
key_handler(event){
|
||||
var key = event.key;
|
||||
if (!key) return;
|
||||
this.clear_widgets();
|
||||
var w = new bricks.Text({text:'key press is:' + key});
|
||||
this.add_widget(w)
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('KeyPress', bricks.KeyPress);
|
||||
|
67
bricks/layout.js
Executable file → Normal file
@ -4,17 +4,37 @@ bricks.key_selectable_stack = [];
|
||||
|
||||
bricks.Layout = class extends bricks.JsWidget {
|
||||
constructor(options){
|
||||
if (! options){
|
||||
options = {};
|
||||
}
|
||||
super(options);
|
||||
this._container = true;
|
||||
this.keyselectable = options.keyselectable || false;
|
||||
this.children = [];
|
||||
if (this.use_key_select){
|
||||
this.enable_key_select();
|
||||
}
|
||||
}
|
||||
build_title(){
|
||||
if (this.title){
|
||||
this.title_w = new bricks.Title3({otext:this.title, i18n:true, dynsize:true});
|
||||
this.add_widget(this.title_w);
|
||||
}
|
||||
}
|
||||
build_description(){
|
||||
if (this.description){
|
||||
this.description_w = new bricks.Text({otext:this.description,
|
||||
i18n:true, dynsize:true
|
||||
});
|
||||
this.add_widget(this.description_w);
|
||||
}
|
||||
}
|
||||
set_key_select_items(){
|
||||
this.key_select_items = this.children;
|
||||
}
|
||||
enable_key_select(){
|
||||
if (!this.keyselectable) return;
|
||||
this.keyselectable = true;
|
||||
this.set_key_select_items();
|
||||
this.selected_children = null;
|
||||
bricks.app.bind('keydown', this.key_handler.bind(this));
|
||||
bricks.key_selectable_stack.push(this)
|
||||
this.select_default_item();
|
||||
@ -25,9 +45,9 @@ bricks.Layout = class extends bricks.JsWidget {
|
||||
return bricks.key_selectable_stack[p] == this;
|
||||
}
|
||||
disable_key_select(){
|
||||
if (!this.keyselectable) return;
|
||||
this.keyselectable = false;
|
||||
bricks.app.unbind('keydown', this.key_handler.bind(this));
|
||||
if (this.is_currkeyselectable()){
|
||||
bricks.app.unbind('keydown', this.key_handler.bind(this));
|
||||
this.select_item.selected(false);
|
||||
this.select_item = null;
|
||||
bricks.key_selectable_stack.pop();
|
||||
@ -35,7 +55,8 @@ bricks.Layout = class extends bricks.JsWidget {
|
||||
return;
|
||||
}
|
||||
select_item(w){
|
||||
if (!this.keyselectable) return;
|
||||
if (!w) return;
|
||||
// if (!this.keyselectable) return;
|
||||
if (this.selected_item){
|
||||
this.selected_item.selected(false);
|
||||
}
|
||||
@ -86,25 +107,31 @@ bricks.Layout = class extends bricks.JsWidget {
|
||||
}
|
||||
down_level(){
|
||||
this.set_key_select_items();
|
||||
for (var i=0;i<this.key_select_items.length;i++){
|
||||
var w = this.key_select_items[i];
|
||||
if(w.keyselectable){
|
||||
w.enable_key_select();
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
if (w.down_level()){
|
||||
return true;
|
||||
}
|
||||
} catch (e){
|
||||
;
|
||||
}
|
||||
var w = this.selected_item;
|
||||
if (! w) return;
|
||||
if (! w.keyselectable){
|
||||
w = w.find_first_keyselectable_child();
|
||||
if (! w) return;
|
||||
}
|
||||
return false;
|
||||
bricks.key_selectable_stack.push(this);
|
||||
this.disable_key_select();
|
||||
w.enable_key_select();
|
||||
}
|
||||
find_first_keyselectable_child(){
|
||||
for (var i=0;i<this.children;i++){
|
||||
if (this.children[i].keyselectable){
|
||||
return this.children[i];
|
||||
}
|
||||
var sw = this.children[i].find_first_keyselectable_child();
|
||||
if (sw) return sw;
|
||||
}
|
||||
return null
|
||||
}
|
||||
enter_handler(){
|
||||
if (! this.selected_item) {
|
||||
return;
|
||||
}
|
||||
this.selected_item.dispatch('click');
|
||||
this.down_level();
|
||||
}
|
||||
key_handler(event){
|
||||
if (!this.is_currkeyselectable()){
|
||||
|
283
bricks/llm.js
@ -41,7 +41,7 @@ bricks.LlmMsgAudio = class extends bricks.UpStreaming {
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
bricks.ModelOutput = class extends bricks.HBox {
|
||||
bricks.ModelOutput = class extends bricks.VBox {
|
||||
/* {
|
||||
icon:
|
||||
output_view:
|
||||
@ -53,16 +53,29 @@ bricks.ModelOutput = class extends bricks.HBox {
|
||||
opts = {};
|
||||
}
|
||||
opts.width = '100%';
|
||||
opts.height = 'auto';
|
||||
super(opts);
|
||||
var hb = new bricks.HBox({width:'100%', cheight:2});
|
||||
this.img = new bricks.Icon({
|
||||
rate:2,
|
||||
tip:this.opts.model,
|
||||
url:this.icon||bricks_resource('imgs/llm.png')
|
||||
});
|
||||
hb.add_widget(this.img);
|
||||
var mname = new bricks.Text({text:this.opts.model});
|
||||
hb.add_widget(mname);
|
||||
this.add_widget(hb);
|
||||
|
||||
this.content = new bricks.HBox({width:'100%'});
|
||||
this.add_widget(this.content);
|
||||
this.logid = null;
|
||||
this.img = new bricks.Icon({rate:2,url:this.icon||bricks_resource('imgs/llm.png')});
|
||||
this.run = new bricks.BaseRunning({target:this});
|
||||
this.add_widget(this.img);
|
||||
this.add_widget(this.run);
|
||||
this.content.add_widget(this.run);
|
||||
this.filler = new bricks.VBox({});
|
||||
this.filler.set_css('filler');
|
||||
this.add_widget(this.filler);
|
||||
this.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
this.content.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
this.content.add_widget(this.filler);
|
||||
this.content.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
this.build_estimate_widgets();
|
||||
}
|
||||
build_estimate_widgets(){
|
||||
@ -104,7 +117,7 @@ bricks.ModelOutput = class extends bricks.HBox {
|
||||
async update_data(data){
|
||||
if (this.run) {
|
||||
this.run.stop_timepass();
|
||||
this.remove_widget(this.run);
|
||||
this.content.remove_widget(this.run);
|
||||
if(this.textvoice){
|
||||
this.upstreaming = new bricks.UpStreaming({
|
||||
url:this.tts_url
|
||||
@ -116,9 +129,18 @@ bricks.ModelOutput = class extends bricks.HBox {
|
||||
this.upstreaming.send(data.content);
|
||||
}
|
||||
this.run = null;
|
||||
var w = await bricks.widgetBuild(this.output_view, this.llmio, data);
|
||||
w.set_css('llm_msg');
|
||||
this.filler.clear_widgets();
|
||||
if (typeof this.output_view === 'string'){
|
||||
this.output_view = JSON.parse(this.output_view);
|
||||
}
|
||||
var desc = bricks.apply_data(this.output_view, data);
|
||||
var w = await bricks.widgetBuild(desc, this.llmio);
|
||||
if (! w){
|
||||
console.log('widgetBuild() return null, desc=', this.output_view, desc, 'data=', data);
|
||||
return;
|
||||
}
|
||||
w.set_css('llm_msg');
|
||||
w.set_style('width', '100%');
|
||||
this.filler.add_widget(w);
|
||||
this.filler.add_widget(this.estimate_w);
|
||||
if (data.logid){
|
||||
@ -157,57 +179,74 @@ bricks.LlmModel = class extends bricks.JsWidget {
|
||||
constructor(llmio, opts){
|
||||
super(opts);
|
||||
this.llmio = llmio;
|
||||
if (opts.use_session){
|
||||
this.messages = [];
|
||||
}
|
||||
this.messages = [];
|
||||
}
|
||||
render_title(){
|
||||
var w = new bricks.HBox({});
|
||||
var w = new bricks.HBox({padding:'15px'});
|
||||
w.bind('click', this.show_setup_panel.bind(this))
|
||||
var img = new bricks.Icon({rate:2,url:this.opts.icon||bricks_resource('imgs/llm.png')});
|
||||
var txt = new bricks.Text({text:this.opts.model});
|
||||
var img = new bricks.Icon({
|
||||
rate:2,
|
||||
tip:this.opts.model,
|
||||
url:this.opts.icon||bricks_resource('imgs/llm.png')
|
||||
});
|
||||
// var txt = new bricks.Text({text:this.opts.model});
|
||||
w.add_widget(img);
|
||||
w.add_widget(txt);
|
||||
// w.add_widget(txt);
|
||||
return w;
|
||||
}
|
||||
show_setup_panel(event){
|
||||
|
||||
}
|
||||
async model_inputed(data){
|
||||
var mout = new bricks.ModelOutput({
|
||||
textvoice:this.textvoice,
|
||||
tts_url:this.tts_url,
|
||||
icon:this.opts.icon,
|
||||
estimate_url:this.llmio.estimate_url,
|
||||
output_view:this.opts.output_view});
|
||||
this.llmio.o_w.add_widget(mout);
|
||||
var fmt = this.opts.user_message_format || { role:'user', content:'${prompt}'};
|
||||
var umsg = bricks.apply_data(fmt, data);
|
||||
var d = data;
|
||||
if (this.messages){
|
||||
this.messages.push(umsg);
|
||||
d = bricks.extend({}, data);
|
||||
d.messages = this.messages;
|
||||
d.model = this.opts.model;
|
||||
d.modelinstanceid = this.opts.modelinstanceid;
|
||||
d.modeltypeid = this.opts.modeltypeid;
|
||||
inputdata2uploaddata(data){
|
||||
var d;
|
||||
if (data instanceof FormData){
|
||||
d = bricks.formdata_copy(data);
|
||||
} else {
|
||||
d = bricks.extend({}, data);
|
||||
d = objcopy(data);
|
||||
}
|
||||
var fmt = this.opts.user_message_format;
|
||||
if (fmt){
|
||||
var umsg = bricks.apply_data(fmt, inputdata2dic(data));
|
||||
this.messages.push(umsg);
|
||||
}
|
||||
if (data instanceof FormData){
|
||||
d.append('model', this.opts.model)
|
||||
d.append('modelinstanceid', this.opts.modelinstanceid)
|
||||
d.append('modeltypeid', this.opts.modeltypeid)
|
||||
d.append('messages', JSON.stringify(this.messages));
|
||||
} else {
|
||||
d.messages = JSON.stringify(this.messages);
|
||||
d.model = this.opts.model;
|
||||
d.mapi = this.mapi;
|
||||
d.modelinstanceid = this.opts.modelinstanceid;
|
||||
d.modeltypeid = this.opts.modeltypeid;
|
||||
}
|
||||
console.log('upload data=', d, this.options);
|
||||
return d;
|
||||
}
|
||||
async model_inputed(data){
|
||||
if (!opts.use_session){
|
||||
this.messages = [];
|
||||
}
|
||||
var mout = new bricks.ModelOutput({
|
||||
textvoice:this.textvoice,
|
||||
tts_url:this.tts_url,
|
||||
icon:this.opts.icon,
|
||||
model:this.opts.model,
|
||||
estimate_url:this.llmio.estimate_url,
|
||||
output_view:this.opts.output_view});
|
||||
this.llmio.o_w.add_widget(mout);
|
||||
if (this.response_mode == 'stream' || this.response_mode == 'async') {
|
||||
var d = this.inputdata2uploaddata(data);
|
||||
console.log('data_inouted=', data, 'upload_data=', d);
|
||||
var hr = new bricks.HttpResponseStream();
|
||||
var resp = await hr.post(this.opts.url, {params:d});
|
||||
await hr.handle_chunk(resp, this.chunk_response.bind(this, mout));
|
||||
this.chunk_ended();
|
||||
} else {
|
||||
var d = this.inputdata2uploaddata(data);
|
||||
var hj = new bricks.HttpJson()
|
||||
var resp = await hj.post(this.opts.url, {params:d});
|
||||
if (this.response_mode == 'sync'){
|
||||
resp.content = bricks.escapeSpecialChars(resp.content)
|
||||
mout.update_data(resp);
|
||||
if (this.messages){
|
||||
var msg = this.llm_msg_format();
|
||||
@ -236,7 +275,7 @@ bricks.LlmModel = class extends bricks.JsWidget {
|
||||
d.content = bricks.escapeSpecialChars(d.content);
|
||||
this.resp_data = d;
|
||||
mout.update_data(d);
|
||||
console.log('stream data=', d);
|
||||
// console.log('stream data=', d);
|
||||
}
|
||||
chunk_ended(){
|
||||
if (! this.messages) {
|
||||
@ -255,6 +294,7 @@ bricks.LlmIO = class extends bricks.VBox {
|
||||
options:
|
||||
{
|
||||
user_icon:
|
||||
list_models_url:
|
||||
input_fields:
|
||||
input_view:
|
||||
output_view:
|
||||
@ -278,31 +318,158 @@ bricks.LlmIO = class extends bricks.VBox {
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.llmmodels = [];
|
||||
this.title_w = new bricks.HBox({cheight:2});
|
||||
this.i_w = new bricks.VBox({cheight:5});
|
||||
this.title_w = new bricks.HBox({cheight:3});
|
||||
var bottom_box = new bricks.HBox({cheight:3});
|
||||
this.i_w = new bricks.Icon({
|
||||
rate:2,
|
||||
url:bricks_resource('imgs/input.png'),
|
||||
margin:'14px',
|
||||
tip:'input data',
|
||||
css:'clickable'
|
||||
});
|
||||
this.nm_w = new bricks.Icon({
|
||||
rate:2,
|
||||
url:bricks_resource('imgs/add.png'),
|
||||
margin:'14px',
|
||||
tip:'add new model',
|
||||
css:'clickable'
|
||||
});
|
||||
bottom_box.add_widget(this.i_w);
|
||||
bottom_box.add_widget(this.nm_w);
|
||||
|
||||
this.nm_w.bind('click', this.open_search_models.bind(this));
|
||||
this.i_w.bind('click', this.open_input_widget.bind(this));
|
||||
this.o_w = new bricks.Filler({overflow:'auto'});
|
||||
this.add_widget(this.title_w);
|
||||
this.add_widget(this.o_w);
|
||||
if (this.models.length < 2 && this.tts_url){
|
||||
this.textvoice = true;
|
||||
}
|
||||
this.add_widget(this.i_w);
|
||||
this.add_widget(bottom_box);
|
||||
this.models.forEach( m =>{
|
||||
if (this.textvoice){
|
||||
m.textvoice = true;
|
||||
m.tts_url = this.tts_url;
|
||||
}
|
||||
var lm = new bricks.LlmModel(this, m);
|
||||
this.llmmodels.push(lm);
|
||||
var tw = lm.render_title();
|
||||
this.title_w.add_widget(tw);
|
||||
this.show_added_model(m);
|
||||
});
|
||||
this.build_input();
|
||||
}
|
||||
show_added_model(m){
|
||||
if (this.textvoice){
|
||||
m.textvoice = true;
|
||||
m.tts_url = this.tts_url;
|
||||
}
|
||||
var lm = new bricks.LlmModel(this, m);
|
||||
this.llmmodels.push(lm);
|
||||
var tw = lm.render_title();
|
||||
this.title_w.add_widget(tw);
|
||||
}
|
||||
async open_search_models(event){
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
var rect = this.showRectage();
|
||||
var opts = {
|
||||
title:"select model",
|
||||
icon:bricks_resource('imgs/search.png'),
|
||||
auto_destroy:true,
|
||||
auto_open:true,
|
||||
auto_dismiss:false,
|
||||
movable:true,
|
||||
top:rect.top + 'px',
|
||||
left:rect.left + 'px',
|
||||
width: rect.right - rect.left + 'px',
|
||||
height: rect.bottom - rect.top + 'px'
|
||||
}
|
||||
var w = new bricks.PopupWindow(opts);
|
||||
var sopts = {
|
||||
data_url:this.list_models_url,
|
||||
data_params:{
|
||||
mii:this.models[0].modelinstanceid,
|
||||
mti:this.models[0].modeltypeid
|
||||
},
|
||||
data_method:'POST',
|
||||
col_cwidth: 24,
|
||||
record_view:{
|
||||
widgettype:"VBox",
|
||||
options:{
|
||||
cheight:20,
|
||||
css:"card"
|
||||
},
|
||||
subwidgets:[
|
||||
{
|
||||
widgettype:"Title4",
|
||||
options:{
|
||||
text:"${name}"
|
||||
}
|
||||
},
|
||||
{
|
||||
widgettype:"Filler",
|
||||
options:{
|
||||
css:"scroll"
|
||||
},
|
||||
subwidgets:[
|
||||
{
|
||||
widgettype:"VBox",
|
||||
options:{
|
||||
css:"subcard"
|
||||
},
|
||||
subwidgets:[
|
||||
{
|
||||
widgettype:"Text",
|
||||
options:{
|
||||
text:"模型描述:${description}",
|
||||
wrap:true
|
||||
}
|
||||
},
|
||||
{
|
||||
widgettype:"Text",
|
||||
options:{
|
||||
text:"启用日期:${enable_date}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
var cols = new bricks.Cols(sopts);
|
||||
cols.bind('record_click', this.add_new_model.bind(this));
|
||||
cols.bind('record_click', w.dismiss.bind(w));
|
||||
w.add_widget(cols);
|
||||
w.open();
|
||||
}
|
||||
async add_new_model(event){
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.models.push(event.params);
|
||||
this.show_added_model(event.params);
|
||||
}
|
||||
async open_input_widget(event){
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
var rect = this.showRectage();
|
||||
var opts = {
|
||||
title:"input data",
|
||||
icon:bricks_resource('imgs/input.png'),
|
||||
auto_destroy:true,
|
||||
auto_open:true,
|
||||
auto_dismiss:false,
|
||||
movable:true,
|
||||
top:rect.top + 'px',
|
||||
left:rect.left + 'px',
|
||||
width: rect.right - rect.left + 'px',
|
||||
height: rect.bottom - rect.top + 'px'
|
||||
}
|
||||
var w = new bricks.PopupWindow(opts);
|
||||
var fopts = {
|
||||
fields:this.input_fields
|
||||
}
|
||||
var fw = new bricks.Form(fopts);
|
||||
fw.bind('submit', this.handle_input.bind(this));
|
||||
fw.bind('submit', w.destroy.bind(w));
|
||||
w.add_widget(fw);
|
||||
w.open();
|
||||
}
|
||||
async handle_input(event){
|
||||
var params = event.params;
|
||||
if (params.prompt)
|
||||
params.prompt = bricks.escapeSpecialChars(params.prompt);
|
||||
await this.show_input(params);
|
||||
for(var i=0;i<this.llmmodels.length;i++){
|
||||
var lm = this.llmmodels[i];
|
||||
@ -314,7 +481,9 @@ bricks.LlmIO = class extends bricks.VBox {
|
||||
}
|
||||
async show_input(params){
|
||||
var box = new bricks.HBox({width:'100%'});
|
||||
var w = await bricks.widgetBuild(this.input_view, this.o_w, params);
|
||||
var data = inputdata2dic(params);
|
||||
console.log('data=', data, 'input_view=', this.input_view);
|
||||
var w = await bricks.widgetBuild(this.input_view, this.o_w, data);
|
||||
w.set_css(this.msg_css||'user_msg');
|
||||
w.set_css('filler');
|
||||
var img = new bricks.Icon({rate:2,url:this.user_icon||bricks_resource('imgs/user.png')});
|
||||
@ -323,14 +492,6 @@ bricks.LlmIO = class extends bricks.VBox {
|
||||
box.add_widget(img);
|
||||
this.o_w.add_widget(box);
|
||||
}
|
||||
build_input(){
|
||||
var fopts = {
|
||||
fields:this.input_fields
|
||||
};
|
||||
var fw = new bricks.InlineForm(fopts);
|
||||
fw.bind('submit', this.handle_input.bind(this));
|
||||
this.i_w.add_widget(fw);
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('LlmIO', bricks.LlmIO);
|
||||
|
@ -96,13 +96,12 @@ bricks.LlmMsgBox = class extends bricks.HBox {
|
||||
var d = {
|
||||
messages:this.messages,
|
||||
mapi:this.mapi,
|
||||
prompt:prompt,
|
||||
model:this.model,
|
||||
}
|
||||
// console.log('messages=', this.messages, 'msg=', msg, 'umsg=', umsg);
|
||||
if (this.response_mode == 'stream') {
|
||||
var hr = new bricks.HttpResponseStream();
|
||||
var resp = await hr.post(this.url, {params:d});
|
||||
var resp = await hr.post(this.url, {data:d});
|
||||
this.responsed();
|
||||
await hr.handle_chunk(resp, this.chunk_response.bind(this));
|
||||
this.chunk_ended();
|
||||
|
0
bricks/markdown_viewer.js
Executable file → Normal file
28
bricks/menu.js
Executable file → Normal file
@ -11,6 +11,8 @@ bricks.Menu = class extends bricks.VBox {
|
||||
super(options);
|
||||
this.dom_element.style.display = "";
|
||||
this.dom_element.style.backgroundColor = options.bgcolor || "white";
|
||||
this.build_title();
|
||||
this.build_description();
|
||||
this.create_children(this, this.opts.items);
|
||||
this.bind('item_click', this.menu_clicked.bind(this));
|
||||
}
|
||||
@ -24,12 +26,19 @@ bricks.Menu = class extends bricks.VBox {
|
||||
console.log(event);
|
||||
let e = event.target;
|
||||
let opts = event.params;
|
||||
if (! opts.url){
|
||||
console.log('itme.url is null');
|
||||
this.dispatch('command', opts);
|
||||
return;
|
||||
var t;
|
||||
var popts;
|
||||
if (this.target == 'PopupWindow'){
|
||||
popts = bricks.get_popupwindow_default_options();
|
||||
bricks.extend(popts, this.popup_options || {});
|
||||
t = new bricks.PopupWindow(popts);
|
||||
} else if (this.target == 'Popup'){
|
||||
popts = bricks.get_popup_default_options();
|
||||
bricks.extend(popts, this.popup_options || {});
|
||||
t = new bricks.Popup(popts);
|
||||
} else {
|
||||
t = bricks.getWidgetById(this.target);
|
||||
}
|
||||
var t = bricks.getWidgetById(this.target);
|
||||
if (t){
|
||||
var desc = {
|
||||
"widgettype":"urlwidget",
|
||||
@ -38,7 +47,7 @@ bricks.Menu = class extends bricks.VBox {
|
||||
}
|
||||
}
|
||||
var w = await bricks.widgetBuild(desc, this);
|
||||
if (w){
|
||||
if (w && ! w.parent){
|
||||
t.clear_widgets();
|
||||
t.add_widget(w);
|
||||
} else {
|
||||
@ -47,6 +56,7 @@ bricks.Menu = class extends bricks.VBox {
|
||||
} else {
|
||||
console.log('menu_clicked():', this.target, 'not found')
|
||||
}
|
||||
this.dispatch('command', opts);
|
||||
}
|
||||
create_children(w, items){
|
||||
for (let i=0;i<items.length;i++){
|
||||
@ -59,13 +69,17 @@ bricks.Menu = class extends bricks.VBox {
|
||||
itw.add_widget(subw);
|
||||
itw.add_widget(w1);
|
||||
this.create_children(w1, item.items);
|
||||
subw.bind('click', w1.toggle_hide.bind(w1));
|
||||
subw.bind('click', this.items_toggle_hide.bind(this, w1));
|
||||
} else {
|
||||
subw.bind('click', this.regen_menuitem_event.bind(this, item))
|
||||
w.add_widget(subw);
|
||||
}
|
||||
}
|
||||
}
|
||||
items_toggle_hide(w, event){
|
||||
w.toggle_hide();
|
||||
event.stopPropagation();
|
||||
}
|
||||
create_menuitem(item){
|
||||
var w = new bricks.HBox({cheight:this.item_cheight||2});
|
||||
var iw, tw;
|
||||
|
@ -1,6 +1,6 @@
|
||||
var bricks = window.bricks || {};
|
||||
|
||||
bricks.Message = class extends bricks.Modal {
|
||||
bricks.Message = class extends bricks.PopupWindow {
|
||||
/*
|
||||
{
|
||||
title:
|
||||
@ -11,55 +11,41 @@ bricks.Message = class extends bricks.Modal {
|
||||
opts.auto_open = true;
|
||||
super(opts);
|
||||
this.create_message_widget();
|
||||
this.panel.set_css('message');
|
||||
this.set_css('message');
|
||||
}
|
||||
create_message_widget(){
|
||||
this.message_w = new bricks.VBox({width:'100%',height:'100%'});
|
||||
var w = new bricks.Filler();
|
||||
this.message_w.add_widget(w);
|
||||
this.add_widget(w);
|
||||
var w1 = new bricks.VScrollPanel({});
|
||||
w.add_widget(w1);
|
||||
var t = new bricks.Text({otext:this.opts.message,
|
||||
wrap:true,
|
||||
halign:'middle',
|
||||
i18n:true});
|
||||
w.add_widget(t);
|
||||
this.add_widget(this.message_w);
|
||||
w1.add_widget(t);
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Error = class extends bricks.Message {
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.panel.set_css('error');
|
||||
this.set_css('error');
|
||||
}
|
||||
}
|
||||
|
||||
bricks.show_error = function(opts){
|
||||
opts.cheight = opts.cheight || 9;
|
||||
opts.cwidth = opts.cwidth || 16;
|
||||
var w = new bricks.Error(opts);
|
||||
w.open();
|
||||
}
|
||||
|
||||
bricks.show_message = function(opts){
|
||||
opts.cheight = opts.cheight || 9;
|
||||
opts.cwidth = opts.cwidth || 16;
|
||||
var w = new bricks.Message(opts);
|
||||
w.open();
|
||||
}
|
||||
|
||||
bricks.PopupForm = class extends bricks.VBox {
|
||||
/*
|
||||
{
|
||||
form:{
|
||||
}
|
||||
}
|
||||
*/
|
||||
constructor(options){
|
||||
super(options);
|
||||
this.form = new bricks.Form(this.opts.form);
|
||||
this.add_widget(this.form);
|
||||
this.form.bind('submit', this.close_popup.bind(this));
|
||||
this.form.bind('discard', this.close_popup.bind(this));
|
||||
}
|
||||
close_popup(e){
|
||||
this.dismiss();
|
||||
}
|
||||
}
|
||||
bricks.Factory.register('Message', bricks.Message);
|
||||
bricks.Factory.register('Error', bricks.Error);
|
||||
|
0
bricks/minify_tools.txt
Executable file → Normal file
5
bricks/modal.js
Executable file → Normal file
@ -167,7 +167,7 @@ bricks.Modal = class extends bricks.BaseModal {
|
||||
*/
|
||||
}
|
||||
|
||||
bricks.ModalForm = class extends bricks.Modal {
|
||||
bricks.ModalForm = class extends bricks.PopupWindow {
|
||||
/*
|
||||
{
|
||||
auto_open:
|
||||
@ -189,6 +189,9 @@ bricks.ModalForm = class extends bricks.Modal {
|
||||
super(opts);
|
||||
this.build_form();
|
||||
}
|
||||
_getValue(){
|
||||
return this.form._getValue();
|
||||
}
|
||||
getValue(){
|
||||
return this.form.getValue();
|
||||
}
|
||||
|
0
bricks/myoperator.js
Executable file → Normal file
99
bricks/period.js
Normal file
@ -0,0 +1,99 @@
|
||||
var bricks = window.bricks || {};
|
||||
bricks.str2date = function(sdate){
|
||||
let [year, month, day] = sdate.split("-");
|
||||
var dateObj = new Date(year, month - 1, day);
|
||||
return dateObj;
|
||||
}
|
||||
bricks.date2str = function(date){
|
||||
let year = date.getFullYear();
|
||||
let month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
let day = String(date.getDate()).padStart(2, '0');
|
||||
let formattedDate = `${year}-${month}-${day}`;
|
||||
return formattedDate;
|
||||
}
|
||||
bricks.addMonths = function(dateObj, months){
|
||||
var newDate = new Date(dateObj);
|
||||
newDate.setMonth(newDate.getMonth() + months);
|
||||
return newDate;
|
||||
}
|
||||
bricks.addYears = function(dateObj, years){
|
||||
const newDate = new Date(dateObj);
|
||||
newDate.setYear(newDate.getYear() + years);
|
||||
return newDate;
|
||||
}
|
||||
bricks.addDays = function(dateObj, days){
|
||||
var newdate = new Date(dateObj);
|
||||
newdate.setDate(newdate.getDate() + days);
|
||||
return newdate;
|
||||
}
|
||||
|
||||
bricks.PeriodDays = class extends bricks.HBox {
|
||||
/*
|
||||
{
|
||||
start_date:
|
||||
end_date:
|
||||
step_type: 'days', 'months', 'years'
|
||||
step_cnt:
|
||||
title:'',
|
||||
splitter:' -- '
|
||||
}
|
||||
event: 'changed';
|
||||
*/
|
||||
constructor(opts){
|
||||
opts.splitter = opts.splitter || ' 至 ';
|
||||
opts.step_cnt = opts.step_cnt || 1;
|
||||
super(opts);
|
||||
this.start_w = new bricks.Text({
|
||||
text:opts.start_date
|
||||
});
|
||||
this.end_w = new bricks.Text({
|
||||
text:opts.end_date
|
||||
});
|
||||
this.start_w.set_css('clickable');
|
||||
this.end_w.set_css('clickable');
|
||||
this.start_w.bind('click', this.step_back.bind(this));
|
||||
this.end_w.bind('click', this.step_forward.bind(this));
|
||||
if (this.title){
|
||||
this.add_widget(new bricks.Text({otext:this.title, i18n:true}));
|
||||
}
|
||||
this.add_widget(this.start_w);
|
||||
this.add_widget(new bricks.Text({
|
||||
otext:this.splitter,
|
||||
i18n:true
|
||||
}));
|
||||
this.add_widget(this.end_w);
|
||||
}
|
||||
date_add(strdate, step_cnt, step_type){
|
||||
var date = bricks.str2date(strdate);
|
||||
switch(step_type){
|
||||
case 'years':
|
||||
var nd = bricks.addYears(date, step_cnt);
|
||||
return bricks.date2str(nd);
|
||||
break;
|
||||
case 'months':
|
||||
var nd = bricks.addMonths(date, step_cnt);
|
||||
return bricks.date2str(nd);
|
||||
break;
|
||||
default:
|
||||
var nd = bricks.addDays(date, step_cnt);
|
||||
return bricks.date2str(nd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
step_back(){
|
||||
this.start_date = this.date_add(this.start_date, -this.step_cnt, this.step_type);
|
||||
this.end_date = this.date_add(this.end_date, -this.step_cnt, this.step_type);
|
||||
this.start_w.set_text(this.start_date);
|
||||
this.end_w.set_text(this.end_date);
|
||||
this.dispatch('changed', {start_date:this.start_date, end_date:this.end_date});
|
||||
}
|
||||
step_forward(){
|
||||
this.start_date = this.date_add(this.start_date, this.step_cnt, this.step_type);
|
||||
this.end_date = this.date_add(this.end_date, this.step_cnt, this.step_type);
|
||||
this.start_w.set_text(this.start_date);
|
||||
this.end_w.set_text(this.end_date);
|
||||
this.dispatch('changed', {start_date:this.start_date, end_date:this.end_date});
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('PeriodDays', bricks.PeriodDays);
|
491
bricks/popup.js
@ -1,87 +1,482 @@
|
||||
var bricks = window.bricks || {};
|
||||
|
||||
bricks.get_popup_default_options = function(){
|
||||
return {
|
||||
timeout:0,
|
||||
archor:'cc',
|
||||
auto_open:true,
|
||||
auto_dismiss:true,
|
||||
auto_destroy:true,
|
||||
movable:true,
|
||||
resizable:false,
|
||||
modal:true
|
||||
}
|
||||
}
|
||||
bricks.Popup = class extends bricks.VBox {
|
||||
/*
|
||||
{
|
||||
timeout:0
|
||||
auto_open:
|
||||
archor:one of ['tl', 'tc', 'tr', 'cl', 'cc', 'cr', 'bl','bc', 'br']
|
||||
widget:null for bricks.Body, string value for widget's id or a widget object;
|
||||
auto_dismiss:
|
||||
auto_open:boolean
|
||||
auto_dismiss:boolean
|
||||
auto_destroy:boolean
|
||||
movable:boolean
|
||||
dismiss_event:
|
||||
resizable:boolean
|
||||
modal:boolean
|
||||
content:{}
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.no_opened = true;
|
||||
this.auto_task = null;
|
||||
this.issub = false;
|
||||
this.set_css('modal');
|
||||
const zindex = bricks.app.new_zindex();
|
||||
this.set_style('zIndex', zindex);
|
||||
this.opened = false;
|
||||
this.set_css('popup');
|
||||
this.bring_to_top();
|
||||
this.content_box = new bricks.VBox({height:'100%',width:'100%'});
|
||||
super.add_widget(this.content_box);
|
||||
this.content_w = this.content_box;
|
||||
this.moving_w = this;
|
||||
if (this.auto_dismiss){
|
||||
bricks.Body.bind('click', this.click_outside.bind(this));
|
||||
}
|
||||
this.target_w = bricks.Body;
|
||||
this.moving_status = false;
|
||||
if (this.movable){
|
||||
this.setup_movable();
|
||||
// console.log('movable ...');
|
||||
}
|
||||
if (this.resizable){
|
||||
this.setup_resizable();
|
||||
}
|
||||
this.set_style('display', 'none');
|
||||
bricks.Body.add_widget(this);
|
||||
this.bind('click', this.bring_to_top.bind(this));
|
||||
if (this.auto_open){
|
||||
this.open();
|
||||
}
|
||||
if (this.content){
|
||||
this.bind('opened', this.load_content.bind(this))
|
||||
}
|
||||
}
|
||||
async load_content(){
|
||||
var w = await bricks.widgetBuild(this.content, this);
|
||||
if (w){
|
||||
this.set_dismiss_events(w);
|
||||
this.content_w.clear_widgets();
|
||||
this.content_w.add_widget(w);
|
||||
}
|
||||
}
|
||||
set_dismiss_events(w){
|
||||
if (!this.dismiss_events) return;
|
||||
this.dismiss_events.forEach(ename => {
|
||||
w.bind(ename, this.destroy.bind(this));
|
||||
});
|
||||
}
|
||||
bring_to_top(){
|
||||
if (this == bricks.app.toppopup){
|
||||
return;
|
||||
}
|
||||
if (bricks.app.toppopup)
|
||||
bricks.app.toppopup.set_css('toppopup', true);
|
||||
this.zindex = bricks.app.new_zindex();
|
||||
this.set_style('zIndex', this.zindex);
|
||||
console.log('this.zindex=', this.zindex, 'app.zindex=', bricks.app.zindex);
|
||||
this.set_css('toppopup');
|
||||
bricks.app.toppopup = this;
|
||||
}
|
||||
popup_from_widget(from_w){
|
||||
var myrect = this.showRectage();
|
||||
var rect = from_w.showRectage();
|
||||
var x,y;
|
||||
var ox, oy;
|
||||
ox = (rect.right - rect.left) / 2 + rect.left;
|
||||
oy = (rect.bottom - rect.top) / 2 + rect.top;
|
||||
if (ox < bricks.app.screenWidth() / 2) {
|
||||
x = rect.right + 3;
|
||||
if (x + (myrect.right - myrect.left) > bricks.app.screenWidth()){
|
||||
x = bricks.app.screenWidth() - (myrect.right - myrect.left);
|
||||
}
|
||||
} else {
|
||||
x = rect.left - (myrect.right - myrect.left) - 3
|
||||
if (x < 0) x = 0;
|
||||
}
|
||||
if (oy < bricks.app.screenHeight() / 2){
|
||||
y = rect.bottom + 3;
|
||||
if (y + (myrect.bottom - myrect.top) > bricks.app.screenHeight()){
|
||||
y = bricks.app.screenHeight() - (myrect.bottom - myrect.top);
|
||||
}
|
||||
} else {
|
||||
y = rect.bottom - (myrect.bottom - myrect.top) - 3
|
||||
if (y < 0) y = 0;
|
||||
}
|
||||
this.set_style('top', y + 'px');
|
||||
this.set_style('left', x + 'px');
|
||||
}
|
||||
setup_resizable(){
|
||||
this.resizable_w = new bricks.Icon({rate:1.5, url:bricks_resource('imgs/right-bottom-triangle.png')});
|
||||
super.add_widget(this.resizable_w);
|
||||
this.resizable_w.set_css('resizebox');
|
||||
this.resizable_w.bind('mousedown', this.resize_start_pos.bind(this));
|
||||
bricks.Body.bind('mousemove', this.resizing.bind(this));
|
||||
bricks.Body.bind('mouseup', this.stop_resizing.bind(this));
|
||||
}
|
||||
resize_start_pos(e){
|
||||
if (e.target != this.resizable_w.dom_element)
|
||||
{
|
||||
// console.log('not event target');
|
||||
return;
|
||||
}
|
||||
var rect = this.showRectage();
|
||||
this.resize_status = true;
|
||||
this.s_offsetX = e.clientX;
|
||||
this.s_offsetY = e.clientY;
|
||||
this.s_width = rect.width;
|
||||
this.s_height = rect.height;
|
||||
e.preventDefault();
|
||||
// console.log('resize_start_pos():', this.s_width, this.s_height, this.s_offsetX, this.s_offsetY);
|
||||
}
|
||||
resizing(e){
|
||||
if (e.target != this.resizable_w.dom_element){
|
||||
this.stop_resizing();
|
||||
// console.log('resizing(): not event target');
|
||||
return;
|
||||
}
|
||||
if (!this.resize_status){
|
||||
// console.log('resizing(): not in resize status');
|
||||
return;
|
||||
}
|
||||
var cx, cy;
|
||||
cx = this.s_width + e.clientX - this.s_offsetX;
|
||||
cy = this.s_height + e.clientY - this.s_offsetY;
|
||||
this.set_style('width', cx + 'px');
|
||||
this.set_style('height', cy + 'px');
|
||||
// console.log('resizing():', this.resize_status, cx, cy);
|
||||
e.preventDefault();
|
||||
}
|
||||
positify_tl(){
|
||||
var rect, w, h, t, l;
|
||||
if (this.top && this.left){
|
||||
this.set_style('top', this.top);
|
||||
this.set_style('left', this.left);
|
||||
return;
|
||||
}
|
||||
rect = bricks.app.showRectage();
|
||||
if (this.cwidth && this.cwidth > 0){
|
||||
w = this.cwidth * bricks.app.charsize;
|
||||
} else if (this.width){
|
||||
if (this.width.endsWith('px')){
|
||||
w = parseFloat(this.width);
|
||||
} else {
|
||||
w = parseFloat(this.width) * rect.width / 100;
|
||||
}
|
||||
} else {
|
||||
w = rect.width * 0.8;
|
||||
}
|
||||
if (this.cheight && this.cheight > 0){
|
||||
h = this.cheight * bricks.app.charsize;
|
||||
} else if (this.height){
|
||||
if (this.height.endsWith('px')){
|
||||
h = parseFloat(this.height);
|
||||
} else {
|
||||
h = parseFloat(this.height) * rect.height / 100;
|
||||
}
|
||||
} else {
|
||||
h = rect.height * 0.8;
|
||||
}
|
||||
var archor = this.archor || 'cc';
|
||||
switch(archor[0]){
|
||||
case 't':
|
||||
t = 0;
|
||||
break;
|
||||
case 'c':
|
||||
t = (rect.height - h) / 2;
|
||||
break;
|
||||
case 'b':
|
||||
t = rect.height - h;
|
||||
break;
|
||||
default:
|
||||
t = (rect.height - h) / 2;
|
||||
break;
|
||||
}
|
||||
switch(archor[1]){
|
||||
case 'l':
|
||||
l = 0;
|
||||
break;
|
||||
case 'c':
|
||||
l = (rect.width - w) / 2;
|
||||
break;
|
||||
case 'r':
|
||||
l = rect.width - w;
|
||||
break;
|
||||
default:
|
||||
l = (rect.width - w) / 2;
|
||||
break;
|
||||
}
|
||||
this.set_style('top', t + 'px');
|
||||
this.set_style('left', l + 'px');
|
||||
return {
|
||||
top:t,
|
||||
left:l
|
||||
}
|
||||
}
|
||||
|
||||
stop_resizing(e){
|
||||
this.resize_status = false;
|
||||
bricks.Body.unbind('mousemove', this.resizing.bind(this));
|
||||
bricks.Body.unbind('mouseup', this.stop_resizing.bind(this));
|
||||
// console.log('stop_resizing():', this.resize_status);
|
||||
}
|
||||
|
||||
setup_movable(){
|
||||
this.moving_w.bind('mousedown', this.rec_start_pos.bind(this));
|
||||
this.moving_w.bind('touchstart', this.rec_start_pos.bind(this));
|
||||
}
|
||||
rec_start_pos(e){
|
||||
if (e.target != this.moving_w.dom_element)
|
||||
{
|
||||
// console.log('moving star failed', e.target, this.moving_w.dom_element, 'difference ...');
|
||||
return;
|
||||
}
|
||||
this.moving_status = true;
|
||||
var rect = this.showRectage();
|
||||
this.offsetX = e.clientX - rect.left;
|
||||
this.offsetY = e.clientY - rect.top;
|
||||
// console.log(rect, '========', this.offsetX, this.offsetY, e.clientX, e.clientY);
|
||||
|
||||
bricks.Body.bind('mouseup', this.stop_moving.bind(this));
|
||||
bricks.Body.bind('touchend', this.stop_moving.bind(this));
|
||||
this.moving_w.bind('mousemove', this.moving.bind(this));
|
||||
this.moving_w.bind('touchmove', this.moving.bind(this));
|
||||
e.preventDefault();
|
||||
// console.log('moving started ...');
|
||||
}
|
||||
moving(e){
|
||||
if (e.target != this.moving_w.dom_element){
|
||||
// console.log('moving failed', e.target, this.moving_w.dom_element, 'difference ...');
|
||||
this.stop_moving();
|
||||
}
|
||||
if (!this.moving_status){
|
||||
// console.log('moving failed', 'not started ...');
|
||||
return;
|
||||
}
|
||||
var cx, cy;
|
||||
cx = e.clientX - this.offsetX;
|
||||
cy = e.clientY - this.offsetY;
|
||||
// console.log(cx, cy, e.clientX, e.clientY, this.offsetX, this.offsetY, '==========');
|
||||
this.set_style('left', cx + 'px');
|
||||
this.set_style('top', cy + 'px');
|
||||
e.preventDefault();
|
||||
}
|
||||
stop_moving(e){
|
||||
// console.log('stop moving ....');
|
||||
this.moving_status = false;
|
||||
this.moving_w.unbind('mousemove', this.moving.bind(this));
|
||||
this.moving_w.unbind('touchmove', this.moving.bind(this));
|
||||
bricks.Body.unbind('mouseup', this.stop_moving.bind(this));
|
||||
bricks.Body.unbind('touchend', this.stop_moving.bind(this));
|
||||
}
|
||||
click_outside(event){
|
||||
if (event.target != this.dom_element){
|
||||
this.dismiss();
|
||||
}
|
||||
}
|
||||
add_widget(w, index){
|
||||
super.add_widget(w, index);
|
||||
if (this.auto_open){
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
transform2screen_at(rect, lt){
|
||||
var screen_rect = bricks.Body.showRectage();
|
||||
top = rect.top + parseInt(lt.y) / 100 * rect.height;
|
||||
left = rect.left + parseInt(lt.x) / 100 * rect.width;
|
||||
return {
|
||||
top:top + 'px',
|
||||
left:left + 'px'
|
||||
}
|
||||
}
|
||||
convert_width(){
|
||||
|
||||
}
|
||||
open(){
|
||||
var rect;
|
||||
|
||||
if (this.widget instanceof bricks.JsWidget){
|
||||
rect = this.widget.showRectage()
|
||||
this.issub = true;
|
||||
} else if (this.widget instanceof String){
|
||||
var w = bricks.getWidgetById(this.widget, bricks.Body);
|
||||
if (!w){
|
||||
ithis.issub = true
|
||||
rect = bricks.Body.showRectage();
|
||||
}
|
||||
} else {
|
||||
rect = bricks.Body.showRectage();
|
||||
if (!this.parent){
|
||||
bricks.app.add_widget(this);
|
||||
}
|
||||
var lt = archor_at(this.archor);
|
||||
if (this.issub){
|
||||
lt = this.transform2screen_at(rect, lt);
|
||||
if (this.width && this.width.endsWith('%')){
|
||||
this.set_style('width', parseFloat(rect.width) * parseFloat(this.width) + 'px');
|
||||
}
|
||||
if (this.height && this.height.endsWith('%')){
|
||||
this.set_style('height', parseFloat(rect.height) * parseFloat(this.height) + 'px');
|
||||
}
|
||||
var rect, w, h;
|
||||
if (this.opened) {
|
||||
return;
|
||||
}
|
||||
this.set_style('top',lt.top);
|
||||
this.set_style('left',lt.left);
|
||||
this.opened = true;
|
||||
if (this.no_opened){
|
||||
if (this.widget instanceof bricks.JsWidget){
|
||||
this.target_w = this.widget;
|
||||
this.issub = true;
|
||||
} else {
|
||||
var w = bricks.getWidgetById(this.widget, bricks.Body);
|
||||
if (w){
|
||||
this.issub = true
|
||||
this.target_w = w;
|
||||
}
|
||||
}
|
||||
this.positify_tl()
|
||||
}
|
||||
this.no_opened = false;
|
||||
this.set_style('display', 'block');
|
||||
this.dispatch('opened');
|
||||
if (this.timeout > 0){
|
||||
this.auto_task = schedule_once(this.auto_dismiss.bind(this), this.timeout)
|
||||
this.auto_task = schedule_once(this.dismiss.bind(this), this.timeout)
|
||||
}
|
||||
if (this.opts.modal && this.opts.widget){
|
||||
this.target_w.disabled(true);
|
||||
}
|
||||
this.bring_to_top();
|
||||
}
|
||||
dismiss(){
|
||||
if (! this.opened) return;
|
||||
if (this.opts.modal){
|
||||
this.target_w.disabled(false);
|
||||
}
|
||||
this.opened = false;
|
||||
if (this.auto_task){
|
||||
this.auto_task.cancel();
|
||||
this.auto_task = null;
|
||||
}
|
||||
this.set_style('display','none');
|
||||
this.dispatch('dismissed');
|
||||
if (this.auto_destroy){
|
||||
this.destroy();
|
||||
this.dispatch('destroy');
|
||||
}
|
||||
}
|
||||
destroy(){
|
||||
if (this.opened){
|
||||
this.dismiss();
|
||||
}
|
||||
if (this.parent){
|
||||
this.parent.remove_widget(this);
|
||||
this.parent = null;
|
||||
}
|
||||
}
|
||||
add_widget(w, i){
|
||||
this.set_dismiss_events(w);
|
||||
this.content_w.add_widget(w, i);
|
||||
if (this.auto_open){
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
remove_widget(w){
|
||||
return this.content_w.remove_widget(w);
|
||||
}
|
||||
clear_widgets(){
|
||||
return this.content_w.clear_widgets();
|
||||
}
|
||||
}
|
||||
|
||||
bricks.get_popupwindow_default_options = function(){
|
||||
return {
|
||||
timeout:0,
|
||||
archor:'cc',
|
||||
auto_open:true,
|
||||
auto_dismiss:true,
|
||||
auto_destroy:true,
|
||||
movable:true,
|
||||
resizable:true,
|
||||
modal:true
|
||||
}
|
||||
}
|
||||
bricks.PopupWindow = class extends bricks.Popup {
|
||||
/*
|
||||
{
|
||||
title:
|
||||
icon:
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
opts.movable = true;
|
||||
opts.resizable = true;
|
||||
var ao = opts.auto_open;
|
||||
opts.auto_open = false
|
||||
opts.auto_dismiss = false;
|
||||
opts.auto_destroy = false;
|
||||
super(opts);
|
||||
this.auto_open = ao;
|
||||
this.title_bar = new bricks.HBox({css:'titlebar', cheight:2, width:'100%'});
|
||||
this.moving_w = this.title_bar;
|
||||
this.add_widget(this.title_bar);
|
||||
this.build_title_bar();
|
||||
var filler = new bricks.Filler({});
|
||||
this.add_widget(filler)
|
||||
|
||||
this.content_w = new bricks.Layout({height:'100%', width:'100%'});
|
||||
this.content_w.set_css('flexbox');
|
||||
filler.add_widget(this.content_w);
|
||||
if (this.auto_open){
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
build_title_bar(){
|
||||
var icon = new bricks.Icon({
|
||||
rate:this.opts.rate,
|
||||
url:this.opts.icon || bricks_resource('imgs/app.png')
|
||||
});
|
||||
this.title_bar.add_widget(icon);
|
||||
this.tb_w = new bricks.IconBar( {
|
||||
cheight:1,
|
||||
margin:'5px',
|
||||
rate:0.8,
|
||||
tools:[
|
||||
{
|
||||
name:'delete',
|
||||
icon:bricks_resource('imgs/app_delete.png'),
|
||||
dynsize:true,
|
||||
tip:'Destroy this window'
|
||||
},
|
||||
{
|
||||
name:'minimax',
|
||||
icon:bricks_resource('imgs/app_minimax.png'),
|
||||
dynsize:true,
|
||||
tip:'minimax this window'
|
||||
},
|
||||
{
|
||||
name:'fullscreen',
|
||||
icon:bricks_resource('imgs/app_fullscreen.png'),
|
||||
dynsize:true,
|
||||
tip:'fullscreen this window'
|
||||
}
|
||||
]
|
||||
});
|
||||
this.title_bar.add_widget(this.tb_w);
|
||||
this.tb_w.bind('delete', this.destroy.bind(this));
|
||||
this.tb_w.bind('minimax', this.dismiss.bind(this));
|
||||
this.tb_w.bind('fullscreen', this.enter_fullscreen.bind(this));
|
||||
if (this.title){
|
||||
this.title_w = new bricks.Text({text:this.title});
|
||||
this.title_bar.add_widget(this.title_w);
|
||||
}
|
||||
}
|
||||
set_title(txt){
|
||||
if (this.title_w){
|
||||
this.title_w.set_text(txt);
|
||||
}
|
||||
}
|
||||
open(){
|
||||
var f = bricks.app.docks.find(o => {
|
||||
if (o == this){
|
||||
}
|
||||
});
|
||||
if (! f){
|
||||
bricks.app.docks.push(this);
|
||||
}
|
||||
super.open();
|
||||
}
|
||||
dismiss(){
|
||||
var f = bricks.app.docks.find(o=> o===this);
|
||||
if (!f){
|
||||
bricks.app.docks.push(this);
|
||||
}
|
||||
super.dismiss()
|
||||
}
|
||||
}
|
||||
bricks.Dock = class extends bricks.HBox {
|
||||
constructor(opts){
|
||||
opts.cheight = opts.cheight || 2;
|
||||
opts.width = opts.width || "80%";
|
||||
super(opts);
|
||||
this.set_css('scroll');
|
||||
this.pw = [];
|
||||
}
|
||||
add_popupwindow(pw){
|
||||
var info = pw.get_window_info();
|
||||
|
||||
}
|
||||
del_popupwindow(pw){
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('Popup', bricks.Popup);
|
||||
bricks.Factory.register('PopupWindow', bricks.PopupWindow);
|
||||
|
24
bricks/progressbar.js
Normal file
@ -0,0 +1,24 @@
|
||||
var bricks = window.bricks || {};
|
||||
|
||||
bricks.ProgressBar = class extends bricks.HBox {
|
||||
/*
|
||||
options:
|
||||
total_value
|
||||
bar_cwidth
|
||||
event:
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.set_css('progress-container');
|
||||
this.text_w = new bricks.Text({text:'0%', cheight:this.bar_cwidth||2});
|
||||
this.text_w.set_css('progress-bar')
|
||||
this.add_widget(this.text_w);
|
||||
}
|
||||
set_value(v){
|
||||
var pzt = (current / total) * 100;
|
||||
pzt = Math.max(0, Math.min(100, percentage));
|
||||
this.text_w.set_style('width', pzt + '%')
|
||||
}
|
||||
}
|
||||
bricks.Factory.register('ProgressBar', bricks.ProgressBar);
|
||||
|
0
bricks/registerfunction.js
Executable file → Normal file
11
bricks/splitter.js
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
var bricks = window.bricks || {};
|
||||
bricks.Splitter = class extends bricks.JsWidget {
|
||||
constructor(ops){
|
||||
super({});
|
||||
}
|
||||
create(){
|
||||
this.dom_element = this._create('hr')
|
||||
}
|
||||
}
|
||||
bricks.Factory.register('Splitter', bricks.Splitter);
|
0
bricks/tab.js
Executable file → Normal file
@ -26,7 +26,6 @@ bricks.Tabular = class extends bricks.DataViewer {
|
||||
return r;
|
||||
}
|
||||
var row = new bricks.VBox({
|
||||
css:'tabular-row'
|
||||
});
|
||||
row.add_widget(r);
|
||||
var content = new bricks.VBox({
|
||||
@ -60,13 +59,16 @@ bricks.Tabular = class extends bricks.DataViewer {
|
||||
} else {
|
||||
row.set_css('tabular-row-selected');
|
||||
}
|
||||
this.dispatch('row_selected', row.user_data);
|
||||
}
|
||||
}
|
||||
async toggle_content(row, flag){
|
||||
if (flag){
|
||||
row.content_widget.show();
|
||||
row.content_widget.clear_widgets();
|
||||
var w = await bricks.widgetBuild(this.content_view, row.content_widget, row.user_data);
|
||||
var desc = objcopy(this.content_view);
|
||||
desc = bricks.apply_data(desc, row.user_data);
|
||||
var w = await bricks.widgetBuild(desc, row.content_widget);
|
||||
if (w){
|
||||
row.content_widget.add_widget(w);
|
||||
}
|
||||
@ -97,10 +99,13 @@ bricks.Tabular = class extends bricks.DataViewer {
|
||||
header = false;
|
||||
}
|
||||
var dr = new bricks.DataRow(options);
|
||||
dr.set_css('tabular-row');
|
||||
dr.render(header);
|
||||
/*
|
||||
dr.event_names.forEach(e => {
|
||||
dr.toolbar_w.bind(e, this.record_event_handle.bind(this, e, record, dr));
|
||||
});
|
||||
*/
|
||||
dr.bind('check_changed', this.record_check_changed.bind(this));
|
||||
return dr;
|
||||
}
|
||||
@ -109,7 +114,7 @@ bricks.Tabular = class extends bricks.DataViewer {
|
||||
this.dispatch('row_check_changed', event.params.user_data);
|
||||
}
|
||||
async renew_record_view(form, row){
|
||||
var d = form.getValue();
|
||||
var d = form._getValue();
|
||||
var record = bricks.extend(row.user_data, d);
|
||||
if (this.content_view){
|
||||
row.rec_widget.renew(record);
|
||||
|
1
bricks/toolbar.js
Executable file → Normal file
@ -26,6 +26,7 @@ bricks.Toolbar = class extends bricks.Layout {
|
||||
this.bar = new bricks.HScrollPanel(options);
|
||||
this.dom_element.classList.add('htoolbar')
|
||||
}
|
||||
this.bar.enable_key_select()
|
||||
this.add_widget(this.bar);
|
||||
this.clicked_btn = null;
|
||||
this.preffix_css = this.opts.css || 'toolbar';
|
||||
|
58
bricks/tree.js
Executable file → Normal file
@ -133,9 +133,8 @@ bricks.TreeNode = class extends bricks.VBox {
|
||||
if (this.view_w){
|
||||
widget.add_widget(this.view_w);
|
||||
}
|
||||
} else {
|
||||
this.str_w.set_text(this.user_data[this.tree.opts.textField]);
|
||||
}
|
||||
this.str_w.set_text(this.user_data[this.tree.opts.textField]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,6 +170,8 @@ bricks.Tree = class extends bricks.VScrollPanel {
|
||||
this.row_height = this.opts.row_height || '35px';
|
||||
this.multitype_tree = this.opts.multitype_tree||false;
|
||||
this.selected_node = null;
|
||||
this.build_title();
|
||||
this.build_description();
|
||||
this.create_toolbar();
|
||||
this.checked_data = [];
|
||||
this.container = new bricks.VBox({
|
||||
@ -209,14 +210,14 @@ bricks.Tree = class extends bricks.VScrollPanel {
|
||||
create_toolbar(){
|
||||
var toolbar = bricks.extend({}, this.toolbar);
|
||||
var tools = [];
|
||||
if (toolbar.tools){
|
||||
toolbar.tools.forEach(f => tools.push(f));
|
||||
}
|
||||
if (this.editable){
|
||||
tools.push({icon:bricks_resource('imgs/add.png'), name:'add'});
|
||||
tools.push({icon:bricks_resource('imgs/update.png'), name:'update'});
|
||||
tools.push({icon:bricks_resource('imgs/delete.png'), name:'delete'});
|
||||
}
|
||||
if (toolbar.tools){
|
||||
toolbar.tools.forEach(f => tools.push(f));
|
||||
}
|
||||
if (tools.length == 0){
|
||||
return;
|
||||
}
|
||||
@ -230,7 +231,7 @@ bricks.Tree = class extends bricks.VScrollPanel {
|
||||
switch (opts.name){
|
||||
case 'add':
|
||||
this.add_new_node();
|
||||
breaks;
|
||||
break;
|
||||
case 'delete':
|
||||
this.delete_node();
|
||||
break;
|
||||
@ -238,16 +239,17 @@ bricks.Tree = class extends bricks.VScrollPanel {
|
||||
this.update_node();
|
||||
break;
|
||||
default:
|
||||
if ((opts.selected_data || opts.checked_data) && ! this.selected_node){
|
||||
w = new bricks.Error({title:'Error', message:'No selected node found'});
|
||||
w.open();
|
||||
return;
|
||||
}
|
||||
console.log('opts=', opts);
|
||||
var d = null;
|
||||
if (opts.checked_data){
|
||||
d = {
|
||||
checked_data:JSON.stringify(this.checked_data)
|
||||
}
|
||||
} else if (opts.selected_node){
|
||||
d = {
|
||||
selected_data:JSON.stringify(this.selected_node.user_data)
|
||||
}
|
||||
d = this.checked_data
|
||||
} else if (opts.selected_data){
|
||||
d = this.selected_node.user_data
|
||||
}
|
||||
this.dispatch(opts.name, d);
|
||||
break;
|
||||
@ -269,7 +271,11 @@ bricks.Tree = class extends bricks.VScrollPanel {
|
||||
var node = this;
|
||||
if (this.selected_node){
|
||||
node = this.selected_node;
|
||||
d[this.parentField] = node.get_id();
|
||||
if (d instanceof FormData){
|
||||
d.append(this.parentField, node.get_id());
|
||||
} else {
|
||||
d[this.parentField] = node.get_id();
|
||||
}
|
||||
}
|
||||
if (this.editable.add_url){
|
||||
var jc = new bricks.HttpJson()
|
||||
@ -316,6 +322,8 @@ bricks.Tree = class extends bricks.VScrollPanel {
|
||||
return;
|
||||
}
|
||||
var w = new bricks.Conform({
|
||||
cwidth:16,
|
||||
cheight:9,
|
||||
title:'Delete node',
|
||||
message:'Please conform delete selected node'
|
||||
});
|
||||
@ -383,24 +391,34 @@ bricks.Tree = class extends bricks.VScrollPanel {
|
||||
async update_node_inputed(event){
|
||||
var d = event.params;
|
||||
var node = this.selected_node;
|
||||
d[this.idField] = node.get_id();
|
||||
if (d instanceof FormData){
|
||||
d.append(this.idField, node.get_id());
|
||||
} else {
|
||||
d[this.idField] = node.get_id();
|
||||
}
|
||||
if(this.editable.update_url){
|
||||
var jc = new bricks.HttpJson()
|
||||
var desc = await jc.post(this.editable.update_url, {params:d});
|
||||
if (desc.widgettype == 'Message'){
|
||||
await this.update_node_data(node, d);
|
||||
var o = formdata2object(d);
|
||||
await this.update_node_data(node, o);
|
||||
}
|
||||
var w = await bricks.widgetBuild(desc, this);
|
||||
w.open();
|
||||
} else {
|
||||
await this.update_node_data(node, d);
|
||||
var o = formdata2object(d);
|
||||
await this.update_node_data(node, o);
|
||||
}
|
||||
}
|
||||
|
||||
async update_node_data(node, data){
|
||||
for (var name in Object.keys(data)){
|
||||
node.user_data[name] = data[name];
|
||||
}
|
||||
var data_keys = Object.keys(node.user_data);
|
||||
Object.keys(data).forEach(k => {
|
||||
if (data_keys.includes(k)){
|
||||
console.log(node.user_data[k], ':', k, ':', data[k]);
|
||||
node.user_data[k] = data[k];
|
||||
}
|
||||
});
|
||||
await node.update_content();
|
||||
}
|
||||
|
||||
|
0
bricks/uitypesdef.js
Executable file → Normal file
291
bricks/utils.js
Executable file → Normal file
@ -1,22 +1,104 @@
|
||||
var bricks = window.bricks || {};
|
||||
bricks.bug = false;
|
||||
|
||||
bricks.formdata_copy = function(fd){
|
||||
var cfd = new FormData();
|
||||
|
||||
// 遍历 originalFormData 中的所有条目并添加到 clonedFormData 中
|
||||
for (var pair of fd.entries()) {
|
||||
cfd.append(pair[0], pair[1]);
|
||||
}
|
||||
return cfd;
|
||||
}
|
||||
|
||||
bricks.map = function(data_source, mapping, need_others){
|
||||
ret = {};
|
||||
Object.entries(data_source).forEach(([key, value]) => {
|
||||
if (mapping.hasOwnProperty(key)){
|
||||
ret[mapping[key]] = data_source[key];
|
||||
} else if (need_others){
|
||||
ret[key] = data_source[key];
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
bricks.relocate_by_eventpos = function(event, widget){
|
||||
var ex,ey;
|
||||
var x,y;
|
||||
var xsize = bricks.Body.dom_element.clientWidth;
|
||||
var ysize = bricks.Body.dom_element.clientHeight;
|
||||
ex = event.clientX;
|
||||
ey = event.clientY;
|
||||
var mxs = widget.dom_element.offsetWidth;
|
||||
var mys = widget.dom_element.offsetHeight;
|
||||
if (ex < (xsize / 2)) {
|
||||
x = ex + bricks.app.charsize;
|
||||
} else {
|
||||
x = ex - mxs - bricks.app.charsize;
|
||||
}
|
||||
if (ey < (ysize / 2)) {
|
||||
y = ey + bricks.app.charsize;
|
||||
} else {
|
||||
y = ey - mys - bricks.app.charsize;
|
||||
}
|
||||
widget.set_style('left', x + 'px');
|
||||
widget.set_style('top', y + 'px');
|
||||
}
|
||||
|
||||
var formdata2object = function(formdata){
|
||||
let result = {};
|
||||
formdata.forEach((value, key) => {
|
||||
result[key] = value;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
var inputdata2dic = function(data){
|
||||
try {
|
||||
var d = {}
|
||||
for (let k of data.keys()){
|
||||
var x = data.get(k);
|
||||
if (k == 'prompt'){
|
||||
x = bricks.escapeSpecialChars(x);
|
||||
}
|
||||
d[k] = x;
|
||||
}
|
||||
return d;
|
||||
} catch (e){
|
||||
return data;
|
||||
}
|
||||
}
|
||||
bricks.delete_null_values = function(obj) {
|
||||
for (let key in obj) {
|
||||
if (obj[key] === null) {
|
||||
delete obj[key];
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
for (let key in obj) {
|
||||
if (obj[key] === null) {
|
||||
delete obj[key];
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
bricks.is_empty = function(obj){
|
||||
if (obj === null) return true;
|
||||
return JSON.stringify(obj) === '{}';
|
||||
}
|
||||
bricks.serverdebug = async function(message){
|
||||
var jc = new bricks.HttpJson();
|
||||
await jc.post(url='/debug', {params:{
|
||||
message:message
|
||||
}});
|
||||
return;
|
||||
}
|
||||
bricks.debug = function(...args){
|
||||
if (! bricks.bug){
|
||||
return;
|
||||
}
|
||||
if (bricks.bug == 'server'){
|
||||
var message = args.join(" ");
|
||||
f = bricks.serverdebug.bind(null, message);
|
||||
schedule_once(f, 0.1);
|
||||
return;
|
||||
}
|
||||
var callInfo;
|
||||
try {
|
||||
throw new Error();
|
||||
@ -31,7 +113,7 @@ bricks.debug = function(...args){
|
||||
}
|
||||
|
||||
bricks.is_mobile = function(){
|
||||
var userAgent = navigator.userAgent;
|
||||
var userAgent = navigator.userAgent;
|
||||
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)) {
|
||||
return true;
|
||||
}
|
||||
@ -77,9 +159,9 @@ var currentScriptPath = function () {
|
||||
}
|
||||
currentScript = scripts[ scripts.length - 1 ].src;
|
||||
}
|
||||
var currentScriptChunks = currentScript.split( '/' );
|
||||
var currentScriptFile = currentScriptChunks[ currentScriptChunks.length - 1 ];
|
||||
return currentScript.replace( currentScriptFile, '' );
|
||||
var currentScriptChunks = currentScript.split( '/' );
|
||||
var currentScriptFile = currentScriptChunks[ currentScriptChunks.length - 1 ];
|
||||
return currentScript.replace( currentScriptFile, '' );
|
||||
}
|
||||
|
||||
bricks.path = currentScriptPath();
|
||||
@ -94,17 +176,17 @@ var bricks_resource = function(name){
|
||||
* @see https://stackoverflow.com/a/71692555/2228771
|
||||
*/
|
||||
function querySelectorAllShadows(selector, el = document.body) {
|
||||
// recurse on childShadows
|
||||
const childShadows = Array.from(el.querySelectorAll('*')).
|
||||
map(el => el.shadowRoot).filter(Boolean);
|
||||
// recurse on childShadows
|
||||
const childShadows = Array.from(el.querySelectorAll('*')).
|
||||
map(el => el.shadowRoot).filter(Boolean);
|
||||
|
||||
bricks.debug('[querySelectorAllShadows]', selector, el, `(${childShadows.length} shadowRoots)`);
|
||||
bricks.debug('[querySelectorAllShadows]', selector, el, `(${childShadows.length} shadowRoots)`);
|
||||
|
||||
const childResults = childShadows.map(child => querySelectorAllShadows(selector, child));
|
||||
|
||||
// fuse all results into singular, flat array
|
||||
const result = Array.from(el.querySelectorAll(selector));
|
||||
return result.concat(childResults).flat();
|
||||
const childResults = childShadows.map(child => querySelectorAllShadows(selector, child));
|
||||
|
||||
// fuse all results into singular, flat array
|
||||
const result = Array.from(el.querySelectorAll(selector));
|
||||
return result.concat(childResults).flat();
|
||||
}
|
||||
|
||||
var schedule_once = function(f, t){
|
||||
@ -182,7 +264,7 @@ bricks.obj_fmtstr = function(obj, fmt){
|
||||
'${name:}, ${age=}'
|
||||
*/
|
||||
var s = fmt;
|
||||
s = s.replace(/\${(\w+)([:=]*)}/g, (k, key, op) => {
|
||||
s = s.replace(/\${(\w+)([:=]*)}/g, (k, key, op) => {
|
||||
if (obj.hasOwnProperty(key)){
|
||||
if (op == ''){
|
||||
return obj[key];
|
||||
@ -257,7 +339,7 @@ var archorize = function(ele,archor){
|
||||
}
|
||||
|
||||
Array.prototype.insert = function ( index, ...items ) {
|
||||
this.splice( index, 0, ...items );
|
||||
this.splice( index, 0, ...items );
|
||||
};
|
||||
|
||||
Array.prototype.remove = function(item){
|
||||
@ -297,26 +379,26 @@ var convert2int = function(s){
|
||||
}
|
||||
|
||||
function setCookie(name,value,days) {
|
||||
var expires = "";
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days*24*60*60*1000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
||||
var expires = "";
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days*24*60*60*1000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
||||
}
|
||||
function getCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i=0;i < ca.length;i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
|
||||
}
|
||||
return null;
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i=0;i < ca.length;i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function eraseCookie(name) {
|
||||
document.cookie = name +'=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
|
||||
function eraseCookie(name) {
|
||||
document.cookie = name +'=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
|
||||
}
|
||||
|
||||
var set_max_height = function(w1, w2){
|
||||
@ -330,13 +412,48 @@ var set_max_height = function(w1, w2){
|
||||
}
|
||||
}
|
||||
var objcopy = function(obj){
|
||||
var o = {}
|
||||
for ( k in obj){
|
||||
if (obj.hasOwnProperty(k)){
|
||||
o[k] = obj[k];
|
||||
}
|
||||
}
|
||||
return o;
|
||||
var s = JSON.stringify(obj);
|
||||
return JSON.parse(s);
|
||||
}
|
||||
|
||||
bricks.set_stream_source = async function(target, url, params){
|
||||
var widget;
|
||||
if (typeof target == typeof ''){
|
||||
widget = bricks.getWidgetById(target);
|
||||
} else if (target instanceof bricks.JsWidget){
|
||||
widget = target;
|
||||
} else {
|
||||
widget = await bricks.widgetBuild(target);
|
||||
}
|
||||
if (! widget){
|
||||
bricks.debug('playResponseAudio():', target, 'can not found or build a widget');
|
||||
return;
|
||||
}
|
||||
const mediaSource = new MediaSource();
|
||||
mediaSource.addEventListener('sourceopen', handleSourceOpen);
|
||||
widget.set_url(URL.createObjectURL(mediaSource));
|
||||
function handleSourceOpen(){
|
||||
const sourceBuffer = mediaSource.addSourceBuffer('audio/wav; codecs=1');
|
||||
var ht = new bricks.HttpText();
|
||||
ht.bricks_fetch(url, {params:params})
|
||||
.then(response => response.body)
|
||||
.then(body => {
|
||||
const reader = body.getReader();
|
||||
const read = () => {
|
||||
reader.read().then(({ done, value }) => {
|
||||
if (done) {
|
||||
mediaSource.endOfStream();
|
||||
return;
|
||||
}
|
||||
sourceBuffer.appendBuffer(value);
|
||||
read();
|
||||
}).catch(error => {
|
||||
console.error('Error reading audio stream:', error);
|
||||
});
|
||||
};
|
||||
read();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bricks.playResponseAudio = async function(response, target){
|
||||
@ -354,8 +471,8 @@ bricks.playResponseAudio = async function(response, target){
|
||||
bricks.debug('playResponseAudio():', target, 'can not found or build a widget');
|
||||
return;
|
||||
}
|
||||
const blob = await response.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
const blob = await response.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
widget.set_url(url);
|
||||
widget.play();
|
||||
}
|
||||
@ -382,12 +499,88 @@ bricks.Observable = class {
|
||||
this.value = v;
|
||||
}
|
||||
set(v){
|
||||
if (this.value != v){
|
||||
var ov = this.value;
|
||||
this.value = v;
|
||||
if (this.value != ov){
|
||||
this.owner.dispatch(this.name, v);
|
||||
}
|
||||
this.value = v;
|
||||
}
|
||||
get(){
|
||||
return this.v;
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Queue = class {
|
||||
constructor() {
|
||||
this.items = [];
|
||||
this._done = false;
|
||||
}
|
||||
|
||||
// 添加元素到队列尾部
|
||||
enqueue(element) {
|
||||
this.items.push(element);
|
||||
}
|
||||
done(){
|
||||
this._done = true;
|
||||
}
|
||||
is_done(){
|
||||
return this._done;
|
||||
}
|
||||
|
||||
// 移除队列的第一个元素并返回
|
||||
dequeue() {
|
||||
if (this.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return this.items.shift();
|
||||
}
|
||||
|
||||
// 查看队列的第一个元素
|
||||
peek() {
|
||||
if (this.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return this.items[0];
|
||||
}
|
||||
|
||||
// 检查队列是否为空
|
||||
isEmpty() {
|
||||
return this.items.length === 0;
|
||||
}
|
||||
|
||||
// 获取队列的大小
|
||||
size() {
|
||||
return this.items.length;
|
||||
}
|
||||
|
||||
// 清空队列
|
||||
clear() {
|
||||
this.items = [];
|
||||
}
|
||||
|
||||
// 打印队列元素
|
||||
print() {
|
||||
console.log(this.items.toString());
|
||||
}
|
||||
}
|
||||
|
||||
function blobToBase64(blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = function() {
|
||||
resolve(reader.result);
|
||||
};
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
/*
|
||||
// 使用队列
|
||||
const queue = new Queue();
|
||||
queue.enqueue(1);
|
||||
queue.enqueue(2);
|
||||
queue.enqueue(3);
|
||||
queue.print(); // 输出: 1,2,3
|
||||
console.log(queue.dequeue()); // 输出: 1
|
||||
queue.print(); // 输出: 2,3
|
||||
*/
|
||||
|
218
bricks/video.js
Executable file → Normal file
@ -26,6 +26,7 @@ bricks.VideoBody = class extends bricks.Layout {
|
||||
bricks.Video = class extends bricks.Layout {
|
||||
/*
|
||||
{
|
||||
title:
|
||||
vtype:
|
||||
url:
|
||||
fullscreen:
|
||||
@ -34,13 +35,22 @@ bricks.Video = class extends bricks.Layout {
|
||||
*/
|
||||
constructor(options){
|
||||
super(options);
|
||||
this.video_body = new bricks.VideoBody(options);
|
||||
this.add_widget(this.video_body);
|
||||
// this.video_body = new bricks.VideoBody(options);
|
||||
this.set_css('video-js');
|
||||
this.set_css('vjs-big-play-centered');
|
||||
this.set_css('vjs-fluid');
|
||||
this.set_style('width', '100%');
|
||||
this.set_style('height', '100%');
|
||||
this.set_style('object-fit', 'contain');
|
||||
this.cur_url = opts.url;
|
||||
this.cur_vtype = opts.type;
|
||||
schedule_once(this.create_player.bind(this), 0.1);
|
||||
this.hidedbtn = new bricks.Button({label:'click me'});
|
||||
this.hidedbtn.bind('click', this.play.bind(this));
|
||||
this.hidedbtn.hide();
|
||||
this.add_widget(this.hidedbtn);
|
||||
}
|
||||
create(){
|
||||
var e;
|
||||
e = document.createElement('video');
|
||||
this.dom_element = e;
|
||||
e.controls = true;
|
||||
}
|
||||
|
||||
destroy_resource(params, event){
|
||||
@ -62,17 +72,46 @@ bricks.Video = class extends bricks.Layout {
|
||||
}
|
||||
}
|
||||
}
|
||||
findVideoButtonByClass(cls){
|
||||
var e = this.dom_element;
|
||||
return e.querySelector('.' + cls);
|
||||
}
|
||||
|
||||
auto_play(){
|
||||
schedule_once(this._auto_play.bind(this), 0.5);
|
||||
schedule_once(this._auto_play.bind(this), 0.8);
|
||||
}
|
||||
_auto_play(){
|
||||
this.set_url(this.opts.url);
|
||||
return;
|
||||
var play_btn = this.findVideoButtonByClass('vjs-big-play-button');
|
||||
if (!play_btn){
|
||||
console.log('vjs-big-play-button not found');
|
||||
return;
|
||||
}
|
||||
if (play_btn.style.display == 'none'){
|
||||
console.log('playing .............already');
|
||||
return;
|
||||
}
|
||||
console.log('video ready, auto_playing ....');
|
||||
schedule_once(this.disable_captions.bind(this), 2);
|
||||
this.hidedbtn.dispatch('click');
|
||||
var clickevent = new MouseEvent('click', {
|
||||
'bubbles': true, // 事件是否冒泡
|
||||
'cancelable': true // 事件是否可取消
|
||||
});
|
||||
play_btn.dispatchEvent(clickevent);
|
||||
/*
|
||||
if (this.autounmute && this.player.muted){
|
||||
schedule_once(this.dispatch_mute.bind(this), 1);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
play(){
|
||||
console.log('Video:play() called....');
|
||||
this.player.play();
|
||||
// this.player.muted(false);
|
||||
}
|
||||
unmuted(){
|
||||
this.player.muted(false);
|
||||
}
|
||||
set_fullscreen(){
|
||||
if (this.fullscreen){
|
||||
@ -85,9 +124,31 @@ bricks.Video = class extends bricks.Layout {
|
||||
}
|
||||
}
|
||||
}
|
||||
dispatch_mute(){
|
||||
var mute_btn = this.findVideoButtonByClass("vjs-mute-control.vjs-control.vjs-button");
|
||||
if (!mute_btn){
|
||||
var isMute = this.player.muted();
|
||||
if (isMuted){
|
||||
this.player.muted(False);
|
||||
}
|
||||
bricks.test_element = this;
|
||||
console.log(this, 'there is not mute button found, isMuted=', isMuted);
|
||||
return;
|
||||
}
|
||||
var clickevent = new MouseEvent('click', {
|
||||
'bubbles': true, // 事件是否冒泡
|
||||
'cancelable': true // 事件是否可取消
|
||||
});
|
||||
var isMuted = this.player.muted();
|
||||
if (isMuted){
|
||||
mute_btn.dispatchEvent(clickevent);
|
||||
}
|
||||
}
|
||||
|
||||
create_player(){
|
||||
if(this.url){
|
||||
this.player = videojs(this.video_body.dom_element, {
|
||||
// this.player = videojs(this.video_body.dom_element, {
|
||||
this.player = videojs(this.dom_element, {
|
||||
controls:true,
|
||||
autoplay:this.autoplay,
|
||||
muted:true,
|
||||
@ -98,37 +159,49 @@ bricks.Video = class extends bricks.Layout {
|
||||
this.player.on('error',this.report_error.bind(this));
|
||||
this.player.on('play', this.report_playok.bind(this));
|
||||
this.player.on('ended', this.report_ended.bind(this));
|
||||
this._set_source();
|
||||
this.set_url(this.opts.url);
|
||||
this.player.ready(this.set_fullscreen.bind(this));
|
||||
/*
|
||||
if (this.autoplay){
|
||||
this.player.autoplay = true;
|
||||
this.player.muted = true;
|
||||
this.player.ready(this.auto_play.bind(this));
|
||||
} else {
|
||||
console.log('autoplay=', this.autoplay, this.auto_play);
|
||||
// this.player.ready(this.auto_play.bind(this));
|
||||
this.auto_play();
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
report_ended(){
|
||||
this.dispatch('play_end',{src:this.video_body.cur_url,type:this.video_body.cur_vtype});
|
||||
if (this.play_status != 'playok'){
|
||||
returnl
|
||||
}
|
||||
this.play_status = 'playend';
|
||||
this.dispatch('play_end',{src:this.cur_url,type:this.cur_vtype});
|
||||
}
|
||||
report_playok(){
|
||||
console.log(this.video_body.cur_url, 'play ok');
|
||||
this.dispatch('play_ok', {src:this.video_body.cur_url,type:this.video_body.cur_vtype});
|
||||
if (this.play_status != ''){
|
||||
return;
|
||||
}
|
||||
this.play_status = 'playok';
|
||||
console.log(this.cur_url, 'play ok');
|
||||
if (this.autounmute && this.player.muted()){
|
||||
schedule_once(this.dispatch_mute.bind(this), 2.5);
|
||||
console.log('mute btn clicked');
|
||||
} else {
|
||||
console.log(this.autounmute, 'player.muted=', this.player.muted);
|
||||
}
|
||||
this.dispatch('play_ok', {src:this.cur_url,type:this.cur_vtype});
|
||||
}
|
||||
report_error(){
|
||||
console.log(this.video_body.cur_url, 'play failed', this.err_cnt, 'times');
|
||||
this.dispatch('play_failed', {'src':this.video_body.cur_url, type:this.video_body.cur_vtype});
|
||||
if (this.play_status != ''){
|
||||
return;
|
||||
}
|
||||
this.play_status = 'playfailed';
|
||||
console.log(this.cur_url, 'play failed', this.err_cnt, 'times');
|
||||
this.dispatch('play_failed', {'src':this.cur_url, type:this.cur_vtype});
|
||||
}
|
||||
_set_source(){
|
||||
if (this.player){
|
||||
this.player.src({
|
||||
src:this.video_body.cur_url,
|
||||
type:this.video_body.cur_vtype
|
||||
src:this.cur_url,
|
||||
type:this.cur_vtype
|
||||
});
|
||||
this.play_status = '';
|
||||
}
|
||||
}
|
||||
set_source(url, vtype){
|
||||
@ -137,17 +210,106 @@ bricks.Video = class extends bricks.Layout {
|
||||
vtype = 'application/x-mpegURL';
|
||||
} else if (t.endsWith('.mp4')){
|
||||
vtype = 'video/mp4';
|
||||
} else if (t.endsWith('.avi')){
|
||||
vtype = 'video/avi';
|
||||
} else if (t.endsWith('.webm')){
|
||||
vtype = 'video/webm';
|
||||
} else {
|
||||
vtype = 'application/x-mpegURL';
|
||||
}
|
||||
if(this.player){
|
||||
this.video_body.cur_url = url;
|
||||
this.video_body.cur_vtype = vtype;
|
||||
this.cur_url = url;
|
||||
this.cur_vtype = vtype;
|
||||
this._set_source();
|
||||
this.play();
|
||||
}
|
||||
}
|
||||
set_url(url){
|
||||
this.set_source(url);
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Iptv = class extends bricks.VBox {
|
||||
/*
|
||||
{
|
||||
iptv_data_url:
|
||||
playok_url:
|
||||
playfailed_url:
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
schedule_once(this.build_subwidgets.bind(this), 0.1);
|
||||
}
|
||||
async build_subwidgets(){
|
||||
console.log('build_subwidgets called');
|
||||
var jc = new bricks.HttpJson();
|
||||
this.deviceid = bricks.deviceid('iptv')
|
||||
this.user_data = await jc.httpcall(this.iptv_data_url, {
|
||||
params:{
|
||||
deviceid:this.deviceid
|
||||
},
|
||||
method:'GET'
|
||||
});
|
||||
console.log('this.user_data =', this.user_data);
|
||||
this.video = new bricks.Video({
|
||||
autoplay:true,
|
||||
autounmute:this.autounmute,
|
||||
url:this.user_data.url
|
||||
});
|
||||
this.title_w = new bricks.Text({text:this.user_data.tv_name, wrap:false});
|
||||
this.add_widget(this.title_w);
|
||||
this.add_widget(this.video);
|
||||
this.video.bind('play_ok', this.report_play_ok.bind(this));
|
||||
this.video.bind('play_failed', this.report_play_failed.bind(this));
|
||||
}
|
||||
async report_play_ok(){
|
||||
console.log(this.user_data, 'channel playing ...', this.playok_url);
|
||||
if (this.playok_url){
|
||||
var ht = new bricks.HttpText();
|
||||
var resp = ht.httpcall(this.playok_url,{
|
||||
params:{
|
||||
deviceid:this.deviceid,
|
||||
channelid:this.user_data.id
|
||||
},
|
||||
method:"GET"
|
||||
});
|
||||
if (resp != 'Error'){
|
||||
console.log('report playok ok');
|
||||
} else {
|
||||
console.log('report playok failed');
|
||||
}
|
||||
} else {
|
||||
console.log('this.playok_url not defined', this.playok_url);
|
||||
}
|
||||
}
|
||||
async report_play_failed(){
|
||||
console.log(this.user_data, 'channel play failed ...');
|
||||
if (this.playfailed_url){
|
||||
var ht = new bricks.HttpText();
|
||||
var resp = ht.httpcall(this.playfailed_url,{
|
||||
params:{
|
||||
deviceid:this.deviceid,
|
||||
channelid:this.user_data.id
|
||||
},
|
||||
method:"GET"
|
||||
});
|
||||
if (resp != 'Error'){
|
||||
console.log('report playfailed ok');
|
||||
} else {
|
||||
console.log('report playfailed failed');
|
||||
}
|
||||
} else {
|
||||
console.log('this.playfailed_url not defined', this.playfailed_url);
|
||||
}
|
||||
}
|
||||
setValue(data){
|
||||
this.user_data = data;
|
||||
this.title_w.set_text(data.tv_name);
|
||||
this.video.set_url(data.url);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
bricks.Factory.register('Video', bricks.Video);
|
||||
bricks.Factory.register('Iptv', bricks.Iptv);
|
||||
|
73
bricks/webspeech.js
Normal file
@ -0,0 +1,73 @@
|
||||
var bricks = window.bricks || {};
|
||||
|
||||
bricks.WebTTS = class extends bricks.VBox {
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
}
|
||||
speak(text){
|
||||
// 检查浏览器是否支持SpeechSynthesis
|
||||
if ('speechSynthesis' in window) {
|
||||
var utterance = new SpeechSynthesisUtterance(text);
|
||||
// 设置语音属性,例如语言
|
||||
utterance.lang = bricks.app.lang;
|
||||
utterance.pitch = 1;
|
||||
utterance.rate = 1;
|
||||
utterance.onstart = function(event) {
|
||||
console.log('语音合成开始');
|
||||
};
|
||||
// 当语音合成结束时触发
|
||||
utterance.onend = function(event) {
|
||||
console.log('语音合成结束');
|
||||
};
|
||||
// 当语音合成出错时触发
|
||||
utterance.onerror = function(event) {
|
||||
console.error('语音合成出错:', event.error);
|
||||
};
|
||||
// 将utterance添加到语音合成队列
|
||||
window.speechSynthesis.speak(utterance);
|
||||
} else {
|
||||
console.error('浏览器不支持SpeechSynthesis');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bricks.WebASR = class extends bricks.VBox {
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.reognition = None;
|
||||
}
|
||||
start_recording(){
|
||||
// 检查浏览器是否支持SpeechRecognition
|
||||
if ('SpeechRecognition' in window) {
|
||||
// 创建SpeechRecognition实例
|
||||
this.recognition = new SpeechRecognition();
|
||||
// 处理识别错误
|
||||
this.recognition.onerror = function(event) {
|
||||
console.error('识别错误:', event.error);
|
||||
};
|
||||
// 处理语音识别结束事件
|
||||
this.recognition.onend = function() {
|
||||
console.log('语音识别已结束');
|
||||
};
|
||||
// 处理识别结果
|
||||
this.recognition.onresult = function(event) {
|
||||
var transcript = event.results[0][0].transcript;
|
||||
this.dispatch('asr_result', {
|
||||
content:transcript
|
||||
});
|
||||
console.log('识别结果:', transcript);
|
||||
};
|
||||
this.recognition.lang = bricks.app.lang;
|
||||
this.recognition.start();
|
||||
} else {
|
||||
console.log('browser has not SpeechRecognition');
|
||||
}
|
||||
}
|
||||
stop_recording(){
|
||||
this.recognition.stop();
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('WebTTS', bricks.WebTTS);
|
||||
bricks.Factory.register('WebASR', bricks.WebASR);
|
||||
|
91
bricks/widget.js
Executable file → Normal file
@ -15,6 +15,13 @@ bricks.resize_observer = new ResizeObserver(entries => {
|
||||
});
|
||||
|
||||
bricks.JsWidget = class {
|
||||
/*
|
||||
popup:{
|
||||
popup_event:
|
||||
popup_desc:
|
||||
popupwindow:false or true
|
||||
}
|
||||
*/
|
||||
constructor(options){
|
||||
if (!options){
|
||||
options = {}
|
||||
@ -38,9 +45,36 @@ bricks.JsWidget = class {
|
||||
var w = bricks.app.tooltip;
|
||||
this.bind('mousemove', w.show.bind(w, this.opts.tip));
|
||||
this.bind('mouseout', w.hide.bind(w));
|
||||
this.bind('click', w.hide.bind(w));
|
||||
}
|
||||
if (this.popup){
|
||||
this.bind(this.popup.popup_event, this.popup_action.bind(this));
|
||||
}
|
||||
bricks.resize_observer.observe(this.dom_element);
|
||||
}
|
||||
destroy_popup(){
|
||||
this.popup_widget.destroy();
|
||||
this.popup_widget = null;
|
||||
}
|
||||
async popup_action(){
|
||||
if (this.popup_widget){
|
||||
this.popup_widget.destroy();
|
||||
this.popup_widget = null;
|
||||
} else {
|
||||
if (this.popup.popupwindow){
|
||||
this.popup_widget = new bricks.PopupWindow(this.popup.optiosn);
|
||||
} else {
|
||||
this.popup_widget = new bricks.Popup(this.popup.options);
|
||||
}
|
||||
this.popup_widget.bind('dismissed', this.destroy_popup.bind(this));
|
||||
var w = await bricks.widgetBuild(this.popup.popup_desc, this, this.user_data);
|
||||
if (w){
|
||||
this.popup_widget.add_widget(w);
|
||||
this.popup_widget.open();
|
||||
this.popup_widget.popup_from_widget(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
showRectage(){
|
||||
return this.dom_element.getBoundingClientRect();
|
||||
}
|
||||
@ -65,8 +99,10 @@ bricks.JsWidget = class {
|
||||
disabled(flag){
|
||||
if(flag){
|
||||
this.dom_element.disabled = true;
|
||||
this.set_style('pointerEvents', 'none');
|
||||
} else {
|
||||
this.dom_element.disabled = false;
|
||||
this.set_style('pointerEvents', 'auto');
|
||||
}
|
||||
}
|
||||
opts_set_style(){
|
||||
@ -153,6 +189,23 @@ bricks.JsWidget = class {
|
||||
}
|
||||
}
|
||||
}
|
||||
enter_fullscreen(){
|
||||
var e = this.dom_element;
|
||||
// 获取要全屏显示的元素
|
||||
// 检查浏览器是否支持Fullscreen API
|
||||
if (e.requestFullscreen) {
|
||||
e.requestFullscreen();
|
||||
} else if (e.mozRequestFullScreen) { // Firefox
|
||||
e.mozRequestFullScreen();
|
||||
} else if (e.webkitRequestFullscreen) { // Chrome, Safari and Opera
|
||||
e.webkitRequestFullscreen();
|
||||
} else if (e.msRequestFullscreen) { // IE/Edge
|
||||
e.msRequestFullscreen();
|
||||
}
|
||||
}
|
||||
exit_fullscreen(){
|
||||
document.exitFullscreen();
|
||||
}
|
||||
h_center(){
|
||||
this.dom_element.style.marginLeft = 'auto';
|
||||
this.dom_element.style.marginRight = 'auto';
|
||||
@ -458,36 +511,22 @@ bricks.Tooltip = class extends bricks.Text {
|
||||
this.set_otext(otext);
|
||||
this.set_style('zIndex', 999999999);
|
||||
this.set_style('display', 'block');
|
||||
var ex,ey;
|
||||
var x,y;
|
||||
var xsize = bricks.Body.dom_element.clientWidth;
|
||||
var ysize = bricks.Body.dom_element.clientHeight;
|
||||
ex = event.clientX;
|
||||
ey = event.clientY;
|
||||
var mxs = this.dom_element.offsetWidth;
|
||||
var mys = this.dom_element.offsetHeight;
|
||||
if (ex < (xsize / 2)) {
|
||||
x = ex + bricks.app.charsize;
|
||||
} else {
|
||||
x = ex - mxs - bricks.app.charsize;
|
||||
}
|
||||
if (ey < (ysize / 2)) {
|
||||
y = ey + bricks.app.charsize;
|
||||
} else {
|
||||
y = ey - mys - bricks.app.charsize;
|
||||
}
|
||||
this.set_style('left', x + 'px');
|
||||
this.set_style('top', y + 'px');
|
||||
if (this.auto_task){
|
||||
this.auto_task.cancel();
|
||||
}
|
||||
this.auto_task = schedule_once(this.hide.bind(this), 30);
|
||||
}
|
||||
hide(){
|
||||
bricks.relocate_by_eventpos(event, this);
|
||||
if (this.auto_task){
|
||||
this.auto_task.cancel();
|
||||
this.auto_task = null;
|
||||
}
|
||||
this.auto_task = schedule_once(this.hide.bind(this), 6);
|
||||
}
|
||||
hide(){
|
||||
try {
|
||||
if (this.auto_task){
|
||||
this.auto_task.cancel();
|
||||
this.auto_task = null;
|
||||
}
|
||||
} catch(e){
|
||||
console.log('Exception:', e);
|
||||
}
|
||||
this.set_style('display', 'none');
|
||||
}
|
||||
}
|
||||
|
@ -6,29 +6,58 @@ bricks.Wterm = class extends bricks.JsWidget {
|
||||
/*
|
||||
{
|
||||
ws_url:
|
||||
host:
|
||||
ssh_port:
|
||||
user:
|
||||
ping_timeout:19
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.socket = null;
|
||||
this.ping_timeout = opts.ping_timeout || 19;
|
||||
schedule_once(this.open.bind(this), 0.5);
|
||||
}
|
||||
charsize_sizing(){
|
||||
var cs = bricks.app.charsize;
|
||||
this.term.setOption('fontSize', cs);
|
||||
}
|
||||
heartbeat(){
|
||||
if (this.socket.readyState != 1) return;
|
||||
this.socket.send('_#_heartbeat_#_');
|
||||
this.heartbeat_task = schedule_once(this.heartbeat.bind(this),
|
||||
this.ping_timeout);
|
||||
}
|
||||
async open(){
|
||||
var term = new Terminal();
|
||||
var term_options = this.term_options || {};
|
||||
var term = new Terminal(term_options);
|
||||
this.term = term;
|
||||
term.open(this.dom_element);
|
||||
var ws = new WebSocket(this.opts.ws_url);
|
||||
bricks.debug('FitAddon=', FitAddon);
|
||||
this.socket = ws;
|
||||
|
||||
this.fitAddon = new FitAddon.FitAddon()
|
||||
term.loadAddon(this.fitAddon)
|
||||
// this.fitAddon.fit()
|
||||
this.fitAddon.fit();
|
||||
this.charsize_sizing();
|
||||
this.bind('resize', this.term_resize.bind(this))
|
||||
ws.onmessage = msg => {
|
||||
term.write(JSON.parse(msg.data).data);
|
||||
ws.onmessage = event => {
|
||||
var msg = JSON.parse(event.data);
|
||||
console.log('ws msg=', msg);
|
||||
if (msg.data == '_#_heartbeat_#_'){
|
||||
console.log('connection alive');
|
||||
} else {
|
||||
term.write(msg.data);
|
||||
}
|
||||
};
|
||||
ws.onclose = (event) => {
|
||||
console.log('websocket closed:', event.code, '--', event.reason);
|
||||
if (this.heartbeat_task) {
|
||||
this.heartbeat_task.cancel();
|
||||
this.heartbeat_task = null;
|
||||
}
|
||||
};
|
||||
ws.onopen = () => {
|
||||
this.heartbeat_task = schedule_once(this.heartbeat.bind(this),
|
||||
this.ping_timeout);
|
||||
};
|
||||
|
||||
term.onData(function(key) {
|
||||
//Enter
|
||||
let msg = {
|
||||
@ -38,13 +67,12 @@ bricks.Wterm = class extends bricks.JsWidget {
|
||||
ws.send(key);
|
||||
});
|
||||
term.focus();
|
||||
term.paste("ls -l\n");
|
||||
}
|
||||
term_resize(){
|
||||
try {
|
||||
this.fitAddon.fit();
|
||||
} catch(e){
|
||||
bricks.debug('resize error', e);
|
||||
console.log('resize error', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
docs/.DS_Store
vendored
@ -39,6 +39,14 @@ bricks的事件处理是在控件描述文件的binds区域中添加事件处理
|
||||
### dataparams
|
||||
获取动态参数时需给定的参数, 可选,对象类型,k,v形式给定参数
|
||||
|
||||
### popup_options
|
||||
当target为“Popup“或“PopupWindow”时,定义Popup或PopupWindow的参数
|
||||
|
||||
#### dismiss_events
|
||||
字符串数组,每个字符串定义一个Popup, PopupWindow的子控件的事件,这些事件发生时将导致Popup, PopupWindow关闭
|
||||
|
||||
#### eventpos
|
||||
Popup, PopupWindow窗体移动到鼠标位置
|
||||
|
||||
### 获取动态参数说明
|
||||
绑定任务获取实时数据作为参数,需要给定以下属性:
|
||||
@ -50,7 +58,15 @@ bricks的事件处理是在控件描述文件的binds区域中添加事件处理
|
||||
datamethod 优先datascript,从datawidget控件中通过datamethod
|
||||
|
||||
### target
|
||||
字符串或控件实例,目标控件实例,如果是字符串,使用”getWidgetById“函数获得目标控件实例,关于target规则请查看[控件id](widgetid.md)
|
||||
支持一下形式的target定义:
|
||||
* 目标控件实例对象
|
||||
* 字符串,且等于“Popup“
|
||||
* 字符串,且等于”PopupWindow“
|
||||
* 其他字符串(控件对象的id)
|
||||
当actiontype为"urlwidget"时,target应该是一个容器控件,所生成的控件将插入或替代到“target”所代表的对象中,如果actiontype是其他类型,则在此对象中执行方法,脚本,定义函数,或定义事件
|
||||
|
||||
|
||||
|
||||
|
||||
### conform
|
||||
如果一个事件处理需要用户确认,可以在事件处理中指定一个conform属性来引发,当此事件发生时,会弹出一个确认窗口,用户确认后才会处理此事件,否则不处理
|
||||
|
6
examples/alipay_recharge.ui
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"widgettype":"VBox",
|
||||
"options":{
|
||||
"height":"100%"
|
||||
}
|
||||
}
|
14
examples/asr.ui
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"widgettype":"ASRClient",
|
||||
"options":
|
||||
{
|
||||
"ws_url":"{{entire_url('/wss/ws/test.ws')}}?userid={{get_user()}}",
|
||||
"icon_options":{
|
||||
"rate":3
|
||||
},
|
||||
"ws_params":{
|
||||
"kkk":1,
|
||||
"brade":"123"
|
||||
}
|
||||
}
|
||||
}
|
29
examples/camera.ui
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"widgettype":"HBox",
|
||||
"options":{
|
||||
"widht":"100%",
|
||||
"height":"100%"
|
||||
},
|
||||
"subwidgets":[
|
||||
{
|
||||
"widgettype":"Camera",
|
||||
"options":{
|
||||
"width":"50%",
|
||||
"height":"90%",
|
||||
"archor":"cl",
|
||||
"auto_open":true,
|
||||
"fps":60
|
||||
}
|
||||
},
|
||||
{
|
||||
"widgettype":"Camera",
|
||||
"options":{
|
||||
"width":"50%",
|
||||
"height":"90%",
|
||||
"archor":"cr",
|
||||
"auto_open":true,
|
||||
"fps":30
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
36
examples/recharge.ui
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"widgettype":"IconbarPage",
|
||||
"options":{
|
||||
"bar_at":"top",
|
||||
"bar_opts":{
|
||||
"margin":"10px",
|
||||
"rate":1.6,
|
||||
"tools":[
|
||||
{
|
||||
"name":"wechat",
|
||||
"icon":"{{entire_url('/imgs/weixinzhifu.png')}}",
|
||||
"label":"微信充值",
|
||||
"tip":"使用微信为账户充值",
|
||||
"content":{
|
||||
"widgettype":"urlwidget",
|
||||
"options":{
|
||||
"url":"{{entire_url('wechat_recharge.ui')}}"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"alipay",
|
||||
"icon":"{{entire_url('/imgs/zhifubao.png')}}",
|
||||
"label":"支付宝充值",
|
||||
"tip":"使用支付宝为账户充值",
|
||||
"content":{
|
||||
"widgettype":"urlwidget",
|
||||
"options":{
|
||||
"url":"{{entire_url('alipay_recharge.ui')}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
6
examples/wechat_recharge.ui
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"widgettype":"VBox",
|
||||
"options":{
|
||||
"height":"100%"
|
||||
}
|
||||
}
|