/**
* This file should be shared by all web properties of AARP and contain functions
* useful to most contexts (and hopefully serve as a reference style/architectural
* guide).
* 
* As to whether some of these global objects should be more like a dictionary
* or a closure, that really depends on needs. If the object in question needs its
* own environment, go with closures.
* 
* @author Kaiser Shahid, 2007-10-02
*/

/* NATIVE PROTOTYPES SHOULD GO HERE */
String.prototype.trim = function() { return this.replace( /^\s+/g, '' ).replace( /\s+$/g, '' ); }
String.prototype.ltrim = function() { return this.replace( /^\s+/g, '' ); }
String.prototype.rtrim = function() { return this.replace( /\s+$/g, '' ); }
String.__ord_map = { " ": 32, "!": 33, '"': 34, "#": 35, "$": 36, "%": 37, "&": 38, "'": 39, "(": 40, ")": 41, "*": 42, "+": 43, ",": 44, "-": 45, ".": 46, "/": 47, "0": 48, "1": 49, "2": 50, "3": 51, "4": 52, "5": 53, "6": 54, "7": 55, "8": 56, "9": 57, ":": 58, ";": 59, "<": 60, "=": 61, ">": 62, "?": 63, "@": 64, "A": 65, "B": 66, "C": 67, "D": 68, "E": 69, "F": 70, "G": 71, "H": 72, "I": 73, "J": 74, "K": 75, "L": 76, "M": 77, "N": 78, "O": 79, "P": 80, "Q": 81, "R": 82, "S": 83, "T": 84, "U": 85, "V": 86, "W": 87, "X": 88, "Y": 89, "Z": 90, "[": 91, "\\": 92, "]": 93, "^": 94, "_": 95, "`": 96, "a": 97, "b": 98, "c": 99, "d": 100, "e": 101, "f": 102, "g": 103, "h": 104, "i": 105, "j": 106, "k": 107, "l": 108, "m": 109, "n": 110, "o": 111, "p": 112, "q": 113, "r": 114, "s": 115, "t": 116, "u": 117, "v": 118, "w": 119, "x": 120, "y": 121, "z": 122, "{": 123, "|": 124, "}": 125, "~": 126 };
String.__chr_map = { '32': " ", '33': "!", '34': '"', '35': "#", '36': "$", '37': "%", '38': "&", '39': "'", '40': "(", '41': ")", '42': "*", '43': "+", '44': ",", '45': "-", '46': ".", '47': "/", '48': "0", '49': "1", '50': "2", '51': "3", '52': "4", '53': "5", '54': "6", '55': "7", '56': "8", '57': "9", '58': ":", '59': ";", '60': "<", '61': "=", '62': ">", '63': "?", '64': "@", '65': "A", '66': "B", '67': "C", '68': "D", '69': "E", '70': "F", '71': "G", '72': "H", '73': "I", '74': "J", '75': "K", '76': "L", '77': "M", '78': "N", '79': "O", '80': "P", '81': "Q", '82': "R", '83': "S", '84': "T", '85': "U", '86': "V", '87': "W", '88': "X", '89': "Y", '90': "Z", '91': "[", "\\": 92, '93': "]", '94': "^", '95': "_", '96': "`", '97': "a", '98': "b", '99': "c", '100': "d", '101': "e", '102': "f", '103': "g", '104': "h", '105': "i", '106': "j", '107': "k", '108': "l", '109': "m", '110': "n", '111': "o", '112': "p", '113': "q", '114': "r", '115': "s", '116': "t", '117': "u", '118': "v", '119': "w", '120': "x", '121': "y", '122': "z", '123': "{", '124': "|", '125': "}", '126': "~" };

function $merge()
{
  if ( arguments.length < 2 )
    return arguments[0];
  
  var obj = {};
  for ( var i = 0; i < arguments.length; i++ )
  {
    for ( var j in arguments[i] )
      obj[j] = arguments[i][j];
  }
  
  return obj;
}

// gets ASCII value of char c
// TODO: make this work nice with chars 128-255?
String.ord = function( c )
{
  c = c.charAt( 0 );
  if ( String.__ord_map[c] )
    return String.__ord_map[c];
  else
    return -1;
}

// gets ASCII character of int c
String.chr = function( c )
{
  c = c + '';
  if ( String.__chr_map[c] )
    return String.__chr_map[c];
  else
    return null;
}

