/*
 * jQuery blockUI plugin
 * Version 2.23 (21-JUN-2009)
 * @requires jQuery v1.2.3 or later
 *
 * Examples at: http://malsup.com/jquery/block/
 * Copyright (c) 2007-2008 M. Alsup
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
 */

;(function($) {

if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
 alert('blockUI requires jQuery v1.2.3 or later! You are using v' + $.fn.jquery);
 return;
}

$.fn._fadeIn = $.fn.fadeIn;

// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
// retarded userAgent strings on Vista)
var mode = document.documentMode || 0;
var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8);
var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode;

//optaros-fangento: allow styles to be overridden in-code (see below)
var styleOverride = null;
$.growlStyleOverride = function(styleOverrideParam) {
 styleOverride = styleOverrideParam;
}
//optaros-fangento: allow growl to be centered in window (see below)
var isCentered = false;
$.growlCenter = function(isCenteredParam) {
 isCentered = isCenteredParam;
}

// global $ methods for blocking/unblocking the entire page
$.blockUI = function(opts) { install(window, opts); };
$.unblockUI = function(opts) { remove(window, opts); };

// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
/* optaros-fangento: fadeTo animates growl towards an element */
$.growlUI = function(title, message, timeout, onClose, fadeTo) {
 var $m = $('<div class="growlUI"></div>');
 if (title) $m.append('<h1>'+title+'</h1>');
 if (message) $m.append('<h2>'+message+'</h2>');
 if (timeout == undefined) timeout = 3000;

 var css = $.blockUI.defaults.growlCSS;

 //optaros-fangento:
 if (styleOverride) {
 css = $.extend({}, css);
 for (var x in styleOverride)
 css[x] = styleOverride[x];
 }

 //optaros-fangento:
 if (isCentered) {
 css = $.extend({}, css);
 var jWin = $(window);
 css.top = (jWin.height()/3) + 'px';
 css.right = (jWin.width()/2 - parseInt(css.width)/2) + 'px';
 }

 $.blockUI({
 message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
 timeout: timeout, showOverlay: false,
 onUnblock: onClose,
 //optaros-fangento:
 css: css,
 //optaros-fangento:
 fadeTo: fadeTo
 });
};

// plugin method for blocking element content
$.fn.block = function(opts) {
 return this.unblock({ fadeOut: 0 }).each(function() {
 if ($.css(this,'position') == 'static')
 this.style.position = 'relative';
 if ($.browser.msie)
 this.style.zoom = 1; // force 'hasLayout'
 install(this, opts);
 });
};

// plugin method for unblocking element content
$.fn.unblock = function(opts) {
 return this.each(function() {
 remove(this, opts);
 });
};

$.blockUI.version = 2.23; // 2nd generation blocking at no extra cost!

// override these in your code to change the default behavior and style
$.blockUI.defaults = {
 // message displayed when blocking (use null for no message)
 message: '<h1>Please wait...</h1>',

 // styles for the message when blocking; if you wish to disable
 // these and use an external stylesheet then do this in your code:
 // $.blockUI.defaults.css = {};
 css: {
 padding: 0,
 margin: 0,
 width: '30%',
 top: '40%',
 left: '35%',
 textAlign: 'center',
 color: '#000',
 border: '3px solid #aaa',
 backgroundColor:'#fff',
 cursor: 'wait'
 },

 // styles for the overlay
 overlayCSS: {
 backgroundColor: '#000',
 opacity: 0.6,
 cursor: 'wait'
 },

 // styles applied when using $.growlUI
 growlCSS: {
 width: '350px',
 top: '10px',
 left: '',
 right: '10px',
 border: 'none',
 padding: '5px',
 opacity: 0.6,
 cursor: null,
 color: '#fff',
 backgroundColor: '#000',
 '-webkit-border-radius': '10px',
 '-moz-border-radius': '10px'
 },

 // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
 // (hat tip to Jorge H. N. de Vasconcelos)
 iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',

 // force usage of iframe in non-IE browsers (handy for blocking applets)
 forceIframe: false,

 // z-index for the blocking overlay
 baseZ: 1000,

 // set these to true to have the message automatically centered
 centerX: true, // <-- only effects element blocking (page block controlled via css above)
 centerY: true,

 // allow body element to be stetched in ie6; this makes blocking look better
 // on "short" pages. disable if you wish to prevent changes to the body height
 allowBodyStretch: true,

 // enable if you want key and mouse events to be disabled for content that is blocked
 bindEvents: true,

 // be default blockUI will supress tab navigation from leaving blocking content
 // (if bindEvents is true)
 constrainTabKey: true,

 // fadeIn time in millis; set to 0 to disable fadeIn on block
 fadeIn: 200,

 // fadeOut time in millis; set to 0 to disable fadeOut on unblock
 fadeOut: 400,

 // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
 timeout: 0,

 // disable if you don't want to show the overlay
 showOverlay: true,

 // if true, focus will be placed in the first available input field when
 // page blocking
 focusInput: true,

 // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
 applyPlatformOpacityRules: true,

 // callback method invoked when unblocking has completed; the callback is
 // passed the element that has been unblocked (which is the window object for page
 // blocks) and the options that were passed to the unblock call:
 // onUnblock(element, options)
 onUnblock: null,

 // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
 quirksmodeOffsetHack: 4
};

// private data and functions follow...

var pageBlock = null;
var pageBlockEls = [];

