MediaWiki:Gadget-QQ.js

'use strict'; // /*jshint shadow:true, scripturl:true, undef:true, latedef:true, unused:true, loopfunc:true */ /*globals mw, jQuery */ function el(tag, child, attr, events) { var node = document.createElement(tag); if (child) { if (typeof child !== 'object') child = [child]; for (var i = 0; i < child.length; ++i) { var ch = child[i]; if ((ch === void(null)) || (ch === null)) continue; else if (typeof ch !== 'object') ch = document.createTextNode(String(ch)); node.appendChild(ch); }	}	if (attr) for (var key in attr) { node.setAttribute(key, String(attr[key])); }	if (events) for (var key in events) { node.addEventListener(key, events[key], false); }	return node; }

var backends = { gbooks: { name: "Google Books", enabled: true, addResults: function (data, callback) { function makeResult(item) { var m;				var texttype; if (item.volumeInfo.printType.includes('BOOK')) texttype = "book"; else if (item.volumeInfo.printType.includes('MAGAZINE')) texttype = "journal" else texttype = "text"; var lang; if (item.volumeInfo.language) { lang = item.volumeInfo.language.replace('iw', 'he'); // hardcoded exceptions can be added here }				var year, month, day; if (item.volumeInfo.publishedDate) { if (m = /(\d{4})-?(\d{2})?-?(\d{2})?/.exec(item.volumeInfo.publishedDate)) { year = m[1]; month = m[2]; day = m[3]; }				}				var page; if (item.volumeInfo.previewLink) { var uri = new mw.Uri(item.volumeInfo.previewLink); if (uri.query.pg) { if (m = /PA(\d+)/.exec(uri.query.pg)) page = m[1]; }				}				var idents = {}; if (item.volumeInfo.industryIdentifiers) { for (var i = 0; i < item.volumeInfo.industryIdentifiers.length; ++i) { var ident = item.volumeInfo.industryIdentifiers[i]; idents[ident.type] = ident.identifier; }				}				var isbn = idents.ISBN_13 || idents.ISBN_10; return { generateCitation: function { var result = "* {{quote-"; result += texttype; if (lang) result += "|" + lang; if (month && day) result += "|date=" + year + "-" + month + "-" + day; else if (month) result += "|year=" + year + "|month=" + month; else if (year) result += "|year=" + year; if (item.volumeInfo.authors) { result += "|author=" + item.volumeInfo.authors[0]; if (item.volumeInfo.authors.length > 1) { for (var i = 1; i < item.volumeInfo.authors.length; i++) { var n = i + 1; result += "|author" + n + "=" + item.volumeInfo.authors[i]; }							}						}

if (item.volumeInfo.title) { result += "|title=" + item.volumeInfo.title; if (item.volumeInfo.subtitle) result += ": " + item.volumeInfo.subtitle; }						if (item.volumeInfo.publisher) result += "|publisher=" + item.volumeInfo.publisher; if (isbn) result += "|isbn=" + isbn; if (page) result += "|page=" + page; if (item.searchInfo && item.searchInfo.textSnippet) { var text = item.searchInfo.textSnippet.replace(/<.*?>/g, '') .replace(/\n/g, " ") .replace(/ \.\.\./g, "{{nb...}}") .replace(/&#39;/g, "'") .replace(/&quot;/g, "\"");							result += "\n|text=" + text + "}}\n";						} else {							result += "}}\n";						}

return result; },					populateNode: function (node, checkbox) { node.appendChild(el('label', [ checkbox, year ? el('strong', year) : el('i', "date unknown"), item.volumeInfo.authors && ", ", item.volumeInfo.authors && item.volumeInfo.authors.join(", "), ", ",							el('cite', [								item.volumeInfo.title,								item.volumeInfo.subtitle && el('small', [": ", item.volumeInfo.subtitle])							]), ]));

node.appendChild(el('span', [ item.volumeInfo.publisher && el('span', [								", ",								item.volumeInfo.publisher,							], { 'class': 'publisher' }), isbn && el('span', [								" (", el('a', ["ISBN " + isbn], {									'href': mw.util.getUrl('Special:BookSources/' + isbn)								}), ")"							], { 'class': 'isbn' }), page && el('span', [								", page ",								page,							], { 'class': 'page' }), item.volumeInfo.previewLink && el('small', [								" [",								el('a', "view", { 'href': item.volumeInfo.previewLink }),								"]"							]),							item.volumeInfo.infoLink && el('small', [								" [",								el('a', "info", { 'href': item.volumeInfo.infoLink }),								"]"							]),							el('small', [								" [",								el('a', "raw", { 'href': 'javascript:void(0);' }, {									'click': function { alert(JSON.stringify(item, null, ' ')); }								}),								"]"							])						]));						if (item.searchInfo && item.searchInfo.textSnippet) { var uiQuote = el('blockquote'); uiQuote.innerHTML = item.searchInfo.textSnippet.replace(/ /g, " "); node.appendChild(uiQuote); }					}				};			}

if (!data.items) { this.uiStatus.textContent = "no more results"; this.uiStatus.style.display = ''; return; }			for (var i = 0; i < data.items.length; ++i) { if (data.items[i].searchInfo && data.items[i].searchInfo.textSnippet) { if (!//.test(data.items[i].searchInfo.textSnippet)) continue; // bogus result }				callback(makeResult(data.items[i])); }			this.uiMore.style.display = ''; this.uiStatus.textContent = ""; this.data.startIndex += data.items.length; },		populateTab: function (tab) { var that = this;

this.uiResults = el('ul'); this.uiStatus = el('div'); this.uiMore = el('a', ["more results"], {				'href': 'javascript:void(0);'			}, {				'click': function {					that.uiStatus.textContent = "please wait...";					this.style.display = 'none';					jQuery.ajax({ url: location.protocol + '//www.googleapis.com/books/v1/volumes', dataType: 'jsonp', data: that.data }).done(function (data) { that.addResults(data, that.callback); });				}			});			tab.appendChild(this.uiResults); tab.appendChild(this.uiStatus); tab.appendChild(this.uiMore); },

search: function (terms, options, callback) { var that = this; while (this.uiResults.firstChild) this.uiResults.removeChild(this.uiResults.firstChild);

this.data = { q: terms, startIndex: 0, maxResults: 20 // orderBy: 'newest' // reverse chronological order; no option for plain chronological order, unforutnately };			this.callback = callback; this.uiMore.style.display = 'none'; this.uiStatus.textContent = "please wait..."; jQuery.ajax({				url: location.protocol + '//www.googleapis.com/books/v1/volumes',				dataType: 'jsonp',				data: this.data			}).done(function (data) {				that.addResults(data, callback);			}); }	} };

var uiQuery, uiTitle, uiBackends, uiTabs, uiTabLabels, uiCitationsTab, uiCitations, uiCurTab, uiCurTabLabel, uiForm; var uiMain = el('div', [	uiTitle = el('div', [ el('strong', "Quiet Quentin"), el('a', "hide", {			'href': 'javascript:void(0);',			'class': 'hide-link'		}, {			'click': function {				uiMain.style.display = 'none';			}		}) ], { 'class': 'title' }),	uiForm = el('form', [ el('fieldset', [			el('legend', "Search for attestations"),			uiQuery = el('input', null, { 'type': 'text', 'placeholder': "term", 'class': 'search-terms', 'value': (function {					var m;					if ([0, 1, 114].indexOf(mw.config.get('wgNamespaceNumber')) !== -1) // main, Talk, Citations						return '"' + mw.config.get('wgTitle') + '"';					if (mw.config.get('wgNamespaceNumber') === 100)						if (m = /[^/]+\/(.*)/.exec(mw.config.get('wgTitle')))							return m[1];					if (mw.config.get('wgCanonicalSpecialPageName') === 'Search')						return '"' + document.getElementById('searchText').value + '"';					return '';				}) }),			el('input', null, { 'type': 'submit', 'value': "search" }), el('br'),			uiBackends = el('div', [ el('strong', "Backends"), ": " ])		])	], {		'action': 'javascript:void(0);' }, {		'submit': function { var hasAny = false; for (var key in backends) { hasAny = (function (backend) {					if (!backend.enabled) {						backend.uiTabLabel.style.display = 'none';						return hasAny;					} else {						backend.uiTabLabel.style.display = ;						if (!hasAny) {							uiCurTab.style.display = 'none';							uiCurTabLabel.classList.remove('active');							uiCurTab = backend.uiTab;							uiCurTabLabel = backend.uiTabLabel;							uiCurTab.style.display = ;							uiCurTabLabel.classList.add('active');						}					}					backend.results = [];

if (backend.enabled) { backend.search(uiQuery.value, null, function (result) {							backend.results.push(result);

var node = el('li'); var checkbox = el('small', [								"[",								el('a', "pick", { 'href': 'javascript:void(0)', 'class': 'take-link' }, {									click: function { if (result.taken) { result.taken = false; node.classList.remove('taken'); } else { result.taken = true; node.classList.add('taken'); }									}								}),								" | ",								el('a', "collapse", { 'href': 'javascript:void(0)' }, { click: function { node.classList.toggle('struck'); }								}),								"] "							]);							result.populateNode(node, checkbox); backend.uiResults.appendChild(node); });						return true;					}				})(backends[key]); }

if (hasAny) { uiTabs.style.display = ''; uiTabLabels.style.display = ''; } else { alert("No backends chosen"); uiTabs.style.display = 'none'; uiTabLabels.style.display = 'none'; }		}	}),	uiTabLabels = el('ul', null, { 'class': 'tab-labels', 'style': 'display: none;' }),	uiTabs = el('div', null, { 'class': 'tabs', 'style': 'display: none;' }) ], {	'class': 'kephir-qq',	'style': 'display: none; position: fixed;' }); jQuery(uiMain).draggable({	handle: uiTitle }).resizable({	alsoResize: uiTabs }); document.body.appendChild(uiMain);

var positions = JSON.parse(localStorage.QQ_positions || "{}"); var size = JSON.parse(localStorage.QQ_size || "{}"); $(function {    var d = $(".kephir-qq").attr("id", function (i) { return "draggable_" + i   })    $.each(positions, function (id, pos) { $("#" + id).css(pos) })   $.each(size, function (id, siz) { $("#" + id).css(siz) })

d.draggable({       stop: function (event, ui) {            positions[this.id] = ui.position            localStorage.QQ_positions = JSON.stringify(positions)        }    }); d.resizable({       stop: function (event, ui) {            size[this.id] = ui.size            localStorage.QQ_size = JSON.stringify(size)        }    }); });

var uiCitationsHash;

function regenerateCitations { var result = [];

for (var key in backends) { var results = backends[key].results; for (var j = 0; j < results.length; ++j) { if (results[j].taken) result.push(results[j].generateCitation); }	}	result = result.join('');

if (uiCitationsHash.checked) { result = result.replace(/^\*/mg, '#*').replace(/#*$/, ''); }	uiCitations.value = result; }

uiTabs.appendChild(uiCurTab = uiCitationsTab = el('div', [ uiCitations = el('textarea', null, {		'rows': 20,		'cols': 80	}), el('br'), el('label', [		uiCitationsHash = el('input', null, { 'type': 'checkbox' }, { 'change': function { regenerateCitations; }		}),		"Put # before each line"	]) ], { 'style': 'display: none' }));

uiTabLabels.appendChild(uiCurTabLabel = el('li', [ el('a', "Picked citations", {		'href': 'javascript:void(0);'	}, {		'click': function {			regenerateCitations;			uiCurTab.style.display = 'none';			uiCurTabLabel.classList.remove('active');			uiCurTab = uiCitationsTab;			uiCurTabLabel = this;			uiCurTab.style.display = '';			uiCurTabLabel.classList.add('active');		}		}) ], { 'class': 'citations-tab' }));

for (var key in backends) { (function (backend) {		uiBackends.appendChild(el('label', [			el('input', null, { 'type': 'checkbox', 'checked': backend.enabled ? 'checked' : '' }, {				'change': function { backend.enabled = this.checked; }			}),			backend.name		]));		backend.uiTab = el('div', [], { 'style': 'display: none;' });		backend.uiTabLabel = el('li', [ el('a', backend.name, { 'href': 'javascript:void(0);' }, {				'click': function {					uiCurTab.style.display = 'none';					uiCurTabLabel.classList.remove('active');					uiCurTab = backend.uiTab;					uiCurTabLabel = backend.uiTabLabel;					uiCurTab.style.display = '';					uiCurTabLabel.classList.add('active');				}				}) ]);		backend.populateTab(backend.uiTab);		uiTabs.appendChild(backend.uiTab);		uiTabLabels.appendChild(backend.uiTabLabel);	})(backends[key]); }

var link = mw.util.addPortletLink(mw.config.get('skin') === 'vector' ? 'p-views' : 'p-cactions',	'javascript:void(0);', 'QQ', 'p-kephir-qq', "search for attestations", '9' ); link.addEventListener('click', function {	uiMain.style.display = '';	uiQuery.focus; }, false);