Whizbang.js

The whizbang.js file controls the behavior of the whizbang form and is necessary for it to operate. Here is a detailed explanation of how it all works, including a walkthrough of the javascript file.

There are a number of styled <div> tags on the WhizBang form that are hidden by default. There is a styled "list" of links that looks like a row of tabs. As you click on each tab, the related div containing that part of the form will be shown (or, if currently shown, hidden).

A second feature of the WhizBang form is query formulation. As you type or click, your query is summarized and presented on the right-hand side of the window.

If you need help modifying this system for your own needs, get in touch with us (support AT philologic DOT uchicago DOT edu).

Here is a heavily commented version of the script.

var allids = new Array();

var activeid = "none";

//allids is an array that will hold all ids of the toggleable divs

//active id is a variable to keep track of which toggleable div is currently shown

//if we have a few of these functions avaialble (i.e. we have a good, modern javascript implementation)

//then lets go ahead and use the stylesheet and start the initialization

//if we don't do this, the user will see a barebones but hopefully functional page.

if (document.getElementById && document.getElementsByTagName && document.createTextNode) {

document.write('<link rel="stylesheet" type="text/css" href="whizbang.css" />');

window.onload = initialize;

}

//the initialization function called just above.

function initialize() {

//let's check if the nav bar exists.... if not, we have no business doing anything.

var exists = eval(document.getElementById('nav'));

if (exists) {

var id;

var navbar = document.getElementById('nav');

var navlinks = navbar.getElementsByTagName('a');

//loop through all the links in the navbar

//extract the IDs of the toggleable divs from the href tags

//store those, then add on onclick to show or hide that div

//when that link is clicked.

for (var j = 0; j < navlinks.length; j++) {

allids[j] = navlinks[j].href.match(/#(\w.+)/)[1];

navlinks[j].href = "#";

navlinks[j].onclick = new Function("sshow('" + allids[j] + "');");

}

//see description of this function below

addLabelProperties();

//set up the query description area

document.getElementById("query").innerHTML = '<h2>Your query:</h2><div id="querytext">Enter search criteria to form a new search.</div>';

//add the javascript function to the reset button

document.getElementById("resetbutton").onclick = new Function ("document.forms[0].reset(); hideall(); setActiveTab('none'); formulateQuery();");

//formulate the query

hasquery = formulateQuery();

//we check to see if there is a '#' in the url (which would mean that a tab has previously

//been clicked open). if someone has been clicking the tabs, and we have some values in

//the form, let's open the tab that was last open. we only want to do that if there is

//a query and a tab has been opened before.

if (window.location.href.indexOf("#") > -1 && hasquery == true) {

activeid = GetCookie("philotab");

if (activeid) {

sshow(activeid);

}

}

}

}

//this function sets the classes of the tabs

//depending on if they are the active tab or not.

function setActiveTab(id) {

SetCookie("philotab", id);

//we set a cookie to the last active tab

//this is so when we come back to the page

//for example using the back button

//we know what tab to open if there is a query

var navlinks = document.getElementById("navlister").getElementsByTagName("li");

for (i = 0; i < navlinks.length; i++) {

if (navlinks[i].id == id + "li") {

navlinks[i].className = "activenav";

} else {

navlinks[i].className = "";

}

}

}

//this function actually makes the active tab visible

function sshow(id) {

//if the tab is already shown, hide it, and we have no active tab

if (document.getElementById(id).style.display == "block") {

hideall();

setActiveTab("none");

//otherwise, hide them all, then make the new active one visible.

//set all the classes appropraitely (isn't this done by the setActiveTab function just called?

//perhaps i am being redundant here...)

} else {

hideall();

setActiveTab(id);

var navlinks = document.getElementById("navlister").getElementsByTagName("li");

for (i = 0; i < navlinks.length; i++) {

if (navlinks[i].id == id + "li") {

navlinks[i].className = "activenav";

}

else {

navlinks[i].className = "";

}

}

//setting the display to 'block' is what makes it visible

document.getElementById(id).style.display = 'block';

// document.getElementById(id).style.border = "1px solid #242E55";

}

}

//simple function -- sets the display for the id to 'none', hiding it

function hide(id) {

document.getElementById(id).style.display = 'none';

}

//take all the ids of toggleable tabs and hide them

function hideall() {

for (var i = 0; i < allids.length; i++) {

hide(allids[i]);

}

}

//construct and show the query in the query summary div.

//this is the part you'd have to edit if you want to change

//the arrangement of the divs or add new tabs.

function formulateQuery() {

var query = "";

var subquery = "";

fieldsets = document.getElementsByTagName('fieldset');

//store all of the fieldsets in the document. make sure you are

//keep your fields in a fieldset if you want them put in the query summary

//loop through the fieldsets. for most fieldsets, we have specific ways of

//writing the query based on what's set and what the values are.

//you gotta edit this to add a new tab

for (i = 0; i < fieldsets.length; i++) {

inputs = fieldsets[i].getElementsByTagName('input');

//grab all the inputs in this fieldset.

subquery = "";

//this is an example of one of the fieldsets and how we have to construct the query

//look at each element, write out something appropriate

if (fieldsets[i].parentNode.id == "resultformat") {

if (document.getElementById("OUTPUTTF").checked) {

subquery = "Frequency by <blue>Title</blue>";

} else if (document.getElementById("kwic").checked) {

subquery = "Occurrences <blue>Line by Line [KWIC]</blue>";

} else if (document.getElementById("OUTPUTTFR").checked) {

subquery = "Frequency by <blue>Title</blue> per <blue>10,000</blue>";

} else if (document.getElementById("OUTPUTHEAD").checked) {

subquery = "Frequency by <blue>Head Object</blue>";

} else if (document.getElementById("OUTPUTAF").checked) {

subquery = "Frequency by <blue>Author</blue>";

if (document.getElementById("AFTITLEDISP").checked) {

subquery += ", <blue>(titles hidden)</blue";

}

} else if (document.getElementById("OUTPUTAFR").checked) {

subquery = "Frequency by <blue>Author</blue> per <blue>10,000</blue>";

if (document.getElementById("AFTITLEDISP").checked) {

subquery += ", <blue>(titles hidden)</blue";

}

} else if (document.getElementById("OUTPUTDF").checked || document.getElementById("OUTPUTDFR").checked) {

if (document.getElementById("OUTPUTDF").checked) {

subquery = "Frequency by <blue>Years</blue>, Year Group: ";

} else if (document.getElementById("OUTPUTDFR").checked) {

subquery = "Frequency by <blue>Years</blue>, per <blue>10,000</blue>, Year Group: ";

}

subquery += "<blue>" + document.getElementById("DFPERIOD").options[document.getElementById("DFPERIOD").selectedIndex].text + "</blue>";

if (document.getElementById("DFTITLEDISP").checked) {

subquery += " <blue>(titles hidden)</blue";

}

} else if (document.getElementById("OUTPUTPF").checked) {

subquery = "<blue>Collocation Table</blue> Spanning ";

subquery += "<blue>" + document.getElementById("POLESPAN").options[document.getElementById("POLESPAN").selectedIndex].text + "</blue> words";

if (document.getElementById("POLEFILTER").checked) {

subquery += ", <blue>(filter off)</blue";

}

} else if (document.getElementById("OUTPUTTR").checked) {

subquery = "<blue>Theme-Rheme</blue> Display: ";

subquery += "<blue>" + document.getElementById("THMPRTLIMIT").options[document.getElementById("THMPRTLIMIT").selectedIndex].text + "</blue>";

} else if (document.getElementById("TRSORT").checked) {

subquery = "Sort by <blue>bibliography</blue>, Order by: ";

subquery += "<blue>" + document.getElementById("trsortorder").options[document.getElementById("trsortorder").selectedIndex].text + "</blue>";

} else if (document.getElementById("OUTPUTSK").checked) {

subquery = "<blue>KWIC sort by keyword</blue> and word to its ";

subquery += "<blue>" + document.getElementById("KWSS").options[document.getElementById("KWSS").selectedIndex].text + "</blue>, Display up to ";

subquery += "<blue>" + document.getElementById("KWSSPRLIM").options[document.getElementById("KWSSPRLIM").selectedIndex].text + "</blue> occurrences";

}

} else if (fieldsets[i].parentNode.id == "searchopt") {

if (document.getElementById("conjpro").checked) {

subquery = "Phrase separated by <blue>" + document.getElementById("phrasedistance").value + "</blue> words";

} else if (document.getElementById("cj6").checked) {

subquery = "Proximity Searching in the <blue>Same Sentence</blue>"

} else if (document.getElementById("cj5").checked) {

subquery = "Proximity Searching in the <blue>Same Paragraph</blue>";

}

//we skip main bib.... that is taken care of under bibliographic

//for the others, we just use the names on the labels and the values to make a simple

//writeup

} else if (fieldsets[i].parentNode.id != "mainbib") {

for(j = 0; j < inputs.length; j++) {

if (inputs[j].value != '' && inputs[j].type == "text" && inputs[j].value != "Terms") {

subquery += inputs[j].label + " <blue>'" + inputs[j].value + "'</blue>, ";

}

}

if (fieldsets[i].parentNode.id == "bibfields") {

inputs = document.getElementById('mainbibfs').getElementsByTagName('input');

for(j = 0; j < inputs.length; j++) {

if (inputs[j].value != '' && inputs[j].type == "text" && inputs[j].value != "Terms") {

subquery += inputs[j].label + " <blue>'" + inputs[j].value + "'</blue>, ";

}

}

}

}

//if we found something in this fieldset, we add it to the main query

//with some specific extras if certain things are certain ways...

if (subquery != "") {

//if there is something in the main search input, and the similarity search is on, say so

if (fieldsets[i].parentNode.id == "basicform") {

if (document.getElementById("etsim").checked) {

subquery += " and <blue>similar words</blue>";

}

//if we have bibliographic stuff, show the bibsort options

} else if (fieldsets[i].parentNode.id == "bibfields") {

subquery += "sort by <blue>" + document.getElementById("sortorder").options[document.getElementById("sortorder").selectedIndex].text + "</blue>";

}

//kill trailing spaces

subquery = subquery.replace(/,\s$/, "");

//don't link maincontents, otherwise make a link to show that tab's visibility

if (fieldsets[i].parentNode.id != "maincontents") {

//query += "<a href='#" + fieldsets[i].parentNode.id + "' onClick='show(this);' >" + fieldsets[i].title + "</a>: " + subquery + "<br>";

query += "<a href='javascript:sshow(\"" + fieldsets[i].parentNode.id + "\")'>" + fieldsets[i].title + "</a>: " + subquery + "<br>";

} else {

query += "<b>" + fieldsets[i].title + "</b>: " + subquery + "<br>";

}

}

}

//no query? ok, show the default

if (query == "") {

document.getElementById("querytext").innerHTML = "Enter search criteria to form a new search.";

return false;

//otherwise, show the query.

} else {

document.getElementById("querytext").innerHTML = query;

return true;

}

}

//for each labeled input, we need to add an appropriate handler to

//update the query when that value changes

function addLabelProperties() {

if ( typeof document.getElementsByTagName == 'undefined' ) return;

var labels = document.getElementsByTagName( "label" );

var label, i = j = 0;

var elem;

while ( label = labels[i++] ) {

if ( typeof label.htmlFor == 'undefined' ) return;

elem = document.getElementById(label.htmlFor);

if ( typeof elem == 'undefined' ) {

self.devError( [label.htmlFor], 'noLabel' );

} else if ( typeof elem.length != 'undefined' && elem.length > 1 && elem.nodeName != 'SELECT' ) {

for ( j = 0; j < elem.length; j++ ) {

elem.item( j ).label = label;

}

}

elem.label = label.innerHTML;

if (elem.type == "text" ) {

elem.onkeyup = function () { formulateQuery() };

} else if (elem.type == "radio" || elem.type == "checkbox") {

elem.onclick = function () { formulateQuery() };

} else if (elem.type == "select-one") {

elem.onchange = function () { formulateQuery(); };

}

}

}