bricks/bricks/utils.js
2024-10-10 14:55:50 +08:00

377 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
return window.setTimeout(f, t);
}
var schedule_interval = function(f, t){
var mf = function(func, t){
console.log('arguments:', func, t);
func();
schedule_once(mf.bind(func, t), t);
}
return 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;
}
}