////////////////////////////////////////////////////////////////////////
// This file is the site's main JS file.  All code runs through here. //
////////////////////////////////////////////////////////////////////////

// jquery.jsonp 2.1.4 (c)2010 Julian Aubourg | MIT License
// http://code.google.com/p/jquery-jsonp/
(function(e,b){function d(){}function t(C){c=[C]}function m(C){f.insertBefore(C,f.firstChild)}function l(E,C,D){return E&&E.apply(C.context||C,D)}function k(C){return/\?/.test(C)?"&":"?"}var n="async",s="charset",q="",A="error",r="_jqjsp",w="on",o=w+"click",p=w+A,a=w+"load",i=w+"readystatechange",z="removeChild",g="<script/>",v="success",y="timeout",x=e.browser,f=e("head")[0]||document.documentElement,u={},j=0,c,h={callback:r,url:location.href};function B(C){C=e.extend({},h,C);var Q=C.complete,E=C.dataFilter,M=C.callbackParameter,R=C.callback,G=C.cache,J=C.pageCache,I=C.charset,D=C.url,L=C.data,P=C.timeout,O,K=0,H=d;C.abort=function(){!K++&&H()};if(l(C.beforeSend,C,[C])===false||K){return C}D=D||q;L=L?((typeof L)=="string"?L:e.param(L,C.traditional)):q;D+=L?(k(D)+L):q;M&&(D+=k(D)+encodeURIComponent(M)+"=?");!G&&!J&&(D+=k(D)+"_"+(new Date()).getTime()+"=");D=D.replace(/=\?(&|$)/,"="+R+"$1");function N(S){!K++&&b(function(){H();J&&(u[D]={s:[S]});E&&(S=E.apply(C,[S]));l(C.success,C,[S,v]);l(Q,C,[C,v])},0)}function F(S){!K++&&b(function(){H();J&&S!=y&&(u[D]=S);l(C.error,C,[C,S]);l(Q,C,[C,S])},0)}J&&(O=u[D])?(O.s?N(O.s[0]):F(O)):b(function(T,S,U){if(!K){U=P>0&&b(function(){F(y)},P);H=function(){U&&clearTimeout(U);T[i]=T[o]=T[a]=T[p]=null;f[z](T);S&&f[z](S)};window[R]=t;T=e(g)[0];T.id=r+j++;if(I){T[s]=I}function V(W){(T[o]||d)();W=c;c=undefined;W?N(W[0]):F(A)}if(x.msie){T.event=o;T.htmlFor=T.id;T[i]=function(){/loaded|complete/.test(T.readyState)&&V()}}else{T[p]=T[a]=V;x.opera?((S=e(g)[0]).text="jQuery('#"+T.id+"')[0]."+p+"()"):T[n]=n}T.src=D;m(T);S&&m(S)}},0);return C}B.setup=function(C){e.extend(h,C)};e.jsonp=B})(jQuery,setTimeout);

/*******JQUERY UI IMAGE LOADER PLUGIN v1.4 ************
*	by alan clarke
*	created: 6 Apr 2011
*	last update: 7 May 2011
*	alan@staticvoid.info
* http://staticvoid.info/imageLoader/
*************************************************/
(function($){$.widget("ui.imageLoader",{options:{async:true,images:[]},total:0,_init:function(){var self=this;var i;self.total++;self.loaded=0;self.data=[];self.stats={loaded:0,errored:0,allcomplete:false};if(typeof self.options.images==='string'){var images=[];$.map($(self.options.images),function(el,i){images.push($(el).attr('src'));});self.options.images=images;}
for(i=0;i<self.options.images.length;i++){self.data.push({init:false,complete:false,error:false,src:self.options.images[i],img:new Image(),i:i});}
for(i=0;((i<self.data.length)&&((self.options.async===true||i===0)||i<parseInt(self.options.async,10)));i++){self._loadImg(i);}
return self;},_loadImg:function(i){var self=this;if(i!==false&&i<self.data.length){if(!self.data[i].init){self.data[i].init=true;self._trigger("start",null,{i:i,data:self.getData()});setTimeout(function(){self.data[i].img.onerror=function(){self.loaded++;self.stats.errored++;self.data[i].error=true;self._trigger("error",null,{i:i,data:self.getData()});self._complete(i);};self.data[i].img.onload=function(){if(self.data[i].img.width<1){return self.data[i].img.onerror();}
self.loaded++;self.stats.loaded++;self.data[i].complete=true;self._trigger("complete",null,{i:i,data:self.getData()});self._complete(i);};self.data[i].img.src=self.data[i].src;},1);}}},_complete:function(i){var self=this;if(!self.options.async||typeof self.options.async==="number"){var next=self._next(i);self._loadImg(next);}
if(self.loaded===self.data.length){self._trigger("allcomplete",null,self.getData());self.stats.allcomplete=true;}},_next:function(j){var self=this;var i;for(i=0;i<self.data.length;i++){if(i!==j&&!self.data[i].init){return i;}}
return false;},getData:function(){return $.extend(true,[],this.data);},getStats:function(){return $.extend(true,[],this.stats);},destroy:function(){$.Widget.prototype.destroy.apply(this,arguments);}});})(jQuery);

