mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-24 11:58:37 +00:00
Merge pull request #976 from samthe13th/iframe-sandbox-v2
Refactor and redesign iframe.html
This commit is contained in:
commit
184d206ee0
326
iframe-examples.js
Normal file
326
iframe-examples.js
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
/**
|
||||||
|
* SANDBOX EXAMPLE CONFIG
|
||||||
|
*
|
||||||
|
* options: (number | boolean | string | null)[]
|
||||||
|
* - OPTIONAL if using a user input; see "input" below
|
||||||
|
* - List of values to test (passed into "result" function)
|
||||||
|
* - An option button will be generated for each value in the list
|
||||||
|
*
|
||||||
|
* input: object
|
||||||
|
* - OPTIONAL
|
||||||
|
* - User input for testing (eg a range slider).
|
||||||
|
* - Output of element onchange will be passed into RESULT function.
|
||||||
|
*
|
||||||
|
* labels: string[]
|
||||||
|
* - OPTIONAL
|
||||||
|
* - List of labels for option buttons (should be same length as options list).
|
||||||
|
* - If no labels are provided, option buttons are labeled with their value
|
||||||
|
*
|
||||||
|
* result: (value: any) => object
|
||||||
|
* - Function that returns a postMessage object
|
||||||
|
* - Based on the value produced by an option button, or a user input
|
||||||
|
*/
|
||||||
|
|
||||||
|
const IFRAME_API = {
|
||||||
|
add: {
|
||||||
|
options: [true],
|
||||||
|
labels: ["Video with styles"],
|
||||||
|
result: value => ({
|
||||||
|
"target": "*",
|
||||||
|
"add": value,
|
||||||
|
"settings": { "style": "width:640px;height:360px;float:left;border:10px solid red;display:block;"}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
automixer: {
|
||||||
|
options: [true, false],
|
||||||
|
result: value => ({ "automixer": value })
|
||||||
|
},
|
||||||
|
bitrate: {
|
||||||
|
options: [-1],
|
||||||
|
labels: ["default (-1)"],
|
||||||
|
input: {
|
||||||
|
title: "bitrate",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 6000,
|
||||||
|
value: 3000
|
||||||
|
},
|
||||||
|
result: value => ({ "bitrate": value, "target": "*" })
|
||||||
|
},
|
||||||
|
camera: {
|
||||||
|
options: [false, true, "toggle"],
|
||||||
|
result: value => ({ "camera": value })
|
||||||
|
},
|
||||||
|
changeAudioDevice: { // change text of add camera button
|
||||||
|
options: [1,2,3,4],
|
||||||
|
result: value => ({ "changeAudioDevice": value })
|
||||||
|
},
|
||||||
|
changeVideoDevice: { // change text of add camera button
|
||||||
|
options: [1,2,3,4],
|
||||||
|
result: value => ({ "changeVideoDevice": value })
|
||||||
|
},
|
||||||
|
close: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "close": value })
|
||||||
|
},
|
||||||
|
getDetailedState: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "getDetailedState": value }),
|
||||||
|
},
|
||||||
|
getDeviceList: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "getDeviceList": value }),
|
||||||
|
},
|
||||||
|
getLoudness: {
|
||||||
|
options: [false, true],
|
||||||
|
result: value => ({ "getLoudness": value }),
|
||||||
|
},
|
||||||
|
getStreamIDs: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "getStreamIDs": value }),
|
||||||
|
},
|
||||||
|
keyframe: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "keyframe": value }),
|
||||||
|
},
|
||||||
|
mute: {
|
||||||
|
options: [
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
"toggle" // open to a better suggestion here.
|
||||||
|
],
|
||||||
|
result: value => ({ "mute": value }),
|
||||||
|
},
|
||||||
|
mic: {
|
||||||
|
options: [true, false, "toggle"],
|
||||||
|
result: value => ({ "mic": value }),
|
||||||
|
},
|
||||||
|
panning: {
|
||||||
|
options: [0, 180, 90],
|
||||||
|
input: {
|
||||||
|
title: "panning",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 180,
|
||||||
|
value: 90
|
||||||
|
},
|
||||||
|
labels: ["Left (0)", "Right (180)", "Center (90)"],
|
||||||
|
result: value => ({ "panning": value }),
|
||||||
|
},
|
||||||
|
previewWebcam: {
|
||||||
|
options: ["previewWebcam"], // publishScreen
|
||||||
|
result: value => ({ "function": value }),
|
||||||
|
},
|
||||||
|
record: {
|
||||||
|
options: [true, false],
|
||||||
|
result: value => ({ "record": value }),
|
||||||
|
},
|
||||||
|
reload: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "reload": value }),
|
||||||
|
},
|
||||||
|
remove: { // target can be a stream ID or * for all.
|
||||||
|
options: [true],
|
||||||
|
labels: ["Target video"],
|
||||||
|
result: value => ({ "target": "*", "remove": value })
|
||||||
|
},
|
||||||
|
sendChat: {
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "Hello"
|
||||||
|
},
|
||||||
|
result: value => ({ "sendChat": value }),
|
||||||
|
},
|
||||||
|
sceneState: {
|
||||||
|
options: [true, false],
|
||||||
|
labels: ["ENABLE TALLY LIGHT (true)", "STOP TALLY LIGHT (false)"],
|
||||||
|
result: value => ({ "sceneState": value })
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
options: ["#main { zoom: 0.5;} video {float: left; margin: 0; padding: 0; } #info {display:none;}"],
|
||||||
|
labels: ["Insert Style Sheet"],
|
||||||
|
result: value => ({ "style": value }),
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
input: {
|
||||||
|
title: "volume",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 200,
|
||||||
|
value: 100
|
||||||
|
},
|
||||||
|
result: value => ({ "volume": value }),
|
||||||
|
},
|
||||||
|
["function: Eval"]: {
|
||||||
|
options: ["eval"], // publishScreen
|
||||||
|
result: value => ({ "function": value, "value": 'alert(\"DANGERUS\")' })
|
||||||
|
},
|
||||||
|
["function: Change html"]: {
|
||||||
|
options: ["changeHTML"], // change text of add camera button
|
||||||
|
result: value => ({ "function": value, "target": "add_camera", "value": "NEW CAMERA TEXT" })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const COMPANION_API = { // list available commands to console
|
||||||
|
bitrate: {
|
||||||
|
input: {
|
||||||
|
title: "bitrate",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 6000,
|
||||||
|
value: 3000
|
||||||
|
},
|
||||||
|
result: value => ({ target: null, action: "bitrate", value })
|
||||||
|
},
|
||||||
|
camera: {
|
||||||
|
options: [false, true, "toggle"],
|
||||||
|
result: value => ({ target: null, action: "camera", value })
|
||||||
|
},
|
||||||
|
forceKeyframe: {
|
||||||
|
options: [null],
|
||||||
|
labels: ["Rainbow puke fix"],
|
||||||
|
result: value => ({ target: null, action: "forceKeyframe", value }),
|
||||||
|
},
|
||||||
|
getDetails: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ target: null, action: "getDetails", value })
|
||||||
|
},
|
||||||
|
group: {
|
||||||
|
options: [1,2,3,4,5,6,7,8],
|
||||||
|
result: value => ({ target: null, action: "group", value })
|
||||||
|
},
|
||||||
|
hangup: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ target: null, action: "hangup", value })
|
||||||
|
},
|
||||||
|
mic: {
|
||||||
|
options: [false, true, "toggle"],
|
||||||
|
result: value => ({ target: null, action: "mic", value })
|
||||||
|
},
|
||||||
|
panning: {
|
||||||
|
options: [0, 180, 90],
|
||||||
|
input: {
|
||||||
|
title: "panning",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 180,
|
||||||
|
value: 90
|
||||||
|
},
|
||||||
|
labels: ["Left (0)", "Right (180)", "Center (90)"],
|
||||||
|
result: value => ({ target: null, action: "panning", value })
|
||||||
|
},
|
||||||
|
record: {
|
||||||
|
options: [false, true, "toggle"],
|
||||||
|
result: value => ({ target: null, action: "record", value })
|
||||||
|
},
|
||||||
|
reload: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ target: null, action: "reload", value })
|
||||||
|
},
|
||||||
|
sendChat: {
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "Hello"
|
||||||
|
},
|
||||||
|
result: value => ({ target: null, action: "sendChat", value }),
|
||||||
|
},
|
||||||
|
speaker: { // "speaker" also works in the same way
|
||||||
|
options: [false, true, "toggle"],
|
||||||
|
result: value => ({ target: null, action: "speaker", value }),
|
||||||
|
},
|
||||||
|
togglehand: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ target: null, action: "togglehand", value }),
|
||||||
|
},
|
||||||
|
togglescreenshare: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ target: null, action: "togglescreenshare", value }),
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
input: {
|
||||||
|
title: "volume",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 200,
|
||||||
|
value: 100
|
||||||
|
},
|
||||||
|
result: value => ({ target: null, "action": "volume", value }),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function guestTargetedAPI(target) {
|
||||||
|
return {
|
||||||
|
addScene: {
|
||||||
|
options: [null,1,2,3,4,5,6,7,8],
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "scene321"
|
||||||
|
},
|
||||||
|
result: value => ({ "action": "addScene", target, value })
|
||||||
|
},
|
||||||
|
display: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ "action": "display", target, value })
|
||||||
|
},
|
||||||
|
forward: {
|
||||||
|
options: [null],
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "room321"
|
||||||
|
},
|
||||||
|
result: value => ({ "action": "forward", target, value })
|
||||||
|
},
|
||||||
|
forceKeyframe: {
|
||||||
|
options: [null],
|
||||||
|
labels: ["Rainbow puke fix"],
|
||||||
|
result: value => ({ "action": "forceKeyframe", target, value })
|
||||||
|
},
|
||||||
|
hangup: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ "action": "hangup", target, value })
|
||||||
|
},
|
||||||
|
group: {
|
||||||
|
options: [0,1,2,3,4,5,6,7,8],
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "group321"
|
||||||
|
},
|
||||||
|
result: value => ({ "action": "group", target, value })
|
||||||
|
},
|
||||||
|
soloChat: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ "action": "soloChat", target, value })
|
||||||
|
},
|
||||||
|
soloVideo: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ "action": "soloVideo", target, value })
|
||||||
|
},
|
||||||
|
speaker: {
|
||||||
|
options: [null],
|
||||||
|
labels: ["Remote speaker"],
|
||||||
|
result: value =>({ "action": "speaker", target, value })
|
||||||
|
},
|
||||||
|
mic: {
|
||||||
|
options: [null],
|
||||||
|
result: value =>({ "action": "mic", target, value })
|
||||||
|
},
|
||||||
|
muteScene: {
|
||||||
|
options: [null,1,2,3,4,5,6,7,8],
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "scene321"
|
||||||
|
},
|
||||||
|
result: value => ({ "action": "muteScene", target, value })
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
input: {
|
||||||
|
title: "volume",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 200,
|
||||||
|
value: 100
|
||||||
|
},
|
||||||
|
result: value => ({ "action": "volume", target, value }),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
200
iframe.css
Normal file
200
iframe.css
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
body {
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0;
|
||||||
|
background-color: #e1e8fc;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 5px;
|
||||||
|
background: white;
|
||||||
|
border: solid;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:last-child) {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
video {
|
||||||
|
max-width: 300px;
|
||||||
|
max-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#viewlink {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
display: flex;
|
||||||
|
padding: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-section {
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom: solid 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-section > h4:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-section-header {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom: solid 1px;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-sizing: border-box;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-post {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-post > * {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-post > button {
|
||||||
|
border-radius: 0;
|
||||||
|
border: 0;
|
||||||
|
padding: 0 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-post-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border: solid 5px #4d66a8;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
overflow: auto;
|
||||||
|
background: white;
|
||||||
|
width: 350px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-body {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 700px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-header {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
background: #4d66a8;
|
||||||
|
color: white;
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-header > button {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iframe-example {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border: solid #4d66a8 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-log {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 200px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: auto;
|
||||||
|
background: #0b0e15;
|
||||||
|
color: white;
|
||||||
|
border-top: solid 1px #6e6e6e;
|
||||||
|
font-family: monospace;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.output-container {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-log {
|
||||||
|
background: #273047;
|
||||||
|
padding: 4px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sensors-log {
|
||||||
|
padding: 10px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-data-logs {
|
||||||
|
height: 100%;
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.target-guest {
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom: solid 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.target-guest-inputs {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
857
iframe.html
857
iframe.html
@ -3,313 +3,58 @@
|
|||||||
<title>IFRAME Example</title>
|
<title>IFRAME Example</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
|
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
|
||||||
<style>
|
<link rel="stylesheet" href="./iframe.css" />
|
||||||
body{
|
<script src="iframe-examples.js"></script>
|
||||||
padding:0;
|
|
||||||
margin:0;
|
|
||||||
background-color: rgb(222,242,253);
|
|
||||||
}
|
|
||||||
iframe {
|
|
||||||
border:0;
|
|
||||||
margin:0;
|
|
||||||
padding:0;
|
|
||||||
display:block;
|
|
||||||
margin:10px;
|
|
||||||
width:100%;
|
|
||||||
height:520px;
|
|
||||||
}
|
|
||||||
#viewlink {
|
|
||||||
width:400px;
|
|
||||||
}
|
|
||||||
#container {
|
|
||||||
display:block;
|
|
||||||
padding:0px;
|
|
||||||
}
|
|
||||||
input{
|
|
||||||
padding:5px;
|
|
||||||
margin:5px;
|
|
||||||
}
|
|
||||||
button{
|
|
||||||
padding:5px;
|
|
||||||
margin:5px;
|
|
||||||
}
|
|
||||||
video{
|
|
||||||
max-width:300px;
|
|
||||||
max-height:100px;
|
|
||||||
}
|
|
||||||
.container{
|
|
||||||
max-height: 900px;
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
<script>
|
||||||
|
const ExpandableCards = {};
|
||||||
|
|
||||||
function loadIframe(){ // this is pretty important if you want to avoid camera permission popup problems. You can also call it automatically via: <body onload=>loadIframe();"> , but don't call it before the page loads.
|
function loadIframe(){ // this is pretty important if you want to avoid camera permission popup problems. You can also call it automatically via: <body onload=>loadIframe();"> , but don't call it before the page loads.
|
||||||
|
var exampleId = generateId();
|
||||||
|
|
||||||
|
// Keep track of which API cards are opened vs closed
|
||||||
|
ExpandableCards[exampleId] = {
|
||||||
|
iframe: false,
|
||||||
|
companion: false,
|
||||||
|
}
|
||||||
|
|
||||||
var iframe = document.createElement("iframe");
|
|
||||||
var iframeContainer = document.createElement("div");
|
|
||||||
iframeContainer.classList.add("container");
|
|
||||||
var iframesrc = document.getElementById("viewlink").value;
|
var iframesrc = document.getElementById("viewlink").value;
|
||||||
iframe.allow = "document-domain;encrypted-media;sync-xhr;usb;web-share;cross-origin-isolated;accelerometer;midi;geolocation;autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
|
var container = document.getElementById("container");
|
||||||
|
var iframe = newElement("iframe", {
|
||||||
if (iframesrc==""){
|
allow: "document-domain;encrypted-media;sync-xhr;usb;web-share;cross-origin-isolated;accelerometer;midi;geolocation;autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;",
|
||||||
iframesrc="./";
|
src: addUrlParams(iframesrc, ["cleanoutput", "transparent", "hidemenu"])
|
||||||
}
|
});
|
||||||
|
var iframeExample = newElement("div", { id: exampleId, classList: "iframe-example" });
|
||||||
if (document.getElementById("clean").checked){
|
var exampleHeader = newElement("div", { classList: "example-header", innerHTML: iframesrc });
|
||||||
if (iframesrc.includes("?")){
|
var exampleBody = newElement("div", { classList: "example-body" });
|
||||||
iframesrc+='&';
|
var outputContainer = newElement("div", { classList: "output-container" });
|
||||||
} else {
|
var customPostContainer = newElement("div", { classList: "custom-post" });
|
||||||
iframesrc+='?';
|
var customPostInput = newElement("input", {
|
||||||
|
classList: "custom-post-input", type: "text", placeholder: "Post Message (format as a JSON object}"
|
||||||
|
});
|
||||||
|
var mainLog = newElement("div", { id: exampleId + "-logs", classList: "main-log" });
|
||||||
|
var streamDataLogs = newElement("div", { classList: "stream-data-logs" } );
|
||||||
|
var controlsContainer = getExampleControls();
|
||||||
|
var targetGuest = getGuestAPIGenerator();
|
||||||
|
var customPostSend = newElement("button", {
|
||||||
|
innerText: "POST",
|
||||||
|
onclick: function() {
|
||||||
|
try {
|
||||||
|
const message = JSON.parse(customPostInput.value);
|
||||||
|
postMessage(message, '*');
|
||||||
|
} catch (error) {
|
||||||
|
alert(error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
iframesrc+="cleanoutput";
|
});
|
||||||
}
|
|
||||||
if (document.getElementById("transparent").checked){
|
|
||||||
if (iframesrc.includes("?")){
|
|
||||||
iframesrc+='&';
|
|
||||||
} else {
|
|
||||||
iframesrc+='?';
|
|
||||||
}
|
|
||||||
iframesrc+="transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.getElementById("hidemenu").checked){
|
customPostContainer.append(customPostInput, customPostSend);
|
||||||
if (iframesrc.includes("?")){
|
controlsContainer.appendChild(targetGuest);
|
||||||
iframesrc+='&';
|
outputContainer.append(iframe, mainLog, customPostContainer);
|
||||||
} else {
|
exampleBody.append(controlsContainer, outputContainer, streamDataLogs);
|
||||||
iframesrc+='?';
|
iframeExample.append(exampleHeader, exampleBody);
|
||||||
}
|
container.prepend(iframeExample);
|
||||||
iframesrc+="hidemenu";
|
|
||||||
}
|
|
||||||
|
|
||||||
iframe.src = iframesrc;
|
|
||||||
|
|
||||||
iframeContainer.appendChild(iframe);
|
|
||||||
|
|
||||||
document.getElementById("container").appendChild(iframeContainer);
|
|
||||||
|
|
||||||
|
|
||||||
var h3 = document.createElement("h3");
|
|
||||||
h3.innerText = "The following commands are exclusive to the IFRAME API.";
|
|
||||||
iframeContainer.appendChild(h3);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Mute Speaker";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');}; // "speaker" also works in the same way.
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Un-Mute Speaker";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Toggle Speaker";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');}; // open to a better suggestion here.
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Mute Mic";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Un-Mute Mic";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Toggle Mic";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Mute Camera";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"camera":false}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Unmute Camera";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"camera":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Toggle Camera";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"camera":"toggle"}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Disconnect";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "0 Bitrate";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":0, "target": "*"}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Low Bitrate";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30, "target": "*"}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "High Bitrate";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000, "target": "*"}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Default Bitrate";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1, "target": "*"}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Reload";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "50% Volume";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "100% Volume";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Pan Left";
|
|
||||||
button.title = "Requires &panning to be added to the view link";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"panning":0}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Pan right";
|
|
||||||
button.title = "Requires &panning to be added to the view link";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"panning":180}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Pan Center";
|
|
||||||
button.title = "Requires &panning to be added to the view link";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"panning":90}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Request Loudness Levels";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Stop Sending Loudness Levels";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Get detailed state (if Director)";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"getDetailedState":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Start Recording";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"record":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Stop Recording";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"record":false}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Say Hello";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Send Keyframe";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"keyframe":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Insert Style Sheet";
|
|
||||||
var stylesheet = "#main { zoom: 0.5;} video {float: left; margin: 0; padding: 0; } #info {display:none;}";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"style":stylesheet}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "get StreamIDs and labels";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"getStreamIDs":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "get media device list";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"getDeviceList":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Start AutoMixer";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"automixer":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Stop AutoMixer";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"automixer":false}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "ENABLE TALLY LIGHT";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"sceneState":true}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "STOP TALLY LIGHT";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"sceneState":false}, '*');};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Add Target Video";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"target":"*", "add":true, "settings": {"style": "width:640px;height:360px;float:left;border:10px solid red;display:block;"}}, '*');}; // target can be a stream ID or * for all.
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Remove Target Video";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"target":"*", "remove": true}, '*');}; // target can be a stream ID or * for all.
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "previewWebcam()";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; // publishScreen
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Change to Camera #2";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"changeVideoDevice":2}, '*');}; // change text of add camera button
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Change to Microphone #4";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"changeAudioDevice":4}, '*');}; // change text of add camera button
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "eval('alert(\"DANGERUS\")'";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"function":"eval", "value":'alert(\"DANGERUS\")'}, '*');}; // publishScreen
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "Change Add Camera text";
|
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"function":"changeHTML", "target":"add_camera", "value":"NEW CAMERA TEXT"}, '*');}; // change text of add camera button
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "CLOSE IFRAME";
|
|
||||||
button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);};
|
|
||||||
iframeContainer.appendChild(button);
|
|
||||||
|
|
||||||
//////////// LISTEN FOR EVENTS
|
//////////// LISTEN FOR EVENTS
|
||||||
|
|
||||||
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
|
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
|
||||||
var eventer = window[eventMethod];
|
var eventer = window[eventMethod];
|
||||||
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
|
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
|
||||||
@ -340,7 +85,7 @@
|
|||||||
media.streams[e.data.streamID].autoplay = true;
|
media.streams[e.data.streamID].autoplay = true;
|
||||||
// media.streams[e.data.streamID].controls = true;
|
// media.streams[e.data.streamID].controls = true;
|
||||||
media.streams[e.data.streamID].srcObject = media.tracks[e.data.trackID].stream;
|
media.streams[e.data.streamID].srcObject = media.tracks[e.data.trackID].stream;
|
||||||
iframeContainer.appendChild(media.streams[e.data.streamID]);
|
Container.appendChild(media.streams[e.data.streamID]);
|
||||||
} else {
|
} else {
|
||||||
if (e.data.kind=="video"){
|
if (e.data.kind=="video"){
|
||||||
media.streams[e.data.streamID].srcObject.getVideoTracks().forEach(trk=>{
|
media.streams[e.data.streamID].srcObject.getVideoTracks().forEach(trk=>{
|
||||||
@ -361,11 +106,9 @@
|
|||||||
return;
|
return;
|
||||||
} // end of video/audio capture
|
} // end of video/audio capture
|
||||||
|
|
||||||
if ("stats" in e.data){
|
if ("stats" in e.data) {
|
||||||
var outputWindow = document.createElement("div");
|
|
||||||
console.log(e.data.stats);
|
console.log(e.data.stats);
|
||||||
|
|
||||||
|
|
||||||
var out = "<br />total_inbound_connections:"+e.data.stats.total_inbound_connections;
|
var out = "<br />total_inbound_connections:"+e.data.stats.total_inbound_connections;
|
||||||
out += "<br />total_outbound_connections:"+e.data.stats.total_outbound_connections;
|
out += "<br />total_outbound_connections:"+e.data.stats.total_outbound_connections;
|
||||||
|
|
||||||
@ -373,325 +116,305 @@
|
|||||||
out += "<br /><br /><b>streamID:</b> "+streamID+"<br />";
|
out += "<br /><br /><b>streamID:</b> "+streamID+"<br />";
|
||||||
out += printValues(e.data.stats.inbound_stats[streamID]);
|
out += printValues(e.data.stats.inbound_stats[streamID]);
|
||||||
}
|
}
|
||||||
|
logOutput(out)
|
||||||
outputWindow.innerHTML = out;
|
|
||||||
iframeContainer.appendChild(outputWindow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("gotChat" in e.data){
|
if ("gotChat" in e.data){
|
||||||
var outputWindow = document.createElement("div");
|
logOutput(e.data.gotChat.msg)
|
||||||
outputWindow.innerHTML = e.data.gotChat.msg;
|
|
||||||
outputWindow.style.border="1px dotted black";
|
|
||||||
iframeContainer.appendChild(outputWindow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("action" in e.data){
|
if ("action" in e.data && e.data.action !== "loudness") {
|
||||||
var outputWindow = document.createElement("div");
|
logOutput("child-page-action: "+e.data.action+"<br />")
|
||||||
outputWindow.innerHTML = "child-page-action: "+e.data.action+"<br />";
|
|
||||||
outputWindow.style.border="1px dotted black";
|
|
||||||
iframeContainer.appendChild(outputWindow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ("streamIDs" in e.data){
|
if ("streamIDs" in e.data){
|
||||||
var outputWindow = document.createElement("div");
|
var out = "child-page-action: streamIDs<br />"
|
||||||
outputWindow.innerHTML = "child-page-action: streamIDs<br />";
|
|
||||||
for (var key in e.data.streamIDs) {
|
for (var key in e.data.streamIDs) {
|
||||||
outputWindow.innerHTML += "streamID: " + key + ", label:"+e.data.streamIDs[key] + "\n";
|
out += "streamID: " + key + ", label:"+e.data.streamIDs[key] + "\n";
|
||||||
}
|
}
|
||||||
outputWindow.style.border="1px dotted black";
|
logOutput(out)
|
||||||
iframeContainer.appendChild(outputWindow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("deviceList" in e.data){
|
if ("deviceList" in e.data){
|
||||||
var outputWindow = document.createElement("div");
|
var out = "child-page-action: deviceList<br />";
|
||||||
outputWindow.innerHTML = "child-page-action: deviceList<br />";
|
|
||||||
for (var i = 0;i<e.data.deviceList.length;i++){
|
for (var i = 0;i<e.data.deviceList.length;i++){
|
||||||
outputWindow.innerHTML += e.data.deviceList[i].label + "<br />";
|
out += e.data.deviceList[i].label + "<br />";
|
||||||
}
|
}
|
||||||
outputWindow.style.border="1px dotted black";
|
logOutput(out);
|
||||||
iframeContainer.appendChild(outputWindow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("loudness" in e.data) {
|
||||||
|
var loudnessOutput;
|
||||||
|
var id = exampleId + "-loudness";
|
||||||
|
var out = "child-page-action: loudness<br />";
|
||||||
|
|
||||||
if ("loudness" in e.data){
|
if (document.getElementById(id)){
|
||||||
//console.log(e.data);
|
loudnessOutput = document.getElementById(id);
|
||||||
if (document.getElementById("loudness")){
|
|
||||||
outputWindow = document.getElementById("loudness");
|
|
||||||
} else {
|
} else {
|
||||||
var outputWindow = document.createElement("div");
|
loudnessOutput = newElement("div", { id, classList: "sensors-log" });
|
||||||
outputWindow.style.border="1px dotted black";
|
streamDataLogs.prepend(loudnessOutput);
|
||||||
iframeContainer.appendChild(outputWindow);
|
|
||||||
outputWindow.id = "loudness";
|
|
||||||
}
|
}
|
||||||
outputWindow.innerHTML = "child-page-action: loudness<br />";
|
|
||||||
for (var key in e.data.loudness) {
|
for (var key in e.data.loudness) {
|
||||||
outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n";
|
out += key + " Loudness: " + e.data.loudness[key] + "\n";
|
||||||
}
|
}
|
||||||
outputWindow.style.border="1px black";
|
logOutput(out, { window: loudnessOutput, replace: true, style: { paddingBottom: '20px', borderBottom: 'dotted 1px #4d66a8' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("detailedState" in e.data){
|
if ("detailedState" in e.data){
|
||||||
var outputWindow = document.createElement("div");
|
logOutput("child-page-action: detailedState<br />"+JSON.stringify(e.data.detailedState)+"<br />")
|
||||||
outputWindow.innerHTML = "child-page-action: detailedState<br />"+JSON.stringify(e.data.detailedState)+"<br />";
|
}
|
||||||
outputWindow.style.border="1px dotted black";
|
|
||||||
iframeContainer.appendChild(outputWindow);
|
if ("callback" in e.data) {
|
||||||
|
if (e.data.callback.action === 'getDetails') {
|
||||||
|
logOutput("child-page-action: getDetails<br />"+JSON.stringify(e.data.callback.result, null, 2))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("sensors" in e.data){
|
if ("sensors" in e.data){
|
||||||
console.log(e.data);
|
var sensorsOutput;
|
||||||
if (document.getElementById("sensors")){
|
var id = exampleId + "-sensors";
|
||||||
outputWindow = document.getElementById("sensors");
|
var out = "child-page-action: sensors<br /><br />";
|
||||||
} else {
|
|
||||||
var outputWindow = document.createElement("div");
|
|
||||||
outputWindow.style.border="1px dotted black";
|
|
||||||
iframeContainer.appendChild(outputWindow);
|
|
||||||
outputWindow.id = "sensors";
|
|
||||||
}
|
|
||||||
outputWindow.innerHTML = "child-page-action: sensors<br /><br />";
|
|
||||||
|
|
||||||
|
if (document.getElementById(id)){
|
||||||
|
sensorsOutput = document.getElementById(id);
|
||||||
|
} else {
|
||||||
|
sensorsOutput = newElement("div", { id, classList: "sensors-log" });
|
||||||
|
streamDataLogs.appendChild(sensorsOutput);
|
||||||
|
}
|
||||||
for (var key in e.data.sensors.lin) {
|
for (var key in e.data.sensors.lin) {
|
||||||
outputWindow.innerHTML += key + " linear: " + e.data.sensors.lin[key] + "<br />";
|
out += key + " linear: " + roundSensorData(e.data.sensors.lin[key]) + "<br />";
|
||||||
}
|
}
|
||||||
for (var key in e.data.sensors.acc) {
|
for (var key in e.data.sensors.acc) {
|
||||||
outputWindow.innerHTML += key + " acceleration: " + e.data.sensors.acc[key] + "<br />";
|
out += key + " acceleration: " + roundSensorData(e.data.sensors.acc[key]) + "<br />";
|
||||||
}
|
}
|
||||||
for (var key in e.data.sensors.gyro) {
|
for (var key in e.data.sensors.gyro) {
|
||||||
outputWindow.innerHTML += key + " gyro: " + e.data.sensors.gyro[key] + "<br />";
|
out += key + " gyro: " + roundSensorData(e.data.sensors.gyro[key]) + "<br />";
|
||||||
}
|
}
|
||||||
for (var key in e.data.sensors.mag) {
|
for (var key in e.data.sensors.mag) {
|
||||||
outputWindow.innerHTML += key + " magnet: " + e.data.sensors.mag[key] + "<br />";
|
out += key + " magnet: " + roundSensorData(e.data.sensors.mag[key]) + "<br />";
|
||||||
}
|
}
|
||||||
outputWindow.style.border="1px black";
|
logOutput(out, { window: sensorsOutput, replace: true })
|
||||||
|
|
||||||
|
function roundSensorData(data) {
|
||||||
|
return Math.round(data * 100000) / 100000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function loadSelfCommands(){
|
function getExampleControls() {
|
||||||
var commands = {}
|
var controlsContainer = newElement("div", { classList: "controls" });
|
||||||
commands.speaker = function(value){sendSelfCommand("speaker",value)}; // "speaker" also works in the same way
|
|
||||||
|
|
||||||
commands.mic = function(value){sendSelfCommand("mic",value)};
|
var iframeExamples = getExamplesSection(
|
||||||
|
IFRAME_API,
|
||||||
|
{
|
||||||
|
guestId: 'iframe',
|
||||||
|
headers: '<h3>IFRAME</h3><p><em>These commands are exclusive to the IFRAME API.</em></p>',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
var companionExamples = getExamplesSection(
|
||||||
|
COMPANION_API,
|
||||||
|
{
|
||||||
|
guestId: 'companion',
|
||||||
|
headers: '<h3>HTTP/WSS</h3><p><em>These commands re-use the Companion.Ninja HTTP/WSS API, except you can send them via this Iframe interface.</em></p>',
|
||||||
|
info: `
|
||||||
|
<p><a target="_blank" style="word-break: break-word" href="https://github.com/steveseguin/Companion-Ninja#api-commands">
|
||||||
|
More details of the below IFRAME API details are here: https://github.com/steveseguin/Companion-Ninja#api-commands
|
||||||
|
</a></p>`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
commands.camera = function(value){sendSelfCommand("camera",value)};
|
var removeIframeButton = document.createElement("button");
|
||||||
|
removeIframeButton.innerHTML = "REMOVE IFRAME";
|
||||||
|
removeIframeButton.onclick = function(){iframeExample.parentNode.removeChild(iframeExample);};
|
||||||
|
exampleHeader.appendChild(removeIframeButton);
|
||||||
|
|
||||||
commands.bitrate = function(value){sendSelfCommand("bitrate",value)};
|
controlsContainer.append(
|
||||||
|
iframeExamples.header,
|
||||||
|
iframeExamples.examples,
|
||||||
|
companionExamples.header,
|
||||||
|
companionExamples.examples
|
||||||
|
);
|
||||||
|
|
||||||
commands.volume = function(value){sendSelfCommand("volume",value)};
|
return controlsContainer
|
||||||
|
}
|
||||||
|
|
||||||
commands.record = function(value){sendSelfCommand("record",value)};
|
function getGuestAPIGenerator() {
|
||||||
|
var targetGuest = newElement('div', {
|
||||||
|
classList: 'target-guest',
|
||||||
|
innerHTML: `<h3>HTTP/WSS Director</h3><p><em>Directors can target commands to individual guests</em></p><h4>Target guest by: </h4>`
|
||||||
|
});
|
||||||
|
var targetGuestBySlot = newElement("input", {
|
||||||
|
type: "radio",
|
||||||
|
checked: true,
|
||||||
|
id: exampleId+"-guest-slot-radio",
|
||||||
|
value: "slot",
|
||||||
|
name: exampleId+"-guest-target",
|
||||||
|
onclick: function() {
|
||||||
|
document.getElementById(exampleId+"-guest-slot").classList.remove("hidden");
|
||||||
|
document.getElementById(exampleId+"-guest-id").classList="hidden";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var targetGuestBySlotLabel = newElement("label", { for: exampleId+"-guest-slot-radio", innerText: "Slot (number)" })
|
||||||
|
var targetGuestById = newElement("input", {
|
||||||
|
type: "radio",
|
||||||
|
id: exampleId+"-guest-id-radio",
|
||||||
|
value: "id",
|
||||||
|
min: 0,
|
||||||
|
name: exampleId+"-guest-target",
|
||||||
|
onclick: function() {
|
||||||
|
document.getElementById(exampleId+"-guest-slot").classList="hidden";
|
||||||
|
document.getElementById(exampleId+"-guest-id").classList.remove("hidden")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var targetGuestByIdLabel = newElement("label", { for: exampleId+"-guest-id-radio", innerText: "streamID (string)" })
|
||||||
|
var targetGuestInputs = newElement("div", { classList: "target-guest-inputs"});
|
||||||
|
var guestIdInput = newElement("input", { id: exampleId+"-guest-id", type: "text", placeholder: "Guest ID", value: "abc123", classList: "hidden" });
|
||||||
|
var guestSlotInput = newElement("input", { value: 1, id: exampleId+"-guest-slot", type: "number", placeholder: "Guest Slot" });
|
||||||
|
var generateGuestAPI = newElement("button", {
|
||||||
|
innerText: "Generate commands",
|
||||||
|
onclick: function() {
|
||||||
|
var targetType = (guestSlotInput.classList.value === "hidden") ? 'id' : 'slot';
|
||||||
|
var value = (targetType === 'id') ? guestIdInput.value : guestSlotInput.value;
|
||||||
|
var guestId = 'guest' + value;
|
||||||
|
var headers = '<h4>Target GUEST ' + value + '</h4><p><em>These commands target a guest';
|
||||||
|
headers += (targetType === 'id') ? ' with id ' : ' in slot ';
|
||||||
|
headers += value + '</em></p>'
|
||||||
|
|
||||||
commands.sayHello = function(value){sendSelfCommand("sendChat","Hello")};
|
if (!document.getElementById(exampleId + '-' + guestId)) {
|
||||||
|
var guestTargetedExamples = getExamplesSection(
|
||||||
|
guestTargetedAPI(value),
|
||||||
|
{ guestId: 'guest' + value, headers },
|
||||||
|
)
|
||||||
|
controlsContainer.appendChild(guestTargetedExamples.header);
|
||||||
|
controlsContainer.appendChild(guestTargetedExamples.examples);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
var target_self = document.body;
|
targetGuestInputs.append(guestIdInput, guestSlotInput, generateGuestAPI);
|
||||||
|
targetGuest.append(targetGuestBySlot, targetGuestBySlotLabel, targetGuestById, targetGuestByIdLabel, targetGuestInputs);
|
||||||
|
|
||||||
var hr = document.createElement("hr");
|
return targetGuest;
|
||||||
target_self.appendChild(hr);
|
}
|
||||||
|
|
||||||
var h3 = document.createElement("h3");
|
function getExamplesSection(api, section) {
|
||||||
h3.innerText = "The following commands re-use the Companion.Ninja HTTP/WSS API, except you can send them via this Iframe interface.";
|
var sectionId = exampleId + "-" + section.guestId;
|
||||||
target_self.appendChild(h3);
|
var header = document.createElement('div');
|
||||||
|
header.classList = "api-section-header";
|
||||||
|
|
||||||
var a = document.createElement("a");
|
var toggleBtn = document.createElement('button');
|
||||||
a.innerText = "More details of the below IFRAME API details are here: https://github.com/steveseguin/Companion-Ninja#api-commands";
|
toggleBtn.innerText = "Show";
|
||||||
a.href = "https://github.com/steveseguin/Companion-Ninja#api-commands";
|
toggleBtn.onclick = function() {
|
||||||
a.target = "_blank";
|
ExpandableCards[exampleId][section.guestId] = !ExpandableCards[exampleId][section.guestId];
|
||||||
target_self.appendChild(a);
|
if (ExpandableCards[exampleId][section.guestId] === true) {
|
||||||
|
document.getElementById(sectionId).classList = "api-section";
|
||||||
|
toggleBtn.innerText = "Hide"
|
||||||
|
} else {
|
||||||
|
document.getElementById(sectionId).classList = "hidden";
|
||||||
|
toggleBtn.innerText = "Show"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var hr = document.createElement("hr");
|
var headerText = document.createElement('div');
|
||||||
target_self.appendChild(hr);
|
headerText.innerHTML = section.headers;
|
||||||
|
|
||||||
|
header.append(headerText, toggleBtn);
|
||||||
|
|
||||||
for (var k in commands) {
|
var examples = document.createElement('div');
|
||||||
|
examples.classList = "hidden";
|
||||||
|
examples.id = sectionId;
|
||||||
|
|
||||||
var button = document.createElement("button");
|
if (section.info) {
|
||||||
button.innerHTML = k + ":<br />TRUE";
|
var info = document.createElement("div");
|
||||||
button.dataset.command = k;
|
info.innerHTML = section?.info;
|
||||||
button.onclick = function(){commands[this.dataset.command](true);}
|
examples.appendChild(info);
|
||||||
target_self.appendChild(button);
|
}
|
||||||
|
|
||||||
var button = document.createElement("button");
|
Object.keys(api).sort().forEach((param) => {
|
||||||
button.innerHTML = k + ":<br />FALSE";
|
var header = document.createElement('h4');
|
||||||
button.dataset.command = k;
|
header.innerHTML = param;
|
||||||
button.onclick = function(){commands[this.dataset.command](false);}
|
examples.appendChild(header);
|
||||||
target_self.appendChild(button);
|
addExamples(examples, param, api[param]);
|
||||||
|
})
|
||||||
|
|
||||||
if (k=="mic" || k=="camera" || k=="record" || k=="speaker"){
|
return { header, examples }
|
||||||
|
}
|
||||||
|
|
||||||
|
function newElement(type, attributes) {
|
||||||
|
var el = document.createElement(type);
|
||||||
|
for (var attr in attributes) {
|
||||||
|
el[attr] = attributes[attr]
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addExamples(parentContainer, name, data) {
|
||||||
|
if (data.options) {
|
||||||
|
for (var i = 0; i < data.options.length; i++) {
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = k + ":<br />TOGGLE";
|
|
||||||
button.dataset.command = k;
|
button.innerHTML = (data.labels !== undefined)
|
||||||
button.onclick = function(){commands[this.dataset.command]("toggle");}
|
? data.labels[i]
|
||||||
target_self.appendChild(button);
|
: JSON.stringify(data.options[i]);
|
||||||
|
|
||||||
|
const result = data.result(data.options[i]); // result needs to be a const, not a var
|
||||||
|
button.onclick = function() { postMessage(result)};
|
||||||
|
parentContainer.appendChild(button)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.input) {
|
||||||
|
var inputWrapper = document.createElement("div");
|
||||||
|
var input = document.createElement("input");
|
||||||
|
|
||||||
|
for (var attr in data.input) {
|
||||||
|
input[attr] = data.input[attr];
|
||||||
|
}
|
||||||
|
if (input.type === 'range') {
|
||||||
|
input.onchange = function() { postMessage(data.result(this.value)) };
|
||||||
|
} else {
|
||||||
|
var button = newElement("button", { innerText: "Send" });
|
||||||
|
button.onclick = function() { postMessage(data.result(input.value)) };
|
||||||
|
inputWrapper.appendChild(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // list available commands to console
|
inputWrapper.prepend(input);
|
||||||
|
parentContainer.appendChild(inputWrapper);
|
||||||
commands.reload = function(){sendSelfCommand("reload",true);};
|
|
||||||
|
|
||||||
commands.hangup = function(){sendSelfCommand("hangup",true);};
|
|
||||||
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = k + ":<br />TRUE";
|
|
||||||
button.onclick = function(){commands["reload"](true);}
|
|
||||||
target_self.appendChild(button);
|
|
||||||
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = k + ":<br />TRUE";
|
|
||||||
button.onclick = function(){commands["hangup"](true);}
|
|
||||||
target_self.appendChild(button);
|
|
||||||
|
|
||||||
return commands;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadGuestCommands(guestid, streamID=false){ // this is the same as the Companion API, but can be issued to the IFRAME API
|
|
||||||
|
|
||||||
var container = document.createElement("div");
|
|
||||||
container.id = "guest_"+guestid+"_container";
|
|
||||||
document.body.appendChild(container);
|
|
||||||
|
|
||||||
var hr = document.createElement("hr");
|
|
||||||
container.appendChild(hr);
|
|
||||||
var h3 = document.createElement("h3");
|
|
||||||
if (streamID){
|
|
||||||
h3.innerHTML = "These target guest with the streamID: <i>"+guestid+ "</i> (if a director)";
|
|
||||||
} else {
|
|
||||||
h3.innerText = "These target the guest in slot "+guestid+ " (if you are director)";
|
|
||||||
}
|
}
|
||||||
container.appendChild(h3);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "transfer popup";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "forward");};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "transfer to 'room321'";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "forward", 'room321');};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "scene 1";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "addScene");}; /// SCENE 1 or specify a custom scene name as a value
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "mute in scene";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "muteScene");};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "mute everywhere";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "mic");};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "hang up";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "hangup");};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "solo chat";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "soloChat");};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "remote speaker";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "speaker");};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "remote display";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "display");};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "rainbow puke fix";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "forceKeyframe");};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "highlight";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "soloVideo");};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "scene 2";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 2);};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "scene 3";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 3);};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "scene 4";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 4);};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "scene 5";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 5);};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "scene 6";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 6);};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = " scene 7";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 7);};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "scene 8";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 8);};
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
var button = document.createElement("button");
|
|
||||||
button.innerHTML = "scene 'test'";
|
|
||||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 'test');}; // specifying a custom scene; it needs to be active for this to work..
|
|
||||||
container.appendChild(button);
|
|
||||||
|
|
||||||
|
|
||||||
var input = document.createElement("label");
|
|
||||||
input.innerHTML = "mic volume:";
|
|
||||||
container.appendChild(input);
|
|
||||||
var input = document.createElement("input");
|
|
||||||
input.type = "range";
|
|
||||||
input.title = "volume";
|
|
||||||
input.min = 0;
|
|
||||||
input.max = 200;
|
|
||||||
input.value = 100;
|
|
||||||
input.onchange = function(){sendGuestCommand(guestid, "volume", this.value);};
|
|
||||||
container.appendChild(input);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendGuestCommand(target, action, value=null){ //
|
function logOutput(output, config) {
|
||||||
iframe.contentWindow.postMessage({"target":target, "action":action, "value":value}, '*'); //
|
var log = document.createElement("div");
|
||||||
//sendMessage(JSON.stringify({"target":target, "action":action, "value":value})); // if using the Companion API..
|
var outputWindow = config?.window ?? mainLog;
|
||||||
|
|
||||||
|
log.innerHTML = output;
|
||||||
|
if (config?.classList) {
|
||||||
|
log.classList = config?.classList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clears the log when a new entry comes in
|
||||||
|
if (config?.replace === true) {
|
||||||
|
outputWindow.innerHTML = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
outputWindow.appendChild(log);
|
||||||
|
outputWindow.scrollTo(0, outputWindow.scrollHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendSelfCommand(action, value=null){
|
function postMessage(message) {
|
||||||
iframe.contentWindow.postMessage({"target":null, "action":action, "value":value}, '*');
|
iframe.contentWindow.postMessage(message, '*');
|
||||||
//sendMessage(JSON.stringify({"target":target, "action":action, "value":value})); // if using the Companion API..
|
var out = "Post: " + JSON.stringify(message);
|
||||||
|
logOutput(out, { classList: "post-log" });
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSelfCommands();
|
|
||||||
loadGuestCommands(1);
|
|
||||||
loadGuestCommands(2);
|
|
||||||
loadGuestCommands(3);
|
|
||||||
var randomGuest = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10);
|
|
||||||
loadGuestCommands(randomGuest, true);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateId() {
|
||||||
|
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
function printValues( obj) {
|
function printValues( obj) {
|
||||||
var out = "";
|
var out = "";
|
||||||
|
|
||||||
for (var key in obj) {
|
for (var key in obj) {
|
||||||
if (typeof obj[key] === "object") {
|
if (typeof obj[key] === "object") {
|
||||||
out +="<br />";
|
out +="<br />";
|
||||||
@ -700,19 +423,31 @@
|
|||||||
out +="<b>"+key+"</b>: "+obj[key]+"<br />";
|
out +="<b>"+key+"</b>: "+obj[key]+"<br />";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addUrlParams(_url, paramCheckboxes) {
|
||||||
|
var url = _url !== "" ? _url : "./";
|
||||||
|
|
||||||
|
for(var i = 0; i < paramCheckboxes.length; i++) {
|
||||||
|
var param = paramCheckboxes[i];
|
||||||
|
if (document.getElementById(param).checked){
|
||||||
|
url += url.includes("?") ? '&' : '?';
|
||||||
|
url += param;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<input placeholder="Enter an VDO.Ninja View URL here" id="viewlink" />
|
||||||
<input placeholder="Enter an VDO.Ninja View URL here" id="viewlink" />
|
<button onclick="loadIframe();">ADD</button>
|
||||||
<button onclick="loadIframe();">ADD</button>
|
<input type="checkbox" id="cleanoutput" >Clean Output
|
||||||
<input type="checkbox" id="clean" >Clean Output
|
<input type="checkbox" id="transparent">Transparent
|
||||||
<input type="checkbox" id="transparent">Transparent
|
<input type="checkbox" id="hidemenu">Hide Menu
|
||||||
<input type="checkbox" id="hidemenu">Hide Menu
|
<div id="container"></div>
|
||||||
<div id="container">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user