Amalgam

By leskets Last update Feb 2, 2008 — Installed 662 times. Daily Installs: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2, 0

Add Syntax Highlighting (this will take a few seconds, probably freezing your browser while it works)

// Amalgam
// version 1.1.1
// 2008−02−02
// Copyright (c) 2008, Thomas Leske
// Released under the GPL license version 3 or any later
// http://www.gnu.org/copyleft/gpl.html
//
// Amalgam is meant to make using incomplete encyclopedias more attractive
// by providing fallbacks for missing articles.
//
// The header and footer contain links to other encyclopedias in priority
// order.
// After opening your prefered encyclopedia please click the link "«" next
// to the name of this encyclopedia.
// Its title says "Prefer this encyclopedia over the others that are listed".
// This will take effect after a reload.
// In order to make your choice for the second best and third best also, 
// you have to start by setting the third best then the second best
// then the best, because clicking the box makes your choice move to the
// front of the list of preferences pushing the others to the right.
//
// For any red link in an article of your prefered encyclopedia a link to
// the encyclopedia currently considered second best is appended. Articles 
// in other encyclopedias will have appended links to the best encyclopedia.
// More links will be appended, if the previous ones are not available 
// according to the latest information that Amalgam has. Move the mouse
// over the link in order to find out.
//
// Parenthesis around an appended link like in (CZ) for Citizendium means,
// that Amalgam does not know if the liked article exits (or it is 
// actually a special page with a colon in the name).
// Square brackets like [CZ] mean that Amalgam knows whether the article 
// exits. As usual a blue link means that it exists, and a red (or grey 
// when visited) link means that it does not exist. You may what to click 
// on a red link anyways, because the data Amalgam keeps may have become
// outdated as it only parses the pages you visit.
//
// The links in the head and foot lines to Citizendium may have a question 
// mark appended. This means that Amalgam does not know whether an article 
// for the same lemma exists there.
//
// Translations from Wikipedia are saved and can later be used from other
// encyclopedias to switch to an encyclopedia in a different language.
//
// If you choose:
//  "Open alternative encyclopedias: in IFrames (Disable JavaScript, Please)"
// in the menu, this will happen:
//
//   For the current lemma all better encyclopedia are automatically opened
//   in IFrames, so that you can immediately read the best available article.
//
//   lexikon.meyers.de will break out of its IFrame, if you have JavaScript
//   enabled.
//
//   For any red link in an article of your prefered encyclopedia a link to
//   the encyclopedia currently considered second best is appended. For worse 
//   encyclopedias any link is appended by links to any better encyclopedia.
//
// With IFrames disabled if you choose:
//   "In case the article is missing, open the fallback: replacing the search page"
//
//   your browser will not clutter with tabs for not found articles.
//   On the other hand you can not use the search engine of the former
//   encyclopedia any more.
//
// Improvements over 1.1:
//  - handle changes in the HTML of encyclopedia2.thefreedictionary.com 
//    for missing articles
// Improvements over 1.05:
//  - any absolute links to the supported encyclopedias will be processed on any page.
//  - minor fixes regarding New World Encyclopedia and the language of the Greasemonkey commands
// Improvements over 1.04:
//  - Fallback from Columbia Encyclopedia was broken: 
//    New message for not found articles is detected now.
// Improvements over 1.03:
//  - layout: no line breaks in links in the header and footer, smaller questionmarks
// Improvements over 1.02:
//  - Cleaned up interface
//  - Footer on Veropedia and Columbia Encyclopedia was misplaced. Now it is not added any more.
//  - Links to headers (with url suffix "#") are cropped properly for internal processing
// Improvements over 1.01:
//  - Fixed bug in code that detects links to images.
// Improvements over 1.0:
//  - columbia.thefreedictionary.com has been renamed to encyclopedia2.thefreedictionary.com
// Improvements over 0.9-beta4:
//  - fixed link titles for references to special pages
// Improvements over 0.9-beta3:
//  - Encyclopedias added.
//  - Translations are stored.
//  - 'Move to rear'-botton added.
// Improvements over 0.9-beta2:
//  - new menu item that makes Amalgam open new tabs instead of
//    using IFrames, where sites can break out. This is the default, 
//    which makes disabling JavaScript unnecessary.
//  - another menu item determines whether to open the fallback in
//    a new tab (default) or by redirecting the page.
//  - Amalgam tracks for all seen articles, whether they exit.
// Improvements over 0.9-beta1:
//  - no IFrames for urls with colons
//  - Sections in Wikiweise (e. g. '==1==') are handled
//
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//
// This is a Greasemonkey user script.
//
// To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "Hello World", and click Uninstall.
//
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
//
// ==UserScript==
// @name           Amalgam
// @namespace      tag:leskets@web.de,2007-10-23:UserScripts
// @description    Crosslinks 10 online encyclopedias (7 English, 3 German). You can send all requests to the best encyclopedia and rely on the fallback functionality. Amalgam also keeps track of the availability of articles and the translations of lemmas.
// @include        http://www.wikiweise.de/wiki/*
// @include        http://lexikon.meyers.de/meyers/*
// @include        http://de.wikipedia.org/wiki/*
// @include        http://en.wikipedia.org/wiki/*
// @include        http://en.citizendium.org/wiki/*
// @include        http://www.conservapedia.com/*
// @include        http://*.veropedia.com/a/*
// @include        http://veropedia.com/a/*
// @include        http://www.newworldencyclopedia.org/entry/*
// @include        http://www.scholarpedia.org/article/*
// @include        http://encyclopedia2.thefreedictionary.com/*
// @include        *
// ==/UserScript==
// TODO: Better support for search functions

var today = new Date();
var today_ms = today.getTime();
var URL_DB_PREFIX = "DB:";
var MS_PER_HOUR = 60 * 60 * 1000;
var MS_PER_DAY = 24 * MS_PER_HOUR;
var REPROBE_INTERVAL_DAYS = 1;
var REPROBE_INTERVAL_MS = REPROBE_INTERVAL_DAYS * MS_PER_DAY;

//var useFrames = true;
function makeMenuToggle(key, defaultValue, toggleOn, toggleOff, prefix) {
  // Load current value into variable
  window[key] = GM_getValue(key, defaultValue);
  // Add menu toggle
  GM_registerMenuCommand((prefix ? prefix+": " : "") + (window[key] ? toggleOff : toggleOn), function() {
    GM_setValue(key, !window[key]);
  });
}
var url = window.location.href;
var realHost = window.location.host;
var urlSuffix;
var local;
var urlPrefixLength;
var urlPrefix = "";
var path = '';

