Benutzer:Se4598/isbnsuche.js

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen

Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Internet Explorer/Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
  • Opera: Strg+F5
// ==UserScript==
// @id             wp_isbnsuche
// @name           ISBN-Suchbeschleuniger
// @version        1.2alpha
// @namespace
// @author         se4598
// @description
// @include        http://de.wikipedia.org/*
// @include        https://de.wikipedia.org/*
// @include        http://de.wikipedia.beta.wmflabs.org/*
// @include        https://de.wikipedia.beta.wmflabs.org/*
// @run-at         document-end
// ==/UserScript==

if ( typeof $ === 'undefined') {
	$ = unsafeWindow.$;
}
if ( typeof mw === 'undefined') {
	mw = unsafeWindow.mw;
}

(function(mw, $){
	
	var config = {
		//will be build in document.ready
		
		/*
		 * internal use
		 * 0: default
		 * 0: mw.loader.using done, config loaded;
		 * 1: mw.hook("wikipage.content");
		 * 2: links replaced/tipsy created
		 */
		loaded: 0,
	};
	var defaultconfig = {
		/*
		 * a framename to use as target in links
		 * note that if frame doesn't exist new tabs/windows don't open in background 
		 * experienced users could also use here e.g. the current pagetitle
		 * * values: _blank , _self , user-defined-name , ...
		 */
		targetframe: 'booksourcesDirect',
		/*
		 * if true every entry gets a own target
		 * should only count if targetframe starts not with '_' (sign for a special frame)
		 * implemented via `targetframe` + '_' + displayname of entry
		 */
		everytargetown: false,
		/*
		 * if true a click on a entry closes the tooltip
		 */
		closeonclick: true,
		/*
		 * how the script should work
		 * if it is 'fixedtarget' then any isbn-link will be replaced with a link provided by `fixedtarget`
		 * for any other value it will be at the moment the normal behavior
		 */
		linkmode: 'normal',
		/*
		 * function which generates the direct link if in `linkmode`=='fixedtarget' 
		 * first parameter is the isbn
		 * should return a string used as href of a link
		 */
		fixedtarget: function (isbn) {
			//return 'https://portal.d-nb.de/opac.htm?referrer=Wikipedia&method=simpleSearch&query='+isbn;
			var val = config.libraries[fixedlibrary];
			if(val === undefined){
				return ['!!!unknown library: '+fixedlibrary+'!!!', '/wiki/Special:Booksources/'+isbn] ;
			} else {
				return [fixedlibrary, val.replace(/\$1/g,isbn)];
			}
		},
		/*
		 * function which generates a list of entries for the tooltip
		 * first paramter is the isbn
		 * should return an array of entries used in a list. a entry should be an array of the displayed name and the url 
		 */
		links: function (isbn){
			/*
			return [ //example list only
			['[[wiki]]', '/wiki/Spezial:ISBN-Suche/'+isbn],
			['DNB','https://portal.d-nb.de/opac.htm?referrer=Wikipedia&method=simpleSearch&query='+isbn],
			['KVK','http://www.ubka.uni-karlsruhe.de/kvk.html?SB='+isbn+'&kataloge=SWB&kataloge=GBV'],
			['Amazon','http://www.amazon.de/s/url=search-alias%3Daps&field-keywords='+isbn],
			];
			*/
			var ret = [];
			var selLibs = config.selectedlibraries.split(' '); 
			for(var i = 0, l = selLibs.length; i < l; i++){
				var val = config.libraries[selLibs[i]];
				if(val === undefined){
					ret.push(['!!!unknown library: '+selLibs[i]+'!!!', '/wiki/Special:Booksources/'+isbn]);
				} else {
					ret.push([selLibs[i], val.replace(/\$1/g,isbn)]);
				}
			}
			return ret;
		},
		
		libraries: {
			"*wiki*":    "/wiki/Special:Booksources/$1",
			"DNB":       "https://portal.d-nb.de/opac.htm?referrer=Wikipedia&method=simpleSearch&query=$1",
			"KVK":       "http://www.ubka.uni-karlsruhe.de/kvk.html?SB=$1&kataloge=SWB&kataloge=GBV",
			"amazon.de": "http://www.amazon.de/s/url=search-alias%3Daps&field-keywords=$1"
		},
		
		selectedlibraries: "*wiki* DNB KVK amazon.de",
		fixedlibrary: "DNB",
		};
	
	var extractISBN = function(element){
		//var isbn = this.getAttribute('href').split('/');
		//isbn = isbn[isbn.length-1];
		var re  = /\/wiki\/[^:\/]+:[^\/]+\/([0-9]+[xX]?)$/;
		var match = re.exec(element.getAttribute('href'));
		if(match !== null){
			return match[1];
		} else {
			return null; //almost impossible
		}
	};
	
	/*
	 * must return a (html) string displayed as tooltip-text 
	 */
	var tipsytext = function(){
		//`this` is the (clicked/hovered) html-element
		//isbn-links doesn't have a own tooltip/title but class .mw-magiclink-isbn
		
		var isbn = extractISBN(this);
		if(isbn === null){
			return 'No ISBN found.';
		}
		var links = config.links(isbn);
		var customtarget = (config.everytargetown && !config.targetframe.startsWith('_'));
		var ret = '<span class="wp-booksourcesDirect-isbn'+isbn+'" />'; // (enough) unique identifier to find the toolip
		for(var i=0,j=links.length; i<j; i++){
			if(i !== 0){
				ret += '<br />';
			}
			if(links[i].length == 2){
				ret += '<a href="'+links[i][1]+'" target="'+
				( customtarget ? (config.targetframe+'_'+links[i][0]) : (config.targetframe) ) //FIXME: for crazy (aka non-[a-z0-9]) linktexts e.g. to allow html as displayed text: how about parsing it as html and then getting the text
				+'">'+links[i][0]+'</a>';
			} else { //links[i].length == 1
				ret += links[i][0];
			}
		};
		return ret;
	};

	var createtipsy = function(index){
		//`this` is the relevant html-element
		var $element = $(this); //must be var
		var options = {
			html: true,
			trigger: 'manual', // -> .tipsy("show"), .tipsy("hide")
			gravity: $.fn.tipsy.autoNS, //position
			opacity: 0.9, //eventually
			title: tipsytext
		};
		$element.tipsy(options);
		
		var isbn = extractISBN(this);
		
		//this is the handler for clicks on isbn links
		//any close-element must be added after tipsy-tooltip is created or created with plain inline-js (onclick="...")
		//unbind wrapper if present
		$element.unbind('click.wp-booksourcesDirect-wrapper');
		$element.click(function(evt){
			//open tooltip
			evt.preventDefault();
			$(this).tipsy("show");
			
			//add close X
			$('<span>')
			.text('X')
			.click(function(){ $element.tipsy("hide");}) //could be improved in the rare cases where unlikely this will be added to a wrong tooltip
			.addClass('wp-booksourcesDirect-closex') //is used as marker class but could be used for styling
			.css({position:'absolute', top:0, right:0, 'font-weight':'bold', border:'2px solid #F00'})
			.appendTo($('.wp-booksourcesDirect-isbn'+isbn).parent().filter(function(){return $(this).children('.wp-booksourcesDirect-closex').length === 0})); //should always get the right one except parallel opening of 2 tooltips for one isbn
			
			//close on click on entry
			if(config.closeonclick){
				$('.wp-booksourcesDirect-isbn'+isbn).parent().find('a').not('.wp-booksourcesDirect-closeonclick') // .wpisbnsuche_closeonclick is a marker
				.addClass('wpisbnsuche-closeonclick')
				.click(function(evt) { $element.tipsy("hide"); });
			}
		});
	};
	
	var tipsyinitalwrapper = function(index){
		//`this` is the relevant html-element
		var $element = $(this);
		$element.bind('click.wp-booksourcesDirect-wrapper', function(evt){
			evt.preventDefault();
			//we must be in state 2
			if(config.loaded == 2){
				config.loaded = 3;
				$('a.mw-magiclink-isbn').each(createtipsy);
				//and trigger wanted tipsy
				$element.click();
			};
		});
	}
	
	var changefixedtarget = function(index){
		//`this` is the relevant html-element
		var isbn = extractISBN(this);
		if(isbn !== null){
			this.setAttribute('href', config.fixedtarget(isbn));
			this.setAttribute('target', config.targetframe);
		} else {
			this.setAttribute('href', '/wiki/Fehler_Keine_ISBN_gefunden');
			this.setAttribute('target', config.targetframe);
		}
		
	};
	
	mw.loader.using(['jquery.tipsy', 'user'], function() {
		if(!mw.libs.booksourcesDirect || mw.libs.booksourcesDirect.loaded === undefined){ //prevent simple multiload
			$.extend(true, config, defaultconfig); //init with default
			mw.libs.booksourcesDirect = $.extend(true, config, mw.libs.booksourcesDirect);  //overwrite with user options and write back/expose cur. config
			config.loaded = 1;
			
			//$(document).ready(function() {
			mw.hook("wikipage.content").add(function() { //could be triggered more than once
				config.loaded = 2; //reset in case of rebuild
				if(config.linkmode === "fixedtarget"){
					$('a.mw-magiclink-isbn').each(changefixedtarget);
					config.loaded = 3;
				} else {
					$('a.mw-magiclink-isbn').each(tipsyinitalwrapper);
				}
			});
		}
	});
	
	// alien - preferencesGadgetOptions
	//TODO: wrong position, not complete, multi-exe, ... => everything ;-) 
	
	var gagaGadgetForm  =  function () {
	   var dialog  =  {
	             script:  "booksourcesDirect",
	             show:    "ISBN-Suche",
	             support: "/wiki/User_Talk:Se4598/isbnsuche.js",
	             suffix:  "Direkte Links auf Bibliotheken",
	             opts:    [ { signature: "manytabs",
	                          type:      "checkbox",
	                          show:      "Jede Domain eigenen Tab (Fenster)",
	                          val:       false
	                        },
	                        { signature: "closeonclick",
	                          type:      "checkbox",
	                          show:      "Bei Klick Auswahlmenü schließen",
	                          val:       true
	                        },
	                        { signature: "linkmode",
	                          type:      "radio",
	                          val:       "normal",
	                          show:      "Funktionsweise",
	                          poly: [{val:'normal',show:"normal"},{val:'fixedtarget',show:"festes Ziel"}],
	                          minimum:   9,
	                          maxlength: 20
	                        },
	                        { signature: "selectedlibraries",
	                          type:      "text",
	                          val:       "*wiki* DNB KVK amazon.de",
	                          show:      "Auswahl an Datenquellen",
	                          suffix:    "(in Reihenfolge)",
	                          minimum:   20,
	                          maxlength: 100
	                       },
	                       { signature: "fixedlibrary",
	                          type:      "text",
	                          val:       "",
	                          show:      "Datenquelle bei festem Ziel",
	                          minimum:   9,
	                          maxlength: 20
	                        }
	                      ]
	   };
	   mw.libs.preferencesGadgetOptions.form( dialog );
	};
	var gagaGadget  =  function () {
	   if ( mw.config.get( "wgCanonicalSpecialPageName" )  ===  "Gadgets" ) {
	      gagaGadgetForm();
	   } else {
	      console.dir( mw.libs.preferencesGadgetOptions.fetch("booksourcesDirect") );
	   }
	};
	if ( ! mw.loader.getState( "ext.gadget.preferencesGadgetOptions" ) ) {
	   mw.loader.implement( "ext.gadget.preferencesGadgetOptions",
	                        [ "//en.wikipedia.org/w/index.php?title="
	                          + "User:PerfektesChaos/js/"
	                          + "preferencesGadgetOptions/r.js"
	                          + "&action=raw&ctype=text/javascript"
	                          + "&maxage=604800&smaxage=10000&*" ],
	                        { },
	                        { } );
	}
	mw.loader.using( [ "user.options",
	                   "ext.gadget.preferencesGadgetOptions" ],
	                 gagaGadget );
	
	
	
})(mw, $);