// 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<html>\n<head>\n<title>Ref</title>\n</head>'
+ '<body>\n</body>\n</html>');
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();
}