Files
leonwww/flumi/Scripts/Constants.gd
2025-08-09 14:57:29 +03:00

2185 lines
76 KiB
GDScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends Node
const MAIN_COLOR = Color(27/255.0, 27/255.0, 27/255.0, 1)
const SECONDARY_COLOR = Color(43/255.0, 43/255.0, 43/255.0, 1)
const HOVER_COLOR = Color(0, 0, 0, 1)
const DEFAULT_CSS = """
body { text-base text-[#000000] text-left }
h1 { text-5xl font-bold }
h2 { text-4xl font-bold }
h3 { text-3xl font-bold }
h4 { text-2xl font-bold }
h5 { text-xl font-bold }
b { font-bold }
i { font-italic }
u { underline }
small { text-xl }
mark { bg-[#FFFF00] }
code { text-xl font-mono }
a { text-[#1a0dab] }
pre { text-xl font-mono }
button { text-[16px] bg-[#1b1b1b] rounded-md text-white hover:bg-[#2a2a2a] active:bg-[#101010] }
button[disabled] { bg-[#666666] text-[#999999] cursor-not-allowed }
"""
var HTML_CONTENT2 = """<head>
<title>My Custom Dashboard</title>
<icon src="https://cdn-icons-png.flaticon.com/512/1828/1828774.png">
<meta name="theme-color" content="#1a202c">
<meta name="description" content="A stylish no-script dashboard">
<font name="roboto" src="https://fonts.gstatic.com/s/roboto/v48/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2" />
<style>
h1 { text-[#ffffff] text-3xl font-bold }
h2 { text-[#cbd5e1] text-xl }
p { text-[#94a3b8] text-base }
button { bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e] active:bg-[#15803d] }
.card { bg-[#1e293b] text-[#f8fafc] rounded-xl p-4 shadow-lg }
</style>
</head>
<body style="bg-[#0f172a] p-8 text-white font-roboto">
<h1 style="text-center mb-4">📊 My Dashboard</h1>
<!-- Top Summary Cards -->
<div style="flex flex-row gap-4 justify-center flex-wrap">
<div style="card w-48 h-24 flex flex-col justify-center items-center">
<h2 style="text-red-500">Users</h2>
<p>1,240</p>
</div>
<div style="card w-48 h-24 flex flex-col justify-center items-center">
<h2>Sales</h2>
<p>$9,842</p>
</div>
<div style="card w-48 h-24 flex flex-col justify-center items-center">
<h2>Visitors</h2>
<p>3,590</p>
</div>
</div>
<separator direction="horizontal" />
<!-- User Info Panel -->
<h2 style="text-center mt-6">👤 User Panel</h2>
<div style="flex flex-row gap-4 justify-center mt-2">
<div style="card w-64">
<p>Name: Jane Doe</p>
<p>Email: jane@example.com</p>
<p>Status: <span style="text-[#22c55e]">Active</span></p>
</div>
<div style="card w-64">
<p>Plan: Pro</p>
<p>Projects: 8</p>
<p>Tasks: 42</p>
</div>
</div>
<separator direction="horizontal" />
<!-- Recent Activity Log -->
<h2 style="text-center mt-6">📝 Recent Activity</h2>
<ul style="w-[80%] mt-2 flex justify-center flex-column gap-2">
<li style="bg-[#334155] px-4 py-2 rounded-xl mb-1"> Task "Update UI" marked as complete</li>
<li style="bg-[#334155] px-4 py-2 rounded-xl mb-1">🔔 New comment on "Bug Fix #224"</li>
<li style="bg-[#334155] px-4 py-2 rounded-xl mb-1">📤 Exported report "Q2 Metrics"</li>
</ul>
<separator direction="horizontal" />
<!-- Action Buttons -->
<h2 style="text-center mt-6">🔧 Actions</h2>
<div style="flex flex-row gap-2 justify-center mt-2">
<button style="rounded-lg px-4 py-2">Create Report</button>
<button style="rounded-lg px-4 py-2 bg-[#3b82f6] hover:bg-[#2563eb] active:bg-[#1e40af]">Invite User</button>
<button style="rounded-lg px-4 py-2 bg-[#facc15] text-[#000] hover:bg-[#eab308] active:bg-[#ca8a04]">Upgrade Plan</button>
</div>
</body>
""".to_utf8_buffer()
var HTML_CONTENTvv = """<head>
<title>My cool web</title>
<icon src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Google_%22G%22_logo.svg/768px-Google_%22G%22_logo.svg.png\">
<meta name=\"theme-color\" content=\"#000000\">
<meta name=\"description\" content=\"My cool web\">
<font name="roboto" src="https://fonts.gstatic.com/s/roboto/v48/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2" />
<style>
h1 { text-[#ff0000] font-italic hover:text-[#00ff00] }
button { hover:bg-[#FF6B35] hover:text-[#FFFFFF] active:bg-[#CC5429] active:text-[#F0F0F0] }
</style>
<style src=\"styles.css\">
<script src=\"script.lua\" />
</head>
<body>
<h1>Header 1</h1>
<h2>Header 2</h2>
<h3>Header 3</h3>
<h4>Header 4</h4>
<h5>Header 5</h5>
<h6>Header 6</h6>
<separator />
<p>Normal font</p>
<p style="font-mono">Mono font</p>
<p style="font-sans">Sans font</p>
<p style="font-roboto">Custom font - Roboto</p>
<p>Hey there! this is a test</p>
<b>This is bold</b>
<i>This is italic <mark>actually, and it's pretty <u>cool</u></mark></i>
<u>This is underline</u>
<small>this is small</small>
<mark>this is marked</mark>
<code>this is code<span> THIS IS A SPAN AND SHOULDNT BE ANY DIFFERENT</span></code>
<p>
<a href="https://youtube.com">Hello gang</a>
</p>
<pre>
Text in a pre element
is displayed in a fixed-width
font, and it preserves
both spaces and
line breaks
</pre>
<p style="text-center w-32 h-32">
So
</p>
<div>
<button style="rounded-lg px-4 py-2 cursor-pointer">Create Report</button>
<button style="rounded-lg px-4 py-2 bg-[#3b82f6] hover:bg-[#2563eb] active:bg-[#1e40af] cursor-pointer">Invite User</button>
<button style="rounded-lg px-4 py-2 bg-[#facc15] text-[#000] hover:bg-[#eab308] active:bg-[#ca8a04] cursor-pointer">Upgrade Plan</button>
</div>
<button disabled="true">Disabled Button</button>
<button>Normal Button</button>
<separator direction="horizontal" />
<!-- Test CSS Properties -->
<h2 style="text-center mt-6">🧪 CSS Properties Test</h2>
<div style="flex flex-col gap-2 justify-center items-center mt-2">
<div style="bg-[#ef4444] text-white p-4 rounded-lg opacity-75 z-10 cursor-pointer">
<p>Opacity 75% with cursor pointer and z-index 10 - Text should show pointer cursor, not I-beam</p>
</div>
<div style="bg-[#10b981] text-white p-4 rounded-lg opacity-50 z-20 cursor-text">
<p>Opacity 50% with cursor text and z-index 20 - Text should show I-beam cursor</p>
</div>
<div style="bg-[#8b5cf6] text-white p-4 rounded-lg opacity-[0.25] z-[999] cursor-default">
<p>Custom opacity 0.25 with cursor default and z-index 999 - Text should show arrow cursor</p>
</div>
<div style="bg-[#f59e0b] text-white p-2 rounded cursor-move">
<p>Cursor move - Text should show move cursor</p>
</div>
<div style="bg-[#06b6d4] text-white p-2 rounded cursor-crosshair">
<p>Cursor crosshair - Text should show crosshair cursor</p>
</div>
<div style="bg-[#84cc16] text-white p-2 rounded cursor-help">
<p>Cursor help - Text should show help cursor</p>
</div>
<div style="bg-[#ec4899] text-white p-2 rounded cursor-not-allowed">
<p>Cursor not-allowed - Text should show forbidden cursor</p>
</div>
</div>
<separator direction="horizontal" />
<!-- Test cursor inheritance -->
<h2 style="text-center mt-6">🖱 Cursor Inheritance Test</h2>
<div style="cursor-pointer bg-[#1e293b] p-4 rounded-lg">
<p>This paragraph is inside a div with cursor-pointer.</p>
<p>Both paragraphs should show pointer cursor instead of default I-beam.</p>
<div style="bg-[#334155] p-2 rounded mt-2">
<p>This nested paragraph should also inherit the pointer cursor.</p>
</div>
</div>
<!-- Border examples -->
<div style="border p-2 mb-2">border</div>
<div style="border-2 p-2 mb-2">border-2</div>
<div style="border-4 p-2 mb-2">border-4</div>
<div style="border-2 border-red-500 p-2 mb-2">border-2 border-red-500</div>
<div style="border p-2 mb-2">border-solid</div>
<div style="border border-dashed p-2 mb-2">border-dashed</div>
<div style="border border-dotted p-2 mb-2">border-dotted</div>
<div style="border-none p-2 mb-2">border-none</div>
<div style="border-t p-2 mb-2">border-t</div>
<div style="border-r p-2 mb-2">border-r</div>
<div style="border-b p-2 mb-2">border-b</div>
<div style="border-l p-2 mb-2">border-l</div>
<div style="border-t-4 p-2 mb-2">border-t-4</div>
<div style="border-b-2 p-2 mb-2">border-b-2</div>
<div style="border-l-6 p-2 mb-2">border-l-6</div>
<div style="border-t-3 border-green-500 p-2 mb-2">border-t-3 border-green-500</div>
<div style="border border-white p-2 mb-2">border-white</div>
<div style="border border-black p-2 mb-2">border-black</div>
<div style="border border-transparent p-2 mb-2">border-transparent</div>
<div style="border border-gray-400 p-2 mb-2">border-gray-400</div>
<div style="border border-slate-700 p-2 mb-2">border-slate-700</div>
<div style="border border-red-500 p-2 mb-2">border-red-500</div>
<div style="border border-green-600 p-2 mb-2">border-green-600</div>
<div style="border border-blue-400 p-2 mb-2">border-blue-400</div>
<div style="border border-yellow-300 p-2 mb-2">border-yellow-300</div>
<select style=\"text-center max-w-5 max-h-32\">
<option value=\"test1\">Test 1</option>
<option value=\"test2\" selected=\"true\">Test 2</option>
<option value=\"test3\">Test 3</option>
<option value=\"test4\" disabled=\"true\">Test 4</option>
<option value=\"test5\">Test 5</option>
</select>
<textarea />
<textarea cols=\"30\" />
<textarea rows=\"2\" />
<textarea maxlength=\"20\" />
<textarea readonly=\"true\">le skibidi le toilet</textarea>
<textarea disabled=\"true\" value=\"DISABLED\" />
<textarea placeholder=\"this is a placeholder...\" />
<!-- action, method, and type=submit are for when we implement Lua -->
<form action=\"/submit\" method=\"POST\">
<span>Name:</span>
<input type=\"text\" placeholder=\"First name\" value=\"John\" maxlength=\"20\" minlength=\"3\" />
<span>Email regex:</span>
<input type=\"text\" placeholder=\"Last name\" value=\"Doe\" pattern=\"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$\" />
<span>Smart:</span>
<input type=\"checkbox\" />
<input type=\"checkbox\" value=\"true\" />
<p>favorite food</p>
<input type=\"radio\" group=\"food\" />
<span>Pizza</span>
<input type=\"radio\" group=\"food\" />
<span>Berry</span>
<input type=\"radio\" group=\"food\" />
<span>Gary</span>
<h2>Color</h2>
<input type=\"color\" value=\"#ff0000\" />
<h2>Date</h2>
<input type=\"date\" value=\"2018-07-22\" />
<h2>Range Slider</h2>
<input style=\"max-w-2 max-h-2\" type=\"range\" min=\"0\" max=\"100\" step=\"5\" value=\"50\" />
<h2>Number Input</h2>
<input type=\"number\" min=\"1\" max=\"10\" step=\"0.5\" value=\"5\" placeholder=\"Enter number\" />
<h2>File Upload</h2>
<input type=\"file\" accept=\".txt,.pdf,image/*\" />
</form>
<separator direction=\"horizontal\" />
# Ordered list
<ol>
<li>hello gang</li>
<li>this</li>
<li>is</li>
</ol>
<ol type=\"zero-lead\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ol>
<ol type=\"lower-alpha\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ol>
<ol type=\"upper-alpha\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ol>
<ol type=\"lower-roman\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ol>
<ol type=\"upper-roman\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ol>
<ul>
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ul>
<ul type=\"circle\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ul>
<ul type=\"none\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ul>
<ul type=\"square\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ul>
<img style=\"text-center max-w-24 max-h-24\" src=\"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQMNUPIKabszX0Js_c0kfa4cz_JQYKfGTuBUA&s\" />
<separator direction=\"vertical\" />
<!-- FLEXBOX EXAMPLES -->
<h2>Flex Row (gap, justify-between, items-center)</h2>
<div style=\"flex flex-row gap-4 justify-between items-center w-64 h-16 bg-[#f0f0f0]\">
<span style=\"bg-[#ffaaaa] w-16 h-8 flex items-center justify-center\">A</span>
<span style=\"bg-[#aaffaa] w-16 h-8 flex items-center justify-center\">B</span>
<span style=\"bg-[#aaaaff] w-16 h-8 flex items-center justify-center\">C</span>
</div>
<h2>Flex Column (gap, items-center, content-center)</h2>
<div style=\"flex flex-col gap-2 items-center content-center h-32 w-32 bg-[#e0e0e0]\">
<span style=\"bg-[#ffaaaa] w-16 h-6 flex items-center justify-center\">1</span>
<span style=\"bg-[#aaffaa] w-16 h-6 flex items-center justify-center\">2</span>
<span style=\"bg-[#aaaaff] w-16 h-6 flex items-center justify-center\">3</span>
</div>
<h2>Flex Wrap (row, wrap, gap)</h2>
<div style=\"flex flex-row flex-wrap gap-2 w-40 bg-[#f8f8f8]\">
<span style=\"bg-[#ffaaaa] w-16 h-6 flex items-center justify-center\">X</span>
<span style=\"bg-[#aaffaa] w-16 h-6 flex items-center justify-center\">Y</span>
<span style=\"bg-[#aaaaff] w-16 h-6 flex items-center justify-center\">Z</span>
<span style=\"bg-[#ffffaa] w-16 h-6 flex items-center justify-center\">W</span>
</div>
<h2>Flex Grow/Shrink/Basis</h2>
<div style=\"flex flex-row gap-2 w-64 bg-[#f0f0f0]\">
<span style=\"bg-[#ffaaaa] flex-grow-1 h-8 flex items-center justify-center\">Grow 1</span>
<span style=\"bg-[#aaffaa] flex-grow-2 h-8 flex items-center justify-center\">Grow 2</span>
<span style=\"bg-[#aaaaff] flex-shrink-0 w-8 h-8 flex items-center justify-center\">No Shrink</span>
</div>
<h2>Align Self</h2>
<div style=\"flex flex-row h-24 bg-[#f0f0f0] items-stretch gap-2 w-64\">
<span style=\"bg-[#ffaaaa] w-12 h-8 self-start flex items-center justify-center\">Start</span>
<span style=\"bg-[#aaffaa] w-12 h-8 self-center flex items-center justify-center\">Center</span>
<span style=\"bg-[#aaaaff] w-12 h-8 self-end flex items-center justify-center\">End</span>
<span style=\"bg-[#ffffaa] w-12 h-8 self-stretch flex items-center justify-center\">Stretch</span>
</div>
</body>""".to_utf8_buffer()
var HTML_CONTENT_S = """<head>
<title>CSS Selector Tests</title>
<style>
/* Descendant selectors */
div p { text-[#663399] }
.container span { bg-[#ffeeaa] }
/* Direct child selectors */
.outer-div > p { font-bold }
.parent > button { bg-[#44cc88] }
/* Adjacent sibling selectors */
h1 + p { text-[#ff0000] font-bold }
h2 + div { bg-[#eeffee] }
/* General sibling selectors */
h1 ~ p { text-[#0000ff] }
h1 ~ .second-p { text-[#0000ff] }
h3 ~ span { bg-[#ffdddd] }
/* Attribute selectors */
input[type="text"] { border border-[#cccccc] bg-[#f9f9f9] }
a[href^="https"] { text-[#008000] font-bold }
button[disabled] { bg-[#888888] text-[#cccccc] }
input[placeholder*="email"] { border-2 border-[#0066cc] bg-[#ffffff] }
div[style$="special"] { bg-[#ffffaa] }
</style>
</head>
<body>
<h1>CSS Selector Test Page</h1>
<p>This paragraph should be red and bold (h1 + p)</p>
<p style="second-p">This paragraph should be blue (h1 ~ p)</p>
<h2>Descendant vs Child Selectors</h2>
<div style="outer-div">
<p>This paragraph should be purple and bold (div p and .outer-div > p)</p>
<div>
<p>This paragraph should be purple but not bold (div p only)</p>
</div>
</div>
<h3>Attribute Selectors</h3>
<input type="text" placeholder="Enter your name" />
<input type="text" placeholder="Enter your email address" />
<input type="password" placeholder="Enter password" />
<br />
<a href="http://example.com">HTTP Link (normal)</a>
<br />
<a href="https://secure.com">HTTPS Link (green and bold)</a>
<br />
<button>Normal Button</button>
<button disabled="true">Disabled Button (gray)</button>
<h3>Sibling Selectors</h3>
<div style="bg-[#eeffee]">This div should have light green bg (h2 + div)</div>
<span>This span should have light red bg (h3 ~ span)</span>
<span>This span should also have light red bg (h3 ~ span)</span>
<div style="container">
<span>This span should have yellow bg (.container span)</span>
<p>Regular paragraph in container</p>
</div>
<div style="parent">
<button>This button should be green (.parent > button)</button>
<div>
<button>This button should be normal (not direct child)</button>
</div>
</div>
<div style="item-special">This div should have yellow bg (class ends with 'special')</div>
<div style="special-item">This div should be normal</div>
</body>
""".to_utf8_buffer()
var HTML_CONTENT3 = """<head>
<title>Task Manager</title>
<icon src="https://cdn-icons-png.flaticon.com/512/126/126472.png">
<meta name="theme-color" content="#1e1e2f">
<meta name="description" content="Manage your tasks easily.">
<style>
h1 { text-[#4ade80] text-3xl font-bold }
p { text-[#94a3b8] text-lg }
input { border border-[#cbd5e1] px-2 py-1 rounded }
</style>
<script src="logic.lua" />
</head>
<body>
<h1 style="text-center">📝 My Task Manager</h1>
<p style="text-center mb-4">Keep track of your to-do list</p>
<!-- Task List -->
<div style="flex flex-col gap-2 w-80 mx-auto bg-[#f8fafc] p-4 rounded">
<span style="flex justify-between items-center bg-[#e2e8f0] px-2 py-1 rounded">
<span> Finish homework</span>
<button style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Delete</button>
</span>
<span style="flex justify-between items-center bg-[#e2e8f0] px-2 py-1 rounded">
<span> Write blog post</span>
<button style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Delete</button>
</span>
<span style="flex justify-between items-center bg-[#e2e8f0] px-2 py-1 rounded">
<span>💪 Gym workout</span>
<button style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Delete</button>
</span>
</div>
<separator direction="horizontal" />
<!-- Add New Task -->
<h2 style="text-center mt-4">Add a New Task</h2>
<form action="/add-task" method="POST" style="flex flex-col gap-2 w-80 mx-auto">
<input type="text" placeholder="Enter task..." minlength="3" required="true" />
<input type="date" />
<button type="submit" style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Add Task</button>
</form>
<separator direction="horizontal" />
<h2 style="text-center">Task Categories</h2>
<div style="flex flex-row gap-2 justify-center items-center w-full">
<span style="bg-[#fef3c7] px-4 py-2 rounded">📚 Study</span>
<span style="bg-[#d1fae5] px-4 py-2 rounded">💼 Work</span>
<span style="bg-[#e0e7ff] px-4 py-2 rounded">🏋 Health</span>
</div>
<form>
<input type=\"password\" placeholder=\"your password...\" />
<button type=\"submit\" style=\"bg-[#4CAF50] rounded-lg text-[#FFFFFF]\">Submit</button>
<button style=\"bg-[#2196F3] rounded-xl text-[#FFFFFF]\">Blue Button</button>
<button style=\"bg-[#FF5722] rounded-full text-[#FFFFFF]\">Orange Pill</button>
<button style=\"bg-[#9C27B0] rounded-[20px] text-[#FFFFFF]\">Purple Custom</button>
<button style=\"bg-[#FFD700] rounded text-[#000000] hover:bg-[#FFA500] hover:text-[#FFFFFF]\">Hover Test</button>
</form>
<h2>Button Style Tests</h2>
<button>Normal, no-styling button.</button>
<h3>Corner Radius Variants</h3>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-none\">No Radius</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-sm\">Small (2px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded\">Default (4px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-md\">Medium (6px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-lg\">Large (8px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-xl\">Extra Large (12px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-2xl\">2XL (16px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-3xl\">3XL (24px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-full\">Full (Pill)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-[30px]\">Custom 30px</button>
<h3>Color Combinations</h3>
<button style=\"bg-[#FF6B6B] text-[#FFFFFF] rounded-lg\">Red Background</button>
<button style=\"bg-[#4ECDC4] text-[#2C3E50] rounded-lg\">Teal & Dark Text</button>
<button style=\"bg-[#45B7D1] text-[#FFFFFF] rounded-lg\">Sky Blue</button>
<button style=\"bg-[#96CEB4] text-[#2C3E50] rounded-lg\">Mint Green</button>
<button style=\"bg-[#FFEAA7] text-[#2D3436] rounded-lg\">Yellow Cream</button>
<button style=\"bg-[#DDA0DD] text-[#FFFFFF] rounded-lg\">Plum Purple</button>
<button style=\"bg-[#98D8C8] text-[#2C3E50] rounded-lg\">Seafoam</button>
<h3>Hover Effects</h3>
<button style=\"bg-[#3498DB] text-[#FFFFFF] rounded-lg hover:bg-[#2980B9] hover:text-[#F8F9FA]\">Blue Hover</button>
<button style=\"bg-[#E67E22] text-[#FFFFFF] rounded-xl hover:bg-[#D35400] hover:text-[#ECF0F1]\">Orange Hover</button>
<button style=\"bg-[#9B59B6] text-[#FFFFFF] rounded-full hover:bg-[#8E44AD] hover:text-[#F4F4F4]\">Purple Pill Hover</button>
<button style=\"bg-[#1ABC9C] text-[#FFFFFF] rounded-2xl hover:bg-[#16A085]\">Turquoise Hover</button>
<h3>Advanced Hover Combinations</h3>
<button style=\"bg-[#34495E] text-[#ECF0F1] rounded hover:bg-[#E74C3C] hover:text-[#FFFFFF]\">Dark to Red</button>
<button style=\"bg-[#F39C12] text-[#2C3E50] rounded-lg hover:bg-[#27AE60] hover:text-[#FFFFFF]\">Gold to Green</button>
<button style=\"bg-[#FFFFFF] text-[#2C3E50] rounded-xl hover:bg-[#2C3E50] hover:text-[#FFFFFF]\">Light to Dark</button>
<h3>Text Color Focus</h3>
<button style=\"text-[#E74C3C] rounded-lg\">Red Text Only</button>
<button style=\"text-[#27AE60] rounded-lg\">Green Text Only</button>
<button style=\"text-[#3498DB] rounded-lg\">Blue Text Only</button>
<button style=\"text-[#9B59B6] rounded-full\">Purple Text Pill</button>
<h3>Mixed Styles</h3>
<button style=\"bg-[#FF7675] text-[#FFFFFF] rounded-[15px] hover:bg-[#FD79A8] hover:text-[#2D3436]\">Custom Mix 1</button>
<button style=\"bg-[#6C5CE7] text-[#DDD] rounded-3xl hover:bg-[#A29BFE] hover:text-[#2D3436]\">Custom Mix 2</button>
<button style=\"bg-[#00B894] text-[#FFFFFF] rounded-[25px] hover:bg-[#00CEC9] hover:text-[#2D3436]\">Custom Mix 3</button>
<button style=\"bg-[#0000ff] text-[#FFFFFF] rounded-[25px] hover:bg-[#ff0000] hover:text-[#2D3436]\">Blue normal, red hover</button>
<h3>Active State Tests</h3>
<button style=\"bg-[#3498DB] text-[#FFFFFF] rounded-lg hover:bg-[#2980B9] active:bg-[#1F618D] active:text-[#F8F9FA]\">Blue with Active</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-xl hover:bg-[#C0392B] active:bg-[#A93226] active:text-[#ECF0F1]\">Red with Active</button>
<button style=\"bg-[#27AE60] text-[#FFFFFF] rounded-full hover:bg-[#229954] active:bg-[#1E8449] active:text-[#D5DBDB]\">Green Pill Active</button>
<button style=\"bg-[#F39C12] text-[#2C3E50] rounded hover:bg-[#E67E22] hover:text-[#FFFFFF] active:bg-[#D35400] active:text-[#F7F9FC]\">Gold Multi-State</button>
<button style=\"bg-[#9B59B6] text-[#FFFFFF] rounded-2xl active:bg-[#7D3C98] active:text-[#E8DAEF]\">Purple Active Only</button>
</body>
""".to_utf8_buffer()
var HTML_CONTENTvvv = """
<head>
<title>Lua API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#000080">
<meta name="description" content="Demonstrating the GURT Lua API">
<style>
body { bg-[#f8f9fa] p-6 }
h1 { text-[#2563eb] text-2xl font-bold }
.container { bg-[#ffffff] p-4 rounded-lg shadow-lg }
.demo-button { bg-[#3b82f6] text-white px-4 py-2 rounded hover:bg-[#2563eb] }
.fancy { bg-green-500 text-red-500 p-2 rounded-full mt-2 mb-2 text-2xl hover:bg-red-300 hover:text-[#2563eb] }
</style>
<script>
local typing = gurt.select('#type')
local mouse = gurt.select('#mouse')
local btnmouse = gurt.select('#btnmouse')
gurt.log('Starting Lua script execution...')
gurt.body:on('keypress', function(el)
typing.text = table.tostring(el)
end)
gurt.body:on('mousemove', function(el)
mouse.text = table.tostring(el)
end)
-- Test element selection and manipulation
local heading = gurt.select('#main-heading')
heading.text = 'Welcome to the New Web!'
local button = gurt.select('#demo-button')
local event_log = gurt.select('#event-log')
button:on('mousedown', function()
print('Mouse down')
end)
button:on('mouseup', function()
print('Mouse up')
end)
button:on('mouseenter', function()
print('Mouse enter')
end)
button:on('mouseexit', function()
print('Mouse exit')
end)
button:on('mousemove', function(el)
btnmouse.text = table.tostring(el)
end)
if button and event_log then
local click_count = 0
local subscription = button:on('click', function()
click_count = click_count + 1
local new_text = 'Button clicked ' .. click_count .. ' time(s)!'
event_log.text = new_text
end)
heading:on('focusin', function()
print('oh u flck')
subscription:unsubscribe()
end)
gurt.log('Event listener attached to button with subscription ID')
else
gurt.log('Could not find button or event log element')
end
-- DOM Manipulation Demo
gurt.log('Testing DOM manipulation...')
-- Create a new div with styling
local new_div = gurt.create('div', { style = 'bg-red-500 p-4 rounded-lg mb-4' })
-- Create a paragraph with text
local new_p = gurt.create('p', {
style = 'text-white font-bold text-lg',
text = 'This element was created dynamically with Lua!'
})
-- Append paragraph to div
new_div:append(new_p)
-- Append div to body
gurt.body:append(new_div)
-- Create another element to test removal
local temp_element = gurt.create('div', {
style = 'bg-yellow-400 p-2 rounded text-black',
text = 'This will be removed in 3 seconds...'
})
gurt.body:append(temp_element)
local test = gurt.setTimeout(function()
print('removed')
temp_element:remove()
end, 3000)
-- gurt.clearTimeout(test)
local addBtn = gurt.select('#add-class')
local removeBtn = gurt.select('#remove-class')
local btnTarget = gurt.select('#btnTarget')
addBtn:on('click', function()
btnTarget.classList:add('fancy')
-- btnTarget.classList:toggle('fancy')
print('Class added')
end)
removeBtn:on('click', function()
btnTarget.classList:remove('fancy')
print('Class removed')
end)
</script>
</head>
<body>
<h1 id="main-heading">Welcome to GURT Lua API Demo</h1>
<div style="container">
<p>This page demonstrates the GURT Lua API in action.</p>
<div id="demo-button" style="w-40 h-40 bg-red-500 p-4 rounded-lg">Click me to see Lua in action!</div>
</div>
<p id="event-log" style="mt-4 p-4 bg-[#f3f4f6] rounded min-h-24">Click the button</p>
<p id="mouse" style="mt-4 p-4 bg-[#f3f4f6] rounded min-h-24">Move your mouse</p>
<p id="btnmouse" style="mt-4 p-4 bg-[#f3f4f6] rounded min-h-24">Move mouse over Button</p>
<p id="type" style="mt-4 p-4 bg-[#f3f4f6] rounded min-h-24">Type something</p>
<div style="mt-6 flex gap-4 items-center">
<div style="text-lg font-semibold">Style Controls:</div>
<button id="add-class" style="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700">Add Class</button>
<button id="remove-class" style="bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700">Remove Class</button>
</div>
<button id="btnTarget" style="bg-gray-600">Button</button>
</body>""".to_utf8_buffer()
var HTML_CONTENT_ADD_REMOVE = """<head>
<title>Lua List Manipulation Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#000080">
<meta name="description" content="Adding and popping list items with GURT Lua API">
<style>
body { bg-[#f8f9fa] p-6 }
h1 { text-[#2563eb] text-4xl font-bold }
.container { flex flex-row bg-[#ffffff] p-4 rounded-lg shadow-lg }
.demo-button { bg-[#3b82f6] text-white px-4 py-2 rounded hover:bg-[#2563eb] cursor-pointer }
ul { list-disc pl-6 }
li { text-[#111827] py-1 }
</style>
<script>
local add_button = gurt.select('#add-button')
local pop_button = gurt.select('#pop-button')
local list = gurt.select('#item-list')
local counter = 1
gurt.log('List manipulation script started.')
add_button:on('click', function()
local new_item = gurt.create('li', {
text = 'Item #' .. counter
})
list:append(new_item)
counter = counter + 1
end)
pop_button:on('click', function()
local items = list.children
local last = items[#items]
if last then
last:remove()
counter = math.max(1, counter - 1)
end
end)
</script>
</head>
<body>
<h1 id="main-heading">List Manipulation with Lua</h1>
<div style="container">
<p>Use the buttons below to add or remove items from the list:</p>
<button id="add-button" style="demo-button inline-block mr-2">Add Item</button>
<button id="pop-button" style="demo-button inline-block">Pop Item</button>
</div>
<ul id="item-list" style="mt-4 bg-[#f3f4f6] p-4 rounded min-h-24">
<!-- List items will appear here -->
</ul>
</body>
""".to_utf8_buffer()
var HTML_CONTENT_DOM_MANIPULATION = """
<head>
<title>DOM Utilities Test</title>
<style>
.test-item { bg-[#e0e7ef] text-[#22223b] rounded p-2 mb-2 }
.highlight { bg-[#ffd700] }
</style>
<script>
local log = gurt.select("#log")
local function log_msg(msg)
log.text = log.text .. msg .. "\\n"
end
local parent = gurt.select("#parent")
local child1 = gurt.select("#child1")
local child2 = gurt.select("#child2")
local child3 = gurt.select("#child3")
print(log)
-- Show DOM property usage
log.text = ""
log_msg("parent of child2: " .. table.tostring(child2.parent))
log_msg("nextSibling of child2: " .. table.tostring(child2.nextSibling))
log_msg("previousSibling of child2: " .. table.tostring(child2.previousSibling))
log_msg("firstChild of parent: " .. table.tostring(parent.firstChild))
log_msg("lastChild of parent: " .. table.tostring(parent.lastChild))
-- Insert Before
gurt.select("#btn-insert-before"):on("click", function()
local newDiv = gurt.create("div", { class = "test-item highlight", text = "Inserted Before Child 2" })
parent:insertBefore(newDiv, child2)
log_msg("Inserted before child2: " .. newDiv._element_id)
end)
-- Insert After
gurt.select("#btn-insert-after"):on("click", function()
local newDiv = gurt.create("div", { class = "test-item highlight", text = "Inserted After Child 2" })
parent:insertAfter(newDiv, child2)
log_msg("Inserted after child2: " .. newDiv._element_id)
end)
-- Replace
gurt.select("#btn-replace"):on("click", function()
local newDiv = gurt.create("div", { class = "test-item highlight", text = "Replacement for Child 2" })
parent:replace(newDiv, child2)
log_msg("Replaced child2 with: " .. newDiv._element_id)
end)
-- Clone
gurt.select("#btn-clone"):on("click", function()
local clone = child3:clone(true)
parent:append(clone)
log_msg("Cloned child3: " .. clone._element_id)
end)
</script>
</head>
<body>
<h1>DOM Utilities Demo</h1>
<div id="parent" style="bg-[#f8fafc] p-4 rounded flex flex-col gap-2">
<div class="test-item">Non-interactible</div>
<div id="child1" class="test-item">Child 1</div>
<div id="child2" class="test-item">Child 2</div>
<div id="child3" class="test-item">Child 3</div>
</div>
<div style="flex gap-2 mt-4">
<button id="btn-insert-before">Insert Before Child 2</button>
<button id="btn-insert-after">Insert After Child 2</button>
<button id="btn-replace">Replace Child 2</button>
<button id="btn-clone">Clone Child 3</button>
</div>
<p id="log" style="mt-4 text-[#444] text-sm">Test</p>
</body>
""".to_utf8_buffer()
var HTML_CONTENTc = """<head>
<title>Input Events API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#059669">
<meta name="description" content="Demonstrating input element events with GURT Lua API">
<style>
body { bg-[#f0fdf4] p-6 }
h1 { text-[#059669] text-3xl font-bold text-center }
h2 { text-[#047857] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.form-group { flex flex-col gap-2 mb-4 }
.input-demo { bg-[#f8fafc] p-4 rounded-lg border }
.event-log { bg-[#1f2937] text-white p-4 rounded-lg font-mono text-sm max-h-64 overflow-auto }
.form-button { bg-[#10b981] text-white px-4 py-2 rounded hover:bg-[#059669] cursor-pointer }
.clear-btn { bg-[#ef4444] text-white px-4 py-2 rounded hover:bg-[#dc2626] cursor-pointer }
</style>
<script>
-- Get the event log element
local eventLog = gurt.select('#event-log')
local function logEvent(elementType, eventType, data)
local timestamp = Time.format(Time.now(), '%H:%M:%S')
local message = '[' .. timestamp .. '] ' .. elementType .. ' -> ' .. eventType
if data then
message = message .. ': ' .. data
end
print(message)
end
-- Text Input Events
local textInput = gurt.select('#text-input')
print('Text input found:', textInput)
if textInput then
textInput:on('input', function(e)
logEvent('Text Input', 'input', e.value)
end)
textInput:on('change', function(e)
logEvent('Text Input', 'change', e.value)
end)
textInput:on('focusin', function()
logEvent('Text Input', 'focusin', nil)
end)
textInput:on('focusout', function()
logEvent('Text Input', 'focusout', nil)
end)
else
print('Text input not found!')
end
-- Email Input Events
local emailInput = gurt.select('#email-input')
emailInput:on('input', function(e)
logEvent('Email Input', 'input', e.value)
end)
emailInput:on('change', function(e)
logEvent('Email Input', 'change', e.value)
end)
-- Password Input Events
local passwordInput = gurt.select('#password-input')
passwordInput:on('input', function(e)
logEvent('Password Input', 'input', table.tostring(e))
end)
passwordInput:on('change', function(e)
logEvent('Password Input', 'change', table.tostring(e))
end)
-- Number Input Events
local numberInput = gurt.select('#number-input')
numberInput:on('change', function(e)
logEvent('Number Input', 'change', e.value)
end)
-- Range Input Events
local rangeInput = gurt.select('#range-input')
rangeInput:on('change', function(e)
logEvent('Range Input', 'change', e.value)
end)
-- Color Input Events
local colorInput = gurt.select('#color-input')
colorInput:on('change', function(e)
logEvent('Color Input', 'change', e.value)
end)
-- Date Input Events
local dateInput = gurt.select('#date-input')
dateInput:on('change', function(e)
logEvent('Date Input', 'change', e.value)
end)
-- File Input Events
local fileInput = gurt.select('#file-input')
fileInput:on('change', function(e)
if e.dataURL then
e.dataURL = e.dataURL:sub(1, 100)
end
if e.text then
e.text = e.text:sub(1, 100)
end
logEvent('File Input', 'change', table.tostring(e))
end)
-- Checkbox Events
local checkbox = gurt.select('#checkbox')
checkbox:on('change', function(e)
logEvent('Checkbox', 'change', table.tostring(e))
end)
-- Radio Button Events
local radio1 = gurt.select('#radio1')
local radio2 = gurt.select('#radio2')
local radio3 = gurt.select('#radio3')
radio1:on('change', function(e)
logEvent('Radio Button 1', 'change', table.tostring(e))
end)
radio2:on('change', function(e)
logEvent('Radio Button 2', 'change', table.tostring(e))
end)
radio3:on('change', function(e)
logEvent('Radio Button 3', 'change', table.tostring(e))
end)
-- Textarea Events
local textarea = gurt.select('#textarea')
textarea:on('input', function(e)
logEvent('Textarea', 'input', e.value:sub(1, 20) .. '...')
end)
textarea:on('change', function(e)
logEvent('Textarea', 'change', 'Length: ' .. #e.value)
end)
-- Select Events
local selectElement = gurt.select('#select-element')
selectElement:on('change', function(e)
logEvent('Select', 'change', 'Index: ' .. table.tostring(e))
end)
-- Button Events
local submitBtn = gurt.select('#submit-btn')
submitBtn:on('click', function()
logEvent('Submit Button', 'click', nil)
end)
submitBtn:on('submit', function(e)
logEvent('Form', 'submit', table.tostring(e))
end)
-- Clear log button
local clearBtn = gurt.select('#clear-btn')
clearBtn:on('click', function()
eventLog.text = '--- Event Log Cleared ---\\n'
eventCount = 0
end)
-- Initial log message
logEvent('System', 'initialized', 'Input events demo ready')
</script>
</head>
<body>
<h1>🎛 Input Events API Demo</h1>
<div style="container mt-6">
<div style="flex flex-row gap-6">
<!-- Input Forms Column -->
<div style="flex-1">
<h2>Input Elements</h2>
<form id="demo-form">
<div style="form-group">
<label>Text Input:</label>
<input id="text-input" key="username" type="text" placeholder="Type something..." />
</div>
<div style="form-group">
<label>Email Input:</label>
<input id="email-input" key="email" type="email" placeholder="Enter email..." />
</div>
<div style="form-group">
<label>Password Input:</label>
<input id="password-input" key="password" type="password" placeholder="Enter password..." />
</div>
<div style="form-group">
<label>Number Input:</label>
<input id="number-input" key="score" type="number" min="0" max="100" value="50" />
</div>
<div style="form-group">
<label>Range Input:</label>
<input id="range-input" key="volume" type="range" min="0" max="100" value="25" />
</div>
<div style="form-group">
<label>Color Input:</label>
<input id="color-input" key="favoriteColor" type="color" value="#ff0000" />
</div>
<div style="form-group">
<label>Date Input:</label>
<input id="date-input" key="birthDate" type="date" value="2024-01-01" />
</div>
<div style="form-group">
<label>File Input:</label>
<input id="file-input" key="attachment" type="file" accept=".txt,.pdf,.png" />
</div>
<div style="form-group">
<input id="checkbox" key="newsletter" type="checkbox" />
<p>Checkbox Option</p>
</div>
<div style="form-group">
<input id="radio1" key="option" type="radio" group="options" value="option1" /><span>Option 1</span>
<input id="radio2" key="option" type="radio" group="options" value="option2" /><span>Option 2</span>
<input id="radio3" key="option" type="radio" group="options" value="option3" /><span>Option 3</span>
</div>
<div style="form-group">
<label>Textarea:</label>
<textarea id="textarea" key="message" placeholder="Write something longer..." rows="3"></textarea>
</div>
<div style="form-group">
<label>Select Dropdown:</label>
<select id="select-element" key="fruit">
<option value="apple">Apple</option>
<option value="banana" selected="true">Banana</option>
<option value="orange">Orange</option>
<option value="grape">Grape</option>
</select>
</div>
<div style="flex gap-2">
<button id="submit-btn" type="submit" style="form-button">Submit Form</button>
<button id="clear-btn" type="button" style="clear-btn">Clear Log</button>
</div>
</form>
</div>
<!-- Event Log Column -->
<div style="flex-1">
<h2>Event Log</h2>
<div style="event-log">
<pre id="event-log">Waiting for events...
</pre>
</div>
<div style="bg-[#e0f2fe] p-4 rounded-lg mt-4">
<h3 style="text-[#0277bd] font-semibold mb-2">Available Events:</h3>
<ul style="text-[#01579b] space-y-1 text-sm">
<li><strong>input:</strong> Fires as you type (real-time)</li>
<li><strong>change:</strong> Fires when value changes and element loses focus</li>
<li><strong>focusin:</strong> Fires when element gains focus</li>
<li><strong>focusout:</strong> Fires when element loses focus</li>
<li><strong>click:</strong> Fires when button is clicked</li>
<li><strong>submit:</strong> Fires when form is submitted (includes form data)</li>
</ul>
</div>
</div>
</div>
</div>
</body>
""".to_utf8_buffer()
var HTML_CONTENT_CLIPBOARD = """<head>
<title>Network & Clipboard API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#059669">
<meta name="description" content="Demonstrating Network fetching and Clipboard operations">
<style>
body { bg-[#f0fdf4] p-6 }
h1 { text-[#059669] text-3xl font-bold text-center }
h2 { text-[#047857] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.clipboard-btn { bg-[#10b981] text-white hover:bg-[#059669] p-4 }
.copy-url-btn { bg-[#8b5cf6] text-white hover:bg-[#7c3aed] }
</style>
<script>
gurt.log('Script started!')
local copyBtn = gurt.select('#copy-text-btn')
copyBtn:on('click', function()
gurt.log('Copy button clicked!')
Clipboard.write('Hello from GURT!')
end)
</script>
</head>
<body>
<h1>Clipboard API</h1>
<div style="container mt-6">
<h2>Clipboard Operations</h2>
<div style="button-group mb-6">
<button id="copy-text-btn" style="action-button clipboard-btn">📋 Copy Text</button>
</div>
</div>
</body>
""".to_utf8_buffer()
var HTML_CONTENTx = """<head>
<title>Signal API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#8b5cf6">
<meta name="description" content="Demonstrating the new Signal API with custom events">
<style>
body { bg-[#f8fafc] p-6 }
h1 { text-[#8b5cf6] text-3xl font-bold text-center }
h2 { text-[#6d28d9] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.signal-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors }
.fire-btn { bg-[#10b981] text-white hover:bg-[#059669] }
.connect-btn { bg-[#3b82f6] text-white hover:bg-[#2563eb] }
.disconnect-btn { bg-[#ef4444] text-white hover:bg-[#dc2626] }
.log-area { bg-[#f1f5f9] p-4 rounded-lg min-h-32 font-mono text-sm }
.status-display { bg-[#ddd6fe] p-3 rounded-md text-[#5b21b6] font-mono }
.info-box { bg-[#fef3c7] border border-[#f59e0b] p-4 rounded-lg }
</style>
<script>
-- Create custom signals
local mySignal = Signal.new()
local dataSignal = Signal.new()
local userActionSignal = Signal.new()
print(".container > div: ", gurt.selectAll('.container > div'))
print(".container div: ", gurt.selectAll('.container div'))
print("button[disabled]: ", gurt.selectAll('button[disabled]'))
print(".container: ", gurt.selectAll('.container'))
print("#log-area: ", gurt.selectAll('#log-area'))
-- Get UI elements
local logArea = gurt.select('#log-area')
local statusDisplay = gurt.select('#status-display')
local connectBtn = gurt.select('#connect-btn')
local disconnectBtn = gurt.select('#disconnect-btn')
local fireBtn = gurt.select('#fire-btn')
local fireDataBtn = gurt.select('#fire-data-btn')
local clearLogBtn = gurt.select('#clear-log-btn')
gurt.log('Signal API demo script started.')
local logMessages = {}
local connectionCount = 0
local activeConnections = {}
-- Function to add message to log
local function addLog(message)
table.insert(logMessages, Time.format(Time.now(), '%H:%M:%S') .. ' - ' .. message)
if #logMessages > 20 then
table.remove(logMessages, 1)
end
logArea.text = table.concat(logMessages, '\\n')
end
-- Function to update status
local function updateStatus()
statusDisplay.text = 'Active Connections: ' .. #activeConnections .. '\\nTotal Events Fired: ' .. connectionCount
end
-- Signal handlers
local function onMySignal(arg1, arg2)
addLog('mySignal fired with args: ' .. (arg1 or 'nil') .. ', ' .. (arg2 or 'nil'))
end
local function onDataSignal(data)
addLog('dataSignal received: ' .. table.tostring(data))
end
local function onUserAction(action, timestamp)
addLog('userActionSignal: ' .. action .. ' at ' .. timestamp)
end
-- Connect button
connectBtn:on('click', function()
-- Connect multiple handlers to demonstrate multiple connections
local conn1 = mySignal:connect(onMySignal)
local conn2 = dataSignal:connect(onDataSignal)
local conn3 = userActionSignal:connect(onUserAction)
table.insert(activeConnections, conn1)
table.insert(activeConnections, conn2)
table.insert(activeConnections, conn3)
addLog('Connected 3 signal handlers')
updateStatus()
end)
-- Disconnect button
disconnectBtn:on('click', function()
for i = 1, #activeConnections do
activeConnections[i]:disconnect()
end
activeConnections = {}
addLog('Disconnected all signal handlers')
updateStatus()
end)
-- Fire simple signal
fireBtn:on('click', function()
mySignal:fire('Hello', 123)
connectionCount = connectionCount + 1
addLog('Fired mySignal with two arguments')
updateStatus()
end)
-- Fire data signal
fireDataBtn:on('click', function()
local sampleData = {
user = 'Alice',
score = math.random(100, 999),
items = {'sword', 'shield', 'potion'}
}
dataSignal:fire(sampleData)
connectionCount = connectionCount + 1
addLog('Fired dataSignal with complex data')
updateStatus()
end)
-- Fire user action signal
gurt.body:on('keypress', function(keyInfo)
if #activeConnections > 0 then
userActionSignal:fire('keypress: ' .. keyInfo.key, Time.format(Time.now(), '%H:%M:%S'))
connectionCount = connectionCount + 1
updateStatus()
end
end)
-- Clear log button
clearLogBtn:on('click', function()
logMessages = {}
logArea.text = 'Log cleared.'
addLog('Log area cleared')
end)
-- Initialize with some sample connections
local initialConn = mySignal:connect(function(a, b)
addLog('Initial handler triggered with: ' .. (a or 'nil') .. ', ' .. (b or 'nil'))
end)
table.insert(activeConnections, initialConn)
addLog('Signal API demo initialized')
addLog('Try connecting handlers and firing signals!')
addLog('Press any key to trigger userActionSignal (when connected)')
updateStatus()
</script>
</head>
<body>
<h1>🔔 Signal API Demo</h1>
<div style="container mt-6">
<div style="info-box mb-6">
<p><strong>Signal API Usage Example:</strong></p>
<p><code>local mySignal = Signal.new()</code></p>
<p><code>mySignal:connect(function(arg1, arg2) print("Event fired with: ", arg1, arg2) end)</code></p>
<p><code>mySignal:fire("Hello", 123)</code></p>
<p><code>connection:disconnect()</code></p>
</div>
<h2>Controls</h2>
<div style="button-group mb-6">
<button id="connect-btn" style="signal-button connect-btn">🔗 Connect Handlers</button>
<button id="disconnect-btn" style="signal-button disconnect-btn"> Disconnect All</button>
<button id="fire-btn" style="signal-button fire-btn">🔔 Fire Simple Signal</button>
<button id="fire-data-btn" style="signal-button fire-btn">📊 Fire Data Signal</button>
<button id="clear-log-btn" style="signal-button">🧹 Clear Log</button>
</div>
<h2>Status</h2>
<div style="status-display mb-6">
<pre id="status-display">Loading status...</pre>
</div>
<h2>Event Log</h2>
<div style="log-area mb-6">
<pre id="log-area">Initializing...</pre>
</div>
<div style="bg-[#e0f2fe] p-4 rounded-lg">
<h3 style="text-[#0277bd] font-semibold mb-2">Signal API Features:</h3>
<ul style="text-[#01579b] space-y-1">
<li><strong>Signal.new():</strong> Creates a new signal object</li>
<li><strong>signal:connect(callback):</strong> Connects a callback function and returns a connection object</li>
<li><strong>signal:fire(...):</strong> Fires the signal with optional arguments</li>
<li><strong>connection:disconnect():</strong> Disconnects a specific connection</li>
<li><strong>signal:disconnect():</strong> Disconnects all connections from the signal</li>
<li><strong>Multiple Connections:</strong> One signal can have multiple connected callbacks</li>
<li><strong>Argument Passing:</strong> Signals can pass multiple arguments to connected callbacks</li>
</ul>
</div>
<button disabled="true">Test</button>
<button disabled="true">Test2</button>
</div>
</body>
""".to_utf8_buffer()
var HTML_CONTENTa = """<head>
<title>Button getAttribute/setAttribute Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#3b82f6">
<meta name="description" content="Demonstrating getAttribute and setAttribute with button controls">
<style>
body { bg-[#f8fafc] p-6 }
h1 { text-[#3b82f6] text-3xl font-bold text-center }
h2 { text-[#1e40af] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.control-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors }
.enable-btn { bg-[#10b981] text-white hover:bg-[#059669] }
.disable-btn { bg-[#ef4444] text-white hover:bg-[#dc2626] }
.toggle-btn { bg-[#8b5cf6] text-white hover:bg-[#7c3aed] }
.status-btn { bg-[#6b7280] text-white hover:bg-[#4b5563] }
.demo-buttons { bg-[#f1f5f9] p-4 rounded-lg }
.status-display { bg-[#e0e7ff] p-3 rounded-md text-[#3730a3] font-mono }
.info-box { bg-[#fef3c7] border border-[#f59e0b] p-4 rounded-lg }
.target-button { bg-[#3b82f6] text-white px-6 py-3 rounded-lg font-semibold hover:bg-[#2563eb] }
.target-button[disabled] { bg-[#9ca3af] text-[#6b7280] cursor-not-allowed }
</style>
<script>
local targetButton = gurt.select('#target-button')
local enableBtn = gurt.select('#enable-btn')
local disableBtn = gurt.select('#disable-btn')
local toggleBtn = gurt.select('#toggle-btn')
local statusBtn = gurt.select('#status-btn')
local statusDisplay = gurt.select('#status-display')
local infoBox = gurt.select('#info-box')
local clickCounter = gurt.select('#click-counter')
gurt.log('Button attribute demo script started.')
local clickCount = 0
-- Function to update the status display
local function updateStatus()
local disabled = targetButton:getAttribute('disabled')
local type = targetButton:getAttribute('type')
local style = targetButton:getAttribute('style')
local id = targetButton:getAttribute('id')
local dataValue = targetButton:getAttribute('data-value')
local status = 'Status: ' .. (disabled and 'DISABLED' or 'ENABLED') .. '\\n'
status = status .. 'Type: ' .. (type or 'button') .. '\\n'
status = status .. 'ID: ' .. (id or 'none') .. '\\n'
status = status .. 'Data Value: ' .. (dataValue or 'none') .. '\\n'
status = status .. 'Click Count: ' .. clickCount
statusDisplay.text = status
-- Update info box with current state
if disabled then
infoBox.text = '🔒 Target button is currently DISABLED. It cannot be clicked and appears grayed out.'
else
infoBox.text = '✅ Target button is currently ENABLED. Click it to see the counter increase!'
end
end
-- Target button click handler
targetButton:on('click', function()
clickCount = clickCount + 1
clickCounter.text = 'Button clicked ' .. clickCount .. ' times!'
gurt.log('Target button clicked! Count:', clickCount)
updateStatus()
end)
-- Enable button functionality
enableBtn:on('click', function()
targetButton:setAttribute('disabled', '') -- Remove disabled attribute
targetButton:setAttribute('data-value', 'enabled')
gurt.log('Target button enabled via setAttribute')
updateStatus()
end)
-- Disable button functionality
disableBtn:on('click', function()
targetButton:setAttribute('disabled', 'true')
targetButton:setAttribute('data-value', 'disabled')
gurt.log('Target button disabled via setAttribute')
updateStatus()
end)
-- Toggle button functionality
toggleBtn:on('click', function()
local currentlyDisabled = targetButton:getAttribute('disabled')
if currentlyDisabled then
-- Currently disabled, so enable it
targetButton:setAttribute('disabled', '')
targetButton:setAttribute('data-value', 'toggled-enabled')
gurt.log('Target button toggled to enabled state')
else
-- Currently enabled, so disable it
targetButton:setAttribute('disabled', 'true')
targetButton:setAttribute('data-value', 'toggled-disabled')
gurt.log('Target button toggled to disabled state')
end
updateStatus()
end)
-- Status check button
statusBtn:on('click', function()
local disabled = targetButton:getAttribute('disabled')
local type = targetButton:getAttribute('type')
local dataValue = targetButton:getAttribute('data-value')
gurt.log('=== BUTTON STATUS CHECK ===')
gurt.log('Disabled attribute:', disabled or 'not set')
gurt.log('Type attribute:', type or 'not set')
gurt.log('Data-value attribute:', dataValue or 'not set')
gurt.log('Click count:', clickCount)
gurt.log('===========================')
-- Demonstrate style setAttribute
local randomColors = {'bg-red-500', 'bg-green-500', 'bg-purple-500', 'bg-orange-500', 'bg-pink-500'}
local randomColor = randomColors[math.random(1, #randomColors)]
if not disabled then
targetButton:setAttribute('style', 'target-button ' .. randomColor .. ' text-white px-6 py-3 rounded-lg font-semibold hover:opacity-75')
gurt.setTimeout(function()
targetButton:setAttribute('style', 'target-button bg-[#3b82f6] text-white px-6 py-3 rounded-lg font-semibold hover:bg-[#2563eb]')
end, 1000)
end
end)
-- Initialize status display
updateStatus()
-- Set initial attributes to demonstrate the methods
targetButton:setAttribute('type', 'button')
targetButton:setAttribute('data-value', 'initial')
-- Update status after setting initial attributes
gurt.setTimeout(function()
updateStatus()
end, 100)
</script>
</head>
<body>
<h1>🔘 Button getAttribute & setAttribute Demo</h1>
<div style="container mt-6">
<div style="info-box mb-6">
<p id="info-box"> Target button is currently ENABLED. Click it to see the counter increase!</p>
</div>
<h2>Target Button</h2>
<div style="demo-buttons mb-6 text-center">
<button id="target-button" style="target-button">🎯 Click Me!</button>
<p id="click-counter" style="mt-3 text-lg font-semibold text-[#374151]">Button clicked 0 times!</p>
</div>
<h2>Control Buttons</h2>
<div style="button-group mb-6">
<button id="enable-btn" style="control-button enable-btn">🟢 Enable Button</button>
<button id="disable-btn" style="control-button disable-btn">🔴 Disable Button</button>
<button id="toggle-btn" style="control-button toggle-btn">🔄 Toggle State</button>
<button id="status-btn" style="control-button status-btn">📊 Check Status</button>
</div>
<h2>Current Attributes</h2>
<div style="status-display mb-6">
<pre id="status-display">Loading status...</pre>
</div>
<div style="bg-[#e0f2fe] p-4 rounded-lg">
<h3 style="text-[#0277bd] font-semibold mb-2">How It Works:</h3>
<ul style="text-[#01579b] space-y-1">
<li><strong>Enable:</strong> Uses <code>setAttribute('disabled', '')</code> to remove the disabled attribute</li>
<li><strong>Disable:</strong> Uses <code>setAttribute('disabled', 'true')</code> to add the disabled attribute</li>
<li><strong>Toggle:</strong> Uses <code>getAttribute('disabled')</code> to check current state, then toggles it</li>
<li><strong>Status:</strong> Uses <code>getAttribute()</code> to read multiple attributes and displays them</li>
<li><strong>Bonus:</strong> Also demonstrates setting custom data attributes and style changes</li>
</ul>
</div>
</div>
</body>
""".to_utf8_buffer()
var HTML_CONTENTva = """<head>
<title>WebSocket API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#059669">
<meta name="description" content="Demonstrating WebSocket real-time communication API">
<style>
body { bg-[#f0fdf4] p-6 }
h1 { text-[#059669] text-3xl font-bold text-center }
h2 { text-[#047857] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.ws-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#10b981] text-white hover:bg-[#059669] }
.send-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#3b82f6] text-white hover:bg-[#2563eb] }
.disconnect-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#ef4444] text-white hover:bg-[#dc2626] }
.clear-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#6b7280] text-white hover:bg-[#4b5563] }
.log-area { bg-[#f1f5f9] p-4 rounded-lg min-h-32 font-mono text-sm max-h-96 overflow-auto }
.info-box { bg-[#dbeafe] border border-[#3b82f6] p-4 rounded-lg }
.input-area { bg-[#f9fafb] p-4 rounded-lg border }
.status-connected { text-[#059669] font-bold }
.status-disconnected { text-[#ef4444] font-bold }
.status-connecting { text-[#f59e0b] font-bold }
</style>
<script>
-- Get UI elements
local logArea = gurt.select('#log-area')
local statusDisplay = gurt.select('#status-display')
local connectBtn = gurt.select('#connect-btn')
local disconnectBtn = gurt.select('#disconnect-btn')
local sendBtn = gurt.select('#send-btn')
local clearLogBtn = gurt.select('#clear-log-btn')
local urlInput = gurt.select('#url-input')
local messageInput = gurt.select('#message-input')
gurt.log('WebSocket API demo script started.')
local logMessages = {}
local socket = nil
local connected = false
-- Function to add message to log
local function addLog(message)
table.insert(logMessages, Time.format(Time.now(), '%H:%M:%S') .. ' - ' .. message)
if #logMessages > 50 then
table.remove(logMessages, 1)
end
logArea.text = table.concat(logMessages, '\\n')
end
-- Function to update status display
local function updateStatus(status, color)
statusDisplay.text = 'Status: ' .. status
statusDisplay.style = 'status-' .. color
end
-- Initialize with default values
urlInput.text = 'wss://echo.websocket.org'
messageInput.text = 'Hello from Gurted!'
-- Connect to WebSocket
connectBtn:on('click', function()
local url = urlInput.text
addLog('Attempting to connect to: ' .. url)
updateStatus('Connecting...', 'connecting')
socket = WebSocket:new(url)
socket:on('open', function()
addLog('✅ Connected to WebSocket server!')
updateStatus('Connected', 'connected')
connected = true
socket:send('Hello from the Gurted web!')
end)
socket:on('message', function(event)
addLog('📨 Received: ' .. event.data)
end)
socket:on('close', function()
addLog('❌ Connection closed')
updateStatus('Disconnected', 'disconnected')
connected = false
end)
socket:on('error', function(event)
addLog('🚨 Error: ' .. (event.message or 'Unknown error'))
updateStatus('Error', 'disconnected')
connected = false
end)
end)
-- Disconnect from WebSocket
disconnectBtn:on('click', function()
if socket and connected then
addLog('Disconnecting from WebSocket...')
socket:close()
else
addLog('No active connection to disconnect')
end
end)
-- Send message
sendBtn:on('click', function()
if socket and connected then
local message = messageInput.text
if message and message ~= '' then
socket:send(message)
addLog('📤 Sent: ' .. message)
else
addLog('❌ Cannot send empty message')
end
else
addLog('❌ Not connected to WebSocket server')
end
end)
-- Clear log button
clearLogBtn:on('click', function()
logMessages = {}
logArea.text = 'Log cleared.'
addLog('WebSocket API demo ready')
end)
-- Allow Enter key to send messages
messageInput:on('keypress', function(e)
if e.key == 'Enter' and socket and connected then
local message = messageInput.text
if message and message ~= '' then
socket:send(message)
addLog('📤 Sent: ' .. message)
messageInput.text = ''
end
end
end)
-- Initialize
updateStatus('Disconnected', 'disconnected')
addLog('WebSocket API demo ready')
addLog('Enter a WebSocket URL and click Connect to start!')
</script>
</head>
<body>
<h1>🔌 WebSocket API Demo</h1>
<div style="container mt-6">
<div style="info-box mb-6">
<h3 style="text-[#1e40af] font-semibold mb-2">WebSocket API Usage:</h3>
<p><code>local socket = WebSocket:new(url)</code></p>
<p><code>socket:on('open', function() ... end)</code></p>
<p><code>socket:on('message', function(event) print(event.data) end)</code></p>
<p><code>socket:send('Hello Server!')</code></p>
<p><code>socket:close()</code></p>
</div>
<h2>Connection</h2>
<div style="input-area mb-6">
<div style="flex flex-col gap-3">
<div>
<label style="block text-sm font-medium mb-1">WebSocket URL:</label>
<input id="url-input" type="text" style="w-full p-2 border border-gray-300 rounded-md" placeholder="ws://echo.websocket.org" />
</div>
<div id="status-display" style="status-disconnected">Status: Disconnected</div>
<div style="flex gap-2">
<button id="connect-btn" style="ws-button">🔗 Connect</button>
<button id="disconnect-btn" style="disconnect-button"> Disconnect</button>
</div>
</div>
</div>
<h2>Send Messages</h2>
<div style="input-area mb-6">
<div style="flex flex-col gap-3">
<div>
<label style="block text-sm font-medium mb-1">Message:</label>
<input id="message-input" type="text" style="w-full p-2 border border-gray-300 rounded-md" placeholder="Type your message..." />
</div>
<div style="flex gap-2">
<button id="send-btn" style="send-button">📤 Send Message</button>
<span style="text-sm text-gray-600">Or press Enter to send</span>
</div>
</div>
</div>
<h2>Event Log</h2>
<div style="button-group mb-3">
<button id="clear-log-btn" style="clear-button">🧹 Clear Log</button>
</div>
<div style="log-area mb-6">
<pre id="log-area">Initializing...</pre>
</div>
<div style="bg-[#f0f9ff] p-4 rounded-lg">
<h3 style="text-[#0369a1] font-semibold mb-2">WebSocket Events:</h3>
<ul style="text-[#075985] space-y-1 text-sm">
<li><strong>open:</strong> Fired when connection is established</li>
<li><strong>message:</strong> Fired when a message is received (event.data contains the message)</li>
<li><strong>close:</strong> Fired when connection is closed</li>
<li><strong>error:</strong> Fired when an error occurs (event.message contains error info)</li>
</ul>
<h3 style="text-[#0369a1] font-semibold mt-4 mb-2">WebSocket Methods:</h3>
<ul style="text-[#075985] space-y-1 text-sm">
<li><strong>WebSocket:new(url):</strong> Creates and connects to WebSocket server</li>
<li><strong>socket:send(message):</strong> Sends a text message to the server</li>
<li><strong>socket:close():</strong> Closes the connection</li>
<li><strong>socket:on(event, callback):</strong> Registers event handlers</li>
</ul>
</div>
</div>
</body>
""".to_utf8_buffer()
var HTML_CONTENTy = """<head>
<title>Network & JSON API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#0891b2">
<meta name="description" content="Demonstrating Network fetch() and JSON APIs">
<style>
body { bg-[#ecfdf5] p-6 }
h1 { text-[#0891b2] text-3xl font-bold text-center }
h2 { text-[#0f766e] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.fetch-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#059669] text-white hover:bg-[#047857] }
.json-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#7c3aed] text-white hover:bg-[#6d28d9] }
.clear-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#ef4444] text-white hover:bg-[#dc2626] }
.response-area { bg-[#f1f5f9] p-4 rounded-lg min-h-32 font-mono text-sm max-h-96 overflow-auto }
.info-box { bg-[#dbeafe] border border-[#3b82f6] p-4 rounded-lg }
.input-area { bg-[#f9fafb] p-4 rounded-lg border }
</style>
<script>
-- Get UI elements
local responseArea = gurt.select('#response-area')
local fetchGetBtn = gurt.select('#fetch-get-btn')
local fetchPostBtn = gurt.select('#fetch-post-btn')
local jsonEncodeBtn = gurt.select('#json-encode-btn')
local jsonDecodeBtn = gurt.select('#json-decode-btn')
local clearLogBtn = gurt.select('#clear-log-btn')
local urlInput = gurt.select('#url-input')
local jsonInput = gurt.select('#json-input')
gurt.log('Network & JSON API demo script started.')
local logMessages = {}
-- Function to add message to log
local function addLog(message)
table.insert(logMessages, Time.format(Time.now(), '%H:%M:%S') .. ' - ' .. message)
if #logMessages > 50 then
table.remove(logMessages, 1)
end
responseArea.text = table.concat(logMessages, '\\n')
end
-- Initialize with default values
urlInput.text = 'https://jsonplaceholder.typicode.com/posts/1'
jsonInput.text = JSON.stringify({
name = 'Alice Johnson',
age = 28,
hobbies = {'reading', 'coding', 'gaming'},
active = true,
score = 95.5
})
-- GET Request Test
fetchGetBtn:on('click', function()
local url = urlInput.text
addLog('Making GET request to: ' .. url)
local response = fetch(url)
addLog('Response Status: ' .. response.status .. ' ' .. response.statusText)
addLog('Response Headers: ' .. JSON.stringify(response.headers))
if response:ok() then
local responseText = response:text()
addLog('Response Body: ' .. responseText:sub(1, 200) .. (responseText:len() > 200 and '...' or ''))
-- Try to parse as JSON
local jsonData = response:json()
if jsonData then
addLog('Parsed JSON successfully')
end
else
addLog('Request failed with status: ' .. response.status)
end
end)
-- POST Request Test
fetchPostBtn:on('click', function()
local url = 'https://jsonplaceholder.typicode.com/posts'
local postData = {
title = 'Test Post from GURT',
body = 'This is a test post created using the GURT Network API',
userId = 1
}
addLog('Making POST request to: ' .. url)
addLog('POST Data: ' .. JSON.stringify(postData))
local response = fetch(url, {
method = 'POST',
headers = {
['Content-Type'] = 'application/json'
},
body = JSON.stringify(postData)
})
addLog('Response Status: ' .. response.status .. ' ' .. response.statusText)
if response:ok() then
local responseText = response:text()
addLog('Created Resource: ' .. responseText)
else
addLog('POST request failed with status: ' .. response.status)
end
end)
-- JSON Encode Test
jsonEncodeBtn:on('click', function()
local inputText = jsonInput.text
addLog('Encoding text to JSON: ' .. inputText:sub(1, 100) .. (inputText:len() > 100 and '...' or ''))
-- Try to parse the input as Lua data first
local success, data = pcall(function()
-- Simple data structure for demo
return {
message = inputText,
timestamp = Time.now(),
random = math.random(1, 100),
nested = {
array = {1, 2, 3},
bool = true
}
}
end)
if success then
local jsonString = JSON.stringify(data)
addLog('JSON Encoded: ' .. jsonString)
else
addLog('Error creating test data for encoding')
end
end)
-- JSON Decode Test
jsonDecodeBtn:on('click', function()
local jsonText = jsonInput.text
addLog('Decoding JSON: ' .. jsonText:sub(1, 100) .. (jsonText:len() > 100 and '...' or ''))
local data, error = JSON.parse(jsonText)
if data then
addLog('JSON Decoded successfully!')
addLog('Data type: ' .. type(data))
if type(data) == 'table' then
local keys = {}
for k, v in pairs(data) do
table.insert(keys, k .. ':' .. type(v))
end
addLog('Keys: ' .. table.concat(keys, ', '))
end
addLog('Stringified back: ' .. JSON.stringify(data))
else
addLog('JSON Decode Error: ' .. (error or 'Unknown error'))
end
end)
-- Clear log button
clearLogBtn:on('click', function()
logMessages = {}
responseArea.text = 'Log cleared.'
addLog('Network & JSON API demo ready')
end)
-- Initialize
addLog('Network & JSON API demo ready')
addLog('Try the buttons above to test network requests and JSON operations!')
</script>
</head>
<body>
<h1>🌐 Network & JSON API Demo</h1>
<div style="container mt-6">
<div style="info-box mb-6">
<h3 style="text-[#1e40af] font-semibold mb-2">API Examples:</h3>
<p><strong>Network:</strong> <code>fetch(url, {method: "POST", headers: {...}, body: "..."})</code></p>
<p><strong>JSON:</strong> <code>JSON.stringify(data)</code> and <code>JSON.parse(jsonString)</code></p>
</div>
<h2>Input Controls</h2>
<div style="input-area mb-6">
<div style="flex flex-col gap-3">
<div>
<label style="block text-sm font-medium mb-1">Test URL:</label>
<input id="url-input" type="text" style="w-full p-2 border border-gray-300 rounded-md" placeholder="Enter API URL..." />
</div>
<div>
<label style="block text-sm font-medium mb-1">JSON Data:</label>
<textarea id="json-input" style="w-full p-2 border border-gray-300 rounded-md" rows="3" placeholder="Enter JSON data..."></textarea>
</div>
</div>
</div>
<h2>Network Tests</h2>
<div style="button-group mb-6">
<button id="fetch-get-btn" style="fetch-button">🔍 GET Request</button>
<button id="fetch-post-btn" style="fetch-button">📤 POST Request</button>
</div>
<h2>JSON Tests</h2>
<div style="button-group mb-6">
<button id="json-encode-btn" style="json-button">📝 JSON Encode</button>
<button id="json-decode-btn" style="json-button">📖 JSON Decode</button>
</div>
<div style="button-group mb-6">
<button id="clear-log-btn" style="clear-button">🧹 Clear Log</button>
</div>
<h2>Response Log</h2>
<div style="response-area mb-6">
<pre id="response-area">Initializing...</pre>
</div>
<div style="bg-[#f0f9ff] p-4 rounded-lg">
<h3 style="text-[#0369a1] font-semibold mb-2">Network API Features:</h3>
<ul style="text-[#075985] space-y-1 text-sm">
<li><strong>fetch(url, options):</strong> Makes HTTP requests with support for all methods</li>
<li><strong>Response methods:</strong> text(), json(), ok() for processing responses</li>
<li><strong>Headers & Body:</strong> Full control over request headers and body content</li>
<li><strong>Status & StatusText:</strong> Access to HTTP response status information</li>
</ul>
<h3 style="text-[#0369a1] font-semibold mt-4 mb-2">JSON API Features:</h3>
<ul style="text-[#075985] space-y-1 text-sm">
<li><strong>JSON.stringify():</strong> Alias for encode (browser compatibility)</li>
<li><strong>JSON.parse():</strong> Alias for decode (browser compatibility)</li>
</ul>
</div>
</div>
</body>
""".to_utf8_buffer()
var HTML_CONTENT = """<head>
<title>setInterval & Network Image Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#7c3aed">
<meta name="description" content="Testing setInterval/clearInterval and network image loading with binary data">
<style>
body { bg-[#f8fafc] p-6 }
h1 { text-[#7c3aed] text-3xl font-bold text-center }
h2 { text-[#6d28d9] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.control-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#7c3aed] text-white hover:bg-[#6d28d9] }
.danger-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#ef4444] text-white hover:bg-[#dc2626] }
.success-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#059669] text-white hover:bg-[#047857] }
.log-area { bg-[#f1f5f9] p-4 rounded-lg min-h-32 font-mono text-sm max-h-96 overflow-auto }
.image-container { text-center p-4 border-2 border-dashed border-[#cbd5e1] rounded-lg }
.counter { text-[#7c3aed] text-6xl font-bold text-center p-4 }
.info-box { bg-[#ede9fe] border border-[#7c3aed] p-4 rounded-lg }
</style>
<script>
-- Get UI elements
local logArea = gurt.select('#log-area')
local counterDisplay = gurt.select('#counter')
local startIntervalBtn = gurt.select('#start-interval-btn')
local stopIntervalBtn = gurt.select('#stop-interval-btn')
local loadImageBtn = gurt.select('#load-image-btn')
local imageContainer = gurt.select('#image-container')
gurt.log('setInterval & Network Image demo script started.')
local logMessages = {}
local counter = 0
local intervalId = nil
-- Function to add message to log
local function addLog(message)
table.insert(logMessages, Time.format(Time.now(), '%H:%M:%S.%f'):sub(1, 12) .. ' - ' .. message)
if #logMessages > 30 then
table.remove(logMessages, 1)
end
logArea.text = table.concat(logMessages, '\\n')
end
-- Update counter display
local function updateCounter()
counterDisplay.text = tostring(counter)
end
-- Start interval button
startIntervalBtn:on('click', function()
if intervalId then
addLog('❌ Interval already running (ID: ' .. intervalId .. ')')
return
end
counter = 0
updateCounter()
intervalId = gurt.setInterval(function()
counter = counter + 1
updateCounter()
addLog('⏱️ Counter updated to: ' .. counter)
end, 500) -- Every 500ms
addLog('✅ Interval started (ID: ' .. intervalId .. ')')
end)
-- Stop interval button
stopIntervalBtn:on('click', function()
if not intervalId then
addLog('❌ No interval to stop')
return
end
gurt.clearInterval(intervalId)
addLog('🛑 Interval stopped (ID: ' .. intervalId .. ')')
intervalId = nil
end)
-- Network image loading
loadImageBtn:on('click', function()
addLog('🔄 Starting random image fetch...')
imageContainer.text = 'Loading image...'
-- Use a random image service that returns binary data
local randomImageUrl = 'https://picsum.photos/300/200?random=' .. math.floor(Time.now() * 1000)
addLog('📡 Fetching: ' .. randomImageUrl)
local response = fetch(randomImageUrl)
-- Handle both success and redirect cases (302 is common for image services)
if response:ok() or response.status == 302 then
addLog('✅ Image fetch response received (Status: ' .. response.status .. ')')
addLog('📊 Content-Type: ' .. (response.headers['content-type'] or 'unknown'))
addLog('📏 Content-Length: ' .. (response.headers['content-length'] or 'unknown'))
-- For image services, we can often use the original URL directly
-- since the browser/engine handles redirects automatically
local imageElement = gurt.create('img', {
src = randomImageUrl,
style = 'max-w-[300px] max-h-[200px] rounded-lg shadow-md'
})
-- Clear container and append new image
imageContainer.text = ''
imageContainer:append(imageElement)
addLog('🖼️ Image element created and appended')
addLog('💡 Note: Image service may use redirects (302), but img tag handles this')
else
addLog('❌ Image fetch failed: ' .. response.status .. ' ' .. (response.statusText or 'Unknown'))
imageContainer.text = 'Failed to load image'
end
end)
-- Initialize
updateCounter()
addLog('🚀 Demo ready!')
addLog('💡 Click "Start Interval" to begin counter')
addLog('🖼️ Click "Load Random Image" to test binary data handling')
</script>
</head>
<body>
<h1> setInterval & 🖼 Network Image Demo</h1>
<div style="container mt-6">
<div style="info-box mb-6">
<h3 style="text-[#6d28d9] font-semibold mb-2">Testing Features:</h3>
<p><strong>Intervals:</strong> <code>gurt.setInterval(callback, delay)</code> and <code>gurt.clearInterval(id)</code></p>
<p><strong>Network Images:</strong> <code>fetch()</code> with binary data and dynamic <code>&lt;img&gt;</code> creation</p>
</div>
<div style="counter mb-6" id="counter">0</div>
<h2>Interval Controls</h2>
<div style="button-group mb-6">
<button id="start-interval-btn" style="control-button"> Start Interval</button>
<button id="stop-interval-btn" style="danger-button"> Stop Interval</button>
</div>
<h2>Network Image Test</h2>
<div style="button-group mb-6">
<button id="load-image-btn" style="success-button">🖼 Load Random Image</button>
</div>
<div id="image-container" style="image-container mb-6">
<p style="text-[#64748b]">Click "Load Random Image" to test binary data fetching</p>
</div>
<h2>Activity Log</h2>
<div style="log-area mb-6">
<pre id="log-area">Initializing...</pre>
</div>
<div style="bg-[#f3f4f6] p-4 rounded-lg">
<h3 style="text-[#374151] font-semibold mb-2">Implementation Notes:</h3>
<ul style="text-[#4b5563] space-y-1 text-sm">
<li><strong>setInterval:</strong> Creates repeating timers (one_shot = false)</li>
<li><strong>clearInterval:</strong> Stops and cleans up interval timers</li>
<li><strong>Binary Data:</strong> fetch() handles binary image data seamlessly</li>
<li><strong>Dynamic DOM:</strong> Images created and appended programmatically</li>
<li><strong>Random Images:</strong> Picsum service provides different images each time</li>
</ul>
</div>
</div>
</body>
""".to_utf8_buffer()