function install(el, opts) {
 var full = (el == window);
 var msg = opts && opts.message !== undefined ? opts.message : undefined;
 opts = $.extend({}, $.blockUI.defaults, opts || {});
 opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
 var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
 msg = msg === undefined ? opts.message : msg;

 // remove the current block (if there is one)
 if (full && pageBlock)
 remove(window, {fadeOut:0});

 // if an existing element is being used as the blocking content then we capture
 // its current place in the DOM (and current display style) so we can restore
 // it when we unblock
 if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
 var node = msg.jquery ? msg[0] : msg;
 var data = {};
 $(el).data('blockUI.history', data);
 data.el = node;
 data.parent = node.parentNode;
 data.display = node.style.display;
 data.position = node.style.position;
 if (data.parent)
 data.parent.removeChild(node);
 }

 var z = opts.baseZ;

 // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
 // layer1 is the iframe layer which is used to supress bleed through of underlying content
 // layer2 is the overlay layer which has opacity and a wait cursor (by default)
 // layer3 is the message content that is displayed while blocking

 var lyr1 = ($.browser.msie || opts.forceIframe)
 ? $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>')
 : $('<div class="blockUI" style="display:none"></div>');
 var lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
 var lyr3 = full ? $('<div class="blockUI blockMsg blockPage" style="z-index:'+z+';display:none;position:fixed"></div>')
 : $('<div class="blockUI blockMsg blockElement" style="z-index:'+z+';display:none;position:absolute"></div>');

 // if we have a message, style it
 if (msg)
 lyr3.css(css);

 // style the overlay
 if (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform)))
 lyr2.css(opts.overlayCSS);
 lyr2.css('position', full ? 'fixed' : 'absolute');

 // make iframe layer transparent in IE
 if ($.browser.msie || opts.forceIframe)
 lyr1.css('opacity',0.0);

 $([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);

 // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
 var expr = setExpr && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
 if (ie6 || expr) {
 // give body 100% height
 if (full && opts.allowBodyStretch && $.boxModel)
 $('html,body').css('height','100%');

 // fix ie6 issue when blocked element has a border width
 if ((ie6 || !$.boxModel) && !full) {
 var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
 var fixT = t ? '(0 - '+t+')' : 0;
 var fixL = l ? '(0 - '+l+')' : 0;
 }

 // simulate fixed position
 $.each([lyr1,lyr2,lyr3], function(i,o) {
 var s = o[0].style;
 s.position = 'absolute';
 if (i < 2) {
 full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
 : s.setExpression('height','this.parentNode.offsetHeight + "px"');
 full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
 : s.setExpression('width','this.parentNode.offsetWidth + "px"');
 if (fixL) s.setExpression('left', fixL);
 if (fixT) s.setExpression('top', fixT);
 }
 else if (opts.centerY) {
 if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
 s.marginTop = 0;
 }
 else if (!opts.centerY && full) {
 var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0;
 var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
 s.setExpression('top',expression);
 }
 });
 }

 // show the message
 if (msg) {
 lyr3.append(msg);
 if (msg.jquery || msg.nodeType)
 $(msg).show();
 }

 if (($.browser.msie || opts.forceIframe) && opts.showOverlay)
 lyr1.show(); // opacity is zero
 if (opts.fadeIn) {
 if (opts.showOverlay)
 lyr2._fadeIn(opts.fadeIn);
 if (msg)
 lyr3.fadeIn(opts.fadeIn);
 }
 else {
 if (opts.showOverlay)
 lyr2.show();
 if (msg)
 lyr3.show();
 }

 // bind key and mouse events
 bind(1, el, opts);

 if (full) {
 pageBlock = lyr3[0];
 pageBlockEls = $(':input:enabled:visible',pageBlock);
 if (opts.focusInput)
 setTimeout(focus, 20);
 }
 else
 center(lyr3[0], opts.centerX, opts.centerY);

 if (opts.timeout) {
 // auto-unblock
 var to = setTimeout(function() {
 full ? $.unblockUI(opts) : $(el).unblock(opts);
 }, opts.timeout);
 $(el).data('blockUI.timeout', to);
 }
};

// remove the block
function remove(el, opts) {
 var full = el == window;
 var $el = $(el);
 var data = $el.data('blockUI.history');
 var to = $el.data('blockUI.timeout');
 if (to) {
 clearTimeout(to);
 $el.removeData('blockUI.timeout');
 }
 opts = $.extend({}, $.blockUI.defaults, opts || {});
 bind(0, el, opts); // unbind events
 var els = full ? $('body').children().filter('.blockUI') : $('.blockUI', el);

 if (full)
 pageBlock = pageBlockEls = null;

 //optaros-fangento:
 if (opts.fadeTo && opts.fadeOut) {
 var fadeToPos = opts.fadeTo.position();
 els.animate({
 right: $(window).width() - (fadeToPos.left + parseInt(opts.css.width)),
 top: fadeToPos.top,
 opacity: 0.05
 }, opts.fadeOut);
 setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
 }
 else if (opts.fadeOut) {
 els.fadeOut(opts.fadeOut);
 setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
 }
 else
 reset(els, data, opts, el);
};

// move blocking element back into the DOM where it started
function reset(els,data,opts,el) {
 els.each(function(i,o) {
 // remove via DOM calls so we don't lose event handlers
 if (this.parentNode)
 this.parentNode.removeChild(this);
 });

 if (data && data.el) {
 data.el.style.display = data.display;
 data.el.style.position = data.position;
 if (data.parent)
 data.parent.appendChild(data.el);
 $(data.el).removeData('blockUI.history');
 }

 if (typeof opts.onUnblock == 'function')
 opts.onUnblock(el,opts);
};

// bind/unbind the handler
function bind(b, el, opts) {
 var full = el == window, $el = $(el);

 // don't bother unbinding if there is nothing to unbind
 if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
 return;
 if (!full)
 $el.data('blockUI.isBlocked', b);

 // don't bind events when overlay is not in use or if bindEvents is false
 if (!opts.bindEvents || (b && !opts.showOverlay))
 return;

 // bind anchors and inputs for mouse and key events
 var events = 'mousedown mouseup keydown keypress';
 b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler);

// former impl...
// var $e = $('a,:input');
// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
};