// Generic Cookie handling routines.  Don't make fun of me, these are from
// http://www.w3schools.com/js/js_cookies.asp.
function setCookie(c_name,value,exdays) {
	var exdate=new Date();
	exdate.setDate(exdate.getDate() + exdays);
	var c_value = escape(value) + ((exdays===null) ? "" : "; expires="+exdate.toUTCString());
	document.cookie=c_name + "=" + c_value + ";path=/";
}

/**
*  Base64 encode / decode
*  http://www.webtoolkit.info/
**/
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(input){var output="";var chr1,chr2,chr3,enc1,enc2,enc3,enc4;var i=0;input=Base64._utf8_encode(input);while(i<input.length){chr1=input.charCodeAt(i++);chr2=input.charCodeAt(i++);chr3=input.charCodeAt(i++);enc1=chr1>>2;enc2=((chr1&3)<<4)|(chr2>>4);enc3=((chr2&15)<<2)|(chr3>>6);enc4=chr3&63;if(isNaN(chr2)){enc3=enc4=64;}else if(isNaN(chr3)){enc4=64;}
output=output+
this._keyStr.charAt(enc1)+this._keyStr.charAt(enc2)+
this._keyStr.charAt(enc3)+this._keyStr.charAt(enc4);}
return output;},decode:function(input){var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(i<input.length){enc1=this._keyStr.indexOf(input.charAt(i++));enc2=this._keyStr.indexOf(input.charAt(i++));enc3=this._keyStr.indexOf(input.charAt(i++));enc4=this._keyStr.indexOf(input.charAt(i++));chr1=(enc1<<2)|(enc2>>4);chr2=((enc2&15)<<4)|(enc3>>2);chr3=((enc3&3)<<6)|enc4;output=output+String.fromCharCode(chr1);if(enc3!=64){output=output+String.fromCharCode(chr2);}
if(enc4!=64){output=output+String.fromCharCode(chr3);}}
output=Base64._utf8_decode(output);return output;},_utf8_encode:function(string){string=string.replace(/\r\n/g,"\n");var utftext="";for(var n=0;n<string.length;n++){var c=string.charCodeAt(n);if(c<128){utftext+=String.fromCharCode(c);}
else if((c>127)&&(c<2048)){utftext+=String.fromCharCode((c>>6)|192);utftext+=String.fromCharCode((c&63)|128);}
else{utftext+=String.fromCharCode((c>>12)|224);utftext+=String.fromCharCode(((c>>6)&63)|128);utftext+=String.fromCharCode((c&63)|128);}}
return utftext;},_utf8_decode:function(utftext){var string="";var i=0;var c=0;var c1=0;var c2=0;var c3=0;while(i<utftext.length){c=utftext.charCodeAt(i);if(c<128){string+=String.fromCharCode(c);i++;}
else if((c>191)&&(c<224)){c2=utftext.charCodeAt(i+1);string+=String.fromCharCode(((c&31)<<6)|(c2&63));i+=2;}
else{c2=utftext.charCodeAt(i+1);c3=utftext.charCodeAt(i+2);string+=String.fromCharCode(((c&15)<<12)|((c2&63)<<6)|(c3&63));i+=3;}}
return string;}};


function getCookie(c_name) {
	var i;
	var x;
	var y;
	var ARRcookies = document.cookie.split(";");
	
	for (i = 0; i < ARRcookies.length; i++) {
	  x = ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
	  y = ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
	  x = x.replace(/^\s+|\s+$/g,"");
	  
	  if (x === c_name) {
	    return unescape(y);
	  }
	}
}

function removeCookie(c_name) {
	setCookie(c_name, 'FALSE', -10);
}

