User:V111P/js/webRefSetup.js

// This script is used in combination with the WebRef script, which is not yet uploaded for use for the English Wikipedia. // v. 2013-04-23 / 0.01.2 if (!window.webRef || !window.webRef.getRef) alert('WebRef Setup error: Please, load WebRef first!'); else webRef.webRefSetup = (function {	'use strict';	function prt(txt) {		if (window.console && console.log)			console.log(txt);	}

window.webRef.webRefSetupVer = 1;

// Shortcuts var refDocData = window.webRef.refDocData; var domain = window.webRef.domain; var dom = window.webRef.dom; var newEl = dom.newEl; var aux = window.webRef.aux; var idToText = webRef.idToText;

var maxStrLengthInOption = 100; var showCharsFromEnd = 20;

var frameBodyStyleObj = { margin: '0 auto', color: '#ffffff', backgroundColor: '#000077', border: '5px solid gray', borderWidth: '5px 0', padding: '1px', font: 'normal normal normal medium serif', textAlign: 'left' };

var refFrame = { frame: null, win: null, doc: null, body: null };

// a collection of references to the form controls var ctrls = {}; // site, title, date, author, publisher, visited, url, code, etc.

refDocData.searchSection = { things: ['title', 'date', 'author'], fieldIdEndings: ['Search'], //['SeparatorBefore', 'Search', 'SeparatorAfter'] fieldSizes: [70] //[5, 70, 5] };	refDocData.aboutSiteFields = [ 'siteName', 'lang', 'publisher', 'authorName', 'authorWikiArticle', 'notAnAuthor' ];

refDocData.buttonSectionButtons = [ {id: 'toCode', onclick: toCode}, {id: 'saveToStorage', onclick: saveToStorage}, {id: 'loadFromVar', onclick: loadFromVar}, {id: 'loadFromStorage', onclick: loadFromStorage}, {id: 'deleteFromStorage', onclick: deleteFromStorage}, {id: 'resetForm', onclick: resetForm}, {id: 'useOnceFromTA', onclick: useOnceFromTA}, {id: 'closeSetup', onclick: closeSetup} ];

function loadFromStorage { var code = localStorage && localStorage.getItem('webRef-1') || ''; ctrls.code.value = (code && '"' + domain + '": ' + code) || ''; }	function deleteFromStorage { if (localStorage && localStorage.getItem('webRef-1') && confirm(idToText['delStorageConfirm'])) localStorage.removeItem('webRef-1'); }	function saveToStorage { var code, obj; if (!window.localStorage || !window.JSON) alert(idToText['noStorage']); else { code = ctrls.code.value.replace(/^[^{]*/, ''); try { obj = JSON.parse(code); } catch (e) { alert(idToText['invalidCode']); return; }			if ( !localStorage.getItem('webRef-1') || confirm(idToText['overwriteStorageConfirm']) ) localStorage.setItem('webRef-1', JSON.stringify(obj, null, '\t')); }	}	function useOnceFromTA { var code, obj; code = ctrls.code.value.replace(/^[^{]*/, ''); try { obj = JSON.parse(code); } catch (e) { alert(idToText['invalidCode']); return; }		if (!window.webRefSiteData) window.webRefSiteData = {}; webRefSiteData[domain] = obj; closeSetup; webRef.getRef; }	function closeSetup { dom.byId('ref01ref').style.display = 'none'; dom.byId('ref01refDiv').style.display = 'none'; webRef.displayWebRefFrame(true); document.body.scrollTop = document.documentElement.scrollTop = 0; }	function resetForm { if (confirm(idToText['resetFormConfirm'])) autoFillInfo; }

aux.shorten = function (longStr) { // shorten a string for display var str = longStr; if (str.length > maxStrLengthInOption) str = str.substr(0, maxStrLengthInOption - 5 - showCharsFromEnd) + ' ... ' + str.substr(str.length - showCharsFromEnd, showCharsFromEnd); return str; };

function autoFillInfo { // Auto fill fields in the Search Results section var i, str, o, autoIn, things = refDocData.searchSection.things; for (o in things) { if (!things.hasOwnProperty(o)) continue; autoIn = refDocData.things[things[o]] && refDocData.things[things[o]].autoSearchIn; if (!autoIn) continue; var selEl = ctrls[things[o] + 'Results']; selEl.innerHTML = ''; var n = 0; for (i = 0; i < autoIn.length; i++) { str = window.webRef.textFromAddr(autoIn[i], false); if (str) { var txt = aux.shorten(autoIn[i]) + ' (' + aux.shorten(str) + ')'; if (n == 0) selEl.appendChild(newEl('option', { value: '', text: idToText['default'] + ': ' + txt }));					n++; selEl.appendChild(newEl('option', { value: autoIn[i], text: txt }));				}			}		}

// Auto fill fields in the About the Site section var searchInArr, thing, formatter; var abtFields = refDocData.aboutSiteFields; var things = refDocData.things; for (var i = 0; i < abtFields.length; i++) { thing = abtFields[i]; searchInArr = (things[thing] && things[thing].autoSearchIn) || []; for (var j = 0; j < searchInArr.length; j++) { str = window.webRef.metaContent[searchInArr[j]]; if (str) { formatter = things[thing].formatter; if (formatter) str = formatter(str); dom.byId(thing + 'DefaultSpan', refFrame.doc) .innerHTML = idToText['default'] + ': ' + str; break; }			}		}	} // autoFillInfo

function createUI { if (!document.body || !document.body.firstChild) { aux.fatalError('Web page is empty!'); }		var i, id, docFrag = document.createDocumentFragment; var subDiv;

function br { docFrag.appendChild(newEl('br')); }

docFrag.appendChild(newEl('strong', {text: idToText['searchSectionH']})); br; dom.text(idToText['searchSectionIntro'], docFrag); br; br;

var searchThings = refDocData.searchSection.things; var fieldIdEndings = refDocData.searchSection.fieldIdEndings; var fieldSizes = refDocData.searchSection.fieldSizes;

for (i = 0; i < searchThings.length; i++) { dom.text(idToText[searchThings[i] + 'Results'], docFrag); br(docFrag); for (var j = 0; j < fieldIdEndings.length; j++) { //' id = searchThings[i] + fieldIdEndings[j]; ctrls[id] = newEl('input', {					id: id,					size: fieldSizes[j],					css: {backgroundColor: (fieldSizes[j] == 5 ? 'gray' : 'white')}				}); docFrag.appendChild(ctrls[id]); }			br; }

var goButton = newEl('input', {			type: 'button',			value: idToText['searchButton'],			onclick: findContainingEls // doesn't work		}); goButton.onclick = findContainingEls; docFrag.appendChild(goButton); br; br;

docFrag.appendChild(newEl('strong', {text: idToText['resultsH']})); br; dom.text(idToText['resultsSectionIntro'], docFrag); br; br;

for (i = 0; i < searchThings.length; i++) { id = searchThings[i] + 'Results'; dom.text(idToText[id], docFrag); br; ctrls[id] = newEl('select', {id: id}); docFrag.appendChild(ctrls[id]); br; }

br; docFrag.appendChild(newEl('strong', {text: idToText['aboutSiteH']})); br; dom.text(idToText['aboutSiteSectionIntro'], docFrag); br; br; for (var i = 0, fieldId; i < refDocData.aboutSiteFields.length; i++) { fieldId = refDocData.aboutSiteFields[i]; dom.text(idToText[fieldId + '_L'], docFrag); br; ctrls[fieldId] = newEl('input', {id: fieldId}); docFrag.appendChild(ctrls[fieldId]); dom.text(' ', docFrag); docFrag.appendChild(newEl('span', { id: fieldId + 'DefaultSpan', css: {color: '#bbbbbb'} }));			br; }

br; dom.text(idToText['buttonsIntro'], docFrag); br; for (var i = 0, buttonData, button; i < refDocData.buttonSectionButtons.length; i++) { buttonData = refDocData.buttonSectionButtons[i]; button = newEl('input', {				type: 'button',				value: idToText[buttonData.id],				onclick: buttonData.onclick //' doesn't work			}); button.onclick = buttonData.onclick; docFrag.appendChild(button); }

br; br; docFrag.appendChild(newEl('strong', {text: idToText['codeTaH']})); br; ctrls.code = newEl('textarea', {			id: 'codeTA',			cols: 100,			rows: 8		}); docFrag.appendChild(ctrls.code);

refFrame.frame = dom.byId('ref00ref'); if (refFrame.frame) refFrame.frame.style.display = 'none';

refFrame.frame = newEl('iframe', {			id: 'ref01ref',			resizable: 'resizable',			css: {width: '100%', position: 'absolute', zIndex: '2147483647', top: 0, left: 0}		}); document.body.insertBefore(refFrame.frame, document.body.firstChild);

refFrame.win = (refFrame.frame.contentWindow			|| refFrame.frame.contentDocument); refFrame.doc = refFrame.win.document; refFrame.doc.open; refFrame.doc.write('<!DOCTYPE html>\n \n \n Ref \n '			+ ' \n \n '); refFrame.doc.close; refFrame.body = refFrame.doc.body; dom.setStyle(refFrame.body, frameBodyStyleObj); refFrame.body.appendChild(docFrag);

var frameHeight = getDocHeight(refFrame.body, refFrame.doc) + 'px'; refFrame.frame.style.height = frameHeight; subDiv = dom.newEl('div', {			id: 'ref01refDiv',			css: {height: frameHeight}		}); document.body.insertBefore(subDiv, document.body.firstChild);

function getDocHeight(b,D) { return Math.max(				Math.max(b.scrollHeight, D.documentElement.scrollHeight),				Math.max(b.offsetHeight, D.documentElement.offsetHeight)//,				//Math.max(b.clientHeight, D.documentElement.clientHeight)			); }	} // createUI

function findContainingEls { // getElAddr var i, o;		var all = dom.byTagName("*"); var patternsToSearchFor = {}; var things = refDocData.searchSection.things; var idEndings = refDocData.searchSection.fieldIdEndings;

for (i = 0; i < things.length; i++) { var pattern = ''; for (var j = 0; j < idEndings.length; j++) { var id = things[i] + idEndings[j]; if (!refFrame.doc.getElementById(id)) { aux.fatalError("findContainingEls: No element with id " + id); }				var val = aux.trimStr(refFrame.doc.getElementById(id).value); if (val) { val = val .replace(/[-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&') // escape .replace(/\s+/g, '\\s+'); pattern += val + '\\s*'; }			}			if (pattern) { pattern = pattern.slice(0, -3); // removing the final \s* patternsToSearchFor[things[i]] = pattern; }		}

var matchedEls = {}; for (o in patternsToSearchFor) { if (!patternsToSearchFor.hasOwnProperty(o)) continue; matchedEls[o] = []; }

// loop through all elements in the document and add to matchedEls[o] // all elements within which the text string patternsToSearchFor[o] is found, // but only if it's not also found in a child node of the element // ("o" is one of 'title', 'date' and 'authors'). for (i = 0; i < all.length; i++) { var el = all[i]; var str = dom.getText(el); var tagName = el.tagName.toLowerCase;

// replace el's parent node with el in the list of elements (matchedEls[o]) // containing the string str. for (o in patternsToSearchFor) { if (!patternsToSearchFor.hasOwnProperty(o)) continue; if (str && str.search(patternsToSearchFor[o]) > -1) { if (el.parentNode) { var n = -1; // matchedEls[o].indexOf(el.parentNode); for (var ii = 0; ii < matchedEls[o].length; ii++) { if (matchedEls[o][ii] == el.parentNode) { n = ii; break; }						}						if (n > -1) matchedEls[o].splice(n, 1); // remove parent if child has the string }					if (tagName != 'script' && tagName != 'style' && el != 'refFrame') matchedEls[o].push(el); }			}		}

var rules = {}; var content; // Add meta info: title, author/authors, date, og:title, og:site_name, var metaC = window.webRef.metaContent; for (o in patternsToSearchFor) { if (!patternsToSearchFor.hasOwnProperty(o)) continue; for (var address in metaC) { if (!metaC.hasOwnProperty(address)) continue; content = metaC[address]; if (content.search(patternsToSearchFor[o]) > -1) { rules[o] = rules[o] || []; rules[o].push({						addr: address,						textContent: content					}); }			}		}

// from the element references of the elements found above, // find their text "addresses" (similar to CSS selectors) for (o in matchedEls) { if (matchedEls[o].length == 0) continue; rules[o] = rules[o] || [];

for (var i = 0, k = rules[o].length, el, address; i < matchedEls[o].length; i++) { el = matchedEls[o][i]; address = getElAddr(el, 50); // second arg is maximum element depth if (address) rules[o][k+i] = { addr: address, textContent: dom.getText(el) };			}		}

// add results to the drop-down menus in the Results section for (o in rules) { var ctrl = ctrls[o + 'Results']; ctrl.innerHTML = ''; // remove all option's from the drop down menu for (var i = 0, rule, option; i < rules[o].length; i++) { rule = rules[o][i]; option = newEl('option', {					value: rule.addr,					text: aux.shorten(rule.addr) + ' (' + aux.shorten(rule.textContent) + ')'				}); ctrl.appendChild(option); }		}

} // findContainingEls

// returns null if maxRecursion is reached and in the case of other errors function getElAddr(el, maxRecursion) { if (el.id) return '#' + el.id; //window.docSelAll = document.querySelectorAll || docSelAll; document.querySelectorAll=null; var compact = true;//false; // example from novatv.bg : // compact : span.medium.black // not comp: #main_column div div div.news_sidebar.right div span // compact ,querySelectorAll=null; = #main_column div div 4div div // not comp,querySelectorAll=null; = #main_column div div 4div div span // bbc compact = span.date // bbc-noncomp = #main-content div.layout-block-a div span span var parent = el.parentNode;

if (maxRecursion < 0) { prt('WebRef debug info: Element is too deep in document structure? (error code: getElAddr: ' + 'maxRecursion)'); return null; }		maxRecursion--;

var tagName = el.tagName.toLowerCase; var classes = aux.collapseWhitespace(el.getAttribute('class') || '').replace(/ /g, '.'); var nodePlusClasses = tagName + (classes ? '.' + classes : '');

if (parent == document.body || parent == document) return numInParent(el) + tagName;

if (compact) { if (el == dom.byTagName('title')[0]) return 'title';

// if only one h1 tag in document, accept this as a unique id			if (tagName == 'h1' && dom.byTagName('h1').length == 1) return 'h1';

// if in the whole document there is only one element of this type with these classes, // accept that as a unique id for this tag // only for browsers supporting document.querySelectorAll (IE8+) if (document.querySelectorAll) { var selEls; try { selEls = document.querySelectorAll(nodePlusClasses); } catch (e) { aux.error('getElAddr: invalid selector: ' + nodePlusClasses); return null; }				if (classes && selEls.length == 1) return nodePlusClasses; }		}

var thisElAddr = ''; // do not record this tag if parent has the same text content if (!compact || dom.getText(parent) != dom.getText(el)) { var n = numInParent(el); if (n && classes // use classes only if there are siblings w/ same tag name				&& document.querySelectorAll   // and no siblings w/ same tag name & same classes				&& parent.querySelectorAll(nodePlusClasses).length == 1			) thisElAddr = nodePlusClasses; else thisElAddr = n + tagName; // n is '' for 0 }

return getElAddr(parent) + (thisElAddr ? ' ' + thisElAddr : ''); } // getElAddr

function numInParent(el) { var tagName = el.tagName.toLowerCase; if (!el.parentNode) aux.fatalError('NO PARENT! ' + tagName); var elsOfThisType = el.parentNode.getElementsByTagName(tagName); var foundNum = -1; for (var i = 0; i < elsOfThisType.length; i++) { if (elsOfThisType[i] == el) { foundNum = i;				break; }		}		if (foundNum == -1) aux.fatalError('CHILD NOT FOUND IN PARENT!'				+ tagName + ' Total children of this type found = ' + i			);

return (foundNum ? foundNum : ''); } // numInParent

function toCode { var str = '"' + domain + '": {\n'; var arr = refDocData.searchSection.things; for (var i = 0, val, name; i < arr.length; i++) { name = arr[i]; val = ctrls[name + 'Results'].value; if (val) str += '\t"' + name + '": "' + val + '",\n'; }		arr = refDocData.aboutSiteFields; for (var i = 0, val, name; i < arr.length; i++) { name = arr[i]; val = ctrls[name].value; if (val) str += '\t"' + name + '": "' + val + '",\n'; }		if (str.charAt(str.length - 2) == ',') str = str.slice(0, -2); // remove last comma str += "\n}"; ctrls.code.value = str; } // toCode

// shows in the textarea the currently used settings for this site // (by reading the variable siteRefs[domain] or reading from local storage) function loadFromVar { var str = ''; if (!window.webRefSiteData || !webRefSiteData[domain]) { loadFromStorage; return; }

str = '"' + domain + '": {\n'; for (var thing in refDocData.things) if (typeof webRefSiteData[domain][thing] != 'undefined') str += '\t"' + thing + '": "' + webRefSiteData[domain][thing] + '",\n'; str = str.slice(0, -2) + '\n}'; ctrls.code.value = str; }

return function { var setupFrame = dom.byId('ref01ref'); webRef.displayWebRefFrame(false); if (setupFrame) { setupFrame.style.display = 'block'; dom.byId('ref01refDiv').style.display = 'block'; }		else { createUI; autoFillInfo; }	}; });

if (window.webRef && webRef.webRefSetupStartOnLoad) { webRef.webRefSetupStartOnLoad = false; webRef.webRefSetup; }