// event handler to suppress keyboard/mouse events when blocking
function handler(e) {
 // allow tab navigation (conditionally)
 if (e.keyCode && e.keyCode == 9) {
 if (pageBlock && e.data.constrainTabKey) {
 var els = pageBlockEls;
 var fwd = !e.shiftKey && e.target == els[els.length-1];
 var back = e.shiftKey && e.target == els[0];
 if (fwd || back) {
 setTimeout(function(){focus(back)},10);
 return false;
 }
 }
 }
 // allow events within the message content
 if ($(e.target).parents('div.blockMsg').length > 0)
 return true;

 // allow events for content that is not being blocked
 return $(e.target).parents().children().filter('div.blockUI').length == 0;
};

function focus(back) {
 if (!pageBlockEls)
 return;
 var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
 if (e)
 e.focus();
};

function center(el, x, y) {
 var p = el.parentNode, s = el.style;
 var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
 var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
 if (x) s.left = l > 0 ? (l+'px') : '0';
 if (y) s.top = t > 0 ? (t+'px') : '0';
};

function sz(el, p) {
 return parseInt($.css(el,p))||0;
};

})(jQuery);

/*
 * jQuery Autocomplete plugin 1.1
 *
 * Copyright (c) 2009 Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $
 * optaros-fangento: changed "hasFocus++>1" to "hasFocus++>0" so that dropdown would pop on single-click instead of double-click (see http://www.edwardotis.net/tech/?p=158)
 */;(function($){$.fn.extend({autocomplete:function(urlOrData,options){var isUrl=typeof urlOrData=="string";options=$.extend({},$.Autocompleter.defaults,{url:isUrl?urlOrData:null,data:isUrl?null:urlOrData,delay:isUrl?$.Autocompleter.defaults.delay:10,max:options&&!options.scroll?10:150},options);options.highlight=options.highlight||function(value){return value;};options.formatMatch=options.formatMatch||options.formatItem;return this.each(function(){new $.Autocompleter(this,options);});},result:function(handler){return this.bind("result",handler);},search:function(handler){return this.trigger("search",[handler]);},flushCache:function(){return this.trigger("flushCache");},setOptions:function(options){return this.trigger("setOptions",[options]);},unautocomplete:function(){return this.trigger("unautocomplete");}});$.Autocompleter=function(input,options){var KEY={UP:38,DOWN:40,DEL:46,TAB:9,RETURN:13,ESC:27,COMMA:188,PAGEUP:33,PAGEDOWN:34,BACKSPACE:8};var $input=$(input).attr("autocomplete","off").addClass(options.inputClass);var timeout;var previousValue="";var cache=$.Autocompleter.Cache(options);var hasFocus=0;var lastKeyPressCode;var config={mouseDownOnSelect:false};var select=$.Autocompleter.Select(options,input,selectCurrent,config);var blockSubmit;$.browser.opera&&$(input.form).bind("submit.autocomplete",function(){if(blockSubmit){blockSubmit=false;return false;}});$input.bind(($.browser.opera?"keypress":"keydown")+".autocomplete",function(event){hasFocus=1;lastKeyPressCode=event.keyCode;switch(event.keyCode){case KEY.UP:event.preventDefault();if(select.visible()){select.prev();}else{onChange(0,true);}break;case KEY.DOWN:event.preventDefault();if(select.visible()){select.next();}else{onChange(0,true);}break;case KEY.PAGEUP:event.preventDefault();if(select.visible()){select.pageUp();}else{onChange(0,true);}break;case KEY.PAGEDOWN:event.preventDefault();if(select.visible()){select.pageDown();}else{onChange(0,true);}break;case options.multiple&&$.trim(options.multipleSeparator)==","&&KEY.COMMA:case KEY.TAB:case KEY.RETURN:if(selectCurrent()){event.preventDefault();blockSubmit=true;return false;}break;case KEY.ESC:select.hide();break;default:clearTimeout(timeout);timeout=setTimeout(onChange,options.delay);break;}}).focus(function(){hasFocus++;}).blur(function(){hasFocus=0;if(!config.mouseDownOnSelect){hideResults();}}).click(function(){if(hasFocus++>0&&!select.visible()){onChange(0,true);}}).bind("search",function(){var fn=(arguments.length>1)?arguments[1]:null;function findValueCallback(q,data){var result;if(data&&data.length){for(var i=0;i<data.length;i++){if(data[i].result.toLowerCase()==q.toLowerCase()){result=data[i];break;}}}if(typeof fn=="function")fn(result);else $input.trigger("result",result&&[result.data,result.value]);}$.each(trimWords($input.val()),function(i,value){request(value,findValueCallback,findValueCallback);});}).bind("flushCache",function(){cache.flush();}).bind("setOptions",function(){$.extend(options,arguments[1]);if("data"in arguments[1])cache.populate();}).bind("unautocomplete",function(){select.unbind();$input.unbind();$(input.form).unbind(".autocomplete");});function selectCurrent(){var selected=select.selected();if(!selected)return false;var v=selected.result;previousValue=v;if(options.multiple){var words=trimWords($input.val());if(words.length>1){var seperator=options.multipleSeparator.length;var cursorAt=$(input).selection().start;var wordAt,progress=0;$.each(words,function(i,word){progress+=word.length;if(cursorAt<=progress){wordAt=i;return false;}progress+=seperator;});words[wordAt]=v;v=words.join(options.multipleSeparator);}v+=options.multipleSeparator;}$input.val(v);hideResultsNow();$input.trigger("result",[selected.data,selected.value]);return true;}function onChange(crap,skipPrevCheck){if(lastKeyPressCode==KEY.DEL){select.hide();return;}var currentValue=$input.val();if(!skipPrevCheck&&currentValue==previousValue)return;previousValue=currentValue;currentValue=lastWord(currentValue);if(currentValue.length>=options.minChars){$input.addClass(options.loadingClass);if(!options.matchCase)currentValue=currentValue.toLowerCase();request(currentValue,receiveData,hideResultsNow);}else{stopLoading();select.hide();}};function trimWords(value){if(!value)return[""];if(!options.multiple)return[$.trim(value)];return $.map(value.split(options.multipleSeparator),function(word){return $.trim(value).length?$.trim(word):null;});}function lastWord(value){if(!options.multiple)return value;var words=trimWords(value);if(words.length==1)return words[0];var cursorAt=$(input).selection().start;if(cursorAt==value.length){words=trimWords(value)}else{words=trimWords(value.replace(value.substring(cursorAt),""));}return words[words.length-1];}function autoFill(q,sValue){if(options.autoFill&&(lastWord($input.val()).toLowerCase()==q.toLowerCase())&&lastKeyPressCode!=KEY.BACKSPACE){$input.val($input.val()+sValue.substring(lastWord(previousValue).length));$(input).selection(previousValue.length,previousValue.length+sValue.length);}};function hideResults(){clearTimeout(timeout);timeout=setTimeout(hideResultsNow,200);};function hideResultsNow(){var wasVisible=select.visible();select.hide();clearTimeout(timeout);stopLoading();if(options.mustMatch){$input.search(function(result){if(!result){if(options.multiple){var words=trimWords($input.val()).slice(0,-1);$input.val(words.join(options.multipleSeparator)+(words.length?options.multipleSeparator:""));}else{$input.val("");$input.trigger("result",null);}}});}};function receiveData(q,data){if(data&&data.length&&hasFocus){stopLoading();select.display(data,q);autoFill(q,data[0].value);select.show();}else{hideResultsNow();}};function request(term,success,failure){if(!options.matchCase)term=term.toLowerCase();var data=cache.load(term);if(data&&data.length){success(term,data);}else if((typeof options.url=="string")&&(options.url.length>0)){var extraParams={timestamp:+new Date()};$.each(options.extraParams,function(key,param){extraParams[key]=typeof param=="function"?param():param;});$.ajax({mode:"abort",port:"autocomplete"+input.name,dataType:options.dataType,url:options.url,data:$.extend({q:lastWord(term),limit:options.max},extraParams),success:function(data){var parsed=options.parse&&options.parse(data)||parse(data);cache.add(term,parsed);success(term,parsed);}});}else{select.emptyList();failure(term);}};function parse(data){var parsed=[];var rows=data.split("\n");for(var i=0;i<rows.length;i++){var row=$.trim(rows[i]);if(row){row=row.split("|");parsed[parsed.length]={data:row,value:row[0],result:options.formatResult&&options.formatResult(row,row[0])||row[0]};}}return parsed;};function stopLoading(){$input.removeClass(options.loadingClass);};};$.Autocompleter.defaults={inputClass:"ac_input",resultsClass:"ac_results",loadingClass:"ac_loading",minChars:1,delay:400,matchCase:false,matchSubset:true,matchContains:false,cacheLength:10,max:100,mustMatch:false,extraParams:{},selectFirst:true,formatItem:function(row){return row[0];},formatMatch:null,autoFill:false,width:0,multiple:false,multipleSeparator:", ",highlight:function(value,term){return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)("+term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")+")(?![^<>]*>)(?![^&;]+;)","gi"),"<strong>$1</strong>");},scroll:true,scrollHeight:180};$.Autocompleter.Cache=function(options){var data={};var length=0;function matchSubset(s,sub){if(!options.matchCase)s=s.toLowerCase();var i=s.indexOf(sub);if(options.matchContains=="word"){i=s.toLowerCase().search("\\b"+sub.toLowerCase());}if(i==-1)return false;return i==0||options.matchContains;};function add(q,value){if(length>options.cacheLength){flush();}if(!data[q]){length++;}data[q]=value;}function populate(){if(!options.data)return false;var stMatchSets={},nullData=0;if(!options.url)options.cacheLength=1;stMatchSets[""]=[];for(var i=0,ol=options.data.length;i<ol;i++){var rawValue=options.data[i];rawValue=(typeof rawValue=="string")?[rawValue]:rawValue;var value=options.formatMatch(rawValue,i+1,options.data.length);if(value===false)continue;var firstChar=value.charAt(0).toLowerCase();if(!stMatchSets[firstChar])stMatchSets[firstChar]=[];var row={value:value,data:rawValue,result:options.formatResult&&options.formatResult(rawValue)||value};stMatchSets[firstChar].push(row);if(nullData++<options.max){stMatchSets[""].push(row);}};$.each(stMatchSets,function(i,value){options.cacheLength++;add(i,value);});}setTimeout(populate,25);function flush(){data={};length=0;}return{flush:flush,add:add,populate:populate,load:function(q){if(!options.cacheLength||!length)return null;if(!options.url&&options.matchContains){var csub=[];for(var k in data){if(k.length>0){var c=data[k];$.each(c,function(i,x){if(matchSubset(x.value,q)){csub.push(x);}});}}return csub;}else
if(data[q]){return data[q];}else
if(options.matchSubset){for(var i=q.length-1;i>=options.minChars;i--){var c=data[q.substr(0,i)];if(c){var csub=[];$.each(c,function(i,x){if(matchSubset(x.value,q)){csub[csub.length]=x;}});return csub;}}}return null;}};};$.Autocompleter.Select=function(options,input,select,config){var CLASSES={ACTIVE:"ac_over"};var listItems,active=-1,data,term="",needsInit=true,element,list;function init(){if(!needsInit)return;element=$("<div/>").hide().addClass(options.resultsClass).css("position","absolute").appendTo(document.body);list=$("<ul/>").appendTo(element).mouseover(function(event){if(target(event).nodeName&&target(event).nodeName.toUpperCase()=='LI'){active=$("li",list).removeClass(CLASSES.ACTIVE).index(target(event));$(target(event)).addClass(CLASSES.ACTIVE);}}).click(function(event){$(target(event)).addClass(CLASSES.ACTIVE);select();input.focus();return false;}).mousedown(function(){config.mouseDownOnSelect=true;}).mouseup(function(){config.mouseDownOnSelect=false;});if(options.width>0)element.css("width",options.width);needsInit=false;}function target(event){var element=event.target;while(element&&element.tagName!="LI")element=element.parentNode;if(!element)return[];return element;}function moveSelect(step){listItems.slice(active,active+1).removeClass(CLASSES.ACTIVE);movePosition(step);var activeItem=listItems.slice(active,active+1).addClass(CLASSES.ACTIVE);if(options.scroll){var offset=0;listItems.slice(0,active).each(function(){offset+=this.offsetHeight;});if((offset+activeItem[0].offsetHeight-list.scrollTop())>list[0].clientHeight){list.scrollTop(offset+activeItem[0].offsetHeight-list.innerHeight());}else if(offset<list.scrollTop()){list.scrollTop(offset);}}};function movePosition(step){active+=step;if(active<0){active=listItems.size()-1;}else if(active>=listItems.size()){active=0;}}function limitNumberOfItems(available){return options.max&&options.max<available?options.max:available;}function fillList(){list.empty();var max=limitNumberOfItems(data.length);for(var i=0;i<max;i++){if(!data[i])continue;var formatted=options.formatItem(data[i].data,i+1,max,data[i].value,term);if(formatted===false)continue;var li=$("<li/>").html(options.highlight(formatted,term)).addClass(i%2==0?"ac_even":"ac_odd").appendTo(list)[0];$.data(li,"ac_data",data[i]);}listItems=list.find("li");if(options.selectFirst){listItems.slice(0,1).addClass(CLASSES.ACTIVE);active=0;}if($.fn.bgiframe)list.bgiframe();}return{display:function(d,q){init();data=d;term=q;fillList();},next:function(){moveSelect(1);},prev:function(){moveSelect(-1);},pageUp:function(){if(active!=0&&active-8<0){moveSelect(-active);}else{moveSelect(-8);}},pageDown:function(){if(active!=listItems.size()-1&&active+8>listItems.size()){moveSelect(listItems.size()-1-active);}else{moveSelect(8);}},hide:function(){element&&element.hide();listItems&&listItems.removeClass(CLASSES.ACTIVE);active=-1;},visible:function(){return element&&element.is(":visible");},current:function(){return this.visible()&&(listItems.filter("."+CLASSES.ACTIVE)[0]||options.selectFirst&&listItems[0]);},show:function(){var offset=$(input).offset();element.css({width:typeof options.width=="string"||options.width>0?options.width:$(input).width(),top:offset.top+input.offsetHeight,left:offset.left}).show();if(options.scroll){list.scrollTop(0);list.css({maxHeight:options.scrollHeight,overflow:'auto'});if($.browser.msie&&typeof document.body.style.maxHeight==="undefined"){var listHeight=0;listItems.each(function(){listHeight+=this.offsetHeight;});var scrollbarsVisible=listHeight>options.scrollHeight;list.css('height',scrollbarsVisible?options.scrollHeight:listHeight);if(!scrollbarsVisible){listItems.width(list.width()-parseInt(listItems.css("padding-left"))-parseInt(listItems.css("padding-right")));}}}},selected:function(){var selected=listItems&&listItems.filter("."+CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);return selected&&selected.length&&$.data(selected[0],"ac_data");},emptyList:function(){list&&list.empty();},unbind:function(){element&&element.remove();}};};$.fn.selection=function(start,end){if(start!==undefined){return this.each(function(){if(this.createTextRange){var selRange=this.createTextRange();if(end===undefined||start==end){selRange.move("character",start);selRange.select();}else{selRange.collapse(true);selRange.moveStart("character",start);selRange.moveEnd("character",end);selRange.select();}}else if(this.setSelectionRange){this.setSelectionRange(start,end);}else if(this.selectionStart){this.selectionStart=start;this.selectionEnd=end;}});}var field=this[0];if(field.createTextRange){var range=document.selection.createRange(),orig=field.value,teststring="<->",textLength=range.text.length;range.text=teststring;var caretAt=field.value.indexOf(teststring);field.value=orig;this.selection(caretAt,caretAt+textLength);return{start:caretAt,end:caretAt+textLength}}else if(field.selectionStart!==undefined){return{start:field.selectionStart,end:field.selectionEnd}}};})(jQuery);
/**
 * Copyright 2009 Optaros, Inc.
 */

