Rwebgui
This commit is contained in:
parent
91ac6a17e8
commit
64d898c31b
@ -1,7 +1,7 @@
|
||||
[metadata]
|
||||
name = boeh
|
||||
name = rwebgui
|
||||
version = 1.0.0
|
||||
description = Service that says boeh when Joe talks.
|
||||
description = RWebGui
|
||||
author = retoor
|
||||
author_email = retoor@molodetz.nl
|
||||
license = MIT
|
||||
@ -15,11 +15,10 @@ package_dir =
|
||||
python_requires = >=3.7
|
||||
install_requires =
|
||||
app @ git+https://retoor.molodetz.nl/retoor/app
|
||||
matrix-nio
|
||||
|
||||
[options.packages.find]
|
||||
where = src
|
||||
|
||||
[options.entry_points]
|
||||
console_scripts =
|
||||
boeh = boeh.__main__:main
|
||||
rwebgui.serve = rwebgui.__main__:main
|
||||
|
0
src/rwebgui/__init__.py
Normal file
0
src/rwebgui/__init__.py
Normal file
17
src/rwebgui/__main__.py
Normal file
17
src/rwebgui/__main__.py
Normal file
@ -0,0 +1,17 @@
|
||||
from rwebgui.app import Application
|
||||
from aiohttp import web
|
||||
import asyncio
|
||||
|
||||
from concurrent.futures import ThreadPoolExecutor as Executor
|
||||
|
||||
|
||||
def main():
|
||||
app = Application()
|
||||
executor = Executor(max_workers=20)
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.set_default_executor(executor)
|
||||
web.run_app(app, loop=loop)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
172
src/rwebgui/app.py
Normal file
172
src/rwebgui/app.py
Normal file
@ -0,0 +1,172 @@
|
||||
import pathlib
|
||||
from aiohttp import web
|
||||
import uuid
|
||||
from app.app import Application as BaseApplication
|
||||
from rwebgui.component import Component
|
||||
import traceback
|
||||
import time
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
class EvalBox(Component):
|
||||
|
||||
async def on_change(self, value):
|
||||
|
||||
try:
|
||||
if value and value.strip().endswith("="):
|
||||
value = value.strip()[:-1]
|
||||
try:
|
||||
result = eval(value)
|
||||
value = value + "= " + str(result)
|
||||
await self.set_attr("value",value)
|
||||
except:
|
||||
pass
|
||||
except AttributeError as ex:
|
||||
print(value)
|
||||
return value
|
||||
|
||||
|
||||
|
||||
class Button(Component):
|
||||
|
||||
async def on_click(self, event):
|
||||
component = self.app.search
|
||||
await component.set_attr("value","Woeiii")
|
||||
|
||||
class Button1(Component):
|
||||
|
||||
async def on_click(self,event):
|
||||
field = self.app.search
|
||||
await field.toggle()
|
||||
value = await field.get_style("display","block")
|
||||
await self.set_attr("innerText", value)
|
||||
|
||||
class RandomString(Component):
|
||||
|
||||
|
||||
async def task_random(self):
|
||||
import random
|
||||
rand_bytes = [random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(15)]
|
||||
random_data = "".join(rand_bytes)
|
||||
while True:
|
||||
remember = random_data[0]
|
||||
random_data = random_data[1:] + remember
|
||||
await self.set_attr("innerHTML",random_data)
|
||||
await asyncio.sleep(0.01)
|
||||
|
||||
class Counter(Component):
|
||||
|
||||
async def task_test(self):
|
||||
while True:
|
||||
await asyncio.sleep(10)
|
||||
print("Slow task")
|
||||
|
||||
|
||||
|
||||
async def task_increment(self):
|
||||
if not self.value:
|
||||
self.value = 0
|
||||
while True:
|
||||
try:
|
||||
self.value = int(self.value)
|
||||
except:
|
||||
self.value = 0
|
||||
self.value += 1
|
||||
await self.set_attr("value",self.value)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
class GPT(Component):
|
||||
|
||||
class Children:
|
||||
prompt = Component
|
||||
answer = Component
|
||||
class submit(Component):
|
||||
async def trigger(self, id_, event, data):
|
||||
print("GOGOG",event,data)
|
||||
return await super().trigger(id_, event, data)
|
||||
async def on_click(self,data):
|
||||
from xmlrpc.client import ServerProxy
|
||||
client = ServerProxy("https://api.molodetz.nl/rpc")
|
||||
prompt = await self.app.prompt.get_attr("value")
|
||||
print(prompt)
|
||||
exit(0)
|
||||
|
||||
await self.answer.set_attr("value",client.gpt4o(prompt))
|
||||
return {"event_id":data['event_id'],"success":True}
|
||||
|
||||
class SpeedMeter(Component):
|
||||
|
||||
def __init__(self, app, id_, description=None, ws = None):
|
||||
self.time_start = time.time()
|
||||
self.bytes_received = 0
|
||||
super().__init__(app, id_, description, ws)
|
||||
|
||||
async def task_update(self):
|
||||
while True:
|
||||
bytes_received = self.bytes_received
|
||||
self.bytes_received = 0
|
||||
|
||||
await self.set_attr("value","{} kb/s".format(bytes_received / 1000))
|
||||
await asyncio.sleep(1)
|
||||
|
||||
async def trigger(self, id_, event, data):
|
||||
super().trigger(id_, event, data)
|
||||
print("JAA")
|
||||
self.bytes_received += len(json.dumps(data))
|
||||
|
||||
|
||||
class App(Component):
|
||||
|
||||
class Children:
|
||||
eval_box = EvalBox
|
||||
search = Component
|
||||
teller1 = Counter
|
||||
teller2 = Counter
|
||||
teller3 = Counter
|
||||
teller4 = Counter
|
||||
teller5 = Counter
|
||||
teller6 = Counter
|
||||
teller7 = Counter
|
||||
link1 = Button
|
||||
random1 = RandomString
|
||||
speed = SpeedMeter
|
||||
toggle = Button1
|
||||
gpt = GPT
|
||||
|
||||
_service = None
|
||||
|
||||
|
||||
class Application(BaseApplication):
|
||||
def __init__(self):
|
||||
self.location = pathlib.Path(__file__).parent
|
||||
self.location_static = self.location.joinpath("static")
|
||||
self.template_path = self.location.joinpath("templates")
|
||||
super().__init__(template_path=self.template_path)
|
||||
self.router.add_static('/static', self.location_static)
|
||||
self.router.add_get("/", self.index_handler)
|
||||
self.router.add_get("/ws/{uuid}", self.websocket_handler)
|
||||
|
||||
async def websocket_handler(self, request):
|
||||
# Extract the UUID from the route
|
||||
uuid_value = request.match_info['uuid']
|
||||
|
||||
# Validate if it's a valid UUID
|
||||
try:
|
||||
uuid_obj = uuid.UUID(uuid_value)
|
||||
except ValueError:
|
||||
return web.Response(text="Invalid UUID", status=400)
|
||||
|
||||
# Upgrade the connection to WebSocket
|
||||
ws = web.WebSocketResponse()
|
||||
await ws.prepare(request)
|
||||
|
||||
print(f"WebSocket connection established with UUID: {uuid_obj}")
|
||||
component = App(self, "app", ws=ws)
|
||||
await component.service()
|
||||
|
||||
return ws
|
||||
|
||||
|
||||
|
||||
async def index_handler(self, request):
|
||||
return await self.render_template("index.html",request,{})
|
239
src/rwebgui/component.py
Normal file
239
src/rwebgui/component.py
Normal file
@ -0,0 +1,239 @@
|
||||
import uuid
|
||||
import json
|
||||
import time
|
||||
import aiohttp
|
||||
import asyncio
|
||||
from aiohttp import web
|
||||
|
||||
class Component:
|
||||
|
||||
@classmethod
|
||||
def define(cls):
|
||||
return cls
|
||||
|
||||
def __init__(self,app, id_, description=None,ws: web.WebSocketResponse=None):
|
||||
|
||||
self.id = id_
|
||||
self.ws = ws
|
||||
self.app = app
|
||||
self.description = description
|
||||
self.children = []
|
||||
self._callbacks = {}
|
||||
self.value = None
|
||||
self._running = False
|
||||
if not hasattr(self,"Children"):
|
||||
return
|
||||
for name in dir(self.Children):
|
||||
if name.startswith("__"):
|
||||
continue
|
||||
|
||||
obj = getattr(self.Children, name)
|
||||
|
||||
instance = obj(app=self.app,id_=name,ws=ws )
|
||||
self.add_child(instance)
|
||||
instance.app = self
|
||||
instance.ws = self.ws
|
||||
setattr(self, name, instance)
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
obj = cls(None, None)
|
||||
obj.__dict__ = json
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def to_json(cls):
|
||||
obj = cls.__dict__ .copy()
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def clone(cls):
|
||||
return cls.from_json(cls.to_json())
|
||||
|
||||
@property
|
||||
def running(self):
|
||||
if not hasattr(self.app, "_running"):
|
||||
return self._running
|
||||
return self.app._running
|
||||
|
||||
@property
|
||||
def tasks(self):
|
||||
tasks_ = [getattr(self, name) for name in dir(self) if name.startswith("task_") and hasattr(self, name)]
|
||||
for child in self.children:
|
||||
tasks_ += child.tasks#.extend(await child.get_tasks())
|
||||
return tasks_
|
||||
|
||||
async def communicate(self, event_id=None):
|
||||
|
||||
async for msg in self.ws:
|
||||
if msg.type == web.WSMsgType.TEXT:
|
||||
# Echo the message back to the client
|
||||
#print(f"Received message: {msg.data}")
|
||||
data = msg.json()
|
||||
if not event_id:
|
||||
pass
|
||||
#return data
|
||||
else:
|
||||
if data.get("event_id") == event_id:
|
||||
return data
|
||||
|
||||
@property
|
||||
def callbacks(self):
|
||||
return hasattr(self.app, "callbacks") and self.app.callbacks or self._callbacks
|
||||
|
||||
|
||||
async def trigger(self,id_, event,data):
|
||||
if self.id == id_:
|
||||
method_name = "on_"+event
|
||||
if hasattr(self, method_name):
|
||||
method = getattr(self, method_name)
|
||||
await method(data)
|
||||
print("JAAJ")
|
||||
for child in self.children:
|
||||
await child.trigger(id_,event,data)
|
||||
|
||||
async def register_callback(self, event_id, callback):
|
||||
self.callbacks[event_id] = callback
|
||||
|
||||
async def call(self, method, args=None,id_=None, callback=True):
|
||||
while not self.running:
|
||||
await asyncio.sleep(0.1)
|
||||
if not args:
|
||||
args= []
|
||||
event_id = str(uuid.uuid4())
|
||||
loop = asyncio.get_running_loop()
|
||||
future = loop.create_future()
|
||||
|
||||
self.callbacks[event_id] = lambda data: future.set_result(data)
|
||||
await self.ws.send_json({
|
||||
"event_id": event_id,
|
||||
"event": "call",
|
||||
"id": id_ and id_ or self.id,
|
||||
"method": method,
|
||||
"args": args,
|
||||
"callback": callback
|
||||
})
|
||||
if callback:
|
||||
response = await self.communicate(event_id=event_id)
|
||||
return response['result']
|
||||
#print("GLUKT")
|
||||
#return response['result']
|
||||
|
||||
return True
|
||||
#return await future
|
||||
|
||||
|
||||
async def get_attr(self, key, default=None):
|
||||
result = await self.call("getAttr", [self.id, key],True)
|
||||
return result or default
|
||||
|
||||
async def set_attr(self, key, value):
|
||||
result = await self.call("setAttr", [self.id,key,value],callback=False)
|
||||
return result
|
||||
|
||||
async def get(self, id_):
|
||||
if self.id == id_:
|
||||
return self
|
||||
for child in self.children:
|
||||
child = await child.get(id_)
|
||||
if child:
|
||||
return child
|
||||
|
||||
async def set_data(self, key, value):
|
||||
result = await self.call("setData", [self.id, key,value], callback=False)
|
||||
return result
|
||||
|
||||
async def get_data(self, key, default=None):
|
||||
result = await self.call("getData", [self.id,key], default,True)
|
||||
return result or default
|
||||
|
||||
async def set_style(self, key, value):
|
||||
result = await self.call("setStyle", [self.id, key,value], callback=False)
|
||||
return result
|
||||
|
||||
async def toggle(self):
|
||||
value = await self.get_style("display", "block")
|
||||
|
||||
if value == "none":
|
||||
value = ""
|
||||
else:
|
||||
value = "none"
|
||||
await self.set_style("display", value)
|
||||
|
||||
async def get_style(self, key, default=None):
|
||||
result = await self.call("getStyle", [self.id,key], default)
|
||||
return result or default
|
||||
|
||||
|
||||
|
||||
|
||||
async def on_keyup(self,event):
|
||||
value = await self.get_attr("value")
|
||||
if self.value != value:
|
||||
if hasattr(self, "on_change"):
|
||||
value = await self.on_change(value)
|
||||
self.value = value
|
||||
return self.value
|
||||
|
||||
|
||||
async def get_tasks(self):
|
||||
tasks = self.tasks
|
||||
for child in self.children:
|
||||
tasks += child.tasks#.extend(await child.get_tasks())
|
||||
return tasks
|
||||
|
||||
async def set_running(self):
|
||||
self._running = True
|
||||
|
||||
async def get_message(self):
|
||||
async for msg in self.ws:
|
||||
return msg
|
||||
|
||||
async def service(self):
|
||||
tasks = self.tasks
|
||||
tasks.append(self.set_running)
|
||||
|
||||
async def events():
|
||||
try:
|
||||
async for msg in self.ws:
|
||||
if msg.type == web.WSMsgType.TEXT:
|
||||
# Echo the message back to the client
|
||||
#print(f"Received message: {msg.data}")
|
||||
data = msg.json()
|
||||
response = {"event_id":data['event_id'],"success":True}
|
||||
response['time_start'] = time.time()
|
||||
if self.callbacks.get(data['event_id']):
|
||||
self.callbacks[data['event_id']](data['result'])
|
||||
elif data.get('data') and not data['data'].get('id'):
|
||||
response['handled'] = False
|
||||
elif data.get('data'):
|
||||
response['handled'] = True
|
||||
response['data'] = await self.trigger(data['data']['id'], data['event'],data['data'])
|
||||
response['cancel'] = True
|
||||
|
||||
response['time_end'] = time.time()
|
||||
response['time_duration'] = response['time_end'] - response['time_start']
|
||||
await self.ws.send_json(response)
|
||||
|
||||
#await ws.send_str(f"Echo: {msg.data}")
|
||||
elif msg.type == web.WSMsgType.ERROR:
|
||||
print(f"WebSocket error: {self.ws.exception()}")
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
pass
|
||||
|
||||
|
||||
#async def the_task():
|
||||
# while True:
|
||||
# time.sleep(1)
|
||||
#while True:
|
||||
tasks.append(events)
|
||||
await asyncio.gather(*[task() for task in tasks])
|
||||
#await asyncio.create_task(asyncio.gather(*[task() for task in tasks]))
|
||||
#await tasks()
|
||||
print("AFTERR")
|
||||
|
||||
|
||||
def add_child(self, child):
|
||||
child.app = self.app
|
||||
child.ws = self.ws
|
||||
self.children.append(child)
|
295
src/rwebgui/static/rwebgui.js
Normal file
295
src/rwebgui/static/rwebgui.js
Normal file
@ -0,0 +1,295 @@
|
||||
|
||||
function elToObject(el){
|
||||
obj = {}
|
||||
if(el.targetElement)
|
||||
el = el.targetElement
|
||||
el.getAttributeNames().forEach(name => {
|
||||
obj[name] = el.getAttribute(name)
|
||||
if(el[name])
|
||||
obj[name] = el[name]
|
||||
})
|
||||
return obj
|
||||
}
|
||||
|
||||
function wrapElement(app, el){
|
||||
const allEvents = [
|
||||
'click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseenter',
|
||||
'mouseleave', 'mouseover', 'mouseout', 'keydown', 'keyup', 'keypress',
|
||||
'focus', 'blur', 'change', 'input', 'submit', 'reset', 'resize',
|
||||
'contextmenu', 'drag', 'drop', 'dragstart', 'dragend', 'dragover',
|
||||
'dragenter', 'dragleave', 'touchstart', 'touchmove', 'touchend',
|
||||
'touchcancel', 'pointerdown', 'pointerup', 'pointermove', 'pointerover',
|
||||
'pointerout', 'pointerenter', 'pointerleave', 'wheel'/*'scroll',*/
|
||||
// Add more as needed
|
||||
];
|
||||
const props = [
|
||||
'data',
|
||||
'id',
|
||||
'isTrusted',
|
||||
'altKey',
|
||||
'ctrlKey',
|
||||
'layerX',
|
||||
'layerY',
|
||||
'movementX',
|
||||
'movementY',
|
||||
'offsetX',
|
||||
'offsetY',
|
||||
'pageX',
|
||||
'pageY',
|
||||
'screenX',
|
||||
'screenY',
|
||||
'shiftKey',
|
||||
'metaKey',
|
||||
'value',
|
||||
'code',
|
||||
'keyCode',
|
||||
'key'
|
||||
]
|
||||
|
||||
el.app = app
|
||||
allEvents.forEach(event => {
|
||||
|
||||
el.addEventListener(event, async(e) => {
|
||||
if(el.app.suppress)
|
||||
return
|
||||
obj = {}
|
||||
obj["id"] = el.id ? el.id : el._uuid
|
||||
obj["uuid"] = el._uuid
|
||||
obj["event"] = event
|
||||
|
||||
obj['attrs'] = elToObject(el)
|
||||
obj['data'] = {}
|
||||
props.forEach(prop => {
|
||||
if(e[prop] != undefined){
|
||||
obj['data'][prop] = e[prop]
|
||||
}
|
||||
if(e["targetElement"] && e["targetElement"][prop] != undefined){
|
||||
obj['data'][prop] = e["targetElement"][prop]
|
||||
}
|
||||
})
|
||||
|
||||
//obj["data"] = JSON.stringify(e)
|
||||
obj["nr"] = el.app.inc()
|
||||
response = await el.app.emit(event, obj);
|
||||
|
||||
},false)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
HTMLElement.prototype.rWebGui = function(){
|
||||
|
||||
const rWebGui = this
|
||||
|
||||
const config = { attributes: true, childList: true, subtree: true };
|
||||
const callback = (mutationList, observer) => {
|
||||
for (const mutation of mutationList) {
|
||||
|
||||
if (mutation.type === "childList") {
|
||||
mutation.addedNodes.forEach(child => {
|
||||
|
||||
wrapElement(rWebGui, child)
|
||||
if(!child._uuid){
|
||||
child._uuid = rWebGui.createUUID()
|
||||
}
|
||||
|
||||
})
|
||||
} else if (mutation.type === "attributes") {
|
||||
obj = {}
|
||||
obj["uuid"] = mutation.target._uuid
|
||||
|
||||
obj[mutation.attributeName] = mutation.target.getAttribute(mutation.attributeName)
|
||||
rWebGui.emit("attributeChanged", obj)
|
||||
}
|
||||
}
|
||||
};
|
||||
// Create an observer instance linked to the callback function
|
||||
const observer = new MutationObserver(callback);
|
||||
|
||||
// Start observing the target node for configured mutations
|
||||
observer.observe(rWebGui, config);
|
||||
|
||||
// Later, you can stop observing
|
||||
//observer.disconnect();
|
||||
|
||||
}
|
||||
|
||||
|
||||
class MyCustomElement extends HTMLElement {
|
||||
static observedAttributes = ["color", "size"];
|
||||
_ready = false
|
||||
_uuid = null
|
||||
ws = null
|
||||
_inc = 0;
|
||||
connected = false
|
||||
callbacks = {}
|
||||
suppress = false
|
||||
inc() {
|
||||
this._inc++;
|
||||
return this._inc
|
||||
}
|
||||
|
||||
get isReady() {
|
||||
return this.app._ready && this.app.connected
|
||||
}
|
||||
|
||||
constructor() {
|
||||
// Always call super first in constructor
|
||||
super();
|
||||
if(!this.parent || !this.parent.app){
|
||||
this.ws = new WebSocket(`ws://${window.location.host}/ws/${this.uuid}`)
|
||||
const me = this
|
||||
this.ws.onopen = ()=>{
|
||||
me.connected = true;
|
||||
}
|
||||
this.ws.onmessage = (e)=>{
|
||||
const data = JSON.parse(e.data)
|
||||
|
||||
if(data.event_id){
|
||||
if(me.callbacks[data.event_id])
|
||||
{
|
||||
me.callbacks[data.event_id](data)
|
||||
}else if(data.event == "call"){
|
||||
const method = me[data.method]
|
||||
if(!method){
|
||||
data['success'] = false;
|
||||
data['result'] = null;
|
||||
}else{
|
||||
let response = method(...data.args)
|
||||
data['result'] = response
|
||||
data['success'] = true
|
||||
}
|
||||
if(data['callback'])
|
||||
me.ws.send(JSON.stringify(
|
||||
data
|
||||
))
|
||||
}else {
|
||||
if(data.event == "set_attr"){
|
||||
const el = document.getElementById(data['id'])
|
||||
if(el){
|
||||
data['data'].forEach(attr=>{
|
||||
el.setAttribute(attr['name'], attr['value'])
|
||||
el[attr['name']] = attr['value']
|
||||
})}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getAttr(id,key){
|
||||
const el = document.getElementById(id)
|
||||
if (el[key] != undefined)
|
||||
return el[key]
|
||||
return el.getAttribute(key)
|
||||
}
|
||||
getData(id,key){
|
||||
const el = document.getElementById(id)
|
||||
return el.dataset[key]
|
||||
}
|
||||
setData(id,key,value){
|
||||
const el = document.getElementById(id)
|
||||
el.dataset[key] = value
|
||||
return true
|
||||
}
|
||||
setStyle(id, key, value){
|
||||
const el = document.getElementById(id)
|
||||
el.style[key] = value
|
||||
}
|
||||
getStyle(id, key){
|
||||
return document.getElementById(id).style[key]
|
||||
}
|
||||
setAttr(id, key, value) {
|
||||
try{
|
||||
document.getElementById(id).setAttribute(key, value)
|
||||
document.getElementById(id)[key] = value
|
||||
}catch(e){
|
||||
console.error("Element not found:", key)
|
||||
console.error("Failed to set value:", value)
|
||||
}
|
||||
return true
|
||||
}
|
||||
get isApp(){
|
||||
return !this.parent || !this.parent.app
|
||||
}
|
||||
|
||||
emit(event, data) {
|
||||
if(!this.app.isReady)
|
||||
|
||||
return false;
|
||||
const me = this
|
||||
return new Promise(resolve => {
|
||||
data["event_id"] = me.inc()
|
||||
me.callbacks[data["event_id"]] = resolve
|
||||
me.app.ws.send(JSON.stringify({"uuid":obj.uuid,"event_id":data["event_id"], "event": event, "data": data}))
|
||||
|
||||
}).then(res => {
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
get uuid() {
|
||||
if(!this._uuid){
|
||||
this._uuid = this.createUUID()
|
||||
}
|
||||
return this._uuid
|
||||
}
|
||||
|
||||
createUUID(){
|
||||
const uuid = crypto.randomUUID();
|
||||
return uuid
|
||||
}
|
||||
|
||||
get app() {
|
||||
if(!this.parent)
|
||||
return this
|
||||
if(!this.parent.app)
|
||||
return this
|
||||
return this.parent.app
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
console.log("Custom element added to page.");
|
||||
|
||||
|
||||
this.rWebGui()
|
||||
if(!this.isApp){
|
||||
this._uuid = this.generateUUID()
|
||||
this._ready = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// this.querySelectorAll("*").forEach(child => {
|
||||
// child.rWebGui()
|
||||
// })
|
||||
/// this.dataset.uuid = this.generateUUID();
|
||||
this._ready = true
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
console.log("Custom element removed from page.");
|
||||
}
|
||||
|
||||
adoptedCallback() {
|
||||
console.log("Custom element moved to new page.");
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
this.emit("attributeChanged", {aa:123})
|
||||
console.log(`Attribute ${name} has changed.`);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("rwebgui-app", MyCustomElement);
|
||||
|
||||
/*
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
console.log("DOM fully loaded and parsed");
|
||||
document.querySelectorAll("*").forEach(child => {
|
||||
child.rWebGui()
|
||||
})
|
||||
})*/;
|
38
src/rwebgui/templates/index.html
Normal file
38
src/rwebgui/templates/index.html
Normal file
@ -0,0 +1,38 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="/static/rwebgui.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<rwebgui-app id="app">
|
||||
|
||||
<h1>I do stuff</h1>
|
||||
<h2 id="header2">I do stuff</h1>
|
||||
<h3>I do stuff</h1>
|
||||
<h4 id="header4">I do stuff</h1>
|
||||
<input id="eval_box" type="text" value="wiii" />
|
||||
<input id="search" type="text" value="wiii" />
|
||||
<input id="teller1" type="text" value="wiii" />
|
||||
<input id="teller2" type="text" value="wiii" />
|
||||
<input id="teller3" type="text" value="wiii" />
|
||||
<input id="teller4" type="text" value="wiii" />
|
||||
<input id="teller5" type="text" value="wiii" />
|
||||
<input id="teller6" type="text" value="wiii" />
|
||||
<input id="teller7" type="text" value="wiii" />
|
||||
<a href="#" id="link1">I do stuff</a>
|
||||
<a href="#" id="toggle">I do stuff</a>
|
||||
<input id="speed" type="text" value="wiii" />
|
||||
|
||||
<div id="random1"></div>
|
||||
|
||||
<div >
|
||||
<textarea id="prompt" type="text" value=""></textarea>
|
||||
<textarea id="answer" type="text" value=""></textarea>
|
||||
<input id="submit" type="button" value="Submit" />
|
||||
|
||||
</div>
|
||||
|
||||
</rwebgui-app>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user