// $Id: common.js,v 1.41 2012/01/09 14:52:53 lebedand Exp $
// defined the map of unsupported charachters in PubMed to be replaced in the links related to the the author names
// map was taken from redirect.cgi
var pubmedUnsupportedCharMap = {
'x000b2':'2',
'x000b3':'3',
'x000b9':'1',
'x000c0':'A',
'x000c1':'A',
'x000c2':'A',
'x000c3':'A',
'x000c4':'A',
'x000c5':'A',
'x000c6':'AE',
'x000c7':'C',
'x000c8':'E',
'x000c9':'E',
'x000ca':'E',
'x000cb':'E',
'x000cc':'I',
'x000cd':'I',
'x000ce':'I',
'x000cf':'I',
'x000d1':'N',
'x000d2':'O',
'x000d3':'O',
'x000d4':'O',
'x000d5':'O',
'x000d6':'O',
'x000d7':'x',
'x000d8':'O',
'x000d9':'U',
'x000da':'U',
'x000db':'U',
'x000dc':'U',
'x000dd':'Y',
'x000df':'ss',
'x000e0':'a',
'x000e1':'a',
'x000e2':'a',
'x000e3':'a',
'x000e4':'a',
'x000e5':'a',
'x000e6':'ae',
'x000e7':'c',
'x000e8':'e',
'x000e9':'e',
'x000ea':'e',
'x000eb':'e',
'x000ec':'i',
'x000ed':'i',
'x000ee':'i',
'x000ef':'i',
'x000f1':'n',
'x000f2':'o',
'x000f3':'o',
'x000f4':'o',
'x000f5':'o',
'x000f6':'o',
'x000f8':'o',
'x000f9':'u',
'x000fa':'u',
'x000fb':'u',
'x000fc':'u',
'x000fd':'y',
'x000ff':'y',
'x00100':'A',
'x00101':'a',
'x00102':'A',
'x00103':'a',
'x00104':'A',
'x00105':'a',
'x00106':'C',
'x00107':'c',
'x00108':'C',
'x00109':'c',
'x0010a':'C',
'x0010b':'c',
'x0010c':'C',
'x0010d':'c',
'x0010e':'D',
'x0010f':'d',
'x00110':'D',
'x00111':'d',
'x00112':'E',
'x00113':'e',
'x00116':'E',
'x00117':'e',
'x00118':'E',
'x00119':'e',
'x0011a':'E',
'x0011b':'e',
'x0011c':'G',
'x0011d':'g',
'x0011e':'G',
'x0011f':'g',
'x00120':'G',
'x00121':'g',
'x00122':'G',
'x00124':'H',
'x00125':'h',
'x00126':'H',
'x00127':'h',
'x00128':'I',
'x00129':'ij',
'x0012a':'I',
'x0012b':'ij',
'x0012e':'I',
'x0012f':'ij',
'x00130':'I',
'x00131':'ij',
'x00132':'IJ',
'x00133':'ij',
'x00134':'J',
'x00135':'j',
'x00136':'K',
'x00137':'k',
'x00138':'k',
'x00139':'L',
'x0013a':'l',
'x0013b':'L',
'x0013c':'l',
'x0013d':'L',
'x0013e':'l',
'x0013f':'L',
'x00140':'l',
'x00141':'L',
'x00142':'l',
'x00143':'N',
'x00144':'n',
'x00145':'N',
'x00146':'n',
'x00147':'N',
'x00148':'n',
'x00149':'n',
'x0014c':'O',
'x0014d':'o',
'x00150':'O',
'x00151':'o',
'x00152':'OE',
'x00153':'oe',
'x00154':'R',
'x00155':'r',
'x00156':'R',
'x00157':'r',
'x00158':'R',
'x00159':'r',
'x0015a':'S',
'x0015b':'s',
'x0015c':'S',
'x0015d':'s',
'x0015e':'S',
'x0015f':'s',
'x00160':'S',
'x00161':'s',
'x00162':'T',
'x00163':'t',
'x00164':'T',
'x00165':'t',
'x00166':'T',
'x00167':'t',
'x00168':'U',
'x00169':'u',
'x0016a':'U',
'x0016b':'u',
'x0016c':'U',
'x0016d':'u',
'x0016e':'U',
'x0016f':'u',
'x00170':'U',
'x00171':'u',
'x00172':'U',
'x00173':'u',
'x00174':'W',
'x00175':'w',
'x00176':'Y',
'x00177':'y',
'x00178':'Y',
'x00179':'Z',
'x0017a':'z',
'x0017b':'Z',
'x0017c':'z',
'x0017d':'Z',
'x0017e':'z',
'x001f5':'g',
'x00405':'S',
'x00406':'I',
'x00408':'J',
'x00455':'s',
'x00456':'i',
'x00458':'j',
'x02102':'C',
'x0210b':'H',
'x0210c':'H',
'x02110':'I',
'x02111':'I',
'x02112':'L',
'x02115':'N',
'x02119':'P',
'x0211a':'Q',
'x0211c':'R',
'x0211d':'R',
'x0211e':'Rx',
'x02124':'Z',
'x0212b':'A',
'x0212c':'B',
'x0212f':'e',
'x02130':'E',
'x02131':'F',
'x02133':'M',
'x02134':'o',
'x0e05d':'h',
'x0e05f':'k',
'x0e3b2':'fj',
'x0e500':'A',
'x0e501':'B',
'x0e503':'D',
'x0e504':'E',
'x0e505':'F',
'x0e506':'G',
'x0e507':'H',
'x0e508':'I',
'x0e509':'J',
'x0e50a':'K',
'x0e50b':'L',
'x0e50c':'M',
'x0e50e':'O',
'x0e512':'S',
'x0e513':'T',
'x0e514':'U',
'x0e515':'V',
'x0e516':'W',
'x0e517':'X',
'x0e518':'Y',
'x0e520':'A',
'x0e522':'C',
'x0e523':'D',
'x0e526':'G',
'x0e529':'J',
'x0e52a':'K',
'x0e52d':'N',
'x0e52e':'O',
'x0e52f':'P',
'x0e530':'Q',
'x0e531':'R',
'x0e532':'S',
'x0e533':'T',
'x0e534':'U',
'x0e535':'V',
'x0e536':'W',
'x0e537':'X',
'x0e538':'Y',
'x0e539':'Z',
'x0e540':'a',
'x0e541':'b',
'x0e542':'c',
'x0e543':'d',
'x0e545':'f',
'x0e546':'g',
'x0e547':'h',
'x0e548':'i',
'x0e549':'j',
'x0e54a':'k',
'x0e54b':'l',
'x0e54c':'m',
'x0e54d':'n',
'x0e54f':'p',
'x0e550':'q',
'x0e551':'r',
'x0e552':'s',
'x0e553':'t',
'x0e554':'u',
'x0e555':'v',
'x0e556':'w',
'x0e557':'x',
'x0e558':'y',
'x0e559':'z',
'x0e560':'A',
'x0e561':'B',
'x0e562':'C',
'x0e563':'D',
'x0e564':'E',
'x0e565':'F',
'x0e566':'G',
'x0e569':'J',
'x0e56a':'K',
'x0e56b':'L',
'x0e56c':'M',
'x0e56d':'N',
'x0e56e':'O',
'x0e56f':'P',
'x0e570':'Q',
'x0e572':'S',
'x0e573':'T',
'x0e574':'U',
'x0e575':'V',
'x0e576':'W',
'x0e577':'X',
'x0e578':'Y',
'x0e579':'Z',
'x0e580':'a',
'x0e581':'b',
'x0e582':'c',
'x0e583':'d',
'x0e584':'e',
'x0e585':'f',
'x0e586':'g',
'x0e587':'h',
'x0e588':'i',
'x0e589':'j',
'x0e58a':'k',
'x0e58b':'l',
'x0e58c':'m',
'x0e58d':'n',
'x0e58e':'o',
'x0e58f':'p',
'x0e590':'q',
'x0e591':'r',
'x0e592':'s',
'x0e593':'t',
'x0e594':'u',
'x0e595':'v',
'x0e596':'w',
'x0e597':'x',
'x0e598':'y',
'x0e599':'z',
'x0ea00':'1',
'x0ea01':'1',
'x0ea02':'2',
'x0ea03':'2',
'x0ea04':'3',
'x0ea05':'3',
'x0ea06':'4',
'x0ea07':'a',
'x0ea08':'a',
'x0ea09':'A',
'x0ea0a':'a',
'x0ea0b':'A',
'x0ea0c':'AB',
'x0ea10':'b',
'x0ea11':'B',
'x0ea12':'b',
'x0ea13':'B',
'x0ea14':'B',
'x0ea15':'B',
'x0ea16':'BC',
'x0ea19':'c',
'x0ea1a':'c',
'x0ea1b':'c',
'x0ea1c':'C',
'x0ea1d':'c',
'x0ea1e':'c',
'x0ea1f':'c',
'x0ea20':'c',
'x0ea21':'c',
'x0ea25':'d',
'x0ea26':'D',
'x0ea27':'d',
'x0ea28':'D',
'x0ea29':'d',
'x0ea2a':'D',
'x0ea2b':'D',
'x0ea2f':'dl',
'x0ea30':'e',
'x0ea31':'e',
'x0ea32':'l',
'x0ea33':'l',
'x0ea34':'f',
'x0ea35':'f',
'x0ea36':'F',
'x0ea37':'f',
'x0ea38':'F',
'x0ea39':'f',
'x0ea3a':'F',
'x0ea3d':'g',
'x0ea3e':'g',
'x0ea3f':'G',
'x0ea40':'g',
'x0ea41':'G',
'x0ea46':'H',
'x0ea47':'h',
'x0ea48':'h',
'x0ea49':'i',
'x0ea4a':'I',
'x0ea4b':'j',
'x0ea4c':'J',
'x0ea4d':'J',
'x0ea4e':'J',
'x0ea4f':'k',
'x0ea50':'k',
'x0ea51':'k',
'x0ea52':'K',
'x0ea53':'K',
'x0ea54':'k',
'x0ea55':'l',
'x0ea56':'L',
'x0ea57':'l',
'x0ea5b':'lnV',
'x0ea5c':'m',
'x0ea5d':'M',
'x0ea5e':'m',
'x0ea5f':'m',
'x0ea63':'n',
'x0ea64':'n',
'x0ea65':'N',
'x0ea66':'n',
'x0ea67':'N',
'x0ea68':'n',
'x0ea69':'n',
'x0ea6a':'N',
'x0ea6d':'nv',
'x0ea6e':'O',
'x0ea6f':'O',
'x0ea70':'O',
'x0ea72':'F',
'x0ea73':'p',
'x0ea74':'P',
'x0ea75':'p',
'x0ea76':'P',
'x0ea77':'p',
'x0ea78':'P',
'x0ea79':'p',
'x0ea7a':'P',
'x0ea8d':'q',
'x0ea8e':'Q',
'x0ea8f':'q',
'x0ea90':'q',
'x0ea91':'Q',
'x0ea92':'q',
'x0ea93':'Q',
'x0ea94':'q',
'x0ea95':'q',
'x0ea96':'q',
'x0ea97':'Q',
'x0ea98':'r',
'x0ea99':'R',
'x0ea9a':'R',
'x0ea9b':'r',
'x0ea9c':'R',
'x0ea9d':'R',
'x0ea9e':'r',
'x0ea9f':'R',
'x0eaa0':'r',
'x0eaa1':'ri',
'x0eaa2':'R',
'x0eaa3':'r',
'x0eaa4':'r1',
'x0eaa5':'RE',
'x0eaa9':'ri',
'x0eaaa':'rj',
'x0eaab':'rN',
'x0eaac':'s',
'x0eaad':'S',
'x0eaae':'S',
'x0eaaf':'s',
'x0eab0':'S',
'x0eab1':'s',
'x0eab2':'S',
'x0eab3':'S',
'x0eab4':'B',
'x0eab5':'E',
'x0eab6':'G',
'x0eab7':'P',
'x0eab8':'Q',
'x0eab9':'t',
'x0eaba':'T',
'x0eabb':'T',
'x0eabc':'t',
'x0eabd':'T',
'x0eabe':'t',
'x0eabf':'T',
'x0eac5':'TT',
'x0eac6':'u',
'x0eac7':'u',
'x0eac8':'U',
'x0eac9':'u',
'x0eaca':'u',
'x0eacc':'V',
'x0eacd':'v',
'x0eace':'v',
'x0eacf':'V',
'x0ead0':'v',
'x0ead1':'V',
'x0ead2':'v',
'x0ead3':'v',
'x0ead4':'V',
'x0ead5':'v',
'x0eadc':'w',
'x0eadd':'w',
'x0eade':'w',
'x0eadf':'x',
'x0eae0':'X',
'x0eae1':'x',
'x0eae2':'X',
'x0eae3':'x',
'x0eae4':'x',
'x0eae5':'X',
'x0eae6':'x',
'x0eae8':'y',
'x0eae9':'Y',
'x0eaea':'y',
'x0eaeb':'Y',
'x0eaec':'y',
'x0eaed':'y',
'x0eaee':'z',
'x0eaef':'Z',
'x0eaf0':'z',
'x0eaf1':'z',
'x0eaf2':'Z',
'x0eaf3':'z',
'x0eaf4':'z',
'x0eafc':'B',
'x0eaff':'A',
'x0eb04':'w',
'x0eb05':'m',
'x0eb06':'M',
'x0eb07':'E',
'x0eb08':'W',
'x0eb0a':'h',
'x0eb0b':'n',
'x0eb0d':'H',
'x0eb0f':'M',
'x0eb10':'m',
'x0eb11':'Z',
'x0eb12':'g',
'x0eb14':'C',
'x0eb15':'E',
'x0eb19':'W',
'x0eb1a':'a',
'x0eb1b':'b',
'x0eb1c':'S',
'x0eb1e':'J',
'x0eb1f':'b',
'x0eb20':'Z',
'x0eb21':'L',
'x0eb22':'g',
'x0fb00':'ffi',
'x0fb01':'fi',
'x0fb02':'fl',
'x0fb03':'ffi',
'x0fb04':'ffl'
    }