//Magento includes prototype and scriptaculous
jQuery.noConflict();

//global vars
var fangento_pin_open = false;
var fangento_friends = new Array();
var fangento_sliding = false;

/**
 * Case-insensitive "contains" extension
 * See: http://stackoverflow.com/questions/187537/is-there-a-case-insensitive-jquery-contains-selector
 *
 */
jQuery.expr[':'].contains_ci = function(a,i,m){ return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase())>=0; };


/**
 * Extracts a URL param.
 * See: http://stackoverflow.com/questions/979975/how-to-get-the-value-from-url-parameter
 *
 */
function fangento_urlParam(param) {
 var regex = '[?&]' + param + '=([^&#]*)';
 var results = (new RegExp(regex)).exec(window.location.href);
 if(results) return results[1];
 return '';
}


/**
 * Formats a date.
 *
 */
function fangento_date_format(date) {
 date = new Date(date * 1000);

 var month = date.getMonth() + 1;
 var day = date.getDate();
 var hour = date.getHours();
 var min = date.getMinutes();

 var hourStr = hour;
 var amPm = 'am';
 if (hour == 0) {
 hourStr = '12';
 }
 else if (hour > 12) {
 hourStr = (hour - 12);
 amPm = 'pm';
 }

 if (min < 10) {
 minStr = '0' + min;
 }
 else {
 minStr = min;
 }

 var returnStr = month + '/' + day + ' at ' + hourStr + ':' + minStr + ' ' + amPm;
 return returnStr;
}


