Playground
by
Jean Pierre Kolb
All Tools
back to jpkc.com
JPKCom Developer Tools
Code & Text Tools
Beautify
Cheat Sheets
Coder
Compiler
Convertor PRO
CSV Editor
JSON Editor
Lorem Ipsum
Markdown Editor
Playground
Regex Debugger
Source Viewer
WP Code Generator
WYSIWYG Editor
Design & Graphics
Colors
Fonts
Geopattern
Graphic Editor
Placeholder Service
Trianglify UI
Security & Utilities
Cryptor (AES-256)
DNS, SSL, Redirect & URL
Cron Job Helper
Docker/Podman Composer
IP Tools
Generator
Hash Generator
Mail Header Analyzer
Info Tools
QR Code
Time Converter
UUID Generator
About
JPKCom Developer Tools
Free online tools for web developers and designers.
32 Tools
available.
Run
Live
Snippets
Export HTML
Import HTML
Assets
0
Bootstrap CSS
Bootstrap JS
Bootstrap Icons
jQuery
Dark Mode
Panels:
HTML
CSS
JS
HTML
13
CSS
SCSS
13
JavaScript
13
Preview
100%
Save & Load Snippets
Save current snippet
Save
Up to 8 snippets stored in LocalStorage. Existing name = overwrite.
Saved Snippets
', assetsMarkerIdx + ASSETS_MARKER.length ); if ( assetsJsonEnd !== -1 ) { try { var importedAssets = JSON.parse( fileContent.slice( assetsMarkerIdx + ASSETS_MARKER.length, assetsJsonEnd ) ); if ( importedAssets && typeof importedAssets === 'object' ) { assets = Object.assign( { bootstrap: false, bsJs: false, icons: false, jquery: false, bsDark: false }, importedAssets ); document.getElementById( 'pg-asset-bootstrap' ).checked = !! assets.bootstrap; document.getElementById( 'pg-asset-bsjs' ).checked = !! assets.bsJs; document.getElementById( 'pg-asset-icons' ).checked = !! assets.icons; document.getElementById( 'pg-asset-jquery' ).checked = !! assets.jquery; document.getElementById( 'pg-asset-bsdark' ).checked = !! assets.bsDark; updateDarkModeAvailability(); updateAssetsCount(); localStorage.setItem( STORAGE.assets, JSON.stringify( assets ) ); assetsRestored = true; } } catch ( e ) {} } } scheduleSave(); updatePreview(); Toast.success( 'Imported ' + imported + ' panel' + ( imported !== 1 ? 's' : '' ) + ( assetsRestored ? ' + assets' : '' ) + ' from file.' ); } /** Download the raw content of a single editor panel */ function downloadPanel( panel ) { var ext = ( panel === 'css' && cssMode === 'scss' ) ? 'scss' : panel; var content = editors[ panel ].getValue(); if ( ! content.trim() ) { Toast.warning( 'Editor is empty.' ); return; } var mime = ( panel === 'js' ) ? 'application/javascript' : 'text/' + ext; downloadBlob( new Blob( [ content ], { type: mime + ';charset=utf-8' } ), 'playground.' + ext ); Toast.success( ext.toUpperCase() + ' downloaded.' ); } // ======================================================================== // Drag-to-resize between editor row and preview // ======================================================================== function initResizer() { var resizer = document.getElementById( 'pg-resizer' ); var editorsEl = document.querySelector( '.pg-editors' ); var app = document.getElementById( 'playground-app' ); var toolbar = document.querySelector( '.pg-toolbar' ); resizer.addEventListener( 'mousedown', function ( e ) { isResizing = true; resizer.classList.add( 'pg-resizing' ); document.body.style.cursor = 'row-resize'; document.body.style.userSelect = 'none'; e.preventDefault(); } ); document.addEventListener( 'mousemove', function ( e ) { if ( ! isResizing ) return; var appRect = app.getBoundingClientRect(); var toolbarH = toolbar ? toolbar.offsetHeight : 44; var newHeight = e.clientY - appRect.top - toolbarH; var minH = 100; var maxH = appRect.height - toolbarH - 80; newHeight = Math.max( minH, Math.min( maxH, newHeight ) ); editorsEl.style.flex = '0 0 ' + newHeight + 'px'; editorsEl.style.maxHeight = 'none'; // Notify ACE editors so they redraw their scrollbars [ 'html', 'css', 'js' ].forEach( function ( p ) { if ( editors[ p ] ) { editors[ p ].resize(); } } ); } ); document.addEventListener( 'mouseup', function () { if ( isResizing ) { isResizing = false; resizer.classList.remove( 'pg-resizing' ); document.body.style.cursor = ''; document.body.style.userSelect = ''; } } ); } // ======================================================================== // Keyboard shortcut: Ctrl+Enter = Run // ======================================================================== function initKeyboardShortcuts() { document.addEventListener( 'keydown', function ( e ) { // Ctrl/Cmd + Enter → Run if ( ( e.ctrlKey || e.metaKey ) && e.key === 'Enter' ) { e.preventDefault(); updatePreview(); return; } // F11 → toggle fullscreen if ( e.key === 'F11' ) { e.preventDefault(); toggleFullscreen(); return; } // Escape → exit fullscreen if ( e.key === 'Escape' && isFullscreen ) { toggleFullscreen(); } } ); } // ======================================================================== // Event binding // ======================================================================== function bindEvents() { // Run button document.getElementById( 'pg-run' ).addEventListener( 'click', updatePreview ); // Live-update toggle document.getElementById( 'pg-live' ).addEventListener( 'change', function () { liveOn = this.checked; } ); // SCSS mode toggle document.getElementById( 'pg-scss-toggle' ).addEventListener( 'change', function () { cssMode = this.checked ? 'scss' : 'css'; editors.css.session.setMode( 'ace/mode/' + ( cssMode === 'scss' ? 'scss' : 'css' ) ); document.getElementById( 'pg-css-label' ).textContent = cssMode === 'scss' ? 'SCSS' : 'CSS'; localStorage.setItem( STORAGE.mode, cssMode ); scheduleUpdate(); } ); // Asset checkboxes: icons, jquery, Bootstrap JS (straightforward toggles) [ { key: 'icons', id: 'pg-asset-icons' }, { key: 'jquery', id: 'pg-asset-jquery' }, { key: 'bsJs', id: 'pg-asset-bsjs' } ].forEach( function ( item ) { document.getElementById( item.id ).addEventListener( 'change', function () { assets[ item.key ] = this.checked; localStorage.setItem( STORAGE.assets, JSON.stringify( assets ) ); updateAssetsCount(); updatePreview(); } ); } ); // Bootstrap CSS checkbox: also controls Dark Mode availability document.getElementById( 'pg-asset-bootstrap' ).addEventListener( 'change', function () { assets.bootstrap = this.checked; updateDarkModeAvailability(); localStorage.setItem( STORAGE.assets, JSON.stringify( assets ) ); updateAssetsCount(); updatePreview(); } ); // Bootstrap Dark Mode toggle document.getElementById( 'pg-asset-bsdark' ).addEventListener( 'change', function () { assets.bsDark = this.checked; localStorage.setItem( STORAGE.assets, JSON.stringify( assets ) ); updateAssetsCount(); updatePreview(); } ); // Open snippets modal document.getElementById( 'pg-open-slots' ).addEventListener( 'click', function () { renderSlotsList(); document.getElementById( 'pg-slot-name' ).value = ''; new bootstrap.Modal( document.getElementById( 'pg-slots-modal' ) ).show(); } ); // Save button inside modal document.getElementById( 'pg-save-slot' ).addEventListener( 'click', function () { if ( saveToSlot( document.getElementById( 'pg-slot-name' ).value ) ) { renderSlotsList(); } } ); // Enter key in name field triggers save document.getElementById( 'pg-slot-name' ).addEventListener( 'keydown', function ( e ) { if ( e.key === 'Enter' ) { document.getElementById( 'pg-save-slot' ).click(); } } ); // Delegated click on slot list items (load / delete) document.getElementById( 'pg-slots-list' ).addEventListener( 'click', function ( e ) { var loadBtn = e.target.closest( '.pg-slot-load' ); var delBtn = e.target.closest( '.pg-slot-del' ); if ( loadBtn ) { var name = loadBtn.getAttribute( 'data-name' ); var slots = getSlots(); var slot = null; for ( var i = 0; i < slots.length; i++ ) { if ( slots[ i ].name === name ) { slot = slots[ i ]; break; } } if ( slot ) { loadSlot( slot ); bootstrap.Modal.getInstance( document.getElementById( 'pg-slots-modal' ) ).hide(); } } if ( delBtn ) { deleteSlot( delBtn.getAttribute( 'data-name' ) ); } } ); // Reset to defaults document.getElementById( 'pg-reset' ).addEventListener( 'click', resetToDefaults ); // Fullscreen toggle document.getElementById( 'pg-fullscreen' ).addEventListener( 'click', toggleFullscreen ); // Preview view mode buttons document.getElementById( 'pg-view-rendered' ).addEventListener( 'click', function () { setPreviewMode( 'rendered' ); } ); document.getElementById( 'pg-view-source' ).addEventListener( 'click', function () { setPreviewMode( 'source' ); } ); // Export full HTML document.getElementById( 'pg-export' ).addEventListener( 'click', exportFullHtml ); // Import HTML — trigger the hidden file input document.getElementById( 'pg-import' ).addEventListener( 'click', function () { document.getElementById( 'pg-import-file' ).click(); } ); // File selected: read and parse document.getElementById( 'pg-import-file' ).addEventListener( 'change', function () { var file = this.files[ 0 ]; if ( ! file ) { return; } var reader = new FileReader(); reader.onload = function ( e ) { importHtml( e.target.result ); }; reader.onerror = function () { Toast.error( 'Failed to read the selected file.' ); }; reader.readAsText( file ); // Reset so the same file can be re-imported without re-selecting this.value = ''; } ); // Open preview in new browser tab document.getElementById( 'pg-open-tab' ).addEventListener( 'click', function () { compileCss( editors.css.getValue(), function ( compiledCss ) { var doc = buildPreviewDoc( editors.html.getValue(), compiledCss, editors.js.getValue() ); var win = window.open( '', '_blank' ); if ( win ) { win.document.write( doc ); win.document.close(); } else { Toast.warning( 'Popup was blocked. Please allow popups for this site.' ); } } ); } ); // Panel visibility toggles [ 'html', 'css', 'js' ].forEach( function ( p ) { document.getElementById( 'pg-toggle-' + p ).addEventListener( 'click', function () { panelVisible[ p ] = ! panelVisible[ p ]; updatePanelVisibility(); } ); } ); // Preview zoom buttons document.getElementById( 'pg-zoom-dec' ).addEventListener( 'click', function () { changePreviewZoom( -1 ); } ); document.getElementById( 'pg-zoom-inc' ).addEventListener( 'click', function () { changePreviewZoom( 1 ); } ); // Per-panel: Font size decrease / increase document.querySelectorAll( '.pg-font-dec' ).forEach( function ( btn ) { btn.addEventListener( 'click', function () { changeFontSize( this.getAttribute( 'data-panel' ), -1 ); } ); } ); document.querySelectorAll( '.pg-font-inc' ).forEach( function ( btn ) { btn.addEventListener( 'click', function () { changeFontSize( this.getAttribute( 'data-panel' ), 1 ); } ); } ); // Per-panel: Copy document.querySelectorAll( '.pg-copy-btn' ).forEach( function ( btn ) { btn.addEventListener( 'click', function () { var panel = this.getAttribute( 'data-panel' ); Clipboard.copy( editors[ panel ].getValue(), { successMessage: panel.toUpperCase() + ' copied!' } ); } ); } ); // Per-panel: Download document.querySelectorAll( '.pg-dl-btn' ).forEach( function ( btn ) { btn.addEventListener( 'click', function () { downloadPanel( this.getAttribute( 'data-panel' ) ); } ); } ); // Per-panel: Clear document.querySelectorAll( '.pg-clear-btn' ).forEach( function ( btn ) { btn.addEventListener( 'click', function () { var panel = this.getAttribute( 'data-panel' ); editors[ panel ].setValue( '', -1 ); scheduleSave(); } ); } ); } // ======================================================================== // Initialise // ======================================================================== $( document ).ready( function () { initEditors(); initResizer(); initKeyboardShortcuts(); bindEvents(); // Let the browser complete the flex layout pass, then tell ACE // to re-measure its container so scrollbars and cursor positions // are calculated correctly from the start. requestAnimationFrame( function () { [ 'html', 'css', 'js' ].forEach( function ( p ) { if ( editors[ p ] ) { editors[ p ].resize(); } } ); // Apply restored (or default) panel visibility updatePanelVisibility(); // Apply restored (or default) preview zoom applyPreviewZoom(); // Render the initial preview after editors are sized updatePreview(); } ); } ); } )();