// Site wide Lightboxing, courtesy of http://fancybox.net/
$(document).ready(function() {
	// Start: Fancybox-Images
  // Simply handles image lightboxing
  $("a.image.lightbox").fancybox({
    'transitionIn' : 'elastic'
    , 'transitionOut' : 'elastic'
    , 'speedIn' : 400
    , 'speedOut' : 200
    , 'titlePosition' : 'inside'
    , 'cyclic' : 'true'
  });
  // End: Fancybox-Images

	// Start: Fancybox-Video
  // Handles video, currently supports Youtube and Vimeo.
  // Opens and autoplays the video.
  $("a.fancyVideo").click(function() {
    var myHREF = this.href;
		var myType = 'swf';
		
    // If this is a youtube video, update the HREF appropriately
    if(myHREF.toLowerCase().indexOf('youtube') >= 0) {
      myHREF = this.href.replace(new RegExp("watch\\?v=", "i"), 'v/') + '&autoplay=1';
      myType = 'swf';
    }
    // If this is a vimeo video, update the HREF appropriately
    if(myHREF.toLowerCase().indexOf('vimeo') >= 0) {
      myHREF = this.href.replace(new RegExp("([0-9])","i"),'moogaloop.swf?clip_id=$1') + '&autoplay=1';
      myType = 'swf';
    }
    // If this is a dailymotion video, update the HREF appropriately    
    if(myHREF.toLowerCase().indexOf('dailymotion') >= 0) {
      myHREF = this.href.split('?')[0].replace(new RegExp('/video/(.*)', 'i'), '/embed/video/$1') + '?autoplay=1&enableApi=1';
      myType = 'iframe';
    }

    $.fancybox({
      'padding'   : 0,
      'autoScale'   : false,
      'transitionIn'  : 'elastic',
      'transitionOut' : 'elastic',
      'speedIn' : 400,
      'speedOut' : 200,
      'title'     : this.title,
      'width'   : 680,
      'height'    : 495,
      'href'      : myHREF,
      'type'      : myType,
      'swf'     : {
        'wmode'   : 'transparent',
        'allowfullscreen' : 'true'
      }
    });

    return false;
  });
	// END: Fancybox-Video
});

// Article level link cleanup technology, helps fix the
// incorrectly entered links in the content.
$(document).ready(function() {
	// Establish our domain at the 2nd level (xxxxxx.yyy, without any www. or such nonsense)
	var domainRoot = document.domain;
	var domainArr = domainRoot.split('.');
	domainRoot = domainArr[domainArr.length - 2] + '.' + domainArr[domainArr.length - 1];
	
	// If the link is an on-domain link, make sure it has not TARGET= attribute
	$("#articleBody a[href*='" + domainRoot + "'], .dailymashup a[href*='" + domainRoot + "']").each(function() {
      $(this).attr('target', '');
  });
  
  // If it is offsite, make sure it has TARGET="_blank", also make sure the
  // HREF value begins with at least http://
  // Also, outbound links are now tracked via the click event
	$("#articleBody a:not([href*='" + domainRoot + "']), .dailymashup a:not([href*='" + domainRoot + "'])").each(function() {
			if(typeof $(this).attr('href') !== 'undefined') {
				if($(this).attr('href').indexOf('.') >= 0 && $(this).attr('href').indexOf('/') !== 0) {
					// If we are missing the leading http://, put it in the URL
					if($(this).attr('href').indexOf('http') != 0) {
						$(this).attr('href','http://' + $(this).attr('href'));
					}
					
					// Force the target="_blank" attribute
		      $(this).attr('target', '_blank');
		      
		      // Last we add the needed click event to track outbound link usage.
		      $(this).click(function() {
						_gaq.push(['_trackEvent', 'Outbound Link', 'Click', $(this).attr('href')]);
					});
				}
			}
  });
});

// This script nicely truncates the additionalFeaturedStories preview texts.
function site_sanitizeLandingFeatured() {
  var titleHeight = 0;
  var sourceText = '';

	// First we need to show the blocks in order to calculate values based on their contents.
  $('div#additionalFeaturedStories').show();
  $('div#additionalFeaturedAdBlock').show();

	// Loop over every block of preview text
  $('div.additionalFeaturedStoryPreviewText p.previewText').each(function() {
		// Show this current preview text's parent div container
    $(this).parent().parent().show();

    titleHeight = $(this).prev().outerHeight();
    sourceText = $(this).html();
		
		// If the element being inspected is the DailyMashup section we need to use one
		// set of string lengths.  Anything else gets a seperate set of number.
		if($(this).hasClass('previewTextMashup')) {
			// Calculate the length of the preview text based on the height of it's header text
	    if(titleHeight >= 25 && titleHeight < 42) // 1 Header Line
	    { sourceText = sourceText.replace(/^(.{125}[^\s]*).*/, "$1").replace(/^\s+|\s+$/g,"");}
	    else if(titleHeight >= 42 && titleHeight < 62) // 2 Header Line
	    { sourceText = sourceText.replace(/^(.{95}[^\s]*).*/, "$1").replace(/^\s+|\s+$/g,"");}
	    else if(titleHeight >= 62 && titleHeight < 80) // 3 Header Line
	    { sourceText = sourceText.replace(/^(.{55}[^\s]*).*/, "$1").replace(/^\s+|\s+$/g,"");}
	    else if(titleHeight >= 80) // 4 Header Line
	    { sourceText = ""; }
		}
		else {
			// Calculate the length of the preview text based on the height of it's header text
	    if(titleHeight >= 25 && titleHeight < 42) // 1 Header Line
	    { sourceText = sourceText.replace(/^(.{170}[^\s]*).*/, "$1").replace(/^\s+|\s+$/g,"");}
	    else if(titleHeight >= 42 && titleHeight < 62) // 2 Header Line
	    { sourceText = sourceText.replace(/^(.{140}[^\s]*).*/, "$1").replace(/^\s+|\s+$/g,"");}
	    else if(titleHeight >= 62 && titleHeight < 80) // 3 Header Line
	    { sourceText = sourceText.replace(/^(.{100}[^\s]*).*/, "$1").replace(/^\s+|\s+$/g,"");}
	    else if(titleHeight >= 80) // 4 Header Line
	    { sourceText = ""; }
    }

    if(sourceText !== "") {
      // Test for and remove non-character results
      var testForNonChar = new RegExp(/\W/g);
      if(testForNonChar.test(sourceText.charAt(sourceText.length -1)))
      { sourceText = sourceText.substring(0, sourceText.length -1); }

      sourceText = sourceText + '&#8230';
    }
    $(this).html(sourceText);
    $(this).show();
  });
}

