/* ecp.js */

var ECP = {
		// common callback functions for opening and closing color box
		// but based on arrays optionally populated on a per-instance basis
		colorBoxOpen: function () {
			// if any close handlers have been installed, call them
			$(ECP.colorBoxOpen_Callbacks).each(function () {
				this.apply();
			});
		}
		,colorBoxClose: function () {
			// if any close handlers have been installed, call them
			$(ECP.colorBoxClose_Callbacks).each(function () {
				this.apply();
			});
		}
		,colorBoxOpen_Callbacks: []
		,colorBoxClose_Callbacks: []
		,TESTING: {
		    fakeRestProxy: false            // production: false
		}
	};

// function for the external javascript clickable map file
function A (URL, COORDS, ALT, areaHilightOptions, SHAPE) {
	var areaOptions = '',
		lookupURL,
		queryStart,
		rtnURL = URL;

	// returns area options as attribute strings
	function getAreaOptions () {
		var areaOptions = '';

		if (areaHilightOptions) {
			// JSON.stringify produces double-quoted string, e.g. '{"fillColor":"666"}'
			areaOptions = ' data-maphilight=\'' + JSON.stringify(areaHilightOptions) + '\'';

			if (areaHilightOptions.group) {
				areaOptions += ' data-maphilight-group="' + areaHilightOptions.group + '"';
			}
		}

		return areaOptions;
	}	// getAreaOptions

	// --- begin A ---

	SHAPE = SHAPE || 'poly';	// optional parameter, for example, for passing 'circle'

	// why would URL ever be empty?!
	if (URL != "") {
		var lowerURL = URL.toLowerCase();

		//  $anchor = $(".state-link-container a:contains('" + URL + "')");
		//	- this original logic not quite enough: since link text arkansas contains state name string kansas
		var $anchor = $(".state-link-container a").filter(function () {
			return $(this).text().toLowerCase() === lowerURL;
		});

		if ($anchor.length) {
			lookupURL = $anchor.attr('href');

			queryStart = lookupURL.indexOf('?');
			rtnURL = lookupURL + (queryStart >= 0 ? '&' : '?') + 'keepThis=true&TB_iframe=true&height=285&width=540';

//			OCMS.consoleMsg('map area href for: ' + URL + ': ' + lookupURL + '\n\t' + rtnURL);

			if (queryStart === -1) {
// right?
//				OCMS.consoleMsg('\t map link not valid from Preview or for unpublished pages');
				// confirm that this will work in production!

				if (OCMS.isIE7) {
					// IE7 seen to NOT like leading / in &name
					if (lookupURL.slice(0, 1) === '/') {	// IE7 doesn't support lookupURL[0]!
						lookupURL = lookupURL.slice(1);
						OCMS.consoleMsg('\t leading / removed for IE7');
					}
				}

				rtnURL = OCMS.constructPageURL(lookupURL, 'keepThis=true&TB_iframe=true&height=285&width=540');

				OCMS.consoleMsg('\t new URL attempt: ' + rtnURL);
			}

			areaOptions = getAreaOptions();
			document.writeln('<area class="thickbox maparea-' + URL + '" shape="' + SHAPE +
							'" href="' + rtnURL + '" coords="' + COORDS + '" title="' + ALT +
							'"' + areaOptions + '>');
		} else {
			OCMS.consoleMsg('link lookup failed for ' + URL);
			// NO area shape written within <map>, therefore no hover (or click) actions
		}
	}
}	// A


// staff contacts component's completion function
var myData;

function loadContactsIntoPage (json, testStatus, xhr) {
	var contactHTML = '';
	myData = json.objStaffContacts;

	$.each(json.objStaffContacts, function(index, value){
		value.Name 			= value.Name || '';
		value.Title 		= value.Title || '';
		value.CompanyName	= value.CompanyName || '';
		value.Phone			= value.Phone || '';

		var displayName = '';
		var pseudoIdEmail = '';
		if (value.PseudoUser != undefined && value.PseudoUser == 'true') {
			displayName = value.PseudoName;
			pseudoIdEmail = value.PseudoIdEmail;
		} else {
			displayName = value.Name;
		}

 		contactHTML +=	'<div class="staffcontact-item">';

		if (value.Image != undefined && value.Image != '#' && value.Image.length) {
			contactHTML += '<img class="staffcontact-image" src="' +
                            value.Image + '" />';
		} else {
			contactHTML += '<div class="bioNoPhoto"></div>';
		}

		contactHTML += '<span class="staffcontact-name" onclick="displayForm(\'' +
		                value.Id + '\',\'' + pseudoIdEmail + '\');">' +
						displayName + '</span>';
		if (value.bioAvail == 'true') {
			contactHTML += '<span class="staffcontact-bio">  | <a onClick="tb_remove();setTimeout(\'loadBio(' +
			                    index +')\', 300)">Biography</a></span>';
		} else {
			contactHTML += '<span style="width: 200px; height: 1.4em; display: inline-block;"></span>';
		}
		contactHTML +=	'<div class="staffcontact-title">' + value.Title + "</div>";

		if ((value.CompanyName != undefined && value.CompanyName.length)) {
			contactHTML += '<div class="staffcontact-company">' + value.CompanyName + "</div>";
		}

		if (value.Street != undefined && value.Street.length) {
			contactHTML += '<div class="staffcontact-street">' + value.Street+ '</div>';
		}
		if (value.City != undefined && value.City.length) {
			contactHTML += '<div class="staffcontact-citystatezip">' + value.City;
		}
		if ((value.City != undefined && value.City.length) && (value.State != undefined && value.State.length))
		{
			contactHTML += ', ' + value.State;
		}
		if (value.Zip != undefined && value.Zip.length) {
			contactHTML += ' ' + value.Zip;
		}
		if (value.City != undefined && value.City.length) {
			contactHTML += '</div>';
		}
		contactHTML += '<div class="staffcontact-phone">' + value.Phone;
		if (value.Fax != undefined && value.Fax.length) {
			contactHTML += ' | Fax: ' + value.Fax;
		}
		contactHTML += '</div></div>';
	});

	$('.staffcontact-staff-list').append(contactHTML);

	if ($.isFunction(prepareStaffContacts)) {
		prepareStaffContacts();
	}
}	// loadContactsIntoPage


// completion function to be called by the Staff Contacts component
function prepareStaffContacts () {
	var modalHtml;

	var $contacts = $('.staffcontact-item');
	OCMS.consoleMsg('number of .staffcontact-item\'s found in page: ' + $contacts.length);

	if ($contacts.length) {
		modalHtml = $('#staff-contacts-source').html();
		$('#staff-contacts-container').append(modalHtml);

//		modalHtml = $('.droppable-contacts .email-sent-container').html();
//		$('#modalWindowBio .email-sent-container').append(modalHtml);

//		$('#staff-contacts-source, .droppable-contacts .email-sent-container').remove();
	} else {
		// is there something special to do if there are none?
	}

    // Attach a handler to the link to handle going back to the list if you close from a form
    $('a#openModalBio').click(function() {
		$('div.staffcontact-staff-list').show();
		$('div.staffcontact-email-form').hide();
		$('div.email-sent-container').hide();
		return true;
	});

}	// prepareStaffContacts


