Register Guidelines E-Books Today's Posts Search

Go Back   MobileRead Forums > E-Book Software > Calibre > Development

Notices

Reply
 
Thread Tools Search this Thread
Old Yesterday, 03:44 PM   #1
ChairmanSaab
Junior Member
ChairmanSaab began at the beginning.
 
Posts: 3
Karma: 10
Join Date: Aug 2025
Device: Generic
Word Lookup tool modification/improvement.

Hi,
I need help with the word lookup tool, especially when using Google dictionary, as alignment is off, reducing the column-gap to 0px greatly elevates the experience, you can enhance it a bit further by setting grid-template-columns: minmax (0px,0px). The improvement is illustrated in the screenshot. You can try this by clicking "inspect" on the Google dictionary page and going to the "computed styles" tab.

Can this be achieved via a plugin to inject javascript? Can anyone help me create one?

Click image for larger version

Name:	1.png
Views:	3
Size:	196.4 KB
ID:	217317

Last edited by BetterRed; Yesterday at 06:29 PM.
ChairmanSaab is offline   Reply With Quote
Old Yesterday, 05:04 PM   #2
ChairmanSaab
Junior Member
ChairmanSaab began at the beginning.
 
Posts: 3
Karma: 10
Join Date: Aug 2025
Device: Generic
Solution.

I'm not able to edit my original post so I'll be posting it here. Credits: ChatGPT

There are two ways, both includes editing lookup.js (located at calibre/app/resource/lookup.js or usr/share/calibre/lookup.js in linux)

Option 1. This is the one I use but might break in the future, please replace the entire code of lookup.js with this one.

Code:
/* vim:fileencoding=utf-8
 * 
 * Copyright (C) 2019 Kovid Goyal <kovid at kovidgoyal.net>
 *
 * Distributed under terms of the GPLv3 license
 */

(function() {
    "use strict";

    var num_tries = 0;

    // apply the 3px indent to any level-1 define heading
    function indentHeadings() {
        document.querySelectorAll('span[role="heading"][aria-level="1"]')
                .forEach(function(el) {
            el.style.position = 'relative';
            el.style.left     = '3px';
        });
    }

    function fix_google_markup() {
        var cc = document.getElementById('center_col');
        if (!cc) {
            if (++num_tries > 10) return;
            setTimeout(fix_google_markup, 100);
            return;
        }

        // zero-out column gaps everywhere
        var style = document.createElement('style');
        style.textContent = `
           * {
             column-gap: 0px !important;
             -webkit-column-gap: 0px !important;
           }
        `;
        document.head.appendChild(style);

        var max_width = 'calc(100vw - 25px)';
        cc.style.maxWidth   = max_width;
        cc.style.marginLeft = '0';

        var rcnt = document.getElementById('rcnt');
        if (rcnt) rcnt.style.marginLeft = '0';

        var cnt = document.getElementById('cnt');
        if (cnt) cnt.style.paddingTop = '0';

        var s = document.getElementById('search');
        if (s) s.style.maxWidth = max_width;

        var params = new URLSearchParams(location.search.slice(1));
        var q      = params.get('q');

        if (q && q.startsWith('define:')) {
            // inline layout tweaks for define: results
            cc.style.position     = 'absolute';
            cc.style.top          = '0';
            cc.style.left         = '0';
            cc.style.paddingLeft  = '0';
            cc.style.paddingRight = '6px';

            ['sfcnt','top_nav','before-appbar','appbar',
             'searchform','easter-egg','topstuff']
            .forEach(function(id) {
                var e = document.getElementById(id);
                if (e) e.style.display = 'none';
            });

            // wrap definition text
            document.querySelectorAll('[data-topic]')
                    .forEach(e => e.style.maxWidth = max_width);

            // now that the define: block is up, indent headings
            indentHeadings();

            // observe any future DOM changes in center_col and re-indent
            new MutationObserver(indentHeadings)
                .observe(cc, { childList: true, subtree: true });
        }

        // remove the promo sidebar if present
        var promo = document.getElementById('promos');
        if (promo) promo.remove();

        // wrap search results
        document.querySelectorAll('[data-ved]')
                .forEach(e => e.style.maxWidth = max_width);

        // prevent overlap of search results + citations
        document.querySelectorAll('cite').forEach(function(elem) {
            var wrapper = elem.closest('div');
            if (wrapper) wrapper.style.position = 'static';
        });
    }

    if (location.hostname === 'www.google.com') {
        window.addEventListener('DOMContentLoaded', fix_google_markup);
    }
})();
Option 2: Has a minor bug where it hides first letter of the heading, not an issue as the same word is visible below. This won't break with updates, just replace again.