//var WIKIWEISE = 1;
var STRAIGHT  = 2;
var SPECIAL   = 3;

// reorder indexes: 
//  Better encyclopedias should be referenced first using their indices.
var defaultPreferencesToIndices = [0,1,2,8,6,4,9,3,5,7];
// Indices correlate:
var hostnames = ['www.wikiweise.de', 'lexikon.meyers.de', 'de.wikipedia.org', 'en.wikipedia.org', 'en.citizendium.org', 'www.conservapedia.com', 'www.veropedia.com', 'www.newworldencyclopedia.org', 'www.scholarpedia.org', 'encyclopedia2.thefreedictionary.com'];
var localPaths = ["/wiki/", "/meyers/", "/wiki/", "/wiki/", "/wiki/", "/", "/a/", "/entry/", "/article/", "/"];
var xPaths = ["//div[@id='div-maincontent-inner-default']", "//div[@id='bodyContent']", "//div[@id='bodyContent']", "//div[@id='bodyContent']", "//div[@id='bodyContent']", "//div[@id='bodyContent']", "//div[@id='articleArea']", "//div[@id='bodyContent']", "//div[@id='bodyContent']", "//div[@id='Ov']"];
var shorthand = ["WW", "MY", "WP", "WP", "CZ", "CS", "VP", "NW", "SP", "CE"];
var language  = ["de", "de", "de", "en", "en", "en", "en", "en", "en", "en"];
var encyclopediaNames = ['Wikiweise', 'Meyers', 'Wikipedia', 'Wikipedia', 'Citizendium', 'Conservapedia', 'Veropedia', 'New World Encyclopedia', 'Scholarpedia', 'Columbia Encyclopedia'];
var explicitPOV = [null, null, null, null, null, "Conservative and Christian", null, "Unification Church", null, null];
var targetEnd = [STRAIGHT, STRAIGHT, SPECIAL, SPECIAL, SPECIAL, SPECIAL, SPECIAL, SPECIAL, SPECIAL, STRAIGHT];
// end (Indices correlate)

var localNamespaces = [ "Wikipedia", "Meyers", "Wikiweise", "Wikiweise", "Bearbeitung", "Bearbeitung_Diskussion", "Meta", "Navigation", "Teilnehmer", "Diskussion", "Talk", "CZ", "Conservapedia", "New_World_Encyclopedia", "Scholarpedia"]; // "Bearbeitung" is treated specially


var hostIndex;
var hostIndexRaw = hostnames.length;
var lang = /\.de$/.test(realHost) ? "de" : "en";
var newworldencyclopediaIndex = -1;
//var articleFound = false;

var storageprefix = "preference";

if (!arraysOk()) {
    log("Some arrays are broken. Exiting.");
    return;
}

function arraysOk() {
    var length = hostnames.length;
    return ((length == defaultPreferencesToIndices.length)
	    && (length == localPaths.length)
	    && (length == xPaths.length)
	    && (length == shorthand.length)
	    && (length == language.length)
	    && (length == encyclopediaNames.length)
	    );
}

function getIndexOfXthBest(preference) {
    return GM_getValue(storageprefix + preference, defaultPreferencesToIndices[preference]);
}

checkAndLogPreferences();

// does not log from Frames
function log(message) {
    if (top.location == self.location) {
	GM_log(message);
    }
}

function checkAndLogPreferences() {
    var currentPreferences = "";
    var checklist = Array(hostnames.length);
    var passcheck = true;
    for (var i = 0; i < hostnames.length; i++) {
	var index = getIndexOfXthBest(i);
	currentPreferences += hostnames[index] + " ";
	if (checklist[index]) {
	    passcheck = false;
	} else {
	    checklist[index] = true;
	}
    }
    //log("Your preferences:" + currentPreferences);
    if (!passcheck) {
	log("Resetting broken preferences.");    
	for (var i = 0; i < hostnames.length; i++) {
	    setPreference(i, defaultPreferencesToIndices[i]);
	}
    }
}

if (/(|.+\.)veropedia\.com/.test(realHost)) {
    host = "www.veropedia.com";
} else {
    host = realHost;
}
var globalhost = host;

var isEncyclopediaSite = false;
for (var i = 0; i < hostnames.length; i++) {
    var k = getIndexOfXthBest(i);
    var hostTmp = hostnames[k];
    if (hostTmp == 'www.newworldencyclopedia.org') {
	newworldencyclopediaIndex = k;
    }
    if (hostTmp == host) {
	local = localPaths[k];
	path = xPaths[k];
	urlPrefix = "http://" + realHost + local;
	lang = language[k];
	hostIndex = k;
	hostIndexRaw = i;
	isEncyclopediaSite = true;
    }
}

if (lang == "de") {
    makeMenuToggle("useFrames", false, "in voller Größe", "in einem Rahmen (IFrame) (Bitte schalten Sie JavaScript ab!)", "Alternative Enzyklopädien öffnen");
    if (!useFrames) {
	makeMenuToggle("openNewTab", true, "die Suchseite ersetzen", "einen neuen Tab öffnen", "Falls der Artikel fehlt, beim weiteren Nachschlagen");
    }
} else {
    makeMenuToggle("useFrames", false, "full size", "in IFrames (Disable JavaScript, Please)", "Open alternative encyclopedias");
    if (!useFrames) {
	makeMenuToggle("openNewTab", true, "replacing the search page", "in a new Tab", "In case the article is missing, open the fallback");
    }
}

if (!isEncyclopediaSite) {
    var allLinks;
    allLinks = document.evaluate
	('//a[@href]',
	 document,
	 null,
	 XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
	 null);
    for (var i = 0; i < allLinks.snapshotLength; i++) {
	var thisLink = allLinks.snapshotItem(i);
	addLinksToAnExternalOne(thisLink);
    }
    return;
}

function addLinksToAnExternalOne(thisLink) {
    var href = thisLink.getAttribute("href");
    for (var j = 0; j < hostnames.length; j++) {
	var hostTmp = hostnames[j];
	var regexp = new RegExp("^http:\/\/" + hostTmp + localPaths[j] + "(.+)$");
	addLinksConditionally(regexp.exec(href), false, thisLink, hostTmp, language[j]);
    }
}