/*	- left as a global function so that the templates that used to have a less robust in-line script
   		block that tried to do this will have minimal modifications
	- note that not all templates that have a .buttonWrapper use this technique!
	- at last count there were about seven that do, and about 25 that did not
*/
function installWholeButtonClickHandler () {
	// 	- set the .buttonWrapper click handler to find out if there's an <a> inside
	// 		(expecting only one), and if it has an href, go to that location
	//	- the actual link occupies a small part of the space covered by the .buttonWrapper
	$(".buttonWrapper").click(function () {
		var $a = $('a', this),
			href;

		if ($a.length) {
			href = $a.attr('href');
			if (href.length && href !== '#') {
				//OCMS.consoleMsg('whole button click handler: ' + href);
				window.location = href;
			}
		} else {
			OCMS.consoleMsg('button ' + $('.buttonTableCell', this).text().trim() + ' does not contain a link');
		}
  });
}	// installWholeButtonClickHandler


// compare to setPageType() in profit-page-detect.js
// then there's this block from the map page(s), now functionized...
//	when we're awake, let's find out what's different

//	2011-Sep-22	pretty sure this does nothing useful now that isn't already happening

function setPageTypeForMap () {
/*
    if ($('#edit-header').length > 0) {
        // edit page
        var typeDetect = $(".ocms-content-name").html();
        var nonProfitPage = typeDetect.search('Non-Profit');
        var comingledPage = typeDetect.search('Comingled');
        $('.state-link-container').css('display', 'block');

        if (nonProfitPage > 0) {
            $('.page-container').addClass('non-profit');
        } else if (comingledPage > 0) {
            $('.page-container').addClass('comingled');
        } else {
            $('.page-container').addClass('profit');
        }
    } else {
        // preview page
        $('.state-link-container').css('display', 'none');
        $('.profit-select-wrap').css('display', 'none');

        var previewPageType = $(".profit-select-content > span > span").html();

        if (previewPageType == 'non-profit') {
            $('.page-container').addClass('non-profit');
        } else if (previewPageType == 'comingled') {
            $('.page-container').addClass('comingled');
        } else {
            $('.page-container').addClass('profit');
        }
    }
*/

	// when Intranet gets ocms-extensions, just use: OCMS.consoleMsg()
	if (typeof console !== 'undefined' && typeof console.log === 'function') {
		console.log('setPageTypeForMap (report only): ' + $('.page-container').attr('class'));
	}
}	// setPageTypeForMap


// strong candidate for inclusion in ocms-extensions.js
$.fn.redraw = function () {
	return $(this).each(function () {
	    OCMS.consoleMsg('redraw hack for IE8');

	    var tn = document.createTextNode(' ');
	    this.appendChild(tn);

	    setTimeout(function () {
	    	tn.parentNode.removeChild(tn);
	    }, 0);
	});
};    // redraw