// Called from many places to handle links.
// Params:
//     link:         URL. 'this' to reuse same window, else ""
//     windowname:   Reference name for window
//     additional:   Attributes for window.open, from:
//        width, height, resizable, scrollbars, toolbar, location, directories,
//        status, menubar, copyhistory.
// Notes: Book version always provides menubar, toolbar, etc.
//
function startTargetBook(link,windowname,width,height,additional)
{
    return startTarget(link,windowname,width,height,additional)
}


//===============================================================================
function startTarget(link,windowname,width,height, additional)
{

    if(! window.focus)
        return false;

    var sizestring = ",width=" + width + ",height=" + height;
  var opt = "menubar=no,toolbar=no,status=no,scrollbars=yes,resizable=yes,dependent=yes,location=no";
    var allOptions = opt + sizestring;
    if (additional) { allOptions = allOptions + ',' + additional; }

    windowname = String(windowname).replace(/-/g, "_")
    var moveToXDefault = 75
    var moveToYDefault = 50

    var moveToX = moveToXDefault
    var moveToY = moveToYDefault
    var yAdj = 50
    var yAdjDelta = 25

    var barNames = ['menubar', 'toolbar', 'statusbar']
    for (var idx in barNames)
    {
  if (String(allOptions).lastIndexOf(barNames[idx] + '=yes') >
      String(allOptions).lastIndexOf(barNames[idx] + '=no'))
    yAdj += yAdjDelta
    }

    try {
        if (window.screen.width && width > 0)
            moveToX = Math.ceil((window.screen.width - width)) - 15
        moveToX = (moveToX > 0 ? moveToX : moveToXDefault)

        if (window.screen.height && height > 0)
            moveToY = Math.ceil((window.screen.height - height)) - yAdj
        moveToY = (moveToY > 0 ? moveToY : moveToYDefault)
    }
    catch (e) {}

    var wLeftTopCornerOptions = ',left=' + moveToX + ',top=' + moveToY + ',screenX=' + moveToX + ',screenY=' + moveToY

    allOptions = allOptions + wLeftTopCornerOptions

    w = window.open (link, windowname, allOptions)

    if (w != undefined)
	w.focus()

    link.target=windowname

    return false;
}


