Участник:Ariely/Bilingual.js

// ==UserScript==
// @name          Wikipedia Dual Language
// @description   Wikipedia displays a topic in dual languages side-by-side
// @include       http://*.wikipedia.org/*
// ==/UserScript==

// GUID for when installed as an extension:
//
//          {22A35D22-D784-11DA-84A6-F804D88083B6}

// Author: Jason Harrop
//         jharrop@gmail.com
//
// http://wikipediabilingual.mozdev.org/
//
// v0.1    2007 01 26 
const WB_version="v0.1   2007 01 26";

// Checks before publishing:
// 1. LOG_LEVEL=1; 

/*

    Copyright (C) 2006  Jason Harrop, jharrop@gmail.com
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of version 2 of the GNU General Public License
    as published by the Free Software Foundation.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details, available at
    http://www.gnu.org/copyleft/gpl.html

*/

/* 
    Compile this with Anthony Lieuallen's Greasemonkey compiler 
    
        http://www.arantius.com/article/my-greasemonkey-compiler
        
    Thanks Arantius!
    
    Thanks also Aaron Boodman and others for the joys of Greasemonkey!

*/




const LOG_LEVEL = 1;

const DEBUG = 4;
const INFO = 3;
const WARN = 2;
const ERROR = 1;

function myGM_log( message, level) {
    if (level <= LOG_LEVEL) {
        GM_log( message);
    }
}

myGM_log( WB_version, 1)

main();

function main(  ) {
    
    replaceLanguageLinks();
    
}