/**
 * jQuery init.
 *
 */
jQuery(document).ready(function() {

 jQuery.growlStyleOverride({backgroundColor: '#FFFF66', opacity: 0.75});

 //grows should be centerized
 jQuery.growlCenter(true);

 //FIX: is there a way to unattach these selectors when they're not needed anymore?
 jQuery('#fangento-app').mouseenter(function() {
 if (!fangento_pin_open && !fangento_sliding) {
 fangento_sliding = true;
 jQuery('#fangento-appBody').slideDown('normal', function() {
 fangento_sliding = false;
 });
 }
 });
 jQuery('#fangento-app').mouseleave(function() {
 if (!fangento_pin_open && !fangento_sliding) {
 fangento_sliding = true;
 jQuery('#fangento-appBody').slideUp('normal', function() {
 fangento_sliding = false;
 });
 }
 });

 //reply-mode
 if (window.location.href.indexOf('fangento=') != -1) {

 jQuery('#fangento-app').slideUp();
 jQuery('#fangento-reply').slideDown();

 var fangento = fangento_urlParam('fangento');
 var fangento_arr = fangento.split('_');
 var sender = fangento_arr[2];

 var threadId = fangento_urlParam('threadId');

 //nbsp to fix spacing problem in IE
 jQuery('#fangento-replyHeader').html(
 '<div style="float:left; margin-right:10px;">' +
 '<fb:profile-pic size=square uid=' + sender + ' facebook-logo=true></fb:profile-pic>' +
 '</div>' +
 '<fb:name uid=' + sender + ' useyou=false></fb:name>&nbsp;' + fangento_messages['needs advice'] + ': <span id="fangento-replyComment" style="font-weight:bold"></span>' +
 '<div style="clear:both"></div>');

 //FIX: we could contruct the fangento string server-side from the threadId
 jQuery.ajax({
 type: 'POST',
 url: fangento_paths['ajax_threadComment'],
 data: ({threadId: threadId}),
 success: function(msg){
 jQuery('#fangento-replyComment').html(msg);
 }
 });

 //sometimes null?
 if (FB.XFBML.Host) FB.XFBML.Host.parseDomTree();

 jQuery.growlUI(fangento_messages['Share your thoughts on this product.'], null, null, function() {
 jQuery('#fangento').effect("highlight", {}, 1000);
 }, jQuery('#fangento'));
 }

 /* example of textarea helper text if needed in future...
 jQuery('#fangento-filter').focus(function () {
 var elem = jQuery(this);
 if (elem.hasClass('foo-default')) {
 elem.removeClass('foo-default');
 elem.val('');
 }
 });
 jQuery('#fangento-filter').blur(function () {
 var elem = jQuery(this);
 if (!elem.val().length) {
 elem.addClass('foo-default');
 elem.val('Search');
 }
 });
 */

 //thumbs-up and thumbs-down hovers
 jQuery('#fangento-thumbsUp').hover(
 function(){
 this.src = fangento_images['thumbs_up_on'];
 },
 function(){
 if (jQuery('#fangento-likeDislike').val() != 'like') {
 this.src = fangento_images['thumbs_up_off'];
 }
 }
 );

 jQuery('#fangento-thumbsDown').hover(
 function(){
 this.src = fangento_images['thumbs_down_on'];
 },
 function(){
 if (jQuery('#fangento-likeDislike').val() != 'dislike') {
 this.src = fangento_images['thumbs_down_off'];
 }
 }
 );

});


