You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, sidebarWidth = "250px", defaultBgColor = "#ffffff") {
// Main Container setup
const container = document.createElement('div');
container.style.display = 'flex';
container.style.width = '100%';
container.style.height = '80vh';
container.style.minHeight = '600px';
container.style.fontFamily = 'Segoe UI, Tahoma, Geneva, Verdana, sans-serif';
container.style.border = '1px solid #ced4da';
container.style.boxSizing = 'border-box';
container.style.color = '#333';
container.style.backgroundColor = defaultBgColor;
// Sidebar setup
const sidebar = document.createElement('div');
sidebar.style.width = sidebarWidth;
sidebar.style.minWidth = sidebarWidth;
sidebar.style.backgroundColor = '#f8f9fa';
sidebar.style.borderRight = '1px solid #dee2e6';
sidebar.style.padding = '15px';
sidebar.style.boxSizing = 'border-box';
sidebar.style.display = 'flex';
sidebar.style.flexDirection = 'column';
sidebar.style.overflowY = 'auto';
sidebar.style.zIndex = '10';
const title = document.createElement('h3');
title.textContent = 'Website Elements';
title.style.margin = '0 0 15px 0';
title.style.fontSize = '18px';
title.style.fontWeight = '600';
sidebar.appendChild(title);
// Draggable Component Library
const components = [
{
name: 'Header Navbar',
type: 'container',
html: '<div style="width: 100%; height: 100%; background-color: #343a40; color: white; display: flex; align-items: center; padding: 0 20px; box-sizing: border-box; font-family: sans-serif; font-size: 18px; font-weight: bold;">Navigation Bar</div>',
width: '100%', height: '60px', resize: true
},
{
name: 'Primary Button',
type: 'button',
html: '<button style="width: 100%; height: 100%; cursor: pointer; border: none; background-color: #0d6efd; color: white; border-radius: 6px; font-size: 16px; font-weight: 500; font-family: sans-serif;">Submit</button>',
width: '120px', height: '45px', resize: true
},
{
name: 'Editable Text Area',
type: 'text',
html: '<div contenteditable="true" style="width: 100%; height: 100%; padding: 10px; box-sizing: border-box; cursor: text; font-family: sans-serif; overflow: hidden; font-size: 16px; border: 1px dashed transparent; line-height: 1.5; color: #495057;">Click here to edit this paragraph text...</div>',
width: '250px', height: '100px', resize: true
},
{
name: 'Title Heading',
type: 'header',
html: '<h1 contenteditable="true" style="margin: 0; width: 100%; height: 100%; cursor: text; font-family: sans-serif; overflow: hidden; font-size: 36px; font-weight: 700; color: #212529;">Heading Title</h1>',
width: '250px', height: '50px', resize: true
},
{
name: 'Original Extracted Image',
type: 'image',
html: `<img src="${originalImg.src}" style="width: 100%; height: 100%; object-fit: contain; pointer-events: none;" draggable="false" alt="Tool Image"/>`,
width: '200px', height: '200px', resize: true
},
{
name: 'Text Input Field',
type: 'input',
html: '<input type="text" placeholder="Type input here..." style="width: 100%; height: 100%; box-sizing: border-box; border: 1px solid #ced4da; border-radius: 4px; padding: 0 12px; font-size: 16px; font-family: sans-serif; outline: none;"/>',
width: '200px', height: '40px', resize: true
},
{
name: 'Structure Block',
type: 'container',
html: '<div style="width: 100%; height: 100%; border: 2px dashed #adb5bd; background: rgba(0, 0, 0, 0.03); box-sizing: border-box; border-radius: 8px;"></div>',
width: '300px', height: '200px', resize: true
}
];
let draggedComponent = null;
// Render Component Buttons in Sidebar
components.forEach(comp => {
const el = document.createElement('div');
el.textContent = comp.name;
el.style.padding = '12px 10px';
el.style.marginBottom = '12px';
el.style.backgroundColor = '#ffffff';
el.style.border = '1px solid #ced4da';
el.style.color = '#495057';
el.style.cursor = 'grab';
el.style.textAlign = 'center';
el.style.borderRadius = '6px';
el.style.boxShadow = '0 1px 3px rgba(0,0,0,0.05)';
el.style.transition = 'all 0.2s';
el.onmouseenter = () => { el.style.backgroundColor = '#e9ecef'; el.style.borderColor = '#adb5bd'; };
el.onmouseleave = () => { el.style.backgroundColor = '#ffffff'; el.style.borderColor = '#ced4da'; };
el.setAttribute('draggable', 'true');
el.addEventListener('dragstart', (e) => {
draggedComponent = comp;
e.dataTransfer.effectAllowed = 'copy';
e.dataTransfer.setData('text/plain', comp.type);
});
el.addEventListener('dragend', () => {
setTimeout(() => draggedComponent = null, 100);
});
sidebar.appendChild(el);
});
// Sidebar Controls Area
const controlsTitle = document.createElement('h3');
controlsTitle.textContent = 'Controls';
controlsTitle.style.marginTop = 'auto';
controlsTitle.style.paddingTop = '20px';
controlsTitle.style.fontSize = '16px';
controlsTitle.style.fontWeight = '600';
sidebar.appendChild(controlsTitle);
const bgBtn = document.createElement('button');
bgBtn.textContent = 'Set Image as BG';
bgBtn.style.padding = '10px';
bgBtn.style.width = '100%';
bgBtn.style.marginBottom = '10px';
bgBtn.style.cursor = 'pointer';
bgBtn.style.backgroundColor = '#198754';
bgBtn.style.color = '#fff';
bgBtn.style.border = 'none';
bgBtn.style.borderRadius = '6px';
bgBtn.onclick = () => {
workspace.style.backgroundImage = `url(${originalImg.src})`;
workspace.style.backgroundSize = 'contain';
workspace.style.backgroundRepeat = 'no-repeat';
workspace.style.backgroundPosition = 'center';
};
bgBtn.onmouseenter = () => bgBtn.style.backgroundColor = '#157347';
bgBtn.onmouseleave = () => bgBtn.style.backgroundColor = '#198754';
sidebar.appendChild(bgBtn);
const gridBtn = document.createElement('button');
gridBtn.textContent = 'Blueprint Grid Mode';
gridBtn.style.padding = '10px';
gridBtn.style.width = '100%';
gridBtn.style.marginBottom = '10px';
gridBtn.style.cursor = 'pointer';
gridBtn.style.backgroundColor = '#6c757d';
gridBtn.style.color = '#fff';
gridBtn.style.border = 'none';
gridBtn.style.borderRadius = '6px';
gridBtn.onclick = () => {
workspace.style.backgroundImage = 'radial-gradient(#adb5bd 1px, transparent 1px)';
workspace.style.backgroundSize = '20px 20px';
workspace.style.backgroundPosition = '0 0';
};
gridBtn.onmouseenter = () => gridBtn.style.backgroundColor = '#5a6268';
gridBtn.onmouseleave = () => gridBtn.style.backgroundColor = '#6c757d';
sidebar.appendChild(gridBtn);
const clearBtn = document.createElement('button');
clearBtn.textContent = 'Clear All Elements';
clearBtn.style.padding = '10px';
clearBtn.style.width = '100%';
clearBtn.style.cursor = 'pointer';
clearBtn.style.backgroundColor = '#dc3545';
clearBtn.style.color = '#fff';
clearBtn.style.border = 'none';
clearBtn.style.borderRadius = '6px';
clearBtn.onclick = () => {
workspace.innerHTML = '';
workspace.appendChild(instructions);
};
clearBtn.onmouseenter = () => clearBtn.style.backgroundColor = '#c82333';
clearBtn.onmouseleave = () => clearBtn.style.backgroundColor = '#dc3545';
sidebar.appendChild(clearBtn);
// Main Workspace Environment setup
const workspace = document.createElement('div');
workspace.style.flex = '1';
workspace.style.position = 'relative';
workspace.style.overflow = 'hidden';
workspace.style.backgroundColor = defaultBgColor;
workspace.style.backgroundImage = 'radial-gradient(#adb5bd 1px, transparent 1px)';
workspace.style.backgroundSize = '20px 20px';
const instructions = document.createElement('div');
instructions.style.position = 'absolute';
instructions.style.top = '20px';
instructions.style.left = '50%';
instructions.style.transform = 'translateX(-50%)';
instructions.style.backgroundColor = 'rgba(33, 37, 41, 0.8)';
instructions.style.color = '#fff';
instructions.style.padding = '10px 20px';
instructions.style.borderRadius = '30px';
instructions.style.fontSize = '14px';
instructions.style.pointerEvents = 'none';
instructions.style.zIndex = '999';
instructions.style.fontFamily = 'sans-serif';
instructions.style.whiteSpace = 'nowrap';
instructions.innerHTML = '✨ Drag widgets here gracefully. Edit text directly. Move via dragging and resize via bottom-right area. ✨';
workspace.appendChild(instructions);
// Global Drag Variables (Kept closely restricted within the module limits)
let currentDraggingElement = null;
let dragStartX = 0;
let dragStartY = 0;
let dragInitialLeft = 0;
let dragInitialTop = 0;
const onGlobalMouseMove = (e) => {
if (currentDraggingElement) {
const dx = e.clientX - dragStartX;
const dy = e.clientY - dragStartY;
currentDraggingElement.style.left = `${dragInitialLeft + dx}px`;
currentDraggingElement.style.top = `${dragInitialTop + dy}px`;
}
};
const onGlobalMouseUp = () => {
if (currentDraggingElement) {
currentDraggingElement.style.zIndex = '';
currentDraggingElement = null;
document.body.style.userSelect = '';
document.removeEventListener('mousemove', onGlobalMouseMove);
document.removeEventListener('mouseup', onGlobalMouseUp);
}
};
// External to Workspace Drop handling
workspace.addEventListener('dragover', (e) => {
if (draggedComponent) {
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
}
});
workspace.addEventListener('drop', (e) => {
if (draggedComponent) {
e.preventDefault();
e.stopPropagation();
if (instructions.parentNode) workspace.removeChild(instructions);
const isResizable = draggedComponent.resize;
const rect = workspace.getBoundingClientRect();
let posX = e.clientX - rect.left - 20;
let posY = e.clientY - rect.top - 20;
// Safe positional boundary clamping
if (posX < 0) posX = 0;
if (posY < 0) posY = 0;
const wrapper = document.createElement('div');
wrapper.style.position = 'absolute';
wrapper.style.left = `${posX}px`;
wrapper.style.top = `${posY}px`;
wrapper.style.width = draggedComponent.width;
wrapper.style.height = draggedComponent.height;
wrapper.style.cursor = 'move';
wrapper.style.boxSizing = 'border-box';
if (isResizable) {
wrapper.style.resize = 'both';
wrapper.style.overflow = 'hidden';
}
const content = document.createElement('div');
content.style.width = '100%';
content.style.height = '100%';
content.style.pointerEvents = 'auto';
content.style.overflow = 'hidden';
content.innerHTML = draggedComponent.html;
wrapper.appendChild(content);
const closeBtn = document.createElement('div');
closeBtn.innerHTML = '×';
closeBtn.style.position = 'absolute';
closeBtn.style.top = '0px';
closeBtn.style.right = '0px';
closeBtn.style.width = '24px';
closeBtn.style.height = '24px';
closeBtn.style.backgroundColor = '#dc3545';
closeBtn.style.color = 'white';
closeBtn.style.lineHeight = '24px';
closeBtn.style.textAlign = 'center';
closeBtn.style.fontSize = '18px';
closeBtn.style.fontWeight = 'bold';
closeBtn.style.fontFamily = 'Arial, sans-serif';
closeBtn.style.cursor = 'pointer';
closeBtn.style.display = 'none';
closeBtn.style.zIndex = '1001';
closeBtn.style.borderBottomLeftRadius = '6px';
wrapper.addEventListener('mouseenter', () => {
closeBtn.style.display = 'block';
wrapper.style.outline = '1px dashed #0d6efd';
});
wrapper.addEventListener('mouseleave', () => {
closeBtn.style.display = 'none';
wrapper.style.outline = 'none';
});
closeBtn.addEventListener('click', (e) => {
workspace.removeChild(wrapper);
e.stopPropagation();
});
wrapper.appendChild(closeBtn);
wrapper.addEventListener('mousedown', (e) => {
const innerRect = wrapper.getBoundingClientRect();
// Allow native resize handle to absorb input rather than drag mechanism
const isBottomRight = (e.clientX - innerRect.left) > (innerRect.width - 25) &&
(e.clientY - innerRect.top) > (innerRect.height - 25);
if (isBottomRight && isResizable) return;
// Restrict intercept for forms and contentEditables giving user text control
if (e.target === closeBtn || e.target.closest('[contenteditable="true"]') ||
e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON') {
return;
}
currentDraggingElement = wrapper;
dragStartX = e.clientX;
dragStartY = e.clientY;
dragInitialLeft = parseInt(wrapper.style.left, 10) || 0;
dragInitialTop = parseInt(wrapper.style.top, 10) || 0;
wrapper.style.zIndex = Math.floor(Date.now() % 1000000);
document.body.style.userSelect = 'none';
document.addEventListener('mousemove', onGlobalMouseMove);
document.addEventListener('mouseup', onGlobalMouseUp);
e.stopPropagation();
});
workspace.appendChild(wrapper);
}
draggedComponent = null;
});
container.appendChild(sidebar);
container.appendChild(workspace);
return container;
}
Apply Changes