/* Replace the links to other languages with links to the parallelise javascript function.

<div id="p-lang" class="portlet">
    <h5> In other languages </h5>
		
    <span class="webdeveloper-id-class-details"> .pBody </span>

    <div class="pBody">

	<ul>
		<span class="webdeveloper-id-class-details"> .interwiki-af </span>
		<li class="interwiki-af">
    			<a href="http://af.wikipedia.org/wiki/Wikipedia:Babel"> Afrikaans </a>
		</li>
*/
function replaceLanguageLinks(  ) {
    // var xpathResult = document.evaluate(xpathExpression, contextNode, namespaceResolver, resultType, result);
    
    var otherLangCount = document.evaluate("count(//div[@id='p-lang']/div/ul/li)", document, null, XPathResult.ANY_TYPE, null).numberValue;
    
    var otherLangAnch = document.evaluate("//div[@id='p-lang']/div/ul/li/a", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
    
    
    var thisAnch;
    var thisHref;
    var thisText;
    
        for (var i = 0; i < otherLangAnch.snapshotLength; i++) {
            thisAnch = otherLangAnch.snapshotItem(i);
            //thisAnch.onclick="alert('Hello ou there ' + i + ' !')";
            thisHref = thisAnch.getAttribute('href');
            thisText = thisAnch.firstChild.nodeValue;
            thisAnch.setAttribute('onclick', "parallelise('" + thisHref + "', '" + thisText + "' )" );        
            thisAnch.removeAttribute('href');
        }
    
    // TODO: add some visual cue that this is different to usual
    // TODO: add a toggle here so user can click to revert to nonGM behaviour
    
    //myGM_log('contains' +  otherLangCount + ' other languages', DEBUG);
}

function addGlobalStyle(css) {
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = css;
    head.appendChild(style);
    // Note that this function will currently dumbly add another copy of css
    // each time the user chooses another language on the same page!
}



/* 
 *
 * the parallelise javascript function
 *
 */

unsafeWindow.parallelise = function(href, text) {

    
    // if our parallel div exists, delete it
    if ( document.getElementById('content-parallel') ) {
        //alert("Add code to kill parallel column");
        var container = document.getElementById('column-content');
        var unwanted = document.getElementById('content-parallel');
        throwaway_node = container.removeChild(unwanted);
        //myGM_log("deleted prexisting content-parallel", DEBUG);
    }
    
    // create appropriate CSS   - top right bottom left
    addGlobalStyle('#content   { width: 40% ! important; float:left ! important; }');
    addGlobalStyle('#content-parallel { width: 40%; float:right; margin: 2.8em 0 0 0; background: white; color: black; border: 1px solid #aaa; border-left: none; line-height: 1.5em; position: relative; z-index: 3; }'); 
    
    //addGlobalStyle('#content-parallel { width: 40%; float:right; margin: 2.8em 0 0 12.2em; padding: 0 1em 1.5em 1em; background: white; color: black; border: 1px solid #aaa; border-right: none; line-height: 1.5em; position: relative; z-index: 3; }'); 
    
    // Somewhere, allow them to say, "use these languages on every page"
    
    
    // Progress meter
    var container = document.getElementById('column-content');
    var tmpDiv = document.createElement("div");
    tmpDiv.setAttribute("id", "content-parallel");
    var myText = document.createTextNode("Fetching " + text + '-- from --' + href);
    tmpDiv.appendChild(myText);
    container.appendChild(tmpDiv);
	
	// get contents and populate the div

    if (!GM_xmlhttpRequest) {
        alert('Please upgrade to the latest version of Greasemonkey.');
        return;
    }
	
	var pageRequest = new GM_xmlhttpRequest({
		method: 'GET',
		url: href,
		onload: function(responseDetails) {

			/* TODO: add 
				 1. "waiting.." and 
				 2. error handling
				
				 3. look at details.responseHeaders, and log a warning if
				    (i)  content type is not text/html  (since XML parser might be used)
				    (ii) charset is not utf-8
			*/
			
			var pageResponse;


			var parser = new DOMParser();
			var responseXML = parser.parseFromString(responseDetails.responseText, "text/xml");  // or application/xhtml+xml

			var roottag = responseXML.documentElement;
			if ((roottag.tagName == "parserError") ||
    				(roottag.namespaceURI == "http://www.mozilla.org/newlayout/xml/parsererror.xml")){
					var serializer = new XMLSerializer();
					alert("Parsing Error!" + serializer.serializeToString(responseXML));
			}

			
			/* Get the internationalization stuff off the html element

				<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 							"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

				<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ar" lang="ar" dir="rtl">
			 */
			// roottag should be the html element
			if ( roottag.nodeName != "html") {
				myGM_log("Warning: found roottag element name '" + roottag.nodeName + "' but expected 'html'!", ERROR);
			}
			//myGM_log("lang: " + roottag.getAttribute("lang"), DEBUG );
			var lang = roottag.getAttribute("lang");
			
			//myGM_log("dir: " + roottag.getAttribute("dir"), DEBUG );
			var dir = roottag.getAttribute("dir");
			
			/* Since the response header indicated it was served as text/html
			   it would have been parsed with the tag soup parser
			   (See http://www.mozilla.org/docs/web-developer/faq.html#xhtmldiff )
			 
			   "The consequence is that XHTML 1.0 Transitional documents 
			   are rendered in the Almost Standards mode when served as 
			   text/html under pretext of the Appendix C but in the 
			   Standards Mode when served as application/xhtml+xml."
			  
			   I assume "tag soup" means HTML
			   
			*/
			//myGM_log("xml:lang : " + roottag.getAttribute("xml:lang"), DEBUG );
			var xmllang = roottag.getAttribute("xml:lang");

	
			// Now get the content proper ...
			var contents = responseXML.getElementById('content');
            
            /* Structure of document looks like:
            
                TODO - document this
            
                body
                    div id=globalWrapper
                    
                        div id=column-content
                        
                            div id=content
                            
                                contains article firstHeading 
                                
                                div id=bodyContent
                                
                                div id=column-one
                                
                                    div id=p-cactions
                                    
                                        // The  _|article|_ _discussion|____|view source|__history|_
                                        // tabs are actually part of div[@id=column-one]/div[@id=p-cactions]
                                        //
                                        // Currently you don't see this in the right hand language,
                                        // which is probably ok.
                                
                        div id=footer
                                       
            */
            
            

			contents.setAttribute("id", "content-parallel");
			contents.setAttribute("lang", lang);
			contents.setAttribute("dir", dir);
			contents.setAttribute("xml:lang", xmllang); // probably irrelevant, but set it anyway

            myGM_log( "Need to extract base URL from " + href, INFO );
            var lead_slashes = href.indexOf("//");
            var domain_start = lead_slashes + 2;
            var without_resource = href.substring(domain_start, href.length);
            var next_slash = without_resource.indexOf("/");
            var domain = without_resource.substring(0, next_slash);
            var baseURL = "http://" + domain;
            myGM_log( "It is " + baseURL, INFO );
            
            // Go through all the hyperlinks - any relative ones need to be
            // made absolute, so they point to the source language wiki
            //var anchors = roottag.getElementsByTagName("a");
            var anchors = contents.getElementsByTagName("a");
            var thisAnch;
            var thisHref;
            myGM_log( "There are " + anchors.length + " anchors", INFO );
            for (var i = 0; i < anchors.length; i++) {
                thisAnch = anchors[i];
                thisHref = thisAnch.getAttribute('href');
                if (thisHref) {
                    if (thisHref.indexOf("http://") == 0 ) {
                        // Do nothing
                    } else if (thisHref.indexOf("#") == 0 ) {
                        // Do nothing
                    } else {
                        // Make absolute
                        thisAnch.removeAttribute('href');
                        thisAnch.setAttribute('href', baseURL + thisHref );  
                        
                        // Any of these links will replace the entire page.
                        // That seems ok, since your back button works
                        
                        // Other possible behaviours:
                        // - open in new window
                        // - call parallelise on it?
                       
                    }
                } else {
                    myGM_log( i + ": No href? ", INFO );                    
                }
            }

            // Do the same for images.
            // Is this ever necessary?  Maybe wikimedia always uses an absolute URL?
            // Could have a look at the source code for it...
            
            // See http://meta.wikimedia.org/wiki/Help:Images_and_other_uploaded_files
            var images = contents.getElementsByTagName("img");
            var thisImage;
            var thisSrc;
            myGM_log( "There are " + images.length + " images", INFO );
            for (var i = 0; i < images.length; i++) {
                thisImage = images[i];
                thisSrc = thisImage.getAttribute('src');
                if (thisSrc) {
                    if (thisSrc.indexOf("http://") == 0 ) {
                        // Do nothing
                    //} else if (thisHref.indexOf("#") == 0 ) {
                        // Do nothing
                    } else {
                        // Make absolute
                        thisImage.removeAttribute('src');
                        thisImage.setAttribute('src', baseURL + thisSrc );  
                        myGM_log( "Made " + thisSrc + " absolute", INFO );
                    }
                } else {
                    myGM_log( i + ": No src? ", INFO );                    
                }
            }
            
            // Other objects?
            
            
			// add in "full screen" option
            var pFullScreen = document.createElement("p");  //hmm document here is a bug?
			pFullScreen.innerHTML= "<a href=\"" + href + "\">[This language full screen]</a>";

			var bodyContent = responseXML.getElementById('bodyContent');
			var siteSub = responseXML.getElementById('siteSub');
            bodyContent.insertBefore(pFullScreen, siteSub.nextSibling);

            // add in a remove option?  
            
             
			var container = document.getElementById('column-content');

			// get rid of the progress meter
			var unwanted = document.getElementById('content-parallel');
			throwaway_node = container.removeChild(unwanted);
			
			// add in the real contents
			container.appendChild(contents);
			// or could have used replacechild (or replacenode?)

        }  // end onload
    }); // end GM_xmlhttpRequest
	
} // end unsafeWindow.parallelise
Prefix: a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9

Portal di Ensiklopedia Dunia

Kembali kehalaman sebelumnya