/**
 * Facebook callback when user is connected.
 *
 */
function fangento_start() {
 //user has just logged in
 if (jQuery('#fangento-appBody').is(':visible')) {
 jQuery('#fangento-appBodyAnon').slideUp();
 }
 //user has reloaded page
 else {
 jQuery('#fangento-appBodyAnon').hide();
 jQuery('#fangento-appBody').show();
 fangento_pin_open = true;
 }

 //footer
 jQuery('#fangento-appHeaderAnon').hide();
 jQuery('#fangento-appBodyFooterAuth').show();
 jQuery('#fangento-learnMore').hide();

 jQuery('#fangento-appBodyAuth').slideDown();

 //load friends
 var sql = 'select name, uid, pic_square_with_logo, online_presence from user where uid in (select uid2 from friend where uid1=' + FB.Facebook.apiClient.get_session().uid + ') order by name';
 FB.Facebook.apiClient.fql_query(sql, function(result, ex) {

 fangento_friends = result;

 jQuery("#fangento-recipients").autocomplete(fangento_friends,
 {
 minChars: 0,
 width: jQuery('#fangento-recipients').width(),
 multiple: true,
 mustMatch: true,
 autoFill: false,
 matchContains: true,
 highlightItem: true,
 formatItem: function(row, i, max, term) {
 //fgoPresence class on these only so that they can be updated dynamically when dropdown is open (not overly necessary)
 var presenceStr = '<img class="fgoPresence" id="fangento-presence2-' + row.uid + '" src="' + BLANK_IMG + '" width="8" height="8" title="" alt=""/>';
 var presencePhrase = '';
 if (row.online_presence == 'active') {
 presenceStr = '<img class="fgoPresence" id="fangento-presence2-' + row.uid + '" src="' + fangento_images['active'] + '" width="8" height="8" title="' + fangento_messages['Online'] + '" alt="' + fangento_messages['Online'] + '"/>';
 presencePhrase = 'Online';
 }
 else if (row.online_presence == 'idle') {
 presenceStr = '<img class="fgoPresence" id="fangento-presence2-' + row.uid + '" src="' + fangento_images['idle'] + '" width="8" height="8" title="' + fangento_messages['Idle'] + '" alt="' + fangento_messages['Idle'] + '"/>';
 presencePhrase = 'Idle';
 }

 var avatar;
 if (!jQuery.trim(row.pic_square_with_logo).length) {
 avatar = 'http://static.ak.connect.facebook.com/pics/q_silhouette_logo.gif';
 }
 else {
 avatar = row.pic_square_with_logo;
 }

 return '<div style="text-align:left;">' +
 '<img src="' + avatar + '" style="float:left; margin-right:2px;"/>' +
 '<div style="height:50px; float:left; margin:0px 2px;">' + presenceStr + '</div>' + row.name + '<br/>' +
 '<em class="fgoPresencePhrase" id="fangento-presencePhrase-' + row.uid +'">' + presencePhrase + '</em>' +
 '</div>';
 },
 formatMatch: function(row) {
 return row.name;
 },
 formatResult: function(row) {
 return row.name;
 }
 }).result(function(event, item) {
 //callback not necessary currently
 });
 });

 //see if there are any replies
 fangento_ping_replies(1);

 //online presence already set above, wait 30 seconds to update it again
 setTimeout('fangento_ping_presence()', 30000);
}