//===============================================================================
function focuswin(windowname)
{
    windowname = String(windowname).replace(/-/g, "_")
    w = window.open("",windowname,"menubar=yes,scrollbars=yes,toolbar=yes,location=yes,status=yes,directories=yes,resizable=yes");
    if (w != undefined)
	w.focus();

    return true;
}


//===============================================================================
function reverseString (inStr)
{
    var outStr = ''

    for (i =0; i <= inStr.length; i++)
    {
  outStr = inStr.charAt(i) + outStr
    }

    return outStr
}


//===============================================================================
function reverseAndReplaceString (inStr, findStr, newStr)
{
    return reverseString(inStr).replace(findStr, newStr)
}

//===============================================================================
function initUnObscureEmail (className, innerHTML)
{

    try{
        if (window.addEventListener)
            window.addEventListener('load', function() {unObscureEmail (className, innerHTML)}, false)
        else if (window.attachEvent)
            window.attachEvent('onload', function() {unObscureEmail (className, innerHTML)})
    }catch(e){
    }
}

//===============================================================================
function unObscureEmail (className, innerHTML)
{
    try {
        if (typeof(unObscuredEmails) == 'undefined')
            unObscuredEmails = new Array()

        if (! unObscuredEmails[className])
        {

            var elmnts = document.getElementsByTagName("span")
            for (var i = 0, len = elmnts.length; i < len; i++)
            {
                if (elmnts.item(i).className.indexOf(className, " ") != -1)
                {
                    elmnts.item(i).innerHTML     = innerHTML;
                    unObscuredEmails[className]  = true

                }
            }
        }
    }
    catch(e){
    }
}

//===============================================================================
function pubMedDbLinkSubmit(control) {
    try{
        if (control.pubmedOption)
            control = control.pubmedOption
        if (control.options)
            location.href = control.options[control.options.selectedIndex].value;
    }
    catch(e){}
    return false;
}

//===============================================================================
// elements "a", "area" with "ref" attribute report to redirect utility before dereferencing link
//
function initRedirectClicks(report_url) {

    if (report_url && typeof jQuery !== 'undefined')
        jQuery(document).click(function(e) {

            //
            if (!e) return true;
            //
            if (e.shiftKey || e.altKey || e.ctrlKey) return true;
            //
            var target = jQuery(e.target).closest("a[ref], area[ref]");
            if (!target || target.length == 0) return true;
            //
            var ref  = target.attr("ref");
            var href = target.attr("href")

            // special processing of href element for pubmed's authors
            if (typeof (href) != 'undefined' && href.indexOf('sites/entrez') && href.indexOf('%5Bauth%5D'))
            {
                var newHref = replacePubMedUnsupportedChars(href);
                if (newHref != href)
                    target.attr("href", newHref)
            }

            // append ref with value of href if 'redirect-to-url' is missing in ref.
            if (typeof (ref) != 'undefined' && ref.indexOf('redirect-to-url') == -1)
                ref = ref + '&redirect-to-url=' + encodeURIComponent(href)

	    jQuery.ajax({
	       type:    "HEAD",
	       url:     report_url + '?' + ref,
	       timeout: 1000,
	       async:   true
	    });
            

            return true;
        });
};

// function to replace unsupported charachters in author names to be searchable in PubMed database.
function replacePubMedUnsupportedChars (str)
{
    // replace low 128 chars automatically
    str = str.replace(/%26%23(x000[0-7][0-9a-f])%3b/ig,
        function($0, $1){
            return (String.fromCharCode('0' + $1))
        }
    )
    // replace others based on map and if it is not in the map replace with empty string.
    str = str.replace(/%26%23(x[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])%3b/ig,
        function($0, $1){
            return (pubmedUnsupportedCharMap[$1] ? pubmedUnsupportedCharMap[$1] : '')
        }
    )
    return str;
}
//===============================================================================
// Based on script written by Dean Edwards, 2005
// http://dean.edwards.name/

var pmc_script = {
  addEvent: function(element, type, handler) {
    // assign each event handler a unique ID
    if (!handler.$$guid) handler.$$guid = this.addEvent_guid++;
    // create a hash table of event types for the element
    if (!element.events) element.events = {};
    // create a hash table of event handlers for each element/event pair
    var handlers = element.events[type];
    if (!handlers) {
      handlers = element.events[type] = {};
      // store the existing event handler (if there is one)
      if (element["on" + type]) {
        handlers[0] = element["on" + type];
      }
    }
    // store the event handler in the hash table
    handlers[handler.$$guid] = handler;
    // assign a global event handler to do all the work
    element["on" + type] = handleEvent;


    function handleEvent(event) {
      var returnValue = true;
      // grab the event object (IE uses a global event object)
      event = event || fixEvent(window.event);
      // get a reference to the hash table of event handlers
      var handlers = this.events[event.type];
      // execute each event handler
      for (var i in handlers) {
        this.$$handleEvent = handlers[i];
        if (this.$$handleEvent(event) === false) {
          returnValue = false;
        }
      }
      return returnValue;
    };

    function fixEvent(event) {
      // add W3C standard event methods
      event.preventDefault = fixEvent.preventDefault;
      event.stopPropagation = fixEvent.stopPropagation;
      return event;
    };

    fixEvent.preventDefault = function() {
      this.returnValue = false;
    };

    fixEvent.stopPropagation = function() {
      this.cancelBubble = true;
    };
  },

  // a counter used to create unique IDs
  addEvent_guid: 1,

  removeEvent: function(element, type, handler) {
    // delete the event handler from the hash table
    if (element.events && element.events[type]) {
      delete element.events[type][handler.$$guid];
    }
  }
}
// special hack for older version of journal list page, where pmc used addEvent method to setup onload event.
// newer version of jlist page is using using jQuery
if (typeof jQuery !== "undefined") {
    pmc_script.addEvent = function () {}
}

