JROB JROB - 6 months ago 11
Javascript Question

Using javascript to list hyperlink URL's as footnotes

I am creating a print stylesheet, and I would like to put a numbered superscript next to each hyperlink with a footnote at the bottom of the page with the URL. This would make for a much cleaner printed page while still allowing you to view the hyperlinked URL's.

My needs are :


  • Insert superscript of a number in numerical order where the hyperlink appears

  • Take into account repeating URL's (if same URL appears twice, reuse the number)

  • Specify a parent element ID to use (don't automatically do the entire page)



Here would be an example:

<p>I may link to <a href="http://www.google.com">Google</a>,
then to <a href="http://www.yahoo.com">Yahoo</a>, then to
<a href="http://www.google.com">Google again</a>. Then finally,
I'll throw in <a href="http://www.bing.com">Bing</a> just for kicks.</p>


So, the Javascript should change this to display as:




I may link to Google1, then to Yahoo2, then to Google again1. Then finally, I'll throw in Bing3 just for kicks.

LINKS:


  1. http://www.google.com

  2. http://www.yahoo.com

  3. http://www.bing.com






I found some old Javascript snippet from 2005 on this site, but it seems horribly outdated and cumbersome.

function footnoteLinks(containerID,targetID) {
if (!document.getElementById ||
!document.getElementsByTagName ||
!document.createElement) return false;
if (!document.getElementById(containerID) ||
!document.getElementById(targetID)) return false;
var container = document.getElementById(containerID);
var target = document.getElementById(targetID);
var h2 = document.createElement('h2');
addClass.apply(h2,['print-onlyX']);
var h2_txt = document.createTextNode('Links');
h2.appendChild(h2_txt);
var coll = container.getElementsByTagName('*');
var ol = document.createElement('ol');
addClass.apply(ol,['print-onlyX']);
var myArr = [];
var thisLink;
var num = 1;
for (var i=0; i<coll.length; i++) {
var thisClass = coll[i].className;
if ( coll[i].getAttribute('href') ||
coll[i].getAttribute('cite') ) {
thisLink = coll[i].getAttribute('href') ? coll[i].href : coll[i].cite;
var note = document.createElement('sup');
addClass.apply(note,['print-onlyX color-light']);
var note_txt;
var j = inArray.apply(myArr,[thisLink]);
if ( j || j===0 ) {
note_txt = document.createTextNode(j+1);
} else {
var li = document.createElement('li');
var li_txt = document.createTextNode(thisLink);
li.appendChild(li_txt);
ol.appendChild(li);
myArr.push(thisLink);
note_txt = document.createTextNode(num);
num++;
}
note.appendChild(note_txt);
if (coll[i].tagName.toLowerCase() == 'blockquote') {
var lastChild = lastChildContainingText.apply(coll[i]);
lastChild.appendChild(note);
} else {
coll[i].parentNode.insertBefore(note, coll[i].nextSibling);
}
}
}
target.appendChild(h2);
target.appendChild(ol);
addClass.apply(document.getElementsByTagName('html')[0],['noted']);
return true;
}
window.onload = function() {
footnoteLinks('content-main','content-main');
}


if(Array.prototype.push == null) {
Array.prototype.push = function(item) {
this[this.length] = item;
return this.length;
};
};

if (!Function.prototype.apply) {
Function.prototype.apply = function(oScope, args) {
var sarg = [];
var rtrn, call;
if (!oScope) oScope = window;
if (!args) args = [];
for (var i = 0; i < args.length; i++) {
sarg[i] = "args["+i+"]";
};
call = "oScope.__applyTemp__(" + sarg.join(",") + ");";
oScope.__applyTemp__ = this;
rtrn = eval(call);
oScope.__applyTemp__ = null;
return rtrn;
};
};
function inArray(needle) {
for (var i=0; i < this.length; i++) {
if (this[i] === needle) {
return i;
}
}
return false;
}
function addClass(theClass) {
if (this.className != '') {
this.className += ' ' + theClass;
} else {
this.className = theClass;
}
}
function lastChildContainingText() {
var testChild = this.lastChild;
var contentCntnr = ['p','li','dd'];
while (testChild.nodeType != 1) {
testChild = testChild.previousSibling;
}
var tag = testChild.tagName.toLowerCase();
var tagInArr = inArray.apply(contentCntnr, [tag]);
if (!tagInArr && tagInArr!==0) {
testChild = lastChildContainingText.apply(testChild);
}
return testChild;
}


Is there a cleaner method of doing this? Seems like a lot of that old Javascript can be reduced by using jQuery.

Answer

check this.

(function($) {

  // init link's hash map
  var links = {};

  // init function named format
  // this method will format all a elements in $contianer
  var format = function($container) {
    // sup started by 1
    var index = 1;
    $container.find('a').each(function() {
      // href is map key, sup index is value
      links[$(this).attr('href')] = links[$(this).attr('href')] || index++;

      // replace the a tag inline with text and sup
      $(this).replaceWith($(this).text() + '<sup>' + links[$(this).attr('href')] + '</sup>');
    });

    // create link list
    var $list = $('<ol><ol>');
    Object.keys(links).forEach(function(link) {
      // append each link to this list
      $list.append('<li><a href="' + link + '">' + link + '</a></li>');
    })

    // append this list to $container
    $container.append($list);
  }

  $(document).ready(function() {
    // call this function
    format($('#result'));
  });
})(jQuery)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>
  I may link to <a href="http://www.google.com">Google</a>, then to <a href="http://www.yahoo.com">Yahoo</a>, then to <a href="http://www.google.com">Google again</a>. Then finally, I'll throw in <a href="http://www.bing.com">Bing</a> just for kicks.
</p>

<div id="result">
  <p>
    I may link to <a href="http://www.google.com">Google</a>, then to <a href="http://www.yahoo.com">Yahoo</a>, then to <a href="http://www.google.com">Google again</a>. Then finally, I'll throw in <a href="http://www.bing.com">Bing</a> just for kicks.
  </p>
</div>

Comments