// Extends jQuery to provide a NY Times like Read-More  on Article pages
// https://github.com/xaviershay/nytimes-
// 2011-NOV-01 Updated to latest version
(function ($) {
  jQuery.fn.slidebox = function() {
    var slidebox = this;
    var originalPosition = slidebox.css('right');
    var open = false;

    /* GA tracking */
    var track = function(label) {
      return _gaq.push(['_trackEvent', 'Slidebox', label]);
    }
    var boxAnimations;

    if (Modernizr.cssanimations) {
      boxAnimations = {
        open:  function() { slidebox.addClass('open'); },
        close: function() { slidebox.removeClass('open'); },
      }
    } else {
      boxAnimations = {
        open: function() {
          slidebox.animate({
            'right': '0px'
          }, 300);
        },
        close: function() {
          slidebox.stop(true).animate({
            'right': originalPosition
          }, 100);
        }
      }
    }

    $(window).scroll(function() {
      var distanceTop = $('#last').offset().top - $(window).height();

      if ($(window).scrollTop() > distanceTop) {
        if (!open) {
          open = true;
          boxAnimations.open();
          track("Open");
        }
      } else {
        open = false;
        boxAnimations.close();
      }
    });

    slidebox.find('.close').click(function() {
      $(this).parent().remove();
      track("Close");
    });
    slidebox.find('.related a').click(function() {
      track("Read More");
    });
  }

  $(function() {
    $('#slidebox').slidebox();
  });
})(jQuery);

// Validates Pothole Pig Submissions then submits the form
function validatePotholeSubmission() {
	var formValid = true;
	
	if($('input#reader_name').val() === "") {
		$('span.reader_name_error').fadeIn();
		formValid = false;
	}
	else { $('span.reader_name_error').fadeOut(); }
	
	if($('input#reader_email').val() === "") {
		$('span.reader_email_error').fadeIn();
		formValid = false;
	}
	else { $('span.reader_email_error').fadeOut(); }
	
	if($('textarea#reader_submission').val() === "") {
		$('span.pothole_information_error').fadeIn();
		formValid = false;
	}
	else { $('span.pothole_information_error').fadeOut(); }
	
	if(formValid === true){ $('form#freeform').submit(); }
}

// Validates Calendar Submissions then submits the form
function validateCalendarSubmission() {
	var formValid = true;
	
	if($('input#name').val() === "") {
		$('span.reader_name_error').fadeIn();
		formValid = false;
	}
	else { $('span.reader_name_error').fadeOut(); }
	
	if($('input#email').val() === "") {
		$('span.reader_email_error').fadeIn();
		formValid = false;
	}
	else { $('span.reader_email_error').fadeOut(); }

	if($('input#phone1').val() === "") {
		$('span.reader_phone_error').fadeIn();
		formValid = false;
	}
	else { $('span.reader_phone_error').fadeOut(); }

	if($('input#event_title').val() === "") {
		$('span.event_title_error').fadeIn();
		formValid = false;
	}
	else { $('span.event_title_error').fadeOut(); }

	if($('input#event_date').val() === "") {
		$('span.event_date_error').fadeIn();
		formValid = false;
	}
	else { $('span.event_date_error').fadeOut(); }
	
	if($('textarea#event_description').val() === "") {
		$('span.event_description_error').fadeIn();
		formValid = false;
	}
	else { $('span.event_description_error').fadeOut(); }
	
	if(formValid === true){ $('form#freeform').submit(); }
}