// ****************************************************************************
//  implementation of figure's popup using jQuery and jQuery.fn.hoverIntent lib
//  it set appropriate handlers for all "a" elements with "figpopup" class name.
// ****************************************************************************
if (typeof jQuery !== "undefined" &&
    typeof jQuery.fn !== "undefined" &&
    typeof jQuery.fn.hoverIntent !== "undefined")
{
(function($j) {
    var JQ_MOUSEENTER_EVT 	= "mouseenter"
    var JQ_MOUSELEAVE_EVT 	= "mouseleave"
    
    var SENSOR_EVT_TS     	= "evtTS.sensor" // TS - TimeStamp

    var SENSOR_MIN_EVT  	= "mouse.in.sensor"
    var SENSOR_MOUT_EVT 	= "mouse.out.sensor"
    
    var CANVAS_MIN_EVT  	= "mouse.in.canvas"
    var CANVAS_MOUT_EVT 	= "mouse.out.canvas"
    var CANVAS_SHOW_EVT   	= "show.canvas"
    var CANVAS_HIDE_EVT   	= "hide.canvas"
    //var CANVAS_MIN_EVT   	= "mouse.in.canvas"
    //var CANVAS_MOUT_EVT   	= "mouse.out.canvas"
    var CANVAS_SHOWN_EVT   	= "shown.canvas"
    var CANVAS_GONE_EVT   	= "gone.canvas"
    
    var LEFT 		  	= "left"
    var RIGHT 		  	= "right"
    var TOP 		  	= "top"
    var BOTTOM 		  	= "bottom"
    var MAX_ITER          	= 15
    var STAT_OF_LONGER    	= 500 // msec
    var JSEVENT_NAME      	= "hover"
    var MIN_LEGEND_WIDTH  	= 400 // px
    var DELAYIN           	= 200 // msec
    var DELAYOUT          	= 250 // msec
    var MIN_IMG_WIDTH           = 150 // px    
    
    // ==========================  popupSensor ================================
    // <a 	@class		="figpopup" // or may be callout
    //		@co-content	="text of the callout" // url like escaped content to hide html there
    //    	@co-class	="co-fancy" // is set to inner box
    //		@co-style	="css stlyes" // is set to inner box
    //		@co-rid		="CO1" // use the cloned box with @id="CO1"
    //		@co-legend      = "text of the legend for images the source of image, usually citaion"
    //                                     ^^^ url like escaped content to hide html there
    //
    //          canvas-rid="" added dynamically when popup canvas generated
    //
    //	also supporting figure popups tagged within parent <a> as next
    //         <img @src-large="" @src=""/>
    //         <img @hires="" @src=""/>
    {
	$j.fn.popupSensor = function  (opts) {
	    /*__logContext({
		n: 'popupSensor',
		t: this,
		o: opts
	    })*/
    
	    var cfgDefaults = {
		statIfLonger 	: STAT_OF_LONGER,
		delayIn 	: DELAYIN,
		delayOut 	: DELAYOUT
	    }
	    
	    var cfg = $j.fn.extend({}, cfgDefaults)
	    $j.fn.extend(cfg, opts)
	    
	    return this.each(function(i){
		    var elm = $j(this)
		    elm.bind(SENSOR_MIN_EVT, 	__sensorMouseIn)  // hoverIntent 	-> SENSOR
		    elm.bind(SENSOR_MOUT_EVT,	__sensorMouseOut) // hoverIntent	-> SENSOR
		    elm.bind(CANVAS_MIN_EVT, 	__canvasMouseIn)  // CANVAS  		-> SENSOR
		    elm.bind(CANVAS_MOUT_EVT, 	__canvasMouseOut) // CANVAS  		-> SENSOR
		    elm.bind(CANVAS_GONE_EVT, 	__canvasGone)     // CANVAS     	-> SENSOR
		    elm.bind(CANVAS_SHOWN_EVT, 	__canvasShown)    // CANVAS     	-> SENSOR
		    
		    elm.data('popupSensor.cfg', $j.extend({}, cfg))
		})
	}

	//
	function __sensorMouseIn (event) {//__loginfo('trace: sensor.__sensorMouseIn()')
	    var elm = $j(this)
	    elm.data('__sensor.mouseIn', true) // set the state
	    elm.bind(JQ_MOUSEENTER_EVT, __sensorInstantMouseIn)
	    
	    var cfg = __getCfg(elm)

	    // save timestamp when mouse entered over sensor
	    // and trigger canvas to show itself
	    if (typeof elm.data(SENSOR_EVT_TS) === "undefined"
		|| elm.data(SENSOR_EVT_TS) === null)
	    {
		elm.data(SENSOR_EVT_TS, event.timeStamp)
		var canvas = __getCanvas(elm)

		if (typeof canvas !== "undefined") 
		    canvas.getCanvasElm().trigger(CANVAS_SHOW_EVT)
	    }
	}
    

	//
	function __sensorMouseOut (event) {//__loginfo('trace: sensor.__sensorMouseOut()')
	    var elm 	= $j(this)
	    elm.data('__sensor.mouseIn', false)
	    
	    __evaluateSensorCanvasStates.apply(this, [event])
	}

	//
	function __sensorInstantMouseIn (event) {//__loginfo('trace: sensor.__sensorInstantMouseIn()')
	    var elm = $j(this)
	    elm.data('__sensor.instantMouseIn', true) // set the state
	    elm.bind(JQ_MOUSELEAVE_EVT, __sensorInstantMouseOut)
	}
	//
	function __sensorInstantMouseOut (event) {//__loginfo('trace: sensor.__sensorInstantMouseOut()')
	    var elm = $j(this)
	    var cfg = __getCfg(elm)
	    var self= this
	    
	    elm.unbind(JQ_MOUSELEAVE_EVT, __sensorInstantMouseOut)
	    elm.data('__sensor.instantMouseIn', false)
	    
	    setTimeout(function(){
		    //__loginfo('trace: sensor.__sensorInstantMouseOut() delayed evaluation')
		     __evaluateSensorCanvasStates.apply(self, [event])
	    }, cfg.delayOut )
	    
	}

    	//
	function __canvasMouseIn (event) {//__loginfo('trace: sensor.__canvasMouseIn()')
	    var elm = $j(this)
	    elm.data('__canvas.mouseIn', true)
	}
    	//
	function __canvasMouseOut (event) {//__loginfo('trace: sensor.__canvasMouseOut()')
	    var elm = $j(this)
	    elm.data('__canvas.mouseIn', false)
	    __evaluateSensorCanvasStates.apply(this, [event])
	}
	
	function __evaluateSensorCanvasStates (event) {//__loginfo('trace: sensor.__evaluateSensorCanvasStates()')
	    var elm 	= $j(this)
	    var canvas 	= __getCanvas(elm)
	    
	    //__loginfo('sensor.__evaluateSensorCanvasStates() __canvas.mouseIn=%s __sensor.mouseIn=%s __sensor.instantMouseIn=%s', elm.data('__canvas.mouseIn'), elm.data('__sensor.mouseIn'), elm.data('__sensor.instantMouseIn'))
	    
	    // notify canvas, to hide
	    if (typeof canvas 					!== "undefined"
		    && elm.data('__canvas.mouseIn') 		!== true
		    && elm.data('__sensor.mouseIn') 		!== true
		    && elm.data('__sensor.instantMouseIn') 	!== true
		    && elm.data('__canvas.shown') 		=== true)
		canvas.getCanvasElm().trigger(CANVAS_HIDE_EVT)
	}
	//
	function __canvasShown (event) {//__loginfo('trace: sensor.__canvasShown()')
	    var elm = $j(this)
	    elm.data('__canvas.shown', true)
	}

	//
	function __canvasGone (event) {//__loginfo('trace: sensor.__canvasGone()')
	    var elm = $j(this)
	    var cfg = __getCfg(elm)
	    elm.data('__canvas.shown', false)
	    elm.unbind(JQ_MOUSEENTER_EVT, __sensorInstantMouseIn)
	    
	    // ping applog	    
	    if (typeof ncbi 			!== "undefined"
		    && typeof ncbi.sg 		!== "undefined"
		    && typeof ncbi.sg.ping 	!== "undefined"
		    && typeof elm.data(SENSOR_EVT_TS) !== "undefined")
	    {
		var lifeSpan 		= event.timeStamp - elm.data(SENSOR_EVT_TS)
		var paramLifeSpan  	= "lifespan=" +  lifeSpan
		
		/* <<< remove block start after new version 10 will be released */
		var ping_info_v8 	= []
		ping_info_v8.push	("jsevent=" + JSEVENT_NAME)
		ping_info_v8.push	(paramLifeSpan)

		if (typeof elm.attr('ref') !== "undefined")
		    ping_info_v8.push	(elm.attr('ref'))
		/* >>> remove block ends */
			
		// applog pinger	    
		if (cfg.statIfLonger < lifeSpan )
		    ncbi.sg._version >= 10 ?
			ncbi.sg.ping(this, event, JSEVENT_NAME, [paramLifeSpan])
		    /* <<< remove block start after new version 10 will be released */
			: ncbi.sg.ping( ping_info_v8 )
		    /* >>> remove block ends */
		
	    }
	    // reset timestamp
	    if (typeof elm.data(SENSOR_EVT_TS) !== "undefined")
		elm.data(SENSOR_EVT_TS, null)
	}

	//
	function __getCfg (elm) {return elm.data('popupSensor.cfg')}
	//
	function __getCanvas (elm) {

	    var canvas 	= elm.data('popupSensor.popupCanvas')
	    var cfg 	= __getCfg(elm)

	    if (typeof canvas === "undefined")
	    {
		canvas = new popupCanvas( {
		    'el'	: 	elm,
		    'delayOut'	:	Math.max(cfg.delayOut, cfg.delayIn),    // maxing to let sensor to sense mouse
										// over when mouse moved from pop canvas to
										// sensor 
		    'delayIn'	: 	cfg.delayIn
		} )

		if (typeof canvas !== "undefined")
		{
		    elm.attr('canvas-rid', canvas.getCanvasElm().attr('id'))
		    __storeCanvas(elm, canvas)
		    
		}
	    } // if (typeof canvas === "undefined")
	    
	    return canvas
	}
	//
	function __storeCanvas (elm, canvas) {elm.data('popupSensor.popupCanvas', canvas)}
    }
    
    //
    function __logContext(opts) {
	//console.group(typeof opts.n !== 'undefined' ? opts.n : this)
	//__loginfo('opts: %o', opts)
	//console.groupEnd()
    }
    //
    function __LogContext(opts) {
	//console.group(typeof opts.n !== 'undefined' ? opts.n : this)
	//__loginfo('opts: %o', opts)
	//console.groupEnd()
    }
    //
    function __loginfo() {
	console.info.apply(this, arguments)
	//console.dir(arguments)
	// arguments properties
	/*
	 console.log(arguments.length);
	console.log(arguments.callee);
	console.log(arguments[1]);
	// Function properties
	console.log(__loginfo.length);
	console.log(__loginfo.caller);
	console.log(arguments.callee.caller);
	console.log(arguments.callee.caller.caller);
	console.log(__loginfo.name);
	console.log(__loginfo.constructor);
	*/
    }
    // ==========================  end of popupSensor =========================

    // ==========================  popupCanvas ================================
    {
	//
	// @param opts.id
	//		id of the image popup image
	//
	// @param opts.rid
	// 		rid of other existing canvas (element with id)
	//
	var popupCanvas = function (opts) {
	    this.__name 	= 'popupCanvas'
	    this.__cfgDefaults 	= {'delayIn': DELAYIN,  'delayOut': DELAYOUT}
	    this.__cfg 	 	= {}
	    this.__canvas 	= undefined
	    this.__imToLoad     = 0
	    this.__imagesBox    = undefined
	    this.__legendBox    = undefined

	    return (this.__init(opts) === true ? this : undefined)
	}
	
	$j.fn.extend(popupCanvas.prototype,  {
	    //
	    __init: function(opts) {
		/*__LogContext({
		    n: 'canvas.__init()',
		    t: this,
		    o: opts
		})*/
		
		$j.fn.extend(this.__cfg, this.__cfgDefaults)
		$j.fn.extend(this.__cfg, opts)
		
		var __canvasCreated = this.__newCanvas()
		
		if (__canvasCreated)
		{
		    var self = this
		    this.bind(JQ_MOUSEENTER_EVT, function (event) {self.__in(event)})
		    this.bind(JQ_MOUSELEAVE_EVT, function (event) {self.__out(event)})
		    this.bind(CANVAS_SHOW_EVT, function (event) {self.show(event)})
		    this.bind(CANVAS_HIDE_EVT, function (event) {self.hide(event)})
		}
		
		return __canvasCreated
		
	    },

	    //
	    __in: function (event) {//__loginfo('trace: canvas.__in()')
    		var cfg 	= this.__cfg
		var elm  	= cfg.el
		elm.trigger(CANVAS_MIN_EVT)
	    },
	    //
	    __out: function (event) {//__loginfo('trace: canvas.__out()')
		var cfg 	= this.__cfg
		var elm  	= cfg.el
		
		setTimeout(function(){elm.trigger(CANVAS_MOUT_EVT)}, cfg.delayOut )
		
	    },
	    //
	    __newCanvas: function () {
		var cfg = this.__cfg
		var el  = cfg.el
		var cid = undefined
		
		/*__logContext({
		    n: 'canvas.__newCanvas()',
		    t: this
		})*/
		// create canvas
		this.__canvas = $j('<div class="co co-default"><div class="co-inner"></div></div>')
		
		// if sensor element was passwed process supported attributes on that element
		if (typeof el !== "undefined")
		{
		    // handle @rid-figpopup [refers to other thumbnail with info about large images]
		    if (typeof el.attr('rid-figpopup') !== "undefined")
		    {
			cid = this.__collectHiresImgs($j($j('#' + el.attr('rid-figpopup'))[0]))
		    }
		    // handle @co-rid  [refers to existing callout block with callout content]
		    else if (typeof el.attr('co-rid') !== "undefined")
		    {
			$j('#' + el.attr('co-rid')).clone().removeAttr('id').show().appendTo(this.__getCanvasInner())
			cid = el.attr('co-rid')
		    }
		    // handle @co-content [URL escaped HTML content of the callout]
		    else if (typeof el.attr('co-content') !== "undefined")
		    {
			cid = '' + Math.floor(Math.random()*1000000)
			this.addContent(el.attr('co-content'))
		    }
		    // search for <img> with @hires or @src-large
		    else
			cid = this.__collectHiresImgs(el)
		}
		// if we were able to generate canvas' id then proceed with adding canvas into body
		if (typeof cid !== "undefined")
		{
		    var cnvs = this.getCanvasElm()
		    
    		    if (typeof el.attr('co-legend') == "string")
			this.addLegend(el.attr('co-legend') )

    		    if (typeof el.attr('co-legend-rid') == "string")
			this.addLegendRid(el.attr('co-legend-rid') )
		    
		    if (typeof el.attr('co-class') == "string")
			this.addClass(el.attr('co-class') )
		    
		    if (typeof el.attr('co-style') == "string")
			this.addStyle(el.attr('co-style') )

		    // append canvas to body
		    cnvs.appendTo( $j(document.body) )
		    cnvs.attr('id', String( '_cid_' + cid ).replace(/\W+/g, "_"))
		    el.attr('canvas-rid', cnvs.attr('id'))
		    
	    	    if (typeof ncbi 			!== "undefined"
	    		    && typeof ncbi.sg 		!== "undefined"
	    		    && typeof ncbi.sg.ping 	!== "undefined")
			ncbi.sg.scanLinks(cnvs.find("a").get())
		}
		
		return typeof cid !== "undefined" ? true : false
	    },
	    //
	    __collectHiresImgs: function (el) {
		var cid  = undefined
		var self = this
		
		/*__logContext({
		    n: 'canvas.__collectHiresImgs()',
		    t: this,
		    el: el
		})*/
		
		if (typeof el !== "undefined")
		{
		    el.find('img[src-large], img[hires]').each (
			function ()
			{
			    var im = $j(this);
			    
			    if (typeof im.attr('src-large') === "undefined")
				im.attr('src-large', im.attr('hires'))
			    
			    if (typeof cid === "undefined") cid = ''
			    
			    cid += '_' + im.attr('src-large') + '_'
			    self.addImage(im)
			}
		    )
		}
		return cid
	    },
	    //
	    bind: function(evntName, cb) {
		/*__logContext({
		    n: 'canvas.bind()',
		    t: this,
		    en: evntName,
		    cb: cb
		})*/
		this.__canvas.bind(evntName, cb)
	    },
	    //
	    show: function (event) {//__loginfo('trace: canvas.show()')
    		var cfg 	= this.__cfg
		var elm  	= cfg.el

		this.__canvas.show()
		this.__canvasArrangeLocation()

		elm.trigger(CANVAS_SHOWN_EVT)

	    },
	    //
	    hide: function (event) {//__loginfo('trace: canvas.hide()')
		var cfg 	= this.__cfg
		var elm = this.__cfg.el
		
		this.__canvas.hide()
		elm.trigger(CANVAS_GONE_EVT)
	    },
	    //
	    addImage: function (imThmb) {
		var cfg = this.__cfg
		var elm = cfg.el
		
		/*__logContext({
		    n: 'canvas.addImage()',
		    t: this,
		    imT: imThmb
		})*/
		
		if (typeof imThmb.attr('src-large') !== "undefined")
		{
		    this.__imToLoad += 1
			if (this.__imToLoad === 1)
			{
				this.__imagesBox = $j('<div class="images-box inline-block"></div>')
				this.__imagesBox.appendTo(this.__getCanvasInner())
			}
			
		    // check if the parent of image has an achnor element
		    // if so reproduce the link around popup image
		    var a
		    var aClosest 	= elm.closest('a')
    		    var imAlt           = imThmb.attr('alt')
		    
		    if (imAlt === undefined)
			imAlt = ''
		    
		    var im 		= $j('<img class="large-thumb"' + ' alt="' + imAlt + '"' + ' src="' + imThmb.attr('src-large') + '" />')

		    if (typeof aClosest !== "undefined")
			a = $j('<a></a>')
			
		    if (typeof a !== "undefined")
		    {
			$j.each(['href', 'ref', 'target'], function(i, item) {
			    if ( aClosest.attr(item) !== "" )
				a.attr(item, aClosest.attr(item))
			    }) // each
			a.bind('click', {}, function(event){
				event.stopPropagation()
				aClosest.trigger(event)
				return event.result === false ? false : true
			})
			im.appendTo(a.appendTo($j('<div class="inline-block"></div>').appendTo( this.__imagesBox)))
		    }
		    else
			im.appendTo($j('<div class="inline-block"></div>').appendTo( this.__imagesBox))
		    
		    // setup in-progress class and onload callbacks 
		    var __self = this
		
		    if (im.data('loaded') !== true)
		    {
			im.parent().addClass('in-progress')
			im.load(function () {
				    /*__logContext({
					n: 'canvas.addImage() img ' + im + 'loaded'
				    })*/
				    var __im = $j(this)

				    __im.data('loaded', true)
				    __im.show()
				    __im.parent().removeClass('in-progress')
				    __self.__imToLoad -= 1
				    __self.__canvasArrangeLocation()
			})
		    }
		}
	    },
	    //
	    addLegend: function (legend) {
		this.__legendBox = $j('<div class="legend">' + decodeURIComponent(legend) + '</div>').css({'text-align': 'left'})
		this.__legendBox.appendTo( this.__getCanvasInner().css({'text-align': 'center'}) )
	    },
	    //
	    addLegendRid: function (lrid) {
		var __legend = $j('#' + lrid).clone().removeAttr('id').show()
		if (typeof __legend !== "undefined")
		{
		    this.__legendBox = $j('<div class="legend"></div>').css({'text-align': 'left'})
		    __legend.appendTo(this.__legendBox)
		    this.__legendBox.appendTo( this.__getCanvasInner().css({'text-align': 'center'}) )
		}
	    },
	    //
	    addContent: function (content) {
		$j('<div class="content">' + decodeURIComponent(content) + '</div>').appendTo( this.__getCanvasInner() )
	    },
	    //
	    addClass: function (clss) {
		this.__getCanvasInner().addClass(clss)
	    },
	    //
	    removeClass: function (clss) {
		this.__getCanvasInner().removeClass(clss)
	    },
	    //
	    addStyle: function (style) {
		this.__getCanvasInner().attr('style', this.__getCanvasInner().attr('style') + ';' + style)
	    },
	    //
	    __getCanvasInner: function () {
		return  this.__canvas.children(".co-inner").size() > 0 ? this.__canvas.children(".co-inner") : this.__canvas
	    },
	    //
	    getCanvasElm: function () {
		var cfg = this.__cfg
		
		/*__logContext({
		    n: 'canvas.getCanvasElm()',
		    t: this
		})*/
		
		return this.__canvas
	    },
	    //
	    __canvasReCalcLocation: function (elm) {
		
		var cnvs 	= this.__canvas
		var ibox        = this.__imagesBox
		var lbox	= this.__legendBox
		var g           = {win: undefined, 'elm': undefined, cnvs: undefined, ibox: undefined, lbox: undefined}
		
		g.win  = {
		    size: 	{w: $j(window).width(), 	h: $j(window).height()},
		    ltc: 	{left: $j(window).scrollLeft(),	top: $j(window).scrollTop()}
		}
		    
		g.elm  = {
		    size: 	{w: elm.outerWidth(true),	h: elm.outerHeight(true)},
		    ltc:	elm.offset()
		}
		
		g.cnvs  = {
		    size: 	{w: cnvs.outerWidth(true),	h: cnvs.outerHeight(true)}
		}
		
		
		if (typeof ibox !== "undefined")
		    g.ibox  = {
			size:	{w: ibox.outerWidth(true),	h: ibox.outerHeight(true)}
		    }

		
		if (typeof lbox !== "undefined")
		{
		    g.lbox  = {
		        size:	{w: lbox.outerWidth(true),	h: lbox.outerHeight(true)}
		    }
		}
		
		var spaceVertical = [
		    {n: TOP, 	v: (g.elm.ltc.top 	- g.win.ltc.top) /** g.win.size.w}*/},
		    {n: BOTTOM,	v: ((g.win.ltc.top 	+ g.win.size.h) - (g.elm.ltc.top 	+ g.elm.size.h))
			/* * g.win.size.w*/}
		]
		var spaceHorizontal = [
		    {n: LEFT, 	v: (g.elm.ltc.left 	- g.win.ltc.left) /* * g.win.size.h*/},
		    {n: RIGHT, 	v: ((g.win.ltc.left 	+ g.win.size.w) - (g.elm.ltc.left 	+ g.elm.size.w))
			/* * g.win.size.h*/},
		]
		g.spH = spaceHorizontal.sort(function(a,b){return b.v - a.v})[0]
		g.spV = spaceVertical.sort(function(a,b){return b.v - a.v})[0]

		// search the bigest area to place popup
		if (g.cnvs.size.w / g.cnvs.size.h < 1
			|| g.win.size.w / g.win.size.h > g.cnvs.size.w / g.cnvs.size.h
			|| (g.spH.v > g.cnvs.size.w )
		    )
		    g.spName = g.spH.n
		else
		    g.spName = g.spV.n
		
		
		// now switch according to found place
		switch (g.spName) {
		    case LEFT:
			g.cnvs.ltc = {top: g.elm.ltc.top + g.elm.size.h/2 - g.cnvs.size.h/2, 	left: g.elm.ltc.left - g.cnvs.size.w}
			break
		    case RIGHT:
			g.cnvs.ltc = {top: g.elm.ltc.top + g.elm.size.h/2 - g.cnvs.size.h/2, 	left: g.elm.ltc.left + g.elm.size.w }
			break
		    case TOP:
			g.cnvs.ltc = {top: g.elm.ltc.top - g.cnvs.size.h, 	left: g.elm.ltc.left + g.elm.size.w/2 - g.cnvs.size.w/2 }
			break
		    case BOTTOM:
			g.cnvs.ltc = {top: g.elm.ltc.top + g.elm.size.h, 	left: g.elm.ltc.left + g.elm.size.w/2 - g.cnvs.size.w/2 }
			break
		    default:
			g.cnvs.ltc = g.elm.ltc
		}
		
		// correction for getting out of the viewport
		// bottom
		if ((g.cnvs.ltc.top + g.cnvs.size.h) > (g.win.ltc.top + g.win.size.h))
		    g.cnvs.ltc.top -= (g.cnvs.ltc.top + g.cnvs.size.h)  - (g.win.ltc.top + g.win.size.h)
		// right
		if ((g.cnvs.ltc.left + g.cnvs.size.w) > (g.win.ltc.left + g.win.size.w))
		    g.cnvs.ltc.left -= (g.cnvs.ltc.left + g.cnvs.size.w)  - (g.win.ltc.left + g.win.size.w)
		//top
		if (g.cnvs.ltc.top < g.win.ltc.top)   g.cnvs.ltc.top = g.win.ltc.top
		//left
		if (g.cnvs.ltc.left < g.win.ltc.left) g.cnvs.ltc.left = g.win.ltc.left

		    
		/*__LogContext({
		    n: 'canvas.__canvasReCalcLocation(): gmtr',
		    'g': g,
		    spH: spaceHorizontal,
		    spV: spaceVertical,
		})*/

		return g
	    },
	    //
	    __canvasArrangeLocation: function (iteration) {
		var __iter = typeof iteration === "number" ? iteration : 0
		var cfg 	= this.__cfg
		var cnvs 	= this.__canvas
		var __self 	= this
		var elm 	= cfg.el
		var lbox        = this.__legendBox
		var ibox        = this.__imagesBox
		
		
		/*__logContext({
		    n: 'canvas.__canvasArrangeLocation()',
		    iter: __iter,
		    t: this
		})*/
	
		// reset height to auto to make next calculations.
		var __imgs = cnvs.find('img')
		__imgs.each(function(){
		    var __im = $j(this)
		    if (__im.data("loaded") === true)
		    {
			__im.height('auto')
		    }
		})
		
		// reset lbox if it exists
		if (typeof lbox !== "undefined")
		    lbox.width('auto')
		
		// make calculations of geometry of key objects (window, elm, canvas)
		var g = this.__canvasReCalcLocation(elm)

		// balance images box and legend box
		if (typeof g.ibox !== "undefined" && typeof g.lbox !== "undefined" && g.lbox.size.w >= g.ibox.size.w)
		{
		    lbox.css({'width': Math.max(g.ibox.size.w, MIN_LEGEND_WIDTH)})
		    g = this.__canvasReCalcLocation(elm)
		}

		// set canvas location
		cnvs.css({
		    'top':	g.cnvs.ltc.top + 'px',
		    'left': 	g.cnvs.ltc.left + 'px'})

		// adjust geometry if all images are loaded and number of iterations is less then
		// predefined number
		if (this.__imToLoad === 0 && __iter < MAX_ITER)
		{
		    // downscale if necessary
		    {
			var __scale = {w: g.cnvs.size.w/(g.win.size.w * 0.95), h: g.cnvs.size.h/(g.win.size.h * 0.975)}
			var __scl = Math.max(__scale.w, __scale.h)

			if (Math.max(__scale.w, __scale.h) > 1)
			{
			    var __imgDownscaleAccum = 0
			    __imgs.each(function(){
				var __im = $j(this)
				
				if (__im.data("loaded") === true)
				{
				    var __downscaleWidthTo = 0;
				    if (__im.width()/__scl > MIN_IMG_WIDTH)
					__downscaleWidthTo = __im.width()/__scl
				    else if (__im.width() > MIN_IMG_WIDTH)
					__downscaleWidthTo = MIN_IMG_WIDTH
				    
				    if (__downscaleWidthTo > 0)
				    {
					//__loginfo('@downscale@%s@ %sx%s to width %s', __iter, __im.width(), __im.height(),    __downscaleWidthTo)
					__imgDownscaleAccum += __im.width() - __downscaleWidthTo
					__im.width(__downscaleWidthTo)
				    }
				}
			    })
			    
			    //__loginfo('@downscale@%s@ Accum = %s', __iter, __imgDownscaleAccum)
			    if (__imgDownscaleAccum > 1) {
				__self.__canvasArrangeLocation(__iter+1)
				return
			    }
			}
		    }
		    // upscale if necessary
		    {
			var __scale = {w: (g.win.size.w * 0.95)/g.cnvs.size.w, h: (g.win.size.h * 0.975)/g.cnvs.size.h}

			if (Math.min(__scale.w, __scale.h) > 1)
			{
			    var __imgUpscaleAccum = 0
			    __imgs.each(function(i){
				var __im          = $j(this)
				var __savedWidth  = __im.width()
				var __savedHeight = __im.height()
				
				__im.width('auto')

				if (__im.data("loaded") === true && __savedWidth < __im.width())
				{
				    var __scl = (1 + (Math.min(__scale.w, __scale.h)-1)*.5)
				    //__loginfo('@upscale@%s@ %sx%s by %s img %o', __iter, __savedWidth, __savedHeight, __scl, __im)
				    __im.width(__savedWidth * __scl > __im.width() ? 'auto': __savedWidth * __scl )
				    __imgUpscaleAccum += __im.width() - __savedWidth
				}else {
				    __im.width(__savedWidth)
				}
				
			    })
			    
			    //__loginfo('@upscale@%s@ Accum = %s', __iter, __imgUpscaleAccum)
			    if (__imgUpscaleAccum > 1)
				__self.__canvasArrangeLocation(__iter+1)
			}
		    }
		}else if (__iter < MAX_ITER)
		{
		    var __imgPreDownscaled = false
		    var __nImgs = __imgs.size()
		
		    // calculate border sizes of canvas
		    var bw = g.cnvs.size.w - cnvs.innerWidth()  + parseFloat(cnvs.css('padding-left'))
			    + parseFloat(cnvs.css('padding-right'))
		    var bh = g.cnvs.size.h - cnvs.innerHeight() + parseFloat(cnvs.css('padding-top'))
			    + parseFloat(cnvs.css('padding-bottom'))

		    __imgs.each(function(){
			var __im = $j(this)
			if (__im.data("loaded") === true)
			{
			    //__loginfo('@loading-in-progress-downscale@ %sx%s to fit into %sx%s', __im.width(), __im.height(), g.win.size.w, g.win.size.h)
			    if (__im.width() > (g.win.size.w - bw)/__nImgs && __im.width() > MIN_IMG_WIDTH)
			    {__im.width((g.win.size.w - bw)/__nImgs); __imgPreDownscaled = true}
			    
			    if (__im.height() > (g.win.size.h - bh)/__nImgs && __im.width() > MIN_IMG_WIDTH)
			    {__im.width( __im.width() / (__im.height()/((g.win.size.h - bh)/__nImgs)) ); __imgPreDownscaled = true}
			    if (__imgPreDownscaled && __im.width() < MIN_IMG_WIDTH)
				 __im.width(MIN_IMG_WIDTH) 
			    
			    //__loginfo('#loading-in-progress-downscale# %sx%s complete', __im.width(), __im.height())
			}
			
			if (__imgPreDownscaled) __self.__canvasReCalcLocation(elm)
		    })
		}
	    }
	})
    }
     // ==========================  popupCanvas ================================
    

     // ==========================  $j.fn.figPopup =============================
    
    $j.fn.figPopup = function(opts){
        var config = {};
	$j.extend ( config, {
            interval:      		200, // not really a pre popup delay, but used that way 
	    delayIn:      		200, // not implemented yet
	    delayOut:                   200, // not implemented yet, but actually it could be an alias to timeout.
            timeout:       		200,
            over:          		function(event){ $j(this).trigger(SENSOR_MIN_EVT) }, // handler onMouseOver
            out:           		function(event){ $j(this).trigger(SENSOR_MOUT_EVT) } // handler  onMouseOut
        } )
        $j.extend(config, opts)
        return  config
    }

    // ==========================  end of $j.fn.figPopup ========================

}) (jQuery) // end of extention of jQuery with figPopup


// ==========================  init handlers on a.figpopup =====================
jQuery(document).ready( function () {
    var fp_cfg = new jQuery.fn.figPopup()
    jQuery('a.figpopup').hoverIntent(fp_cfg).popupSensor({statIfLonger: 500, delayIn: fp_cfg.delayIn, delayOut: fp_cfg.delayOut})
});
// ==========================  end of init handlers on a.figpopup ==============
}