Code:
        var cc = document.getElementById('center_col');
         // --- paste this code below the above line, ctrl+f in your fav text editor to find the line ---
         var style = document.createElement('style');
         style.textContent = `
           * {
             column-gap: 0px !important;
             -webkit-column-gap: 3px !important;
           }
         `;
         document.head.appendChild(style);
         // --- and the between the below line, you can leave this comment if you'd like ---
        var max_width = 'calc(100vw - 25px)';

Click image for larger version

Name:	2.jpeg
Views:	3
Size:	69.2 KB
ID:	217318

Last edited by BetterRed; Yesterday at 06:32 PM.
ChairmanSaab is offline   Reply With Quote
Old Yesterday, 06:07 PM   #3
BetterRed
null operator (he/him)
BetterRed ought to be getting tired of karma fortunes by now.BetterRed ought to be getting tired of karma fortunes by now.BetterRed ought to be getting tired of karma fortunes by now.BetterRed ought to be getting tired of karma fortunes by now.BetterRed ought to be getting tired of karma fortunes by now.BetterRed ought to be getting tired of karma fortunes by now.BetterRed ought to be getting tired of karma fortunes by now.BetterRed ought to be getting tired of karma fortunes by now.BetterRed ought to be getting tired of karma fortunes by now.BetterRed ought to be getting tired of karma fortunes by now.BetterRed ought to be getting tired of karma fortunes by now.
 
Posts: 21,767
Karma: 30237628
Join Date: Mar 2012
Location: Sydney Australia
Device: none
Moderator Notice
I moved this to the Development Forum.

I don't think the Viewer has plugin support… yet.

And I uploaded the images to here; use the paper clip icon to upload attachments

BR

Last edited by BetterRed; Yesterday at 06:34 PM.
BetterRed is online now   Reply With Quote
Old Yesterday, 09:55 PM   #4
ChairmanSaab
Junior Member
ChairmanSaab began at the beginning.
 
Posts: 3
Karma: 10
Join Date: Aug 2025
Device: Generic
Post Fixed Non-dictionary results