// Retrieves an JSONP document for a specific Edition/Section and loads it into the specific CSS element.
// This will be used to load /news/, /sports/, /citylife/ and current IS used on the MES home page.
function loadSectionStoryList(site_short_name, channel, edition_entry_id, resultTarget) {
	// Source our data.  Note this is an XML document.
	var myDataURL = 'http://www.tacomaweekly.com/index.php?/jsonp/edition_story_list/_jqjsp/' + site_short_name + '/' + channel + '/' + edition_entry_id + '/&SectionLeadStoryCallback=?';

	$.jsonp({
		'url': myDataURL
		, 'cache': true
		, 'success': function(data) { renderSectionStoryList(data, site_short_name, channel, edition_entry_id, resultTarget); }
	});
}
// Callback for loadSectionStoryList, used to render the SectionStoryList
function renderSectionStoryList(data, site_short_name, channel, edition_entry_id, resultTarget) {
	data = decodeArticleData(data);
	// This can be any HTML we want, and we use the following format for replacment tags:
	//     [[field_name]]
	// Keep these in sync with the field names from the above myDataURL's names to avoid
	// possible confusion.
	var myStoryListTemplate =	'<div class="box" style="display: none;"><p class="dateText">[[entry_date]]</p><h3><a href="/[[channel_short_name]]/view/[[url_title]]/">[[title]]</a></h3>[[article_thumbnail]]<p>[[body]]</p><div class="bio"><div class="left"><p class="bio">[[bio]]</p></div><div class="right"><p><a href="/[[channel_short_name]]/view/[[url_title]]/">Read More <strong>&gt;&gt;</strong></a></p></div><div class="clear"></div></div><div class="clear"></div><p class="bottomBorder"></p></div>';

	// Stage our workspace variable before the loop
	var myStoryItem = '';
	var myStoryBody = '';
	var testForNonChar = new RegExp(/\W/g);

	// Since we now have the document in hand, fadeOut the LOADING image.
	// The callback function will process the rest of the data into the DOM.
	$(resultTarget + ' img.loading').fadeOut('fast', function() {
		// Loop through each record in the JSON object
		for(var article = 0; article < data.length; article++) {
			if(data[article].article_edition_id === edition_entry_id) {
				// Set our local item to a fresh version of the HTML template
				myStoryItem = myStoryListTemplate;
				
				// Clean and sanitize the body content for the intended usage. Shorten to summary length of 215 characters. If the last character is non-alpha, remove it (then add an ellipsis).
				myStoryBody = data[article].body.replace(/^(.{215}[^\s]*).*/, "$1").replace(/^\s+|\s+$/g,"");
				if(testForNonChar.test(myStoryBody.charAt(myStoryBody.length -1)))
				{ myStoryBody = myStoryBody.substring(0, myStoryBody.length -1); }
				myStoryBody = myStoryBody + '&#8230';
	
				// Check the XML record for a thumbnail image. If there is an image perform the appropriate
				// template replacement. If there is no image, remove the replacement tag entirely.
				if(data[article].article_thumbnail.length > 0) {
					myStoryItem = myStoryItem.replace(/\[\[article_thumbnail\]\]/g, '<a href="/[[channel_short_name]]/view/[[url_title]]/"><img src="' + data[article].article_thumbnail + '" class="thumbnail" alt="[[title]]" /></a>');
				} else { myStoryItem = myStoryItem.replace(/\[\[article_thumbnail\]\]/g, ''); }
				
				// Perform the rest of the template replacments.
				myStoryItem = myStoryItem.replace(/\[\[entry_date\]\]/g, data[article].entry_date);
				myStoryItem = myStoryItem.replace(/\[\[url_title\]\]/g, data[article].url_title);
				myStoryItem = myStoryItem.replace(/\[\[channel_short_name\]\]/g, data[article].channel_short_name);
				myStoryItem = myStoryItem.replace(/\[\[title\]\]/g, data[article].title);
				myStoryItem = myStoryItem.replace(/\[\[bio\]\]/g, data[article].bio);
				myStoryItem = myStoryItem.replace(/\[\[body\]\]/g, myStoryBody);
				
				// Append the record to the end of the desired DOM parent
				$(resultTarget).append(myStoryItem);
			}
		}
		$(resultTarget + ' div.box').fadeIn('slow');
	});
}

// Retrieves an JSONP document for a specific Other Papers sidebar and loads it into 
// the specified CSS element.
function loadRecentStoryList(site_short_name, channel, limit, resultTarget) {
	// Source our data.  Note this is an XML document.
	var myDataURL = 'http://www.tacomaweekly.com/index.php?/jsonp/recent_story_list/_jqjsp/' + site_short_name + '/' + channel + '/' + limit + '/';

	$.jsonp({
		'url': myDataURL
		, 'cache': true
		, 'success': function(data) { renderRecentStoryList(data, site_short_name, channel, limit, resultTarget); }
	});
}
// Callback for loadRecentStoryList, used to render the RecentStoryList
function renderRecentStoryList(data, site_short_name, channel, limit, resultTarget) {
	data = decodeArticleData(data);

	if(data.length > 0) {
		// This might contain extra <li /> tags that we do not want. Clean out the house before insertion.
		$(resultTarget + ' ol').html('');
	
		// Since we now have the document in hand, fadeOut the LOADING image.
		// The callback function will process the rest of the data into the DOM.
		$(resultTarget + ' img.loading').fadeOut('slow', function() {
			for(var article = 0; article < data.length; article++) {
				// Build the <li> entry for insertion to the DOM
				myListItem = '<li><a href="' + data[article].native_url + '" onClick="_gaq.push([\'_trackEvent\', \'Other Papers\', \'' + site_short_name + '/' + data[article].url_title + '\']);">' + data[article].title + '</a></li>';
					// Insert the item into the DOM
				$(resultTarget + ' ol').append(myListItem);
			}
			// Now that the DOM is built, fadeIn the parent OL object for a nice visual experience.
			$(resultTarget + ' ol').fadeIn('slow');
		});
	}
}

