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('\n\n\nRef\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();

}