376 lines
8.3 KiB
JavaScript
Executable File
376 lines
8.3 KiB
JavaScript
Executable File
var bricks = window.bricks || {};
|
|
bricks.bug = false;
|
|
bricks.delete_null_values = function(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.debug = function(...args){
|
|
if (! bricks.bug){
|
|
return;
|
|
}
|
|
var callInfo;
|
|
try {
|
|
throw new Error();
|
|
} catch (e) {
|
|
callInfo = e.stack.split('\n')[2].trim();
|
|
}
|
|
console.log(callInfo, ...args);
|
|
}
|
|
|
|
bricks.is_mobile = function(){
|
|
var userAgent = navigator.userAgent;
|
|
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)) {
|
|
return true;
|
|
}
|
|
if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)) {
|
|
return true;
|
|
}
|
|
if (window.innerWidth <= 768 && window.innerHeight <= 1024) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
class _TypeIcons {
|
|
constructor(){
|
|
this.kv = {}
|
|
}
|
|
get(n, defaultvalue){
|
|
return objget(this.kv, n, defaultvalue);
|
|
}
|
|
register(n, icon){
|
|
this.kv[n] = icon;
|
|
}
|
|
}
|
|
|
|
TypeIcons = new _TypeIcons();
|
|
|
|
/**
|
|
* Current Script Path
|
|
*
|
|
* Get the dir path to the currently executing script file
|
|
* which is always the last one in the scripts array with
|
|
* an [src] attr
|
|
*/
|
|
var currentScriptPath = function () {
|
|
var currentScript;
|
|
if (document.currentScript){
|
|
currentScript = document.currentScript.src;
|
|
} else {
|
|
bricks.debug('has not currentScriot');
|
|
var scripts = document.querySelectorAll( 'script[src]' );
|
|
if (scripts.length < 1){
|
|
return null;
|
|
}
|
|
currentScript = scripts[ scripts.length - 1 ].src;
|
|
}
|
|
var currentScriptChunks = currentScript.split( '/' );
|
|
var currentScriptFile = currentScriptChunks[ currentScriptChunks.length - 1 ];
|
|
return currentScript.replace( currentScriptFile, '' );
|
|
}
|
|
|
|
bricks.path = currentScriptPath();
|
|
|
|
var bricks_resource = function(name){
|
|
return bricks.path + name;
|
|
}
|
|
|
|
/**
|
|
* Finds all elements in the entire page matching `selector`, even if they are in shadowRoots.
|
|
* Just like `querySelectorAll`, but automatically expand on all child `shadowRoot` elements.
|
|
* @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);
|
|
|
|
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();
|
|
}
|
|
|
|
var schedule_once = function(f, t){
|
|
/* f: function
|
|
t:time in second unit
|
|
*/
|
|
t = t * 1000
|
|
window.setTimeout(f, t);
|
|
}
|
|
|
|
var schedule_interval = function(f, t){
|
|
var mf = function(func, t){
|
|
func();
|
|
schedule_once(f, t);
|
|
}
|
|
schedule_once(mf.bind(f,t), t);
|
|
}
|
|
|
|
var debug = function(){
|
|
bricks.debug(...arguments);
|
|
}
|
|
|
|
var import_cache = new Map()
|
|
|
|
var import_css = async function(url){
|
|
if (objget(import_cache, url)===1) return;
|
|
var result = await (bricks.tget(url));
|
|
debug('import_css():tget() return', result);
|
|
var s = document.createElement('style');
|
|
s.setAttribute('type', 'text/javascript');
|
|
s.innerHTML = result;
|
|
document.getElementsByTagName("head")[0].appendChild(s);
|
|
import_cache.set(url, 1);
|
|
}
|
|
|
|
var import_js = async function(url){
|
|
if (objget(import_cache, url)===1) return;
|
|
// var result = await (bricks.tget(url));
|
|
// debug('import_js():tget() return', url, result);
|
|
var s = document.createElement('script');
|
|
s.setAttribute('type', 'text/javascript');
|
|
s.src=url;
|
|
// s.innerHTML = result;
|
|
document.body.appendChild(s);
|
|
import_cache.set(url, 1);
|
|
|
|
}
|
|
|
|
bricks.extend = function(d, s){
|
|
for (var p in s){
|
|
if (! s.hasOwnProperty(p)){
|
|
continue;
|
|
}
|
|
if (d[p] && (typeof(d[p]) == 'object')
|
|
&& (d[p].toString() == '[object Object]') && s[p]){
|
|
bricks.extend(d[p], s[p]);
|
|
} else {
|
|
d[p] = s[p];
|
|
}
|
|
}
|
|
return d;
|
|
}
|
|
|
|
var objget = function(obj, key, defval){
|
|
if (obj.hasOwnProperty(key)){
|
|
return obj[key];
|
|
}
|
|
return defval;
|
|
}
|
|
|
|
bricks.obj_fmtstr = function(obj, fmt){
|
|
/* fmt like
|
|
'my name is ${name}, ${age=}'
|
|
'${name:}, ${age=}'
|
|
*/
|
|
var s = fmt;
|
|
s = s.replace(/\${(\w+)([:=]*)}/g, (k, key, op) => {
|
|
if (obj.hasOwnProperty(key)){
|
|
if (op == ''){
|
|
return obj[key];
|
|
} else {
|
|
return key + op + obj[key];
|
|
}
|
|
}
|
|
return ''
|
|
})
|
|
return s;
|
|
}
|
|
|
|
var archorize = function(ele,archor){
|
|
/* archor maybe one of the:
|
|
"tl", "tc", "tr",
|
|
"cl", "cc", "cr",
|
|
"bl", "bc", "br"
|
|
*/
|
|
if (! archor)
|
|
archor = 'cc';
|
|
var v = archor[0];
|
|
var h = archor[1];
|
|
var y = "0%";
|
|
switch(v){
|
|
case 't':
|
|
y = "0%";
|
|
break;
|
|
case 'b':
|
|
y = '100%';
|
|
break;
|
|
case 'c':
|
|
y = '50%';
|
|
break;
|
|
default:
|
|
y = '50%';
|
|
break;
|
|
}
|
|
var x = "0%";
|
|
switch(h){
|
|
case 'l':
|
|
x = "0%";
|
|
break;
|
|
case 'r':
|
|
x = '100%';
|
|
break;
|
|
case 'c':
|
|
x = '50%';
|
|
break;
|
|
default:
|
|
x = '50%';
|
|
break;
|
|
}
|
|
ele.style.top = y;
|
|
ele.style.left = x;
|
|
var o = {
|
|
'x':x,
|
|
'y':y
|
|
}
|
|
var tsf = bricks.obj_fmtstr(o, 'translateY(-${y}) translateX(-${x})');
|
|
ele.style.transform = tsf;
|
|
ele.style.position = "absolute";
|
|
}
|
|
|
|
Array.prototype.insert = function ( index, ...items ) {
|
|
this.splice( index, 0, ...items );
|
|
};
|
|
|
|
Array.prototype.remove = function(item){
|
|
var idx = this.indexOf(item);
|
|
if (idx >= 0){
|
|
this.splice(idx, 1);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
bricks.absurl = function(url, widget){
|
|
if (url.startsWith('http://') || url.startsWith('https://')){
|
|
return url;
|
|
}
|
|
var base_uri = widget.baseURI;
|
|
if (url.startsWith('/')){
|
|
base_uri = bricks.Body.baseURI;
|
|
url = url.substring(1);
|
|
}
|
|
paths = base_uri.split('/');
|
|
delete paths[paths.length - 1];
|
|
var ret_url = paths.join('/') + url;
|
|
return ret_url;
|
|
}
|
|
|
|
var debug = function(...args){
|
|
bricks.debug(...args);
|
|
}
|
|
|
|
var convert2int = function(s){
|
|
if (typeof(s) == 'number') return s;
|
|
var s1 = s.match(/\d+/);
|
|
return parseInt(s1[0]);
|
|
}
|
|
|
|
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=/";
|
|
}
|
|
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;
|
|
}
|
|
function eraseCookie(name) {
|
|
document.cookie = name +'=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
|
|
}
|
|
|
|
var set_max_height = function(w1, w2){
|
|
var v1 = w1.dom_element.offsetHeight;
|
|
var v2 = w2.dom_element.offsetHeight;
|
|
var v = v1 - v2;
|
|
if (v < 0){
|
|
w1.set_height(w2.dom_element.offsetHeight);
|
|
} else if (v > 0) {
|
|
w2.set_height(w1.dom_element.offsetHeight);
|
|
}
|
|
}
|
|
var objcopy = function(obj){
|
|
var o = {}
|
|
for ( k in obj){
|
|
if (obj.hasOwnProperty(k)){
|
|
o[k] = obj[k];
|
|
}
|
|
}
|
|
return o;
|
|
}
|
|
|
|
bricks.playResponseAudio = async function(response, target){
|
|
var widget = null;
|
|
if (response.status != 200){
|
|
bricks.debug('playResponseAudio(): response.status != 200', response.status);
|
|
return;
|
|
}
|
|
if (typeof target == typeof ''){
|
|
widget = bricks.getWidgetById(target);
|
|
} else {
|
|
widget = bricks.widgetBuild(target);
|
|
}
|
|
if (! widget){
|
|
bricks.debug('playResponseAudio():', target, 'can not found or build a widget');
|
|
return;
|
|
}
|
|
const blob = await response.blob();
|
|
const url = URL.createObjectURL(blob);
|
|
widget.set_url(url);
|
|
widget.play();
|
|
}
|
|
|
|
bricks.widgetBuildWithData = async function(desc_tmpl, from_widget, data){
|
|
if (!desc_tmpl){
|
|
bricks.debug('bricks.widgetBuildWithData():data=', data, 'desc_tmpl=', desc_tmpl);
|
|
}
|
|
var s = bricks.obj_fmtstr(data, desc_tmpl);
|
|
var desc = JSON.parse(s);
|
|
var w = await bricks.widgetBuild(desc, from_widget);
|
|
if (! w){
|
|
bricks.debug(desc, 'widgetBuild() failed...........');
|
|
return;
|
|
}
|
|
w.row_data = data;
|
|
return w;
|
|
}
|
|
|
|
bricks.Observable = class {
|
|
constructor(owner, name, v){
|
|
this.owner = owner;
|
|
this.name = name;
|
|
this.value = v;
|
|
}
|
|
set(v){
|
|
if (this.value != v){
|
|
this.owner.dispatch(this.name, v);
|
|
}
|
|
this.value = v;
|
|
}
|
|
get(){
|
|
return this.v;
|
|
}
|
|
}
|