// Retrieves a JSONP document for a specific article and loads it into the specific CSS element.
// This will be used to load the FEATURED area for each paper's home and section pages.
function loadSectionLeadStory(site_short_name, channel, entry_id, resultTarget, featuredImage) {
	// Source our data.  Note this is an XML document.
	var myDataURL = 'http://www.tacomaweekly.com/index.php?/jsonp/featured_story/_jqjsp/' + site_short_name + '/' + channel + '/' + entry_id + '/';
	
	$.jsonp({
		'url': myDataURL
		, 'success': function(data) { renderSectionLeadStory(data, site_short_name, channel, entry_id, resultTarget, featuredImage); }
	});
}
// Callback for loadSectionLeadStory, used to render the SectionLeadStory
function renderSectionLeadStory(data, site_short_name, channel, entry_id, resultTarget, featuredImage) {	
	data = decodeArticleData(data);
	
	if(data.length > 0) {
		// This can be any HTML we want, and we use the following format for replacment tags:
		//     [[field_name]]
		// Keep these in sync with the field names from the above myDataURL's names to avoid
		// possible confusion.
		var myStoryListTemplate =	'<a href="/[[channel_short_name]]/view/[[url_title]]/"><img src="[[featured_image]]" width="920" height="384" alt="[[title]]" /></a><h1><a href="/[[channel_short_name]]/view/[[url_title]]/">[[title]]</a></h1><div id="featuredStoryPreviewText" onclick="window.location = \'/[[channel_short_name]]/view/[[url_title]]/\';">[[body]]</div><p><span class="readMore"><a href="/[[channel_short_name]]/view/[[url_title]]/">Read More <strong>&gt;&gt;</strong></a></span></p>';
		// Stage our workspace variable before the loop
		var myStoryItem = '';

		// Since we now have the document in hand, fadeOut the LOADING image.
		// The callback function will process the rest of the data into the DOM.
		$(resultTarget).parent().children('img.loading').fadeOut('fast', function() {
			// Set our local item to a fresh version of the HTML template
			myStoryItem = myStoryListTemplate;
			// Perform the rest of the template replacments.
			myStoryItem = myStoryItem.replace(/\[\[entry_date\]\]/g, data[0].entry_date);
			myStoryItem = myStoryItem.replace(/\[\[url_title\]\]/g, data[0].url_title);
			myStoryItem = myStoryItem.replace(/\[\[channel_short_name\]\]/g, data[0].channel_short_name);
			$('div#featuredStoryPreviewText').html($('div#featuredStoryPreviewText').remove('p:last').html());
			myStoryItem = myStoryItem.replace(/\[\[featured_image\]\]/g, featuredImage);
			myStoryItem = myStoryItem.replace(/\[\[title\]\]/g, data[0].title);
			myStoryItem = myStoryItem.replace(/\[\[bio\]\]/g, data[0].bio);
			myStoryItem = myStoryItem.replace(/\[\[body\]\]/g, data[0].body.replace('<p>&#8230;</p>',''));
			// Append the record to the end of the desired DOM parent
			$(resultTarget).append(myStoryItem);
			//$(resultTarget + ' div#featuredStoryPreviewText p:last').remove();

			$(resultTarget).fadeIn('slow');
		});
	}
}
// Retrieves an JSONP document for a specific article
function loadFullArticle(site_short_name, channel, url_title) {
	var myDataURL = 'http://www.tacomaweekly.com/index.php?/jsonp/single_story/_jqjsp/' + site_short_name + '/' + channel + '/' + url_title + '/';
	$.jsonp({
		'url': myDataURL
		, 'cache': true
		, 'success': function(data) { renderFullArticle(data); }
	});
}
// Callback for loadFullArticle, used to render the FullArticle
function renderFullArticle(data) {
	data = decodeArticleData(data);

	// Load the title
	$('#thisArticleTitle').html(data[0].title);
	// Load the subheadline, show the block if a subheadline exists
	if (data[0].subheadline.length > 0) {
		$('#thisArticleSubheadline').html(data[0].subheadline);
		$('#thisArticleSubheadline').parent().show();
	}
	// Load the entry date
	$('#thisArticleEntryDate').replaceWith(data[0].entry_date);	
	// Load the body
	$('#thisArticleBody').replaceWith(data[0].body);
	
	// Load the images, show the block if any images exists
	if(data[0].article_images.length > 0) {
		// Load the image itself
		$('#thisArticleImageContainer img#thisArticleImage').attr('src',data[0].article_images[0].image_matrix_thumbnail);
		// Load the image ALT attribute, use the cutline if possible, article title if not
		if(data[0].article_images[0].image_matrix_cutline.length > 0) {
			$('#thisArticleImageContainer img#thisArticleImage').attr('alt',data[0].article_images[0].image_matrix_cutline);
		} 
		else { $('#thisArticleImageContainer img#thisArticleImage').attr('alt',data[0].title); }
		
		$('#thisArticleImageContainer a.image.lightbox').attr('href',data[0].article_images[0].image_matrix_image);
		// Load the image caption, use both Byline and Cutline if possible, either/or if not
		if(data[0].article_images[0].image_matrix_byline.length > 0 && data[0].article_images[0].image_matrix_cutline.length > 0) {
			$('#thisArticleImageContainer a.image.lightbox').attr('title', data[0].article_images[0].image_matrix_byline + ' - ' + data[0].article_images[0].image_matrix_cutline);
		} 
		else if(data[0].article_images[0].image_matrix_byline.length > 0) {
			$('#thisArticleImageContainer a.image.lightbox').attr('title', data[0].article_images[0].image_matrix_byline);
		} 
		else if(data[0].article_images[0].image_matrix_cutline.length > 0) {
			$('#thisArticleImageContainer a.image.lightbox').attr('title', data[0].article_images[0].image_matrix_cutline);
		}
		// If there multiple images, show the MORE IMAGES button
		if(data[0].article_images.length > 1) { $('#thisArticleImageContainer a.moreImages').show(); }
		// Now that we have loaded the image data, show the block
		$('#thisArticleImageContainer').show();
	}
	
	loadArticleBio(data[0].author_id_1, data[0].author_id_2, data[0].author_id_3, function() {
		// Now we show everything
		$('div.first.article').show(0, function() {
			$('.articleShowAfterRender').show(0);
		});
	});
}
// Retrieves an JSONP document for a specific articles bio section
function loadArticleBio(author_id_1, author_id_2, author_id_3, callback) {
	var myDataURL = 'http://www.tacomaweekly.com/jsonp/contributor_list/_jqjsp/' + author_id_1 + '/' + author_id_2 + '/' + author_id_3 + '/';
	$.jsonp({
		'url': myDataURL
		, 'cache': true
		, 'complete': function() {
			if(typeof callback != 'undefined') { callback(); }
		}
		, 'success': function(bioData) {
			renderArticleBio(bioData, author_id_1, author_id_2, author_id_3, callback);
		}
	});
}
// Callback for loadArticleBio, used to render the ArticleBio
function renderArticleBio(bioData, author_id_1, author_id_2, author_id_3, callback) {
	bioData = decodeContributorData(bioData);
	
	var bioHTML = '';
	
	// The logic for bio display is as such:
	//   - No assigned writer gets a generic PUBLISHED IN string
	//   - 1 writer gets a picture (if available) and a credit string
	//   - 2 writers gets just the credit string in this format:  WRITER NAME and WRITER NAME
	//   - 3 writers gets just the credit string in this format:  WRITER NAME, WRITER NAME and WRITER NAME
	if(author_id_1.length < 1 && author_id_2.length < 1 && author_id_3.length < 1) {
		bioHTML = '';
	}
	// One writer
	else if(author_id_1.length > 0 && author_id_2.length < 1 && author_id_3.length < 1) {
		bioHTML = 'By <strong>' + bioData[0].title + '</strong>';
		// Add the picture if they have it
		if(bioData[0].contributor_thumb.length > 0) {
			bioHTML = '<img src="' + bioData[0].contributor_thumb + '" alt="bioData[0].title" />' + bioHTML;
		}
	}
	// Two or more writers
	else {
		bioHTML = '<strong>' + bioData[0].title + '</strong>';
		// If there is only 2 writers
		if(author_id_3.length < 1) { 
			bioHTML = bioHTML + ' and <strong>' + bioData[1].title + '</strong>';
		}
		// If there are 3 writers
		else { 
			bioHTML = bioHTML + ', <strong>' + bioData[1].title + '</strong> and <strong>' + bioData[1].title + '</strong>'; 
		}
	}
	$('#thisArticleBio').replaceWith(bioHTML);
}