$(document).ready(function () {

	function formattedCarouselDescription (desc, item) {
		// - returns the formatted HTML of the given 'raw' description html, which might include meta formatting
		// - also deletes one of Rail Video's containers (if present) within item, but only after
		//   using its text
		var vidHref,
			$rrLaunchVidLink;

		if (desc) {
		    // newlines removed (likely not necessary) and h1 from {}-wrapped text
			desc = desc
					.replace(/\n/g, ' ')
					.replace(/{([^}]+)}/m, '<h1>$1</h1>');

			// if there is a link to a video, for Rail Video it'll be in a.right-rail-image-link
			vidHref = $('.right-rail-image-link', item).attr('href');
			$rrLaunchVidLink = $('.right-rail-video-container .right-rail-video-container', item);

			if (vidHref) {
				// look for text enclosed by [[ and ]] and make it the magic video link
				if (desc.search(/\[\[(.+)\]\]/g) >= 0) {
					desc = desc.replace(/\[\[(.+)\]\]/g, '<a class="rightrail-launch-video" href="' + vidHref + '">$1</a>');

					// remove link provided by Rail Video; we'll use the placeholder from their text
					OCMS.consoleMsg('formattedCarouselDescription: adding [[video link]] and removing Rail Video\'s "Watch Video"');
				} else {
					// if this item has a .rrvc within an .rrvc, then
					// move that to the bottom of the description
					if ($rrLaunchVidLink.length) {
						desc += '<a class="rightrail-launch-video" href="' + vidHref + '">' + $rrLaunchVidLink.text() + '</a>';
					}
				}
			}

			// we either don't need $rrLaunchVidLink any more,
			// or we have already copied its innerHTML and appended to desc
			$rrLaunchVidLink.remove();
		}

		return desc || '';
	}	// formattedCarouselDescription


	function convertToCarouselList ($items) {
		// if our collection is not using ocmsCarousel markup, make it so
		// but don't bother with the carousel-nav and swicher

        OCMS.consoleMsg('convertToCarouselList: ' + $items.length);
        if ($items.length) {
            // get the $parent now, before we wrap each item with li.ocmsCarouselItem
            var $parent = $items.eq(0).parent();

            //OCMS.consoleMsg('convertToCarouselList: parent: ' +
            //    $parent.get(0).tagName + ' #' + $parent.attr('id') + ' .' + $parent.attr('class'));

            $items.each(function () {
                $(this).replaceWith('<li class="ocmsCarouselItem">' + this.innerHTML + '</li>');
            });

            // for proper results, requires that they all have the same parent, which they should
            $parent.wrapInner('<ul class="ocmsCarousel">');
        }
	}	// convertToCarouselList


    function createCarouselDescription () {
        // called as a method on a carousel item whose markup is either from
        // CarouselImage or RailVideo

        /*
            Ugh: for earlier Orchestra 3.5's, if Carousel Link was not specified, we still
            get a.carousel-image-link with href="#"; but sometime shortly after 2011-Nov-11
            when this happens the href attribute will simply be omitted

            sample INITIAL content: -  Carousel Image
                <span>
                    <span>
                        <a class="carousel-image-link" href="#">
                            <img class="carousel-image" src="/servlet/servlet.FileDownload?file=00P30000007Wpi8EAC">
                        </a>
                        <p class="carousel-description">
                            {Item 1 Title}
                            This is a description for the first image.
                            <br />
                            and they're going to put <a href="#">markup</a> in here!
                        </p>
                    </span>
                </span>

            <span>
                <div class="right-rail-video-container a0RT000000Bo5AeMAJ">
                    <div class="right-rail-imageblock-image">
                        <div class="small-block-image">
                            <a class="right-rail-image-link" href="http://www.youtube.com/embed/=0Rh4gGPieNU?rel=0&amp;wmode=transparent">
                                <img src="/servlet/servlet.FileDownload?file=00P300000085KlWEAU" />
                            </a>
                        </div>
                        <div class="right-rail-imageblock-content-container">
                            <div class="right-rail-imageblock-title">
                            </div>
                            <div class="right-rail-imageblock-content-body">
                            </div>
                        </div>
                        <div class="clear">
                        </div>
                    </div>
                    <div class="right-rail-video-container">
                        <a href="http://www.youtube.com/embed/=0Rh4gGPieNU?rel=0&amp;wmode=transparent" id="rightrail-launch-video"> Watch Video </a>
                    </div>
                </div>

                <script>
                       var content_id = 'a0RT000000Bo5AeMAJ';
                       $("." + content_id + " > .right-rail-video-container > #rightrail-launch-video").colorbox({iframe:true, innerWidth:425, innerHeight:344});
                       $("." + content_id + " > .right-rail-imageblock-image > .small-block-image > .right-rail-image-link").colorbox({iframe:true, innerWidth:425, innerHeight:344});
                </script>
            </span>


            sample NEW content:
                <span>
                    <a class="carousel-image-link" href="#">
                        <img class="carousel-image" src="/servlet/servlet.FileDownload?file=00P30000007Wpk3EAC">
                    </a>
                    <div class="carousel-description">
                        <h1>From the first sketch to the last nail</h1>
                        This is a description for the third item. It shouldn't really be able to contain HTML.
                        <br>
                        <a href="http://useabill.org/quotable/">Click me &amp;adquo;</a>
                    </div>
                </span>
        */

        //OCMS.consoleMsg('createCarouselDescription: ');
        //OCMS.consoleMsg($(this).html().trim().replace(/></g, '>\n<'));

        var srcDescription = $("p.carousel-description", this).html(),
            rrTitle = '',
            $oldContainer;

        if (!srcDescription) {
            // look for content: Right Rail Video
            srcDescription = $('.right-rail-imageblock-content-body', this).html();

            // Rail Video content has an optional, text-only title attribute
            rrTitle = $('.right-rail-imageblock-title', this).text();
            if (rrTitle) {
                rrTitle = '<div class="right-rail-imageblock-title">' + rrTitle + '</div>';
            }
        }

        $oldContainer = $("p.carousel-description", this);

        if (!$oldContainer.length) {
            $oldContainer = $('.right-rail-imageblock-content-container', this);
        }

        //				OCMS.consoleMsg($(this).html().trim().replace(/></g, '>\n<'));

        // replace the old p with a new div; same class, structured contents
        $oldContainer.remove();

        $(this).append('<div class="carousel-description">' +
                            rrTitle +
                            formattedCarouselDescription(srcDescription, this) +
                        '</div>');


    }   // createCarouselDescription


	function prepareHomeCarousel () {

		function formatHomePageCarouselText ($carouselItems) {

			// --- begin formatHomePageCarouselText ---

			$carouselItems.each(function () {
				// content: Carousel Image
				// - make p.carousel-description into div.carousel-description
				// - if there's title text within {}, break that into an h1

                createCarouselDescription.call(this);

				if (OCMS.isIE7 || OCMS.isIE8) {
					OCMS.consoleMsg('IE7 and IE8 require unique markup for the alpha png text background image');
					$('.carousel-description', this)
						.wrapInner('<div class="textOnTop">')
						.prepend('<img class="ieAlphaFade" src="' + rsrcPath() + 'css/images/carouselTextBkgnd376x474.png" alt="" />');

                    // tell IE8 to ignore these elements in its special case slideshow fade
                    if (OCMS.isIE8) {
                        $(this).find('.carousel-description').addClass('ssIGNORE');
                    }
				}
			});
		}	// formatHomePageCarouselText


		function removeEmptyCarouselImageLinks ($items) {
			// change useless links like this:
			//	<a class="carousel-image-link" href="#">
			// 		<img class="carousel-image" src="/servlet/servlet.FileDownload?file=00P30000007Wpi8EAC">
			//	</a>
			// in to just:
			//	<img class="carousel-image" src="/servlet/servlet.FileDownload?file=00P30000007Wpi8EAC">

			$('a.carousel-image-link[href="#"] > img', $items).unwrap();
		}	// removeEmptyCarouselImageLinks


		function buildThumbnailNav ($carouselItems, slidesController) {
			var navMarkup;

			if ($carouselItems.length > 1 ) {
				navMarkup = '<div class="homeCarouselNav">';
				$carouselItems.each(function () {
					var imgMarkup = $(this).find('a.carousel-image-link').html();

					if (!imgMarkup) {
						// content not Carousel Image; look for nasty right rail video
						imgMarkup = $(this).find('a.right-rail-image-link').html();
					}
					navMarkup += '<div>' + imgMarkup + '</div>';
				});
				navMarkup += '</div>';

				$('.homeCarousel').append(navMarkup);

				$('.homeCarouselNav img').each(function (nIt) {
					$(this).click(function () {
						slidesController.goToSlideNumber(nIt);
					});
				});

			}
		}	// buildThumbnailNav


		function goCallback (paramBlock) {
			/*	parameter to call back function
				{
					oldIndex,
					newIndex,
					$newItem,
					maxIndex
				} */

			// queue the text transition separately, and
			// update the thumbnail img.active

			// hide the current slide's text
			var $parent = paramBlock.$newItem.parent();	// ul
			$('li.ocmsCarouselItem', $parent).eq(paramBlock.oldIndex).find('.carousel-description').hide();

            // still can't get IE8 to do a smooth text fade in
			setTimeout(function () {
				if (!OCMS.isIE8) {
					paramBlock.$newItem.find('.carousel-description').fadeIn(textTransitionSpeed);
				} else {
					paramBlock.$newItem.find('.carousel-description')
						.css('left', '950px')
						.show()
						.animate({left: '574px'}, textTransitionSpeed);
				}
			}, textDelay);

			$('.homeCarouselNav > div').eq(paramBlock.oldIndex).removeClass('active').end()
									.eq(paramBlock.newIndex).addClass('active');
		}	// goCallback


		// --- begin prepareHomeCarousel ---

		var $carouselItems = $('.homeCarousel > span > span');

		convertToCarouselList($carouselItems);
		$carouselItems = $('.homeCarousel .ocmsCarousel li');
		if ($carouselItems.length) {
			OCMS.consoleMsg('initCarousel: ' + $carouselItems.length + ' .ocmsCarousel li');

			formatHomePageCarouselText($carouselItems);

			// these will be inherited by goCallback
			var textDelay 			= OCMS.pageOptions('textDelay') || 2200,
				textTransitionSpeed = OCMS.pageOptions('textTransitionSpeed') || 1000;

			var homeSlides = OCMS.slideShow({
						selector: $carouselItems,
						slideDuration: OCMS.pageOptions('slideDuration') || 12000,
						transitionSpeed: OCMS.pageOptions('transitionSpeed') || 2000,
						stopMinutes: OCMS.pageOptions('stopMinutes') || 60,
						preGoCallback: goCallback
					});

            // assumes home slide show always running and to be resumed upon closing colorbox
            // homeSlides.getIsRunning() will help
			ECP.colorBoxOpen_Callbacks.push(homeSlides.pause);
			ECP.colorBoxClose_Callbacks.push(homeSlides.resume);

			// dynamically create the thumbnail trail at the bottom of the slideshow image area
			// using the same full-size images scaled down to fit
			buildThumbnailNav($carouselItems, homeSlides);
			// remove...() must follow build...() since the former uses the original structure
			removeEmptyCarouselImageLinks($carouselItems);

			// must trigger initial text-in transition (and after thumbnails are ready)
			homeSlides.goToSlideNumber(0);

			// Jane, get me off this crazy thing!
			$('.homeCarouselNav').dblclick(homeSlides.toggle);
		}
	}	// prepareHomeCarousel


	function buildBulletNavStaticSlideShow (el, selectorString) {
		var $this = $(el),
			$selector = $this.find(selectorString),
			ss,
			$bullets;

		function updateNavBullets (params) {
			// params : {oldIndex, newIndex, $newItem, maxIndex}
			$bullets.eq(params.oldIndex).removeClass('active');
			$bullets.eq(params.newIndex).addClass('active');
		}	// updateNavBullets ()

		// --- begin buildBulletNavStaticSlideShow ---

		if ($selector.length > 1) {
		    // don't use .prev and .next to avoid possible conflicts
			var navTemplate = '<div class="ssBulletNav"><span class="ssBNPrev"></span>{bulletItems}<span class="ssBNNext"></span></div>';

			if (!$.isFunction(OCMS.slideShow)) {
				OCMS.consoleMsg('▶▶ missing OCMS.slideShow');
				return;
			}

			ss = OCMS.slideShow({
				selector: $selector,
				transitionSpeed: 600,
				slideDuration: 10000,
				autoStart: false,
				preGoCallback: updateNavBullets
			});

            // not appropriate if we don't know if the slideshow is running at the time that
            // colorbox is opened
			//ECP.colorBoxOpen_Callbacks.push(ss.pause);
			//ECP.colorBoxClose_Callbacks.push(ss.resume);

			// we'll use a simple, empty b element for our bullets
			// (and get the markup without us looping)
			var placeholders = '#####################'
				.slice(0, $selector.length)
				.replace(/#/g, '<b></b>');

			$this.append(navTemplate.supplant({bulletItems: placeholders}));

			$this.find('.ssBNPrev').click(ss.previous);
			$this.find('.ssBNNext').click(ss.next);
			$bullets = $this.find('.ssBulletNav b');
			$bullets.each(function (nIt) {
				$(this)
					.click(function () {
						ss.goToSlideNumber(nIt);
					})
					.dblclick(ss.toggle);
			});

			ss.goToSlideNumber(0);
		} else {
			// just one or zero items; might normally be display: none, we better show this one
			$selector.show();
		}

		return ss;
	}	// buildBulletNavStaticSlideShow


	function prepareSlideDeck () {

		$('.slideDeck').each(
			function (nIt, deck) {
				var $slides = $('> span', deck).eq(0).children(),
				    $carLogom,
				    retryCount = 0;

                function adjustDescriptionForLogo () {
                    var $img = $(this);
                    if (!$img.height()) {
                        retryCount++;
                        if (retryCount < 30) {
                            OCMS.consoleMsg('adjustDescriptionForLogo retry: ' + retryCount);
                            setTimeout(function () {
                                adjustDescriptionForLogo.call($img);
                            }, 100);
                         } else {
                            OCMS.consoleMsg('adjustDescriptionForLogo last chance for image load');
                            setTimeout(function () {
                                adjustDescriptionForLogo.call($img);
                            }, 3000);
                         }
                    } else {
                        $('.carousel-description', deck).css({top: $img.height() + 10});
                        OCMS.consoleMsg('adjustDescriptionForLogo ' + $('.carousel-description', deck).css('top'));
                    }
                }


				// div.slideDeck > span#sf:23:de:xx:99 > span - corresponds to each slide
				if ($slides.length) {
                    $carLogo = $('.carouselLogoImage img', deck);

					//OCMS.consoleMsg('➜ simulating .ocmsCarousel markup...');
					//OCMS.consoleMsg($slides.parent().parent());
					//OCMS.consoleMsg($slides.parent().parent().html().trim().replace(/></g, '>\n<'));
					convertToCarouselList($slides);

					//OCMS.consoleMsg('➜ re-establishing list of slides...');
                    // get them again after the conversion to CarouselList
                    $slides = $('.ocmsCarouselItem', deck);

 					//OCMS.consoleMsg('➜ formatting slide markup...');
                    $slides.each(createCarouselDescription);

					//OCMS.consoleMsg('➜ building slideDeck\'s bullet nav...');
					var slideShow = buildBulletNavStaticSlideShow(deck, '.ocmsCarouselItem');

					$('.ocmsCarouselItem', deck).each(function (nItem, item) {
						//OCMS.consoleMsg('➜ reformatting carousel description...');
						$('.carousel-description', item)
							.html(formattedCarouselDescription($('.carousel-description', item).html(), item));
					});

                    if ($carLogo.length) {
                        if ($carLogo.attr('complete')) {
                            //OCMS.consoleMsg('prepareSlideDeck $carLogo complete');
                            adjustDescriptionForLogo.call($carLogo);
                        } else {
                            //OCMS.consoleMsg('prepareSlideDeck: setting $carLogo load handler');
                            $carLogo.load(adjustDescriptionForLogo);
                        }
                    }

					// .slideDeck slide shows should hit the ground running
					if ($slides.length > 1) {
                        slideShow.resume();
					}
				}
			}
		);
	}	// prepareSlideDeck


	function prepareFooterSignUpForm () {
		$('.footer-signup-input input[type="text"]').hintText('Enter your e-mail address');
		$('.footer-signup-input form').submit(function () {
			var $email = $(this).find('#txtEmail');
			if ($email.text().trim().length === 0 || $email.hasClass('hintText')) {
				alert('Enter your email address to sign up.');
				$email.focus();

				return false;	// cancel form submission
			}
		});
	}	// prepareFooterSignUpForm ()


	function createListItemsFromSmallBlocks(params) {
		var linkRef,
			imgRef,
			backImg,
			itemTemplate = '<li><a class="aCarousel" href="{linkRef}"><img src="{imgRef}" alt="" /><table><tr><td>{step}</td><td>{title}</td></tr></table></a></li>',
			$src,
			$dest;

		$src = $(params.source);
		$dest = $(params.dest);

		if ($src.length + $dest.length !== 2) {
			OCMS.consoleMsg('couldn\'t find source and/or destination: ' + params);
		} else {
			// get and remove first .small-block
			// its image becomes the background image for this carousel area

			backImg = $src.find('.small-block-image img').eq(0).attr('src');

			$dest.parent().css({
				'background-image': 'url(' + backImg + ')',
				'background-repeat': 'no-repeat',
				'background-color': '#333'					// should be redundant
			});

			$src.find('.small-block').eq(0).remove();

			$src.find('.small-block').each(function(nBlockIndex) {
				imgRef = $('.small-block-image img', this).attr('src');
				linkRef = $('.small-block-title a', this).attr('href');
				title = $('.small-block-title', this).text();
				if (!linkRef) {
					linkRef = '#';
					OCMS.consoleMsg('couldn\'t find href for ' + params.source + '\'s block ' + nBlockIndex);
					// of course, we could also check .small-block-text a and .more-link for their href
					// but for now, we'll insist on a title -- this is currently pretty specific to
					// the needs of the 3C2C page template (e.g. S&I > Green Communities > Certification)
				}
				$dest.append(itemTemplate.supplant({
					imgRef: imgRef,
					linkRef: linkRef,
					step: '' + (nBlockIndex + 1),
					title: title
				}));
			});
		}
	}	// createListItemsFromSmallBlocks ()


	function waitForRSSWidgetItems ($feedContainers, completionFunction, secondsToWait) {
		var	maxRecheckCount = secondsToWait || 11;

		function readySetGo (nIt, containerElement) {
			var $container = $(containerElement),
				$items,
				reCheckCount;

			$items = $container.find('.rss-item'),

			OCMS.consoleMsg('# of RSS items: ' + $items.length + ' (' + $container.parent().attr('class') + ' > ' + $container.attr('class') + ')');

			if ($items.length === 0) {
				if ($container.find('.rss-container').length === 0) {

					reCheckCount = $container.data('rss-recheck-count');
					if (!reCheckCount) {
						reCheckCount = 1;
					} else {
						reCheckCount++;
					}

					if (reCheckCount < maxRecheckCount) {
						$container.data('rss-recheck-count', reCheckCount);
						// try again in 1s if .rss-container is not present; if it is, it's an empty feed
						setTimeout(function () {
							readySetGo(nIt, $container);
							}, 1000);
					} else {
						OCMS.consoleMsg('giving up on RSS feed (' + $container.parent().attr('class') + ' > ' + $container.attr('class') + ')');
					}
				}
			} else {
				completionFunction.call($container.find('.rss-container'));
			}

		}	// readySetGo()

		// --- begin waitForRSSWidgetItems ---

		OCMS.consoleMsg('waiting for RSS feeds... number of containers: ' + $feedContainers.length);
		$feedContainers.each(readySetGo);
	}	// waitForRSSWidgetItems


	function prepareHomeRSSFeeds () {

		function prepareAFeed ($feedContainer) {
			var $items = $feedContainer.find('.rss-item'),
				reCheckCount;

			OCMS.consoleMsg('number of Home RSS items: ' + $items.length + '(' + $feedContainer.parent().attr('class') + ')');

			if ($items.length === 0) {
				if ($feedContainer.find('.rss-container').length === 0) {

					reCheckCount = $feedContainer.data('reCheckCount');
					if (!reCheckCount) {
						reCheckCount = 1;
					} else {
						reCheckCount++;
					}

					if (reCheckCount < 11) {
						$feedContainer.data('reCheckCount', reCheckCount);
						// try again in 1s if .rss-container is not present; if it is, it's an empty feed
						setTimeout(function () {
							prepareAFeed($feedContainer);
							}, 1000);
					} else {
						OCMS.consoleMsg('giving up on Home RSS feed (' + $feedContainer.parent().attr('class') + ')');
					}
				}
			} else {
				$items.each(function (nIndex) {
					//	.RSS-Feed
					//		.rss-container
					//			.rss-item
					//				.rss-title
					//				.rss-body
					//				.rss-date
					//			...
					// for each .rss-date:
					//		- convert its text to something nice
					//		- append a div.rss-item-date-tile with "{day}<br>{dow-abbr}" to its div.rss-item

					// limit to 10 as per request 2011-Jul-22
					if (nIndex > 9) {
						$(this).remove();
					} else {
						var sDate = $(this).find('.rss-item-date').text(),
							dDate,
							sTileDate = '';

						if (sDate.length) {
							dDate = new Date(sDate);

							$(this).find('.rss-item-date').html(dDate.getMonthName() + ' ' + dDate.getDate() + ', ' + dDate.getFullYear());

							sTileDate = '<span>' + dDate.getDate() + '</span><br>' + dDate.getMonthNameAbbr();
						} else {
							OCMS.consoleMsg('did not find .rss-item-date!');
						}

						$(this).append('<div class="rss-item-date-tile">' + sTileDate + '</div>');
					}
				});
			}
		}	// prepareAFeed

		// --- begin prepareHomeRSSFeeds ---

		// OCMS.assert(!OCMS.inPageEditor);

		// we expect up to three .RSS-Feeds, each of which will have a .rss-container only when
		// its list of .rss-items has been filled in
		// each feed will fill in its items independently of each other

		$('#homeContentLeftTabs .RSS-Feed').each(function () {
			prepareAFeed($(this));
		});
	}	// prepareHomeRSSFeeds


	function prepareShareThis () {
		if (typeof stLight !== 'undefined') {
			stLight.options({
				publisher: 'b3ecd4dc-58af-4b91-a48f-824d4da10401'
			});
		} else {
			OCMS.consoleMsg('ShareThis was not loaded.');
		}
	}	// prepareShareThis


/*
	function installLightBoxForRightRailSlideshow () {

		// first, some DOM correction to do:
		// the right-rail Slideshow (and Video!) containers use ids instead of classes for
		// the launching link
		var $launchLinks = $('.right-rail-slideshow-image-container > a');

		// TODO
		// currently called only for level1LandingNews... and actually, not even that now!
		OCMS.consoleMsg('confirm RightRailSlideShow markup and JS');

		$launchLinks.each(function () {
			$(this)
				.removeAttr('id')
				.addClass('rightrail-launch-slideshow')
				// hook-up any Start Slideshow links we find to a colorbox slideshow
				.each(function () {
					var $targetImages = $(this).next('.horizontal-image-bar-image').find('a');

					// specify the images to be part of this slideshow
					$targetImages.colorbox({
						transition: 'elastic',
						close: 'CLOSE',
						initialWidth: 200,
						initialHeight: 200
						current: '{current} of {total}'
					});	//, width: '50%', height: '45%'});

					// then hook-up this link to launch that slideshow
					$(this).click(function (evt) {
						evt.preventDefault();
						$targetImages.eq(0).click();
					});
				});
		});
	}	// installLightBoxForRightRailSlideshow
*/

// future things to parameterize:
//		colorbox options
//		launch link text

	function customizeLightboxSlideShow () {

		function fixRRailSlideShow () {
			var $showContainer = $(this),
				$rrls = $showContainer.find('#rightrail-launch-slideshow'),
				ssId,
				$cbItems;

			// first, we'll 'fix' the launch link
			if ($rrls.length === 1) {
				$rrls.removeAttr('id').addClass('rightrail-launch-slideshow');
				//// remove sloppy extra spaces... nah, just redefine it to better text
				//$rrls.text($rrls.text().trim());
				$rrls.text('View Slideshow');
			}

			if ($showContainer.find('.horizontal-image-bar-image a').length === 0) {
				//right-rail-slideshow-image-container
				OCMS.consoleMsg('no slideshow images; hiding View Slideshow link');
				$rrls.hide();
			} else {
				// now, we want to remove the existing colorbox settings from this rightrail slideshow
				// container and install our own
				// simply respecifying on same elements will do it

				// the following expedient logic requires that the relevant HTML source
				// looks something like <div class="right-rail-slideshow-container a0RT000000BoFrmMAF">
				ssId = $showContainer.attr('class').split(' ')[1];	// unique id is 2nd

				if (ssId) {
					$cbItems = $showContainer.find('a[rel="rightrail-slideshow-image-' + ssId + '"]');
					OCMS.consoleMsg('slideshow for ' + $cbItems.length + ' items for ' + ssId);
				} else {
					// sadly, the original RRSlideShow thingy includes JS that sometimes comes up
					// with an empty id for this
					// (this logic could be used with or without the a[rel...] version, which was
					//  based on the approach taken by the component itself)
					$cbItems = $(this).find('.horizontal-image-bar-image > a');
					OCMS.consoleMsg('slideshow for ' + $cbItems.length + ' items by position');

					// colorbox really wants a common rel on these a's
					ssId = Math.random() * 100000;
					$cbItems.each(function () {
						$(this).attr('rel', '.rrsi-' + ssId);
					});

					// ...and, if we're here, the RRSS component threw an exception and didn't complete
					// the launch click hook-ups, so...
					$showContainer.find('a.right-rail-image-link').add($rrls).click(function () {
						$cbItems.eq(0).click();
					})
				}

// link text mystery of Oct-14
				$cbItems.each(function (nIt) {
					var linkText = $(this).text();
					OCMS.consoleMsg('RRSS img ' + nIt + ' ' + linkText);
					if (linkText) {
						$(this).text('');
					}
				});

				$cbItems.colorbox({
					photo: true,			// assure colorbox that those servlet links are photos
					transition: 'elastic',
					close: 'CLOSE',
					initialWidth: 200,
					initialHeight: 200,
					current: '{current} of {total}'
				});

// link text mystery of Oct-14
//				$cbItems.each(function (nIt) {
//					OCMS.consoleMsg('rrss img ' + nIt + ' ' + $(this).text());
//				});

				// only use the pointer when there are slide show images
				$showContainer.find('.right-rail-image-link').addClass('pointer');
			}
		}	// fixRRailSlideShow

		// --- begin customizeLightboxSlideShow ---

		// OCMS.assert(!OCMS.inPageEditor);
 		$('.right-rail-slideshow-container').each(fixRRailSlideShow);
	}	// customizeLightboxSlideShow


	function fixLightBoxForRightRailVideo () {
		// original BROKEN component in-line scripting (see 2011-Sep-06):
		//	var content_id = '';
		//  $("." + content_id + " > .right-rail-video-container > #rightrail-launch-video").colorbox({iframe:true, innerWidth:425, innerHeight:344});
		//	$("." + content_id + " > .right-rail-imageblock-image > .small-block-image > .right-rail-image-link").colorbox({iframe:true, innerWidth:425, innerHeight:344});
		// as is, the above would never have worked!

		// OCMS.assert(!OCMS.inPageEditor);

		// DOM ids must be unique
		// note: this rightrail is not hyphenated
		$('#rightrail-launch-video').each(function (nIt) {
			$(this)
				.removeAttr('id')
				.addClass('rightrail-launch-video')
				.addClass('rrlv-' + nIt);
			OCMS.consoleMsg(this.tagName + '#rightrail-launch-video changed to class: rrlv-' + nIt);
		});

		// qualify .right-rail-image-link since it is also used within .right-rail-slideshow-container
		$('.rightrail-launch-video, .right-rail-video-container .right-rail-image-link')
			.each(function () {
				var href = $(this).attr('href');

				if (href) {
					// to include in a colorbox iframe, the YouTube url
					// should be embed/{videoId}, not watch?v={videoId}
					if (href.indexOf('watch?v=') > 0) {
						$(this).attr('href', href.replace('watch?v=', 'embed/'));
						OCMS.consoleMsg('video link changed to ' + $(this).attr('href'));
					}

                    OCMS.consoleMsg('colorbox\'ing [' + $(this).text().trim() + ']  '  + $(this).attr('href'));

					// use these colorbox settings in preference to those hard-wired within the component
					$(this).colorbox({
						iframe: true,
						close: 'CLOSE',
						innerWidth: 640,	// tricky guesses
						innerHeight: 400,
						onOpen: ECP.colorBoxOpen,
						onClosed: ECP.colorBoxClose
					});
				} else {
					OCMS.consoleMsg('☹ rightrail video link had no href');
				}
			});
	}	// fixLightBoxForRightRailVideo


	function f_rssSlicer (nDefaultLimit) {
		// returns a callback function to limit the number of .rss-item's within the container this
		return function () {
			var maxRSSItems = OCMS.pageOptions('maxRSSItems') || nDefaultLimit || 50;

			$(this).find('.rss-item').slice(maxRSSItems).remove();
		}
	}	// f_rssSlicer


	function prepareSpecificTemplates () {
		var nImageMarqueListItems;

		function removeEmptyHorizontalCarousel (container) {
			var $container = $(container || '.carouselWrap');

			if ($container.find('.jcarousel-item').length === 0 &&
				$container.find('> .carouselTitle').text().trim().length === 0) {

				$container.remove();
				OCMS.consoleMsg('horizontal carousel section has no content; removed from page');
			}
		}	// removeEmptyHorizontalCarousel


		// --- begin prepareSpecificTemplates ---

		// OCMS.assert(!OCMS.inPageEditor);

		if ($('.pgLev3C2Col').length) {
			// Level 3 Content 2-Column page

			createListItemsFromSmallBlocks({
				source: '.droppableArea',
				dest:	'#mycarousel'
			});

			$('#mycarousel').jcarousel({scroll: 3});
//?			$('#mycarousel li:last').addClass('shortenCarousel150');
		} else if ($('.level1LandingNews').length) {
			// .level1LandingNews

			// limit each RSS feed to 10 items, as requested
/*
			$('.rss-container').each(function () {
				$(this).find('.rss-item').slice(maxRSSItems).remove();
			});
*/
			waitForRSSWidgetItems($('.RSS-Container'), f_rssSlicer(10));
			OCMS.consoleMsg('➜ confirm .level1LandingNews RSS feed limiter operation');
		} else if ($('.pgLev3CCW').length) {
			// ECP Level 3 Content Custom Widget
			// (essentially the mangled name for what should be Level-3 Content 1-Column Right Rail)

			// expected only within .content-body-left
			if ($('.RSS-Container').length) {
				waitForRSSWidgetItems($('.RSS-Container'), f_rssSlicer());
			}
			customizeLightboxSlideShow();
		} else if ($('.pgLev2L3B3P').length) {
			// ECP Level2 Landing 3Button 3Photo (e.g. Where We Work > Springville)

			// previously at bottom of template
            nImageMarqueListItems = imageMarqueeInit(230, 203);
            if (nImageMarqueListItems) {
                  $('#mycarousel li:last').addClass('shortenCarousel230');
                  $('#mycarousel')
                      .jcarousel({scroll: 3})	// previously scrolled only 1 at a time (slow, annoying)
					  .jcarousel('buttons');	// call jcarousel internal method: required for IE8 to not show scroll buttons when not relevant
			}

			removeEmptyHorizontalCarousel();
		} else if ($('.pgLev2L4B4PCar').length) {
			// ECP Level2 Landing 4Photo (e.g. S&I > Green)

			// previously at bottom of template
			nImageMarqueListItems = imageMarqueeInit(170, 190);

			if (nImageMarqueListItems) {
				$('#mycarousel li:last').addClass('shortenCarousel170');
				// for some reason, in IE only, this jcarousel({scroll: 4}) call seems to add
				// 4 placeholder li's when this ul#mycarousel is empty
				$('#mycarousel')
				    .jcarousel({scroll: 4})	// previously scrolled only 1 at a time (slow, annoying)
                    .jcarousel('buttons');	// call jcarousel internal method: required for IE8 to not show scroll buttons when not relevant

				// do NOT know why jCarousel insists on showing the > scroll arrow when there
				// are four items that seem to fit within their container but it wants to scroll
				// a bit anyway *further investigation warranted*, but for now: brute force fix
				if ($('.jcarousel-item').length === 4) {
					$('.jcarousel-next').hide();
				}
			}

            removeEmptyHorizontalCarousel();
		} else if ($('.pgLev3LDS').length) {
			// Level 3 Landing Dynamic Spotlight
			prepareRandomFellow();
			waitForRSSWidgetItems($('.RSS-Container'), f_rssSlicer(5));
		} else if ($('.pgLev3LRR').length) {
			// Level 3 Landing Right Rail
			customizeLightboxSlideShow();
		}
	}	// prepareSpecificTemplates


	function installGoHomeClick () {
		$('.header-image').click(function () {
			if (!OCMS.inPageEditor && !OCMS.inPagePreview) {
				window.location.href = "/";
			}
		}).attr('title', OCMS.inPageEditor || OCMS.inPagePreview ? 'go to home page (live site only)' : 'Go to our Home page');
	}	// installGoHomeClick


	function installPrintClick () {
		$('.icon-container img[alt="Print"]').click(function() {
			window.print();
		});
	}	// installPrintClick


	function linkifyBottomImageItems () {
      	OCMS.consoleMsg('.bottom-image-items: ' + $(".bottom-image-item").length);

		$(".bottom-image-item").each(function () {
			var htmlLink = $(".buttonText a", this).attr("href");

//	      	OCMS.consoleMsg('\t buttonText a: ' + htmlLink, ' >> ',
//	      		$('.backRef', this).length,
//	      		$('.bottom-image-arrow', this).length,
//	      		$('.newsPhotoLink', this).length);

			$('.backRef', this).attr('href', htmlLink);
			$('.bottom-image-arrow', this).attr('href', htmlLink);
			$('.newsPhotoLink', this).attr('href', htmlLink);		// occurs less frequently
		});
	}	// linkifyBottomImageItems


	function installMapInteractions () {
		if ($('map#usaMap').length) {
			// wraps a div with a canvas around img.map
			// maphilight.js original source via http://davidlynch.org/js/maphilight/docs/
			$('img.map').maphilight({
				fillColor: '64655d',
				fillOpacity: 1,
				stroke: false,
				strokeColor: '555',		// default for state circles
				fade: false,
				wrapClass: 'mapWrapper',
				groupBy: 'data-maphilight-group'
			});

			//$('map > area').easyTooltip(); /*use for html code version*/
			$("area").easyTooltip();

			// this line appears within thickbox.js, but there are complications and it's not
			// having effect. being called called twice. Hmmph?
			//		$("#TB_closeWindowButton").click(tb_remove);
			// we'll try adding our own
			$("#TB_closeWindowButton").live('click', tb_remove);
		}
	}	// installMapInteractions


	// want to be able to continue to use PlainText for the "Global Descriptive Phrase",
	// yet we need to be able to control line break position
	function prepareSloganText () {
		// expecting and requiring only plain text, we can use .text() instead of .html()
		var $sloganContainer,
			slogan;

		// OCMS.assert(!OCMS.inPageEditor);
		$sloganContainer = $('.header-description');
		if ($sloganContainer.length) {
			slogan = $sloganContainer.text();
			$sloganContainer.html(slogan.replace('{br}', '<br>'));
		}
	}	// prepareSloganText


	function prepareRandomFellow () {

		function prepareRandomFellowSuccessHandler (json, textStatus, xhr) {
			var html = '',
				oFellow = json.objFellowProjects.Fellow,
				aProjects = json.objFellowProjects.Projects;

			// always output div.rfPhoto, but omit the img if no photo
			html += '<h2>Fellow Spotlight</h2><div class="rfPhoto">' +
						(oFellow.FellowPhoto ? ('<img src="' + oFellow.FellowPhoto + '" />') : '') +
					'</div>';

			if (oFellow.FellowName) {
				html += '<h3><span>' + oFellow.FellowName + '</span></h3>';
				if (oFellow.FellowStartYear) {
					html+= oFellow.FellowStartYear + '&ndash;';
					if (oFellow.FellowEndYear) {
						html+= oFellow.FellowEndYear;
					}
				}
			}

			if (oFellow.FellowHostOrgName) {
				html += '<h4>Host</h4>' + oFellow.FellowHostOrgName;
				if (oFellow.FellowCity) {
					html += '<br />' + oFellow.FellowCity;
					if (oFellow.FellowState) {
						html += ", " + oFellow.FellowState;
					}
				}
			}

			// when no projects we're getting an array of 1 element whose value is {}
			if (aProjects.length && aProjects[0].ProjectName) {
				html += '<h4>Projects</h4>';
				for (var i = 0; i < aProjects.length; i++) {
					html += aProjects[i].ProjectName + '<br />';
				}
			}

			if (oFellow.Biography) {
				// probably contains <p> tags, possibly many!
				// gack! it might also have other markup!, including <br />'s instead of <p>'s!

				// we'll work only from the first paragraph

				// self-calling closure for 'local' variables - experimental!
				(function () {
					var bio = oFellow.Biography,
						p1Close = bio.search(/<\/p>/i),
						space;

					if (p1Close >= 0) {
						// assumes it must begin with <p>
						bio = bio.slice(3, p1Close);
					} else {
						p1Close = bio.search(/<br[ \/]?>/i);
						bio = bio.slice(0, p1Close);
					}

					if (bio.length > 350) {
						space = bio.indexOf(' ', 310);
						bio = bio.slice(0, space) + '&hellip;';
						//OCMS.consoleMsg(oFellow.Biography);
						//OCMS.consoleMsg(bio);
					}

					html += '<div class="rfBio">' + bio + '</div>';
				})();
			}

			$('#rfDestination').append(html);

			if (oFellow.FellowBioPage) {
				// wrap a link to their bio page around their photo and their name
				var fellowLinkOpen = '<a href="' + oFellow.FellowBioPage + '" title="learn more about ' + oFellow.FellowName + '">';

				$('#rfDestination .rfPhoto img, #rfDestination h3 span').wrap(fellowLinkOpen);  // jQuery will close the <a> for us
                // 2011-Dec-14 yet another link to full bio
                $('#rfDestination').append(fellowLinkOpen + 'More »</a>');
				//OCMS.consoleMsg('random fellow bio link set to ' + oFellow.FellowBioPage);

				if (OCMS.inPagePreview) {
					$('#rfDestination .rfPhoto a, #rfDestination h3 a, #rfDestination > a').each(function () {
						$(this).attr('title', $(this).attr('title') + ' [PRODUCTION only - does not work in Preview]');
					});
				}
			}
		}	//	getRandomFellowSuccessHandler


        if (ECP.TESTING.fakeRestProxy) {
            OCMS.consoleMsg('orchestraRestProxy: getRandomFellow NOT called');
        } else {
            // grrrr... doAjaxJsonCall pre-flight shenanigans STILL currently required as of now
            var cms = $(document).data('cms'),
                ctxt = cms.context.type || cms.context,
                endpoint = 'ecpocms__RoseFellowPersonAjax';

            if (ctxt === 'site') {
                endpoint = '/' + endpoint;
            }

            $.orchestracmsRestProxy.doAjaxJsonCall(
                endpoint,
                {action: 'getRandomFellow'},
                prepareRandomFellowSuccessHandler,
                true,
                'ecpocms'
            );
        }
	}	// prepareRandomFellow


	function rsrcPath () {
		var $thisScript = $('script[src$="js/ecp.js"]'),
			rPath = '';

		if ($thisScript.length) {
			// 'js/ecp.js' is 9 characters long: omit them
			rPath = $thisScript.attr('src').slice(0, -9);
		}

		return rPath;
	}	// rsrcPath


	function fixTBLoadingAnimation () {
		var rPath;

		if (typeof imgLoader !== 'undefined') {
			//OCMS.consoleMsg('TB\'s imgLoader.src: ' + imgLoader.src);

			rPath = rsrcPath();
			if (rPath) {
				imgLoader.src = rPath + 'images/loadingAnimation.gif';
				OCMS.consoleMsg('TB\'s new imgLoader.src: ' + imgLoader.src);
			}
		}
	}	// fixTBLoadingAnimation


	function tidyStaffContacts () {
		// replace the title for the staff contacts popup
		$('.staff-contacts-link > a').attr('title','Staff Contacts');

		// if Staff Contacts content has not been dropped on the page, remove the link that shows thems
		if ($('#staff-contacts-source').length === 0) {
			$('.contacts-container').hide();
		}
	}	// tidyStaffContacts


	// should now be unnecessary and able to be removed
	function temporary_spanifyHack () {
		if ($('.level1LandingNews').length) {		// and intranet all?
			$('.dropMiddleBoxes h1.document-1-title').each(function () {
				// if this h1 has span siblings, it's not at the right level!
				if ($(this).siblings('span').length > 1) {
					// wrap this and the immediately following span.document-1-content in a span of their own,
					// the way Orchestra used to do (and will again when it's fixed)
					$($(this).add($(this).next()).wrapAll('<span class="spanifyHack">'));
					OCMS.consoleMsg('temporary_SpanifyHack activated!');
				}
			});
		}
	}	// temporary_spanifyHack


	// note: this are "quick" JS-based hacks when an appropriate CSS-based solution
	// was not apparent (i.e. more time might reveal better solutions)
	function hacksForIE () {
		var $widthContainer;

		// hacks for IE7 POS
		if ($.browser.msie && parseInt($.browser.version, 10) === 7) {
			// original source says 13, but that creates a form that's too tall in IE7 and the
			// bottom button gets pushed partly over the edge (why doesn't it just expand in height?)
			$('.staffcontact-email-form #txtBody').attr('rows', '10');


			// heavy-handily correct the width of div.footer-social-media-icons that IE7 believes
			// should be 100% of available width; this div is floated and contains floated images
			// from a Horizonal Image Bar and should take only the required width

			// the spans that enclose the images have an appropriate width (well, almost anyway)
			$widthContainer = $('.footer-social-media-icons > span');
			if ($widthContainer.length) {
				$widthContainer.parent().css('width', $widthContainer.width() + 15);
				OCMS.consoleMsg('.footer-social-media-icons width set to ' +
					($widthContainer.width() + 15) +
					', and is now ' +
					$widthContainer.parent().css('width')
				);
			}

			// Home page's middle/right in place slideshow containers (.tabbox) don't
			// fill the width of their container as they should in IE7
			$widthContainer = $('#homeContentRightTabs .tabBoxArea');
			if ($widthContainer.length) {
				// - 2px for left and right 1px borders
				$widthContainer.find('.tabBox').css('width', $widthContainer.width() - 2);
				OCMS.consoleMsg('#homeContentRightTabs .tabBox width set to ' +
					($widthContainer.width() - 2) +
					', and is now ' +
					$widthContainer.find('.tabBox').css('width')
					);
			}

			// table cell display properties have been used to vertically middle align
			// "button" text, but IE7 knows nothing of this
			$('.buttonTableCell a').each(function checkForTwoLineButtonCellLinks () {
				if ($(this).height() > 26) {	// nominally seen as 21px, with two-lines being 42px
					$(this).addClass('twoLines');
				}
			});
		}
	}	// hacksForIE


	// --- begin $().ready() ---
	try {
		OCMS.consoleMsg('♦♢ ecp.js:$().ready() -- START ♢♦ ', Date());

		OCMS.addBrowserClasses();
		OCMS.addAuthorClasses();
		OCMS.removeEditorHints();

		prepareFooterSignUpForm();

		if (!OCMS.inPageEditor) {
			prepareHomeCarousel();

			// - build slide shows for each special Small Block With Image container
			// - currently expected to be only on home page (PublicHome), middle-right and now
			//	 the News & Events main page (Level1LandingNews)
			$('.sbwiStaticSlides').each(function (nIt, el) {
				buildBulletNavStaticSlideShow(el, '.small-block, span > .right-rail-video-container');
			});

			// fix-up the carousel text for the mid-page, tab-based static carousels (that originally
			// only supported SmallBlockWithImage content
			$('.tabBox .sbwiStaticSlides span > .right-rail-video-container').each(function () {
				var $videoDescription = $('.right-rail-imageblock-content-body', this);

				if ($videoDescription.length === 1) {
					var oldDesc = $videoDescription.html().trim();
					var newDesc = formattedCarouselDescription(oldDesc, $(this).parent());

					$videoDescription.html(newDesc);
				}
			});


            // replacement for former div#content-carousel > div.gallery > div.rotator concoction
			prepareSlideDeck();

			fixLightBoxForRightRailVideo();

			prepareHomeRSSFeeds();	// nothing to do if not Home page (or in page editor)

			prepareSloganText();

			installPrintClick();

			tidyStaffContacts();

			prepareSpecificTemplates();

			linkifyBottomImageItems();
		}

		prepareShareThis();

		installGoHomeClick();

		installMapInteractions();

		hacksForIE();

		setTimeout(fixTBLoadingAnimation, 3);	// tries only once, hope 3s is enough

		OCMS.consoleMsg('♦♦ ecp.js:$().ready() -- EXIT ♦♦ ', Date());
	} catch (ex) {
		OCMS.consoleMsg('▶▶ ecp.ready()', ex);
        if (ex.type) {
            console.log('\t' + ex.type);
        }
        if (ex.arguments && ex.arguments.length) {
            for (var nIt = 0; nIt < ex.arguments.length; ++nIt) {
                console.log('\t' + ex.arguments[nIt]);
            }
        }
	}
});	// $(document).ready