var AARP = {
  __version__: '1.0b1'
  
  /*
  store & set user's login state
  */
  // NEW [2008-02-14 | kaiser]: awesome, no one told me these additions were happening, so I had to infer it
  // from eForce's personalization component. GOTTA LOVE THE PROCESS AND TRANSPARENCY HERE!!!@1
  , User: { name: '', firstName: '', mail: 0, isLoggedIn: false, accountStatus: '', expirationDate: '' }
  , setUser: function()
  {
    var inf = Cookies.get( 'header' );
    if ( inf == null ) return;
    inf = inf.replace( /\"/g, '' ) ;
    var inf = inf.split( '|' );
    
    AARP.User.isLoggedIn = true;
    
    AARP.User.name = inf[2];
    AARP.User.firstName = inf[0];
    AARP.User.messages = inf[1];
    
    try { AARP.User.accountStatus = inf[3]; } catch ( e ) { }
    try { AARP.User.expirationDate = inf[4]; } catch ( e ) { }
  }
  /*
  Helper Objects/Functions
  */
  
  /**
  * Hopefully a useful function to open new windows. Usage:
  * 
  * AARP.newWindow( 'http://...', '_new', 500, 500 );
  * AARP.newWindow( 'http://...', '_new', 500, 600, { titlebar: true, menubar: true, addressbar: true } );
  *
  * @param href string Where the window should point to
  * @param name string The name of the window (equivalent to target attribute)
  * @param w int (Optional) Width of window
  * @param h int (Optional) Height of window
  * @param opts int (Optional) Additional options, defined below, are either true or false.
  *        - centered (window centered on screen), scrollbars, titlebar, addressbar, menubar, statusbar, toolbar, resizable, left, top
  *        By default, everything is false, except for resizable and centered.
  * @return object The reference to the new window
  */
  
  , newWindow: function( href, name )
  {
    var w = '', h = '', opts = {};
    if ( arguments.length > 2 )
      w = arguments[2];
    if ( arguments.length > 3 )
      h = arguments[3];
    if ( arguments.length > 4 )
      opts = arguments[4];
    
    w = parseInt( w );
    if ( !w ) w = 100;
    h = parseInt( h );
    if ( !h ) h = 100;
    
    // merge default values on absense of these items. otherwise, presence denotes true
    for ( var x in AARP.__newWindow_default_opts )
    {
      if ( opts[x] ) opts[x] = 1;
      else opts[x] = AARP.__newWindow_default_opts[x];
    }
    
    var xpos = 0, ypos = 0;
    if ( ( parseInt( navigator.appVersion ) >= 4 ) && (opts.centered) )
    {
      xpos = (screen.width - w) / 2;
      ypos = (screen.height - h) / 2;
    }
    
    var args = "width=" + w + "," 
      + "height=" + h + "," 
      + "location=" + opts.addressbar + "," 
      + "menubar=" + opts.menubar + ","
      + "resizable=" + opts.resizable + ","
      + "scrollbars=" + opts.scrollbars + ","
      + "status=" + opts.statusbar + "," 
      + "titlebar=" + opts.titlebar + ","
      + "toolbar=" + opts.toolbar + ","
      + "hotkeys=" + opts.hotkeys + ","
      + "screenx=" + xpos + "," // netscape
      + "screeny=" + ypos + "," // netscape
      + "left=" + xpos + ","
      + "top=" + ypos
    ;
    
    return window.open( href, name, args );
  }
  , __newWindow_default_opts: { 
    addressbar: 0
    , menubar: 0
    , resizable: 1
    , scrollbars: 0
    , statusbar: 0
    , titlebar: 0
    , toolbar: 0
    , left: 0
    , top: 0
    , hotkeys: 0
    , centered: 1
  }
  
  /*
  The 'page' variable contains convenient components of the URL for all sorts of use.
  setPage() parsers the URL into these components.
  */
  
  // NEW [2008-02-12 | kaiser] added some new properties:
  // is_authoring; site {dotorg,bulletin}; path_effective; pathc_effective
  , page: { url: '', protocol: 'http', host: '', port: '80', path: '', pathc: [], file: '', querystring: '', parameters: {}, anchor: ''
    , is_authoring: false, site: 'dotorg', path_effective: '', pathc_effective: []
  }
  , setPage: function()
  {
    AARP.page.url = document.location.toString();
    
    // separate path from querystring. [0] is full path, [1] is querystring
    var __path_qs = AARP.page.url.split( '?', 2 );
    
    // if url is 'http://www.aarp.org/health/', tmp would be [http:, , www.aarp.org, health, ]
    // if url is 'http://www.aarp.org/health/page.html', tmp would be [http:, , www.aarp.org, health, page.html]
    var tmp = __path_qs[0].split( '/' );
    
    // protocol
    var tmp2 = tmp.shift(); tmp.shift();
    AARP.page.protocol = tmp2.substring( 0, tmp2.length - 1 );
    
    // domain & port
    tmp2 = tmp.shift().split( ':' );
    AARP.page.host = tmp2[0];
    if ( tmp2.length > 1 )
      AARP.page.port = tmp2[1];
    
    // remove page from end (page could be an empty string)
    tmp2 = '';
    if ( tmp.length > 0 )
      tmp2 = tmp.pop();
    
    // remove & save anchor
    var anchor = [];
    if ( __path_qs[1] ) anchor = __path_qs[1].split( '#', 2 );
    else
    {
      // no querystring, so anchor would be immediately after page
      anchor = tmp2.split( '#', 2 );
      tmp2 = anchor[0];
    }
    
    if ( anchor[1] ) AARP.page.anchor = anchor[1];
    
    // set path & filename  
    AARP.page.file = tmp2.substring( 0, tmp2.length );
    AARP.page.path = '/' + tmp.join( '/' );
    if ( AARP.page.path == '/' )
      AARP.page.path = '';
    else
      AARP.page.pathc = AARP.page.path.substring( 1, AARP.page.path.length ).split( '/' );
    //AARP.page.pathc = tmp;
    
    // parse querystring into dictionary
    if ( __path_qs.length > 1 && __path_qs[1] != '' )
    {
      AARP.page.querystring = __path_qs[1];
      tmp = __path_qs[1].split( '&' ); //AARP.page.querystring.split( '&' );
      var ptr = AARP.page.parameters;
      for ( var p = 0; p < tmp.length; p++ )
      {
        var tmp3 = tmp[p].split( '=', 2 );
        if ( tmp3.length == 1 ) tmp2[1] = '';

        // check if the parameter already exists. if so, either convert to
        // an array, or append
        if ( ptr[tmp3[0]] )
        {
          // array
          if ( ptr[tmp3[0]].push )
            ptr[tmp3[0]].push( unescape( tmp3[1] ) );
          else
            ptr[tmp3[0]] = [ ptr[tmp3[0]], unescape( tmp3[1] ) ];
        }
        else
          ptr[tmp3[0]] = unescape( tmp3[1] );
      }
    }

    // TODO: add ?querystring to end?
    var portStr = '';
    if ( AARP.page.port != '80' )
      portStr = ':' + AARP.page.port;

    AARP.page.url = AARP.page.protocol + '://' + AARP.page.host + portStr + AARP.page.path + '/' + AARP.page.file;

    // NEW [2008-02-12 | kaiser]: set site and whether or not in authoring mode,
    // and also set what the real path(s) would be.

    if ( AARP.page.url.match( /bulletin[^.]*\.aarp/ ) ) AARP.page.site = 'bulletin';
    if ( AARP.page.url.match( /products[^.]*\.aarp/ ) ) AARP.page.site = 'products';
    if ( AARP.page.host.match( /w-d|w-s|author/ ) || AARP.page.port == '4402' )
    {
      AARP.page.is_authoring = true;

      // set what would be the published path. if we're on /content/bulletin.html 
      // or /content/home.html, set the root values
      if ( AARP.page.pathc.length > 2 )
      {
        //alert(AARP.page.pathc);
        last_dir = '';
        for ( var i = 2; i < AARP.page.pathc.length; i++ )
        {
          AARP.page.pathc_effective.push( AARP.page.pathc[i] );
          last_dir = AARP.page.pathc[i];
        }
        // if last_dir IS articles, the filename is an article, otherwise, it should be a valid channel.
        if ( last_dir != 'articles' )
        {
          var tf = AARP.page.file.split( '.' );
          if ( tf.length > 0 ) AARP.page.pathc_effective.push( tf[0] );
        }
        AARP.page.path_effective = '/' + AARP.page.pathc_effective.join( '/' );
      }
      else
      {
        AARP.page.path_effective = '';
        AARP.page.pathc_effective = [];
      }
    }
    else
    {
      AARP.page.path_effective = AARP.page.path;
      AARP.page.pathc_effective = AARP.page.pathc;
    }
  }
  
  /**
  * pageLpaded()
  * 
  * Should be called prior to BODY closing.
  */
  , pageLoaded: function()
  {
    if ( document.location.toString().match( /debugAds/ ) )
      AARPAds.debug();
    
    if ( AARP.page.parameters['generalStatus'] )
      AARP.generalStatus( AARP.page.parameters['generalStatus'] );
  }
  
  // if generalStatus is in querystring, attempt to show the div that should be populated with the value
  , generalStatus: function( msg )
  {
    try
    {
      $( 'generalStatus' ).innerHTML = msg;
      Effect.Appear( 'generalStatus' );
      setTimeout( "Effect.Squish( 'generalStatus' );", 4000 );
    }
    catch ( e ) { }
  }
  
  // the legendary encryption/decryption library, defined below
  , daw: null
  
  /*
  Objects/Functions definition deferred for other scripts.
  */
  , Login: null // header.js
  , Comment: null // community/comments.js
  , Flag: null // community/content.js
  , Favorite: null // community/content.js
  , Email: null // community/content.js
  , Form: null // global.forms.js
  , Validator: null // global.forms.js
  , Persistence: null
  , Personalization: null
}


/*
% Kaiser Shahid, 2007-09-17
Set of functions to easily handle cookie retrieval/manipulation. Code
adapted from http://www.quirksmode.org/js/cookies.html
*/

var Cookies = {
  __version__: ''
  , cookies: {}
  , domain: 'aarp.org'
  , path: '/'
  , load: function()
  {
    var ca = document.cookie.split( ';' );
    for ( var i = 0; i < ca.length; i++ )
    {
      var c = ca[i].ltrim();
      var kv = c.split( '=', 2 );
      // unescape value if hexcodes are in
      if ( kv[1] && kv[1].match( /\%[0-9a-zA-Z]+/ ) )
        kv[1] = unescape( kv[1] );
      this.cookies[kv[0]] = kv[1];
    }
  }
  
  , get: function( key )
  {
    if ( this.cookies[key] )
      return this.cookies[key];
    else
      return null;
  }
  
  /*
  Parameters: key, val, expiry, domain, path.
  Expiry should be in seconds. Use helper methods to convert other times.
  */
  
  , set: function( key, val )
  {
    var buffer = key + '=' + escape( val );
    var expiry = arguments[2];
    var domain = this.domain;
    var path = this.path;
    
    if ( expiry )
    {
      // CHANGED: if possible, figure out a way to account for DST, since 
      // getTime() seems to need a couple of hours padded on to actually persist.
      // --> getTime() returns milliseconds. duh.
      var date = new Date();
      date.setTime( date.getTime() + expiry*1000 );
      buffer += '; expires=' + date.toUTCString();
    }
    
    if ( arguments.length > 3 )
      domain = arguments[3];
    if ( arguments.length > 4 )
      path = arguments[4];
    
    buffer += '; path=' + path + '; domain=' + domain; // + '; domain=' + domain;
    document.cookie = buffer;
    this.cookies[key] = val;
    //alert( buffer + "\n\n" + document.cookie );
  }
  
  /*
  Parameters: key, domain, path.
  */
  
  , expire: function( key )
  {
    var domain = this.domain;
    var path = this.path;
    
    if ( arguments.length > 1 )
      domain = arguments[1];
    if ( arguments.length > 2 )
      path = arguments[2];
    
    this.set( key, 'x', -1, domain, path );
    delete this.cookies[key];
  }
  
  , debug: function()
  {
    var str = '';
    for ( var k in this.cookies )
      str += k + '=>' + this.cookies[k] + "\n";
    return str + "\n\n" + document.cookie;
  }
}

Cookies.load();


/*
% Kaiser Shahid, 2007-09-17
Set of functions to handle serving ads.

/community
  # $zonename = 'channel_community'
  # $iachn = 'community'
  showCommunityHomepage
    # $dindx = 'yes'
  /%object%
    # $taxa = 'subchannel_%object%'
    # $iasub = '%object%'
    # $dindx = 'yes'
  /%user%/%object% --> this is equivalent to /portfolio/%object%/index.jsp?membername=%user%&pageNum=1
  /portfolio/%object%/index.jsp?membername=%user%[&pageNum=%page%]
    # $taxa = 'subchannel_%object%'
    # $iasub = '%object%'
    # $dindx = 'yes'
    ? $pgid = '%user%__%object%__page_%page%'
  /%user%/%object%/%label%/%id%
    # $taxa = 'subchannel_%object%'
    # $iasub = '%object%'
    ? $pgid = '%user%__%object%__id_%id%'
  /profile
    # skip!
  /community/%user%
    # skip!
/%channel%/index.html
  # $zonename = 'channel_%channel%'
  # $iachn = '%channel%'
  # $dindx = 'yes'
  /articles/index.html
    ? $taxa = 'subchannel_articles'
    # $iasub = 'articles'
    # $dindx = 'yes'
    %id%.html
      # $zonename = '%converted:pgid[0]%'
      # $taxa = '%converted:pgid[1]%'
      # $pgid = '%pgid%'
  /%subchannel%/index.html
    # $taxa = 'subchannel_%subchannel%'
    # $iasub = '%subchannel%'
    # $dindx = 'yes'
    /articles/index.html
      ? $taxb = 'articles'
      # $dindx = 'yes'
      %id%.html
        # $zonename = '%converted:pgid[0]%'
        # $taxa = '%converted:pgid[1]%'
        # $pgid = '%pgid%'
/states[/index.html]
  # $zonename = 'channel_states'
  # $iachn = 'states'
  # $dindx = 'yes'
  %state%.html
    # $taxa = 'subchannel__state_%state%' OR 'subchannel__%state%' (if state is full name)
    # $iasub = 'state_%state%' OR '%state%' (if %state% is full name)
    # $dindx = 'yes'
/members[/index.html]
  # $zonename = 'channel_members'
  # $iachn = 'members'
  # $dindx = 'yes'
*/

var AARPAds = {
  __version__: ''
  , sitename: 'aarporgv2.dart'
  , sitename_map: { 'bulletin':'bulletin.dart','products':'aarppnsv2.dart' }
  , zonename: ''
  , kw: ''
  , house: ''
  , taxa: ''
  , taxb: ''
  , iachn: ''
  , iasub: ''
  , dindx: ''
  , jsrpt: ''
  , sorce: ''
  , pgid: ''
  , ord: 0
  , tile: 0
  , pgtyp: ''
  , tpl: null
  
  , tpl_str: '<' + "script type=\"text/javascript\" src=\"http://ad.doubleclick.net/N1175/adj/#{sitename}/#{zonename};abr=!webtv;kw=#{kw};sz=#{width}x#{height};tile=#{tile};jsrpt=yes;grab=all;house=#{house};taxa=#{taxa};taxb=#{taxb};iachn=#{iachn};iasub=#{iasub};dindx=#{dindx};sorce=#{sorce};pgid=#{pgid};ord=#{ord}?\">"
    + '<' + "/script><!-- ad_doc_write -->"
    + '<' + "script type='text/javascript'>"
    + "if ((!document.images && navigator.userAgent.indexOf(\"Mozilla/2.\") >= 0) || (navigator.userAgent.indexOf(\"WebTV\") >= 0)) {"
    + "document.write('<a href=\"http://ad.doubleclick.net/N1175/jump/#{sitename}/#{zonename};kw=#{kw};sz=#{width}x#{height};tile=#{tile};jsrpt=no;grab=all;house=#{house};taxa=#{taxa};taxb=#{taxb};iachn=#{iachn};iasub=#{iasub};dindx=#{dindx};sorce=#{sorce};pgid=#{pgid};ord=#{ord}?\">');"
    + "document.write('<img src=\"http://ad.doubleclick.net/N1175/ad/#{sitename}/#{zonename};kw=#{kw};sz=#{width}x#{height};tile=#{tile};jsrpt=no;grab=all;house=#{house};taxa=#{taxa};taxb=#{taxb};iachn=#{iachn};iasub=#{iasub};dindx=#{dindx};sorce=#{sorce};pgid=#{pgid};ord=#{ord}?\" width=\"#{width}\" height=\"#{height}\" border=\"0\"></a>');"
    + "}"
    + '<' + "/script>"
  , width: 0
  , height: 0
  , buffer: ''
  
  // TODO: figure out definitions how to get definitions for these
  , dem1: ''
  , dem2: ''
  , dem3: ''
  , debugInline: false
  , _pri: ''
  , _sec: ''
  , _ter: ''
  , _qua: ''
  
  /*
  AARPAds will set the taxonomy, page id, etc., based on any set vars and also where
  the user currently is (since /community will need to auto-generate all AARPAds).
  
  AARPAds SHOULD ONLY BE CALLED BEFORE <head> CLOSES! (AARPAds will allow the CMS to set
  some parameters manually through the custom head file).
  */
  
  , init: function()
  {
    AARPAds.ord = Math.floor( Math.random() * 1298948098294839 );
    AARPAds.tpl = new Template( AARPAds.tpl_str );
    
    //if ( AARPAds.sitename_map[AARP.page.host] )
    //  AARPAds.sitename = AARPAds.sitename_map[AARP.page.host];
    if( AARPAds.sitename_map[AARP.page.site] )
      AARPAds.sitename = AARPAds.sitename_map[AARP.page.site];
    
    var tmp = null;
    // woo! with setPage(), don't need to worry about AARPAds nonsense that used to be here.
    //var comp = document.location.toString().split( '/' );
    //var comp = "http://beta.aarp.org/health/index.html".split( '/' );
    
    var protocol = AARP.page.protocol;
    var domain = AARP.page.host;
    var page = AARP.page.file;
    var querystring = AARP.page.querystring;
    var comp = AARP.page.path.split( '/' );
    comp.shift();
    if ( comp.length == 0 ) comp.push( '' ); // to make sure code doesn't throw errors, just put in a dummy value
    
    // /pri/articles/article.html -> 3
    // /pri/sec/articles/articles.html -> 4
    
    //Modified by Yonas Hassen on 02 July 2008:
    //Added third and fourth level subdirectories.
    //These will fill the values for 'taxa' and 'taxb' respectively, 
    //only if 'iachn' and 'iasub' are not null.
    var _pri = comp[0];
    var _sec = comp[1];
    var _ter = comp[2];
    var _qua = comp[3];
    AARPAds._pri = _pri;
    AARPAds._sec = _sec;
    AARPAds._ter = _ter;
    AARPAds._qua = _qua;
    
    /* dbg( "Ad Init:\n"
      + 'url: ' + AARP.page.url + "\n"
      + "querystring: " + querystring + "\n"
      + 'domain: ' + domain + "\n"
      + 'page: ' + page + "\n"
      + 'pathc: ' + comp + "\n"
      + 'primary: ' + _pri + "\n"
      + 'secondary: ' + _sec + "\n"
    ); */
    
    //TODO: check for subdomain properties (bulletin, magazine, etc.)--
    //taxonomy/zonename/etc. conventions should be the same throughout
    //(at least for the time being), so only sitename ever needs to change.
    
    var isArticle = false;
    
    // CMS processing
    if ( _pri != 'community' )
    {
      // normalize pgid to set for zonename, taxa, and taxb
      // NEW (2008-02-05): add != 'null' test
      var pgid = null;
      if ( AARPAds.pgid != '' && AARPAds.pgid != 'null' )
      {
        if ( AARPAds.pgid.match( /\/content\/articlerepository/ ) )
        {
          isArticle = true;
          
          // remove '/content/articlerepository' from beginning, and article label from end
          pgid = AARPAds.pgid.split( '/' );
          if ( pgid[0] == '' ) pgid.shift();
          pgid.shift(); pgid.shift();
          pgid.pop();
          
          /*
          // NEW [2008-07-10 | kaiser]: special processing for articles only (used to
          // be anytime pgid was pre-set). the article template was changed way back per
          // scott's request to include dcsubject1 as a zonename, but apparently he now 
          // wants the repository path to be the zonename and dcsubject1 to be taxa/taxb.
          // this code change is specific to how the data is outputted on the proxy, so
          // any changes to the ad code in the proxy (regarding zonename) will affect this.
          
          var taxonomy = AARPAds.zonename.split( /__/ );
          var l1 = pgid[0];
          var l2 = 'null';
          if ( pgid[1] ) l2 = pgid[1];
          
          AARPAds.zonename = l1 + '__' + l2;
          AARPAds.taxa = taxonomy[0];
          AARPAds.taxb = taxonomy[1];
          if ( !AARPAds.taxa || AARPAds.taxa == '' ) AARPAds.taxa = 'null';
          if ( !AARPAds.taxb || AARPAds.taxb == '' ) AARPAds.taxb = 'null';
          */
          
          // NEW [2007-12-14 | kaiser]: don't override taxa, taxb, and zonename if they're set
          //if ( AARPAds.taxa == '' || AARPAds.taxa == 'null' ) AARPAds.taxa = pgid[0];
          //if ( (AARPAds.taxb == '' || AARPAds.taxb == 'null') && pgid.length > 1 ) AARPAds.taxb = pgid[1];
          if ( AARPAds.zonename == '' )
          {
            AARPAds.zonename = pgid[0];
            for ( var i = 1; i < pgid.length; i++ )
              AARPAds.zonename += '_' + pgid[i];
          }
        }
      }
      else
      {
        // NEW [2008-07-09]: assign a page id
        AARPAds.pgid = '/' + AARP.page.path;
        AARPAds.taxa = _ter;
        AARPAds.taxb = _qua;
      }
      
      // for now, AARPAds only includes states pages. but it could grow.
      var notPrimaryChannels = /^states$/;
      if ( !comp[0].match( notPrimaryChannels ) )
      {
        // no matter what, index.html in the CMS will be an index/landing page of some sort.
        // however, if dindx is manually set at startup, its current value will be respected.
        // TODO: match for /^index/ instead?
        
        if ( page != 'index.html' && AARPAds.dindx == '' )
          AARPAds.dindx = 'no';
        else if ( page == 'index.html' )
          AARPAds.dindx = 'yes';
      
        if ( comp[1] == 'articles' )
          _sec = 'articles';
        else if ( comp[2] == 'articles' )
        {
          _sec = comp[1];
          _ter = 'articles';
        }
      }
      else
      {
        // main state landing & individual state pages
        if ( _pri == 'states' && comp.length <= 2 )
          AARPAds.dindx = 'yes';
      }
      
      AARPAds.iachn = _pri;
      AARPAds.iasub = _sec;
    }
    else
    {
      var comObjMatch = /^(people|photos|video|journals|groups|tags)$/;
      if ( page.match( /^showCommunityHome/ ) )
        AARPAds.dindx = 'yes';
      else
      {
        // /community/%object%
        var m = null;
        if ( comp[1] ) m = comp[1].match( comObjMatch );
        
        if ( AARP.page.file == 'search.bt' )
        {
          AARPAds.zonename = 'search_results';
          AARPAds.dindx = 'yes';
        }
        else if ( m )
        {
          _sec = comp[1];
          AARPAds.dindx = 'yes';
        }
        // user's profile index
        else if ( comp.length == 2 )
        {
          AARPAds.dindx = 'yes';
        }
        // /community/portfolio/%object%/index.jsp?membername=%user%&pageNum=%page%
        else if ( comp[1] == 'portfolio' )
        {
          _sec = comp[2];
          AARPAds.dindx = 'yes';
          m = querystring.match( /membername=([\w_]+)/ );
          if ( m[1] )
          {
            AARPAds.pgid = m[1] + '__' + _sec;
            m = querystring.match( /pageNum=([\d]+)/ );
            if ( m[1] )
              AARPAds.pgid += '__page_' + m[1];
            else
              AARPAds.pgid += '__page_1';
          }
        }
        // /community/%user%/%object%[/%label%/%id%]
        else if ( comp[1] != 'misc' && comp[1] != 'profile' )
        {
          // TODO: should i set page [id] to be %user%__%object%__%id%?
          _sec = comp[2];
          AARPAds.pgid = comp[1] + '__' + _sec;
          
          // if the url decomp is 
          if ( comp.length == 5 )
             AARPAds.pgid += '__id_' + comp[4]; // + '__' + comp[3]
          else if ( comp.length == 3 )
          {
            AARPAds.pgid += '__page_1';
            AARPAds.dindx = 'yes';
          }
          
          page = AARPAds.pgid;
        }
        else
        {
          // TODO: what would go here?
        }
      }
    }
    
    // NEW [2008-07-10 | kaiser]: moved stuff under this branch since it interferes with article behavior.
    if ( !isArticle )
    {
      if ( AARPAds.zonename == '' )
      {
        // NEW [2008-07-09 | kaiser]: if in a subchannel, make sure to set the zone to subchannel. may need to revisit
        // code regarding 2008-02-16 later (once scott gives test cases)
        if ( _sec && _sec != '' && _sec != 'null' )
          AARPAds.zonename = 'subchannel_' + _sec;
        else
          AARPAds.zonename = 'channel__' + _pri;
      }
      
      if ( AARPAds.taxa == 'topic' ) AARPAds.taxa = 'null';
      if ( AARPAds.taxb == 'subtopic' ) AARPAds.taxb = 'null';
      
      if ( AARPAds.taxb == '' ) AARPAds.taxb = _ter;    
      AARPAds.iachn = _pri;
      AARPAds.iasub = _sec;
      
      //Added by Yonas Hassen on 02 July 2008
      if (AARPAds.iachn != '' && AARPAds.iasub != '')
      {
        if ( AARPAds.taxa == '' || AARPAds.taxa == 'null' ) AARPAds.taxa = _ter;
        if ( AARPAds.taxb == '' || AARPAds.taxb == 'null' ) AARPAds.taxb = _qua;
      }
    }
    
    var kw = Cookies.get( 'search-kw' );
    var queryPatterns = /(query|tags|groupQuery|keywords|terms)=([^&]+)/;
    
    // look for & set query for duration of session
    var m = document.location.toString().match( queryPatterns );
    if ( m )
    {
      AARPAds.kw = AARPAds.kw_normalize( m[2] );
      Cookies.set( 'search-kw', AARPAds.kw );
    }
    else if ( kw )
      AARPAds.kw = kw;
    
    // NEW (2008-01-22): per Scott's fixes
    // set 'null' if these are empty still
    // # Modified by Yonas Hassen (30 June 2008)
    var tmp = ['kw', 'taxa', 'taxb', 'iachn', 'iasub', 'sorce', 'pgid'];
    for ( var y in tmp )
    {
      y = tmp[y];
      if ( AARPAds[y] == '' || AARPAds[y] == undefined ) AARPAds[y] = 'null';
    }
    
    // NEW [2008-07-31 | kaiser]: post-fixing things
    AARPAds['sorce'] = AARPAds.normalize( AARPAds['sorce'].toLowerCase() );
    
    // for easier debugging: just show output inline with the ad so that
    // viewing community code is easier
    if ( AARP.page.parameters['debugAds'] )
      AARPAds.debugInline = true;
    
    // there's a 49 character limit on zonenames
    try
    {
      if ( AARPAds.zonename.length > 49 )
        AARPAds.zonename = AARPAds.zonename.substring( 0, 49 );
    }
    catch ( e ) { }
  }
  
  // output ad code
  // optional 3rd parameter, if given, should be an id string of an object whose innerHTML will be set 
  //    to the ad code.
  //    NEW [2009-02-20 | kaiser]: typecheck on 3rd parameter. if object, will do innerHTML, otherwise, will return the ad string
  
  , serve: function( width, height )
  {
    AARPAds.fix_before_serve();
    AARPAds.width = width;
    AARPAds.height = height;
    
    var obj = null;
    var ret_str = false;
    if ( arguments.length > 2 )
    {
      if ( typeof( arguments[2] ) == 'object' )
      {
        obj = arguments[2];
        obj = $( obj );
      }
      else
      {
        ret_str = true;
      }
    }
    
    // we're sending 'AARPAds' as the dictionary because, well, AARPAds is a 
    // dictionary. with super powers.
    
    AARPAds.tile++;
    var buffer = AARPAds.tpl.evaluate( AARPAds );
    
    if ( obj == null )
    {
      if ( !ret_str )
      {
        if ( AARPAds.debugInline )
          buffer += "<textarea rows='10' cols='25'>Tile #" + AARPAds.tile + "\n" + buffer.replace( "<" + "&gt;" ).replace( ">", "&lt;" ) + "</textarea>\n\n";
        document.write( buffer );
      }
    }
    else
      obj.innerHTML = buffer;
    
    if ( !AARPAds.debugInline )
      AARPAds.buffer += "Tile #" + AARPAds.tile + "\n" + buffer + "\n\n";
    
    if ( ret_str ) return buffer;
  }
  
  // NEW [2008-02-16 | kaiser]: catch any runtime errors post-initialize
  , fix_before_serve: function()
  {
    if ( AARP.page.file == 'search.bt' )
    {
      AARPAds.zonename = 'search_results';
    }
    // TODO: individual checks on overwriting taxa/taxb?
    else if ( AARPAds.taxa == 'topic' || AARPAds.taxa == '' ) //  || AARPAds.taxb == 'subtopic' || AARPAds.taxb == ''
    {
      AARPAds.zonename = 'channel_community';
      AARPAds.taxa = 'null';
      AARPAds.taxb = 'null';
    }
  }
  
  , debug: function()
  {
    document.write( "<textarea rows='20' cols='60'>" + AARPAds.buffer + "</textarea>" );
  }
  
  // convert 'fancy' characters into alphanumeric and underscore
  , normalize: function( str )
  {
    /*
    str = str.replace( /[^\w\s-]/g, '' );
    str = str.replace( /-/g, ' ' );
    */
    
    // Round 1: remove non-word characters from beginning & end of string
    // Round 2: all non-word, non-dash characters get converted to _
    // Round 3: replace any remaining spaces with _
    str = str.trim().replace( /^[^\w]+/, '' ).replace( /[^\w]+$/, '' );
    str = str.replace( /[^\w-]+/g, '_' );
    str = str.replace( /\s+/g, '_' );
    
    if ( arguments.length > 1 )
      str = str.toLowerCase();
    
    return str;
  }
  
  // simlar to normalize(), except convert all non-words to spaces, then convert 
  // groups of spaces to +
  , kw_normalize: function( str )
  {
    // trim & replace non-words at beginning and end with empty strings
    str = str.trim().replace( /^[^\w]+/, '' ).replace( /[^\w]+$/, '' );
    // replace any run of non-words and dashes with a single space
    str = str.replace( /[^\w-]+/g, ' ' );
    // convert one or more spaces to a single plus
    str = str.replace( /\s+/g, '+' );
    
    return str.toLowerCase();
  }
}

// TODO: for search keywords, we need to make sure those are available via querystring, because we 
//       need to incorporate that into the ad code init before any ads are served.

/**
* Ported David's daw_encrypt.py to Javascript. Biggest missing pieces was ord() and chr(), which I implemented on String:
* the caveat is that they can only handle asci characters 33-127. Which is fine, since these functions would be
* used for non-special character encodings (i.e. email, urls, timestamps, plaintext).
* 
* @author Kaiser Shahid, 2007-10-09
*/

// TODO: obfuscate this! (or at least the key.)
AARP.daw = {
  aKey: [ 26, 238, 80, 83, 225, 13, 123, 145, 78, 248, 63, 65, 54, 208, 199, 45, 152, 229, 168, 109, 82, 189, 183, 208, 132, 192, 141, 139, 42, 239, 20, 166, 66, 54, 43, 40, 62, 114, 14, 34, 39, 30, 66, 220, 237, 82, 218, 82, 194, 66, 245, 200, 102, 240, 232, 97, 165, 42, 93, 236, 19, 109, 160, 14, 163, 15, 127, 222, 219, 18, 213, 90, 220, 234, 59, 125, 243, 14, 237, 104, 85, 200, 140, 200, 49, 52, 124, 83, 36, 241, 162, 237, 18, 222, 150, 73, 84, 130, 114, 92, 123, 3, 205, 176, 100, 232, 244, 244, 244, 47, 187, 128, 82, 177, 33, 135, 152, 249, 49, 157, 88, 70, 69, 45, 138, 94, 5, 116, 74, 231, 76, 243, 55, 39, 136, 158, 138, 214, 109, 173, 16, 170, 163, 182, 166, 111, 141, 168, 243, 150, 112, 64, 141, 130, 71, 199, 77, 187, 151, 174, 103, 216, 127, 153, 147, 43, 70, 164, 17, 192, 181, 141, 184, 68, 174, 50, 48, 187, 219, 90, 3, 19, 83, 61, 244, 93, 216, 118, 140, 157, 181, 34, 118, 57, 167, 180, 132, 127, 232, 77, 146, 248, 29, 9, 225, 121, 145, 23, 163, 162, 65, 79, 219, 67, 143, 160, 169, 202, 90, 105, 227, 107, 98, 243, 44, 44, 135, 67, 96, 99, 13, 40, 163, 34, 8, 21, 220, 153, 162, 154, 172, 111, 11, 193, 24, 199, 142, 133, 166, 17, 69, 97, 96, 86, 74, 106, 31, 39, 12, 190, 224, 212, 216, 201, 181, 22, 13, 56, 98, 185, 226, 248, 214, 180, 182, 124, 157, 14, 89, 7, 212, 173, 67, 161, 101, 85, 191, 183, 205, 222, 65, 56, 56, 163, 60, 219, 41, 6, 228, 123, 142, 182, 4, 123, 156, 87, 240, 196, 206, 59, 160, 70, 10, 122, 39, 0, 202, 42, 197, 45, 171, 96, 100, 57, 230, 96, 178, 9, 57, 97, 126, 114, 236, 56, 76, 100, 88, 118, 137, 116, 113, 74, 195, 115, 240, 137, 226, 198, 208, 93, 4, 19, 9, 232, 216, 216, 238, 100, 116, 244, 24, 231, 220, 57, 116, 162, 184, 13, 79, 131, 114, 225, 168, 246, 198, 194, 59, 62, 161, 222, 29, 65, 187, 190, 24, 24, 46, 191, 174, 208, 84, 105, 211, 160, 61, 108, 117, 53, 237, 200, 175, 52, 200, 246, 16, 207, 84, 118, 98, 60, 165, 171, 179, 233, 237, 151, 2, 184, 16, 19, 230, 150, 207, 31, 114, 208, 239, 60, 179, 225, 56, 8, 146, 130, 216, 35, 152, 34, 188, 205, 218, 116, 97, 29, 23, 66, 56, 4, 200, 244, 88, 124, 204, 101, 24, 218, 207, 20, 134, 87, 92, 120, 127, 42, 241, 183, 17, 79, 173, 248, 3, 28, 4, 35, 107, 160, 25, 230, 214, 106, 107, 59, 15, 61, 242, 180, 237, 122, 187, 61, 165, 245, 248, 126, 101, 164, 184, 99, 3, 2, 26, 68, 190, 173, 19, 191, 132, 64, 4, 83, 192, 75, 184, 51, 90, 16, 95, 203, 213, 203, 231, 115, 38, 225, 139, 76, 41, 245, 177, 88, 108, 55, 12, 156, 72, 230, 53, 29, 150, 122, 129, 183, 136, 35, 121, 215, 141, 62, 112, 181, 233, 182, 242, 38, 1, 98, 111, 247, 176, 164, 147, 178, 58, 128, 32, 121, 138, 48, 120, 65, 176, 97, 169, 29, 106, 117, 85, 115, 40, 151, 245, 68, 242, 37, 98, 5, 89, 71, 110, 114, 147, 55, 249, 219, 117, 239, 89, 16, 39, 234, 213, 134, 17, 136, 247, 68, 77, 213, 217, 136, 194, 119, 49, 17, 98, 4, 156, 13, 127, 231, 183, 95, 11, 63, 114, 130, 88, 41, 38, 89, 91, 152, 52, 143, 15, 19, 88, 191, 186, 219, 138, 233, 52, 186, 179, 123, 76, 76, 246, 127, 230, 49, 231, 54, 238, 90, 99, 152, 64, 70, 85, 36, 25, 174, 80, 68, 56, 159, 15, 235, 236, 41, 193, 180, 101, 203, 142, 179, 111, 4, 178, 234, 49, 130, 4, 50, 213, 46, 38, 95, 176, 244, 37, 245, 234, 182, 221, 206, 61, 100, 206, 232, 194, 93, 204, 73, 116, 156, 45, 172, 55, 47, 236, 40, 26, 210, 105, 88, 233, 96, 242, 89, 94, 114, 54, 52, 26, 62, 123, 173, 241, 20, 190, 159, 190, 46, 220, 78, 162, 161, 100, 34, 173, 223, 184, 74, 144, 159, 238, 119, 12, 168, 248, 87, 29, 114, 147, 236, 124, 212, 160, 157, 97, 231, 96, 189, 17, 79, 16, 182, 94, 219, 118, 144, 145, 56, 8, 183, 171, 228, 209, 37, 175, 193, 70, 108, 228, 61, 177, 23, 165, 33, 185, 166, 169, 176, 155, 190, 136, 128, 96, 190, 55, 214, 11, 73, 63, 78, 175, 33, 167, 52, 175, 184, 14, 112, 198, 244, 230, 153, 110, 83, 197, 188, 25, 27, 36, 182, 201, 225, 168, 138, 186, 230, 226, 160, 46, 90, 186, 80, 125, 114, 230, 150, 144, 94, 233, 123, 99, 158, 111, 224, 9, 33, 187, 97, 236, 139, 65, 207, 169, 53, 150, 62, 242, 248, 80, 207, 87, 160, 184, 111, 26, 234, 248, 173, 229, 0, 200, 184, 216, 82, 236, 239, 43, 184, 12, 185, 98, 221, 162, 95, 95, 128, 33, 111, 197, 12, 125, 136, 103, 190, 143, 225, 23, 21, 146, 153, 139, 78, 199, 9, 220, 68, 12, 46, 230, 42, 215, 138, 120, 61, 25, 69, 115, 99, 182, 1, 208, 110, 163, 112, 163, 36, 63, 237, 238, 175, 141, 8, 189, 200, 177, 68, 6, 239, 131, 125, 190, 60, 2, 149, 36, 18, 137, 238, 221, 60, 125, 209, 160, 200, 31, 181, 188, 247, 107, 219, 17, 215, 236, 35, 45, 182, 244, 93, 198, 38, 76, 89, 145, 134, 244, 168, 57, 22, 23, 92, 2, 52, 56, 219, 165, 9, 107, 25, 200, 68, 103, 0, 185, 230, 226, 168, 221, 39, 175, 70, 146, 229, 120, 187, 169, 108, 226, 154, 120, 73, 246, 4, 151, 59, 81, 22 ]
  , encrypt: function( s, start, backwards )
  {
    L = [];
    if ( backwards )
      key = 1023 - start;
    else
      key = start;
    
    for ( var i = 0; i < s.length; i++ )
    {
      next = String.ord( s.charAt( i ) ) ^ AARP.daw.aKey[key];
      L.push( AARP.daw._hex( next ) ); // strip of the 0x added by hex
      if ( backwards )
      {
        key -= 1;
        if ( key < 0 )
          key = 1023;
      }
      else
      {
        key += 1;
        if ( key > 1023 )
          key = 0;
      }
    }
    
    L.push( AARP.daw._hex( start ) );
    return L.join( "" );
  }
  , decrypt: function( s )
  {
    start = parseInt( s.substring( s.length - 2 ), 16 ) // last two chars are encoded start value
    backwards = start % 2;
    s = s.substring( 0, s.length - 2 );
    L = [];
    
    if ( backwards )
      key = 1023 - start;
    else
      key = start;
    
    var max = Math.floor( s.length / 2 ) - 1;
    
    for ( var i = 0; i <= max; i++ )
    {
      var lo = i * 2;
      var hi = (i + 1) * 2;
      next = parseInt( s.substring( lo, hi ), 16 ) ^ AARP.daw.aKey[key];
      
      L.push( String.chr( next ) );
      
      if ( backwards )
      {
        key -= 1;
        if ( key < 0 )
          key = 1023;
      }
      else
      {
        key += 1;
        if ( key > 1023 )
          key = 0;
      }
    }
    
    return L.join( "" );  
  }
  , _hex: function( n )
  {
    s = n.toString( 16 );
    if ( s.length == 1 )
          return "0" + s;
      else
          return s;
  }
  , crypt_text: function( plain )
  {
    var start = plain.length % 250;
    var backwards = start % 2;
    return AARP.daw.encrypt( plain, start, backwards );
  }
  , decrypt_text: function( enc )
  {
    return AARP.daw.decrypt( enc );
  }
  , create_timestamp: function()
  {
    var s = null;
    if ( arguments.length > 0 )
    {
      s = arguments[0];
    }
    else
    {
      s = new Date();
      s = s.getTime();
    }
    var start = s % 250;
    var backwards = start % 2;

    return AARP.daw.encrypt( s + "", start, backwards );
  }
  , show_timestamp: function( ts )
  {
    var s = parseInt( AARP.daw.decrypt( ts + "" ) );
    return new Date( s );
  }
}

// added by kaiser shahid [2007-11-05]
// this used to be here, i thought...

var defaultText = {
  __version__: ''
  , set: function( obj, txt )
  {
    if ( obj.value.trim() == '' )
      obj.value = txt;
  }
  , unset: function( obj, txt )
  {
    if ( obj.value.trim() == txt )
      obj.value = '';
  }
}

// added by kaiser shahid [2008-02-05]
AARP.hitTracker = {
  server: 'www.aarp.org'
  , name: ''
  , url: ''
  , repoUrl: ''
  , authorName: ''
  , category: ''
  , debugURL: ''
  , hit: function()
  {
    // do not track author instance hits
    if ( AARP.page.is_authoring ) return;
    
    // NEW [2008-03-24]: remove 'debug=y'
    AARP.hitTracker.url = AARP.hitTracker.url.replace( /debug=[^&]+/, '' );
    
    // remove empty querystring
    if ( AARP.hitTracker.url[AARP.hitTracker.url.length-1] == '?' )
      AARP.hitTracker.url = AARP.hitTracker.url.substring( 0, AARP.hitTracker.url.length-1 );
    
    // NEW [2008-03-05 | kaiser]: add site to top of category if not dotorg
    var category = AARP.hitTracker.category;
    if ( AARP.page.site != 'dotorg' ) category = '/' + AARP.page.site + category;
    
    url = 'http://' + AARP.hitTracker.server + '/community/hitTracker/track.action'
      + '?name=' + escape( AARP.hitTracker.name ) + '&url=' + escape( AARP.hitTracker.url )
      + '&repoUrl=' + escape( AARP.hitTracker.repoUrl ) + '&authorName=' + escape( AARP.hitTracker.authorName )
      + '&category=' + escape( category )
    ;
    
    var img = new Image();
    img.src = url;
    
    AARP.hitTracker.debugURL = url;
    if ( AARP.page.parameters['debug'] ) document.write( "this: " + AARP.hitTracker.url + "<br />target: " + url + "<br />path, effective: " + AARP.page.pathc_effective + "<br />path: " + AARP.page.pathc + "<br />category: " + category + "<br />site: " + AARP.page.site );
    //document.location = url;
  }
}

/**
* AARP.Persistence provides larger, more long-term storage solutions on the browser end,
* utilizing either Mozilla's globalStorage or IE's userData. If neither are available, returns
* false on any calls  made to its methods.
* 
* @author Kaiser Shahid, 2007-10-09
*/

// TODO: fill this out.

AARP.Persistence = {
  __version__: ''
  , persistable: false
  , type: ''
  , domain: 'aarp.org' // default domain to store data to. aarp.org will be available to all subdomains
  , init: function()
  {
    this.persistable = true;
    if ( globalStorage )
      this.type = 'mozilla'; 
    else if ( userData )
      this.type = 'ie';
    else
      this.persistable = false;
  }
}

function dbg( str ) { if ( document.location.toString().match( /debug/ ) ) { alert(str); } }

AARP.setPage();
AARP.setUser();

// CHANGED [2008-03-05 | kaiser]: only condition needed now is that staging & dev point to www-s
if ( AARP.page.host.match( /-[sd]\.aarp/ ) ) AARP.hitTracker.server = 'beta-s.aarp.org';

AARP.Personalization = {
  // User not logged in
  notLoginImage: ''
  , notLoginImageLink: ''
  // Not an active member
  , notMemberImage: ''
  , notMemberImageLink: ''
  // Active Member
  , activeMemberImage: ''
  , actibeMemberImageLink: ''
  //Expiring member
  , expiringMemberImage: ''
  , expiringMemberImageLink: ''
  //Expired member
  , expiredmemberimage: ''
  , expiredmemberimageLink: ''
  , checkStatus: function()
  {
    //var loginStatus   = checkLoginStatus("header");
    var loginStatus = AARP.User.isLoggedIn;
            
    // Defining the variable
    var userName    ="";
    var accountStatus  ="";
    var expirationDate  ="";
    
    if (loginStatus) // != null
    {
      userName = AARP.User.name;
      accountStatus = AARP.User.accountStatus;
      expirationDate = AARP.User.expirationDate;
      //if ( AARP.page.is_authoring ) { alert( "accountStatus=" + accountStatus ); }
      // checking for account status
      if (accountStatus == "0") 
      {
        if (expirationDate != undefined || expirationDate != '') 
        {
          // checking for non user member
          var toDay   = new Date();
          
          // parsing the expire date
          var exactDate    =  expirationDate.split(' ')[0];
          var expireMonth    =  exactDate.split('/')[0];
          var expireDay    =  exactDate.split('/')[1];
          var expireYear    =  exactDate.split('/')[2];
          
          var expireDay    = new Date(expireYear,expireMonth-1,expireDay);
          
          var milli_toDay   = toDay.getTime();
          var milli_expireDay   = expireDay.getTime();
          var diff     = milli_expireDay - milli_toDay;
          var noDay    = Math.round(diff/(1000*60*60*24));          
                    
          if (noDay>180) 
          {
            // active member
            if (AARP.Personalization.activeMemberImage!="")
            {
              //checking the image reference is there or not
              if (AARP.Personalization.actibeMemberImageLink!="")
              {
                document.write("<a href='"+AARP.Personalization.actibeMemberImageLink+"'>"+AARP.Personalization.activeMemberImage+"</a>");
              }
               else 
              {
                document.write("<a href='#' onclick='return false;'>"+AARP.Personalization.activeMemberImage+"</a>");
              }  
            }
          }
          else if (noDay<=180) 
          {
            //expering member
            if (AARP.Personalization.expiringMemberImage!="")
            {
              //checking the image reference is there or not
              if (AARP.Personalization.expiringMemberImageLink!="")
              {
                document.write("<a href='"+AARP.Personalization.expiringMemberImageLink+"'>"+AARP.Personalization.expiringMemberImage+"</a>");
              }
               else 
              {
                document.write("<a href='#' onclick='return false;'>"+AARP.Personalization.expiringMemberImage+"</a>");
              }  
            }
          }
        }        
      }
      else if (accountStatus == "5") 
      {
        //expired member
        if (AARP.Personalization.expiredmemberimage!="")
        {
          //checking the image reference is there or not
          if (AARP.Personalization.expiredmemberimageLink!="")
          {
            document.write("<a href='"+AARP.Personalization.expiredmemberimageLink+"'>"+AARP.Personalization.expiredmemberimage+"</a>");
          }
           else 
          {
            document.write("<a href='#' onclick='return false;'>"+AARP.Personalization.expiredmemberimage+"</a>");
          }  
        }
        
      }
      else
      {
        if (AARP.Personalization.notMemberImage!="")
        {
          //checking the image reference is there or not
          if (AARP.Personalization.notMemberImageLink!="")
          {
            document.write("<a href='"+AARP.Personalization.notMemberImageLink+"'>"+AARP.Personalization.notMemberImage+"</a>");
          }
           else 
          {
            document.write("<a href='#' onclick='return false;'>"+AARP.Personalization.notMemberImage+"</a>");
          }  
        }            
      }
    }
    else
    {
      // should display the default Image
      if (AARP.Personalization.notLoginImage!="")
      {
        //checking the image reference is there or not
        if (AARP.Personalization.notLoginImageLink!="")
        {
          document.write("<a href='"+AARP.Personalization.notLoginImageLink+"'>"+AARP.Personalization.notLoginImage+"</a>");
        }
         else 
        {
          document.write("<a href='#' onclick='return false;'>"+AARP.Personalization.notLoginImage+"</a>");
        }  
      }
    }
  }
}


/**
* compatibility with popup option in article authoring.
*/

function CFC_popup(/*String*/ url, /*String*/ name, /*String*/ features)
{
  var defaultWidth = 500;
  var defaultHeight = 400;
  if (url.indexOf("/content/") == 0) url = url.substr(8);
  var w = window.open(url, name, features);
  w.focus();
}









/*
The below is for email and favorite overlays
Copied by Jon Lechliter from article_v2.js (2008-12-16)
-------------------------------------------------------*/

AARP.Email = {
  __version__: ''
  , email_validation: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/
  , mail_template: ''
  , generalStatus: ''
  , currentOverlay: ''
  , overlayToPrefix: {}
  , formToPrefix: {}
  , overlayCreated: false
  , nodeCache: {}

  , open: function( event )
  {
    hideCalcs();
    hideSelectBoxes() ;
    hideFlash() ;
    
    var overlay = 'emailOverlay';
    var form = 'emailContentForm';
    var prefix = 'email';
    
    if ( arguments.length > 1 && arguments[1] )
      overlay = arguments[1];
    if ( arguments.length > 2 && arguments[2] )
      form = arguments[2];
    if ( arguments.length > 3 && arguments[3] )
      prefix = arguments[3];
    
    AARP.Email.currentOverlay = overlay;
    AARP.Email.currentForm = form;
    
    AARP.Email.overlayToPrefix[overlay] = prefix;
    AARP.Email.formToPrefix[form] = prefix;
    
  var objBody = document.getElementsByTagName("body").item(0);
  
  var objOverlay = null;
  if ( !AARP.Email.overlayCreated )
  {
    objOverlay = document.createElement("div");
    objOverlay.setAttribute('id','overlay');
    objOverlay.style.display = 'none';
    objBody.appendChild(objOverlay);
    AARP.Email.overlayCreated = objOverlay;
  }
  else
  {
    objOverlay = AARP.Email.overlayCreated;
  }
  
  var overlayDel = null;
  if ( !AARP.Email.nodeCache[overlay] )
  {
    overlayDel = $("tools").removeChild($(overlay));
    objBody.appendChild(overlayDel);
    AARP.Email.nodeCache[overlay] = overlayDel;
  }
  else
  {
    overlayDel = AARP.Email.nodeCache[overlay];
  }
  
  var arrayPageSize = getPageSize();
  $('overlay').setStyle({position: 'absolute', top: '0', left: '0'});
  $('overlay').style.width = arrayPageSize[0] +"px";
  $('overlay').style.height = arrayPageSize[1] +"px";

  var overlayDuration = 0.2;  // shadow fade in/out duration
  var overlayOpacity = 0.6;  // controls transparency of shadow overlay
  new Effect.Appear('overlay', { duration: overlayDuration, from: 0.0, to: overlayOpacity });
  
  var arrayPageScroll = getPageScroll();
  var dialogBoxTop = arrayPageScroll[1] + (arrayPageSize[3] / 3);
  var dialogBoxWidth = 350;
  var dialogBoxLeft = ((arrayPageSize[0] - dialogBoxWidth) / 2) + arrayPageScroll[0];
  overlayDel.style.top = dialogBoxTop +"px"; 
  overlayDel.style.left = dialogBoxLeft +"px"; 
  overlayDel.setStyle({position: 'absolute', zIndex: 1000000});

  $(overlay).show();

  }
  , send: function()
  {
    var prefix = 'email';
    
    if ( arguments.length > 0 && arguments[0] )
    {
      AARP.Email.currentForm = arguments[0];
      prefix = AARP.Email.formToPrefix[arguments[0]];
    }
    
    // this first check indicates that this is on a non-community page (presumably an article).
    // fill in fields if true.
    
    var ctypename = $( prefix + '.contentTypeName' );
    if ( ctypename && ctypename.value == "article" )
    {
      var em = $( prefix + '.from' ).value;
      var emc = AARP.daw.crypt_text( em );
      var url = AARP.page.protocol + '://' + AARP.page.host + ':' + AARP.page.port + AARP.page.path + '/' + AARP.page.file;
      $( prefix + '.status' ).style.display = 'none';
      var req = $( prefix + '.required' );
      
      // repository id gives unique value
      //$( prefix + '.contentId' ).value = AARPAds.pgid;
      $( prefix + '.contentTitle' ).value = document.title;
      $( prefix + '.permalinkUrl' ).value = url;
      $( prefix + '.redirect' ).value = url + '?generalStatus=' + AARP.Email.generalStatus;
      
      // TODO: when form validation is built, use that instead of this
      var msgs = [];
      if ( !em.match( AARP.Email.email_validation ) )
        msgs.push( "Your E-mail address is invalid" );
      
      // split up recipients list and validate each email;
      // show the addresses that aren't valid.

      var tmpRE = /,\s*/;
      var tmp = $( prefix + '.to' ).value.trim().split( tmpRE );
      var recipients = [];
      var rinvalid = [];
      for ( var i = 0; i < tmp.length; i++ )
      {
        if ( tmp[i].match( AARP.Email.email_validation ) )
          recipients.push( AARP.daw.crypt_text( tmp[i].trim() ) );
        else
          rinvalid.push( tmp[i] );
      }
      if ( rinvalid.length > 0 )
        msgs.push( 'These recipients are invalid: ' + rinvalid.join( ", " ) );
      else
      {
        // limit # of recipients after processing copyme
        if ( $( prefix + '.copyme' ).checked ) recipients.push( emc );
        if ( recipients.length > 5 )
          msgs.push( "You can send emails up to 5 people at a time (including yourself). You currently have " + recipients.length ) + " people on your list";
      }
      
      if ( req && req.value.match( /emailContentMessage/ ) )
      {
        var _m = $( prefix + '.message' );
        if ( _m.value.trim() == '' )
          msgs.push( "Message must not be empty." );
      }
      
      if ( msgs.length > 0 )
      {
        $( prefix + '.status' ).innerHTML = "The following errors occurred:<br />&ndash; " + msgs.join( '<br />&ndash; ' );
        $( prefix + '.status' ).style.display = 'block';
      }
      else
      {
        var realname = $( prefix + '.fromName' ).value.trim();
        if ( realname == '' ) realname = em;
        
        //$( prefix + '.email' ).disabled = true;
        $( prefix + '.email' ).value = em;
        $( prefix + '.realname' ).value = $( prefix + '.fromName' ).value = realname;
        $( prefix + '.recipients' ).value = recipients.join( ',' );
        $( prefix + '.mail_template' ).value = AARP.Email.mail_template;
        $( prefix + '.subject' ).value = 'AARP.org Article from ' + em;
        $( AARP.Email.currentForm ).submit();
      }
    }
  }

  , close: function()
  {
    if ( arguments.length > 0 )
      AARP.Email.currentOverlay = arguments[0];
    
    // hide error messages
    var prefix = AARP.Email.overlayToPrefix[AARP.Email.currentOverlay];
    $( prefix + '.status' ).style.display = 'none';
    
  $(AARP.Email.currentOverlay).hide();
  var overlayDuration = 0.2;  // shadow fade in/out duration
  new Effect.Fade('overlay', { duration: overlayDuration});
  showCalcs();
  showSelectBoxes() ;
  showFlash() ;
  }
}

AARP.Email.mail_template = AARP.daw.crypt_text( 'http://assets.aarp.org/aarp.org_/misc/formmail_email-tpl_article.html' );
AARP.Email.generalStatus = escape( 'Thanks! Your email has been sent.' );

AARP.Favorite = {
  __version__: ''

  , errorHandler: function(transport)
  {
    if (AARP.page.querystring["debug"])
    {
        alert(transport.responseText);
    }
  }
  
  // need two parameters: stringURL and articleTitle
  , Article: {
    submitURL: '/community/articleFavorite/submit.bt'
    , checkURL: '/community/articleFavorite/validate.bt'
    , open: function()
    {
      $( 'favorite.title' ).innerHTML = document.title;
      overlayConfirmation('favoriteContentOverlay');
    }
    , save: function()
    {
      if ( !AARP.User.isLoggedIn )
      {
        // TODO: make a nicer way of showing error/status message
        alert( "You must be logged in." );
        return;
      }
      
      // TODO: does one save the proxy path or the repository path?
      // TODO: is it right to be using document.title going forward?
      var params = 'articleURL=http://' + AARP.page.host + AARP.page.path + '/' + AARP.page.file
        + '&articleTitle=' + escape( document.title )
        ;
      
      new Ajax.Request(
        AARP.Favorite.Article.submitURL
        , { method: 'get', parameters: params, onSuccess: AARP.Favorite.Article.save__onSuccess, onError: AARP.Favorite.errorHandler }
      );
    }
    , save__onSuccess: function( response )
    {
      // TODO: check response for status code
      //alert(response.responseText.trim());
      AARP.generalStatus( 'This has been saved to your Bookmarks on your Profile Page.' );
      closeOverlayConfirmation();
    }
    , unsave: function()
    {
      
    }
    /*
    check that the current article is already saved? use Cookies to
    cache this info (maybe do it per session).
    */
    // TODO: parameter check to see if an external method is explicitly forcing an action
    , check: function()
    {
      var page = AARP.page.path + '/' + AARP.page.file;
      var params = 'articleID=' + page + '&memberID=' + AARP.User.name;
      
      new Ajax.Request(
        AARP.Favorite.Article.checkURL
        , { method: 'post', data: params, onSuccess: AARP.Favorite.Article.check__onSuccess }
      );
      
      /* var article = Cookies.get( 'favorite.article.' + page;
      
      // not saved for this session
      if ( article == null )
      {
        
      } */
      
    }
    , check__onSuccess: function( response )
    {
      var val = response.responseText.trim().toLowerCase();
      if ( val == "true" )
      {
        // TODO: disable bookmark link and indicate that this is already saved
      }
    }
  }
}


/*
Dynamic character counter for <textarea> and <input> tags
Copied by Jon Lechliter from bulletin/js/global.js (2008-7-30)
-------------------------------------------------------*/

function getObject(obj) {
  var theObj;
  if(document.all) 
  {
      if(typeof obj=="string") 
    {
          return document.all(obj);
      } 
    else 
    {
          return obj.style;
      }
    }
  
  if(document.getElementById) 
  {
      if(typeof obj=="string") 
    {
          return document.getElementById(obj);
      } 
    else 
    {
          return obj.style;
      }
    }
  return null;
}

function toCount(entrance,exit,text,characters) {
  var entranceObj=getObject(entrance);
  var exitObj=getObject(exit);
  var length=characters - entranceObj.value.length;
    
  if(length <= 0) 
  {
      length=0;
        text='<span class="disable">You have reached your character limit.</span>';
      entranceObj.value=entranceObj.value.substr(0,characters);
    }
    
  exitObj.innerHTML = text.replace("{CHAR}",length);
}

/* end: Dynamic character counter */


/* Old Functions for Social Bookmarking tool */
function toggleShare() {
  $('shareBG').style.visibility = "visible";
  $('socialBookmarks').style.display= "block";
}

function toggleShareOff() {
  $('shareBG').style.visibility = "hidden";
  $('socialBookmarks').style.display= "none";
}

function toggleShare2() {
  $('socialBookmarks2').style.display = "block";
  $('socialBookmarks2').style.visibility = "visible";
  $('shareBG2').style.visibility = "visible";
}

function toggleShareOff2() {
  $('socialBookmarks2').style.display = "none";
  $('socialBookmarks2').style.visibility = "hidden";
  $('shareBG2').style.visibility = "hidden";
}


/* Functions for Social Bookmarking tool */
AARP.Share = {
  __version__: ''
  , errorHandler: function(transport)
  {
    if (AARP.page.querystring["debug"])
    {
        alert(transport.responseText);
    }
  }
  ,  open: function()
    {
      overlayConfirmation('shareContentOverlay');
      yahooBuzzArticleHeadline = document.title;
      yahooBuzzArticleSummary = getMetaValue('description');
      yahooBuzzArticleId = window.location.href;
  }
}

function openShareWindow(url) {
  var flowURL = null;
  if(url=="DIGG") {
    flowURL = "http://digg.com/remote-submit?url=" + window.location.href + "&title=" + document.title + "&bodytext=" + getMetaValue('description');
  } else if(url =="DELICIOUS") {
    flowURL = "http://del.icio.us/post?url=" + window.location.href + "&title=" + document.title;
  } else if(url =="LINKEDIN") {
    flowURL = "http://www.linkedin.com/shareArticle?mini=true&url=" + window.location.href + "&title=" + document.title + "&summary=" + getMetaValue('description');
  } else if(url == "FACEBOOK") {
    flowURL = "http://www.facebook.com/sharer.php?u=" + window.location.href + "&t=" + document.title;
  }
  var shareWindowRef = window.open(''+flowURL,"SHARE",'left=20,top=20,width=650,height=450,toolbar=0,resizable=0,scrollbars=1');
}

function getMetaValue(metaName) {
  var metaTags=document.getElementsByTagName("META");
  for (var i=0; i<metaTags.length; i++) {
    if (metaTags[i].name.toLowerCase() == metaName.toLowerCase()) {
      return metaTags[i].content;
    }
  }
  return "NA";
}
/* end: Functions for Social Bookmarking tool */


/*
  Function for disabling ads
-----------------------------------*/

function removeAds() {
  var adArr = $$('div.ad');
  
  for (var i = 0; i<adArr.length; i++) {
    adArr[i].style.display = "none";  
  }
}

/* end: Function for disabling ads */


/**
* Helper functions to fix dynamic right column for (what else) IE.
* @author Kaiser Shahid (2009-02-20; 2009-02-23)
*/

AARP.externalRight = {
  found_ads: 0
  , dbg: null
  
  /**
  * This function will turn the calls to AARPAds.serve() into actual HTML, in order to reduce
  * the number of document.write() calls and also do a little modifying of html (mainly
  * wrapping the ad code with a div and giving it a unique id).
  */
  , adFix: function( str )
  {
    // NEW [2009-05-11 | kaiser]: it looks like the end head and opening body tag are included as part of output, so strip
    // those off. split on that.
    
    var head_body_remover = new RegExp( /<\/head><body[^>]+>/ );
    var div_container_remover = new RegExp( "<div id='AARPRightColumn'>" );
    var script_matcher_init = new RegExp(
      '<' + 'script[^>]*>\\s*AARPAds\.init[^;]+;\\s*</' + 'script>'
    );
    var script_matcher_serve = new RegExp(
      '<' + 'script[^>]*>\\s*AARPAds\\.serve([^;]+);\\s*</' + 'script>', 'g'
    );
    
    // replace the start & end of the big container and then the script init call
    
    // [NEW [2009-06-02 | kaiser]: the tag balancing with the replacement of
    // AARPRightColumn seemed to be broken, so now just replace the opening tag
    // and id with a plain <div>. this code was removed: "replace( /\s*<\/div>\s*$/, '' )"
    
    str = str.replace( head_body_remover, '' );
    str = str.replace( div_container_remover, '<div>' ).replace( script_matcher_init, '' );
    str += "<div id='aarp.ad.___separator___' style='display: none;'> </div>";
    AARPAds.init();
    
    var t = null;
    if ( document.location.href.match( /debug/ ) )
    {
      t = document.createElement( 'textarea' );
      t.id = 'dbgggr';
      t.value = str;
      t.style.width = '100%';
      t.style.height = '100px';
      document.getElementsByTagName( 'body' )[0].appendChild( t );
      AARP.externalRight.dbg = t;
    }
    
    var serves = str.match( script_matcher_serve );
    for ( var i = 0; i < serves.length; i++ )
    {
      // break up '...serve( x, y )...' into '..serve( ' and 'x,y )...'
      var tmp = serves[i].split( /serve\(\s*/ );
      // break up 'x, y )...' into 'x, y' and ' )...'
      tmp = tmp[1].split( /\s*\)/ );
      
      // parse out the dimensions and retrieve the corresponding ad code.
      // also, wrap the ad code with a unique container and id
      var dim = tmp[0].split( /,\s*/ );
      var w = parseInt( dim[0] ), h = parseInt( dim[1] );
      var ad_buff = "<div id='aarp.ad." + i + "'>" + AARPAds.serve( w, h, true ) + "</div>";
      AARP.externalRight.found_ads++;
      
      // replace the script call with the actual ad output
      str = str.replace( serves[i], ad_buff );
    }
    
    if ( AARP.externalRight.dbg != null ) AARP.externalRight.dbg.value = str;
    
    return str;
  }
  
  /**
  * Once the page finishes loading, re-examine the right column and move each of the ads inserted at the bottom to
  * the appropriate slots above. The typical way to check if the current node is an ad element is if:
  * 1) the separator has been found
  * 2) the current element is not: SCRIPT, NOSCRIPT, non-HTML element (whitespace, html comments)
  */
  
  , postFix: function()
  {
    //if ( !navigator.userAgent.toString().match( /MSIE/ ) ) return;
    
    var right = $( 'rightColumn' );
    var dbg = $( 'rightColumnText' );
    
    var found_separator = false;
    var last_ele_was_script = false;
    var ad_counter = 0;
    var ad_containers = [];
    var dbg = AARP.externalRight.dbg;
    
    for ( var i = 0; i < right.childNodes.length; i++ )
    {
      var node = right.childNodes[i];
      var tagname = ''; if ( node.tagName ) tagname = node.tagName.toUpperCase();
      //dbg.value += node.tagName + ' -> ' + node.id  + ' ? ' + node.src + "\n";
      
      if ( node.id == 'aarp.ad.___separator___' )
      {
        if ( dbg ) dbg.value += "\n# found_separator!";
        found_separator = true;
        continue;
      }
      else if ( tagname == 'DIV' && node.getAttribute( 'table' ) == 'y' )
      {
        ad_containers = AARP.externalRight.extractAdContainers( node );
        if ( dbg ) dbg.value += "\nad_containers=" + ad_containers;
      }
      
      if ( !found_separator ) continue;
      
      // a legitimate ad node; remove and insert into container pointed to by ad_counter,
      // then increment ad_counter by 1.
      if ( tagname != 'SCRIPT' && tagname != 'NOSCRIPT' && tagname.match( /[\w]+/ ) )
      {
        //dbg.value += ad_counter + ' - ' + tagname + ' : ' + node.innerHTML + "\n\n";
        right.removeChild( node );
        if ( ad_containers[ad_counter] )
        {
          ad_containers[ad_counter].appendChild( node );
          ad_counter++;
        }
        last_ele_was_script = false;
      }
    }
  }
  
  /**
  * Grabs the first child of each node under parent that has 'ad' in the class name.
  */
  
  , extractAdContainers: function( parent )
  {
    var ad_containers = [];
    for ( var i = 0; i < parent.childNodes.length; i++ )
    {
      var node = parent.childNodes[i];
      if ( node.className.match( /^ad/ ) )
        ad_containers.push( node.firstChild );
    }
    
    return ad_containers;
  }
}


AARP.misc = {
   mostPopularFixer: function( div_id )
   {
     /*
       Event.observe( window, 'load', function() {
           if ( !$( div_id ) ) return;
           var li = $( div_id ).getElementsByTagName( 'a' );
           for ( var i = 0; i < li.length; i++ )
           {
               var a = li[i];
               try { a.innerHTML = unescape( a.innerHTML ); }
               catch ( e ) {}
           }
       } );
     */
   }
}

/**
* Moved from js/cms/ctg.js to here. Could be useful for other things.
*/

AARP.XMLParser = {
   parse: function( xml )
   {
       var xmlDoc = null;
       var docType = "text/xml";

       var opts = {}; if ( arguments[1] ) opts = arguments[1];
       if ( opts.docType ) docType = opts.docType;

       try //Internet Explorer
       {
           xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" );
           xmlDoc.async = false;
           // IE parser does not like DOCTYPE =/
           xmlDoc.loadXML( xml.replace( /^\s*<!DOCTYPE[^>]+>/, '' ) );
       }
       catch( e )
       {
           try //Firefox, Mozilla, Opera, etc.
           {
               var parser = new DOMParser();
               xmlDoc = parser.parseFromString( xml, docType );
           }
           catch( f ) { dbg(f.description) }
       }

       return xmlDoc;
   }

   , getSpanText: function( span )
   {
       if ( span.childNodes.length > 0 )
           return span.childNodes[0].nodeValue;
       else
           return '';
   }
}

/*
Expandable Categories.
  Example can be seen at http://www.aarp.org/aarp/About_AARP/contact_aarp/
*/

AARP.expandCats = {
    enabled: false
    , categories: function()
    {
        if ( !AARP.expandCats.enabled ) return;

        var groupArray = $$('.categoryGroup');
        var groupTitleArray = $$('.categoryGroup h3 a');
        var subGroupsArray = $$('.subGroups');
        var categoryArray = $$('.category');
        var categoryTitleArray = $$('.category h4 a');
        var contentArray = $$('.categoryContent');

        for (var i = 0; i < groupArray.length; ++i) {
          var subCat = groupArray[i].getElementsByTagName("div");
          var groupId = groupArray[i].id;
          for (var j = 0; j < subCat.length; ++j) {
            if (subCat[j].id.indexOf(groupId + "_") != 0) {
              if (subCat[j].className == "category") {
                subCat[j].id = groupId + "_" + subCat[j].id;
              }
              if (subCat[j].className == "categoryContent") {
                subCat[j].id = subCat[j].parentNode.id + "_content";
              }
            }
          }
        }

        for (var i = 0; i < groupTitleArray.length; ++i) {
          var groupTitle = groupTitleArray[i];
          groupTitle.onclick = switcherManual;
        }

        for (var i = 0; i < categoryTitleArray.length; ++i) {
          var subCatTitle = categoryTitleArray[i];
          subCatTitle.onclick = switcherManual2;
        }

        function switcherManual()
        {
            var thisGroup = "";
            var parent = this.parentNode;
            while ( parent != null ) {
              if ( parent.className && parent.className == "categoryGroup" ) {
                thisGroup = parent;
              }
              parent = parent.parentNode;
            }
            var subGroup = document.getElementById(thisGroup.id + "_subGroup");
            if (subGroup == null) {
              subGroup = document.getElementById(thisGroup.id + "_" + "categorySolo");
            }
            if (subGroup.style.display == "block") {
              subGroup.style.display = "none";
              thisGroup.getElementsByTagName("a")[0].className = "";
            } else {
              for (var i = 0; i < groupTitleArray.length; ++i) {
                groupTitleArray[i].className = "";
              }
              for (var i = 0; i < subGroupsArray.length; ++i) {
                subGroupsArray[i].style.display = "none";
              }
              for (var i = 0; i < categoryArray.length; ++i) {
                if (categoryArray[i].id.indexOf("categorySolo") > -1) {
                  categoryArray[i].style.display = "none";
                }
              }
              subGroup.style.display = "block";
              thisGroup.getElementsByTagName("a")[0].className = "on";
              for (var i = 0; i < contentArray.length; ++i) {
                if (contentArray[i].id.indexOf("categorySolo") < 0) {
                  contentArray[i].style.display = "none"
                  if (categoryTitleArray[i]) {
                    categoryTitleArray[i].className = "";
                  }
                  if (contentArray[i].id.split("_content")[0] == this.href.split("#")[1]) {
                    contentArray[i].style.display = "block";
                    categoryTitleArray[i].className = "on";
                  }
                }
        
              }
              if (!subGroup) {
                soloCat.style.display = "block"
              }
            }
            return false;
        } //switcherManual
    
        function switcherManual2()
        {
            var thisGroup = "";
            var parent = this.parentNode;
            while ( parent != null ) {
              if ( parent.className && parent.className == "category" ) {
                thisGroup = parent;
              }
              parent = parent.parentNode;
            }
            var catContent = document.getElementById(thisGroup.id + "_content");
        
            if (catContent == null) {
              catContent = document.getElementById(thisGroup.id + "_" + thisGroup.id + "Solo");
            }
            if (catContent.style.display == "block") {
              catContent.style.display = "none";
              thisGroup.getElementsByTagName("a")[0].className = "";
            } else {
              for (var i = 0; i < contentArray.length; ++i) {
                if (contentArray[i].id.indexOf("categorySolo") < 0) {
                  contentArray[i].style.display = "none";
                  if (categoryTitleArray[i]) {
                    categoryTitleArray[i].className = "";
                  }
                }
              }
              for (var i = 0; i < contentArray.length; ++i) {
                if (contentArray[i].id.indexOf("categorySolo") > -1) {
                  categoryArray[i].style.display = "none";
                }
              }
              catContent.style.display = "block";
              thisGroup.getElementsByTagName("a")[0].className = "on";
            }
            return false;
        } //switcherManual2
    }
}
//Event.observe( window, 'load', function() { AARP.expandCats.categories(); } );


if ( ( typeof swapFromCommunity ) == 'undefined' ) {
  function swapFromCommunity() {
  }
} ;