// Retrieves an JSONP document for a specific article gallery
function loadArticleGallery(site_short_name, channel, url_title) {
	var myDataURL = 'http://www.tacomaweekly.com/index.php?/jsonp/single_story_gallery/_jqjsp/' + site_short_name + '/' + channel + '/' + url_title + '/';
	$.jsonp({
		'url': myDataURL
		, 'cache': true
		, 'success': function(data) { renderArticleGallery(data); }
	});
}
// Callback for loadArticleGallery, used to render the loadArticleGallery
function renderArticleGallery(data, site_short_name, channel, url_title) {
	data = decodeArticleData(data);
	
	// Load the title
	$('#thisArticleTitle').html(data[0].title);
	// Load the subheadline, show the block if a subheadline exists
	if (data[0].subheadline.length > 0) {
		$('#thisArticleSubheadline').html(data[0].subheadline);
		$('#thisArticleSubheadline').parent().show();
	}
	// Load the entry date
	$('#thisArticleEntryDate').replaceWith(data[0].entry_date);	

	loadArticleBio(data[0].author_id_1, data[0].author_id_2, data[0].author_id_3, function() {
		var htmlImage = '';
		
		for(var image = 0; image < data[0].article_images.length; image++) {
			htmlImage += '<a class="grid_5 image lightbox" href="' + data[0].article_images[image].image_matrix_image + '" rel="article-gallery" ';

			// Load the image caption, use both Byline and Cutline if possible, either/or if not
			if(data[0].article_images[image].image_matrix_byline.length > 0 && data[0].article_images[image].image_matrix_cutline.length > 0) {
				htmlImage += 'title="' + data[0].article_images[image].image_matrix_byline + ' - ' + data[0].article_images[image].image_matrix_cutline + '"';
			} 
			else if(data[0].article_images[image].image_matrix_byline.length > 0) {
				htmlImage += 'title="' + data[0].article_images[image].image_matrix_byline + '"';
			} 
			else if(data[0].article_images[image].image_matrix_cutline.length > 0) {
				htmlImage += 'title="' + data[0].article_images[image].image_matrix_cutline + '"';
			}
			// Make sure the <a /> tag is closed
			htmlImage += ' >';

			// Load the image ALT attribute, use the cutline if possible, article title if not
			if(data[0].article_images[0].image_matrix_cutline.length > 0) {
				htmlImage += '<img src="' + data[0].article_images[image].image_matrix_thumbnail + '" width="280px" alt="' + data[0].article_images[image].image_matrix_cutline + '"/>';
			} 
			else {
				htmlImage += '<img src="' + data[0].article_images[image].image_matrix_thumbnail + '" width="280px" alt="' + data[0].title + '"/>';
			}

			htmlImage += '</a>';
		}
		
		$('.article.imageGallery').append(htmlImage);
		
	  // Simply handles image lightboxing
	  // Matches the site-wide lightboxing, recalling here because these images are injected and
	  // not available at document.ready runtime.
	  $("a.image.lightbox").fancybox({
	    'transitionIn' : 'elastic'
	    , 'transitionOut' : 'elastic'
	    , 'speedIn' : 400
	    , 'speedOut' : 200
	    , 'titlePosition' : 'inside'
	    , 'cyclic' : 'true'
	  });
	  // End: Fancybox-Images
	
		// Now we show everything
		$('div.first.article').show(0, function() {
			$('.articleShowAfterRender').show(0);
		});
	});
}

