User:Chlod/Scripts/GoToTitle.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// GoToTitle
// Author: Chlod
// Version: 1.0.1-REL

// Navigate to any page using an input box that opens when you click on the page title.
// Non-intrusive to work with other title-modifying userscripts.

(function() {
    
    var overlayId = "goto_titleOverlay";
    
    function getTitleInput(parentContainer) {
    	var titleInput = document.createElement("input");
    	titleInput.style.padding = "0";
        titleInput.style.width = "100%";
        titleInput.style.height = "100%";
        titleInput.style.border = "0";
        titleInput.style.fontSize = "inherit";
        titleInput.style.fontFamily = "inherit";
        
        titleInput.addEventListener("keydown", function(kdEvent) {
            if (Array.isArray(window.GoToTitleHooks))
                window.GoToTitleHooks.forEach(f => f(kdEvent));
            if (kdEvent.key === "Escape")
                parentContainer.parentElement.removeChild(parentContainer);
            else if (kdEvent.key === "Enter")
                window.location.href = mw.config.get("wgArticlePath")
                	.replace('$1', mw.util.wikiUrlencode(titleInput.value));
        });
        
        // Because there's no inbuilt value for plain title with namespace.
        var namespace = mw.config.get("wgFormattedNamespaces")[mw.config.get("wgNamespaceNumber")];
        titleInput.value = (namespace.length > 0 ? namespace + ":" : "") + mw.config.get("wgTitle");
        
        return titleInput;
    }
    
    document.body.addEventListener("click", function(event) {
        var currentParent = event.target;
        
        // Traverse click event and check if it hits the title heading.
        do {
        	if (currentParent == null)
        		// Whoops, we went too far!
        		return;
            if (currentParent.id === overlayId) return;
            if (
            	// Standard heading
            	currentParent.id === "firstHeading"
            	// No overlay existing
            	&& document.getElementById(overlayId) === null
        	) {
                var relativeContainer = document.createElement("div");
                var absoluteContainer = document.createElement("div");
                var titleHeight = currentParent.getBoundingClientRect().height;
                
                relativeContainer.id = overlayId;
                relativeContainer.style.position = "relative";
                relativeContainer.style.top = "-" + (+(titleHeight + 1)) + "px";
                relativeContainer.style.width = "100%";
                
                absoluteContainer.style.position = "absolute";
                absoluteContainer.style.width = "100%";
                absoluteContainer.style.height = titleHeight + "px";
                absoluteContainer.style.top = absoluteContainer.style.left = "0";
                
                relativeContainer.style.fontSize = 
                    absoluteContainer.style.fontSize = "inherit";
                relativeContainer.style.fontFamily = 
                    absoluteContainer.style.fontFamily = "inherit";
                
                var titleInput = getTitleInput(relativeContainer);
                absoluteContainer.appendChild(titleInput);
                relativeContainer.appendChild(absoluteContainer);
                currentParent.appendChild(relativeContainer);
                
        		titleInput.focus();
                
                return;
            } else if (
            	// Vector 2022 floating header
            	currentParent.classList.contains("mw-page-title-main")
            	// No overlay existing
            	&& document.getElementById(overlayId) === null
        	) {
        		var titleHeight = currentParent.getBoundingClientRect().height;
        		currentParent.style.position = "relative";
        		
        		var absoluteContainer = document.createElement("div");
                absoluteContainer.id = overlayId;
                absoluteContainer.style.position = "absolute";
                absoluteContainer.style.width = "100%";
                absoluteContainer.style.height = titleHeight + "px";
                absoluteContainer.style.top = absoluteContainer.style.left = "0";
                absoluteContainer.style.minHeight = "1.2em";
                
                var titleInput = getTitleInput(absoluteContainer);
                absoluteContainer.appendChild(titleInput);
                currentParent.appendChild(absoluteContainer);
        		
        		titleInput.focus();
        		
        		return;
        	}
        } while ((currentParent = currentParent.parentElement) !== document.body);
        
        // Did not hit event heading. Close if not found.
        var overlayElement = document.getElementById(overlayId);
        if (overlayElement != null) {
            overlayElement.parentElement.removeChild(overlayElement);
        }
        
    });
    
})();