/****************
 * sitepoint-ref-links.js
 * ------------------
 * Add links to words marked up using the <code> tag to the SitePoint Reference
 * Supports HTML elements, HTML tags, HTML core attributes, CSS properties and Microformats.
 * ------------------
 * Copyright (c) 2008 SitePoint Pty. Ltd. http://www.sitepoint.com/
 *
 * Uses Simon Willison's addLoadEvent - http://simonwillison.net/2004/May/26/addLoadEvent/
 * Version 1.0, May 2008: Matthew Magain mjm@sitepoint.com
 */

var RefLinks =
{
  init: function()
  {
    // Element must be marked up with <code>
    var all_code_elements = document.getElementsByTagName('code');
	for (var j=0; j < all_code_elements.length; j++) 
	{
      if(all_code_elements[j].firstChild && all_code_elements[j].firstChild.nodeValue)
      {
		  if (RefLinks.IsHTMLElement(all_code_elements[j].firstChild.nodeValue)) {
			RefLinks.InsertAnchor('html', all_code_elements[j], 'element');
		  } else if (RefLinks.IsMicroformat(all_code_elements[j].firstChild.nodeValue)) {
			RefLinks.InsertAnchor('html', all_code_elements[j], 'microformat');	  
		  } else if (RefLinks.IsHTMLTag(RefLinks.StripHyphensAndBrackets(all_code_elements[j].firstChild.nodeValue))) {
			RefLinks.InsertAnchor('html', all_code_elements[j], 'tag');
		  } else if (RefLinks.IsHTMLCoreAttribute(all_code_elements[j].firstChild.nodeValue)) {
			RefLinks.InsertAnchor('html', all_code_elements[j], 'attribute');
		  } else if (RefLinks.IsCSSProperty(all_code_elements[j].firstChild.nodeValue)) {
			RefLinks.InsertAnchor('css', all_code_elements[j], 'property');
		  } else if (RefLinks.IsNonStandardCSSProperty(RefLinks.StripHyphensAndBrackets(all_code_elements[j].firstChild.nodeValue))) {
			RefLinks.InsertAnchor('css', all_code_elements[j], 'property');
		  }
	  }
    }
  },

  // Replace current text with appropriate link to the SitePoint Reference
  InsertAnchor: function(sLanguage, aNode, sType) 
  {
    var refURL='http://reference.sitepoint.com/' + sLanguage + '/';
	if (sType == 'attribute') 
	  refURL += 'core-attributes/';
    var aLink = document.createElement('a');
    aLink.href = refURL + RefLinks.StripHyphensAndBrackets(aNode.firstChild.nodeValue.toLowerCase());
	aLink.title = 'Look up the ' + aNode.firstChild.nodeValue + ' ' + sType 
	  + ' in the SitePoint ' + sLanguage.toUpperCase() + ' Reference.';
    var aTextNode = document.createTextNode(aNode.firstChild.nodeValue);
    aLink.appendChild(aTextNode);
	aNode.removeChild(aNode.firstChild);
    aNode.appendChild(aLink);
    aNode.className = "ref-term"; // Blow away any existing classes. A little heavy-handed, perhaps.
  },
  
  // Checks whether the keyword matches an HTML Element
  IsHTMLElement: function(aString) 
  {
    // font tag is missing; the CSS font property gets precedence
    var htmlElements = ['blockquote', 'cite', 'body', 'br', 'center', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html', 'p', 'base', 'link', 'meta', 'script', 'style', 'title', 'dd', 'dir', 'dl', 'dt', 'li', 'menu', 'ol', 'ul', 'a', 'abbr', 'acronym', 'address', 'b', 'basefont', 'bdo', 'big', 'blink', 'code', 'comment', 'del', 'dfn', 'em', 'i', 'ins', 'kbd', 'marquee', 'nobr', 'noscript', 'plaintext', 'pre', 'q', 'rb', 'rbc', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'tt', 'u', 'var', 'wbr', 'xmp', 'button', 'fieldset', 'form', 'input', 'isindex', 'label', 'legend', 'optgroup', 'option', 'select', 'textarea', 'applet', 'area', 'bgsound', 'embed', 'img', 'map', 'noembed', 'object', 'param', 'caption', 'col', 'colgroup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'frame', 'frameset', 'noframes', 'iframe']; 
	for (var i=0; i < htmlElements.length; i++) {
	  if (aString == htmlElements[i])
          return true;
	}
	return false;  
  },

  // Checks whether the keyword matches an HTML element, 
  // once the angle brackets are stripped out
  IsHTMLTag: function(aString) 
  {
    return RefLinks.StripHyphensAndBrackets(RefLinks.IsHTMLElement(aString));
  },
  
  // Checks whether the keyword matches an HTML core attribute
  IsHTMLCoreAttribute: function(aString) 
  {
    var htmlCoreAttributes = ['id', 'class', 'dir', 'lang', 'style'];
	for (var i=0; i < htmlCoreAttributes.length; i++) {
	  if (aString == htmlCoreAttributes[i])
          return true;
	}
	return false;  
  },
  
  // Checks whether the keyword matches a CSS property
  IsCSSProperty: function(aString) 
  {
    var cssProperties = ['height', 'min-height', 'max-height', 'width', 'min-width', 'max-width', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', 'margin', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'padding', 'border-top-color', 'border-top-style', 'border-top-width', 'border-top', 'border-right-color', 'border-right-style', 'border-right-width' ,'border-right', 'border-bottom-color', 'border-bottom-style', 'border-bottom-width', 'border-bottom', 'border-left-color', 'border-left-style', 'border-left-width', 'border-left', 'border-color', 'border-style', 'border-width', 'border', 'outline-color', 'outline-style', 'outline-width', 'outline', 'display', 'position', 'float', 'clear', 'visibility', 'top', 'right', 'bottom', 'left', 'z-index', 'overflow', 'clip', 'list-style-type', 'list-style-position', 'list-style-image', 'list-style', 'table-layout', 'border-collapse', 'border-spacing', 'empty-cells', 'caption-side', 'background-color', 'background-image', 'background-repeat', 'background-position', 'background-attachment', 'background', 'color', 'font-family', 'font-size', 'font-weight', 'font-style', 'font-variant', 'font', 'letter-spacing', 'word-spacing', 'line-height', 'text-align', 'text-decoration', 'text-indent', 'text-transform', 'text-shadow', 'vertical-align', 'white-space', 'direction', 'unicode-bidi', 'content', 'counter-increment', 'counter-reset', 'quotes', 'cursor', 'page-break-before', 'page-break-inside', 'page-break-after', 'orphans', 'widows', 'zoom', 'filter', 'behavior', 'expression',];
	for (var i=0; i < cssProperties.length; i++) {
	  if (aString == cssProperties[i])
          return true;
	}
	return false;
  },

  // Checks whether the keyword matches a CSS property
  IsNonStandardCSSProperty: function(aString) 
  {
    var nonStandardCSSProperties = ['moz-border-radius', 'moz-box-sizing'];
	for (var i=0; i < nonStandardCSSProperties.length; i++) {
	  if (aString == nonStandardCSSProperties[i])
          return true;
	}
	return false;
  },
  
  // Checks whether the keyword matches one of the microformats listed on the SitePoint Reference  
  IsMicroformat: function(aString)
  {
    var microformats = ['hCalendar', 'hCard', 'hReview'];
	for (var i=0; i < microformats.length; i++) {
	  if (aString == microformats[i])
          return true;
	}
	return false;
  },

  // Convert a tag to its corresponding HTML element
  // e.g. <ul> becomes ul.
  StripHyphensAndBrackets: function(aString)
  {
    var resultString = aString;
    var pattern1 = /\<*\>/;
	var pattern2 = /^-/;
    if (pattern1.test(aString))
    {
	  resultString = aString.substring(1, aString.length-1);
    } else if (pattern2.test(aString))
    {
	  resultString = aString.substring(1, aString.length);
    }
	return resultString;
  }
};

// addLoadEvent is already added by another script, so we remove it 
// here to prevent it from being added again.
/* function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
} */

addLoadEvent(RefLinks.init); 