html {
}
q-component button { }
q-component basiccard {
q-property title: "Basic"
q-property message: "Ready"
}
q-component sourcecomp {
q-property myprop: "source value"
function genericfunction() { return this.myprop; }
}
q-component targetcomp {
q-property prop1: 24
q-property prop2: "hello"
q-property prop3: sourceObj
q-property prop4: sourceObj.myprop
q-property prop5: 24%
q-property prop6: 25vw
q-property prop7: 30px
q-property prop8: sourceObj.genericfunction
q-property prop9: sourceObj.genericfunction()
}
q-component signal-source {
q-signal mysignal(name, message)
}
q-component signal-receiver {
q-property lastMessage: "none"
function handleSignal(name, message) {
this.lastMessage = name + " said " + message;
alert(this.lastMessage);
}
}
q-component event-demo {
q-signal customnotice(message)
q-property myprop: "event property"
onclick { alert("Component click handler: " + this.myprop); }
oncustomnotice(message) { alert("Custom signal handler: " + message + " / " + this.myprop); }
}
q-component inline-demo {
q-property otherprop: "world"
q-property myprop: this.otherprop
}
q-component collection-demo {
q-property myarray: [25, 30, 35, 40]
q-property myobj: { key1: 25, key2: 30, key3: 40 }
}
q-component paintedcomp {
q-property color: "black"
q-property width: 240px
q-property height: 120px
q-property paintvars: [this.color, this.width, this.height]
onPaintBackground(paintvars) {
this.clearRect(white);
this.setFill(color);
this.drawRect(0, 0, parseFloat(width), parseFloat(height));
}
}
q-style style1 {
border: 2px solid green;
color: white;
background: #2f6f4e;
padding: 10px;
border-radius: 6px;
}
q-style style2 {
q-style-class { qhtml-style-two }
border: 2px solid #305f9f;
color: #0d2b4c;
background: #d9ecff;
padding: 10px;
border-radius: 6px;
}
q-style loudStyle {
border: 3px solid #c2410c;
color: #7c2d12;
background: #ffedd5;
padding: 10px;
border-radius: 6px;
}
q-theme mytheme {
div { style2 }
span { style1 }
h2 { loudStyle }
.someclass div { loudStyle }
}
q-default-theme mydefault {
.defaultbox { style1 }
}
q-theme mytheme2 {
q-child-theme { mytheme }
p { loudStyle }
}
h1 { text { QHTML7 feature examples } }
p { text { Each button uses QHTML onclick handlers. Style and theme sections should be visually inspectable directly. } }
section#coreSyntax {
h2 { text { 1. Core syntax } }
div.sample {
h3 { text { Product } }
p { text { Lightweight UI syntax. } }
}
div,section,h3 { text { Nested selector chain } }
div#main.card {
p { text { Class and id shorthand card body } }
}
div#my-id.my-class,span.my-class,h2#id2 { text { Multiple selector shorthand } }
button checkCore#checkCore {
text { Confirm core syntax }
onclick {
alert(
"h1: " + document.querySelector("h1").textContent +
"\n#main: " + document.querySelector("#main").textContent.trim() +
"\n#id2: " + document.querySelector("#id2").textContent.trim()
);
}
}
}
section#components {
h2 { text { 2. Components and functions } }
basiccard basicOne#basicOne {
div.sample {
h3 { text { Component instance rendered } }
p { text { This content is inside a q-component instance. } }
}
}
sourcecomp sourceObj#sourceObj { }
button functionButton#functionButton {
text { Call component function }
onclick {
alert("sourceObj.genericfunction() returned: " + document.querySelector("#sourceObj").genericfunction());
}
}
}
section#properties {
h2 { text { 3. Properties, references, units, and callable values } }
targetcomp targetObj#targetObj { }
button propertyButton#propertyButton {
text { Inspect properties }
onclick {
var target = document.querySelector("#targetObj");
alert(
"prop1 number: " + target.prop1 +
"\nprop2 string: " + target.prop2 +
"\nprop3 object id: " + target.prop3.id +
"\nprop4 path: " + target.prop4 +
"\nprop5 unit: " + target.prop5 +
"\nprop6 unit: " + target.prop6 +
"\nprop7 unit: " + target.prop7 +
"\nprop8 callable: " + target.prop8() +
"\nprop9 call result: " + target.prop9
);
}
}
button changePropertyButton#changePropertyButton {
text { Change referenced property }
onclick {
var source = document.querySelector("#sourceObj");
source.myprop = "changed source value";
alert("sourceObj.myprop is now: " + source.myprop);
}
}
}
section#signals {
h2 { text { 4. Signals } }
signal-source signalSender#signalSender { }
signal-receiver signalTarget#signalTarget { }
button connectSignalButton#connectSignalButton {
text { Connect and emit signal }
onclick {
var sender = document.querySelector("#signalSender");
var receiver = document.querySelector("#signalTarget");
sender.mysignal.disconnectAll();
sender.mysignal.connect(receiver.handleSignal);
sender.mysignal("bob", "hello");
alert("Receiver lastMessage property: " + receiver.lastMessage);
}
}
}
section#events {
h2 { text { 5. Event handlers } }
event-demo eventBox#eventBox {
div.sample { text { Click this component area to confirm component onclick. } }
}
button eventButton#eventButton {
q-signal customnotice(message)
q-property myprop: "button event property"
text { Trigger button handlers }
onclick {
alert("Button onclick with this.myprop: " + this.myprop);
this.customnotice("signal from button");
}
oncustomnotice(message) {
alert("Button custom signal handler received: " + message);
}
}
button mouseButton#mouseButton {
text { Confirm event parameter }
onclick(event) {
alert("Native event parameter type: " + event.type);
}
}
button caseButton#caseButton {
text { Confirm onCLICK casing }
onCLICK {
alert("Uppercase onCLICK is bound as click.");
}
}
button mousePressButton#mousePressButton {
text { Confirm mousepress mapping }
onmousepress(event) {
alert("onmousepress received native event: " + event.type);
}
}
button fireEventBoxSignal#fireEventBoxSignal {
text { Fire component custom signal }
onclick {
document.querySelector("#eventBox").customnotice("manual signal call");
}
}
}
section#inlineTemplates {
h2 { text { 6. Backtick inline templates } }
inline-demo inlineObj#inlineObj { }
button inlineButton#inlineButton {
text { Inspect inline template property }
onclick {
alert("inlineObj.myprop: " + document.querySelector("#inlineObj").myprop);
}
}
}
section#collections {
h2 { text { 7. Arrays and objects } }
collection-demo collectionObj#collectionObj { }
button collectionButton#collectionButton {
text { Mutate array and object }
onclick {
var demo = document.querySelector("#collectionObj");
demo.myarray.push(45);
demo.myobj.key4 = 50;
alert("array: " + demo.myarray.join(", ") + "\nobject key4: " + demo.myobj.key4);
}
}
}
section#htmlPrimitive {
h2 { text { 8. html primitive } }
div.sample {
div,span { html { Raw HTML inserted by html { } } }
}
button htmlButton#htmlButton {
text { Confirm raw HTML }
onclick {
alert(document.querySelector("#htmlPrimitive strong").textContent);
}
}
}
section#paint {
h2 { text { 9. Paint handlers } }
paintedcomp paintBox#paintBox {
div.sample {
text { This component receives a CSS paint background when paint worklets are available. }
}
}
button paintButton#paintButton {
text { Change paint color }
onclick {
var box = document.querySelector("#paintBox");
box.color = box.color === "black" ? "green" : "black";
alert("paintBox.color is now: " + box.color);
}
}
}
section#styles {
h2 { text { 10. Styles } }
style1 {
div#styleOne { text { style1 applied directly } }
}
style2 {
span#styleTwo { text { style2 applied directly } }
}
style1 { div {
style2 { span#combinedStyle {
text { style1 and style2 nested application }
} }
} }
style1,div,span#styleChain { text { style1 used in a selector chain } }
button styleButton#styleButton {
text { Change style1 live }
onclick {
var q = document.querySelector("q-html");
q.qhtmlComponentRegistry.stylesByName.get("style1").setCssText("border: 3px solid #7c3aed; color: white; background: #6d28d9; padding: 10px; border-radius: 6px;");
alert("style1 was changed. The green style boxes should now be purple.");
}
}
}
section#themes {
h2 { text { 11. Themes } }
mytheme {
div#themeDiv.theme-target { text { div styled by mytheme } }
span#themeSpan.theme-target { text { span styled by mytheme } }
h2#themeHeading { text { h2 styled by mytheme } }
div.someclass {
div#themeNested.theme-target { text { nested selector styled by mytheme } }
}
}
mydefault {
div#defaultThemeBox.defaultbox { text { q-default-theme fallback style } }
}
mytheme2 {
p#childThemeParagraph { text { q-child-theme plus local p rule } }
}
button themeButton#themeButton {
text { Change theme live }
onclick {
var q = document.querySelector("q-html");
q.qhtmlComponentRegistry.stylesByName.get("loudStyle").setCssText("border: 3px solid #0f766e; color: #134e4a; background: #ccfbf1; padding: 10px; border-radius: 6px;");
q.qhtmlComponentRegistry.themesByName.get("mytheme").refresh();
q.qhtmlComponentRegistry.themesByName.get("mytheme2").refresh();
alert("loudStyle was changed. Theme headline/nested/p boxes should now be teal.");
}
}
}
section {
q-component mycomp15 {
q-property myprop: 15
onmypropchanged{ alert(`changed myprop to ${this.myprop}`); }
div,span {
slot slotname { text { default contents when not specified } }
}
}
mycomp15 object15 {
}
button {
onclick { object15.myprop = 24; }
text { Click here }
}
}