/**
 * Callback for logout button in default(ask)-mode.
 *
 */
function fangento_logout() {
 //footer
 jQuery('#fangento-appBodyFooterAuth').hide();
 jQuery('#fangento-appHeaderAnon').show();
 jQuery('#fangento-learnMore').hide();

 jQuery('#fangento-appBodyAuth').hide();
 jQuery('#fangento-appBodyAnon').show();

 jQuery('#fangento-appBody').slideUp();
 fangento_pin_open = false;
}


/**
 * Callback for ask-your-friends button in default(ask)-mode.
 *
 */
function fangento_ask() {
 jQuery('#fangento-appBodyAuthAsk').slideUp();
 jQuery('#fangento-appBodyAuthSend').slideDown();
}


/**
 * Callback for cancel button in default(ask)-mode.
 *
 */
function fangento_cancel() {
 jQuery('#fangento-appBodyAuthSend').slideUp();
 jQuery('#fangento-appBodyAuthAsk').slideDown();
}


/**
 * Callback for send button in default(ask)-mode.
 *
 */
function fangento_send() {

 var recipientsStr = jQuery.trim( jQuery('#fangento-recipients').val() );

 if (!recipientsStr.length) {
 jQuery.growlUI(fangento_messages['Please choose at least one friend.']);
 return;
 }

 var recipients = recipientsStr.split(/,\s*/);

 var message = jQuery('#fangento-message').val();
 if (!message.length) {
 jQuery.growlUI(fangento_messages['Please enter a question.']);
 return;
 }
 var messageTxt = message;

 var storeId = fangento_store_id;
 var productId = fangento_product_id;
 var fbId = FB.Facebook.apiClient.get_session().uid;

 var ids = [];
 var base_fangento_str = storeId + '_' + productId + '_' + fbId;

 //note that this loop will remove dups
 for (var i = 0; i < fangento_friends.length; i++) {
 var name = fangento_friends[i].name;
 if (jQuery.inArray(fangento_friends[i].name, recipients) != -1) {
 ids.push(fangento_friends[i].uid);
 }
 }

 jQuery.ajax({
 type: 'POST',
 url: fangento_paths['ajax_thread'],
 data: ({fangento: base_fangento_str, 'ids[]': ids, message: messageTxt, url: window.location.href}),
 success: function(msg){
 var threadStr = '&threadId=' + msg;

 //FIX: send notifications server-side?
 for (var i = 0; i < ids.length; i++) {
 var id = ids[i];
 var fangento_str = base_fangento_str + '_' + id;
 var href = window.location.href;
 var url;
 if (href.indexOf('?') == -1) {
 url = href + '?fangento=' + fangento_str + threadStr;
 }
 else {
 url = href + '&fangento=' + fangento_str + threadStr;
 }

 var new_message = '<a href="' + url + '">' + message + '</a>';
 FB.Facebook.apiClient.notifications_send(id, new_message, function() {});
 }

 //alert('Your messages have been sent.');
 jQuery.growlUI(fangento_messages['Your messages have been sent.']);

 jQuery('#fangento-recipients').val('');
 jQuery('#fangento-message').val('');

 jQuery('#fangento-appBodyAuthSend').slideUp();
 jQuery('#fangento-appBodyAuthAsk').slideDown();

 fangento_ping_replies(1, true);
 }
 });
}


/**
 * Callback for send button in reply-mode.
 *
 */