// Decodes article data from it's Base64 glory
function decodeArticleData(data) {
	for(var entry = 0; entry < data.length; entry++) {
		data[entry].title = Base64.decode(data[entry].title); 
		data[entry].url_title = Base64.decode(data[entry].url_title); 
		data[entry].native_url = Base64.decode(data[entry].native_url); 
		data[entry].channel_short_name = Base64.decode(data[entry].channel_short_name); 
		data[entry].entry_date = Base64.decode(data[entry].entry_date); 
		data[entry].subheadline = Base64.decode(data[entry].subheadline); 
		data[entry].body = Base64.decode(data[entry].body); 
		data[entry].article_thumbnail = Base64.decode(data[entry].article_thumbnail); 
		data[entry].article_video = Base64.decode(data[entry].article_video); 
		data[entry].bio = Base64.decode(data[entry].bio); 
		data[entry].author_id_1 = Base64.decode(data[entry].author_id_1); 
		data[entry].author_id_2 = Base64.decode(data[entry].author_id_2);
		data[entry].author_id_3 = Base64.decode(data[entry].author_id_3); 
		data[entry].article_edition_id = Base64.decode(data[entry].article_edition_id); 
		data[entry].article_tags = Base64.decode(data[entry].article_tags);
		data[entry].count = Base64.decode(data[entry].count);
		// Decodes the article_images sub-object
		for(var image = 0; image < data[entry].article_images.length; image++) {
			data[entry].article_images[image].image_matrix_thumbnail = Base64.decode(data[entry].article_images[image].image_matrix_thumbnail);
			data[entry].article_images[image].image_matrix_image = Base64.decode(data[entry].article_images[image].image_matrix_image);
			data[entry].article_images[image].image_matrix_byline = Base64.decode(data[entry].article_images[image].image_matrix_byline);
			data[entry].article_images[image].image_matrix_cutline = Base64.decode(data[entry].article_images[image].image_matrix_cutline);
		}
	}
	return data;
}

// Decodes article data from it's Base64 glory
function decodeContributorData(data) {
	for(var entry = 0; entry < data.length; entry++) {
		data[entry].title = Base64.decode(data[entry].title);
		data[entry].contributor_email = Base64.decode(data[entry].contributor_email);
		data[entry].contributor_thumb = Base64.decode(data[entry].contributor_thumb);
		data[entry].channel_short_name = Base64.decode(data[entry].channel_short_name);
		data[entry].contributor_type = Base64.decode(data[entry].contributor_type);
	}
	return data;
}