/* Dec-09 Richard's bio-update */
function loadBio (bioNum) {
	$('body').append('<div id="inlineBio"><div class="bioBodyContent"></div></div>');

   // $('#TB_title').remove();
   $('#indBioWrap').remove();
//!?   $('#indBioWrap').css('visibility', 'visible');

   var userName = myData[bioNum].Name;

   var newHtml = '<div id="indBioWrap"><div class="indBioLeft">';

    if (myData[bioNum].Image) {
        newHtml = newHtml + '<img src="' + myData[bioNum].Image + '" />';
    } else {
        newHtml = newHtml + '<div class="indBioNoPhoto"></div>';
    }

   newHtml = newHtml + '<div class="indBioName">' +
            myData[bioNum].Name + '</div><div class="indBioTitle">' +
            myData[bioNum].Title + '</div><div class="indBioPhone">' +
            myData[bioNum].Phone + '</div><a class="indBioPrint" href="#" onclick="generateBioPDF(\'' +
            myData[bioNum].Id + '\');">Print Bio</a></div>';

    var bioid = myData[bioNum].bioId;

    var params = {
        action: 'getBioText',
        id:     bioid
    };

    var biotext = '';

	var cms = $(document).data('cms');
	var endpoint;
	var ctxt;
	if (cms.context.type !== undefined) {
		ctxt = cms.context.type;
	} else {
		ctxt = cms.context;
	}

    endpoint = 'ecpocms__StaffBioAjax';

    $.orchestracmsRestProxy.doAjaxJsonCall(endpoint, params,
        function(json, testStatus, xhr) {
            if (json.bioBiography) {
                biotext = json.bioBiography;
            } else {
                biotext = '';
            }
           }, false, 'ecpocms');    // note: asynchronous call: we'll wait for the content

    newHtml = newHtml + '<div class="indBioRight">' + biotext + '</div>';

    $('.bioBodyContent').append(newHtml);
    var bodyHeight = $('.bioBodyContent').height();
    $('.bioBorderLeft').height(bodyHeight);
    $('.bioBorderRight').height(bodyHeight);

    // show after content has been added
	tb_show("", "#TB_inline?height=440&width=840&inlineId=inlineBio&noresize", "");
}   // loadBio