urlPrefixLength = urlPrefix.length;
var urlSuffixTmp = url.substring(urlPrefixLength);
var urlSuffixTmpArray = /[^#]#(.+)/.exec(urlSuffixTmp);
if (urlSuffixTmpArray) {
    urlSuffix = urlSuffixTmpArray[1];
} else {
    urlSuffix = urlSuffixTmp;
}


var articleFound = isArticleOnPage();

function isStillASearchURL() {
    var arrayIsStillASearch = /(Special|Spezial):(Search|Suche)\?search=([^&]*).*/.exec(urlSuffix);
    if (arrayIsStillASearch) {
	var isStillASearch = arrayIsStillASearch[3];
	if (isStillASearch) {
	    urlSuffix = isStillASearch; //TODO: unexpected side effect
	    return true;
	}
    }
}

function isArticleOnPage() {
    if (isStillASearchURL()) {
	return false;
    }
    if (host == 'www.wikiweise.de') {
	var articlesInside = document.evaluate
		("//div[@class='div-articletext']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	var articleInside = articlesInside.snapshotItem(0);
	if (articleInside) {
	    return true;
	} else {
	    return false;
	}
    } else if ((host == 'lexikon.meyers.de') || (host == 'en.citizendium.org' ) || (host == 'www.conservapedia.com')) {
	var articlesInside = document.evaluate
	    ("//div[@class='noarticletext']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	var articleInside = articlesInside.snapshotItem(0);
	if (articleInside) {
	    return false;
	} else {
	    return true;
	}	
    } else if (host == 'www.veropedia.com') {
	var textsInside = document.getElementsByTagName('B');
      	for (var i = 0; i < textsInside.length; i++) {
	    var candidate = textsInside.item(i).firstChild.nodeValue;
	    //log("candidate: " + candidate);
	    if (/^We couldn\'t find the article:/.test(candidate)) {
		return false;
	    }
	}
	var articlesInside = document.evaluate
	    ("//span[@class='bodyText']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	var bodytext = articlesInside.snapshotItem(0);
	if (bodytext) {
	    return (1 < bodytext.childNodes.length);
	} else {
	    return false;
	}
    } else if (host == 'www.scholarpedia.org') {
	var textsInside = document.getElementsByTagName('TD');
      	for (var i = 0; i < textsInside.length; i++) {
	    var candidate = textsInside.item(i).firstChild.nodeValue;
	    //log("candidate: " + candidate);
	    if (/This article does not have authors yet\. It has not been peer-reviewed or accepted for publication\./.test(candidate)) {
		return false;
	    }
	}
	return true;
    } else if (host == 'encyclopedia2.thefreedictionary.com') {
	var textsInside = document.getElementsByTagName('P');
      	for (var i = 0; i < textsInside.length; i++) {
	    var candidateTmp = textsInside.item(i).firstChild;
	    if (candidateTmp) {
		var candidate = candidateTmp.nodeValue;
		//log("candidate: " + candidate);
		if (/Word not found in the/.test(candidate)) {
		    return false;
		}
	    }
	}
	textsInside = document.getElementsByTagName('TD');
      	for (var i = 0; i < textsInside.length; i++) {
	    //log("textsInside.item(i).innerHTML:" + textsInside.item(i).innerHTML);
	    if (/is not available in the encyclopedia/.test(textsInside.item(i).innerHTML)) {
		return false;
	    }
	}
	return true;
    } else { // *.wikipedia.org
	var articlesInside = document.evaluate
	    ("//div[@id='no-articletext']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	var articleInside = articlesInside.snapshotItem(0);
	if (articleInside) {
	    return false;
	} else {
	    articlesInside = document.evaluate
		("//a[@href='wiki?title=" + urlSuffix + "&action=edit']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	    articleInside = articlesInside.snapshotItem(0);
	    if (articleInside) {
		return false;
	    } else {
		return true;
	    }
	}
    }
}

urlSuffix = decodeForHost(urlSuffix, host);
setLinkStateSticky(urlSuffix, !articleFound);


function undoSiteLocal(linkEnd) {
    var localnameCandidateArray = /^(\w*)(:|%3A)(.*)/.exec(linkEnd);
    if (localnameCandidateArray) {
	var localnameCandidate = localnameCandidateArray[1];
	for (var j = 0; j < localNamespaces.length; j++) {
	    if (localnameCandidate == localNamespaces[j]) {
		if (localnameCandidate == "Bearbeitung") {
		    return localnameCandidateArray[3];
		} else {
		    return null; // not possible
		}
	    }
	}
    }
    return linkEnd;
}

// translationAvailable must be an Array or null
function isOK(host, hostIndex, translationAvailable, lang) {
    var hostTmp = hostnames[hostIndex];
    if (hostTmp == host || hostTmp == globalhost) {
	return false;
    } else {
	if (translationAvailable) {
	    if (translationAvailable[hostIndex]) {
		return true;
	    } else {
		return false;
	    }
	} else {
	    return (lang == language[hostIndex]);
	}
    }
}

function getTextSkipping() {
    if (lang == "de") {
	return "übergangen";
    } else {
	return 'skipping';
    }
}

function getTextNewTab() {
    if (lang == "de") {
	return "autom. in neuem Tab geöffnet (Menüeinstellung)";
    } else {
	return 'auto new Tab (menu setting)';
    }
}

function getTextRedirect() {
    if (lang == "de") {
	return "autom. Weiterleitung (Menüeinstellung)";
    } else {
	return 'auto redirect (menu setting)';
    }
}

function getTextArticleNotFound() {
    if (lang == "de") {
	return "Artikel nicht gefunden";
    } else {
	return "Article not found";
    }
}

function getTextLookUp() {
    if (lang == "de") {
	return "In einer anderen Enzyklopädie nachschlagen";
    } else {
	return "Look up in another encyclopedia";
    }
}

function getTextLookUp2() {
    if (lang == "de") {
	return 'geordnet nach Präferenz';
    } else {
	return 'in priority order';
    }
}

function getTextLeaveFrame() {
    if (lang == "de") {
	return "Frame verlassen";
    } else {
	return "leave frame";
    }
    
}

function getTextIFramePrefered(isFallback) {
    var result = "";
    if (lang == "de") {
	if (isFallback) {
	    result += "<b>Rückgriff</b> auf die zweitbeste Enzyklopädie.";
	} else {
	    result += "Als besser eingestufte Enzyklopädien werden nun automatisch aufgeschlagen.";
	}
	 result += " Durch Klicken auf enthaltene Verweise öffnen Sie einen neuen Tab. Falls sich die enthaltene Seite selbst aus ihrem Frame befreit, schalten Sie, bitte, JavaScript ab!";
    } else {
	if (isFallback) {
	    result += "<b>Fallback</b> to the second best encyclopedia.";
	} else {
	    result += "Encyclopedias considered better are looked up automatically.";
	}
	result +=  " Clicking on any a link inside will open a new tab. You may want to deactivate JavaScript in order to keep the framed site from escaping.";
    }
    return '<p>' + result + '</p>';
}

function insideFrame() {
    return (top != self);
}

function getTranslationKey(sourceLang, urlSuffix, targetLang) {
    return sourceLang + "|" + targetLang + "|" + urlSuffix.toLowerCase();
}

function saveTranslation(sourceLang, urlSuffix, targetLang, translation) {
    if (translation) {
	var key = getTranslationKey(sourceLang, urlSuffix, targetLang);
	GM_setValue(key, translation);
	if (!loadTranslation(targetLang, translation, sourceLang)) {
	    var key2 = getTranslationKey(targetLang, translation, sourceLang);
	    GM_setValue(key2, urlSuffix);
	}
    }
}

function loadTranslation(sourceLang, urlSuffix, targetLang) {
    var key = getTranslationKey(sourceLang, urlSuffix, targetLang);
    return GM_getValue(key, null);
}

// uses the interwiki links of wikipedia
function getTranslation(urlSuffix, targetLang) {
    if (lang == targetLang) {
	return urlSuffix;
    } else {
	var interwikiLinks = document.evaluate
	    ("//li[@class='interwiki-" + targetLang + "']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	var interwikiLink = interwikiLinks.snapshotItem(0);
	var result = null;
	if (interwikiLink) {
	    var a = interwikiLink.firstChild;
	    if (a) {
		if (a.nodeName.toUpperCase() == "A") {
		    href = a.getAttribute("href");
		    if (href) {
			var pos = 0;
			var posSave = 0;
			while (true) {
			    pos = href.indexOf("/", pos);
			    if (pos <= 0) {
				break;
			    } else {
				posSave = pos;
				pos++;
			    }
			}
			var result = href.substring(posSave + 1);
			saveTranslation(lang, urlSuffix, targetLang, result);
			if (/\.wikipedia\.org$/.test(host)) {
			    setLinkState(targetLang + ".wikipedia.org", urlSuffix, false);
			}
			return result;
		    }
		}
	    }
	}
	return loadTranslation(lang, urlSuffix, targetLang);
    }
}

function getTextPOV() {
    return "explicit point of view"
}

var LINK_SEPARATOR = ' &ndash;&nbsp;';

function getAlternativeLinksParagraph(urlSuffix, isRepetition, linkNames, linkTargets, urlSuffixTranslation) {
    var idsuffix = isRepetition ? "2" : "";
    var links = "";
    links += '<p style="font-size: small"';
    links += ' id="collection_of_article_links' + ((isRepetition) ? "2" : "") + '" hostindex="' + hostIndex + '" linkname="' + linkNames[hostIndex] + '"'; 
    links += '>';
    if (!isRepetition && !articleFound && !containsColon(urlSuffix)) {
	var titlesInside = document.evaluate
	    ("//title", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	var titleInside = titlesInside.snapshotItem(0);
	//FIXME: no effect!
	titleInside.firstChild.nodeValue = getTextNotFound() + " " + titleInside.firstChild.nodeValue;
    }

    var isIndexFirstAfterHostIndex = true;
    var isFirstItem = true;    
    var currentpageFirst = false;
    for (var i = 0; i < hostnames.length; i++) {
	var k = getIndexOfXthBest(i);
	if (isOK(globalhost, k, urlSuffixTranslation, lang)) {
	    if (!isFirstItem) {
		links += LINK_SEPARATOR;
	    }
	    var tmpLinkContainer = document.createElement('div');
	    tmpLinkContainer.innerHTML = '<a href="' + linkTargets[k] + '" hostindex="' + k + '">' + toNonbreaking(linkNames[k]) + '</a>';
	    var tmpLink = tmpLinkContainer.firstChild;
	    var redinfo = isLinkRed(hostnames[k], urlSuffixTranslation[k]); //TODO: encode?
	    setRed(tmpLink, (!(!redinfo.defined || !redinfo.red)));
	    //tmpLink.firstChild.nodeValue = tmpLink.firstChild.nodeValue + ((!redinfo.defined && !containsColon(urlSuffixTranslation[k])) ? "?" : "");
	    if (!redinfo.defined && !containsColon(urlSuffixTranslation[k])) {
		var questionmark = document.createElement('span');
		questionmark.style.fontSize = ".8em";
		questionmark.style.color = "black";
// 		var sub = document.createElement('sub');
// 		sub.appendChild(document.createTextNode("?"));
		var sub = document.createTextNode("?");
		questionmark.appendChild(sub);
		tmpLink.appendChild(questionmark);
	    }
	    insertRedInfo(tmpLink, linkNames[k], redinfo);
	    links += tmpLinkContainer.innerHTML;
	    if ((hostIndexRaw < i) && isIndexFirstAfterHostIndex) {
		if (!articleFound && !containsColon(urlSuffix)) {
		    if (!useFrames) {
			links += '(->';
			if (redinfo.defined && redinfo.red && (today_ms - redinfo.timestamp_ms < REPROBE_INTERVAL_MS)) {
			    links += getTextSkipping();
			} else {
			    if (openNewTab || (k == newworldencyclopediaIndex)) {
				links += getTextNewTab();
			    } else {
				links += getTextRedirect();
			    }
			    if (!isRepetition) {
				if (openNewTab || (k == newworldencyclopediaIndex)) {
				    GM_openInTab(linkTargets[k]);
				} else {
				    location.href = linkTargets[k];
				}
			    }
			    if (k != newworldencyclopediaIndex) isIndexFirstAfterHostIndex = false;
			}
			links += ')';
		    } else {
			if (k != newworldencyclopediaIndex) isIndexFirstAfterHostIndex = false;
		    }
		} else {
		    if (k != newworldencyclopediaIndex) isIndexFirstAfterHostIndex = false;
		}
	    }
	    isFirstItem = false;
	} else if (k == hostIndex) {
	    if (isFirstItem) {
		currentpageFirst = true;
	    } else {
		links += ' - ';
	    }
	    links += '<a name="MoveToFront" id="MTF_button' + idsuffix + '" title="' + getTextMTFButton() + '">&laquo;</a>&nbsp;<b>' + toNonbreaking(linkNames[k]) + '</b>&nbsp;<a name="MoveToRear" id="MTR_button' + idsuffix + '" title="' + getTextMTRButton() + '">&raquo;</a> ';
	    isFirstItem = false;
	}
    }
    links += '</p>';
    var linksElement = document.createElement('div');
    linksElement.innerHTML = links;
    var resultElement = document.createElement('div');
    resultElement.appendChild(linksElement);
    return resultElement;
}

function getAlternativeLinks(urlSuffix, isRepetition) {
    //log("getAlternativeLinks() urlSuffix:" + urlSuffix);
    var urlSuffixTranslation = Array(hostnames.length);
    // indices correlate:
    var linkNames = Array(hostnames.length);
    for (var i = 0; i < hostnames.length; i++) {
	urlSuffixTranslation[i] = getTranslation(urlSuffix, language[i]);
	linkNames[i] = encyclopediaNames[i];
	if (lang != language[i]) {
	    linkNames[i] += " (" + language[i] + ")";
	}
    }

    var linkTargets = Array(hostnames.length);
    for (var i = 0; i < hostnames.length; i++) {
	var thisTargetEnd = targetEnd[i];
	var linkTargetEnd = "";
	//log("getAlternativeLinks() urlSuffixTranslation[i], hostnames[i]:" + urlSuffixTranslation[i]+ " "+ hostnames[i]);
	if (urlSuffixTranslation[i]) {
	    var urlSuffixTranslationTmp = encodeForHost(urlSuffixTranslation[i], hostnames[i]);
	    if (thisTargetEnd == STRAIGHT) {
		linkTargetEnd = decodeURIComponent(urlSuffixTranslationTmp);
	    } else if (thisTargetEnd == SPECIAL) { //TODO: use encodeURIComponent?
		linkTargetEnd = 'Spezial:Suche?search=' + urlSuffixTranslationTmp + '&go=Go';
	    } else {
		log("unknown targetEnd:" + thisTargetEnd);
	    }
	    linkTargets[i] = "http://" + hostnames[i] + localPaths[i] + linkTargetEnd;
	}
    }
    var links = '';
    if (isRepetition && host != 'www.wikiweise.de') {
	links += '<hr />';
    }    
    if (explicitPOV[hostIndex]) {
	links += '<p>' + getTextPOV() + ": " + '<i>' + explicitPOV[hostIndex]+ '</i>' + '</p>';
    }    
    if (!articleFound && !containsColon(urlSuffix)) {
	links += '<p>' + '<b>' + getTextArticleNotFound() + '</b>' + '</p>';
    }
    if (hostIndex == newworldencyclopediaIndex) {
	links += '<p>' + getTextLimitedSupport() + '</p>';
    }
    var newElement = document.createElement('div');
    var newLink;
    if (insideFrame()) { // avoid recursive embedding of iframes
	newElement.innerHTML = '<a href="' + url + '">' + getTextLeaveFrame() + '</a>';
	newLink = newElement.firstChild;
	newLink.addEventListener('click', leaveFrame, true);
    } else {
	newElement.innerHTML = links;
	newElement.appendChild(getAlternativeLinksParagraph(urlSuffix, isRepetition, linkNames, linkTargets, urlSuffixTranslation));
	newElement.appendChild(getIframesConditionally(urlSuffix, isRepetition, linkNames, linkTargets));
    }
    if (!isRepetition && host != 'www.wikiweise.de') {
	var newElement2 = document.createElement('div');
	newElement2.innerHTML = '<hr />';
	newElement.appendChild(newElement2.firstChild);
    }    
    return newElement;
}

function getIframesConditionally(urlSuffix, isRepetition, linkNames, linkTargets) {
    var links = "<p>";
    if (!isRepetition && !containsColon(urlSuffix) && useFrames) {
	var isFirst = true;
	var isIframeWritten = false;
	for (var i = 0; i < hostIndexRaw; i++) { // only look up in better (->preferences) encyclopedias
	    var k = getIndexOfXthBest(i);
	    if (isOK(globalhost, k, urlSuffixTranslation, lang)) {
		if (isFirst) {
		    links += getTextIFramePrefered(false);
		    isFirst = false;
		}
		links += getIFrame(k, linkNames, linkTargets);
		isIframeWritten = true;
	    }
	}
	if (!articleFound && !isIframeWritten) { // Search in second best encyclopedia
	    for (var i = hostIndexRaw + 1; i < hostnames.length; i++) { // Find second best encyclopedia
		var k = getIndexOfXthBest(i);
		if (isOK(globalhost, k, urlSuffixTranslation, lang)) {
		    links += getTextIFramePrefered(true);
		    links += getIFrame(k, linkNames, linkTargets);
		    break;
		}
	    }
	}
    }    
    links += '</p>';
    var resultElement = document.createElement('div');
    resultElement.innerHTML = links;
    return resultElement;
}

function getTextLimitedSupport() {
    if (lang == "de") {
	return "Diese Seite wird nur eingeschränkt unterstützt.";
    } else {
	return "Support for this site is limited.";
    }
}

function moveTo(event, isFront) {
    var MTid = (isFront) ? "MTF_button" : "MTR_button";
    var bottonElement = document.getElementById(MTid);

    checkAndLogPreferences();
    var pElement = document.getElementById("collection_of_article_links");
    var myHostIndex = parseInt(pElement.getAttribute('hostindex'));
    //log("myHostIndex: " + myHostIndex);
    var aInside = document.evaluate
	("//p[@id='collection_of_article_links']//a[@hostindex]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
    var reversePreferences = getReversePreferences(aInside);

    var lastIndex = myHostIndex;
    var savedPreference = getPreference(myHostIndex);
    if (isFront) {
	for (var preference = 0; preference < savedPreference; preference++) {
	    var index = reversePreferences[preference];
	    if (index != -1) {
		setPreference(lastIndex, preference);
		lastIndex = index;
	    }
	}
    } else {
	for (var preference = hostnames.length - 1; savedPreference < preference; preference--) {
	    var index = reversePreferences[preference];
	    if (index != -1) {
		setPreference(lastIndex, preference);
		lastIndex = index;
	    }
	}
    }
    setPreference(lastIndex, savedPreference);
    checkAndLogPreferences();
    //TODO broken:
    //     showUpdatedPreferences("collection_of_article_links");
    //     showUpdatedPreferences("collection_of_article_links2");
}


function moveToRear(event) {
    moveTo(event, false);    
}

function moveToFront(event) {
    moveTo(event, true);
}

//determine the current preference of every index
function getReversePreferences(aInside) {
    var reversePreferences = Array(hostnames.length);
    for (var i = 0; i < hostnames.length; i++) {
	reversePreferences[i] = -1;
    }
    for (var i = 0; i < aInside.snapshotLength; i++) {
	var thisHostIndex = parseInt(aInside.snapshotItem(i).getAttribute('hostindex'));
	reversePreferences[getPreference(thisHostIndex)] = thisHostIndex;
	log("preference, host: " + getPreference(thisHostIndex) + " " + hostnames[thisHostIndex]);
    }
    return reversePreferences;
}

function showUpdatedPreferences(pElementId) {
    var pElement = document.getElementById(pElementId);
    var myHostIndex = parseInt(pElement.getAttribute('hostindex'));
    var myName = parseInt(pElement.getAttribute('linkname'));
    var aInside = document.evaluate
	("//p[@id='" + pElementId + "']//a[@hostindex]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
    var collectedLinks = Array(hostnames.length);
    for (var i = 0; i < aInside.snapshotLength; i++) {
	var link = aInside.snapshotItem(i);
	var thisHostIndex = parseInt(link.getAttribute('hostindex'));
	collectedLinks[collectedLinks] = link.cloneNode(true);
    }
    aInside = document.evaluate
	("//p[@id='" + pElementId + "']//a[@hostindex]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
    var reversePreferences = getReversePreferences(aInside);
//     while (pElement.hasChildNodes()) {
//    	pElement.removeChild(pElement.firstChild);
//     }
    var isFirst = true;
    var myPreference = getPreference(myHostIndex);
    for (var preference = 0; preference < hostnames.length; preference++) {
	var index;
	if (myPreference == preference) {
	    index = myHostIndex;
	} else {
	    index = reversePreferences[preference];
	}
	if (index != -1) {
	    if (!isFirst) {
		pElement.appendChild(document.createTextNode(LINK_SEPARATOR));
	    }
	    if (myPreference == preference) {
		var tmpTextContainer = document.createElement('div');
		tmpTextContainer.innerHTML = '<b>' + myName + '</b> ';
		pElement.appendChild(document.createTextNode(tmpTextContainer.firstChild));
	    } else {
		pElement.appendChild(collectedLinks[i]);
	    }
	    isFirst = false;
	}
    }
}

function setPreference(index, preference) {
    log("setPreference: " + hostnames[index] + " " + preference);
    GM_setValue(storageprefix + preference, index);
}

function getPreference(index) {
    for (var i = 0; i < hostnames.length; i++) {
	if (index == getIndexOfXthBest(i)) {
	    return i;
	}
    }
    log("Error: ReversePreference not found");
}

function getTextMTFButton() {
    if (lang == "de") {
	return "Diese Enzyklopädie den übrigen Aufgelisteten vorziehen";
    } else {
	return "Prefer this encyclopedia over the others that are listed";
    }
}

function getTextMTRButton() {
    if (lang == "de") {
	return "Die übrigen aufgelisteten Enzyklopädien dieser vorziehen";
    } else {
	return "Prefer all other encyclopedias that are listed over this one";
    }
}

function getTextIFramesUnsupported() {
    if (lang == "de") {
	return "Ihr Browser kann leider keine eingebetteten Frames anzeigen: Sie k&ouml;nnen die eingebettete Seite &uuml;ber den folgenden Verweis aufrufen: ";
    } else {
	return "Your Browser does not support IFrames: You can access the embedded page with the following link: "; 
    }
}

function getIFrame(hostIndex, linkNames, linkTargets) {
    var result = "";
    result += '<p><b>' + linkNames[hostIndex] + ':</b> ' + linkTargets[hostIndex] + '</p>';
    result += '<iframe src="' + linkTargets[hostIndex] + '" width="100%" height="200" name="' + linkNames[hostIndex] + '">';
    result += '  <p>' + getTextIFramesUnsupported() + '<a href="' + linkTargets[hostIndex] + '">' + linkNames[hostIndex] + '</a></p>';
    result += '</iframe>';
    return result;
}

function leaveFrame(event) {
    top.location = self.location;
    event.stopPropagation();
    event.preventDefault();
}

function insertLinks(articletext, urlSuffix) {
    for (var i=0; i <= 1; i++) {
	var isRepetition = (1 == i);
	var idsuffix = isRepetition ? "2" : "";
	var newElement = getAlternativeLinks(nonLocalUrlSuffix, isRepetition);
	if (i == 0) {
	    articletext.insertBefore(newElement, articletext.firstChild);
	} else {
	    //articletext.insertBefore(newElement, null);
	    articletext.appendChild(newElement);
	}
	document.getElementById('MTF_button' + idsuffix).addEventListener('click', moveToFront, true);
	document.getElementById('MTR_button' + idsuffix).addEventListener('click', moveToRear, true);
	if (host == 'www.veropedia.com' || host == 'encyclopedia2.thefreedictionary.com') {
	    break; // footer would not be placed properly
	}
    }
}

function refersToImage(thisLink) {
    if ("image" == thisLink.getAttribute("class")) {
	return true;
    } else {
	style = thisLink.getAttribute("style");
	if (style) {
	    if (0 <= style.indexOf("image")) {
		return true;
	    }
	}
	if (thisLink.firstChild) {
	    return ("IMG" == thisLink.firstChild.nodeName.toUpperCase());
	} else {
	    return false;
	}
    }
}

function setRed(thisLink, red) {
    if (red) {
	if (host == "www.wikiweise.de") {
	    thisLink.setAttribute("class", "inexistingArticle");//thisLink.removeAttribute("class");
	} else if (host == "encyclopedia2.thefreedictionary.com") {
	    thisLink.style.color = "#a00000";
	} else { // works for "*.wikipedia.org" and "en.citizendium.org"
	    thisLink.setAttribute("class", "new");
	}
    } else {
	if (host == "www.wikiweise.de") {
	    thisLink.setAttribute("class", "existingArticle");
	} else if (host == "encyclopedia2.thefreedictionary.com") {
	    thisLink.style.color = "#000080";
	} else { // works for "*.wikipedia.org" and "en.citizendium.org"
	    thisLink.removeAttribute("class");
	}
    }
}

// spaces to underscores, remove reference to section
function decodeWikiweise(linkEnd) {
    return linkEnd.replace(/(%20|\ )/g, "_").replace(/==[0-9]+==$/, "");
}

// spaces to underscores
function decodeVeropedia(linkEnd) {
    return linkEnd.replace(/(%20|\ )/g, "_");
}

// pluses to underscores
function decodeColumbia(linkEnd) {
    return linkEnd.replace(/(\+)/g, "_").toLowerCase();
}

function toNonbreaking(myString) {
    return myString.replace(/\ /g, "&nbsp;");
}

function underscoresTo(linkEnd, replacement) {
    var result = "";
    var pos = 0;
    var oldpos;
    var tail = linkEnd;
    while (pos < linkEnd.length) {
	oldpos = pos;
	pos = linkEnd.indexOf("_", pos);
	if (pos < 0) {
	    break;
	} else {
	    result += linkEnd.substring(oldpos, pos);
	    result += replacement;
	    pos++;
	    tail = linkEnd.substring(pos);
	}
    }
    result += tail;
    return result;
    // has issues with an illegal character:
    //  return linkEnd.replace(new RegExp("\\_", "g"), replacement); // linkEnd.replace(/\_/g, replacement)
}

// underscores to pluses
function encodeColumbia(linkEnd) {
    //log("encodeColumbia" + linkEnd);
    return underscoresTo(linkEnd, "+");
}

// underscores to spaces
function encodeWikiweise(linkEnd) {
    //log("encodeWikiweise" + linkEnd);
    return underscoresTo(linkEnd, "%20");
}

function encodeForHost(linkEnd, hostname) {
    if (hostname == "www.wikiweise.de") {
	return encodeWikiweise(linkEnd);
    } else if (hostname == "encyclopedia2.thefreedictionary.com") {
	return encodeColumbia(linkEnd);
    } else {
	return linkEnd;
    }
}

function decodeForHost(linkEnd, hostname) {
    if (hostname == 'www.wikiweise.de') {
	return decodeWikiweise(linkEnd);
    } else if (hostname == 'www.veropedia.com') {
	return decodeVeropedia(linkEnd);
    } else if (hostname == 'encyclopedia2.thefreedictionary.com') {
	return decodeColumbia(linkEnd);
    } else {
	return linkEnd;
    }
}

function addLink(thisLink, hostIndex, linkEnd, redinfo) {
    var newElement = thisLink.cloneNode(true);
    thisLink.parentNode.insertBefore(newElement, thisLink);
    //log("addLink()");
    var myLinkEnd = encodeForHost(linkEnd, hostnames[hostIndex]);
    thisLink.href = "http://" + hostnames[hostIndex] + localPaths[hostIndex] + myLinkEnd;
    while (thisLink.firstChild) {
	thisLink.removeChild(thisLink.firstChild);
    }
    var textNodeContent = "";
    textNodeContent += redinfo.defined 
	? "[" 
	: "(";
    textNodeContent += shorthand[hostIndex];
    textNodeContent += redinfo.defined 
	? "]" 
	: ")";
//     var sub = document.createElement('sub');
//     sub.appendChild(document.createTextNode(textNodeContent));
    var sub = document.createTextNode(textNodeContent);
    thisLink.appendChild(sub);
    thisLink.style.fontSize = ".8em";
    thisLink.style.fontStyle = "normal";
    insertRedInfo(thisLink, encyclopediaNames[hostIndex], redinfo);
    setRed(thisLink, (redinfo.defined && redinfo.red));
}

function getTextMissing() {
    if (lang == "de") {
	return "fehlt";
    } else {
	return "missing";
    }
}

function getTextAvailable() {
    if (lang == "de") {
	return "vorhanden";
    } else {
	return "available";
    }
}

function getTextDays() {
    if (lang == "de") {
	return "Tage";
    } else {
	return "days";
    }
}

function getTextHours() {
    if (lang == "de") {
	return "Stunden";
    } else {
	return "hours";
    }
}

function getTextUnknown() {
    if (lang == "de") {
	return "unbekannt";
    } else {
	return "unknown";
    }
}

function getTextSpecialPage() {
    if (lang == "de") {
	return "Spezialseite";
    } else {
	return "special page";
    }
}

function insertRedInfo(link, name, redinfo) {
    var state ="";
    if (redinfo.defined) {
	if (redinfo.red) {
	    state += getTextMissing();
	} else {
	    state += getTextAvailable();
	}
	state += " ";
	state += "(";
	var age_ms = (today_ms - redinfo.timestamp_ms);
	var age_days = Math.floor(age_ms / MS_PER_DAY);
	if (0 < age_days) {
	    state += age_days + " " + getTextDays() + " ";
	}
	var age_hours = Math.floor((age_ms - age_days * MS_PER_DAY) / MS_PER_HOUR);
	state += age_hours + " " + getTextHours();
	state += ")";
    } else {
	if (redinfo.isSpecial) {
	    state = getTextSpecialPage();
	} else {
	    state = getTextUnknown();
	}
    }
    link.setAttribute('title', name + ": " + state);
}

function getKey(host, linkEnd) {
    return URL_DB_PREFIX + host + "|" + linkEnd;
}

// Do not change this setting again during the remaining Processing
// of the page via setLinkState().
// Call only once!
function setLinkStateSticky(linkEnd, isRed) {
    //log ("setLinkStateSticky:" + host + ", " + linkEnd + ", " + isRed);
    var myLinkEnd = linkEnd.toLowerCase();
    setLinkStateUnsave(host, myLinkEnd, isRed);
    stickyHost = host;
    stickyLinkEnd = myLinkEnd;
}

function containsColon(linkEnd) {
    return /^(\w*)(:|%3A)(.*)/.test(linkEnd);
}

var stickyHost;
var stickyLinkEnd;

function setLinkStateUnsave(host, linkEnd, isRed) {
    var myLinkEnd = linkEnd.toLowerCase();
    if (stickyHost && stickyLinkEnd) {
	if ((stickyHost == host) && (stickyLinkEnd == myLinkEnd)) {
	    return; //ignore
	}
    }
    if (containsColon(myLinkEnd)) {
	return; //ignore
    }
    var key = getKey(host, myLinkEnd);
    //log ("setLinkState:" + key + ", " + isRed);
    GM_setValue(key, (isRed ? "true" : "false") + "|" + today_ms);
}

function setLinkState(host, linkEnd, isRed) {
    if (host != globalhost) {
	if (isRed) {
	    log("setLinkState() for lemma " + linkEnd + " on foreign host " + host + ((isRed) ? "blocked" : ""));
	    return; // setting would be insecure
	}
    }
    var myLinkEnd = linkEnd.toLowerCase();
    if (host == 'www.newworldencyclopedia.org') {
	return;  // links to nonexistent articles can not be distinguished on this site.
    }
    setLinkStateUnsave(host, myLinkEnd, isRed)
}

function isLinkRed(host, linkEnd) {
    var myLinkEnd = linkEnd.toLowerCase();
    var key = getKey(host, myLinkEnd)
    var value = GM_getValue(key, null);
    if (value) {
	var valueArray = /(true|false)\|([0-9]+)/.exec(value);
	var isRed = (valueArray[1] == "true");
	//log ("isLinkRed for " + host + "|" + myLinkEnd + ": " + isRed);
	return {defined: true, red: isRed, timestamp_ms: parseInt(valueArray[2])};
    } else {
	//log ("isLinkRed for " + host + "|" + myLinkEnd + ": undefined");
	if (containsColon(linkEnd)) {
	    return {defined: false, isSpecial: true};
	} else {
	    return {defined: false, isSpecial: false};
	}
    }
}

function addLinks(host, thisLink, linkEnd, lang) {
    var linksAdded = false;
    var myLinkRed = isLinkRed(host, linkEnd);
    var isRed = (myLinkRed) 
	? myLinkRed.red 
	: true; // link probably contains column
    for (var i = 0; i < hostnames.length; i++) {
	var k = getIndexOfXthBest(i);
	var myLinkEnd = (hostnames[k] == "encyclopedia2.thefreedictionary.com")
	    ? linkEnd.toLowerCase()
	    : linkEnd;
	var redinfo = isLinkRed(hostnames[k], myLinkEnd);
	if (isOK(host, k, null, lang)) {
	    if (useFrames) {
		if (i > hostIndexRaw) {
		    if (isRed && !linksAdded) {
			addLink(thisLink, k, myLinkEnd, redinfo);
		    }
		    if (k != newworldencyclopediaIndex) {
			break;
		    }
		} else {
		    addLink(thisLink, k, myLinkEnd, redinfo);
		    linksAdded = true;
		}
	    } else {
		if (isRed || (i < hostIndexRaw)) {
		    addLink(thisLink, k, myLinkEnd, redinfo);
		    if (!redinfo.defined || !redinfo.red) {
			if (k != newworldencyclopediaIndex) {
			    break; // because of the automatic fallback, one working link is sufficient.
			}
		    }
		}
	    }
	}
    }
}

function addLinksConditionally(linkEndArray, isRed, thisLink, host, lang) {
    if (linkEndArray) {
	var linkEnd = linkEndArray[1];
	if (!refersToImage(thisLink)) {
	    var nonLocalLinkEnd = undoSiteLocal(decodeForHost(linkEnd, host));
	    if (nonLocalLinkEnd) {
		setLinkState(host, nonLocalLinkEnd, isRed);
		if (globalhost == 'www.veropedia.com' && host == "en.wikipedia.org" && !isRed) {
		    setLinkState(globalhost, nonLocalLinkEnd, true);
		}
		addLinks(host, thisLink, nonLocalLinkEnd, lang);
	    }
	}
    }
}

function insertLinksAt(path, nonLocalUrlSuffix) {
    var articleTexts = document.evaluate
	(path, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
    var articleText = articleTexts.snapshotItem(0);
    if (articleText) {
	insertLinks(articleText, nonLocalUrlSuffix);
    }
    return articleText;
}

var allLinks;
allLinks = document.evaluate
    ('//a[@href]',
     document,
     null,
     XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
     null);

// Add links to other encyclopedias:
var links;
if (path != '') {
    var nonLocalUrlSuffix = undoSiteLocal(urlSuffix);
    if (nonLocalUrlSuffix) {
	if (!insertLinksAt(path, nonLocalUrlSuffix)) {
	    if (host == 'encyclopedia2.thefreedictionary.com') {
	       if (!insertLinksAt("//div[@id='MainTxt']", nonLocalUrlSuffix)) {
		  insertLinksAt("//td[@id='MainTitle']", nonLocalUrlSuffix);
	       }
	    }
	}
    }
}

var regexp = new RegExp("^" + local + "(.+)");
for (var i = 0; i < allLinks.snapshotLength; i++) {
    var thisLink = allLinks.snapshotItem(i);
    if (insideFrame()) { // leave the frame by opening links in a new tab
	thisLink.setAttribute("target", "_blank");
    }
    var href = thisLink.getAttribute("href"); // relative path
    addLinksToAnExternalOne(thisLink);
    if (host == 'www.conservapedia.com') {
	if (/^\/index.php\?/.test(href)) {
	    addLinksConditionally(/^\/index.php\?title=([^&]*)&action=edit/.exec(href), true, thisLink, host, lang);
	} else {
	    addLinksConditionally(regexp.exec(href), false, thisLink, host, lang);
	}
    } else if (host == 'www.veropedia.com') {
	addLinksConditionally(new RegExp("^\.\." + local + "(.+)").exec(href), false, thisLink, host, lang);
    } else if (host == 'encyclopedia2.thefreedictionary.com') {
	addLinksConditionally(new RegExp("^([^:/]*)$").exec(href), false, thisLink, host, lang);
    } else {
	// log("href:" + href);
	addLinksConditionally(regexp.exec(href), false, thisLink, host, lang);
	// check for red links:
	if (host == "www.wikiweise.de") {
	    //  e. g. http://www.wikiweise.de/Frontcontroller?command=editArticle&article=Nachschlagewerk
	    addLinksConditionally(/^\/Frontcontroller\?command=editArticle&article=([^&]*)/.exec(href), true, thisLink, host, lang);
	} else if (host == "en.citizendium.org") { 
	    //  e. g. http://en.citizendium.org/wiki?title=Reference&action=edit
	    addLinksConditionally(/^\/wiki\?title=([^&]*)&action=edit/.exec(href), true, thisLink, host, lang);
	} else {
	    //  e. g. http://de.wikipedia.org/w/index.php?title=Nullarbor-Nationalpark&action=edit
	    addLinksConditionally(/^\/w\/index.php\?title=([^&]*)&action=edit/.exec(href), true, thisLink, host, lang);
	}	
    }
}

function getTextNotFound() {
    if (lang == "de") {
	return "Nicht gefunden:"
    } else {
	return "Not found:"
    }
}