Files
archived-vdo.ninja/examples/simple-iframe-replacement.html
2025-10-21 20:52:45 -04:00

312 lines
9.4 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>Simple IFRAME Replacement Example</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.example {
border: 2px solid #ddd;
padding: 20px;
margin: 20px 0;
border-radius: 8px;
}
.old-way {
background: #fff3e0;
}
.new-way {
background: #e8f5e9;
}
pre {
background: #f5f5f5;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
}
button {
padding: 10px 20px;
font-size: 16px;
margin: 5px;
cursor: pointer;
}
.messages {
border: 1px solid #ddd;
padding: 10px;
height: 200px;
overflow-y: auto;
margin: 10px 0;
background: white;
}
h2 {
margin-top: 0;
}
</style>
</head>
<body>
<h1>Simple IFRAME Replacement with VDO.Ninja DataChannel SDK</h1>
<div class="example old-way">
<h2>❌ Old Way: Hidden IFRAME</h2>
<pre><code>// HTML
&lt;iframe id="vdo-iframe"
src="https://vdo.ninja/?room=myroom&amp;push=sender&amp;view=receiver&amp;datachannel=true"
style="display:none"&gt;&lt;/iframe&gt;
// JavaScript
const iframe = document.getElementById('vdo-iframe');
// Send message
iframe.contentWindow.postMessage({
action: 'send-data',
data: 'Hello from parent'
}, '*');
// Receive messages
window.addEventListener('message', (event) => {
if (event.origin !== 'https://vdo.ninja') return;
console.log('Received:', event.data);
});</code></pre>
<p><strong>Problems:</strong></p>
<ul>
<li>Hidden IFRAME still loads full VDO.Ninja UI</li>
<li>Cross-origin communication limitations</li>
<li>No direct control over connections</li>
<li>Hard to debug</li>
</ul>
</div>
<div class="example new-way">
<h2>✅ New Way: DataChannel SDK</h2>
<pre><code>// JavaScript only - no hidden IFRAME needed!
const node = new VDONinjaDataChannel();
// Connect and join room
await node.joinRoom({
room: 'myroom',
streamID: 'sender',
label: 'my-device'
});
// Send message
node.publish({ data: 'Hello from SDK' });
// Receive messages
node.addEventListener('data', (event) => {
console.log('Received:', event.detail.data);
});</code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li>No hidden IFRAME overhead</li>
<li>Direct DataChannel control</li>
<li>Label-based routing</li>
<li>Mesh networking support</li>
<li>Better debugging</li>
</ul>
</div>
<div class="example">
<h2>🚀 Live Demo</h2>
<p>Try it out! This demo shows two nodes communicating without any IFRAMEs.</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div>
<h3>Node A</h3>
<button onclick="connectNodeA()">Connect</button>
<button onclick="sendFromA()">Send Message</button>
<div class="messages" id="messagesA"></div>
</div>
<div>
<h3>Node B</h3>
<button onclick="connectNodeB()">Connect</button>
<button onclick="sendFromB()">Send Message</button>
<div class="messages" id="messagesB"></div>
</div>
</div>
</div>
<div class="example">
<h2>📝 Common Use Cases</h2>
<h3>1. IoT Sensor Network</h3>
<pre><code>// Sensor publishes data
const sensor = new VDONinjaDataChannel();
await sensor.joinRoom({ room: 'iot', label: 'temperature-sensor' });
setInterval(() => {
sensor.publish({
temp: Math.random() * 30 + 20,
unit: 'celsius',
timestamp: Date.now()
});
}, 5000);</code></pre>
<h3>2. Remote Control</h3>
<pre><code>// Controller subscribes to specific device
const controller = new VDONinjaDataChannel();
await controller.joinRoom({ room: 'iot', label: 'controller' });
// Subscribe to all temperature sensors
controller.subscribe('temperature-sensor');
controller.addEventListener('data', (e) => {
if (e.detail.data.temp > 25) {
// Send command back
controller.publish(
{ command: 'turn-on-fan' },
{ toLabel: e.detail.label }
);
}
});</code></pre>
<h3>3. Multi-User Chat</h3>
<pre><code>// Each user joins with unique ID but same label
const chat = new VDONinjaDataChannel();
await chat.joinRoom({
room: 'chatroom',
streamID: `user-${Date.now()}`,
label: 'chat-user'
});
// Subscribe to all chat users
chat.subscribe('chat-user');
// Send message to all
chat.publish({
message: 'Hello everyone!',
user: 'John'
});</code></pre>
</div>
<script src="../vdoninja-datachannel-sdk.js"></script>
<script>
let nodeA = null;
let nodeB = null;
let messageCount = { A: 0, B: 0 };
async function connectNodeA() {
if (nodeA) nodeA.disconnect();
nodeA = new VDONinjaDataChannel({
wss: 'wss://apibackup.vdo.ninja:443'
});
nodeA.addEventListener('data', (e) => {
addMessage('messagesA', `Received: ${JSON.stringify(e.detail.data)}`);
});
nodeA.addEventListener('peer-connected', (e) => {
addMessage('messagesA', '🔗 Peer connected!');
});
try {
await nodeA.joinRoom({
room: `demo-${window.location.hostname}`,
streamID: 'node-a',
label: 'demo-node'
});
addMessage('messagesA', '✅ Connected to room');
// Auto-discover and connect to peers
setTimeout(async () => {
const peers = Array.from(nodeA.peerStreamIDs.keys());
for (const peer of peers) {
if (peer !== nodeA.uuid) {
await nodeA.view(nodeA.peerStreamIDs.get(peer));
}
}
}, 1000);
} catch (error) {
addMessage('messagesA', `❌ Error: ${error.message}`);
}
}
async function connectNodeB() {
if (nodeB) nodeB.disconnect();
nodeB = new VDONinjaDataChannel({
wss: 'wss://apibackup.vdo.ninja:443'
});
nodeB.addEventListener('data', (e) => {
addMessage('messagesB', `Received: ${JSON.stringify(e.detail.data)}`);
});
nodeB.addEventListener('peer-connected', (e) => {
addMessage('messagesB', '🔗 Peer connected!');
});
try {
await nodeB.joinRoom({
room: `demo-${window.location.hostname}`,
streamID: 'node-b',
label: 'demo-node'
});
addMessage('messagesB', '✅ Connected to room');
// Subscribe to demo nodes
nodeB.subscribe('demo-node');
// Auto-connect to node A
setTimeout(() => {
nodeB.view('node-a');
}, 1000);
} catch (error) {
addMessage('messagesB', `❌ Error: ${error.message}`);
}
}
function sendFromA() {
if (!nodeA || !nodeA.connected) {
alert('Node A not connected!');
return;
}
messageCount.A++;
const data = {
message: `Hello from Node A (#${messageCount.A})`,
timestamp: new Date().toISOString()
};
nodeA.publish(data);
addMessage('messagesA', `Sent: ${JSON.stringify(data)}`);
}
function sendFromB() {
if (!nodeB || !nodeB.connected) {
alert('Node B not connected!');
return;
}
messageCount.B++;
const data = {
message: `Hello from Node B (#${messageCount.B})`,
timestamp: new Date().toISOString()
};
nodeB.publish(data);
addMessage('messagesB', `Sent: ${JSON.stringify(data)}`);
}
function addMessage(containerId, message) {
const container = document.getElementById(containerId);
const div = document.createElement('div');
div.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
container.appendChild(div);
container.scrollTop = container.scrollHeight;
}
// Cleanup on page unload
window.addEventListener('beforeunload', () => {
if (nodeA) nodeA.disconnect();
if (nodeB) nodeB.disconnect();
});
</script>
</body>
</html>