function fangento_send_reply(btn) {
 var fangento = fangento_urlParam('fangento');
 var fangento_arr = fangento.split('_');
 var sender = fangento_arr[2];

 var threadId = fangento_urlParam('threadId');

 //app-to-user notif needs to be sent server-side
 var newUrl = window.location.href.replace(/[?|&]fangento=([^&#]*)/, '').replace(/[?|&]threadId=([^&#]*)/, '');

 var reply = jQuery('#fangento-replyMessage').val();
 var likeDislike = jQuery('#fangento-likeDislike').val();
 if (likeDislike.length == 0) {
 jQuery.growlUI(fangento_messages['Please select whether you like or dislike this product.']);
 return;
 }
 else if (reply.length == 0) {
 jQuery.growlUI(fangento_messages['Please type a reply.']);
 return;
 }

 /*sample code for using blockUI load spinner
 jQuery('#foo').block({
 // disable horz centering
 centerX: false,
 // disable vertical centering
 centerY: false,
 // apply css props as desired
 fadeOut: 0, //immediate change
 message: '<img src="' + fangento_images['ajax_loader'] + '"/>',
 css: { top: '33%', left: '0%', width: '100%', backgroundColor: '', border: '' },
 timeout: 1000,
 onUnblock: function() {
 jQuery('#foo').hide();
 jQuery('#fangento-compose').show();
 }
 });

 .unblock
 */

 jQuery.ajax({
 type: 'POST',
 url: fangento_paths['ajax_reply'],
 data: ({fangento: fangento, fangento_message: reply, like_dislike: likeDislike, newUrl: newUrl, threadId: threadId}),
 success: function(msg){
 //sent server-side
 //FB.Facebook.apiClient.notifications_send(sender, 'has provided advice on this <a href="' + newUrl + '">product</a>.', function() {});

 //alert('Your reply has been sent.');
 jQuery.growlUI(fangento_messages['Your reply has been sent.'], fangento_messages['Thanks for sharing!']);

 jQuery('#fangento-reply').slideUp();
 jQuery('#fangento-app').slideDown();
 }
 });
}


/**
 * Callback for like/dislike (thumbs-up/thumbs-down) toggles.
 *
 */
function fangento_like_dislike(likeDislike) {
 if (likeDislike == 'like') {
 jQuery('#fangento-likeDislike').val('like');
 jQuery('#fangento-thumbsDown').attr('src', fangento_images['thumbs_down_off']);
 }
 else if (likeDislike == 'dislike') {
 jQuery('#fangento-likeDislike').val('dislike');
 jQuery('#fangento-thumbsUp').attr('src', fangento_images['thumbs_up_off']);
 }
}


/**
 * Pings for threads/replies and populates them into UI.
 *
 */
function fangento_ping_replies(force, onlyOnce) {
 //in case user logs out
 if (FB.Facebook.apiClient.get_session() == null) return;

 //FIX: consolidate fangento_str into global convenience func
 var storeId = fangento_store_id;
 var productId = fangento_product_id;
 var fbId = FB.Facebook.apiClient.get_session().uid;

 var fangento_str = storeId + '_' + productId + '_' + fbId;

 jQuery.getJSON(
 fangento_paths['ajax_replies'],
 ({fangento: fangento_str, force: force}),
 function(data){

 //fields available:
 //content
 //date_modified
 //facebook_id
 //is_new

 if (data != null && data.length) {

 var html = '';
 var numNew = 0;

 for (var i = 0; i < data.length; i++) {

 var currData = data[i];

 html += '<div style=" border-top:1px solid #CCCCCC; padding:5px 10px 5px 10px; font-weight:bold; text-align:left; font-size:11px;">' + currData.content + '</div>';

 if (currData.replies.length) {

 jQuery.each(currData.replies, function(i) {

 html += (

 '<div style="border-top:1px solid #CCCCCC; padding:5px 10px 5px 10px; font-size:11px">' +
 ' <fb:profile-pic size=square width=25 uid=' + this.facebook_id + ' facebook-logo=true></fb:profile-pic>' +
 ' <img src="' + (this.like_dislike ? fangento_images['thumbs_up_on'] : fangento_images['thumbs_down_on']) + '"/>' +
 ' <img class="fgoPresence" id="fangento-presence-' + this.facebook_id + '" src="' + BLANK_IMG + '" width="8" height="8"/>' +
 ' <fb:name uid=' + this.facebook_id + ' useyou=false></fb:name>: ' +
 ' ' + this.content + '<div style="text-align:right; color:#AAAAAA">' + fangento_date_format (this.date_modified) + '</div>' +
 '</div>'

 );

 if (this.is_new == 1) {
 numNew++;
 }

 });

 }
 else {
 html += (
 '<div style="border-top:1px solid #CCCCCC; padding:5px 10px 5px 10px; font-size:11px; font-style: italic; text-align:center;">' +
 fangento_messages['Awaiting replies...'] +
 '</div>'
 );
 }

 }

 jQuery('#fangento-appBodyAuthReplies').html(html);

 if (numNew) {
 jQuery.growlUI(fangento_messages['You have'] + ' ' + (numNew == 1 ? fangento_messages['a new reply.'] : numNew + ' ' + fangento_messages['new replies.']));
 }

 //sometimes null?
 if (FB.XFBML.Host) FB.XFBML.Host.parseDomTree();
 }

 if (!onlyOnce)
 setTimeout('fangento_ping_replies(0)', 10000);
 }
 );
}


/**
 * Pings Facebook for presence and updates presence indicators.
 *
 */
function fangento_ping_presence() {
 //in case user logs out
 if (FB.Facebook.apiClient.get_session() == null) return;

 var sql = 'select uid, online_presence from user where uid in (select uid2 from friend where uid1=' + FB.Facebook.apiClient.get_session().uid + ') order by name';
 FB.Facebook.apiClient.fql_query(sql, function(result, ex) {

 var presenceMap = new Object();

 for (var i = 0; i < result.length; i++) {
 presenceMap[result[i].uid] = result[i].online_presence;
 }

 jQuery('.fgoPresence').each(function(i) {
 //the version in the autocomplete dropdown are called fangento-presence2-; FIX: come up with better naming scheme
 var facebookId = this.id.replace(/fangento-presence-/, '').replace(/fangento-presence2-/, '');

 if (facebookId == null || facebookId.length == 0 || presenceMap[facebookId] === undefined) {
 //debugging only
 //alert(facebookId + ' not found in presenceMap.');
 }
 else {
 var foo = presenceMap[facebookId];

 //FIX: need to set width and height of blank everywhere or use a blank that's already sized
 if (foo == 'idle') {
 this.src = fangento_images['idle'];
 this.alt = this.title = fangento_messages['Idle'];
 }
 else if (foo == 'active') {
 this.src = fangento_images['active'];
 this.alt = this.title = fangento_messages['Online'];
 }
 else {
 this.src = BLANK_IMG;
 this.alt = this.title = '';
 }
 }
 });

 jQuery('.fgoPresencePhrase').each(function(i) {
 //the version in the autocomplete dropdown are called fangento-presence2-; FIX: come up with better naming scheme
 var facebookId = this.id.replace(/fangento-presencePhrase-/, '');

 if (facebookId == null || facebookId.length == 0 || presenceMap[facebookId] === undefined) {
 //debugging only
 //alert(facebookId + ' not found in presenceMap.');
 }
 else {
 var foo = presenceMap[facebookId];

 if (foo == 'idle') {
 this.innerHTML = fangento_messages['Idle'];
 }
 else if (foo == 'active') {
 this.innerHTML = fangento_messages['Online'];
 }
 else {
 this.innerHTML = '';
 }
 }
 });

 for (var i = 0; i < fangento_friends.length; i++) {
 var foo = presenceMap[ fangento_friends[i]['uid'] ];
 if (foo === undefined) {
 //debugging
 //alert(fangento_friends[i]['uid'] + ' not found in presenceMap.');
 }
 else {
 fangento_friends[i]['online_presence'] = foo;
 }
 }

 //ping status every 30 seconds
 setTimeout('fangento_ping_presence()', 30000);
 });
}
