Singel<
function User( id, data )
{
if( typeof data == 'object' )
this.init( id, data.u, data.s, data.a, data.n, data.c, data.r, data.t );
}
User.prototype.init = function( id, uid, sex, age, name, city, region, t )
{
this.id = id;
this.uid = uid;
this.sex = sex;
this.age = age;
this.name = name;
this.city = city;
this.region = region;
this.timestamp = t;
};
User.prototype.get_image_url = function()
{
var prefix = this.uid.substring( 0, 3 );
return 'http://g.helgon.net/u/%7B'+ prefix +'/%7B'+ this.uid +'%7D.jpg';
};
User.prototype.encode = function()
{
var n = { name:'n', sex:'s', age:'a', /*city:'c', region:'r',*/ uid:'u',
timestamp:'t' }, u = {}, property;
for( property in this )
if( n[property] )
u[n[property]] = this[property];
return u;
};
// run cb( args[0], ... args[N] ) with the this object set to a given user (id,
// url or User object), fetching it as needed from the server or our user cache
User.apply = function( user, cb, args )
{
var id;
if( typeof user == 'object' ) // we got a User object
return cb.apply( user, args );
if( typeof user == 'string' ) // we got a url (or id)
id = Users.id_from_url( user );
if( typeof user == 'number' ) // we got a user id
id = user;
if( user = Users.get( id ) ) // we had a cached copy
{
cb.apply( user, args );
if( (new Date).getTime() - user.timestamp < poll )
return; // ...and there was no need to refresh it
cb = 0; // refresh, but don't add the avatar again.
}
// okay, we need to pull the user data from the server
var url = host + purl + id;
// this generates a call User.parse( xhrdata, url, cb, args ) call:
get( url, make_caller( User.parse, [url, cb, args] ) );
};
// Parse profile data, update the user cache, and optionally call the provided
// callback with the this object set to the appropriate User, passing on args.
User.parse = function( data, url, cb, args )
{
var u = new User, html = typeof data=='string' ? data : data.responseText;
html = html.replace( /\s+/gm, ' ' );
u.id = Users.id_from_url( url );
if( !u.id ) return; // probably our own profile -- just ignore it, for now
u.uid = id_re.exec( html )[1];
if( data = headline_re.exec( html ) ) // name, sex, age, city, region
{
u.name = data[1];
u.sex = data[2];
u.age = parseInt( data[3], 10 );
u.city = data[4];
u.region = data[5];
}
u.timestamp = (new Date).getTime();
Users.save( u );
if( cb )
cb.apply( u, args||[] );
};
// avatar script
function inject_avatar_before( node ) // assumes a User this object
{
// exit early to cop out of showing the ugly (drawn) default avatars
if( this.uid.match( /00000000-0000-0000-0000-0000000000/ ) ) return;
node.parentNode.style.minHeight = '60px';
var img = document.createElement( 'img' );
with( img )
{
src = this.get_image_url();
className = 'largeimageborder';
style.width = '40px';
style.height = '56px';
align = 'middle';
}
var a = document.createElement( 'a' );
a.href = host + purl + this.id;
a.appendChild( img );
var space = document.createTextNode(' ');
node.parentNode.insertBefore( space, node );
node.parentNode.insertBefore( a, space );
}
function fetch_and_inject_avatar( node, n )
{
User.apply( node.href, inject_avatar_before, [node] );
}
switch( location.pathname.toLowerCase() )
{
case '/':
case '/start/start.asp':
case '/guestbook/guestbook.asp':
break;
case '/userinfo/userinfo.asp': // just update the cache for this user
User.parse( document.documentElement.innerHTML, location.href );
break;
default:
foreach( profile_links, fetch_and_inject_avatar );
}
|