The ScramjetFrame class provides an abstraction over proxy iframe creation, allowing you to manage isolated browsing contexts without worrying about proxy internals.
Creating a frame
Frames are created using the createFrame() method on your ScramjetController instance:
const { ScramjetController } = $scramjetLoadController ();
const scramjet = new ScramjetController ({ prefix: '/scramjet/' });
await scramjet . init ();
// Create a new frame
const frame = scramjet . createFrame ();
// Add it to the DOM
document . body . appendChild ( frame . frame );
You can also pass an existing iframe element to createFrame() if you want to use a pre-configured iframe: const existingIframe = document . getElementById ( 'myIframe' );
const frame = scramjet . createFrame ( existingIframe );
Navigation methods
The ScramjetFrame class provides several methods for controlling navigation within the isolated context:
Navigate to a URL
Use the go() method to navigate to a new URL:
// Navigate with a string URL
frame . go ( 'https://example.com' );
// Navigate with a URL object
frame . go ( new URL ( 'https://example.com/page' ));
Browser history navigation
// Go back in history
frame . back ();
Accessing frame properties
The ScramjetFrame instance provides access to useful properties:
Current URL
Get the current proxified URL:
const currentUrl = frame . url ;
console . log ( 'Current URL:' , currentUrl . href );
console . log ( 'Hostname:' , currentUrl . hostname );
console . log ( 'Path:' , currentUrl . pathname );
ScramjetClient instance
Access the ScramjetClient instance running inside the iframe:
const client = frame . client ;
// The client provides low-level access to the proxy internals
The client property gives you access to the Scramjet instance running within the iframe’s context, allowing for advanced manipulation if needed.
Raw iframe element
Access the underlying HTMLIFrameElement:
const iframeElement = frame . frame ;
// You can manipulate the iframe directly
iframeElement . style . width = '100%' ;
iframeElement . style . height = '600px' ;
iframeElement . setAttribute ( 'sandbox' , 'allow-scripts allow-same-origin' );
Building a browser interface
Here’s a complete example of building a simple browser interface with navigation controls:
<! DOCTYPE html >
< html >
< head >
< style >
* {
margin : 0 ;
padding : 0 ;
box-sizing : border-box ;
}
body {
font-family : system-ui , -apple-system , sans-serif ;
display : flex ;
flex-direction : column ;
height : 100 vh ;
}
.toolbar {
display : flex ;
gap : 8 px ;
padding : 12 px ;
background : #f5f5f5 ;
border-bottom : 1 px solid #ddd ;
}
.toolbar button {
padding : 8 px 16 px ;
border : 1 px solid #ccc ;
background : white ;
cursor : pointer ;
border-radius : 4 px ;
}
.toolbar button :hover {
background : #e9e9e9 ;
}
.toolbar input {
flex : 1 ;
padding : 8 px 12 px ;
border : 1 px solid #ccc ;
border-radius : 4 px ;
font-size : 14 px ;
}
#frameContainer {
flex : 1 ;
position : relative ;
}
iframe {
width : 100 % ;
height : 100 % ;
border : none ;
}
</ style >
</ head >
< body >
< div class = "toolbar" >
< button id = "backBtn" > ← Back </ button >
< button id = "forwardBtn" > Forward → </ button >
< button id = "reloadBtn" > ↻ Reload </ button >
< input type = "text" id = "urlBar" placeholder = "Enter URL..." />
< button id = "goBtn" > Go </ button >
</ div >
< div id = "frameContainer" ></ div >
< script >
( async () => {
// Initialize Scramjet
if ( 'serviceWorker' in navigator ) {
await navigator . serviceWorker . register ( '/scramjet.all.js' , {
scope: '/scramjet/' ,
});
}
await navigator . serviceWorker . ready ;
const { ScramjetController } = $scramjetLoadController ();
const scramjet = new ScramjetController ({
prefix: '/scramjet/' ,
});
await scramjet . init ();
// Create frame
const frame = scramjet . createFrame ();
document . getElementById ( 'frameContainer' ). appendChild ( frame . frame );
// Get UI elements
const urlBar = document . getElementById ( 'urlBar' );
const backBtn = document . getElementById ( 'backBtn' );
const forwardBtn = document . getElementById ( 'forwardBtn' );
const reloadBtn = document . getElementById ( 'reloadBtn' );
const goBtn = document . getElementById ( 'goBtn' );
// Navigation functions
const navigate = () => {
let url = urlBar . value . trim ();
if ( ! url ) return ;
// Add protocol if missing
if ( ! url . match ( / ^ https ? : \/\/ / )) {
url = 'https://' + url ;
}
frame . go ( url );
};
// Event listeners
goBtn . addEventListener ( 'click' , navigate );
urlBar . addEventListener ( 'keypress' , ( e ) => {
if ( e . key === 'Enter' ) navigate ();
});
backBtn . addEventListener ( 'click' , () => frame . back ());
forwardBtn . addEventListener ( 'click' , () => frame . forward ());
reloadBtn . addEventListener ( 'click' , () => frame . reload ());
// Update URL bar when navigation occurs
frame . addEventListener ( 'urlchange' , ( event ) => {
urlBar . value = event . url ;
document . title = event . url ;
});
// Optional: Log navigation events
frame . addEventListener ( 'navigate' , ( event ) => {
console . log ( 'Navigating to:' , event . url );
});
// Start with a default page
frame . go ( 'https://example.com' );
})();
</ script >
</ body >
</ html >
Multiple frames
You can create and manage multiple frames simultaneously:
const { ScramjetController } = $scramjetLoadController ();
const scramjet = new ScramjetController ({ prefix: '/scramjet/' });
await scramjet . init ();
// Create multiple frames
const frame1 = scramjet . createFrame ();
const frame2 = scramjet . createFrame ();
document . getElementById ( 'container1' ). appendChild ( frame1 . frame );
document . getElementById ( 'container2' ). appendChild ( frame2 . frame );
// Navigate each frame independently
frame1 . go ( 'https://example.com' );
frame2 . go ( 'https://example.org' );
// Each frame has independent event listeners
frame1 . addEventListener ( 'urlchange' , ( e ) => {
console . log ( 'Frame 1 URL:' , e . url );
});
frame2 . addEventListener ( 'urlchange' , ( e ) => {
console . log ( 'Frame 2 URL:' , e . url );
});
Advanced usage
Detecting when context is ready
Listen for the contextInit event to know when the frame has fully initialized:
frame . addEventListener ( 'contextInit' , ( event ) => {
console . log ( 'Frame initialized!' );
console . log ( 'Window object:' , event . window );
console . log ( 'Client instance:' , event . client );
});
Styling frames
Style the iframe element to fit your application:
const frame = scramjet . createFrame ();
// Apply styles directly
frame . frame . style . cssText = `
width: 100%;
height: 100%;
border: none;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
` ;
// Or use classes
frame . frame . className = 'proxy-frame' ;
Frame cleanup
When you’re done with a frame, remove it from the DOM:
// Remove the frame
frame . frame . remove ();
// Or keep a reference and reuse it later
const frames = new Map ();
frames . set ( 'main' , frame );
// Later...
const mainFrame = frames . get ( 'main' );
mainFrame . go ( 'https://newurl.com' );
Event handling Learn how to handle navigation, URL changes, and download events
Cookie management Manage cookies within isolated frame contexts