Skip to content

Commit 2b8f872

Browse files
authored
1 parent d117432 commit 2b8f872

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed

iframe-api-explorer.html

+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>API Explorer</title>
5+
<style>
6+
body {
7+
font-family: system-ui, -apple-system, sans-serif;
8+
margin: 0;
9+
padding: 20px;
10+
background: #f0f0f0;
11+
}
12+
iframe {
13+
width: 100%;
14+
border: 1px solid #ccc;
15+
border-radius: 4px;
16+
background: white;
17+
transition: height 0.2s ease;
18+
}
19+
</style>
20+
</head>
21+
<body>
22+
<iframe id="explorerFrame" sandbox="allow-scripts"></iframe>
23+
24+
<script>
25+
// Create the HTML content for the iframe
26+
const iframeContent = `
27+
<!DOCTYPE html>
28+
<html>
29+
<head>
30+
<style>
31+
body {
32+
font-family: system-ui, -apple-system, sans-serif;
33+
margin: 0;
34+
padding: 20px;
35+
}
36+
.container {
37+
max-width: 800px;
38+
margin: 0 auto;
39+
}
40+
.input-group {
41+
display: flex;
42+
gap: 8px;
43+
margin-bottom: 20px;
44+
}
45+
input[type="text"] {
46+
flex: 1;
47+
padding: 8px;
48+
border: 1px solid #ccc;
49+
border-radius: 4px;
50+
font-size: 16px;
51+
}
52+
button {
53+
padding: 8px 16px;
54+
background: #0066cc;
55+
color: white;
56+
border: none;
57+
border-radius: 4px;
58+
cursor: pointer;
59+
font-size: 16px;
60+
}
61+
button:hover {
62+
background: #0052a3;
63+
}
64+
pre {
65+
background: #f5f5f5;
66+
padding: 20px;
67+
border-radius: 4px;
68+
overflow-x: auto;
69+
white-space: pre-wrap;
70+
word-wrap: break-word;
71+
}
72+
.error {
73+
color: #cc0000;
74+
}
75+
</style>
76+
</head>
77+
<body>
78+
<div class="container">
79+
<h1>API Explorer</h1>
80+
<form onsubmit="makeRequest(); return false;">
81+
<div class="input-group">
82+
<input type="text" id="urlInput" placeholder="Enter API URL" value="https://datasette.io/content/stats.json?_size=1">
83+
<button onclick="makeRequest()">Submit</button>
84+
</div>
85+
</form>
86+
<pre id="output">// Response will appear here</pre>
87+
</div>
88+
89+
<script>
90+
let currentHeight = null;
91+
function updateParentHeight() {
92+
// Borrowed from https://github.com/FaiblUG/setIframeHeight/blob/5509feb0f281251d03065991b1c5f451f40fa8bd/dist/set-iframe-height-child.js#L31C1-L31C220
93+
let newHeight = Math.min(
94+
Math.max(
95+
document.body.offsetHeight, document.documentElement.offsetHeight
96+
),
97+
Math.max(
98+
Math.max(
99+
document.body.scrollHeight, document.documentElement.scrollHeight
100+
),
101+
Math.max(
102+
document.body.clientHeight, document.documentElement.clientHeight
103+
)
104+
)
105+
);
106+
if (currentHeight === newHeight) {
107+
return;
108+
}
109+
currentHeight = newHeight;
110+
window.parent.postMessage({
111+
type: 'resize',
112+
height: newHeight
113+
}, '*');
114+
}
115+
116+
updateParentHeight();
117+
118+
setInterval(updateParentHeight, 1000);
119+
120+
function makeRequest() {
121+
const url = document.getElementById('urlInput').value;
122+
const output = document.getElementById('output');
123+
124+
// Send message to parent window
125+
window.parent.postMessage({
126+
type: 'api-request',
127+
url: url,
128+
method: 'GET'
129+
}, '*');
130+
131+
output.textContent = 'Loading...';
132+
}
133+
134+
// Listen for response from parent
135+
window.addEventListener('message', function(event) {
136+
const output = document.getElementById('output');
137+
138+
if (event.data.type === 'api-response') {
139+
if (event.data.error) {
140+
output.textContent = 'Error: ' + event.data.error;
141+
output.classList.add('error');
142+
} else {
143+
output.textContent = JSON.stringify(event.data.response, null, 2);
144+
output.classList.remove('error');
145+
}
146+
// Content has changed, update height
147+
setTimeout(() => {
148+
updateParentHeight();
149+
}, 100);
150+
}
151+
});
152+
SCUB
153+
</body>
154+
</html>
155+
`.replace('SCUB', '</' + 'script>');
156+
157+
// Set up the iframe with the content
158+
const iframe = document.getElementById('explorerFrame');
159+
iframe.src = 'data:text/html;charset=utf-8,' + encodeURIComponent(iframeContent);
160+
161+
// Listen for messages from the iframe
162+
window.addEventListener('message', async function(event) {
163+
if (event.data.type === 'api-request') {
164+
try {
165+
const response = await fetch(event.data.url, {
166+
method: event.data.method
167+
});
168+
169+
const data = await response.json();
170+
171+
// Send response back to iframe
172+
iframe.contentWindow.postMessage({
173+
type: 'api-response',
174+
response: data
175+
}, '*');
176+
} catch (error) {
177+
// Send error back to iframe
178+
iframe.contentWindow.postMessage({
179+
type: 'api-response',
180+
error: error.message
181+
}, '*');
182+
}
183+
} else if (event.data.type === 'resize') {
184+
// Update iframe height when child requests it
185+
iframe.style.height = event.data.height + 'px';
186+
}
187+
});
188+
</script>
189+
</body>
190+
</html>

0 commit comments

Comments
 (0)