function generateBioPDF(bioId){
	objWindow = window.open('/ecpocms__BiographyPDF?bioId=' + bioId);
}

// sortByTier was formerly duplicated in ECPLeaders and ECPLeadersInvestment
// Function that will be used to sort all the users coming back alphabetically in order to make finding a user easier
function sortByTier (a, b) {
    var asrt,
        bsrt,
        x1,
        y1,
        x2,
        y2,
        aname,
        bname,
        retval = 0;

    if (!a.bioTier) {
        a.bioTier = '999';
    }
    if (!b.bioTier) {
        b.bioTier = '999';
    }

    x1 = a.bioTier.toLowerCase();
    y1 = b.bioTier.toLowerCase();

    if (!a.bioUserName) {
        a.bioUserName = '';
    }
    if (!b.bioUserName) {
        b.bioUserName = '';
    }
    aname = a.bioUserName.split(' ');
    bname = b.bioUserName.split(' ');

    if (aname.length) {
        x2 = aname[aname.length - 1].toLowerCase();
    } else {
        x2 = '';
    }

    if (bname.length) {
        y2 = bname[bname.length - 1].toLowerCase();
    } else {
        y2 = '';
    }

    if ([x1, x2] > [y1, y2]) {
        retval = 1;
    } else if ([x1, x2] < [y1, y2]) {
        retval = -1;
    }

    //OCMS.consoleMsg(retval, x1, x2, '---', y1, y2);

    return retval;
}   // sortByTier
