1
0
Fork
You've already forked janus-script-dialog
0
dialogs for JanusXR
JavaScript 100%
Find a file
2026年01月07日 21:29:49 +01:00
asset added icons + docs 2025年12月31日 20:07:00 +01:00
example1.xml 🔧 master: work in progress [might break] 2026年01月07日 21:29:49 +01:00
example2.xml 🔧 master: work in progress [might break] 2026年01月07日 21:29:49 +01:00
janus-script-dialog.js 🔧 master: work in progress [might break] 2026年01月07日 21:29:49 +01:00
janus-script-dialog.webp 📃 master: update documentation 2026年01月02日 12:52:14 +01:00
LICENSE.txt added license 2026年01月01日 21:46:22 +01:00
README.md 🔧 master: work in progress [might break] 2026年01月07日 21:29:49 +01:00

Dialogs for JanusXR

DEMO

Launch the examples straight into any JML browser (like janusweb):

What is it?

  • easy reactive dialogs in JML
  • naive markdown support
  • hand-tracking support (great for AR)
  • infinite scaleable AR-menu (via URLs)
  • template variables
  • theme-able
  • dialog can intialize/watch objects and updates the dialog when keyvalues change
  • redirects window.alert(...) to immersive dialog

What is janusXR? It's an open, user-operated immersive web layer, open-sourced by the JanusVR company, that seamlessly lives within websites, even 12 years later thanks to janusweb. It provides a highly viable and easy-to-adopt ecosystem of portals, enabling immersive experiences that challenge the traditional app store paradigm. Get started with this guide.

<fireboxroom>
 <assets>
 <assetscript src="janus-script-jjq.js"/>
 <assetscript src="janus-script-dialog.js"/>
 <assetobject src="asset/button.glb" id="button"/>
 <assetsound src="asset/button.click.mp3" id="button-click"/>
 <assetsound src="asset/button.hover.mp3" id="button-hover"/>
 </assets>
 <room selfavatar="false" showavatar="false" skybox="false" walk_speed="0.8">
 <dialog content_id="menu1" pos="0 1.3 0.4" rotation="0 35 0" js_id="mydialog"/>
 <object js_id="menu1" watch="foo,bar" visible="false">
 <paragraph width="300px" height="200px" lighting="false">
 # example1.xml
 Hello **world** was clicked ${room.foo.clicks = room.foo.clicks || 0} times 
 > this is markdown btw
 </paragraph>
 <button pos="-0.33 0.98 0.21" text="hello" onclick="room.foo.clicks++"/>
 <button pos="0.33 0.98 0.21" text="alert()" onclick="alert('hello world')"/>
 <button pos="-0.33 0.69 0.21" text="example2.xml" onclick="room.openLink('example2')"/>
 <link url="example2.xml" js_id="example2" auto_load="true" scale="0 0 0"/>
 </object>
 </room>
</fireboxroom>

There's various things going on above:

  • a dialog (re)uses content defined elsewhere (menu1)
  • objects room.foo and room.bar are being watched by the dialog (watch="foo,bar")
  • calling window.alert('hello world') will trigger a dialog in front of the user

Attributes

NOTE: <paragraph> are used for panels, since JML allows inline content for these elements. Also fontscale is important to set for each button, to keep the implementation KiSS.

tag attribute info
<dialog> content_id="string" which js_id of an <object> to use as content
<dialog> pos="0 0 0" where to position your dialog
<dialog> billboard="false" always face user or not
warning: >1 transparent dialogs might tank your fps
<dialog> backportal="false" hide backportals (desirable in AR-mode).
use <button onclick=" janus.navigateBack()" text="back"/> if true
<dialog> debug="false" show theme in browserconsole
<dialog> reroute="true" reroute window.alert to <dialog>
<dialog> theme_default="light" set default theme
<object> watch="" (commaseparated) objects to watch for changes.
watch="a,b" initializes/watches objects room.a and room.b
<object> invert="true" inverts colors (useful for icon <object> inside <button> e.g.)
<button> lighting"="false"
<button> use="button" specify model to render behind text
(default expects <assetobject src="..." id="button"/>)
<button> text="my button" label of the text
<button> locked="true"
<button> scale="1 1 1"
<button> scale_back="1 1 1"
<button> fontscale="0.6"
<button> col="0 0 0"
<button> col_text="1 1 1"
<paragraph> width="300px" set the height of markdown/html panel
<paragraph> height="200px" set the width of markdown/html panel

Events:

event example
dialog_button_click room.addEventListener("dialog_button_click", (e) => console.log(e.text) )
dialog_button_hover room.addEventListener("dialog_button_hover", (e) => console.log(e.text) )
dialog_theme_init room.addEventListener("dialog_theme_init", (e) => console.log("theme init") )
dialog_theme_apply room.addEventListener("dialog_theme_init", (e) => console.log("theme apply") )
dialog_content_remove room.addEventListener("dialog_content_remove", (e) => console.log("remove") )
dialog_content_render room.addEventListener("dialog_content_render", (e) => console.log("render") )
dialog_paragraph_render room.addEventListener("dialog_paragraph_render", (e) => console.log("render") )

Examples


room.theme.current = "light" // change theme (included: "dark" and "light")

$('mydialog').render('menu2') // replaces the dialog's content with different js_id
alert("hello") // triggers popup

// bit more advanced popup
alert("OK",{timeout:1000,header:"status"})

Icons

example2.xml shows how to use icons:

 <button pos="-0.56 2.09 0.21" use="icon" onclick="janus.navigateBack()">
 <object id="icon-arrow-left" invert="true" lighting="false" col="1 1 1" pos="0.002 0 0.01" scale="1.8 1.8 1.8"/>
 </button>

This technique works for all icons:

  • add a button with custom backgroundobject (use="icon" e.g.)
  • add the asset of that backgroundobject <assetobject src="asset/button.icon.glb" id="icon"/> e.g.)

for the icon/arrow:

  • download an icon .svg from css.gg (asset/icon.arrow-left.glb e.g.)
  • blender: import .svg
  • blender: convert to Mesh (rightclick in non-edit mode)
  • blender: export as glb (asset/icon.back.glb e.g.)
  • add asset (<assetobject src="asset/icon.arrow-left.glb" id="icon-arrow-left"/> e.g.)

Themes

Basically include a script like below

NOTE: please check the light/dark theme in the sourcecode as a reference

room.addEventListener('dialog_theme_init', function(){
 room.theme.current = "mytheme" // set my current theme as default 
 room.theme.mytheme = {
 css: (opts) => `
 /* css for <paragraph> goes here */
 `,
 jml: {
 "*": { // this applies to all JML elements
 lighting: "false" 
 },
 text: { // or just <text> element e.g.
 col: "1 0 1"
 }
 },
 custom: (opts) => {
 // here you can set things in batch via jjq selectors
 $$('text', opts.db).set('col', opts.invert ? '1 0 1' : '0 1 0')
 $$('object', opts.db).set('lighting', 'false')
 $$('object', opts.db).set('transparent','false')
 }
 }
 },

Notes:

  • tested with janusweb 1.5.56

Usage

// TODO

commandline:

$ cd myroom
$ wget '...'