Category Archives: JavaScript

Auto-generated Line Numbers

I’ve been using the Google Code Prettify plugin for my code samples, which is nice for syntax highlighting, but still lacks something I think every code sample should have: line numbers.

I didn’t want to have to add them manually to every code sample I put up, so I came up with a quick solution to auto-generate line numbers with JavaScript. Because I wanted a quick solution, this code uses jQuery for all the heavy lifting.

Here it is, complete with line numbers:

$(document).ready(
  function() {
    $("pre.prettyprint").each(
      function() {
        var code = $(this).html();
        code = escape(code);
        // %0A is a line feed, %0D is a carriage return
        if (code.indexOf("%0D%0A") > -1) {
          linecount = code.match(/%0D%0A/g).length;
        }
        else if (code.indexOf("%0A") > -1) {
          linecount = code.match(/%0A/g).length;
        }
        else if (code.indexOf("%0D") > -1) {
          linecount = code.match(/%0D/g).length;
        }
        code = unescape(code);
        var linenumbers = 1;
        for (i = 1; i < linecount; i++) {
          linenumbers += "<br />" + (i + 1);
        }
        $(this).before("<pre class=\"linenumbers\">" + linenumbers + "</pre>")
      }
    );
  }
);

And then this little bit of CSS so it matches the prettify.css that comes with the Google Code Prettify plugin:

pre.linenumbers {
  width: auto;
  background-color: #EEE;
  border-width: 1px 0 1px 1px;
  border-style: solid;
  border-color: #888;
  float: left;
  margin: 0;
  padding: 2px 4px;
  color: #888;
  text-align: right;
}

I purposefully keep the numbers in a separate element from the code, so they don’t interfere when you try to copy the code samples to your clipboard.

And there you have it. Now I can easily reference specific line numbers in my code.

DOM Scripting External Links

Here’s the JavaScript:

function externalLinks() {
  var domainList = new Array("andycouch.com", "google.com");  // Your domain(s).
  // Links to anything on these domains are considered internal.
  // Enclose each domain in quotes, separated by a comma.  (e.g. "domain1", "domain2")
  // You do not need to list sub-domains.  This function already assumes all sub-domains
  // are internal.

  // Open external links in a new window?  true = yes, false = no
  var newWindow = true;

  // Add a special class to external links?  true = yes, false = no
  var addClass = true;
  // Class name for external links.
  var extClass = "external";

  // Add a warning dialog to external links?  true = yes, false = no
  var addWarning = true;
  // Text for warning dialog.
  var warning = "You are about to leave my site.";

  if (!document.getElementsByTagName) return false;
  var anchorList = document.getElementsByTagName("a");
  var protocolStart = "^http[s]?:\/\/";
  var protocol = new RegExp(protocolStart, "i");
  var domains = "";
  for (var i=0; i < domainList.length; i++) {
    domains += "(" + domainList[i] + ")";
    if (i < (domainList.length - 1)) {
      domains += "|";
    }
  }
  var mySites = new RegExp(protocolStart + "([a-z0-9-\.]*\.)?" + domains, "i");

  for (var i=0; i < anchorList.length; i++) {
    if (anchorList[i].href.match(protocol) && !anchorList[i].href.match(mySites)) {
      if (newWindow) anchorList[i].setAttribute("target", "_blank");
      if (addClass) anchorList[i].className=extClass;
      if (addWarning) anchorList[i].onclick=function() {
        var leave = window.confirm(warning);
        return leave;
      }
    }
  }
}
window.onload=externalLinks;

Here’s some extra CSS:

a.external {
  padding-right: 17px;
  background: url("/images/icon_globe.png") right center no-repeat;
}

I’ll add some more text to this entry eventually.