Update: Fixes rendering issues with non-dictionary results. Tested on 8.7.0. {Mods: is it possible to delete the above post with code? I'll be including all the screenshots in this post.}

Code:
/* vim:fileencoding=utf-8
 * 
 * Copyright (C) 2019 Kovid Goyal <kovid at kovidgoyal.net>
 *
 * Distributed under terms of the GPLv3 license
 */

(function() {
    "use strict";

    var num_tries = 0;
    var styleAdded = false; // Track if we've added our CSS styles


    function fix_google_markup() {
        var cc = document.getElementById('center_col');
        if (!cc) {
            if (++num_tries <= 10) {
                return setTimeout(fix_google_markup, 100);
            }
            return;
        }

        // figure out if they actually got a dictionary card
        var isDict = !!document.querySelector('.lr_container, .lr_dct_ent');

        // grab the raw query
        var params = new URLSearchParams(location.search.slice(1));
        var q      = params.get('q') || '';

        // 1) DICTIONARY MODE
        if (isDict) {
            // Only add styles once to prevent duplication
            if (!styleAdded) {
                var style = document.createElement('style');
                style.textContent = `
                   * {
                     column-gap: 0!important;
                     -webkit-column-gap: 0!important;
                   }
                   #center_col {
                     position: absolute !important;
                     top: 1px !important; /* Using your preferred 1px value */
                     left: 0 !important;
                     z-index: 100;
                   }
                   #cnt {
                     position: relative;
                     min-height: 100vh;
                   }
                   /* Clear the space where search form was */
                   #searchform, #appbar, #before-appbar {
                     display: none !important;
                   }
                `;
                document.head.appendChild(style);
                styleAdded = true;
            }

            var maxW = 'calc(100vw - 25px)';
            cc.style.maxWidth   = maxW;
            cc.style.marginLeft = '0';

            ['rcnt','cnt','search']
              .forEach(function(id) {
                  var e = document.getElementById(id);
                  if (e) {
                      if (id==='search') e.style.maxWidth = maxW;
                      else if (id==='cnt')  e.style.paddingTop = '0';
                      else                  e.style.marginLeft = '0';
                  }
              });

            cc.style.paddingLeft  = '0';
            cc.style.paddingRight = '6px';

            // hide everything but the dictionary
            ['sfcnt','top_nav','easter-egg','topstuff']
            .forEach(function(id){
                var e = document.getElementById(id);
                if (e) e.style.display = 'none';
            });

            // Special handling for searchform area
            ['searchform', 'appbar', 'before-appbar'].forEach(function(id) {
                var e = document.getElementById(id);
                if (e) e.style.display = 'none';
            });

            // constrain define text
            document
              .querySelectorAll('[data-topic]')
              .forEach(e => e.style.maxWidth = maxW);

            // indent headings and watch for re-renders
            indentHeadings();
            new MutationObserver(indentHeadings)
              .observe(cc, { childList:true, subtree:true });
            
            // Ensure footer stays at bottom - with null check
            var cnt = document.getElementById('cnt');
            if (cnt) cnt.style.minHeight = '100vh';
        }

        // 2) Normal MODE (define: but no dict card)
        else if (q.startsWith('define:')) {
            // SAFER: Use try-catch for Normal mode operations
            try {
                ['sfcnt','top_nav','before-appbar','appbar',
                 'searchform','easter-egg','topstuff']
                .forEach(function(id){
                    var e = document.getElementById(id);
                    if (e) e.style.display = 'none';
                });
            } catch(e) {
                console.error("Error in Normal mode cleanup:", e);
            }
        }

        // 3) UNIVERSAL CLEAN-UP (with null checks)
        try {
            // remove that promo sidebar, wrap rest nicely
            var promo = document.getElementById('promos');
            if (promo) promo.remove();

            document
              .querySelectorAll('[data-ved]')
              .forEach(e => e.style.maxWidth = '100%');

            document
              .querySelectorAll('cite')
              .forEach(c => {
                  var wrap = c.closest('div');
                  if (wrap) wrap.style.position = 'static';
              });
        } catch(e) {
            console.error("Error in universal cleanup:", e);
        }
    }

    if (location.hostname === 'www.google.com') {
        window.addEventListener('DOMContentLoaded', fix_google_markup);
        
        // Re-run on resize to handle Google's dynamic layout changes
        window.addEventListener('resize', function() {
            // Reset try counter to handle DOM changes
            num_tries = 0;
            styleAdded = false;
            fix_google_markup();
        });
    }
})();
Click image for larger version

Name:	Lookup.png
Views:	6
Size:	109.6 KB
ID:	217322Click image for larger version

Name:	normalmode.jpg
Views:	5
Size:	347.7 KB
ID:	217323
ChairmanSaab is offline   Reply With Quote
Old Yesterday, 11:28 PM   #5
kovidgoyal
creator of calibre
kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.
 
kovidgoyal's Avatar
 
Posts: 45,395
Karma: 27756918
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
https://github.com/kovidgoyal/calibr...9997fb939fa02b
kovidgoyal is online now   Reply With Quote
Reply


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Dictionary lookup word-wrap foosion Viewer 7 08-09-2021 12:07 AM
Use external browser for lookup-word in Calibre-4.1 3n4n Library Management 1 10-26-2019 07:39 AM
Can't select a particular word to highlight or lookup on NC nookleus Nook Color & Nook Tablet 4 01-06-2011 10:47 AM
Classic Noob Question on Word Lookup boxer Barnes & Noble NOOK 4 07-31-2010 09:22 AM
Lookup a word on the dictionary Adamastorx Sony Reader 1 02-19-2009 03:57 PM


All times are GMT -4. The time now is 03:39 AM.


MobileRead.com is a privately owned, operated and funded community.