├── README.md ├── quickSearch.uc.js ├── quickSearch_NoBar.uc.js └── theme.json /README.md: -------------------------------------------------------------------------------- 1 | # ⭐ Quick Search - Zen Browser ⭐ 2 | Script to quickly search for a word or phrase in the Zen Browser through a pop up thus removing the need to create and swtich to a new tab. 3 | 4 | ## Search Popup 5 | 6 | https://github.com/user-attachments/assets/95702ac2-96bf-478e-8e47-0afa4916c1c2 7 | 8 | 9 | ## Glance Mode 10 | 11 | 12 | 13 | 14 | https://github.com/user-attachments/assets/827215fc-e985-4f71-8646-6e3a6b7e624b 15 | 16 | 17 | 18 | 19 | ## 🔧 Installation 20 | ## Part 1: Install fx-autoconfig 21 | 22 | 1. **Download the Files** 23 | - Go to the [fx-autoconfig GitHub page](https://github.com/MrOtherGuy/fx-autoconfig/tree/master). 24 | - Click the green `< > Code` button and download the ZIP file. 25 | 26 | 2. **Navigate to Your Zen Browser Installation Folder** 27 | - Locate your Zen Browser installation folder: 28 | - Default location on Windows: `C:\Program Files\Zen Browser`. 29 | - If unsure, open `about:support` in Zen Browser, and look for the "Application Binary" field. 30 | 31 | 3. **Extract fx-autoconfig ZIP File** 32 | - Open the extracted folder and locate the `program` folder. Inside, you’ll find: 33 | - A `defaults` folder. 34 | - A `config.js` file. 35 | 36 | 4. **Move Files to the Installation Folder** 37 | - You can **merge** or **replace** the files depending on your preferred method: 38 | - **Merge**: 39 | - **config.js**: Open the `config.js` file from the ZIP. 40 | - If a `config.js` file exists in your Zen Browser folder, copy its content from the ZIP version and paste it into your existing file, then save. 41 | - If no `config.js` file exists, copy the one from the ZIP directly to your Zen Browser folder. 42 | - **defaults folder**: Navigate to `defaults > pref > config-prefs.js` both in the ZIP and Zen Browser folder. Open both files, copy the content from the ZIP version, and paste it into the existing file in Zen Browser. If the folder or file doesn’t exist, simply copy the entire `defaults` folder into your Zen Browser folder. 43 | - **Replace**: 44 | - Drag and drop the entire `defaults` folder and `config.js` from the ZIP file into the Zen Browser installation folder. Replace any existing files when prompted. 45 | 46 | 5. **Navigate to Your Zen Profile Folder** 47 | - Open Zen Browser and go to `about:profiles`. 48 | - Locate the desired profile, find the "Root Directory," and click "Open Folder." 49 | 50 | 6. **Copy the Profile Files** 51 | - Go back to the `profile` folder in the fx-autoconfig ZIP. 52 | - Copy the `chrome` folder into the profile's root directory. 53 | 54 | 55 | ## Part 2: Install Quick Search 56 | 57 | 1. **Open the Required Folder** 58 | - From your profile root folder, navigate to `chrome > JS`. 59 | 60 | 2. **Download the Quick Search Plugin** 61 | - Go to the [Quick Search GitHub page](https://github.com/Darsh-A/Quick-Search-Zen-Browser/tree/main). 62 | - Click the green `< > Code` button and download the ZIP file. 63 | 64 | 3. **Check Configuration in Zen Browser** 65 | - Open a new tab, type `about:config`, and press Enter. 66 | - Look up `zen.urlbar.replace-newtab`. Note whether it is set to `true` or `false`. 67 | 68 | 4. **Install the Plugin** 69 | - Extract the Quick Search ZIP file. 70 | - Depending on the `zen.urlbar.replace-newtab` value: 71 | - If `false`: Copy `quickSearch_NoBar.uc.js` from the extracted ZIP to the `JS` folder. 72 | - If `true`: Copy `quickSearch.uc.js` from the extracted ZIP to the `JS` folder. 73 | 74 | 5. **Clear Startup Cache** 75 | - Open `about:support` in Zen Browser. 76 | - Click "Clear startup cache..." in the top-right corner. When prompted, restart the browser. 77 | 78 | 79 | 80 | ## ⚙️ Configuration 81 | 82 | - Default search engine is set to Google. You can change it by modifying the `defaultEngine` variable in the script config (line 125). 83 | 84 | Additional search engines present: 85 | 86 | - DuckDuckGo: `d:` 87 | - Bing: `b:` 88 | - Ecosia: `e:` 89 | - Stackoverflow: `so:` 90 | - Github: `gh:` 91 | - Wikipedia: `wiki:` 92 | 93 | 94 | - You can change the css of the popup by modifying the `injectCSS` variable in the script (line 14). 95 | 96 | 97 | - Line 420 addes parameters to the search engine URL. You can add more parameters there. 98 | 99 | 100 | ## 🔍 Usage 101 | ### For the `quickSearch.uc.js` file: 102 | - Open the url bar and type whatever you want to search for. 103 | - Press `Ctrl + Enter` to open the search popup. 104 | - Press `Ctrl + Shift + Enter` to open the search popup in a Glance Mode. 105 | 106 | ### For the `quickSearch_NoBar.uc.js` file: 107 | - Press `Ctrl+Enter` to open the search popup. 108 | - Then press `Enter` to search the query. 109 | 110 | -------------------------------------------------------------------------------- /quickSearch.uc.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // Create and inject CSS for the search container 5 | const injectCSS = () => { 6 | const css = ` 7 | @keyframes quicksearchSlideIn { 8 | 0% { 9 | transform: translateY(-100%); 10 | opacity: 0; 11 | } 12 | 60% { 13 | transform: translateY(5%); 14 | opacity: 1; 15 | } 16 | 80% { 17 | transform: translateY(-2%); 18 | } 19 | 100% { 20 | transform: translateY(0); 21 | } 22 | } 23 | 24 | @keyframes quicksearchSlideOut { 25 | 0% { 26 | transform: translateY(0); 27 | opacity: 1; 28 | } 29 | 100% { 30 | transform: translateY(-100%); 31 | opacity: 0; 32 | } 33 | } 34 | 35 | #quicksearch-container { 36 | position: fixed; 37 | top: 10px; 38 | right: 10px; 39 | width: 550px; 40 | height: 300px; 41 | background-color: #1e1f1f; 42 | border-radius: 8px; 43 | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); 44 | z-index: 9999; 45 | display: none; 46 | flex-direction: column; 47 | overflow: hidden; 48 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; 49 | opacity: 0; 50 | border: 1px solid #e0e0e0; 51 | } 52 | 53 | #quicksearch-container.visible { 54 | display: flex; 55 | opacity: 1; 56 | animation: quicksearchSlideIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; 57 | } 58 | 59 | #quicksearch-container.closing { 60 | animation: quicksearchSlideOut 0.3s ease-in forwards; 61 | } 62 | 63 | #quicksearch-browser-container { 64 | flex: 1; 65 | width: 100%; 66 | border: none; 67 | background-color: #f9f9f9; 68 | position: relative; 69 | overflow: hidden; 70 | } 71 | 72 | #quicksearch-content-frame { 73 | width: 100%; 74 | height: 100%; 75 | border: none; 76 | overflow: hidden; 77 | background-color: white; 78 | transform-origin: 0 0; 79 | transform: scale(1); 80 | } 81 | 82 | .quicksearch-close-button { 83 | position: absolute; 84 | top: 8px; 85 | right: 8px; 86 | width: 24px; 87 | height: 24px; 88 | background-color: rgba(240, 240, 240, 0.8); 89 | border: none; 90 | border-radius: 50%; 91 | font-size: 14px; 92 | display: flex; 93 | align-items: center; 94 | justify-content: center; 95 | color: #555; 96 | cursor: pointer; 97 | z-index: 10000; 98 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); 99 | transition: background-color 0.2s, transform 0.2s; 100 | } 101 | 102 | .quicksearch-close-button:hover { 103 | background-color: rgba(220, 220, 220, 0.9); 104 | transform: scale(1.1); 105 | color: #000; 106 | } 107 | `; 108 | 109 | const styleElement = document.createElement('style'); 110 | styleElement.id = 'quicksearch-styles'; 111 | styleElement.textContent = css; 112 | document.head.appendChild(styleElement); 113 | }; 114 | 115 | // Configuration 116 | const config = { 117 | searchEngines: { 118 | google: { 119 | prefix: 'g:', 120 | url: 'https://www.google.com/search?q=' 121 | }, 122 | bing: { 123 | prefix: 'b:', 124 | url: 'https://www.bing.com/search?q=' 125 | }, 126 | duckduckgo: { 127 | prefix: 'd:', 128 | url: 'https://duckduckgo.com/?q=' 129 | }, 130 | ecosia: { 131 | prefix: 'e:', 132 | url: 'https://www.ecosia.org/search?q=' 133 | }, 134 | stackoverflow: { 135 | prefix: 'so:', 136 | url: 'https://stackoverflow.com/search?q=' 137 | }, 138 | github: { 139 | prefix: 'gh:', 140 | url: 'https://github.com/search?q=' 141 | }, 142 | wikipedia: { 143 | prefix: 'wiki:', 144 | url: 'https://en.wikipedia.org/wiki/Special:Search?search=' 145 | } 146 | }, 147 | defaultEngine: 'google' 148 | }; 149 | 150 | // Function to ensure Services are available 151 | function ensureServicesAvailable() { 152 | if (typeof Services === 'undefined' && typeof Components !== 'undefined') { 153 | try { 154 | Components.utils.import("resource://gre/modules/Services.jsm"); 155 | return true; 156 | } catch (e) { 157 | return false; 158 | } 159 | } 160 | return typeof Services !== 'undefined'; 161 | } 162 | 163 | // Function to load content in browser 164 | function loadContentInBrowser(browser, searchUrl) { 165 | try { 166 | try { 167 | const uri = Services.io.newURI(searchUrl); 168 | const principal = Services.scriptSecurityManager.getSystemPrincipal(); 169 | browser.loadURI(uri, {triggeringPrincipal: principal}); 170 | } catch (e) { 171 | browser.loadURI(searchUrl); 172 | } 173 | return true; 174 | } catch (e) { 175 | try { 176 | browser.setAttribute("src", searchUrl); 177 | return true; 178 | } catch (e) { 179 | return false; 180 | } 181 | } 182 | } 183 | 184 | // Function to adjust content scaling to fit container 185 | function adjustContentScaling(element) { 186 | if (!element) return; 187 | 188 | element.addEventListener('load', function() { 189 | const scaleFactor = 0.95; 190 | element.style.transform = `scale(${scaleFactor})`; 191 | element.style.transformOrigin = '0 0'; 192 | 193 | if (element.tagName.toLowerCase() === 'iframe') { 194 | setTimeout(() => { 195 | try { 196 | if (element.contentDocument) { 197 | const style = element.contentDocument.createElement('style'); 198 | style.textContent = ` 199 | body, html { 200 | overflow: hidden !important; 201 | height: 100% !important; 202 | width: 100% !important; 203 | margin: 0 !important; 204 | padding: 0 !important; 205 | } 206 | 207 | * { 208 | scrollbar-width: none !important; 209 | } 210 | *::-webkit-scrollbar { 211 | display: none !important; 212 | width: 0 !important; 213 | height: 0 !important; 214 | } 215 | 216 | body { 217 | visibility: visible !important; 218 | opacity: 1 !important; 219 | background-color: #1e1f1f !important; 220 | display: block !important; 221 | } 222 | 223 | body > * { 224 | z-index: auto !important; 225 | position: relative !important; 226 | } 227 | `; 228 | element.contentDocument.head.appendChild(style); 229 | 230 | const mainContent = element.contentDocument.body; 231 | if (mainContent) { 232 | mainContent.style.transformOrigin = '0 0'; 233 | } 234 | } 235 | } catch (e) { 236 | // Cross-origin restrictions might prevent this 237 | } 238 | }, 500); 239 | } 240 | }); 241 | } 242 | 243 | // Wait for browser to be fully initialized 244 | function init() { 245 | injectCSS(); 246 | 247 | let urlbar = null; 248 | if (gBrowser && gBrowser.urlbar) { 249 | urlbar = gBrowser.urlbar; 250 | } else { 251 | urlbar = document.getElementById("urlbar") || document.querySelector("#urlbar"); 252 | } 253 | 254 | if (urlbar) { 255 | attachEventListeners(urlbar); 256 | } else { 257 | setTimeout(init, 1000); 258 | } 259 | } 260 | 261 | // Attach event listeners to the URL bar 262 | function attachEventListeners(urlbar) { 263 | let currentQuery = ''; 264 | 265 | // Input event to track typing 266 | urlbar.addEventListener("input", function(event) { 267 | if (event.target && typeof event.target.value === 'string') { 268 | currentQuery = event.target.value; 269 | } 270 | }, true); 271 | 272 | // Add keydown event listener for Ctrl+Enter 273 | urlbar.addEventListener("keydown", function(event) { 274 | if (event.ctrlKey && event.key === "Enter") { 275 | // Check if Shift is also pressed for Glance mode 276 | if (event.shiftKey) { 277 | event.preventDefault(); 278 | event.stopPropagation(); 279 | 280 | let query = ''; 281 | try { 282 | if (typeof currentQuery === 'string' && currentQuery.length > 0) { 283 | query = currentQuery.trim(); 284 | } 285 | } catch (error) { 286 | return; 287 | } 288 | 289 | if (query) { 290 | openInGlanceMode(query); 291 | } 292 | 293 | return false; 294 | } else { 295 | // Original Ctrl+Enter behavior 296 | event.preventDefault(); 297 | event.stopPropagation(); 298 | 299 | let query = ''; 300 | try { 301 | if (typeof currentQuery === 'string' && currentQuery.length > 0) { 302 | query = currentQuery.trim(); 303 | } 304 | } catch (error) { 305 | return; 306 | } 307 | 308 | if (query) { 309 | handleQuickSearch(query, urlbar); 310 | } 311 | 312 | return false; 313 | } 314 | } 315 | }, true); 316 | 317 | // Update the tooltip to include Glance mode information 318 | const urlbarTooltip = "Quick Search Normal: Type a query and press Ctrl+Enter\n" + 319 | "Quick Search Glance: Type a query and press Ctrl+Shift+Enter\n" + 320 | "Prefixes: g: (Google), b: (Bing), d: (DuckDuckGo), e: (Ecosia), " + 321 | "so: (Stack Overflow), gh: (GitHub), wiki: (Wikipedia)"; 322 | try { 323 | urlbar.setAttribute("tooltip", urlbarTooltip); 324 | urlbar.setAttribute("title", urlbarTooltip); 325 | } catch (error) { 326 | // Non-critical if tooltip fails 327 | } 328 | } 329 | 330 | // Function to open a URL in Zen Browser's Glance mode 331 | function openInGlanceMode(query) { 332 | let searchEngine = config.defaultEngine; 333 | let searchQuery = query; 334 | 335 | for (const [engine, engineData] of Object.entries(config.searchEngines)) { 336 | if (query.startsWith(engineData.prefix)) { 337 | searchEngine = engine; 338 | searchQuery = query.substring(engineData.prefix.length).trim(); 339 | break; 340 | } 341 | } 342 | 343 | const baseUrl = config.searchEngines[searchEngine].url; 344 | let searchUrl; 345 | 346 | if (searchEngine === 'google') { 347 | searchUrl = baseUrl + encodeURIComponent(searchQuery); 348 | } else if (searchEngine === 'stackoverflow') { 349 | searchUrl = baseUrl + encodeURIComponent(searchQuery) + '&s=relevance'; 350 | } else if (searchEngine === 'github') { 351 | searchUrl = baseUrl + encodeURIComponent(searchQuery) + '&type=repositories'; 352 | } else { 353 | searchUrl = baseUrl + encodeURIComponent(searchQuery); 354 | } 355 | 356 | try { 357 | if (window.gZenGlanceManager) { 358 | const browserRect = document.documentElement.getBoundingClientRect(); 359 | const centerX = browserRect.width / 2; 360 | const centerY = browserRect.height / 2; 361 | 362 | const data = { 363 | url: searchUrl, 364 | x: centerX, 365 | y: centerY, 366 | width: 10, 367 | height: 10 368 | }; 369 | 370 | window.gZenGlanceManager.openGlance(data); 371 | } else { 372 | gBrowser.addTab(searchUrl, { 373 | triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal() 374 | }); 375 | } 376 | } catch (error) { 377 | console.error("Error opening glance mode:", error); 378 | gBrowser.addTab(searchUrl, { 379 | triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal() 380 | }); 381 | } 382 | } 383 | 384 | // Process the search query and show in in-browser container 385 | function handleQuickSearch(query, urlbar) { 386 | let searchEngine = config.defaultEngine; 387 | let searchQuery = query; 388 | 389 | // Check if query starts with a search engine prefix 390 | for (const [engine, engineData] of Object.entries(config.searchEngines)) { 391 | if (query.startsWith(engineData.prefix)) { 392 | searchEngine = engine; 393 | searchQuery = query.substring(engineData.prefix.length).trim(); 394 | break; 395 | } 396 | } 397 | 398 | ensureServicesAvailable(); 399 | 400 | // Build the search URL - handle special cases for better compatibility 401 | let searchUrl; 402 | const baseUrl = config.searchEngines[searchEngine].url; 403 | 404 | // Some engines work better with different parameter styles 405 | if (searchEngine === 'google') { 406 | searchUrl = baseUrl + encodeURIComponent(searchQuery); 407 | } else if (searchEngine === 'stackoverflow') { 408 | searchUrl = baseUrl + encodeURIComponent(searchQuery) + '&s=relevance'; 409 | } else if (searchEngine === 'github') { 410 | searchUrl = baseUrl + encodeURIComponent(searchQuery) + '&type=repositories'; 411 | } else { 412 | searchUrl = baseUrl + encodeURIComponent(searchQuery); 413 | } 414 | 415 | try { 416 | // Get or create the container 417 | const container = createSearchContainer(); 418 | const browserContainer = document.getElementById('quicksearch-browser-container'); 419 | 420 | // Clear any previous content 421 | while (browserContainer.firstChild) { 422 | browserContainer.removeChild(browserContainer.firstChild); 423 | } 424 | 425 | // Make the container visible immediately 426 | container.classList.add('visible'); 427 | 428 | // Close the URL bar using Zen Browser's approach 429 | closeUrlBar(urlbar); 430 | 431 | // Add ESC key listener for this container 432 | addEscKeyListener(container); 433 | 434 | // Try browser element first 435 | const browserElement = createBrowserElement(); 436 | 437 | if (browserElement) { 438 | browserElement.id = 'quicksearch-content-frame'; 439 | browserElement.style.width = '100%'; 440 | browserElement.style.height = '100%'; 441 | browserElement.style.border = 'none'; 442 | browserElement.style.background = '#1e1f1f'; 443 | browserElement.style.overflow = 'hidden'; 444 | 445 | browserContainer.appendChild(browserElement); 446 | 447 | const success = loadContentInBrowser(browserElement, searchUrl); 448 | 449 | if (success) { 450 | adjustContentScaling(browserElement); 451 | return; 452 | } else { 453 | browserContainer.removeChild(browserElement); 454 | } 455 | } 456 | 457 | // Create an iframe as fallback if browser element failed 458 | const iframe = document.createElement('iframe'); 459 | iframe.id = 'quicksearch-content-frame'; 460 | iframe.style.width = '100%'; 461 | iframe.style.height = '100%'; 462 | iframe.style.border = 'none'; 463 | iframe.style.background = 'white'; 464 | iframe.style.overflow = 'hidden'; 465 | 466 | // Enhanced sandbox permissions for better rendering 467 | iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-top-navigation'); 468 | iframe.setAttribute('scrolling', 'no'); 469 | iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'; 470 | iframe.referrerPolicy = 'origin'; 471 | 472 | iframe.addEventListener('load', function() { 473 | setTimeout(() => { 474 | const containerWidth = browserContainer.clientWidth; 475 | const containerHeight = browserContainer.clientHeight; 476 | 477 | const scaleFactor = 0.95; 478 | iframe.style.width = `${Math.floor(containerWidth / scaleFactor)}px`; 479 | iframe.style.height = `${Math.floor(containerHeight / scaleFactor)}px`; 480 | }, 500); 481 | }); 482 | // First append to container, then set source 483 | browserContainer.appendChild(iframe); 484 | 485 | // Small delay before setting source 486 | setTimeout(() => { 487 | iframe.src = searchUrl; 488 | }, 100); 489 | 490 | // Apply content scaling 491 | adjustContentScaling(iframe); 492 | 493 | } catch (error) { 494 | // Last resort: open in a new tab/window 495 | try { 496 | gBrowser.addTab(searchUrl, { 497 | triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal() 498 | }); 499 | } catch (e) { 500 | window.open(searchUrl, '_blank'); 501 | } 502 | } 503 | } 504 | 505 | function closeUrlBar(urlbar) { 506 | if (!urlbar) return; 507 | 508 | try { 509 | if (window.gZenUIManager && typeof window.gZenUIManager.handleUrlbarClose === 'function') { 510 | window.gZenUIManager.handleUrlbarClose(false, false); 511 | return; 512 | } 513 | 514 | // Reset selection 515 | urlbar.selectionStart = urlbar.selectionEnd = 0; 516 | } catch (e) { 517 | } 518 | } 519 | 520 | function addEscKeyListener(container) { 521 | if (container._escKeyListener) { 522 | document.removeEventListener('keydown', container._escKeyListener); 523 | } 524 | 525 | container._escKeyListener = function(event) { 526 | if (event.key === 'Escape') { 527 | event.preventDefault(); 528 | event.stopPropagation(); 529 | closeQuickSearch(container); 530 | document.removeEventListener('keydown', container._escKeyListener); 531 | } 532 | }; 533 | 534 | document.addEventListener('keydown', container._escKeyListener); 535 | } 536 | 537 | // Function to close the quick search container 538 | function closeQuickSearch(container) { 539 | if (!container) container = document.getElementById('quicksearch-container'); 540 | if (!container) return; 541 | 542 | container.classList.add('closing'); 543 | 544 | setTimeout(() => { 545 | container.classList.remove('visible'); 546 | container.classList.remove('closing'); 547 | 548 | // Clear iframe source when closing 549 | const iframe = document.getElementById('quicksearch-content-frame'); 550 | if (iframe) { 551 | try { 552 | iframe.src = 'about:blank'; 553 | } catch (err) { 554 | } 555 | } 556 | 557 | // Remove the ESC key listener 558 | if (container._escKeyListener) { 559 | document.removeEventListener('keydown', container._escKeyListener); 560 | container._escKeyListener = null; 561 | } 562 | }, 300); 563 | } 564 | 565 | // Create and initialize the search container 566 | function createSearchContainer() { 567 | if (document.getElementById('quicksearch-container')) { 568 | return document.getElementById('quicksearch-container'); 569 | } 570 | 571 | // Create the container elements 572 | const container = document.createElement('div'); 573 | container.id = 'quicksearch-container'; 574 | 575 | // Container for the browser element 576 | const browserContainer = document.createElement('div'); 577 | browserContainer.id = 'quicksearch-browser-container'; 578 | browserContainer.style.flex = '1'; 579 | browserContainer.style.width = '100%'; 580 | browserContainer.style.position = 'relative'; 581 | browserContainer.style.overflow = 'hidden'; 582 | 583 | // Create floating close button 584 | const closeButton = document.createElement('button'); 585 | closeButton.className = 'quicksearch-close-button'; 586 | closeButton.innerHTML = '✕'; // X symbol 587 | closeButton.title = 'Close'; 588 | closeButton.onclick = (e) => { 589 | e.stopPropagation(); 590 | closeQuickSearch(container); 591 | }; 592 | 593 | // Assemble the elements 594 | container.appendChild(browserContainer); 595 | container.appendChild(closeButton); 596 | 597 | document.body.appendChild(container); 598 | 599 | return container; 600 | } 601 | 602 | function createBrowserElement() { 603 | try { 604 | const browser = document.createXULElement("browser"); 605 | 606 | browser.setAttribute("type", "content"); 607 | browser.setAttribute("remote", "true"); 608 | browser.setAttribute("maychangeremoteness", "true"); 609 | browser.setAttribute("disablehistory", "true"); 610 | browser.setAttribute("flex", "1"); 611 | browser.setAttribute("noautohide", "true"); 612 | 613 | return browser; 614 | } catch (e) { 615 | try { 616 | const browser = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser"); 617 | 618 | browser.setAttribute("type", "content"); 619 | browser.setAttribute("remote", "true"); 620 | 621 | return browser; 622 | } catch (e) { 623 | return null; 624 | } 625 | } 626 | } 627 | 628 | // Initialize after a small delay 629 | setTimeout(init, 1000); 630 | })(); 631 | -------------------------------------------------------------------------------- /quickSearch_NoBar.uc.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | const injectCSS = () => { 5 | const css = ` 6 | @keyframes quicksearchSlideIn { 7 | 0% { 8 | transform: translateY(-100%); 9 | opacity: 0; 10 | } 11 | 60% { 12 | transform: translateY(5%); 13 | opacity: 1; 14 | } 15 | 80% { 16 | transform: translateY(-2%); 17 | } 18 | 100% { 19 | transform: translateY(0); 20 | } 21 | } 22 | 23 | @keyframes quicksearchSlideOut { 24 | 0% { 25 | transform: translateY(0); 26 | opacity: 1; 27 | } 28 | 100% { 29 | transform: translateY(-100%); 30 | opacity: 0; 31 | } 32 | } 33 | 34 | @keyframes quicksearchExpand { 35 | 0% { 36 | height: 56px; 37 | } 38 | 60% { 39 | height: 370px; 40 | } 41 | 80% { 42 | height: 330px; 43 | } 44 | 100% { 45 | height: 340px; 46 | } 47 | } 48 | 49 | @keyframes quicksearchCollapseAndSlideOut { 50 | 0% { 51 | transform: translateY(0); 52 | height: 340px; 53 | opacity: 1; 54 | } 55 | 30% { 56 | height: 56px; 57 | transform: translateY(0); 58 | opacity: 0.9; 59 | } 60 | 100% { 61 | height: 56px; 62 | transform: translateY(-100%); 63 | opacity: 0; 64 | } 65 | } 66 | 67 | #quicksearch-container { 68 | position: fixed; 69 | top: 10px; 70 | right: 10px; 71 | width: 550px; 72 | height: 56px; 73 | background-color: #1e1f1f; 74 | border-radius: 8px; 75 | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); 76 | z-index: 9999; 77 | display: none; 78 | flex-direction: column; 79 | overflow: hidden; 80 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; 81 | opacity: 0; 82 | border: 1px solid #e0e0e0; 83 | transition: height 0.3s ease; 84 | } 85 | 86 | #quicksearch-container.visible { 87 | display: flex; 88 | opacity: 1; 89 | animation: quicksearchSlideIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; 90 | } 91 | 92 | #quicksearch-container.closing { 93 | animation: quicksearchSlideOut 0.3s ease-in forwards; 94 | } 95 | 96 | #quicksearch-container.expanded.closing { 97 | animation: quicksearchCollapseAndSlideOut 0.5s ease-in forwards; 98 | } 99 | 100 | #quicksearch-container.expanded { 101 | animation: quicksearchExpand 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; 102 | height: 340px; 103 | } 104 | 105 | #quicksearch-searchbar-container { 106 | display: flex; 107 | padding: 10px; 108 | background-color: #2a2a2a; 109 | border-bottom: 1px solid #444; 110 | align-items: center; 111 | min-height: 56px; 112 | box-sizing: border-box; 113 | } 114 | 115 | #quicksearch-searchbar { 116 | flex: 1; 117 | height: 36px; 118 | border-radius: 18px; 119 | border: none; 120 | padding: 0 15px; 121 | font-size: 14px; 122 | background-color: #3a3a3a; 123 | color: #f0f0f0; 124 | outline: none; 125 | transition: background-color 0.2s; 126 | } 127 | 128 | #quicksearch-searchbar:focus { 129 | background-color: #444; 130 | box-shadow: 0 0 0 2px rgba(255,255,255,0.1); 131 | } 132 | 133 | #quicksearch-browser-container { 134 | flex: 1; 135 | width: 100%; 136 | border: none; 137 | background-color: #1e1f1f; 138 | position: relative; 139 | overflow: hidden; 140 | opacity: 0; 141 | transition: opacity 0.3s ease; 142 | } 143 | 144 | #quicksearch-container.expanded #quicksearch-browser-container { 145 | opacity: 1; 146 | } 147 | 148 | #quicksearch-content-frame { 149 | width: 100%; 150 | height: 100%; 151 | border: none; 152 | overflow: hidden; 153 | background-color: #1e1f1f; 154 | transform-origin: 0 0; 155 | transform: scale(1); 156 | } 157 | 158 | .quicksearch-close-button { 159 | width: 24px; 160 | height: 24px; 161 | background-color: rgba(240, 240, 240, 0.8); 162 | border: none; 163 | border-radius: 50%; 164 | font-size: 14px; 165 | display: flex; 166 | align-items: center; 167 | justify-content: center; 168 | color: #555; 169 | cursor: pointer; 170 | margin-left: 8px; 171 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); 172 | transition: background-color 0.2s, transform 0.2s; 173 | } 174 | 175 | .quicksearch-close-button:hover { 176 | background-color: rgba(220, 220, 220, 0.9); 177 | transform: scale(1.1); 178 | color: #000; 179 | } 180 | 181 | .quicksearch-engine-indicator { 182 | display: flex; 183 | align-items: center; 184 | padding: 0 8px; 185 | font-size: 12px; 186 | color: #aaa; 187 | } 188 | `; 189 | 190 | const styleElement = document.createElement('style'); 191 | styleElement.id = 'quicksearch-styles'; 192 | styleElement.textContent = css; 193 | document.head.appendChild(styleElement); 194 | }; 195 | 196 | const config = { 197 | searchEngines: { 198 | google: { 199 | prefix: 'g:', 200 | url: 'https://www.google.com/search?q=' 201 | }, 202 | bing: { 203 | prefix: 'b:', 204 | url: 'https://www.bing.com/search?q=' 205 | }, 206 | duckduckgo: { 207 | prefix: 'd:', 208 | url: 'https://duckduckgo.com/?q=' 209 | }, 210 | ecosia: { 211 | prefix: 'e:', 212 | url: 'https://www.ecosia.org/search?q=' 213 | }, 214 | stackoverflow: { 215 | prefix: 'so:', 216 | url: 'https://stackoverflow.com/search?q=' 217 | }, 218 | github: { 219 | prefix: 'gh:', 220 | url: 'https://github.com/search?q=' 221 | }, 222 | wikipedia: { 223 | prefix: 'wiki:', 224 | url: 'https://en.wikipedia.org/wiki/Special:Search?search=' 225 | } 226 | }, 227 | defaultEngine: 'google' 228 | }; 229 | 230 | function ensureServicesAvailable() { 231 | if (typeof Services === 'undefined' && typeof Components !== 'undefined') { 232 | try { 233 | Components.utils.import("resource://gre/modules/Services.jsm"); 234 | return true; 235 | } catch (e) { 236 | return false; 237 | } 238 | } 239 | return typeof Services !== 'undefined'; 240 | } 241 | 242 | function loadContentInBrowser(browser, searchUrl) { 243 | try { 244 | try { 245 | const uri = Services.io.newURI(searchUrl); 246 | const principal = Services.scriptSecurityManager.getSystemPrincipal(); 247 | browser.loadURI(uri, {triggeringPrincipal: principal}); 248 | } catch (e) { 249 | browser.loadURI(searchUrl); 250 | } 251 | return true; 252 | } catch (e) { 253 | try { 254 | browser.setAttribute("src", searchUrl); 255 | return true; 256 | } catch (e) { 257 | return false; 258 | } 259 | } 260 | } 261 | 262 | function adjustContentScaling(element) { 263 | if (!element) return; 264 | 265 | element.addEventListener('load', function() { 266 | const scaleFactor = 0.95; 267 | element.style.transform = `scale(${scaleFactor})`; 268 | element.style.transformOrigin = '0 0'; 269 | 270 | if (element.tagName.toLowerCase() === 'iframe') { 271 | setTimeout(() => { 272 | try { 273 | if (element.contentDocument) { 274 | const style = element.contentDocument.createElement('style'); 275 | style.textContent = ` 276 | body, html { 277 | overflow: hidden !important; 278 | height: 100% !important; 279 | width: 100% !important; 280 | margin: 0 !important; 281 | padding: 0 !important; 282 | } 283 | 284 | * { 285 | scrollbar-width: none !important; 286 | } 287 | *::-webkit-scrollbar { 288 | display: none !important; 289 | width: 0 !important; 290 | height: 0 !important; 291 | } 292 | 293 | body { 294 | visibility: visible !important; 295 | opacity: 1 !important; 296 | background-color: #1e1f1f !important; 297 | display: block !important; 298 | } 299 | 300 | body > * { 301 | z-index: auto !important; 302 | position: relative !important; 303 | } 304 | `; 305 | element.contentDocument.head.appendChild(style); 306 | 307 | const mainContent = element.contentDocument.body; 308 | if (mainContent) { 309 | mainContent.style.transformOrigin = '0 0'; 310 | } 311 | } 312 | } catch (e) { 313 | // Cross-origin restrictions might prevent this 314 | } 315 | }, 500); 316 | } 317 | }); 318 | } 319 | 320 | function init() { 321 | injectCSS(); 322 | attachGlobalHotkey(); 323 | } 324 | 325 | function attachGlobalHotkey() { 326 | window.addEventListener("keydown", function(event) { 327 | if (event.ctrlKey && event.key === "Enter") { 328 | event.preventDefault(); 329 | event.stopPropagation(); 330 | 331 | showQuickSearchContainer(); 332 | 333 | return false; 334 | } 335 | }, true); 336 | } 337 | 338 | function showQuickSearchContainer() { 339 | const container = createSearchContainer(); 340 | container.classList.add('visible'); 341 | container.classList.remove('expanded'); 342 | 343 | const searchBar = document.getElementById('quicksearch-searchbar'); 344 | if (searchBar) { 345 | setTimeout(() => { 346 | searchBar.focus(); 347 | }, 100); 348 | } 349 | 350 | addEscKeyListener(container); 351 | } 352 | 353 | function handleQuickSearch(query) { 354 | let searchEngine = config.defaultEngine; 355 | let searchQuery = query; 356 | 357 | for (const [engine, engineData] of Object.entries(config.searchEngines)) { 358 | if (query.startsWith(engineData.prefix)) { 359 | searchEngine = engine; 360 | searchQuery = query.substring(engineData.prefix.length).trim(); 361 | break; 362 | } 363 | } 364 | 365 | ensureServicesAvailable(); 366 | 367 | let searchUrl; 368 | const baseUrl = config.searchEngines[searchEngine].url; 369 | 370 | if (searchEngine === 'google') { 371 | searchUrl = baseUrl + encodeURIComponent(searchQuery); 372 | } else if (searchEngine === 'stackoverflow') { 373 | searchUrl = baseUrl + encodeURIComponent(searchQuery) + '&s=relevance'; 374 | } else if (searchEngine === 'github') { 375 | searchUrl = baseUrl + encodeURIComponent(searchQuery) + '&type=repositories'; 376 | } else { 377 | searchUrl = baseUrl + encodeURIComponent(searchQuery); 378 | } 379 | 380 | try { 381 | const container = document.getElementById('quicksearch-container'); 382 | const browserContainer = document.getElementById('quicksearch-browser-container'); 383 | 384 | container.classList.add('expanded'); 385 | 386 | const engineIndicator = document.getElementById('quicksearch-engine-indicator'); 387 | if (engineIndicator) { 388 | engineIndicator.textContent = searchEngine.charAt(0).toUpperCase() + searchEngine.slice(1); 389 | } 390 | 391 | while (browserContainer.firstChild) { 392 | browserContainer.removeChild(browserContainer.firstChild); 393 | } 394 | 395 | const browserElement = createBrowserElement(); 396 | 397 | if (browserElement) { 398 | browserElement.id = 'quicksearch-content-frame'; 399 | browserElement.style.width = '100%'; 400 | browserElement.style.height = '100%'; 401 | browserElement.style.border = 'none'; 402 | browserElement.style.background = '#1e1f1f'; 403 | browserElement.style.overflow = 'hidden'; 404 | 405 | browserContainer.appendChild(browserElement); 406 | 407 | const success = loadContentInBrowser(browserElement, searchUrl); 408 | 409 | if (success) { 410 | adjustContentScaling(browserElement); 411 | return; 412 | } else { 413 | browserContainer.removeChild(browserElement); 414 | } 415 | } 416 | 417 | const iframe = document.createElement('iframe'); 418 | iframe.id = 'quicksearch-content-frame'; 419 | iframe.style.width = '100%'; 420 | iframe.style.height = '100%'; 421 | iframe.style.border = 'none'; 422 | iframe.style.background = '#1e1f1f'; 423 | iframe.style.overflow = 'hidden'; 424 | 425 | iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-top-navigation'); 426 | iframe.setAttribute('scrolling', 'no'); 427 | iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'; 428 | iframe.referrerPolicy = 'origin'; 429 | 430 | iframe.addEventListener('load', function() { 431 | setTimeout(() => { 432 | const containerWidth = browserContainer.clientWidth; 433 | const containerHeight = browserContainer.clientHeight; 434 | 435 | const scaleFactor = 0.95; 436 | iframe.style.width = `${Math.floor(containerWidth / scaleFactor)}px`; 437 | iframe.style.height = `${Math.floor(containerHeight / scaleFactor)}px`; 438 | }, 500); 439 | }); 440 | 441 | browserContainer.appendChild(iframe); 442 | 443 | setTimeout(() => { 444 | iframe.src = searchUrl; 445 | }, 100); 446 | 447 | adjustContentScaling(iframe); 448 | 449 | } catch (error) { 450 | try { 451 | gBrowser.addTab(searchUrl, { 452 | triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal() 453 | }); 454 | } catch (e) { 455 | window.open(searchUrl, '_blank'); 456 | } 457 | } 458 | } 459 | 460 | function addEscKeyListener(container) { 461 | if (container._escKeyListener) { 462 | document.removeEventListener('keydown', container._escKeyListener); 463 | } 464 | 465 | container._escKeyListener = function(event) { 466 | if (event.key === 'Escape') { 467 | event.preventDefault(); 468 | event.stopPropagation(); 469 | closeQuickSearch(container); 470 | } 471 | }; 472 | 473 | document.addEventListener('keydown', container._escKeyListener); 474 | } 475 | 476 | function closeQuickSearch(container) { 477 | if (!container) container = document.getElementById('quicksearch-container'); 478 | if (!container) return; 479 | 480 | // Add closing class but don't remove expanded yet 481 | container.classList.add('closing'); 482 | 483 | // Determine animation duration based on whether it's expanded 484 | const animationDuration = container.classList.contains('expanded') ? 500 : 300; 485 | 486 | setTimeout(() => { 487 | container.classList.remove('visible'); 488 | container.classList.remove('closing'); 489 | container.classList.remove('expanded'); 490 | 491 | const iframe = document.getElementById('quicksearch-content-frame'); 492 | if (iframe) { 493 | try { 494 | iframe.src = 'about:blank'; 495 | } catch (err) { 496 | // Ignore errors 497 | } 498 | } 499 | 500 | if (container._escKeyListener) { 501 | document.removeEventListener('keydown', container._escKeyListener); 502 | container._escKeyListener = null; 503 | } 504 | }, animationDuration); 505 | } 506 | 507 | function createSearchContainer() { 508 | if (document.getElementById('quicksearch-container')) { 509 | return document.getElementById('quicksearch-container'); 510 | } 511 | 512 | const container = document.createElement('div'); 513 | container.id = 'quicksearch-container'; 514 | 515 | const searchBarContainer = document.createElement('div'); 516 | searchBarContainer.id = 'quicksearch-searchbar-container'; 517 | 518 | const searchBar = document.createElement('input'); 519 | searchBar.id = 'quicksearch-searchbar'; 520 | searchBar.type = 'text'; 521 | searchBar.placeholder = 'Search (use prefixes: g:, b:, d:, e:, so:, gh:, wiki:)'; 522 | searchBar.autocomplete = 'off'; 523 | 524 | try { 525 | if (window.UrlbarProvider && window.UrlbarProviderQuickSuggest) { 526 | searchBar.setAttribute('data-urlbar', 'true'); 527 | } 528 | } catch (e) { 529 | } 530 | 531 | const engineIndicator = document.createElement('div'); 532 | engineIndicator.id = 'quicksearch-engine-indicator'; 533 | engineIndicator.className = 'quicksearch-engine-indicator'; 534 | engineIndicator.textContent = 'Google'; 535 | 536 | const closeButton = document.createElement('button'); 537 | closeButton.className = 'quicksearch-close-button'; 538 | closeButton.innerHTML = '✕'; 539 | closeButton.title = 'Close'; 540 | closeButton.onclick = (e) => { 541 | e.stopPropagation(); 542 | closeQuickSearch(container); 543 | }; 544 | 545 | searchBar.addEventListener('keydown', (e) => { 546 | if (e.key === 'Enter' || (e.ctrlKey && e.key === "Enter")) { 547 | e.preventDefault(); 548 | handleQuickSearch(searchBar.value); 549 | } 550 | 551 | if (e.key !== 'Enter' && e.key !== 'Escape') { 552 | setTimeout(() => { 553 | let currentEngine = config.defaultEngine; 554 | const query = searchBar.value; 555 | 556 | for (const [engine, engineData] of Object.entries(config.searchEngines)) { 557 | if (query.startsWith(engineData.prefix)) { 558 | currentEngine = engine; 559 | break; 560 | } 561 | } 562 | 563 | engineIndicator.textContent = currentEngine.charAt(0).toUpperCase() + currentEngine.slice(1); 564 | }, 10); 565 | } 566 | }); 567 | 568 | searchBarContainer.appendChild(searchBar); 569 | searchBarContainer.appendChild(engineIndicator); 570 | searchBarContainer.appendChild(closeButton); 571 | 572 | const browserContainer = document.createElement('div'); 573 | browserContainer.id = 'quicksearch-browser-container'; 574 | browserContainer.style.flex = '1'; 575 | browserContainer.style.width = '100%'; 576 | browserContainer.style.position = 'relative'; 577 | browserContainer.style.overflow = 'hidden'; 578 | 579 | container.appendChild(searchBarContainer); 580 | container.appendChild(browserContainer); 581 | 582 | document.body.appendChild(container); 583 | 584 | return container; 585 | } 586 | 587 | function createBrowserElement() { 588 | try { 589 | const browser = document.createXULElement("browser"); 590 | 591 | browser.setAttribute("type", "content"); 592 | browser.setAttribute("remote", "true"); 593 | browser.setAttribute("maychangeremoteness", "true"); 594 | browser.setAttribute("disablehistory", "true"); 595 | browser.setAttribute("flex", "1"); 596 | browser.setAttribute("noautohide", "true"); 597 | 598 | return browser; 599 | } catch (e) { 600 | try { 601 | const browser = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser"); 602 | 603 | browser.setAttribute("type", "content"); 604 | browser.setAttribute("remote", "true"); 605 | 606 | return browser; 607 | } catch (e) { 608 | return null; 609 | } 610 | } 611 | } 612 | 613 | setTimeout(init, 1000); 614 | })(); 615 | -------------------------------------------------------------------------------- /theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "quick-search-zen-browser", 3 | "name": "Quick Search", 4 | "description": "This is a quick search script for zen browser. Allows an user to quickly search a query in a small pop up container thus removing the need to swtich to a whole different tab ", 5 | "homepage": "https://github.com/Darsh-A/Quick-Search-Zen-Browser", 6 | "js": true, 7 | "readme": "https://raw.githubusercontent.com/Darsh-A/Quick-Search-Zen-Browser/refs/heads/main/README.md", 8 | "author": "Darsh A", 9 | "version": "1.0.0", 10 | "tags": [ 11 | "sine", 12 | "Quick Search", 13 | "fx-autoconfig", 14 | "JavaScript", 15 | "Darsh A" 16 | ], 17 | "createdAt": "2025-05-26", 18 | "updatedAt": "2025-05-26" 19 | } 20 | --------------------------------------------------------------------------------