Jump to content

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.util.getUrl(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("vector-sticky-header-context-bar-primary")
				// 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);
		}
		
	});
	
})();