Corey Mwamba

testbed → JavaScript Rendering of...

JavaScript Rendering of References for Quotations and Paraphrases

The cite attribute is not presented to the reader by many browsers, even though it can hold important information. Citr.js is JavaScript that exposes this information along with the title attribute in blockquote and q elements to create meaningful references. Citr.js is made available under the GNU Affero General Public Licence and is on Github.

You can read a full explanation but here I'll present the code. It's actually pretty basic.

Basic workings

The JavaScript

  1. looks for blockquote and q elements;
  2. determines the class(es) of the found elements;
  3. extracts the url from the cite attribute and text from the title attribute; and then
  4. presents these attributes as (possibly hyperlinked) citations, according to the set class.

I needed a method of finding the class name and luckily, Code Tricks provided: and the InsertAfter method is from Stack Overflow.

function getElementByClass (className, parent) {
  parent || (parent = document);
  var descendants = parent.getElementsByTagName('*'), i=-1, e, result=[];
  while (e=descendants[++i]) {
    ((' '+(e['class']||e.className)+' ').indexOf(' '+className+' ') > -1) && result.push(e);
  }
  return result;
}

function insertAfter(referenceNode, newNode) {
    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}


var footnotes = getElementByClass('footnote');
var marginalia = getElementByClass('marginalia');
var harvard = getElementByClass('harvard');
var indirect =  getElementByClass('indirect');
var bq = document.getElementsByTagName('blockquote');
var iq = document.getElementsByTagName('q');

for (var i = 0; i < bq.length; i++) {
			var quoteRef = bq[i].getAttribute('cite');
			var quoteTitle = bq[i].getAttribute('title');
			// we only need to create a citation if there's a reference or a title 
			if (quoteRef || quoteTitle) {
				var quoteCite  = document.createElement('cite');
				if (quoteRef && quoteTitle) {
					var refLink = document.createElement('a');
					refLink.href = quoteRef;
					refLink.innerText = quoteTitle;
					quoteCite.appendChild(refLink);
				}
				else {
					quoteCite.innerText = quoteTitle; 
				}
			if (bq[i].className.indexOf('footnote') < 0) {
			bq[i].appendChild(quoteCite);
			}
			}
		}

	

		for (var i = 0; i < indirect.length; i++) {
			var quote = indirect[i];
			quote.style='quotes: none';
		}
		if (footnotes) {
			var footList = document.createElement('ol');	
		}
		
			for (var i = 0; i < harvard.length; i++) {
				var quote = harvard[i];
				var quoteCite  = document.createElement('cite');
				var quoteRef = quote.getAttribute('cite');
				var quoteTitle = quote.getAttribute('title');
				quoteCite.innerHTML = ' (';
				if (quoteRef && quoteTitle) {
					var quoteLink = document.createElement('a');
					quoteLink.setAttribute('href',quoteRef);
					quoteLink.innerHTML = quoteTitle;
				}
				else {
					var quoteLink = document.createTextNode(quoteTitle); 
				}
				quoteCite.appendChild(quoteLink);
				quoteCite.innerHTML +=  ')';
				insertAfter(quote,quoteCite);
			}
			
			for (var i = 0; i < footnotes.length; i++) {
				var quote = footnotes[i];
				var quoteAft = document.createElement('sup');
				quoteAft.innerHTML = '[';
				var aftLink = document.createElement('a');
				quoteAft.appendChild(aftLink);
				aftLink.setAttribute('href', '#cite-' + (i + 1));
				aftLink.innerText = i + 1;
				quoteAft.appendChild(aftLink);
				quoteAft.innerHTML += ']';
                                if (quote.nodeName == 'Q') {
					insertAfter(quote,quoteAft);
				}
				else if (quote.nodeName == 'BLOCKQUOTE')  {
					var lastPara = quote.lastChild;
					if (lastPara.nodeName == '#text') {
						var ele = lastPara.previousSibling;
						ele.appendChild(quoteAft);
					}
					else { 
						lastPara.appendChild(quoteAft); 
						}
				}
			
				
				var quoteRef = quote.getAttribute('cite');
				var quoteTitle = quote.getAttribute('title');
				var quoteCite  = document.createElement('li');
				quoteCite.value = i + 1;
				quoteCite.id = 'cite-' + quoteCite.value;
				if (quoteRef && quoteTitle) {
					var quoteLink = document.createElement('a');
					quoteLink.setAttribute('href',quoteRef);
					quoteLink.innerHTML = quoteTitle;
				}
				else {
					var quoteLink = document.createTextNode(quoteTitle); 
				}
				quoteCite.appendChild(quoteLink);
				footList.appendChild(quoteCite);
			}

			for (var i = 0; i < marginalia.length; i++) {
				var quote = marginalia[i];
				var  quoteParent = quote.parentNode;
				//modify this line to get the style that you want
				quoteParent.style = 'display: inline-block; width: 70%; vertical-align: text-top; margin-top: 0.5em';
				var quoteRef = quote.getAttribute('cite');
				var quoteTitle = quote.getAttribute('title');
				//this does not have to be an aside if you don't want - it could be a <div>
				var quoteCite  = document.createElement('aside');
				//modify this line to get the style that you want
				quoteCite.style = 'width: 20%; display: inline-block; margin-left: 1.5em; vertical-align: text-top; margin-top:0.5em;text-align: left; font-size: 0.7em';	
				quoteCite.id = 'marginnote-' + (i +1);
				if (quoteRef && quoteTitle) {
					var quoteLink = document.createElement('a');
					quoteLink.setAttribute('href',quoteRef);
					quoteLink.innerHTML = quoteTitle;
				}
				else {
					var quoteLink = document.createTextNode(quoteTitle); 
				}
				quoteCite.appendChild(quoteLink);				
				insertAfter(quoteParent,quoteCite);			
			}


		
		
		if (footnotes.length) {
			var bodyFoot = document.createElement('footer');

			bodyFoot.appendChild(footList);
			var footHeading = document.createElement('h2');
			footHeading.innerText = 'References';
			bodyFoot.appendChild(footHeading);
			bodyFoot.appendChild(footList);
			document.body.appendChild(bodyFoot);
		}