The Code
This user script runs on Google web search result pages. It uses hardcoded knowledge of Google's markup—each search result is wrapped in a <p class="g"> element—to wrap a real <h2> tag around the title of each result. It also adds an <h1>Search Results</h1> element at the top of the page. This <h1> is hidden from sighted users, but screen readers will still "see" it in the DOM and announce it to blind users.
Save the following user script as googleheaders.user.js:
// ==UserScript==
// @name Google Headings
// @namespace http://zeus.jesus.cam.ac.uk/~jg307/mozilla/userscripts/
// @description Add real heading elements to google search results
// @include http://google.tld/search*
// @include http://www.google.tld/search*
// ==/UserScript==
// based on code by James Graham
// and included here with his gracious permission
var mainHeading = document.createElement('h1');
var headingText = document.createTextNode('Search Results');
mainHeading.appendChild(headingText);
mainHeading.style.visibility="Hidden";
mainHeading.style.height="0";
mainHeading.style.width="0";
var body = document.getElementsByTagName('body')[0];
body.insertBefore(mainHeading, body.firstChild);
var resultsParagraphs = document.evaluate("//p[@class='g']",
document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
if (resultsParagraphs.snapshotLength) {
var heading = resultsParagraphs.snapshotItem(0);
var headingSize = document.defaultView.getComputedStyle(
heading, '').getPropertyValue("font-size");
var headingWeight = document.defaultView.getComputedStyle(
heading, '').getPropertyValue("font-weight");
}
for (var i = 0; i < resultsParagraphs.snapshotLength; i++) {
var paragraphNode = resultsParagraphs.snapshotItem(i);
var linkNode = paragraphNode.getElementsByTagName('a')[0];
var heading = document.createElement('h2');
heading.appendChild(linkNode.cloneNode(true));
heading.style.fontSize = headingSize;
heading.style.fontWeight = headingWeight;
heading.style.marginBottom = 0;
heading.style.marginTop = 0;
paragraphNode.replaceChild(heading, linkNode);
try {
paragraphNode.removeChild(
paragraphNode.getElementsByTagName('br')[0]);
}
catch(error) {
}
}