// end of hoverIntent routines for figures' popups
// ****************************************************************************

// =============================================================================
// <a href="..." rid="_xid1">toggle link</a>
// <div class="toggle-panel" id="_xid1">....content...</div>
function togglePanel(elm) {
    if (typeof jQuery !== "undefined")
    { 
	var jElm = jQuery(elm)
	var jPanel = jQuery('#' + jElm.attr('rid'))
	jPanel.slideToggle(200).toggleClass('hide')
	jElm.toggleClass('toggled')
	if (jElm.hasClass('toggled'))
	    jElm.find('span').replaceWith('<span>&#x25bc;</span>')
	else
	    jElm.find('span').replaceWith('<span>&#x25ba;</span>')
    }
    return false
}

// =============================================================================
function cpToggle(elm) { // copyright permissions slide toggler; structure is <dl><dt>TogglerLink</dt><dd>Toggled Content</dd></dl>
    if (typeof jQuery !== "undefined")
    { 
        jQuery(elm).parent().next().slideToggle(200) 
	var dl = jQuery(elm).parent().parent()
    
        if ( dl.hasClass('inline-block'))
    	    dl.removeClass('inline-block')
	else
	    dl.addClass('inline-block')    
    }
    
    return false
}
// next variable handles behaviuor of the radio buttons on the journal list page
var xpmc_fp = {
	onLoadHandler:  function () {
		var thisForm = document.forms['journalsearch'];
		// Set title switch
		if (thisForm.elements['title-switch'] !== undefined) {
			if (thisForm.elements['title-switch'].length !== undefined) {
				var title_switch_idx = (pmc_fp.init_state.title_switch === 'hide') ? 0 : 1;
				thisForm.elements['title-switch'][title_switch_idx].checked = true;
			}
			else {
				thisForm.elements['title-switch'].value = pmc_fp.init_state.title_switch;
			}
		}
		// Set search option
		if (thisForm.elements['search-option'] !== undefined) {
			if (thisForm.elements['search-option'].length !== undefined) {
				var search_opt_idx = (pmc_fp.init_state.search_option === 'journals') ? 0 : 1;
				thisForm.elements['search-option'][search_opt_idx].checked = true;
			}
			else {
				thisForm.elements['search-option'].value = pmc_fp.init_state.search_option;
			}
			if (pmc_fp.has_autocomplete === 'yes') {
				var termInput = jQuery('#term');
				thisForm.elements['search-option'][0].onclick = function() {
					termInput.ncbiautocomplete('option', 'isEnabled', true);
				};
				thisForm.elements['search-option'][1].onclick = function() {
					termInput.ncbiautocomplete('option', 'isEnabled', false);
				};
				
				termInput.keyup(function(event) {
					if (event.keyCode === 13) {
						return doSearch();
					}
				});
			}
		}
		// Set tabindex
		thisForm.elements['tabindex'].value = pmc_fp.init_state.tabindex;
	}
};
// init onload event with front page radio buttons handler
if (typeof jQuery !== 'undefined') 
{
    jQuery(document).ready( function () {
	if (typeof pmc_fp !== "undefined" && typeof xpmc_fp !== "undefined")
	    xpmc_fp.onLoadHandler()
    });
}

