//::: Prototype 00:00:00.0156220

var Prototype={
Version:'1.4.0',
ScriptFragment:'(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
emptyFunction:function(){},
K:function(x){return x}}
var Class={
create:function(){
return function(){
this.initialize.apply(this,arguments);}}}
var Abstract=new Object();
Object.extend=function(destination,source){
for(property in source){
destination[property]=source[property];}
return destination;}
Object.inspect=function(object){
try{
if(object==undefined)return 'undefined';
if(object==null)return 'null';
return object.inspect?object.inspect():object.toString();}catch(e){
if(e instanceof RangeError)return '...';
throw e;}}
Function.prototype.bind=function(){
var __method=this,args=$A(arguments),object=args.shift();
return function(){
return __method.apply(object,args.concat($A(arguments)));}}
Function.prototype.bindAsEventListener=function(object){
var __method=this;
return function(event){
return __method.call(object,event||window.event);}}
Object.extend(Number.prototype,{
toColorPart:function(){
var digits=this.toString(16);
if(this<16)return '0'+digits;
return digits;},
succ:function(){
return this +1;},
times:function(iterator){
$R(0,this,true).each(iterator);
return this;}});
var Try={
these:function(){
var returnValue;
for(var i=0;i<arguments.length;i++){
var lambda=arguments[i];
try{
returnValue=lambda();
break;}catch(e){}}
return returnValue;}}
var PeriodicalExecuter=Class.create();
PeriodicalExecuter.prototype={
initialize:function(callback,frequency){
this.callback=callback;
this.frequency=frequency;
this.currentlyExecuting=false;
this.registerCallback();},
registerCallback:function(){
setInterval(this.onTimerEvent.bind(this),this.frequency*1000);},
onTimerEvent:function(){
if(!this.currentlyExecuting){
try{
this.currentlyExecuting=true;
this.callback();}finally{
this.currentlyExecuting=false;}}}}
function $(){
var elements=new Array();
for(var i=0;i<arguments.length;i++){
var element=arguments[i];
if(typeof element=='string')
element=document.getElementById(element);
if(arguments.length==1)
return element;
elements.push(element);}
return elements;}
Object.extend(String.prototype,{
stripTags:function(){
return this.replace(/<\/?[^>]+>/gi,'');},
stripScripts:function(){
return this.replace(new RegExp(Prototype.ScriptFragment,'img'),'');},
extractScripts:function(){
var matchAll=new RegExp(Prototype.ScriptFragment,'img');
var matchOne=new RegExp(Prototype.ScriptFragment,'im');
return(this.match(matchAll)||[]).map(function(scriptTag){
return(scriptTag.match(matchOne)||['',''])[1];});},
evalScripts:function(){
return this.extractScripts().map(eval);},
escapeHTML:function(){
var div=document.createElement('div');
var text=document.createTextNode(this);
div.appendChild(text);
return div.innerHTML;},
unescapeHTML:function(){
var div=document.createElement('div');
div.innerHTML=this.stripTags();
return div.childNodes[0]?div.childNodes[0].nodeValue:'';},
toQueryParams:function(){
var pairs=this.match(/^\??(.*)$/)[1].split('&');
return pairs.inject({},function(params,pairString){
var pair=pairString.split('=');
params[pair[0]]=pair[1];
return params;});},
toArray:function(){
return this.split('');},
camelize:function(){
var oStringList=this.split('-');
if(oStringList.length==1)return oStringList[0];
var camelizedString=this.indexOf('-')==0?oStringList[0].charAt(0).toUpperCase()+oStringList[0].substring(1):oStringList[0];
for(var i=1,len=oStringList.length;i<len;i++){
var s=oStringList[i];
camelizedString+=s.charAt(0).toUpperCase()+s.substring(1);}
return camelizedString;},
inspect:function(){
return "'"+this.replace('\\','\\\\').replace("'",'\\\'') + "'";}});
String.prototype.parseQuery=String.prototype.toQueryParams;
var $break=new Object();
var $continue=new Object();
var Enumerable={
each:function(iterator){
var index=0;
try{
this._each(function(value){
try{
iterator(value,index++);}catch(e){
if(e!=$continue)throw e;}});}catch(e){
if(e!=$break)throw e;}},
all:function(iterator){
var result=true;
this.each(function(value,index){
result=result&&!!(iterator||Prototype.K)(value,index);
if(!result)throw $break;});
return result;},
any:function(iterator){
var result=true;
this.each(function(value,index){
if(result=!!(iterator||Prototype.K)(value,index))
throw $break;});
return result;},
collect:function(iterator){
var results=[];
this.each(function(value,index){
results.push(iterator(value,index));});
return results;},
detect:function(iterator){
var result;
this.each(function(value,index){
if(iterator(value,index)){
result=value;
throw $break;}});
return result;},
findAll:function(iterator){
var results=[];
this.each(function(value,index){
if(iterator(value,index))
results.push(value);});
return results;},
grep:function(pattern,iterator){
var results=[];
this.each(function(value,index){
var stringValue=value.toString();
if(stringValue.match(pattern))
results.push((iterator||Prototype.K)(value,index));})
return results;},
include:function(object){
var found=false;
this.each(function(value){
if(value==object){
found=true;
throw $break;}});
return found;},
inject:function(memo,iterator){
this.each(function(value,index){
memo=iterator(memo,value,index);});
return memo;},
invoke:function(method){
var args=$A(arguments).slice(1);
return this.collect(function(value){
return value[method].apply(value,args);});},
max:function(iterator){
var result;
this.each(function(value,index){
value=(iterator||Prototype.K)(value,index);
if(value>=(result||value))
result=value;});
return result;},
min:function(iterator){
var result;
this.each(function(value,index){
value=(iterator||Prototype.K)(value,index);
if(value<=(result||value))
result=value;});
return result;},
partition:function(iterator){
var trues=[],falses=[];
this.each(function(value,index){((iterator||Prototype.K)(value,index)?
trues:falses).push(value);});
return[trues,falses];},
pluck:function(property){
var results=[];
this.each(function(value,index){
results.push(value[property]);});
return results;},
reject:function(iterator){
var results=[];
this.each(function(value,index){
if(!iterator(value,index))
results.push(value);});
return results;},
sortBy:function(iterator){
return this.collect(function(value,index){
return{value:value,criteria:iterator(value,index)};}).sort(function(left,right){
var a=left.criteria,b=right.criteria;
return a<b?-1:a>b?1:0;}).pluck('value');},
toArray:function(){
return this.collect(Prototype.K);},
zip:function(){
var iterator=Prototype.K,args=$A(arguments);
if(typeof args.last()=='function')
iterator=args.pop();
var collections=[this].concat(args).map($A);
return this.map(function(value,index){
iterator(value=collections.pluck(index));
return value;});},
inspect:function(){
return '#<Enumerable:'+this.toArray().inspect()+'>';}}
Object.extend(Enumerable,{
map:Enumerable.collect,
find:Enumerable.detect,
select:Enumerable.findAll,
member:Enumerable.include,
entries:Enumerable.toArray});
var $A=Array.from=function(iterable){
if(!iterable)return[];
if(iterable.toArray){
return iterable.toArray();}else{
var results=[];
for(var i=0;i<iterable.length;i++)
results.push(iterable[i]);
return results;}}
Object.extend(Array.prototype,Enumerable);
Array.prototype._reverse=Array.prototype.reverse;
Object.extend(Array.prototype,{
_each:function(iterator){
for(var i=0;i<this.length;i++)
iterator(this[i]);},
clear:function(){
this.length=0;
return this;},
first:function(){
return this[0];},
last:function(){
return this[this.length-1];},
compact:function(){
return this.select(function(value){
return value!=undefined||value!=null;});},
flatten:function(){
return this.inject([],function(array,value){
return array.concat(value.constructor==Array?
value.flatten():[value]);});},
without:function(){
var values=$A(arguments);
return this.select(function(value){
return !values.include(value);});},
indexOf:function(object){
for(var i=0;i<this.length;i++)
if(this[i]==object)return i;
return -1;},
reverse:function(inline){
return(inline!==false?this:this.toArray())._reverse();},
shift:function(){
var result=this[0];
for(var i=0;i<this.length-1;i++)
this[i]=this[i+1];
this.length--;
return result;},
inspect:function(){
return '['+this.map(Object.inspect).join(', ')+']';}});
var Hash={
_each:function(iterator){
for(key in this){
var value=this[key];
if(typeof value=='function')continue;
var pair=[key,value];
pair.key=key;
pair.value=value;
iterator(pair);}},
keys:function(){
return this.pluck('key');},
values:function(){
return this.pluck('value');},
merge:function(hash){
return $H(hash).inject($H(this),function(mergedHash,pair){
mergedHash[pair.key]=pair.value;
return mergedHash;});},
toQueryString:function(){
return this.map(function(pair){
return pair.map(encodeURIComponent).join('=');}).join('&');},
inspect:function(){
return '#<Hash:{'+this.map(function(pair){
return pair.map(Object.inspect).join(': ');}).join(', ')+'}>';}}
function $H(object){
var hash=Object.extend({},object||{});
Object.extend(hash,Enumerable);
Object.extend(hash,Hash);
return hash;}
ObjectRange=Class.create();
Object.extend(ObjectRange.prototype,Enumerable);
Object.extend(ObjectRange.prototype,{
initialize:function(start,end,exclusive){
this.start=start;
this.end=end;
this.exclusive=exclusive;},
_each:function(iterator){
var value=this.start;
do{
iterator(value);
value=value.succ();}while(this.include(value));},
include:function(value){
if(value<this.start)
return false;
if(this.exclusive)
return value<this.end;
return value<=this.end;}});
var $R=function(start,end,exclusive){
return new ObjectRange(start,end,exclusive);}
var Ajax={
getTransport:function(){
return Try.these(
function(){return new ActiveXObject('Msxml2.XMLHTTP')},
function(){return new ActiveXObject('Microsoft.XMLHTTP')},
function(){return new XMLHttpRequest()})||false;},
activeRequestCount:0}
Ajax.Responders={
responders:[],
_each:function(iterator){
this.responders._each(iterator);},
register:function(responderToAdd){
if(!this.include(responderToAdd))
this.responders.push(responderToAdd);},
unregister:function(responderToRemove){
this.responders=this.responders.without(responderToRemove);},
dispatch:function(callback,request,transport,json){
this.each(function(responder){
if(responder[callback]&&typeof responder[callback]=='function'){
try{
responder[callback].apply(responder,[request,transport,json]);}catch(e){}}});}};
Object.extend(Ajax.Responders,Enumerable);
Ajax.Responders.register({
onCreate:function(){
Ajax.activeRequestCount++;},
onComplete:function(){
Ajax.activeRequestCount--;}});
Ajax.Base=function(){};
Ajax.Base.prototype={
setOptions:function(options){
this.options={
method:'post',
asynchronous:true,
parameters:''}
Object.extend(this.options,options||{});},
responseIsSuccess:function(){
return this.transport.status==undefined||this.transport.status==0||(this.transport.status>=200&&this.transport.status<300);},
responseIsFailure:function(){
return !this.responseIsSuccess();}}
Ajax.Request=Class.create();
Ajax.Request.Events=['Uninitialized','Loading','Loaded','Interactive','Complete'];
Ajax.Request.prototype=Object.extend(new Ajax.Base(),{
initialize:function(url,options){
this.transport=Ajax.getTransport();
this.setOptions(options);
this.request(url);},
request:function(url){
var parameters=this.options.parameters||'';
if(parameters.length>0)parameters+='&_=';
try{
this.url=url;
if(this.options.method=='get'&&parameters.length>0)
this.url+=(this.url.match(/\?/)?'&':'?')+parameters;
Ajax.Responders.dispatch('onCreate',this,this.transport);
this.transport.open(this.options.method,this.url,
this.options.asynchronous);
if(this.options.asynchronous){
this.transport.onreadystatechange=this.onStateChange.bind(this);
setTimeout((function(){this.respondToReadyState(1)}).bind(this),10);}
this.setRequestHeaders();
var body=this.options.postBody?this.options.postBody:parameters;
this.transport.send(this.options.method=='post'?body:null);}catch(e){
this.dispatchException(e);}},
setRequestHeaders:function(){
var requestHeaders=['X-Requested-With','XMLHttpRequest',
'X-Prototype-Version',Prototype.Version];
if(this.options.method=='post'){
requestHeaders.push('Content-type',
'application/x-www-form-urlencoded');
if(this.transport.overrideMimeType)
requestHeaders.push('Connection','close');}
if(this.options.requestHeaders)
requestHeaders.push.apply(requestHeaders,this.options.requestHeaders);
for(var i=0;i<requestHeaders.length;i+=2)
this.transport.setRequestHeader(requestHeaders[i],requestHeaders[i+1]);},
onStateChange:function(){
var readyState=this.transport.readyState;
if(readyState!=1)
this.respondToReadyState(this.transport.readyState);},
header:function(name){
try{
return this.transport.getResponseHeader(name);}catch(e){}},
evalJSON:function(){
try{
return eval(this.header('X-JSON'));}catch(e){}},
evalResponse:function(){
try{
return eval(this.transport.responseText);}catch(e){
this.dispatchException(e);}},
respondToReadyState:function(readyState){
var event=Ajax.Request.Events[readyState];
var transport=this.transport,json=this.evalJSON();
if(event=='Complete'){
try{(this.options['on'+this.transport.status]||this.options['on'+(this.responseIsSuccess()?'Success':'Failure')]||Prototype.emptyFunction)(transport,json);}catch(e){
this.dispatchException(e);}
if((this.header('Content-type')||'').match(/^text\/javascript/i))
this.evalResponse();}
try{(this.options['on'+event]||Prototype.emptyFunction)(transport,json);
Ajax.Responders.dispatch('on'+event,this,transport,json);}catch(e){
this.dispatchException(e);}
if(event=='Complete')
this.transport.onreadystatechange=Prototype.emptyFunction;},
dispatchException:function(exception){(this.options.onException||Prototype.emptyFunction)(this,exception);
Ajax.Responders.dispatch('onException',this,exception);}});
Ajax.Updater=Class.create();
Object.extend(Object.extend(Ajax.Updater.prototype,Ajax.Request.prototype),{
initialize:function(container,url,options){
this.containers={
success:container.success?$(container.success):$(container),
failure:container.failure?$(container.failure):(container.success?null:$(container))}
this.transport=Ajax.getTransport();
this.setOptions(options);
var onComplete=this.options.onComplete||Prototype.emptyFunction;
this.options.onComplete=(function(transport,object){
this.updateContent();
onComplete(transport,object);}).bind(this);
this.request(url);},
updateContent:function(){
var receiver=this.responseIsSuccess()?
this.containers.success:this.containers.failure;
var response=this.transport.responseText;
if(!this.options.evalScripts)
response=response.stripScripts();
if(receiver){
if(this.options.insertion){
new this.options.insertion(receiver,response);}else{
Element.update(receiver,response);}}
if(this.responseIsSuccess()){
if(this.onComplete)
setTimeout(this.onComplete.bind(this),10);}}});
Ajax.PeriodicalUpdater=Class.create();
Ajax.PeriodicalUpdater.prototype=Object.extend(new Ajax.Base(),{
initialize:function(container,url,options){
this.setOptions(options);
this.onComplete=this.options.onComplete;
this.frequency=(this.options.frequency||2);
this.decay=(this.options.decay||1);
this.updater={};
this.container=container;
this.url=url;
this.start();},
start:function(){
this.options.onComplete=this.updateComplete.bind(this);
this.onTimerEvent();},
stop:function(){
this.updater.onComplete=undefined;
clearTimeout(this.timer);(this.onComplete||Prototype.emptyFunction).apply(this,arguments);},
updateComplete:function(request){
if(this.options.decay){
this.decay=(request.responseText==this.lastText?
this.decay*this.options.decay:1);
this.lastText=request.responseText;}
this.timer=setTimeout(this.onTimerEvent.bind(this),
this.decay*this.frequency*1000);},
onTimerEvent:function(){
this.updater=new Ajax.Updater(this.container,this.url,this.options);}});
document.getElementsByClassName=function(className,parentElement){
var children=($(parentElement)||document.body).getElementsByTagName('*');
return $A(children).inject([],function(elements,child){
if(child.className.match(new RegExp("(^|\\s)"+className+"(\\s|$)")))
elements.push(child);
return elements;});}
if(!window.Element){
var Element=new Object();}
Object.extend(Element,{
visible:function(element){
return $(element).style.display!='none';},
toggle:function(){
for(var i=0;i<arguments.length;i++){
var element=$(arguments[i]);
Element[Element.visible(element)?'hide':'show'](element);}},
hide:function(){
for(var i=0;i<arguments.length;i++){
var element=$(arguments[i]);
element.style.display='none';}},
show:function(){
for(var i=0;i<arguments.length;i++){
var element=$(arguments[i]);
element.style.display='';}},
remove:function(element){
element=$(element);
element.parentNode.removeChild(element);},
update:function(element,html){
$(element).innerHTML=html.stripScripts();
setTimeout(function(){html.evalScripts()},10);},
getHeight:function(element){
element=$(element);
return element.offsetHeight;},
classNames:function(element){
return new Element.ClassNames(element);},
hasClassName:function(element,className){
if(!(element=$(element)))return;
return Element.classNames(element).include(className);},
addClassName:function(element,className){
if(!(element=$(element)))return;
return Element.classNames(element).add(className);},
removeClassName:function(element,className){
if(!(element=$(element)))return;
return Element.classNames(element).remove(className);},
cleanWhitespace:function(element){
element=$(element);
for(var i=0;i<element.childNodes.length;i++){
var node=element.childNodes[i];
if(node.nodeType==3&&!/\S/.test(node.nodeValue))
Element.remove(node);}},
empty:function(element){
return $(element).innerHTML.match(/^\s*$/);},
scrollTo:function(element){
element=$(element);
var x=element.x?element.x:element.offsetLeft,
y=element.y?element.y:element.offsetTop;
window.scrollTo(x,y);},
getStyle:function(element,style){
element=$(element);
var value=element.style[style.camelize()];
if(!value){
if(document.defaultView&&document.defaultView.getComputedStyle){
var css=document.defaultView.getComputedStyle(element,null);
value=css?css.getPropertyValue(style):null;}else if(element.currentStyle){
value=element.currentStyle[style.camelize()];}}
if(window.opera&&['left','top','right','bottom'].include(style))
if(Element.getStyle(element,'position')=='static')value='auto';
return value=='auto'?null:value;},
setStyle:function(element,style){
element=$(element);
for(name in style)
element.style[name.camelize()]=style[name];},
getDimensions:function(element){
element=$(element);
if(Element.getStyle(element,'display')!='none')
return{width:element.offsetWidth,height:element.offsetHeight};
var els=element.style;
var originalVisibility=els.visibility;
var originalPosition=els.position;
els.visibility='hidden';
els.position='absolute';
els.display='';
var originalWidth=element.clientWidth;
var originalHeight=element.clientHeight;
els.display='none';
els.position=originalPosition;
els.visibility=originalVisibility;
return{width:originalWidth,height:originalHeight};},
makePositioned:function(element){
element=$(element);
var pos=Element.getStyle(element,'position');
if(pos=='static'||!pos){
element._madePositioned=true;
element.style.position='relative';
if(window.opera){
element.style.top=0;
element.style.left=0;}}},
undoPositioned:function(element){
element=$(element);
if(element._madePositioned){
element._madePositioned=undefined;
element.style.position=
element.style.top=
element.style.left=
element.style.bottom=
element.style.right='';}},
makeClipping:function(element){
element=$(element);
if(element._overflow)return;
element._overflow=element.style.overflow;
if((Element.getStyle(element,'overflow')||'visible')!='hidden')
element.style.overflow='hidden';},
undoClipping:function(element){
element=$(element);
if(element._overflow)return;
element.style.overflow=element._overflow;
element._overflow=undefined;}});
var Toggle=new Object();
Toggle.display=Element.toggle;
Abstract.Insertion=function(adjacency){
this.adjacency=adjacency;}
Abstract.Insertion.prototype={
initialize:function(element,content){
this.element=$(element);
this.content=content.stripScripts();
if(this.adjacency&&this.element.insertAdjacentHTML){
try{
this.element.insertAdjacentHTML(this.adjacency,this.content);}catch(e){
if(this.element.tagName.toLowerCase()=='tbody'){
this.insertContent(this.contentFromAnonymousTable());}else{
throw e;}}}else{
this.range=this.element.ownerDocument.createRange();
if(this.initializeRange)this.initializeRange();
this.insertContent([this.range.createContextualFragment(this.content)]);}
setTimeout(function(){content.evalScripts()},10);},
contentFromAnonymousTable:function(){
var div=document.createElement('div');
div.innerHTML='<table><tbody>'+this.content+'</tbody></table>';
return $A(div.childNodes[0].childNodes[0].childNodes);}}
var Insertion=new Object();
Insertion.Before=Class.create();
Insertion.Before.prototype=Object.extend(new Abstract.Insertion('beforeBegin'),{
initializeRange:function(){
this.range.setStartBefore(this.element);},
insertContent:function(fragments){
fragments.each((function(fragment){
this.element.parentNode.insertBefore(fragment,this.element);}).bind(this));}});
Insertion.Top=Class.create();
Insertion.Top.prototype=Object.extend(new Abstract.Insertion('afterBegin'),{
initializeRange:function(){
this.range.selectNodeContents(this.element);
this.range.collapse(true);},
insertContent:function(fragments){
fragments.reverse(false).each((function(fragment){
this.element.insertBefore(fragment,this.element.firstChild);}).bind(this));}});
Insertion.Bottom=Class.create();
Insertion.Bottom.prototype=Object.extend(new Abstract.Insertion('beforeEnd'),{
initializeRange:function(){
this.range.selectNodeContents(this.element);
this.range.collapse(this.element);},
insertContent:function(fragments){
fragments.each((function(fragment){
this.element.appendChild(fragment);}).bind(this));}});
Insertion.After=Class.create();
Insertion.After.prototype=Object.extend(new Abstract.Insertion('afterEnd'),{
initializeRange:function(){
this.range.setStartAfter(this.element);},
insertContent:function(fragments){
fragments.each((function(fragment){
this.element.parentNode.insertBefore(fragment,
this.element.nextSibling);}).bind(this));}});
Element.ClassNames=Class.create();
Element.ClassNames.prototype={
initialize:function(element){
this.element=$(element);},
_each:function(iterator){
this.element.className.split(/\s+/).select(function(name){
return name.length>0;})._each(iterator);},
set:function(className){
this.element.className=className;},
add:function(classNameToAdd){
if(this.include(classNameToAdd))return;
this.set(this.toArray().concat(classNameToAdd).join(' '));},
remove:function(classNameToRemove){
if(!this.include(classNameToRemove))return;
this.set(this.select(function(className){
return className!=classNameToRemove;}).join(' '));},
toString:function(){
return this.toArray().join(' ');}}
Object.extend(Element.ClassNames.prototype,Enumerable);
var Field={
clear:function(){
for(var i=0;i<arguments.length;i++)
$(arguments[i]).value='';},
focus:function(element){
$(element).focus();},
present:function(){
for(var i=0;i<arguments.length;i++)
if($(arguments[i]).value=='')return false;
return true;},
select:function(element){
$(element).select();},
activate:function(element){
element=$(element);
element.focus();
if(element.select)
element.select();}}
var Form={
serialize:function(form){
var elements=Form.getElements($(form));
var queryComponents=new Array();
for(var i=0;i<elements.length;i++){
var queryComponent=Form.Element.serialize(elements[i]);
if(queryComponent)
queryComponents.push(queryComponent);}
return queryComponents.join('&');},
getElements:function(form){
form=$(form);
var elements=new Array();
for(tagName in Form.Element.Serializers){
var tagElements=form.getElementsByTagName(tagName);
for(var j=0;j<tagElements.length;j++)
elements.push(tagElements[j]);}
return elements;},
getInputs:function(form,typeName,name){
form=$(form);
var inputs=form.getElementsByTagName('input');
if(!typeName&&!name)
return inputs;
var matchingInputs=new Array();
for(var i=0;i<inputs.length;i++){
var input=inputs[i];
if((typeName&&input.type!=typeName)||(name&&input.name!=name))
continue;
matchingInputs.push(input);}
return matchingInputs;},
disable:function(form){
var elements=Form.getElements(form);
for(var i=0;i<elements.length;i++){
var element=elements[i];
element.blur();
element.disabled='true';}},
enable:function(form){
var elements=Form.getElements(form);
for(var i=0;i<elements.length;i++){
var element=elements[i];
element.disabled='';}},
findFirstElement:function(form){
return Form.getElements(form).find(function(element){
return element.type!='hidden'&&!element.disabled&&['input','select','textarea'].include(element.tagName.toLowerCase());});},
focusFirstElement:function(form){
Field.activate(Form.findFirstElement(form));},
reset:function(form){
$(form).reset();}}
Form.Element={
serialize:function(element){
element=$(element);
var method=element.tagName.toLowerCase();
var parameter=Form.Element.Serializers[method](element);
if(parameter){
var key=encodeURIComponent(parameter);
if(key.length==0)return;
if(parameter[1].constructor !=Array)
parameter[1]=[parameter[1]];
return parameter[1].map(function(value){
return key+'='+encodeURIComponent(value);}).join('&');}},
getValue:function(element){
element=$(element);
var method=element.tagName.toLowerCase();
var parameter=Form.Element.Serializers[method](element);
if(parameter)
return parameter[1];}}
Form.Element.Serializers={
input:function(element){
switch(element.type.toLowerCase()){
case 'submit':
case 'hidden':
case 'password':
case 'text':
return Form.Element.Serializers.textarea(element);
case 'checkbox':
case 'radio':
return Form.Element.Serializers.inputSelector(element);}
return false;},
inputSelector:function(element){
if(element.checked)
return[element.name,element.value];},
textarea:function(element){
return[element.name,element.value];},
select:function(element){
return Form.Element.Serializers[element.type=='select-one'?
'selectOne':'selectMany'](element);},
selectOne:function(element){
var value='',opt,index=element.selectedIndex;
if(index>=0){
opt=element.options[index];
value=opt.value;
if(!value&&!('value' in opt))
value=opt.text;}
return[element.name,value];},
selectMany:function(element){
var value=new Array();
for(var i=0;i<element.length;i++){
var opt=element.options[i];
if(opt.selected){
var optValue=opt.value;
if(!optValue&&!('value' in opt))
optValue=opt.text;
value.push(optValue);}}
return[element.name,value];}}
var $F=Form.Element.getValue;
Abstract.TimedObserver=function(){}
Abstract.TimedObserver.prototype={
initialize:function(element,frequency,callback){
this.frequency=frequency;
this.element=$(element);
this.callback=callback;
this.lastValue=this.getValue();
this.registerCallback();},
registerCallback:function(){
setInterval(this.onTimerEvent.bind(this),this.frequency*1000);},
onTimerEvent:function(){
var value=this.getValue();
if(this.lastValue!=value){
this.callback(this.element,value);
this.lastValue=value;}}}
Form.Element.Observer=Class.create();
Form.Element.Observer.prototype=Object.extend(new Abstract.TimedObserver(),{
getValue:function(){
return Form.Element.getValue(this.element);}});
Form.Observer=Class.create();
Form.Observer.prototype=Object.extend(new Abstract.TimedObserver(),{
getValue:function(){
return Form.serialize(this.element);}});
Abstract.EventObserver=function(){}
Abstract.EventObserver.prototype={
initialize:function(element,callback){
this.element=$(element);
this.callback=callback;
this.lastValue=this.getValue();
if(this.element.tagName.toLowerCase()=='form')
this.registerFormCallbacks();
else
this.registerCallback(this.element);},
onElementEvent:function(){
var value=this.getValue();
if(this.lastValue!=value){
this.callback(this.element,value);
this.lastValue=value;}},
registerFormCallbacks:function(){
var elements=Form.getElements(this.element);
for(var i=0;i<elements.length;i++)
this.registerCallback(elements[i]);},
registerCallback:function(element){
if(element.type){
switch(element.type.toLowerCase()){
case 'checkbox':
case 'radio':
Event.observe(element,'click',this.onElementEvent.bind(this));
break;
case 'password':
case 'text':
case 'textarea':
case 'select-one':
case 'select-multiple':
Event.observe(element,'change',this.onElementEvent.bind(this));
break;}}}}
Form.Element.EventObserver=Class.create();
Form.Element.EventObserver.prototype=Object.extend(new Abstract.EventObserver(),{
getValue:function(){
return Form.Element.getValue(this.element);}});
Form.EventObserver=Class.create();
Form.EventObserver.prototype=Object.extend(new Abstract.EventObserver(),{
getValue:function(){
return Form.serialize(this.element);}});
if(!window.Event){
var Event=new Object();}
Object.extend(Event,{
KEY_BACKSPACE:8,
KEY_TAB:9,
KEY_RETURN:13,
KEY_ESC:27,
KEY_LEFT:37,
KEY_UP:38,
KEY_RIGHT:39,
KEY_DOWN:40,
KEY_DELETE:46,
element:function(event){
return event.target||event.srcElement;},
isLeftClick:function(event){
return(((event.which)&&(event.which==1))||((event.button)&&(event.button==1)));},
pointerX:function(event){
return event.pageX||(event.clientX+(document.documentElement.scrollLeft||document.body.scrollLeft));},
pointerY:function(event){
return event.pageY||(event.clientY+(document.documentElement.scrollTop||document.body.scrollTop));},
stop:function(event){
if(event.preventDefault){
event.preventDefault();
event.stopPropagation();}else{
event.returnValue=false;
event.cancelBubble=true;}},
findElement:function(event,tagName){
var element=Event.element(event);
while(element.parentNode&&(!element.tagName||(element.tagName.toUpperCase()!=tagName.toUpperCase())))
element=element.parentNode;
return element;},
observers:false,
_observeAndCache:function(element,name,observer,useCapture){
if(!this.observers)this.observers=[];
if(element.addEventListener){
this.observers.push([element,name,observer,useCapture]);
element.addEventListener(name,observer,useCapture);}else if(element.attachEvent){
this.observers.push([element,name,observer,useCapture]);
element.attachEvent('on'+name,observer);}},
unloadCache:function(){
if(!Event.observers)return;
for(var i=0;i<Event.observers.length;i++){
Event.stopObserving.apply(this,Event.observers[i]);
Event.observers[i][0]=null;}
Event.observers=false;},
observe:function(element,name,observer,useCapture){
var element=$(element);
useCapture=useCapture||false;
if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.attachEvent))
name='keydown';
this._observeAndCache(element,name,observer,useCapture);},
stopObserving:function(element,name,observer,useCapture){
var element=$(element);
useCapture=useCapture||false;
if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.detachEvent))
name='keydown';
if(element.removeEventListener){
element.removeEventListener(name,observer,useCapture);}else if(element.detachEvent){
element.detachEvent('on'+name,observer);}}});
Event.observe(window,'unload',Event.unloadCache,false);
var Position={
includeScrollOffsets:false,
prepare:function(){
this.deltaX=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;
this.deltaY=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;},
realOffset:function(element){
var valueT=0,valueL=0;
do{
valueT+=element.scrollTop||0;
valueL+=element.scrollLeft||0;
element=element.parentNode;}while(element);
return[valueL,valueT];},
cumulativeOffset:function(element){
var valueT=0,valueL=0;
do{
valueT+=element.offsetTop||0;
valueL+=element.offsetLeft||0;
element=element.offsetParent;}while(element);
return[valueL,valueT];},
positionedOffset:function(element){
var valueT=0,valueL=0;
do{
valueT+=element.offsetTop||0;
valueL+=element.offsetLeft||0;
element=element.offsetParent;
if(element){
p=Element.getStyle(element,'position');
if(p=='relative'||p=='absolute')break;}}while(element);
return[valueL,valueT];},
offsetParent:function(element){
if(element.offsetParent)return element.offsetParent;
if(element==document.body)return element;
while((element=element.parentNode)&&element!=document.body)
if(Element.getStyle(element,'position')!='static')
return element;
return document.body;},
within:function(element,x,y){
if(this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element,x,y);
this.xcomp=x;
this.ycomp=y;
this.offset=this.cumulativeOffset(element);
return(y>=this.offset[1]&&
y<this.offset[1]+element.offsetHeight&&
x>=this.offset[0]&&
x<this.offset[0]+element.offsetWidth);},
withinIncludingScrolloffsets:function(element,x,y){
var offsetcache=this.realOffset(element);
this.xcomp=x+offsetcache[0]-this.deltaX;
this.ycomp=y+offsetcache[1]-this.deltaY;
this.offset=this.cumulativeOffset(element);
return(this.ycomp>=this.offset[1]&&
this.ycomp<this.offset[1]+element.offsetHeight&&
this.xcomp>=this.offset[0]&&
this.xcomp<this.offset[0]+element.offsetWidth);},
overlap:function(mode,element){
if(!mode)return 0;
if(mode=='vertical')
return((this.offset[1]+element.offsetHeight)-this.ycomp)/
element.offsetHeight;
if(mode=='horizontal')
return((this.offset[0]+element.offsetWidth)-this.xcomp)/
element.offsetWidth;},
clone:function(source,target){
source=$(source);
target=$(target);
target.style.position='absolute';
var offsets=this.cumulativeOffset(source);
target.style.top=offsets[1]+'px';
target.style.left=offsets[0]+'px';
target.style.width=source.offsetWidth+'px';
target.style.height=source.offsetHeight+'px';},
page:function(forElement){
var valueT=0,valueL=0;
var element=forElement;
do{
valueT+=element.offsetTop||0;
valueL+=element.offsetLeft||0;
if(element.offsetParent==document.body)
if(Element.getStyle(element,'position')=='absolute')break;}while(element=element.offsetParent);
element=forElement;
do{
valueT-=element.scrollTop||0;
valueL-=element.scrollLeft||0;}while(element=element.parentNode);
return[valueL,valueT];},
clone:function(source,target){
var options=Object.extend({
setLeft:true,
setTop:true,
setWidth:true,
setHeight:true,
offsetTop:0,
offsetLeft:0},arguments[2]||{})
source=$(source);
var p=Position.page(source);
target=$(target);
var delta=[0,0];
var parent=null;
if(Element.getStyle(target,'position')=='absolute'){
parent=Position.offsetParent(target);
delta=Position.page(parent);}
if(parent==document.body){
delta[0]-=document.body.offsetLeft;
delta[1]-=document.body.offsetTop;}
if(options.setLeft)target.style.left=(p[0]-delta[0]+options.offsetLeft)+'px';
if(options.setTop)target.style.top=(p[1]-delta[1]+options.offsetTop)+'px';
if(options.setWidth)target.style.width=source.offsetWidth+'px';
if(options.setHeight)target.style.height=source.offsetHeight+'px';},
absolutize:function(element){
element=$(element);
if(element.style.position=='absolute')return;
Position.prepare();
var offsets=Position.positionedOffset(element);
var top=offsets[1];
var left=offsets[0];
var width=element.clientWidth;
var height=element.clientHeight;
element._originalLeft=left-parseFloat(element.style.left||0);
element._originalTop=top-parseFloat(element.style.top||0);
element._originalWidth=element.style.width;
element._originalHeight=element.style.height;
element.style.position='absolute';
element.style.top=top+'px';;
element.style.left=left+'px';;
element.style.width=width+'px';;
element.style.height=height+'px';;},
relativize:function(element){
element=$(element);
if(element.style.position=='relative')return;
Position.prepare();
element.style.position='relative';
var top=parseFloat(element.style.top||0)-(element._originalTop||0);
var left=parseFloat(element.style.left||0)-(element._originalLeft||0);
element.style.top=top+'px';
element.style.left=left+'px';
element.style.height=element._originalHeight;
element.style.width=element._originalWidth;}}
if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)){
Position.cumulativeOffset=function(element){
var valueT=0,valueL=0;
do{
valueT+=element.offsetTop||0;
valueL+=element.offsetLeft||0;
if(element.offsetParent==document.body)
if(Element.getStyle(element,'position')=='absolute')break;
element=element.offsetParent;}while(element);
return[valueL,valueT];}}

//::: Common 00:00:00.0781100

function $I(id){Claim.isString(id,"$I.id");var element=$(id);Claim.isObject(element,"Required HTML element id: "+id);return element;}
function $F(id){Claim.isString(id,"$F.id")
Claim.isObject($(id),"Required form element id: "+id)
return Form.Element.getValue(id)}
function $T(tagName){var element=document.getElementsByTagName(tagName).item(0)
Claim.isObject(element,"Required HTML element tag: "+tagName)
return element}
function $SO(id){return $I(id).options[$I(id).selectedIndex]}
Number.prototype.toText=function(base,width){Claim.isNumber(base,"Number.toText.base")
Claim.isTrue(base>0,"Number.toText.base")
Claim.isNumber(width,"Number.toText.width")
Claim.isTrue(width>=0,"Number.toText.width")
var text=this.toString(base||10)+""
while(text.length<width)
text="0"+text
return text}
Number.prototype.toDec=function(width){Claim.isNumber(width,"Number.toText.width")
Claim.isTrue(width>=0,"Number.toText.width")
return this.toText(10,width)}
Number.prototype.toHex=function(width){Claim.isNumber(width,"width","Number.toText.width")
Claim.isTrue(width>=0,"width","Number.toText.width")
return this.toText(16,width)}
Date.prototype.toText=function(){var year=this.getUTCFullYear().toDec(4)
var month=this.getUTCMonth().toDec(2)
var day=this.getUTCDate().toDec(2)
var hours=this.getUTCHours().toDec(2)
var minutes=this.getUTCMinutes().toDec(2)
var seconds=this.getUTCSeconds().toDec(2)
var milliseconds=this.getUTCMilliseconds().toDec(3)
return year+"-"+month+"-"+day+" "+hours+":"+minutes+":"+seconds+"."+milliseconds}
var PreLoad={}
PreLoad.preLoad=function(){PreLoad.log=new Log4Js.Logger("PreLoad")}
PreLoad.onLoad=function(){PreLoad.log.debug("Done pre-load")}
PreLoad.actions=[]
PreLoad.actions.push(PreLoad.preLoad)
Event.observe(window,"load",PreLoad.onLoad)
var Url={}
Url.parse=function(url){Claim.isString(url,"Url.parse.url")
var parsed={}
parsed.full=url
parsed.base=url.replace(/\?.*$/,'')
parsed.protocol=url.replace(/:.*$/,'')
parsed.domain=parsed.base.replace(/^[^:]*:\/[\/]/,'').replace(/[:\/].*$/,'')
parsed.path=parsed.base.replace(/^[^\/]*\/\/[^\/]*[\/]/,'/')
parsed.query=url.replace(/^[^?]*\??/,'')
parsed.params=parsed.query.split("&").inject({},function(params,paramValue){pair=paramValue.split("=")
params[pair[0]]=unescape(pair[1])
return params})
return parsed}
Url.trimAnchor=function(url){var i=url.lastIndexOf("#");var isHasSharpMark=i>-1
var isHasQMark=url.lastIndexOf("?")>-1
if(isHasSharpMark&&((isHasQMark&&i>url.lastIndexOf("="))||!isHasQMark)){url=url.substr(0,i);}
return url;}
Url.appendParams=function(url,params){Claim.isString(url,"Url.appendParams.url")
if(!params||params=="")
return url
if(typeof(params)=="string")
return url+(url.match(/\?/)?"&":"?")+params
return $A($H(params).keys().sort()).inject(url,function(url,param){return Url.appendParamValue(url,param,params[param])})}
Url.appendParamValue=function(url,param,value){Claim.isString(url,"Url.appendParamValue.url")
Claim.isString(param,"Url.appendParamValue.param")
Claim.isScalar(value,"Url.appendParamValue.value")
return url+(url.match(/\?/)?"&":"?")+escape(param)+"="+escape(value)}
Url.relativeUrl=function(options){Claim.isObject(options,"Url.relativeUrl.options")
var protocol=options.protocol||Url.here.protocol
Claim.isString(protocol,"Url.relativeUrl.options.protocol")
var domain=options.domain||Url.here.domain
Claim.isString(domain,"Url.relativeUrl.options.domain")
var path=options.path||Url.here.path
Claim.isString(path,"Url.relativeUrl.options.path")
if(!path.match(/^[\/]/)){var base=Url.here.path
path="../"+path
while(path.match(/^\.\.[\/]/)){path=path.replace(/^\.\.[\/]/,"")
base=base.replace(/\/[^\/]+$/,"")}
path=base+"/"+path}
var params={}
var withHereParams=options.withHereParams||false
Claim.isBoolean(withHereParams,"Url.relativeUrl.options.withHereParams")
if(withHereParams)
Object.extend(params,Url.here.params)
var withClearanceParams=options.withClearanceParams
if(withClearanceParams==undefined)
withClearanceParams=domain!=Url.here.domain
Claim.isBoolean(withClearanceParams,"Url.relativeUrl.options.withClearanceParams")
if(withClearanceParams){Object.extend(params,Clearance.getAllLevelParams())}
var optionsParams=options.params||{}
Claim.isObject(optionsParams,"Url.relativeUrl.options.params")
Object.extend(params,options.params||{})
return Url.appendParams(protocol+":/"+"/"+domain+path,params)}
Url.here=undefined
Url.preLoad=function(){Url.here=Url.parse(location.href)}
PreLoad.actions.push(Url.preLoad)
var Claim={}
Claim.check=function(condition,claim,comment){if(!comment)
comment=claim
else
comment=claim+": "+comment
var log=Claim.log
Claim.log=undefined
try{if(condition){if(log)
log.debug(comment)}
else{if(log)
log.error(comment)
else
alert(comment)
throw new Error(comment)}}
finally{Claim.log=log}}
Claim.valueType=function(object){if(object==undefined)
return"undefined"
if(object==null)
return"null"
return typeof(object)+"("+object+")"}
Claim.isTrue=function(condition,comment){Claim.check(condition,"isTrue("+Claim.valueType(condition)+")",comment)}
Claim.isFalse=function(condition,comment){Claim.check(!condition,"isFalse("+Claim.valueType(condition)+")",comment)}
Claim.isNull=function(object,comment){Claim.check(typeof(object)==null,"isNull("+Claim.valueType(object)+")",comment)}
Claim.isNotNull=function(object,comment){Claim.check(typeof(object)!=null,"isNotNull("+Claim.valueType(object)+")",comment)}
Claim.isUndefined=function(object,comment){Claim.check(typeof(object)=='undefined',"isUndefined("+Claim.valueType(object)+")",comment)}
Claim.isNotUndefined=function(object,comment){Claim.check(typeof(object)!='undefined',"isNotUndefined("+Claim.valueType(object)+")",comment)}
Claim.isObject=function(object,comment){Claim.check(!!object,"isObject("+Claim.valueType(object)+")",comment)}
Claim.isNumber=function(object,comment){Claim.check(typeof(object)=="number","isNumber("+Claim.valueType(object)+")",comment)}
Claim.isBoolean=function(object,comment){Claim.check(typeof(object)=="boolean","isBoolean("+Claim.valueType(object)+")",comment)}
Claim.isString=function(object,comment){Claim.check(typeof(object)=="string","isString("+Claim.valueType(object)+")",comment)}
Claim.isScalar=function(object,comment){Claim.check(typeof(object)=="string"||typeof(object)=="number"||typeof(object)=="boolean","isScalar("+Claim.valueType(object)+")",comment)}
Claim.isArray=function(object,comment){Claim.check(object&&object.length!=undefined,"isArray("+Claim.valueType(object)+")",comment)}
Claim.areEqual=function(object1,object2,comment){Claim.check(object1==object2,"areEqual("+Claim.valueType(object1)+" ? "+Claim.valueType(object2)+")",comment)}
Claim.isFunction=function(object,comment){Claim.check(typeof(object)=='function',"isFunction("+Claim.valueType(object)+")",comment)}
Claim.preLoad=function(){Claim.log=new Log4Js.Logger("Claim")}
PreLoad.actions.push(Claim.preLoad)
var Cookies={}
Cookies.defaultOptions={}
Cookies.rawByName={}
Cookies.valueByName={}
Cookies.set=function(name,value,options){Claim.isString(name,"Cookies.set.name")
Claim.isObject(value,"Cookies.set.value")
var fullOptions=Cookies.fullOptions(name,options)
var raw=Cookies.toJson(value)
Cookies.valueByName[name]=value
Cookies.rawByName[name]=raw
var cookie=Cookies.fullCookie(name,raw,fullOptions)
Cookies.log.info("Set cookie: "+cookie)
document.cookie=cookie}
Cookies.get=function(name){Claim.isString(name,"Cookies.get.name")
return Cookies.valueByName[name]}
Cookies.clear=function(name,options){Claim.isString(name,"Cookies.clear.name")
var fullOptions=Cookies.fullOptions(name,options)
fullOptions.expires=Cookies.expiration(-1)
var cookie=Cookies.fullCookie(name,"",fullOptions)
delete(Cookies.rawByName[name])
delete(Cookies.valueByName[name])
Cookies.log.info("Clear cookie: "+cookie)
document.cookie=cookie}
Cookies.fullOptions=function(name,options){Claim.isString(name,"Cookies.fullOptions.name")
var fullOptions=Object.extend({},Cookies.defaultOptions)
fullOptions=Object.extend(fullOptions,options||{})
if(!fullOptions.path){var error="Set cookie name: "+name+" without a path"
Cookies.log.error(error)
throw error}
if(fullOptions.path.charAt(0)!="/"){var error="Set cookie name: "+name+" invalid path: "+fullOptions.path
Cookies.log.error(error)
throw error}
if(!fullOptions.domain){var error="Set cookie name: "+name+" without a domain"
Cookies.log.error(error)
throw error}
if(fullOptions.domain.charAt(0)!="."){var error="Set cookie name: "+name+" invalid domain: "+fullOptions.domain
Cookies.log.error(error)
throw error}
return fullOptions}
Cookies.expiration=function(millis){Claim.isNumber(millis,"Cookies.expiration.millis")
var today=new Date()
var now=Date.parse(today)
today.setTime(now+1*millis)
return today.toUTCString()}
Cookies.fullCookie=function(name,raw,options){Claim.isString(name,"Cookies.fullCookie.name")
var cookie=name+"="+raw
$H(options).each(function(pair){if(pair[1]!=undefined)
cookie+=";"+pair[0]+"="+pair[1]})
return cookie}
Cookies.toJson=function(object){if(object==undefined)
return"undefined"
if(object==null)
return"null"
if(typeof(object)=="string")
return"\""+Cookies.jsonEscape(object.toString())+"\""
if(typeof(object)=="number"||typeof(object)=="boolean")
return object.toString()
if(object.toJson)
return object.toJson()
var json=""
var seperator=""
if(typeof object=='object'&&object.constructor.toString().match(/array/i)!=null){$A(object).each(function(value){json+=seperator+Cookies.toJson(value)
seperator=","})
return"["+json+"]"}
else{var json=""
$H(object).each(function(pair){json+=seperator+Cookies.toJson(pair[0])+":"+Cookies.toJson(pair[1])
seperator=","})
return"{"+json+"}"}}
Cookies.jsonEscape=function(text){Claim.isString(text,"Claim.jsonEscape.text")
var escaped=""
for(var i=0;i<text.length;i++){var code=text.charCodeAt(i)
if(code<32||code==59){escaped+="\\u"+code.toHex(4)}
else{var nextChar=text.charAt(i)
if(nextChar=="\""||nextChar=="\\")
escaped+="\\"
escaped+=nextChar}}
return escaped}
Cookies.preLoad=function(){Cookies.log=new Log4Js.Logger("Cookies")
Cookies.defaultOptions.path="/"
Cookies.defaultOptions.domain="."+Url.here.domain.replace(/^[a-zA-Z0-9\-]+./,'')
document.cookie.split(';').each(function(cookie){if(!cookie){if(Cookies.rawByName!=undefined){Cookies.rawByName={};Cookies.valueByName={};}
throw $break}
var name=cookie.replace(/^\s*([^=]+)=.*$/,'$1')
var raw=cookie.replace(/^[^=]*=/,'')
Cookies.rawByName[name]=raw
Cookies.log.info("Load cookie name: "+name+" value: "+raw)
try{var value=undefined
eval("value="+raw)
Cookies.valueByName[name]=value}
catch(error){Cookies.log.error("Invalid cookie name: "+name+" value: "+value+" error: "+error)
Cookies.valueByName[name]=null}})}
Cookies.pop=function(){var each,s=[];for(each in this.rawByName){s[s.length]=each
s[s.length]=":"
s[s.length]=this.rawByName[each]
s[s.length]="\n"}
alert(unescape(s.join("")));}
PreLoad.actions.push(Cookies.preLoad)
var Log4Js={}
Log4Js.levelNames=["All","Debug","Info","Warn","Error","Fatal","None"]
Log4Js.ALL=0
Log4Js.DEBUG=1
Log4Js.INFO=2
Log4Js.WARN=3
Log4Js.ERROR=4
Log4Js.FATAL=5
Log4Js.NONE=6
Log4Js.configVersion=0
Log4Js.targetsByName={"*":[]}
Log4Js.setTargets=function(name,targets){Claim.isString(name,"Log4Js.setTargets.name")
Claim.isArray(targets,"Log4Js.setTargets.targets")
Log4Js.targetsByName[name]=targets
Log4Js.configVersion++}
Log4Js.removeTargets=function(name){Claim.isString(name,"Log4Js.removeTargets.name")
if(name=="*")
Log4Js.targetsByName[name]=[]
else
delete(Log4Js.targetsByName[name])
Log4Js.configVersion++}
Log4Js.getTargets=function(name){Claim.isString(name,"Log4Js.getTargets.name")
return Log4Js.targetsByName[name]}
Log4Js.findPrefix=function(name){Claim.isString(name,"Log4Js.findPrefix.name")
while(true){if(name=="")
name="*"
var targets=Log4Js.targetsByName[name]
if(targets)
return name
var lastDot=name.lastIndexOf(".")
name=lastDot>0?name.substring(0,lastDot):""}}
Log4Js.findTargets=function(name){Claim.isString(name,"Log4Js.findTargets.name")
return this.getTargets(this.findPrefix(name))}
Log4Js.toConfig=function(){var anchorsByName={}
var targetAnchorByJson={}
var targetByAnchor={}
var nextAnchor=1
$H(Log4Js.targetsByName).each(function(pair){var name=pair[0]
var targets=pair[1]
anchorsByName[name]=targets.inject([],function(anchors,target){var json=target.toJson()
var anchor=targetAnchorByJson[json]
if(!anchor){anchor=targetAnchorByJson[json]="t"+nextAnchor++
targetByAnchor[anchor]=target}
anchors.push(anchor)
return anchors})})
return{targetByAnchor:targetByAnchor,anchorsByName:anchorsByName}}
Log4Js.fromConfig=function(config){Claim.isObject(config,"Log4Js.fromConfig.config")
Claim.isObject(config.anchorsByName,"Log4Js.fromConfig.config.anchorsByName")
Claim.isObject(config.targetByAnchor,"Log4Js.fromConfig.config.targetByAnchor")
var targetsByName=$H(config.anchorsByName).inject({},function(targetsByName,pair){var name=pair[0]
var anchors=pair[1]
targetsByName[name]=$A(anchors).inject([],function(targets,anchor){targets.push(config.targetByAnchor[anchor])
return targets})
return targetsByName})
Log4Js.targetsByName=targetsByName
Log4Js.configVersion++}
Log4Js.pop=function(conf){if(!conf||typeof(conf)!='object'){conf={anchorsByName:{"*":["t1"],Claim:["t2"]},targetByAnchor:{t1:new Log4Js.PopupTarget(Log4Js.ALL,"log4js-%U-%T",true),t2:new Log4Js.PopupTarget(Log4Js.FATAL,"log4js-%U-%T",true)}};}
Cookies.set("log4js.config",conf,{});this.fromConfig(conf);}
Log4Js.add=function(sClassName,enLEVEL){Claim.isString(sClassName,"Log4Js.add(sClassName, enLEVEL) - sClassName must be a string");Claim.isString(enLEVEL,"Log4Js.add(sClassName, enLEVEL) - enLEVEL must Log Level ALL, DEBUG, WARN, ...");var iLevel=this[enLEVEL.toUpperCase()];Claim.isNumber(iLevel,"Log4Js.add(sClassName, enLEVEL) - Log4Js."+enLEVEL+" is not a valid warn-level");Claim.check(iLevel>=0&&iLevel<=6,"0 <= iLevel <= 6","Log4Js.add(sClassName, enLEVEL) - Log4Js[enLEVEL must be between 0 to 6");var conf=this.toConfig();conf.targetByAnchor.newAnchor=new Log4Js.PopupTarget(iLevel,"log4js-%U-%T",true)
conf.anchorsByName[sClassName]=["newAnchor"];this.pop(conf);}
Log4Js.clear=function(sClassName){Claim.isString(sClassName,"Log4Js.clear(sClassName) - sClassName must be a string");var conf=this.toConfig();delete conf.anchorsByName[sClassName];this.pop(conf);}
Log4Js.stop=function(){var conf={anchorsByName:{"*":["t1"]},targetByAnchor:{t1:new Log4Js.PopupTarget(Log4Js.NONE,"log4js-%U-%T",true)}};Cookies.set("log4js.config",conf,{});this.fromConfig(conf);}
Log4Js.preLoad=function(){var config=Cookies.get("log4js.config")
if(config)
Log4Js.fromConfig(config)
PreLoad.log.debug("Start pre-load")}
PreLoad.actions.push(Log4Js.preLoad)
Log4Js.Logger=Class.create()
Log4Js.Logger.prototype={}
Log4Js.Logger.prototype.initialize=function(name){Claim.isString(name,"Log4Js.Logger.name")
this.name=name
this.configVersion=-1}
Log4Js.Logger.prototype.debug=function(text){this.emit(Log4Js.DEBUG,text)}
Log4Js.Logger.prototype.info=function(text){this.emit(Log4Js.INFO,text)}
Log4Js.Logger.prototype.warn=function(text){this.emit(Log4Js.WARN,text)}
Log4Js.Logger.prototype.error=function(text){this.emit(Log4Js.ERROR,text)}
Log4Js.Logger.prototype.fatal=function(text){this.emit(Log4Js.FATAL,text)}
Log4Js.Logger.prototype.emit=function(level,text){if(this.configVersion<Log4Js.configVersion){this.targets=Log4Js.findTargets(this.name)
this.configVersion=Log4Js.configVersion}
if(this.targets.length>0){Claim.isNumber(level,"Log4Js.Logger.emit.level")
Claim.isTrue(Log4Js.DEBUG<=level&&level<=Log4Js.FATAL)
Claim.isScalar(text,"text")
var event={time:new Date().toText(),level:level,name:this.name,text:text,url:location.href}
this.targets.each(function(target){target.emit(event)})}}
Log4Js.AbstractTarget=function(){}
Log4Js.AbstractTarget.prototype={}
Log4Js.AbstractTarget.prototype.emit=function(event){Claim.isObject(event,"Log4Js.AbstractTarget.emit.event")
Claim.isNumber(event.level,"Log4Js.AbstractTarget.emit.event.level")
if(event.level>=this.level)
this._emit(event)}
Log4Js.AlertTarget=Class.create()
Log4Js.AlertTarget.prototype=new Log4Js.AbstractTarget()
Log4Js.AlertTarget.prototype.initialize=function(level){Claim.isNumber(level,"Log4Js.AlertTarget.level")
Claim.isTrue(Log4Js.ALL<=level&&level<=Log4Js.NONE,"Log4Js.AlertTarget.level")
this.level=level}
Log4Js.AlertTarget.prototype._emit=function(event){Claim.isObject(event,"Log4Js.AlertTarget._emit.event")
alert(event.time+" "+event.url+" "+Log4Js.levelNames[event.level]+" "+event.name+":\n"+event.text)}
Log4Js.AlertTarget.prototype.toJson=function(){return"new Log4Js.AlertTarget(Log4Js."+Log4Js.levelNames[this.level].toUpperCase()+")"}
Log4Js.TableTarget=Class.create()
Log4Js.TableTarget.prototype=new Log4Js.AbstractTarget()
Log4Js.TableTarget.prototype.backLog=[]
Log4Js.TableTarget.prototype.initialize=function(level,table,isLastOnTop){Claim.isNumber(level,"Log4Js.TableTarget.level")
Claim.isTrue(Log4Js.ALL<=level&&level<=Log4Js.NONE,"Log4Js.TableTarget.level")
Claim.isObject(table,"Log4Js.TableTarget.table")
Claim.isBoolean(isLastOnTop,"Log4Js.TableTarget.isLastOnTop")
this.level=level
this.isLastOnTop=isLastOnTop
if(typeof(table)=="string"){this.name=table
this.table=$(table)}
else{this.name=table.id
this.table=table}}
Log4Js.TableTarget.prototype.initTable=function(event){Claim.isObject(event,"Log4Js.TableTarget.initTable.event")
this.table=this.table||$(this.name)
if(!this.table)
return false
if(this.table.rows.length>0)
return true
var row=this.table.insertRow(-1)
row.insertCell(-1).innerHTML="Time"
row.insertCell(-1).innerHTML="Level"
row.insertCell(-1).innerHTML="Name"
row.insertCell(-1).innerHTML="Text"
row=this.table.insertRow(-1)
row.insertCell(-1).innerHTML=event.time
row.insertCell(-1).innerHTML="<hr />"
row.insertCell(-1).innerHTML="LOG4JS"
row.insertCell(-1).innerHTML=event.url
row=this.table.insertRow(-1)
row.insertCell(-1).innerHTML=event.time
row.insertCell(-1).innerHTML="<hr />"
row.insertCell(-1).innerHTML="LOG4JS"
row.insertCell(-1).innerHTML=event.url
row=this.table.insertRow(-1)
row.insertCell(-1).innerHTML="Time"
row.insertCell(-1).innerHTML="Level"
row.insertCell(-1).innerHTML="Name"
row.insertCell(-1).innerHTML="Text"
return true}
Log4Js.TableTarget.prototype._emit=function(event){Claim.isObject(event,"Log4Js.TableTarget._emit.event")
this.backLog.push(event)
if(!this.initTable(event))
return
while(this.backLog.length>0){var event=this.backLog.shift()
var row=this.table.insertRow(this.isLastOnTop?2:-1)
row.insertCell(-1).innerHTML=event.time
row.insertCell(-1).innerHTML=Log4Js.levelNames[event.level]
row.insertCell(-1).innerHTML=event.name
row.insertCell(-1).innerHTML=event.text}}
Log4Js.TableTarget.prototype.toJson=function(){return"new Log4Js.TableTarget(Log4Js."+Log4Js.levelNames[this.level].toUpperCase()+","+Cookies.toJson(this.name)+","+Cookies.toJson(this.isLastOnTop)+")"}
Log4Js.PopupTarget=Class.create()
Log4Js.PopupTarget.prototype=new Log4Js.AbstractTarget()
Log4Js.PopupTarget.windows={}
Log4Js.PopupTarget.prototype.initialize=function(level,name,isLastOnTop){Claim.isNumber(level,"Log4Js.Prototype.level")
Claim.isTrue(Log4Js.ALL<=level&&level<=Log4Js.NONE,"Log4Js.Prototype.level")
Claim.isString(name,"Log4Js.Prototype.name")
Claim.isBoolean(isLastOnTop,"Log4Js.Prototype.isLastOnTop")
this.name=name
name=name.replace(/%T/,new Date().toText())
name=name.replace(/%U/,location.href)
name=name.replace(/\W+/g,'_')
name=name.replace(/[_]+/g,'_')
this.windowName=name
this.level=level
this.isLastOnTop=isLastOnTop}
Log4Js.PopupTarget.prototype._emit=function(event){Claim.isObject(event,"Log4Js.Prototype._emit.event")
if(!this.window||this.window.closed){this.window=Log4Js.PopupTarget.windows[name]
if(!this.window||this.window.closed){this.window=Log4Js.PopupTarget.windows[name]=window.open("",this.windowName,'width=640,height=480,'+'scrollbars=1,status=0,toolbars=0,resizable=1')
if(!this.window||this.window.closed){alert("A popup window manager is blocking the logger "+"popup display.\n"+"You need to allow popups to see the logged events.")
this.emit=function(event){}
return}
this.window.document.writeln("<table id='log-table'></table>")
this.window.document.close()}
this.table=this.window.document.getElementById("log-table")
this.target=new Log4Js.TableTarget(this.level,this.table,this.isLastOnTop)}
this.target._emit(event)}
Log4Js.PopupTarget.prototype.toJson=function(){return"new Log4Js.PopupTarget(Log4Js."+Log4Js.levelNames[this.level].toUpperCase()+","+Cookies.toJson(this.name)+","+Cookies.toJson(this.isLastOnTop)+")"}
var Clearance={}
Clearance.MEMBER=0;Clearance.GUEST=1;Clearance.levelNames=["Anonymnous","Unclassified","Restricted","Confidential"]
Clearance.ANONYMOUS=0
Clearance.UNCLASSIFIED=1
Clearance.RESTRICTED=2
Clearance.CONFIDENTIAL=3
Clearance.level=undefined
Clearance.userId=undefined
Clearance.isLevel=function(level){return Clearance.level==level}
Clearance.hasLevel=function(level){Claim.isNumber(level,"Clearance.hasLevel.level")
Claim.isTrue(0<=level&&level<=Clearance.CONFIDENTIAL,"Clearance.hasLevel.level")
if(Clearance.hasLoginType()==true){return Clearance.level>=level}return false;}
Clearance.requireLevel=function(requiredLevel,loginUrl,urlParam){Claim.isNumber(requiredLevel,"Clearance.requireLevel.requiredLevel")
var minLevel=Clearance.ANONYMOUS
var maxLevel=Url.here.protocol=="https"?Clearance.CONFIDENTIAL:Clearance.UNCLASSIFIED
Claim.isTrue(minLevel<=requiredLevel&&requiredLevel<=maxLevel,"Clearance.requireLevel.requiredLevel")
Claim.isString(loginUrl,"Clearance.requireLevel.loginUrl")
Claim.isString(urlParam,"Clearance.requireLevel.urlParam")
Clearance.log.debug("Required: "+requiredLevel+" level: "+Clearance.level)
if(Clearance.level<requiredLevel){var url=Url.appendParamValue(loginUrl,urlParam,location.href)
Clearance.log.info("Redirect to "+url)
location=url}}
Clearance.isUnclassified=function(){return Clearance.isLevel(Clearance.UNCLASSIFIED)}
Clearance.hasUnclassified=function(){return Clearance.hasLevel(Clearance.UNCLASSIFIED)}
Clearance.isGuest=function(){var currentLoginType=Clearance.loginType();if(currentLoginType){if(currentLoginType==Clearance.GUEST)
return true;return false;}}
Clearance.isMember=function(){var currentLoginType=Clearance.loginType();if(currentLoginType){if(currentLoginType==Clearance.MEMBER)
return true;return false;}}
Clearance.hasLoginType=function(){if(Clearance.loginType())
return true;return false;}
Clearance.loginType=function(){var unclCookie=Cookies.get(Clearance.cookieName(Clearance.UNCLASSIFIED,true));if(unclCookie){var cookieParams=unclCookie.en.toQueryParams()
if(cookieParams["LT"])
return cookieParams["LT"];}
return null}
Clearance.refresh=function(){Cookies.preLoad();Clearance.preLoad();}
Clearance.load=function(sessionToken){var sessionQuerystring=sessionToken.replace(/^[^?]*\??/,'');if(sessionQuerystring.length==0)
sessionQuerystring=sessionToken;Url.here.params=sessionQuerystring.split("&").inject({},function(params,paramValue){pair=paramValue.split("=")
params[pair[0]]=unescape(pair[1])
return params})
Clearance.refresh();}
Clearance.requireUnclassified=function(loginUrl,param){Clearance.requireLevel(Clearance.UNCLASSIFIED,loginUrl,param)}
Clearance.isRestricted=function(){return Clearance.isLevel(Clearance.RESTRICTED)}
Clearance.hasRestricted=function(){return Clearance.hasLevel(Clearance.RESTRICTED)},Clearance.requireRestricted=function(loginUrl,param){Clearance.requireLevel(Clearance.RESTRICTED,loginUrl,param)}
Clearance.isConfidential=function(){return Clearance.isLevel(Clearance.CONFIDENTIAL)}
Clearance.hasConfidential=function(){return Clearance.hasLevel(Clearance.CONFIDENTIAL)}
Clearance.requireConfidential=function(loginUrl,param){Clearance.requireLevel(Clearance.CONFIDENTIAL,loginUrl,param)}
Clearance.getExpiration=function(expiration){if(typeof(expiration)!="number")
return
var dateExpiration=new Date(expiration)
var dateNow=new Date()
shouldbeexpired=Number(dateExpiration.getTime())-Number(dateNow.getTime());if(shouldbeexpired>0)
return shouldbeexpired
else
return}
Clearance.getParams=function(level){Claim.isNumber(level,"Clearance.getEncrypted.level")
Claim.isTrue(level>=Clearance.UNCLASSIFIED&&level<=Clearance.CONFIDENTIAL,"Clearance.getEncrypted.level")
if(!Clearance.hasLevel(level))
return null
var params={}
params.ux=Clearance.getExpiration(Clearance.params.ux)
if(params.ux){params.un=Clearance.params.un
params.ui=Clearance.params.ui}else{Clearance.level=0;return null}
if(level>=Clearance.RESTRICTED){params.rx=Clearance.getExpiration(Clearance.params.rx)
if(params.rx)
params.rn=Clearance.params.rn}
if(level>=Clearance.CONFIDENTIAL){params.cx=Clearance.getExpiration(Clearance.params.cx)
if(params.cx)
params.cn=Clearance.params.cn}
return params}
Clearance.getAllLevelParams=function(){var params={}
for(level=1;level<=3;level=level+1){Object.extend(params,Clearance.getParams(level))}
return params;}
Clearance.getMagic=function(level){params=Clearance.getParams(level)
if(params)
return Url.appendParams("",params)
return null}
Clearance.prefix=["Oberon1.A.","Oberon1.U.","Oberon1.R.","Oberon1.C."],Clearance.cookieName=function(level,isTimed){Claim.isNumber(level,"Clearance.cookieName.level")
Claim.isTrue(level>=Clearance.ANONYMOUS&&level<=Clearance.CONFIDENTIAL,"Clearance.cookieName.level")
Claim.isBoolean(isTimed,"Clearance.cookieName.isTimed")
if(level>Clearance.UNCLASSIFIED)
return Clearance.prefix[level]+(isTimed?"T":"S")
else
return Clearance.prefix[level]}
Clearance.setCookies=function(level,userId,encrypted,expires){Claim.isNumber(level,"Clearance.setCookies.level")
Claim.isTrue(level>=Clearance.ANONYMOUS&&level<=Clearance.CONFIDENTIAL,"Clearance.setCookies.level")
if(level!=Clearance.ANONYMOUS)
Claim.isString(userId,"Clearance.setCookies.userId")
Claim.isString(encrypted,"Clearance.setCookies.encrypted")
var value={ui:userId,en:encrypted}
if(expires){value.ex=expires
var date=new Date()
date.setSeconds(date.getSeconds()+Math.round(expires/1000))
Cookies.set(Clearance.cookieName(level,true),value,{expires:date.toUTCString()})
if(level>Clearance.UNCLASSIFIED){Cookies.set(Clearance.cookieName(level,false),value,{expires:undefined})}}
else{Claim.isTrue(level==Clearance.UNCLASSIFIED||level==Clearance.ANONYMOUS,"Clearance.setCookies.level")
Cookies.set(Clearance.cookieName(level,true),value,{expires:undefined})}}
Clearance.clearCookies=function(level){Claim.isNumber(level,"Clearance.clearCookies.level")
Claim.isTrue(level>=Clearance.UNCLASSIFIED&&level<=Clearance.CONFIDENTIAL,"Clearance.clearCookies.level")
Cookies.clear(Clearance.cookieName(level,false),{})
Cookies.clear(Clearance.cookieName(level,true),{})}
Clearance.forget=function(url){Clearance.log.debug("Forget user")
Clearance.clearCookies(Clearance.UNCLASSIFIED)
Clearance.clearCookies(Clearance.RESTRICTED)
Clearance.clearCookies(Clearance.CONFIDENTIAL)
var url=Url.appendParamValue(url,"ui","none")
Clearance.log.info("Redirect to "+url)
location=url}
Clearance.params={},Clearance.preLoad=function(){Clearance.urlParamsToCookies()
Clearance.level=Clearance.ANONYMOUS
Clearance.log.debug("Achieved Anonymnous")
if(Clearance.processCookies(Clearance.UNCLASSIFIED,"un","ux"))
if(Clearance.processCookies(Clearance.RESTRICTED,"rn","rx"))
Clearance.processCookies(Clearance.CONFIDENTIAL,"cn","cx")}
Clearance.urlParamsToCookies=function(){Clearance.log=new Log4Js.Logger("Clearance")
Clearance.level=Clearance.ANONYMOUS
Clearance.log.debug("Try to access current URL clearance parameters")
if(Url.here.params.an){Clearance.setCookies(Clearance.ANONYMOUS,Url.here.params.ui,Url.here.params.an);}
if(Url.here.params.ui){if(Url.here.params.un&&Url.here.params.ux)
Clearance.setCookies(Clearance.UNCLASSIFIED,Url.here.params.ui,Url.here.params.un,((typeof(Url.here.params.ux)=="number")?(Url.here.params.ux*1000.0):Url.here.params.ux))
else if(Url.here.params.un)
Clearance.setCookies(Clearance.UNCLASSIFIED,Url.here.params.ui,Url.here.params.un,null)
else
Clearance.clearCookies(Clearance.UNCLASSIFIED)}
Clearance.log.debug("Strip clearance params from URL")
delete(Url.here.params["ui"])
delete(Url.here.params["un"])
delete(Url.here.params["ux"])
delete(Url.here.params["rn"])
delete(Url.here.params["rx"])
delete(Url.here.params["cn"])
delete(Url.here.params["cx"])
delete(Url.here.params["an"])}
Clearance.processCookies=function(level,en,ex){Claim.isNumber(level,"Clearance.processCookies.level")
Claim.isTrue(level>Clearance.level&&level<=Clearance.CONFIDENTIAL,"Clearance.processCookies.level")
Clearance.log.debug("Process "+Clearance.prefix[level]+" cookies")
var sessionName=Clearance.cookieName(level,false)
var timedName=Clearance.cookieName(level,true)
var session=Cookies.get(sessionName)
var timed=Cookies.get(timedName)
if(!session){Clearance.log.debug("No "+sessionName+" cookie => "+Clearance.levelNames[Clearance.level])
return false}
if(!timed){Clearance.log.debug("No "+timedName+" cookie => "+Clearance.levelNames[Clearance.level])
return false}
if(!session.ui){Clearance.log.debug("No "+sessionName+".ui => "+Clearance.levelNames[Clearance.level])
return false}
if(!timed.ui){Clearance.log.debug("No "+timedName+".ui => "+Clearance.levelNames[Clearance.level])
return false}
if(session.ui!=timed.ui){Clearance.log.debug("Mismatch {"+sessionName+","+timedName+"}.ui => "+Clearance.levelNames[Clearance.level])
return false}
if(!session.en){Clearance.log.debug("No "+sessionName+".en => "+Clearance.levelNames[Clearance.level])
return false}
if(!timed.en){Clearance.log.debug("No "+timedName+".en => "+Clearance.levelNames[Clearance.level])
return false}
if(session.en!=timed.en){Clearance.log.debug("Mismatch {"+sessionName+","+timedName+"}.en => "+Clearance.levelNames[Clearance.level])
return false}
if(level>Clearance.UNCLASSIFIED){if(session.ui!=Clearance.userId){Clearance.log.debug("Mismatch "+sessionName+".ui => "+Clearance.levelNames[Clearance.level])
return false}}
else{Clearance.params.ui=session.ui
Clearance.userId=session.ui}
Clearance.params[en]=session.en
var dateExpired=new Date()
var millExp=timed.ex?timed.ex:1
Clearance.params[ex]=Number(dateExpired.getTime())+Number(millExp)
Clearance.level=level
Clearance.log.debug("Achieved "+Clearance.levelNames[Clearance.level])
return true}
PreLoad.actions.push(Clearance.preLoad)
var Jast={}
Jast.timeout=20000
Jast.pendingRequestByUrl={}
Jast.pendingRequestById={}
Jast.isPreLoad=true
Jast.nextRequestId=0
Jast.activeRequestCount=0
Jast.response=function(id,isOk,result,caching){Claim.isNumber(id,"Jast.response.id")
Claim.isBoolean(isOk,"Jast.response.isOk")
request=Jast.pendingRequestById[id]
if(!request){Jast.Request.log.warn("Unknown load request id: "+id+" isOk: "+isOk)
return}
request.loaded(isOk,result,caching)}
Jast.clearCache=function(){$H(Cookies.valueByName).keys.each(function(name){if(name.substr(0,5)=="Jast.")
Cookies.clear(name)})}
Jast.Request=Class.create()
Jast.Request.prototype={}
Jast.Request.stateNames=["Uninitialized","Loading","Loaded","Interactive","Complete"]
Jast.Request.UNINITIALIZED=0
Jast.Request.LOADING=1
Jast.Request.LOADED=2
Jast.Request.INTERACTIVE=3
Jast.Request.COMPLETE=4
Jast.Request.statusNames=["Create","Success","Failure","Timeout"]
Jast.Request.CREATE=0
Jast.Request.SUCCESS=1
Jast.Request.FAILURE=2
Jast.Request.TIMEOUT=3
Jast.Request.preLoad=function(){Jast.Request.log=new Log4Js.Logger("Jast.Request")}
PreLoad.actions.push(Jast.Request.preLoad)
Jast.Request.onLoad=function(){Jast.isPreLoad=false
var length=Jast.nextRequestId
Jast.Request.log.debug("Complete "+length+" pre-load request(s)")
length.times(function(id){request=Jast.pendingRequestById[id]
if(request&&!request.uses)
if(request.result)
request.complete()
else{if(request.options.timeout>0){request.setTimeout=setTimeout(request.timedOut.bind(request),request.options.timeout)
Jast.Request.log.debug("Reset timeout for Preloaded Request. Request id: "+request.id+" setTimeout: "+request.setTimeout)}}})}
Event.observe(window,"load",Jast.Request.onLoad)
Jast.Request.prototype.initialize=function(url,options){Claim.isString(url,"Jast.Request.url")
this.url=url
this.options={timeout:Jast.timeout,toReuse:true,unimportant:[]}
Object.extend(this.options,options||{})
var parsed=Url.parse(url)
$A(this.options.unimportant).each(function(param){delete(parsed.params[param])})
$A(["un","ux","rn","rx","cn","cx"]).each(function(param){delete(parsed.params[param])})
this.cacheId=Url.appendParams(parsed.base,parsed.params)
this.cacheId="Just."+this.cacheId.replace(/[=;]/g,'_')
this.usedBy=[]
this.id=Jast.nextRequestId++
this.state=-1
this.status=Jast.Request.CREATE
Jast.Request.log.debug("Create request id: "+this.id+" url: "+this.url+" unimportant: "+Cookies.toJson(this.options.unimportant)+" cacheId: "+this.cacheId+" toReuse: "+this.options.toReuse+" timeout: "+this.options.timeout)
this.advanceTo(Jast.Request.UNINITIALIZED)
this.dispatch("onCreate")
var name
var cached=Cookies.get(name=this.cacheId+".T")||Cookies.get(name=this.cacheId+".S")
if(cached){Jast.Request.log.debug("Fetch request id: "+this.id+" from cookie name: "+name)
if(Jast.isPreLoad){Jast.pendingRequestByUrl[this.cacheId]=this
Jast.pendingRequestById[this.id]=this}
this.loaded(cached.isOk,cached.result,undefined)
return}
var request=Jast.pendingRequestByUrl[this.cacheId]
if(request&&this.options.toReuse&&request.options.toReuse&&request.state<=Jast.Request.LOADED){Jast.Request.log.debug("Merge request id: "+this.id+" with request id: "+request.id+" state: "+Jast.Request.stateNames[request.state]+" status: "+Jast.Request.statusNames[request.status])
this.uses=request
this.advanceTo(request.state)
this.result=request.result
this.status=request.status
request.usedBy.push(this)}
else{this.makeRequest()}}
Jast.Request.prototype.makeRequest=function(){this.fullUrl=Url.appendParamValue(this.url,"jastId",this.id)
Jast.Request.log.info("Make request id: "+this.id+" fullUrl: "+this.fullUrl)
this.scriptId="jast-script-"+this.id
Jast.pendingRequestByUrl[this.cacheId]=this
Jast.pendingRequestById[this.id]=this
var isHeadNotExists=(0==document.getElementsByTagName("HEAD").length);if(Jast.isPreLoad&&isHeadNotExists){Jast.Request.log.debug("Write script id: "+this.scriptId+" for request id: "+this.id)
document.write("<"+"script")
document.write(' id="'+this.scriptId+'"')
document.write(' type="text/javascript"')
document.write(' src="'+this.fullUrl+'"')
document.write("></"+"script"+">")}
else{Jast.Request.log.debug("Create script id: "+this.scriptId+" for request id: "+this.id)
script=document.createElement("script")
script.setAttribute("id",this.scriptId)
script.setAttribute("type","text/javascript")
script.setAttribute("src",this.fullUrl)
$T("head").appendChild(script)
if(this.options.timeout>0){this.setTimeout=setTimeout(this.timedOut.bind(this),this.options.timeout)
Jast.Request.log.debug("Request id: "+this.id+" setTimeout: "+this.setTimeout)}}
this.advanceTo(Jast.Request.LOADING)}
Jast.Request.prototype.loaded=function(isOk,result,caching){Claim.isBoolean(isOk,"Jast.Request.loaded.isOk")
if(this.state>=Jast.Request.LOADED){Jast.Request.log.warn("Reloaded request id: "+this.id+" isOk: "+isOk)
return}
Jast.Request.log.info("Loaded request id: "+this.id+" isOk: "+isOk)
if(this.setTimeout){clearTimeout(this.setTimeout)
Jast.Request.log.debug("Request id: "+this.id+" clearTimeout: "+this.setTimeout)
delete(this["setTimeout"])}
if(caching&&caching.expires||session){var value={isOk:isOk,result:result}
var session=caching.session
delete(caching["session"])
if(caching.expires){Jast.Request.log.debug("Cache in: "+this.cacheId+".T for "+caching.expires+"ms")
Cookies.set(this.cacheId+".T",value,caching)}
delete(caching["expires"])
if(session){Jast.Request.log.debug("Cache in: "+this.cacheId+".S for rest of session")
Cookies.set(this.cacheId+".S",value,caching)}}
this.advanceTo(Jast.Request.LOADED)
this.result=result
this.status=isOk?Jast.Request.SUCCESS:Jast.Request.FAILURE
var status=this.status
this.usedBy.each(function(request){request.result=result
request.status=status})
if(!Jast.isPreLoad)
this.complete()}
Jast.Request.prototype.timedOut=function(){if(this.state>=Jast.Request.LOADED){Jast.Request.log.warn("Retimedout request id: "+this.id)
return}
Jast.Request.log.info("Timedout request id: "+this.id)
this.advanceTo(Jast.Request.LOADED)
this.status=Jast.Request.TIMEOUT
this.usedBy.each(function(request){request.status=Jast.Request.TIMEOUT})
this.complete()}
Jast.Request.prototype.complete=function(){Jast.Request.log.debug("Complete request id: "+this.id)
this.advanceTo(Jast.Request.INTERACTIVE)
this.dispatchUsed("on"+Jast.Request.statusNames[this.status])
this.advanceTo(Jast.Request.COMPLETE)
delete(Jast.pendingRequestByUrl[this.cacheId])
delete(Jast.pendingRequestById[this.id])
this.usedBy.each(function(request){delete(Jast.pendingRequestById[request.id])})
if(this.scriptId){Jast.Request.log.debug("Remove script id: "+this.scriptId+" for request id: "+this.id)
var script=$I(this.scriptId)
script.parentNode.removeChild(script)}}
Jast.Request.prototype.advanceTo=function(state){Claim.isNumber(state,"Jast.Remove.advanceTo.state")
Claim.isTrue(0<=state&&state<=Jast.Request.COMPLETE,"Jast.Remove.advanceTo.state")
while(this.state<state){var nextState=this.state++
this.dispatch("on"+Jast.Request.stateNames[this.state])
this.usedBy.each(function(request){request.advanceTo(nextState)})}}
Jast.Request.prototype.dispatch=function(event){Claim.isString(event,"Jast.Request.dispatch.event")
Jast.Request.log.debug("Dispatch event: "+event+" for request id: "+this.id)
if(this.options[event]){try{this.options[event](this)}
catch(e){Jast.Request.log.warn("Exception in "+event+" for request id: "+request.id+" exception: "+e.message);}}
Jast.Responders.dispatch(event,this)}
Jast.Request.prototype.dispatchUsed=function(event){Claim.isString(event,"Jast.Responders.dispatchUsed.event")
Jast.Request.log.debug("DispatchUsed event: "+event+" for request id: "+this.id)
this.dispatch(event)
this.usedBy.each(function(request){request.dispatchUsed(event)})}
Jast.Responders={}
Jast.Responders.responders=[]
Jast.Responders._each=function(iterator){Claim.isObject(iterator,"Jast.Responders._each.iterator")
this.responders._each(iterator)}
Jast.Responders.register=function(responderToAdd){Claim.isObject(responderToAdd,"Jast.Request.register.responderToAdd")
if(!this.include(responderToAdd))
this.responders.push(responderToAdd)}
Jast.Responders.unregister=function(responderToRemove){Claim.isObject(responderToRemove,"Jast.Responders.unregister.responderToRemove")
this.responders=this.responders.without(responderToRemove)}
Jast.Responders.dispatch=function(event,request){Claim.isString(event,"Jast.Responders.dispatch.event")
Claim.isObject(request,"Jast.Responders.dispatch.request")
Claim.isNumber(request.id,"Jast.Responders.dispatch.request.id")
this.log.debug("Dispatch event "+event+" for request id: "+request.id)
this.each(function(responder){if(responder[event]){try{responder[event](request)}
catch(e){this.log.warn(" Exception in "+event+" for request id: "+request.id+" exception: "+e.message);}}})}
Jast.Responders.preLoad=function(){Jast.Responders.log=new Log4Js.Logger("Jast.Responders")}
Object.extend(Jast.Responders,Enumerable)
PreLoad.actions.push(Jast.Responders.preLoad)
Jast.Responders.register({onCreate:function(){Jast.activeRequestCount++
Jast.Responders.log.debug("Active requests up to "+Jast.activeRequestCount)
Claim.isTrue(Jast.activeRequestCount>=1,"Jast.Responders.activeRequestCount")},onComplete:function(){Jast.activeRequestCount--
Jast.Responders.log.debug("Active requests down to "+Jast.activeRequestCount)
Claim.isTrue(Jast.activeRequestCount>=0,"Jast.Responders.activeRequestCount")}})
$A(PreLoad.actions).each(function(action){action()})//::: UserAccount 00:00:00.0937320

Object.extend(Class,{isInheritable:function(parentClassName){if(!parentClassName)return false;var parentClass;switch(typeof(parentClassName)){case"function":parentClass=parentClassName;parentClassName=parentClass.toString();return(!parantClassName.match(/function\(/gi)&&window[parentClassName]!=null&&window[parentClassName]==eval(parentClassName));case"string":try{parentClass=eval(parentClassName);}catch(ex){return false;}
return(parentClass!=null&&typeof(parentClass)=='function');default:return false;}},createSubclass:function(parentClassName){var parentClass;if(!Class.isInheritable(parentClassName))
throw"Illegal parameter for Class.createSubclass:"+parentClassName+". Class.create accepts a valid class-name as string, or a reference to the class if the class has a static override for the toString(), providing its class name as string.";if(typeof(parentClassName)=='string'){parentClass=eval(parentClassName);}else{parentClass=parentClass;parentClassName=parentClass.toString();}
Claim.isString(parentClassName,"Class.createSubclass(parentClassName)");Claim.check(typeof(parentClass)=='function'&&typeof(parentClass.prototype.initialize)=='function',"typeof(eval(parentClassName).prototype.initialize) == 'function'","Class.createSubclass(parentClassName): parentClassName is not inheritable using the createSubclass mechanizm.");var f=new Function(parentClassName+".prototype.initialize.apply(this, arguments);\n"
+"this.initialize.apply(this, arguments)");return f;}});Object.extend(Claim,{isFunction:function(object,comment)
{{Claim.check(typeof(object)=='function',"isFunction("+Claim.valueType(object)+")",comment)}}});Object.extend(Element,{log:new Log4Js.Logger("Element"),setText:function(e,sText){var tag=e.tagName.toUpperCase();switch(tag){case"INPUT":case"TEXTAREA":e.value=sText;break;case"SELECT":e.value=sText;break;default:try{e.innerHTML=sText;}catch(ex){try{if(typeof e.innerText=='undefined')
e.textContent=sText;else
e.innerText=sText;}catch(ex){this.log.error("Element.setText: failed to set to element the text: "+sText);}}}}});Serialize=function(obj){if(!obj)return'null';var str='';var psik='';for(each in obj){str+=psik;psik=",";str+=each+":"
switch(typeof(obj[each])){case'function':break;case'object':str+=Serialize(obj[each]);break;case'string':str+='"'+obj[each].replace(/\"/,"\"")+'"';break;default:str+=obj[each];}}
return"{"+str+"}";}
Function.prototype.insert=function(sCodeLine){var a=this.toString().split("{");a[1]="\n\t"+sCodeLine+a[1];return(eval("a = "+a.join("{")));}
Glossary={_terms:{},addPair:function addPair(key,value){this._terms[key]=value;},term:function term(key){return this._terms[key];}};Glossary.addPair('{JAST_REQUEST_TIMEOUT_DEF_MSG}','Problems connecting to the server.');Glossary.addPair('{JAST_REQUEST_REFUSED_DEF_MSG}','Server failes the request');function ask(){var s='';while(s!="STOP"){s=prompt('To close - enter "STOP"',s);if(s=="STOP")return;alert(eval(s));}}
function CreateHiddenInput(sName,sValue)
{var input=document.createElement("input");input.setAttribute("type","hidden");input.setAttribute("name",sName);input.setAttribute("value",sValue);return input;}
function PostIframeRequest(form,callback){var parts=window.location.hostname.split(".");document.domain=parts[parts.length-2]+"."+parts[parts.length-1];var remotingDiv=document.createElement("div");document.body.appendChild(remotingDiv);remotingDiv.id="remotingDiv";remotingDiv.innerHTML="<iframe name='remotingFrame' id='remotingFrame' style='border:0;width:0;height:0;'></iframe>";remotingDiv.iframe=document.getElementById('remotingFrame');remotingDiv.form=form;remotingDiv.form.setAttribute('target','remotingFrame');remotingDiv.form.target='remotingFrame';remotingDiv.appendChild(remotingDiv.form);remotingDiv.callback=callback;remotingDiv.form.submit();}
function InvokeCallback(returnStatus){try
{document.getElementById('remotingDiv').callback(returnStatus);}
catch(ex){}}
if(!window.UA)UA={};UA.UserUtils=Class.create();UA.UserUtils.prototype.Callback;UA.UserUtils.DoLogIn=function(tickInterval,numOfTicks,callback,paramsList){UA.UserUtils.prototype.Callback=callback;UserLogIn();UA.UserUtils.runPolling(tickInterval,numOfTicks,paramsList);}
UA.UserUtils.DoLogOut=function(callback){UserLogOut();}
UA.UserUtils.DoRegister=function(callback){UserRegister();}
UA.UserUtils.DoEndGameFlow=function(launcherObjects){EndGameFlow(launcherObjects);}
UA.UserUtils.runPolling=function(tickInterval,numOfTicks,paramsList){var funcStringBuilder="UA.UserUtils.polling("+tickInterval+","+numOfTicks;if(paramsList!=null&&paramsList!=undefined)
funcStringBuilder+=(",'"+paramsList+"')");else
funcStringBuilder+=")";setTimeout(funcStringBuilder,tickInterval);}
UA.UserUtils.polling=function(tickInterval,numOfTicks,paramsList){if(numOfTicks==0)
{UA.UserUtils.prototype.Callback("User is still Logged off.");return;}
if(!UA.User.prototype.IsLoggedOn())
{numOfTicks=numOfTicks-1;UA.UserUtils.runPolling(tickInterval,numOfTicks,paramsList);return;}
UA.UserUtils.InitializeUA(UA.UserUtils.prototype.Callback,paramsList);}
UA.UserUtils.InitializeUA=function(callback,paramsList){var methodsArr=new Array(UA.User.Methods.ISSUBSCRIBED,UA.User.Methods.GETUSER,UA.User.Methods.HASFREETRIAL,UA.User.Methods.GET_OBERON_CLIENT_USERID,UA.User.Methods.GET_PARTNER_PROGRAM_ID);if(paramsList==undefined)
paramsList=null;else
methodsArr.push(UA.User.Methods.ISAUTHORIZED);UA.UserUtils.prototype.Callback=callback;UA.User.prototype.GetData(methodsArr,paramsList,InitializeUASuccess,InitializeUAFail,InitializeUATimeout);}
function InitializeUASuccess(request){var user={};user.IsSuccessful=true;user.IsCompleted=true;if(request.IsAuthorized!=undefined){if(request.IsAuthorized.Status!="ACCOUNT_ERROR")
user.IsAuthorized=request.IsAuthorized.Data.isAuthorized;else
user.IsCompleted=false;}
if(request.IsSubscribed.Status!="ACCOUNT_ERROR")
user.IsSubscribed=(request.IsSubscribed.Data.isSubscribed=="True")?true:false;else
user.IsCompleted=false;if(request.HasFreeTrial.Status!="ACCOUNT_ERROR")
user.HasFreeTrial=(request.HasFreeTrial.Data.hasFreeTrial=="True")?true:false;else
user.IsCompleted=false;if(request.GetOberonClientUserId.Status!="ACCOUNT_ERROR")
user.OberonClientUserId=request.GetOberonClientUserId.Data.userGuid;else
user.IsCompleted=false;if(request.GetPartnerProgramId.Status!="ACCOUNT_ERROR")
user.PartnerProgramId=request.GetPartnerProgramId.Data.ProgramId;else
user.IsCompleted=false;if(request.GetBasicUserDetails.Status!="ACCOUNT_ERROR"){user.Nickname=request.GetBasicUserDetails.Data.Nickname;user.AvatarURL=request.GetBasicUserDetails.Data.AvatarURL;user.AvatarName=request.GetBasicUserDetails.Data.AvatarName;}
else
user.IsCompleted=false;UA.UserUtils.prototype.Callback(user);}
function InitializeUAFail(request){var user={};user.IsSuccessful=false;user.ErrorMessage=request.Status;UA.UserUtils.prototype.Callback(user);}
function InitializeUATimeout(request){var user={};user.IsSuccessful=false;user.ErrorMessage="Timeout";UA.UserUtils.prototype.Callback(user);}
UA.daysToDate=function(){var i,arr=[];for(i=0;i<arguments.length;i++)
arr[i]=new Date(arguments[i]*86400000);return arr;}
if(!window.UA)UA={};UA.Request=Class.create();UA.Request.STATUS_OK="OK";UA.Request.STATUS_GENERAL_ERROR="GENERAL_ERROR";UA.Request.toString=function(){return"UA.Request";}
UA.Request.AsPrototype=function(){return new UA.Request({},new Function());}
UA.Request.prototype.initialize=function(oBoss,fSuccessCallback,fFailCallback,fTimeoutCallback){this.log=Object.extend({},this.log);this.boss=this.log.boss=oBoss;this.successCallbacks=[];this.failiorCallbacks=[];this.timeoutCallbacks=[];if(fSuccessCallback)
{this.successCallbacks.push(fSuccessCallback);this.isSynchronous=false;}
else
{this.isSynchronous=true;}
if(!fFailCallback)fFailCallback=oBoss.defaultOnFailior;if(typeof(fFailCallback)=='function')this.failiorCallbacks.push(fFailCallback);if(!fTimeoutCallback)fTimeoutCallback=oBoss.defaultOnTimeout;if(typeof(fTimeoutCallback)=='function')this.timeoutCallbacks.push(fTimeoutCallback);this.parameters={};}
UA.Request.prototype.log={emit:function(iLevel,sText){if(this.boss.log&&typeof(this.boss.log.emit)=='function'){this.boss.log.emit(iLevel,sText);}else
this.log.error("Cannot log for caller-object: "+this.boss.toString()+". Level: "+iLevel+", Message: "+sText);},fatal:function(sText){this.emit(Log4Js.FATAL,sText);},error:function(sText){this.emit(Log4Js.ERROR,sText);},warn:function(sText){this.emit(Log4Js.WARN,sText);},info:function(sText){this.emit(Log4Js.INFO,sText);},debug:function(sText){this.emit(Log4Js.DEBUG,sText);},log:new Log4Js.Logger("UA.Request.log"),boss:null,toString:function(){return"UA.Request.log";}}
UA.Request.prototype.url="UNSET-VALUE";UA.Request.prototype.isSent=false;UA.Request.prototype.dispatch=function request_Dispatch(retObj,arrHandlers,sEventName){if(arrHandlers.length==0){this.log.info(sEventName+' from '+this.toString()+' contained no handlers.');return;}
this.log.info('Dispatching '+sEventName+' from '+this.toString());var i,cb;for(i=0;i<arrHandlers.length;i++){cb=arrHandlers[i];if(cb&&typeof(cb)=='function'){cb.call(this.boss,retObj,this.parameters);}}}
UA.Request.prototype.toString=function(){return"[UA.Request("+this.id+")] of "+this.boss.toString();}
UA.Request.prototype.onSuccess=function(request){this.dispatch(request.result.Data,this.successCallbacks,"onSuccess");}
UA.Request.prototype.onFailure=function(request){this.log.error("Failed on request of: "+this.boss.toString()+" to url: "+this.urlWithParams+", Status: "+request.result.Status);this.dispatch(request.result,this.failiorCallbacks,"onFailure");}
UA.Request.prototype.onTimeout=function(request){this.log.error("Timeout on request of: "+this.boss.toString()+" to url: "+this.urlWithParams);this.dispatch(request,this.timeoutCallbacks,"onTimeout");}
UA.Request.prototype.apply=function(){if(this.isSent)
return;this.isSent=true;if(Clearance.level>=Clearance.UNCLASSIFIED)
this.parameters.cookieData=Clearance.getMagic(Clearance.UNCLASSIFIED);var url=Url.appendParams(this.url,this.parameters);this.urlWithParams=url;if(this.isSynchronous)
{var strScriptTag=[];strScriptTag[strScriptTag.length]="<script ";strScriptTag[strScriptTag.length]=" type=\"text/javascript\""
strScriptTag[strScriptTag.length]=" src=\"";strScriptTag[strScriptTag.length]=url
strScriptTag[strScriptTag.length]="\"></script>";document.write(strScriptTag.join(""));}
else
{this._JAST=new Jast.Request(url,this);}}
var EMPTY_RESULT="EMPTY_RESULT";window.OK="OK";if(!window.UA)UA={};UA.Game=Class.create();UA.Game.Requests=[];UA.Game.Methods={GAMEHIGHSCORES:"GetGameHighScores",USERSCORE:"GetUserScoreData",SESSION_CERT:"GetSingleSessionCert",GRACE_CERTS:"GetGraceCerts",GETGAMEEVERHIGHSCORES:"GetGameEverHighScores",GETGAMEWEEKLYHIGHSCORES:"GetGameWeeklyHighScores",GETGAMEHOURLYHIGHSCORES:"GetGameHourlyHighScores"}
UA.Game.Scores={};UA.Game.Scores.Periods={};UA.Game.Scores.Periods.WEEK="WEEK";UA.Game.Scores.Periods.HOUR="HOUR";UA.Game.Scores.Periods.EVER="EVER";UA.Game.Avatar={};UA.Game.Avatar.Size={};UA.Game.Avatar.Size.Size150x200="Size150x200";UA.Game.Avatar.Size.Size65x87="Size65x87";UA.Game.Avatar.Size.Size86x115="Size86x115";UA.Game.Avatar.Size.Size98x131="Size98x131";UA.Game.Avatar.Size.Size124x165="Size124x165";UA.Game.Avatar.Size.Size24x24="Size24x24";UA.Game.Avatar.Size.Size48x48="Size48x48";UA.Game.prototype.SEND_GAME_DATA_POST_URL="UNSET_VALUE";UA.Game.prototype.isCachedResponse=false;UA.Game.prototype.initialize=function(p_sku){this._prv={Sku:p_sku,scores:{}};this.log=new Log4Js.Logger(this.toString())
this.log.info("UA.Game("+p_sku+") initiated.");}
UA.Game.GameRequest=Class.createSubclass("UA.Request");UA.Game.GameRequest.prototype=UA.Request.AsPrototype()
UA.Game.GameRequest.prototype.initialize=function gameCtor(oGame,fSuccessCallback,fFailCallback,fTimeoutCallback){if(oGame.isCachedResponse){this.url=this.boss.USER_CACHED_HANDLER_URL}else{this.url=this.boss.PRIME_HANDLER_URL;}
this.parameters={Sku:oGame._prv.Sku,Period:"",Mode:""};}
UA.Game.prototype.getGameRequest=function(fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.Game.GameRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.id=UA.Game.Requests.length;UA.Game.Requests[r.id]=r;return r;}
UA.Game.prototype.defaultOnFailior=null;UA.Game.prototype.defaultOnTimeout=null;UA.Game.prototype.toString=function gameToString(){return"[UI.Game("+this._prv.Sku+")]";}
UA.Game.prototype.GetUserHighScore=function(iMode,fSuccess,fFailure,fTimeout){if(iMode==null||isNaN(iMode))iMode=0;var r=this.getGameRequest(fSuccess,fFailure,fTimeout);r.parameters.Mode=iMode;r.parameters.MethodName=UA.Game.Methods.USERSCORE;r.apply();return r;}
UA.Game.prototype.GetSingleSessionCert=function(iMode,fSuccess,fFailure,fTimeout){var r=this.getGameRequest(fSuccess,fFailure,fTimeout);r.parameters.methodName=UA.User.Methods.GETDATA;r.parameters.MethodList=UA.Game.Methods.SESSION_CERT;r.apply();return r;}
UA.Game.prototype.GetGraceCerts=function(iMode,fSuccess,fFailure,fTimeout){var r=this.getGameRequest(fSuccess,fFailure,fTimeout);r.parameters.MethodName=UA.User.Methods.GETDATA;r.parameters.MethodList=UA.Game.Methods.GRACE_CERTS;r.apply();return r;}
UA.Game.prototype.GetGameHighScores=function(iMode,iAmount,ePeriod,fSuccess,fFail,fTimeout,eSize){var r=this.getGameRequest(fSuccess,fFail,fTimeout);r.parameters.Mode=iMode;r.parameters.TopScores=iAmount;r.parameters.Period=ePeriod;if(eSize==null||eSize==undefined)
delete r.parameters.Size;else
r.parameters.Size=eSize;r.parameters.MethodName=UA.Game.Methods.GAMEHIGHSCORES;r.apply();}
UA.Game.prototype.SendGameData=function(gameData,callback){var formSendGameData=document.createElement("form");formSendGameData.setAttribute("method","POST");formSendGameData.setAttribute("action",UA.Game.prototype.SEND_GAME_DATA_POST_URL);formSendGameData.appendChild(CreateHiddenInput("GameData",gameData));formSendGameData.appendChild(CreateHiddenInput("channel",UA.CHANNEL));PostIframeRequest(formSendGameData,callback);}
if(!window.UA)UA={};UA.StaticUser=Class.create();UA.User=Class.create();UA.User.Requests=[];UA.User.Methods={GETUSERDETAILS:"GetUserDetails",GETALLSCORES:"GetAllScores",GETUSERGAMES:"GetUserGames",HASFREETRIAL:"HasFreeTrial",ISSUBSCRIBED:"IsSubscribed",ISAUTHORIZED:"IsAuthorized",GETCURRENTPERMITTEDSKUS:"GetCurrentPermittedSKUs",GETPLANNEDPERMITTEDSKUS:"GetPlannedPermittedSKUs",GETPACKAGEEXPIRATIONUTCDATE:"GetPackageExpirationUTCDate",ISNICKNAMEAVAILABLE:"IsNicknameAvailable",GETAVATARXML:"GetAvatarXml",GETWARDROBEXML:"GetWardrobeXml",ISUSERNAMEAVAILABLE:"IsUsernameAvailable",ISCAPTCHAMATCH:"IsCaptchaMatch",GETUSERTOKENS:"GetUserTokens",GETUSERLOGINDAYS:"GetUserLoginDays",GETHIGHESTMEDAL:"GetHighestMedal",GETPERSONADATABYNICKNAME:"GetPersonaDataByNickname",GETDATA:"GetData",GET_OBERON_CLIENT_USERID:"GetOberonClientUserId",GET_PARTNER_PROGRAM_ID:"GetPartnerProgramId"}
UA.User.USER_HANDLER_URL="UNSET-VALUE";UA.User.POST_DATA_REDIRECT_URL="UNSET-VALUE";UA.User.LOGGED_IN="LoggedIn";UA.User.ANONYMOUS="Anonymous";UA.User.prototype.initialize=function(){this.params={};}
UA.User.prototype.log=new Log4Js.Logger("[UA.User]");UA.User.prototype.IsLoggedOn=function(dontReloadCookies){if(dontReloadCookies==undefined||dontReloadCookies==false)
Clearance.refresh();return Clearance.hasUnclassified();}
UA.User.prototype.isGuest=function(dontReloadCookies){return(!UA.User.prototype.IsLoggedOn(dontReloadCookies)||Clearance.isGuest());}
UA.User.prototype.LogOff=function(){Clearance.forget(Url.relativeUrl({withClearanceParams:false,withHereParams:true}));}
UA.User.prototype.getCookieData=function(isEscaped){var cookieData=Clearance.getMagic(Clearance.UNCLASSIFIED);if(isEscaped)
cookieData=escape(cookieData);return cookieData;}
UA.User.UserRequest=Class.createSubclass("UA.Request");UA.User.UserRequest.prototype=UA.Request.AsPrototype()
UA.User.UserRequest.prototype.initialize=function userReqCTor(oUser,fSuccessCallback,fFailCallback,fTimeoutCallback){var curUrl=this.boss.USER_HANDLER_URL;if(this.isSynchronous)
curUrl=curUrl.toLowerCase().replace("processjaccount.ashx","getuseraccountdata.ashx");if((oUser.params.isSecured)&&(curUrl.indexOf('HTTPS')==-1)&&(curUrl.indexOf('https')==-1))
curUrl=curUrl.replace('HTTP','HTTPS').replace('http','https');this.url=curUrl;delete oUser.params.isSecured;this.boss=this.log.boss=oUser;this.parameters=Object.extend({},this.boss.params);}
UA.User.UserRequest.prototype.addParameter=function(key,val){this.parameters[key]=val;}
UA.User.prototype.GetUserDetails=function(fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.methodName=UA.User.Methods.GETUSERDETAILS;r.apply();}
UA.User.prototype.GetUserGames=function(fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.methodName=UA.User.Methods.GETUSERGAMES;r.apply();}
UA.User.prototype.IsNicknameAvailable=function(sNickname,sLanguage,fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.Nickname=sNickname;r.parameters.Language=sLanguage;r.parameters.methodName=UA.User.Methods.ISNICKNAMEAVAILABLE;r.apply();}
UA.User.prototype.IsUsernameAvailable=function(sUsername,sLanguage,fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.Username=sUsername;r.parameters.Language=sLanguage;r.parameters.methodName=UA.User.Methods.ISUSERNAMEAVAILABLE;r.apply();}
UA.User.prototype.IsCaptchaMatch=function(sUsername,sRandomNum,sCaptchaUserText,fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.username=sUsername;r.parameters.randomNum=sRandomNum;r.parameters.captchaUserText=sCaptchaUserText;r.parameters.methodName=UA.User.Methods.ISCAPTCHAMATCH;r.apply();}
UA.User.prototype.GetAvatarXml=function(fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.methodName=UA.User.Methods.GETAVATARXML;r.apply();}
UA.User.prototype.GetWardrobeXml=function(fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.methodName=UA.User.Methods.GETWARDROBEXML;r.apply();}
UA.User.prototype.GetUserTokens=function(fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.methodName=UA.User.Methods.GETUSERTOKENS;r.apply();}
UA.User.prototype.GetUserLoginDays=function(fSuccessCallback,fFailCallback,fTimeoutCallback){if(this.isGuest()){var data={};data.Status="ACCOUNT_NOT_CREATED";fFailCallback(data);return;}
var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.methodName=UA.User.Methods.GETUSERLOGINDAYS;r.apply();}
UA.User.prototype.GetHighestMedal=function(fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.methodName=UA.User.Methods.GETHIGHESTMEDAL;r.apply();}
UA.User.prototype.GetPersonaDataByNickname=function(nickname,avatarSize,sku,fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);if(nickname!=null)
r.parameters.Nickname=encodeURIComponent(nickname);r.parameters.AvatarSize=avatarSize;r.parameters.Sku=sku;r.parameters.methodName=UA.User.Methods.GETPERSONADATABYNICKNAME;r.apply();}
UA.User.prototype.GetPersonaData=function(fSuccessCallback,fFailCallback,fTimeoutCallback){var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.methodName=UA.User.Methods.GETPERSONADATABYNICKNAME;r.apply();}
UA.User.prototype.GetCaptchaUrl=function(username,randomNum){var url;url=UA.User.prototype.CAPTCHA_IMAGE_URL;url=Url.appendParamValue(url,"username",username);url=Url.appendParamValue(url,"randomNum",randomNum);return url;}
UA.User.ReportAbuse=function(abusingNickname,description,utcTime,retURL){var formReportAbuse=document.createElement("form");formReportAbuse.setAttribute("method","POST");formReportAbuse.setAttribute("action",UA.User.POST_DATA_REDIRECT_URL);cookieData=Clearance.getMagic(Clearance.UNCLASSIFIED);formReportAbuse.appendChild(CreateHiddenInput("cookieData",cookieData));formReportAbuse.appendChild(CreateHiddenInput("abusingNickname",abusingNickname));formReportAbuse.appendChild(CreateHiddenInput("description",description));formReportAbuse.appendChild(CreateHiddenInput("utcTime",utcTime));formReportAbuse.appendChild(CreateHiddenInput("retUrl",retURL));formReportAbuse.appendChild(CreateHiddenInput("failUrl",Url.here.full));formReportAbuse.appendChild(CreateHiddenInput("methodName","ReportAbuse"));formReportAbuse.appendChild(CreateHiddenInput("channel",UA.CHANNEL));document.body.insertBefore(formReportAbuse,null);formReportAbuse.submit();}
UA.User.prototype.defaultOnFailior=null;UA.User.prototype.defaultOnTimeout=null;UA.User.prototype.toString=function(){return"[User: "+this.Nickname+"]";}
UA.User.prototype.getUserRequest=function(fSuccessCallback){var r=new UA.User.UserRequest(this,fSuccessCallback);r.id=UA.User.Requests.length;UA.User.Requests[r.id]=r;return r;}
UA.User.prototype.GetData=function(methodsArr,paramsList,fSuccessCallback,fFailCallback,fTimeoutCallback){if(methodsArr.length==0){return;}
var r=new UA.User.UserRequest(this,fSuccessCallback,fFailCallback,fTimeoutCallback);r.parameters.methodName=UA.User.Methods.GETDATA;var methodsStr=methodsArr[0];for(var i=1;i<methodsArr.length;i++)
{methodsStr+=(","+methodsArr[i]);}
r.parameters.MethodList=methodsStr;if(paramsList!=null)
{var paramsArr=paramsList.split(",");for(var i=0;i<paramsArr.length;i++)
{var kNv=paramsArr[i].split(":");r.addParameter(kNv[0],kNv[1]);}}
r.apply();}
UA.User.prototype.getCachedData=function(fSuccessCallback,fFailCallback,fTimeoutCallback)
{UA.User.prototype.getCachedData.CACHED_DATA_COOKIE_NAME='uaCachedData';this.getCachedData_OnSuccess=fSuccessCallback;this.log.debug('getCachedData - Searching for cached data in cookie.');this.cachedData=Cookies.get(UA.User.prototype.getCachedData.CACHED_DATA_COOKIE_NAME);if(this.cachedData!=undefined&&this.cachedData!=null)
{this.log.debug('getCachedData - Cached data found in cookie.');this.getCachedData_OnSuccess(this.cachedData);}
else
{this.log.debug('getCachedData - No cached data in cookie. Retreiving data from server.');this.GetUserDetails(UA.User.prototype.getCachedData_OnSuccess,fFailCallback,fTimeoutCallback);}}
UA.User.prototype.getDemographicData=function()
{this.log.debug('getDemographicData - Searching for cached data in cookie.');this.cachedData=Cookies.get(UA.User.prototype.getCachedData.CACHED_DATA_COOKIE_NAME);var result=null;if(this.cachedData!=undefined&&this.cachedData!=null)
{result=this.cachedData;this.log.debug('getDemographicData - Cached data found in cookie.');}
if(!UA.User.prototype.getDemographicData.IsCalledOnce){UA.User.prototype.getDemographicData.IsCalledOnce=true;var fFailCallback=function(data){this.log.debug('UA.User.prototype.getDemographicData failed');};var fTimeoutCallback=function(data){this.log.debug('UA.User.prototype.getDemographicData timed out');};this.getCachedData_OnSuccess=function(data){this.log.debug('UA.User.prototype.getDemographicData succeded');};this.GetUserDetails(UA.User.prototype.getCachedData_OnSuccess,fFailCallback,fTimeoutCallback);}
return result;}
UA.User.prototype.getCachedData.CACHED_DATA_COOKIE_NAME='uaCachedData';UA.User.prototype.getDemographicData.IsCalledOnce=false;UA.User.prototype.getCachedData_OnSuccess=function(userDetails)
{this.cachedData={};this.cachedData.gender=userDetails.gender;this.cachedData.birthYear=parseInt(userDetails.birthYear);this.cachedData.zipCode=parseInt(userDetails.zipCode);this.log.debug('getCachedData - Writing cached data in cookie.');Cookies.set(UA.User.prototype.getCachedData.CACHED_DATA_COOKIE_NAME,this.cachedData,{expires:Cookies.expiration(691200000)});if(this.getCachedData_OnSuccess!=undefined&&this.getCachedData_OnSuccess!=null)
this.getCachedData_OnSuccess(this.cachedData);}
UA.User.prototype.PostData=function(methodName){var form=document.createElement("form");form.setAttribute("method","POST");form.setAttribute("action",UA.User.POST_DATA_REDIRECT_URL);form.appendChild(CreateHiddenInput("methodName",methodName));if(this.params!=null)
for(var paramName in this.params)
form.appendChild(CreateHiddenInput(paramName,this.params[paramName]));document.body.insertBefore(form,null);form.submit();}//::: UserAccount Channel=110035530 00:00:00.1249760
try{
  UA.Game.prototype.PRIME_HANDLER_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/1900.1/APP/ProcessJAccount.ashx?channel=110035530';
  UA.Game.prototype.SEND_GAME_DATA_POST_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/1900.1/APP/SendGameData.ashx';
  UA.User.POST_DATA_REDIRECT_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/1900.1/APP/PostData.ashx';
  UA.User.prototype.USER_HANDLER_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/1900.1/APP/ProcessJAccount.ashx?channel=110035530';
  UA.User.prototype.SAVE_AVATAR_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/1900.1/APP/SetAvatar.ashx';
  UA.User.prototype.GET_AVATAR_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/1900.1/APP/AvatarXML.ashx';
  UA.User.prototype.CAPTCHA_IMAGE_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/1900.1/APP/Captcha.ashx';
  UA.Game.prototype.USER_CACHED_HANDLER_URL = 'http://userassets.apizone.betaregion.oberon-media.com/UserAccount/Processing/1900.1/APP/ProcessJAccount.ashx?channel=110035530';
  UA.User.prototype.GET_CACHED_AVATAR_URL = 'http://userassets.apizone.betaregion.oberon-media.com/UserAccount/Processing/1900.1/APP/AvatarXML.ashx';
  UA.UserUtils.IFrameLoginURL = '';
  UA.CHANNEL = 110035530;
}
catch (e) {}

//::: GameCatalog Code 00:00:00.1249760

Function.prototype.getArgNamesArray=function(){try{return/function[^\(]*\(([^\)]*)\)/.exec(this.toString())[1].replace(/\s*/g,"").split(",");}catch(ex){return[];}}
Array.prototype.cut=function(iStart,iCount)
{var iEnd=undefined;if(iStart==undefined)iStart=0;iEnd=(iCount==undefined)?this.length:iStart+iCount;return this.slice(iStart,iEnd);}
Array.prototype.page=function(iPage,iItemsInPage)
{return this.cut(iPage*iItemsInPage,iItemsInPage);}
if(window.GameCatalog==null)
GameCatalog={};GameCatalog.PRODUCT_CODE_VARNAME="code";GameCatalog.LANGUAGE_VARNAME="lc";GameCatalog.CHANNEL_VARNAME="channel";GameCatalog.BILLING_CNTRY_VARNAME="BillingCountry";GameCatalog.LOBBY_VARNAME="lobby";GameCatalog.language="";GameCatalog.channelCode=-1;GameCatalog.baseBuyURL="";GameCatalog.baseGamePageURL="";GameCatalog.baseLobbyURL="";GameCatalog.billingCountry="";GameCatalog.millisPerDay=24*60*60*1000;GameCatalog.TagSkuLinks=function()
{this.initialize();var e,a=new Array()
for(e in this)a[e]=this[e];for(e=0;e<arguments.length;e++)a[e]=arguments[e];return a;}
GameCatalog.TagSkuLinks.prototype.initialize=function()
{this.dictionary={}}
GameCatalog.TagSkuLinks.prototype.byWeight=function(iStart,iCount,isForceSort)
{if(!this._byWeight||isForceSort)
{this._byWeight=this.concat().sort(function(a,b)
{return b.weight-a.weight;});}
return this._byWeight.cut(iStart,iCount);}
GameCatalog.TagSkuLinks.prototype.bySkuProperty=function(sSkuProp,isDescSort,iStart,iCount,isForceSort)
{if(!this["_sku_"+sSkuProp]||isForceSort){var orderVar=-1;if(isDescSort)
orderVar=1;this["_sku_"+sSkuProp]=this.concat().sort(function(a,b){if(b.sku[sSkuProp]==a.sku[sSkuProp])return 0;return(b.sku[sSkuProp]>a.sku[sSkuProp])?orderVar:(orderVar*(-1));});}
return this["_sku_"+sSkuProp].cut(iStart,iCount);}
GameCatalog.SkuTagLinks=function()
{this.initialize();var e,a=new Array()
for(e in this)a[e]=this[e];for(e=0;e<arguments.length;e++)a[e]=arguments[e];return a;}
GameCatalog.SkuTagLinks.prototype.initialize=GameCatalog.TagSkuLinks.prototype.initialize;GameCatalog.SkuTagLinks.prototype.byWeight=GameCatalog.TagSkuLinks.prototype.byWeight;GameCatalog.SkuTagLinks.prototype.byTagProperty=function(sTagProp,isDescSort,iStart,iCount,isForceSort)
{if(!this["_tag_"+sTagProp]||isForceSort){var orderVar=-1;if(isDescSort)
orderVar=1;var arr=this.concat().sort(function(a,b){if(b.tag[sTagProp]==a.tag[sTagProp])return 0;return(b.tag[sTagProp]>a.tag[sTagProp])?orderVar:(orderVar*(-1));});this["_tag_"+sTagProp]=arr;}
return this["_tag_"+sTagProp].cut(iStart,iCount);}
GameCatalog.Category=Class.create();GameCatalog.Category.prototype.initialize=function(code,name,internalName,categoryURL)
{var params=this.initialize.getArgNamesArray();for(var i=0;i<params.length;i++)
if(arguments[i]!==undefined)this[params[i]]=arguments[i];this.games={};this.games.All=[];this.games.All.bySkuProperty=GameCatalog.Game.All.bySkuProperty}
GameCatalog.Category.All=[];GameCatalog.Category.All.byCategoryProperty=function(sPropName,iStart,iCount,isForceSort){if(!this[0]||undefined===this[0][sPropName])
return this;if(!this["_"+sPropName]||isForceSort)
{this["_"+sPropName]=this.concat().sort(function(a,b)
{if(a[sPropName]==b[sPropName])return 0;return(a[sPropName]<b[sPropName])?-1:1;});}
return this["_"+sPropName].cut(iStart,iCount);}
GameCatalog.Category.ByCode={};GameCatalog.Game=Class.create();GameCatalog.Game.All=[];GameCatalog.Game.All.bySkuProperty=GameCatalog.Category.All.byCategoryProperty;GameCatalog.Game.All.dictionary={};GameCatalog.Game.All.BySku=GameCatalog.Game.All.dictionary;GameCatalog.Game.prototype.initialize=function(sku,name,smallThumbnail,categoryCode,productCode,lobbyUID,isMultiPlayer,thumbnail16x16,isNew,publishDate,thumbnail100x75,thumbnail179x135,thumbnail320x240,isLocalized,thumbnail130x75,downloadURL,oneThirdDesc,twoThirdsDesc,isOnline)
{if(typeof(arguments[0])=='object')arguments=arguments[0];var params=this.initialize.getArgNamesArray();for(var i=0;i<params.length;i++)
if(arguments[i]!==undefined)this[params[i]]=arguments[i];this['publishDate']=new Date(this['publishDate']*GameCatalog.millisPerDay);this['gamePageURL']=GameCatalog.Game.generateGamePageURL(this['productCode']);this['buyURL']=GameCatalog.Game.generateBuyURL(this['productCode']);this['lobbyURL']=GameCatalog.Game.generateLobbyURL(this['lobbyUID']);this.tagLinks=new GameCatalog.SkuTagLinks();}
GameCatalog.Game.prototype.getRecentGames=function(count){var isNew="isNew",pDate="publishDate";var a=GameCatalog.Game.All.bySkuProperty(isNew).concat();var arr=[];for(var i=a.length-1;i>=0;i--){if(a[i].isNew==false)
break;arr.push(a[i]);}
arr=arr.sort(function(a,b)
{if(a[pDate]==b[pDate])return 0;return(a[pDate]>b[pDate])?-1:1;});return arr.cut(0,count);}
GameCatalog.Game.addTag=function(oTag,dblWeight){if(this.tagLinks.dictionary[oTag.internalName])
return this.tagLinks.dictionary[oTag.internalName];return this.addTagLink({weight:dblWeight,tag:oTag,sku:this});}
GameCatalog.Game.prototype.addTagLink=function(oLink){if(!this.tagLinks.dictionary[oLink.tag.internalName])
this.tagLinks[this.tagLinks.length]=this.tagLinks.dictionary[oLink.tag.internalName]=oLink;if(!oLink.tag.skuLinks.dictionary[this.sku])
oLink.tag.addSkuLink(oLink);return oLink;}
GameCatalog.Tag=Class.create();GameCatalog.Tag.keyProperty="internalName";GameCatalog.Tag.propertyList="name, count";GameCatalog.Tag.prototype.initialize=function()
{if(typeof(arguments[0])=='object')args=arguments[0];this[GameCatalog.Tag.keyProperty]=args[0];var prop=GameCatalog.Tag.propertyList.replace(/\s*/g,"").split(",");this.tagPageURL=GameCatalog.URLs.tagPageURL.replace(/TAG_INTERNAL_NAME/g,args[0]);for(var i=0;i<prop.length;i++)
if(args[i+1]!==undefined)
{var val=args[i+1];if(prop[i].indexOf('Date')!=-1)
val=new Date(val*GameCatalog.millisPerDay)
this[prop[i]]=val;}
this.skuLinks=new GameCatalog.TagSkuLinks();}
GameCatalog.Tag.prototype.addSkuLink=function(oLink)
{if(!this.skuLinks.dictionary[oLink.sku.sku])
this.skuLinks.dictionary[oLink.sku.sku]=this.skuLinks[this.skuLinks.length]=oLink;if(!oLink.sku.tagLinks.dictionary[this.internalName])
oLink.sku.addTagLink(oLink);}
GameCatalog.Tag.prototype.addSku=function(sku,dblWeight){if(typeof(sku)=='number')sku=GameCatalog.Game.All.dictionary[sku];if(!sku)return;this.addSkuLink({weight:dblWeight,sku:sku,tag:this});}
GameCatalog.Tag.prototype.addSkus=function()
{var i=0;while(i<arguments.length){this.addSku(arguments[i++],arguments[i++]);}}
GameCatalog.Tag.prototype.isFullyLoaded=function()
{return this.count==this.skuLinks.length;}
GameCatalog.Tag.All=[];GameCatalog.Tag.All.byTagProperty=function(sProp,isDescSort,iStart,iCount,isForceSort)
{if(!this["_by_"+sProp]||isForceSort)
{var orderVar=-1;if(isDescSort)
orderVar=1;this["_by_"+sProp]=this.concat().sort(function(a,b)
{if((b[sProp]==a[sProp]))return 0;return(b[sProp]>a[sProp])?orderVar:(orderVar*(-1));});}
return this["_by_"+sProp].cut(iStart,iCount);}
GameCatalog.Tag.All.dictionary={}
GameCatalog.URLs={gamePageURL:'/Deluxe.aspx?code=GAME_SKU&lc=en&channel=110167437',gameImageBase:'/images/games/',buyURL:'http://Jeuxentelechargement-beta.jeu.orange.fr/Checkout.asp?code=CHECKOUT_SKU&channel=110167437&lc=fr&BillingCountry=FR',lobbyURL:'/Lobby.aspx?lobby=LOBBY_ID&channel=110167437&lc=en',categoryURL:'/Category.aspx?code=CATEGORY_CODE',tagPageURL:'/Tag.aspx?tag=TAG_INTERNAL_NAME&ln=en'};GameCatalog.addCategory=function(code,name,internalName)
{var categoryURL=GameCatalog.URLs.categoryURL.replace(/CATEGORY_CODE/g,code);var category=new GameCatalog.Category(code,name,internalName,categoryURL);GameCatalog.Category.ByCode[code]=GameCatalog.Category.All[GameCatalog.Category.All.length]=category;return category;}
GameCatalog.addGame=function(sku,name,smallThumbnail,categoryCode,productCode,lobbyUID,isMultiPlayer,thumbnail16x16,isNew,publishDate,thumbnail100x75,thumbnail179x135,thumbnail320x240,isLocalized,thumbnail130x75,downloadURL,oneThirdDesc,twoThirdsDesc,isOnline)
{var newGame=new GameCatalog.Game(sku,name,smallThumbnail,categoryCode,productCode,lobbyUID,isMultiPlayer,thumbnail16x16,isNew,publishDate,thumbnail100x75,thumbnail179x135,thumbnail320x240,isLocalized,thumbnail130x75,downloadURL,oneThirdDesc,twoThirdsDesc,isOnline)
GameCatalog.Game.All[GameCatalog.Game.All.length]=newGame;GameCatalog.Game.All.BySku[newGame.sku]=newGame;return newGame;}
GameCatalog.addTag=function(){var tag=this.Tag.All.dictionary[arguments[0]];if(tag)return tag;var newTag=new this.Tag(arguments);this.Tag.All[this.Tag.All.length]=newTag;this.Tag.All.dictionary[arguments[0]]=newTag;return newTag;}
GameCatalog.Game.generateGamePageURL=function(productCode)
{var gamePageURLBuilder=new Array();gamePageURLBuilder=gamePageURLBuilder.concat(GameCatalog.baseGamePageURL,"?",GameCatalog.PRODUCT_CODE_VARNAME,"=",productCode,"&",GameCatalog.LANGUAGE_VARNAME,"=",GameCatalog.language,"&",GameCatalog.CHANNEL_VARNAME,"=",GameCatalog.channelCode);return gamePageURLBuilder.join("");}
GameCatalog.Game.generateBuyURL=function(productCode)
{var buyURLBuilder=new Array();buyURLBuilder=buyURLBuilder.concat(GameCatalog.baseBuyURL,"?",GameCatalog.PRODUCT_CODE_VARNAME,"=",productCode,"&",GameCatalog.CHANNEL_VARNAME,"=",GameCatalog.channelCode,"&",GameCatalog.LANGUAGE_VARNAME,"=",GameCatalog.language,"&",GameCatalog.BILLING_CNTRY_VARNAME,"=",GameCatalog.billingCountry);return buyURLBuilder.join("");}
GameCatalog.Game.generateLobbyURL=function(lobbyUID)
{if(lobbyUID!="")
{var lobbyURLBuilder=new Array();lobbyURLBuilder=lobbyURLBuilder.concat(GameCatalog.baseLobbyURL,"?",GameCatalog.LOBBY_VARNAME,"=",lobbyUID,"&",GameCatalog.CHANNEL_VARNAME,"=",GameCatalog.channelCode,"&",GameCatalog.LANGUAGE_VARNAME,"=",GameCatalog.language);return lobbyURLBuilder.join("");}
return"";}//::: GameCatalog Data 00:00:00.1249760
//::: PresenceCatalog 00:00:01.1404060
// Presence catalog namespace
if (window.PresenceCatalog == null) 
	PresenceCatalog = {};

// Lobby / Lobbies
PresenceCatalog.Lobbies = {};

PresenceCatalog.Lobbies.All = [];
PresenceCatalog.Lobbies.All.ByLobby = {};
PresenceCatalog.Lobbies.All.BySku = {};
PresenceCatalog.addLobby = function( lobbyID, numberOfPlayers )
{
	var newLobby = 
			{ 
				LobbyID : lobbyID,
				NumberOfPlayers : numberOfPlayers
			};
    this.Lobbies.All[this.Lobbies.All.length] = newLobby;
    this.Lobbies.All.ByLobby[newLobby.LobbyID] = newLobby;
}

PresenceCatalog.addLobbySku = function( sku, lobbyID, numberOfPlayers )
{
	var newLobby = 
			{ 
				LobbyID : lobbyID,
				NumberOfPlayers : numberOfPlayers
			};
    this.Lobbies.All[this.Lobbies.All.length] = newLobby;
    this.Lobbies.All.BySku[sku] = newLobby;
}

PresenceCatalog.addLobbySku2 = function( sku, lobbyID, numberOfPlayers, membersAutoPlayRoomURL, nonMembersAutoPlayRoomURL )
{
    var newLobby = 
            {
                LobbyID             : lobbyID,
				NumberOfPlayers     : numberOfPlayers,
				MembersRoomURL      : membersAutoPlayRoomURL,
                NonMembersRoomURL   : nonMembersAutoPlayRoomURL
            }
    this.Lobbies.All[this.Lobbies.All.length] = newLobby;
    this.Lobbies.All.BySku[sku] = newLobby;
}

// Room / Rooms
PresenceCatalog.Rooms = {};

PresenceCatalog.Rooms.All = [];
PresenceCatalog.Rooms.All.ByRoom = {};
PresenceCatalog.addRoom = function( roomID, numberOfPlayers )
{
	var newRoom = 
			{
				RoomID : roomID,
				NumberOfPlayers : numberOfPlayers
			};

    this.Rooms.All[this.Rooms.All.length] = newRoom;
    this.Rooms.All.ByRoom[newRoom.RoomID] = newRoom;
}

PresenceCatalog.Rooms.All.ByCategory = {};
PresenceCatalog.addCategory = function( categoryCODE,numberOfPlayers )
{
	var newCategory = 
			{
				CategoryCODE : categoryCODE,
				NumberOfPlayers : numberOfPlayers
			};

    this.Rooms.All.ByCategory[categoryCODE] = newCategory;
}

PresenceCatalog.getTopPlayedSkus = function(iTop) 
{
    var topSkus = new Array();
    var allSkus = new Array();
    for (sku in this.Lobbies.All.BySku)
    {
        var currElement = 
            {
                Sku             : sku,
                NumberOfPlayers : this.Lobbies.All.BySku[sku].NumberOfPlayers
            };
        allSkus[allSkus.length] = currElement;
    }
    allSkus.sort(PresenceCatalog.getTopPlayedSkus.sortSkus);
    
    for (index = 0; index < allSkus.length && index < iTop; ++index)
    {
        topSkus[topSkus.length] = allSkus[index].Sku;
    }
    return topSkus;
}

PresenceCatalog.getTopPlayedSkus.sortSkus = function(a, b)
{
    return b.NumberOfPlayers - a.NumberOfPlayers;
}

// place holder (the whole community)
PresenceCatalog.NumberOfPlayers = 0;
//::: Flash.js 00:00:01.1404060
Flash = Class.create();


/**
 * a list of all settings that are not coppied directly from the 
 * settings object to the rendered output, 
 * either because they are syntax related, or because they are for 
 * internal use
 */
Flash.nonAttributeSettings = ['targetElement', 'log', 'id'
							 ,'classid','codebase','type','pluginspage', 'src'
							 ];
/**
 * a list of all settings that must be presented as <param> in <object> syntax
 * @type Array
 */
Flash.objectParams = ['bgcolor','quality','wmode','base','menu'
                     ,'scale','swremote','loop','salign'
                     ,'devicefont','embedmovie','seemlesstabbing'
                     ,'allowFullScreen'
					 ,'flashvars','allowscriptaccess'];

/**
 * default settings 
 * @type Object
 */
Flash.defaultSettings = 
	{	classid		: "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
	,	codebase	: "http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0"
	,	type		: "application/x-shockwave-flash"
	,	pluginspage	: "http://www.macromedia.com/go/getflashplayer"
	}

/**
 * @param {String} sSwfUrl 
 *  The Url to the presented swf file
 * @param {Object(optional)} oSettings 
 *	Supports the folowing settings<ol>
 *  <li>height
 *  <li>width
 *  <li>menu
 *  <li>wmode
 *  <li>quality
 *  <li>allowScriptAccess
 *  <li>wmode
 *  <li>base 
 *  </ol>
 * @param {String(optional)} sNoSettingsAttributes
 * This optional parameter allows the oSettings parameter to be provided 
 * with properties that should not be copied as flash settings. <br>
 * The usage is when the passed object is used as a setting object for other uses,
 * and contain attributes that must not be coppied to the flash object
 */
Flash.prototype.initialize = function(sSwfUrl, oSettings, sNoSettingsAttributes)
{
	/**
	 * The displayed movie
	 * @type String
	 */
	this.swfUrl = sSwfUrl;
	/**
	 * the settings object
	 * @type Object
	 */
	this.settings = Object.extend({}, this.constructor.defaultSettings);
	sNoSettingsAttributes = "," + sNoSettingsAttributes + ",";
	var each;
	for(each in oSettings)
		if (sNoSettingsAttributes.indexOf("," + each + ",") == -1)
			this.settings[each] = oSettings[each];

	/**
	 * The logger
	 * @type Log4Js.Logger
	 */
	this.log = this.settings.log || new Log4Js.Logger(this.settings.id || this.settings.targetElement &&  this.settings.targetElement != document || this.swfUrl || "Blank Flash instance")
	delete this.settings.log;

	/**
	 * the target DOM Container (or its ID as a string)
	 * @type DOMContainer|String
	 */
	this.targetElement = this.settings.targetElement;
	delete this.settings.targetElement;

	/**
	 * Holds the syntax to use ( object | embed ), based on the detected browser type
	 * <code>object</code> syntax is used on IE based browsers, on Windows only, except Opera.<br>
	 * The var is initiated in {@link Flash#render} method.
	 * @type String
	 */
	this.useSyntax = null;

	/**
	 * The HTML prepared and returned by {@link Flash#render}
	 * @type String
	 */
	 this.HTML = null;

	/**
	 * Holds all the key-values of all attributes for the tag.
	 * key-value pairs are collected by the used syntax (object or embed)
	 * @type prototype:Hash
	 */
	this.attributes = $H();

	/**
	 * Holds all the key-values of all params for the tag
	 * key-value pairs are collected by the used syntax
	 * @type prototype:Hash
	 */
	this.params = $H();

	//if the targetElement and the swf are provided - perform the render 
	if (this.targetElement && this.swfUrl) 
	{
		this.render(this.targetElement);
	}

}
/**
 * returns the syntax for the run-time environment.
 * <code>object</code> syntax is used on IE based browsers, on Windows only, except Opera.<br>
 * @type String
 * @returns 'object' or 'embed', depening on the run-time environment
 * @overridable
 */
Flash.prototype.getTagSyntax = function()
{
	var isIE  = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;
	var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
	var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;

	return (isIE && isWin && !isOpera)? 'object': 'embed';
}

/**
 * copy all supported attributes that are populated in settings to attributes
 * @private
 */
Flash.prototype.prv_prepareAttributes = function()
{
	var attribute; 
	for(attribute in this.settings)
	{
		if(Flash.nonAttributeSettings.indexOf(attribute) != -1) continue;
		this.attributes[attribute] = this.settings[attribute];
	}
}

/**
 * move attributes to param for '<object>' syntax
 * @private
 */
Flash.prototype.prv_moveAttributesToParams = function()
{

	var attribute;
	for (attribute in this.attributes)
	{
		if (typeof(this.attributes[attribute]) == 'function' ) continue;
		if( Flash.objectParams.indexOf( attribute.toLowerCase() ) != -1)
		{
			this.params[attribute] = this.attributes[attribute];
			delete this.attributes[attribute];
		}
	}
}

/**
 * emmits into the provided <codE>out</code> array the output of the 
 * attributes prepared at this.attributes according the prepared syntax
 * @private
 */
Flash.prototype.prv_renderAttributes = function(out)
{
	this.attributes.each(
		function(kv,i)
		{
			out[out.length] = ' ';
			out[out.length] = kv[0];
			out[out.length] = '="';
			out[out.length] = kv[1];
//			out[out.length] = escape(kv[1]);
			out[out.length] = '"';
		}
	);
	out[out.length] = ">\n";
}
/**
 *
 */
Flash.prototype.prv_renderParams = function(out)
{
	if(this.useSyntax != 'object') return;
	this.params.movie = this.swfUrl;
	this.params.each(
		function(kv,i)
		{
			out[out.length] = '<param name="';
			out[out.length] = kv[0];
			out[out.length] = '" value="';
			out[out.length] = kv[1];
			//out[out.length] = escape(kv[1]);
			out[out.length] = '"/>\n';
		}
	);
}
/**
 * bag of method references used to open the tag, according to the required syntax
 * on the constructor, the bag is overriden by the reference of the method that implements the required syntax.
 * @private
 */
Flash.prototype.prv_renderOpenTag = 
{	object: function(out)
			{
				out[out.length] = '<object classid="';
				out[out.length] = this.settings.classid;
				out[out.length] = '"\n\t codebase="'; 
				out[out.length] = this.settings.codebase;
				out[out.length] = '"\n\t id="'; 
				out[out.length] = this.objectID;
				out[out.length] = '"\n\t';
			}
,	embed : function(out)
			{
				out[0] = out[1] = out[2] = "";
				out.push('<embed type="');
				out.push(this.settings.type);
				out.push('" pluginspage="');
				out.push(this.settings.pluginspage);
				out.push('" name="');
				out.push(this.objectID);
 				out.push('" src="');
				out.push(this.swfUrl);
				out.push('"');
			}
}

/**
 * bag of method references used to close the tag, according to the required syntax
 * on the constructor, the bag is overriden by the reference of the method that implements the required syntax.
 * @private
 */
Flash.prototype.prv_renderCloseTag = 
{	object: function(out)
			{
				out[out.length] = "</object>";
			}

,	embed : function(out)
			{
				out.push("</embed>");
			}
}


/**
 * returns the HTML for the flash-tag in the syntax relevant for the run-time environment 
 * if target element is provided - renders the HTML into it.<br>
 * <code>targetElement</codE> can be provided as an argument, or as entry on <code>settings</code> arguments to the constructor.
 * The returned HTML is also kept on {@link Flash#HTML}.
 *
 * @param {String} targetElement
 * the ID of the DOM Container to render the Flash tag into.<br>
 * When not provided - <code>this.settings.targetElement</code> is used.
 *
 * @type String
 * @returns the prepared HTML for the flash tag
 */
Flash.prototype.render = function(targetElement)
{
	//detect the right syntax
	this.useSyntax = this.getTagSyntax();

	//get browser-dependent open and close tag method-references
	if(typeof(this.prv_renderOpenTag  ) != 'function') this.prv_renderOpenTag = this.prv_renderOpenTag[this.useSyntax];
	if(typeof(this.prv_renderCloseTag ) != 'function') this.prv_renderCloseTag = this.prv_renderCloseTag[this.useSyntax];

	//copy all supported attributes that are populated in settings to attributes
	this.prv_prepareAttributes();

	//move attributes to param for '<object>' syntax
	if (this.useSyntax == 'object')	this.prv_moveAttributesToParams();

	//find the target element;	
	if (!targetElement) 
		targetElement = 
			this.targetElement = 
				this.settings.targetElement || this.targetElement;

	//if the object is not in the DOM yet 
	if( targetElement && !$(targetElement) )
	{
		//if the name exists in postLoadRender collection - we're on the onLoad already
		if(!Flash.postLoadRender[targetElement])
		{
			Flash.postLoadRender[targetElement] =
				Flash.postLoadRender[Flash.postLoadRender.length] =
					this;
			return;
		}
	}

	//get the object
	targetElement = $(targetElement);

	//get or create objectID
	this.objectID = this.settings.id || ((targetElement)? targetElement.id + "_Flash" : "avatar_Flash");

	var out = [];
	this.prv_renderOpenTag(out);
	this.prv_renderAttributes(out);
	this.prv_renderParams(out);
	this.prv_renderCloseTag(out);

	out = out.join("");

	var o = $(this.objectID);
	if (o)
	{
		o.parentNode.removeChild(o);
	}

	if( targetElement === document)
		document.write(out);
	else if( $(targetElement) )
		targetElement.innerHTML = out;

	this.HTML = out;

	return out;
}
/**
 * a collection of all Flash instances that were provided 
 * a target-element and a swf name, but thier target was not 
 * found in the dom by the time of the eval of this file.
 * @type Array
 * @private
 */
Flash.postLoadRender = [];

/**
 * fires on load of the window. 
 * attached by Event.observe with the eval of this file
 */
Flash.renderPostLoad = function()
{
	var arr = Flash.postLoadRender;
	for(var i = 0 ; i < arr.length; i++) arr[i].render();
}
Event.observe(window, "load", Flash.renderPostLoad);


/**
 * gets a reference to the node in the dom of the <code>object</code> or <code>embed</code>
 *
 * @param {String(optional)} movieName
 * The ID of the object tag to retrieve. When not provided - assumes the current objectID.
 */
Flash.prototype.getFlashMovieObject = function (movieName)
{
	if( !movieName ) movieName = this.objectID;

	if (window.document[movieName]) 
	{
		return window.document[movieName];
	}
	if (navigator.appName.indexOf("Microsoft Internet")==-1)
	{
		if (document.embeds && document.embeds[movieName])
			return document.embeds[movieName]; 
	}
	else // if (navigator.appName.indexOf("Microsoft Internet")!=-1)
	{
		return document.getElementById(movieName);
	}
}//::: AvatarViewer 00:00:01.1404060

if(!window.GameCatalog)GameCatalog={};GameCatalog.AvatarViewer=Class.create("UA.User");GameCatalog.AvatarViewer.defaultSettings={movie:"/Community/avatars/2.0/FAV.swf",tinyAvatarCashedURL:undefined,tinyAvatarLiveURL:undefined,height:200,width:150,wmode:"transparent",base:"",quality:"high",bgcolor:"#ffffff",menu:false,allowscriptaccess:true,showTypes:""}
GameCatalog.AvatarViewer.internalSettings='channel,targetElement,nickname,cookieData,log,guestAvatarXML,tinyAvatarCashedURL,tinyAvatarLiveURL,movie,showTypes'
GameCatalog.AvatarViewer.prototype.initialize=function(oSettings)
{this.settings=Object.extend(GameCatalog.AvatarViewer.defaultSettings);this.settings=Object.extend(this.settings,oSettings||{});Claim.isString(this.settings.tinyAvatarCashedURL,"default setting [tinyAvatarCashedURL] is not initiated and not provided on oSettings constructor argument.")
Claim.isString(this.settings.tinyAvatarLiveURL,"default setting [tinyAvatarLiveURL] is not initiated and not provided on oSettings constructor argument.")
Claim.isString(this.settings.guestAvatarXML,"default setting [guestAvatarXML] is not initiated and not provided on oSettings constructor argument.")
this.log=this.settings.logger;if(typeof(this.log)=='string')this.log=new Log4Js.Logger("this.log");if(!this.log)this.log=new Log4Js.Logger("AvatarViewer");Claim.isTrue(this.log instanceof Log4Js.Logger,"settings.log can be ither a Log4Js.Logger or a string to be used as logger-name");this.log.debug("creating Flash worker-instance");this.fav=new Flash(this.settings.movie,this.settings,GameCatalog.AvatarViewer.internalSettings);}
GameCatalog.AvatarViewer.prototype.prv_isInternalSettings=function(sSettingName)
{return-1!=GameCatalog.AvatarViewer.internalSettings.indexOf(','+sSettingName.toLowerCase()+',');}
GameCatalog.AvatarViewer.prototype.getCookieData=function()
{return Clearance.getMagic(Clearance.UNCLASSIFIED);}
GameCatalog.AvatarViewer.prototype.useLiveProcessing=function()
{if(this.settings.nickname)
{return false;}
else
{return true;}}
GameCatalog.AvatarViewer.prototype.appendUserIdentification=function(baseUrl)
{if(this.settings.nickname)
{this.log.debug("nickname found on settings object: "+this.settings.nickname);baseUrl=Url.appendParamValue(baseUrl,"channel",this.settings.channel);baseUrl+=("&nickname="+encodeURIComponent(this.settings.nickname));}
else
{var magic=this.settings.cookieData||this.getCookieData();if(!magic)
{this.log.debug("no credentials nor nickname provided - guest avatar assumend");return this.settings.guestAvatarXML;}
this.log.debug("cookieData: "+magic);baseUrl=Url.appendParamValue(baseUrl,"cookiedata",magic);}
return baseUrl;}
GameCatalog.AvatarViewer.prototype.render=function(targetElement)
{if(!targetElement)targetElement=this.settings.targetElement;targetElement=$(targetElement);var useLiveProcessingURL=this.useLiveProcessing();var avatarBaseURLSetting=(useLiveProcessingURL)?"tinyAvatarLiveURL":"tinyAvatarCashedURL";var avatarURL=this.settings[avatarBaseURLSetting];this.log.debug("Selected avatarBaseURL : "+avatarURL);avatarURL=this.appendUserIdentification(avatarURL);this.log.debug("avatarURL : "+avatarURL);this.fav.settings.flashvars=["CurrentAvatarUrl=",escape(avatarURL),"&showmytypes=",escape(this.settings.showTypes)].join("");this.log.info("prepared flashvars: "+this.fav.settings.flashvars);this.fav.settings.flashvars=this.fav.settings.flashvars.replace(/https/gi,'http');this.log.info("flashvars:"+this.fav.settings.flashvars);this.HTML=this.fav.render(targetElement);this.log.debug("avatar viewer HTML: "+this.HTML.replace(/\</g,"&lt;"));return this.HTML;}//::: ChannelConfig 00:00:01.1404060

initLogger = new Log4Js.Logger("Catalog.Congfig"); //----------------------------------------------------------------------------

try{ 
	Claim.isObject(GameCatalog.AvatarViewer, "the script that defines GameCatalog.AvatarStudio must be initiated before the call to the script that configs catalog utils"); 
	Claim.isObject(GameCatalog.AvatarViewer.defaultSettings,"the script that defines GameCatalog.AvatarStudio.defaultSettings must be initiated before the call to the script that configs catalog utils"); 
	Object.extend
	( 
		GameCatalog.AvatarViewer.defaultSettings , 
		{
			tinyAvatarLiveURL : Url.appendParamValue(UA.User.prototype.GET_AVATAR_URL , "type","tiny") 
			,tinyAvatarCashedURL: Url.appendParamValue(UA.User.prototype.GET_CACHED_AVATAR_URL, "type", "tiny") 
			,guestAvatarXML : "//config/NoAvatar.xml"
			,showTypes : "~glasses~hair~face~skull~shirt~beard~background~body~jewelry~hats~"
			,movie : "/community/avatars/2.0/FAV.swf" ,channel : UA.CHANNEL 
		} 
	);

	GameCatalog.AvatarViewer.initiated = true; 
	}
	catch(e){ initLogger.warn("Failed initiating GameCatalog.AvatarViewer: " + Serialize(e) )
} 
//----------------------------------------------------------------------------
//::: Legacy JavaScript 00:00:01.1560280

/************ START /javascript/2100/TC.Utils.js ***********/


/* === TMP FIXES ON PRODUCT UTILS === */
//-=-=-=-=-=- Enhances on Object -=-=-=-=-=-
Object.clone = function(obj) {
    return this.extend({}, obj);
}
/**
* @param {variant} value
* @returns pseodo-JSON serialization of the variant
* @type string
*/
Object.serialize = function(value) {
    var arrObjs = [];
    // ser is defined here so it could see arrObjs, 
    // and make sure there is no endless recursion, 
    // or objects that are serialized twice in a same tree
    function ser(v) {
        switch (typeof (v)) {
            case 'NaN': return "NaN";
            case 'undefined': return "undefined";
            case 'boolean': return (v).toString();
            case 'number': return (isFinite(v)) ? (v).toString() : "\"Infinity\"";
            case 'string': return "\"" + v.replace(/\"/g, "\\\"") + "\"";
            case 'function': return "{function}";
        }
        // handle objects
        if (v == null) return "null";
        if (v instanceof Date) return "new Date(" + v.getTime() + ")";
        if (v instanceof Array) {
            var i, arr = [];

            if (GameCatalog.TagSkuLinks
			   && v.byWeight == GameCatalog.TagSkuLinks.prototype.byWeight
 			   )
                return "[GameCatalog.TagSkuLinks,length: " + v.length + "]";

            if (GameCatalog.SkuTagLinks
			   && v.byWeight == GameCatalog.SkuTagLinks.prototype.byWeight)
                return "[GameCatalog.SkuTagLinks,length: " + v.length + "]";

            for (i = 0; i < v.length; i++)
                arr[arr.length] = ser(v[i]);

            return "[" + arr.toString() + "]";
        }

        //serialize an unknown object
        // - prevent recursive serialization
        if (arrObjs.indexOf(v) != -1) {
            return "\"*ref" + ((v.id) ? "-id:" + v.id : ((v.name) ? "-name:" + v.name : ":" + v.toString())) + "\"";
        }
        arrObjs[arrObjs.length] = v;


        //handle html-dom-nodes
        if (v.parentNode && v.attributes && (v.children || v.childNodes) && v.tagName) {
            var i, e = { tagName: v.tagName
						, parent: v.parentNode.tagName
						, innerHTML: "\"" + v.innerHTML.replace(/"/g, "\\\"").replace(/</g, "&lt;") + "\""
            };
            for (i = 0; i < v.attributes.length; i++)
                if (v.attributes[i].value && v.attributes[i].value != "null")
                e[v.attributes[i].name] = v.attributes[i].value;

            return ser(e);
        }

        // - do the serializing...
        var each, arr = [];
        // Note: the for-each could throw for activeX objects and such
        try {
            for (each in v) {
                if (null !== v[each])
                    arr[arr.length] = each + ":" + ser(v[each]);
            }
            return "{" + arr.toString() + "}";

        } catch (ex) {
            return "\"-error in serializing: " + ex.message + "-\""
        }
    }

    return ser(value);
}

/**
* copies properties to destination from source only when they are totally undefined on the destination.
*
* @param {object} destination
*
* @param {object} source
*/
Object.safeExtend = function(destination, source) {
    for (property in source) {
        if (undefined === destination[property])
            destination[property] = source[property];
    }
    return destination;
}

//-=-=-=-=-=- /Enhances on Object -=-=-=-=-=-
//-=-=-=-=-=- Enhances on Class -=-=-=-=-=-
/**
* Creates a constructor function.
* When provided a parent - it createa a subclass of the provided parent,
* or throws an error.
* 
* @param {string|function(optional)} parent
*  The parent class name in string, or a reference to the parent class constructor
*/
// - fix: allow it to accept (parent) and link inheritance.
Class.create = function(parent) {
    var fConstr = function() {
        var arrCtors = [];
        var fConstructor = this.constructor;
        do {
            //fConstructor could be a system class that doesn't implement initialize
            if ('function' == typeof (fConstructor.prototype.initialize))
                arrCtors[arrCtors.length] = fConstructor.prototype.initialize;
            fConstructor = fConstructor.parentConstructor;
        }
        while (typeof (fConstructor) == 'function');

        for (var i = arrCtors.length; i-- > 0; ) {
            arrCtors[i].apply(this, arguments);
        }
    }

    if (parent) {
        return Class.linkInheritance(parent, fConstr);
    }

    return fConstr;
}
/**
* @param {function|object|string} parent
*  A parent class, an instance of it, or a string representing its class name
*
* @param {function} subclass
*  The subclass function
*/
// - new.
Class.linkInheritance = function(parent, subclass) {
    if (typeof (parent) == 'string')
        parent = eval(parent);
    Claim.check(typeof (parent) == 'object'
			   || typeof (parent) == 'function'
			   , "'parent' is a function or an object"
			   , "Class.linkInheritance(parent)")
    Claim.isFunction(subclass, "Class.linkInheritance(subclass)");

    //copy all static members
    subclass = Object.extend(subclass, parent);
    delete subclass.AsPrototype;

    //keep the parent constructor in parentConstructor
    subclass.parentConstructor = parent;

    //--THROWS FRIENDLY ERRORS WHEN MISUSED--
    subclass.prototype = Class.AsPrototype(parent);

    //override the 'constructor' attribute on the new prototype instance 
    //(originally it was the parent constructor)
    subclass.prototype.constructor = subclass;

    return subclass;
}
/**
* Mostly for internal use, but can be used to determine wether a class is inheritable.
* When the provided parameter is not inheritable - it throws an error.
*
* @param {string|function|object} fClass
*  A string evaluates to a class or a the class itselfs
*
* Function:
*  if
*		can be instantiated using a default constructor
* 			OR
* 		parent.AsPrototype() returns a valid instance
* 			OR
* 		parent === Object
*	  creates an instance, and puts initialize_base on it.
*
* String:
*  if	
*		evaluates to a valid class name
* 	carrSuperclasss recursively on evaluation's returned value
*
* Object: 
*  creates a shellow copy, and puts initialize_base on it.
*/
// - new.
Class.AsPrototype = function(fClass) {
    switch (typeof (fClass)) {
        case 'string':
            if (window[fClass] != null
			   && window[fClass] === eval(fClass)) {
                if (typeof (eval(fClass)) != 'function') throw new Error("'" + fClass + "' does not evaluates to a valid class");
                return Class.AsPrototype(eval(fClass));
            }
        case 'function':
            var oProto;
            if (fClass === Object) return {};

            if (typeof (fClass.AsPrototype) == 'function') {
                oProto = fClass.AsPrototype();
                if (typeof (oProto) != 'object') throw new Error("provided class implements.AsPrototype() but it did not return an instance.");
            }
            else {
                try {
                    oProto = new fClass();
                }
                catch (ex) {
                    throw new Error("Class.AsPrototype(fClass) Failed to instantiate 'fClass' with default constructor. \n\nError message: " + ex.message);
                }
            }
            return oProto;

        case 'object':
            return Object.extend({}, fClass);

        default:
            throw new Error("A prototype can be extracted only from one of the followings: \n\t- an object instance \n\t- a valid constractor function \n\t- a string evaluates to ither one of the above");
    }
}

/**
*
*/
Class.enhancePrototype = function(fClass, oInterface) {
    Claim.check(typeof (fClass) == 'function'
				, "Class.enhancePrototype(fClass,oInterface) - fClass"
				, "fClass must be a function"
				);
    Claim.check(oInterface && typeof (oInterface) == 'object'
				, "Class.enhancePrototype(fClass,oInterface) - oInterface"
				, "oInterface must be an object"
				);

    return Object.extend(fClass.prototype, oInterface);
}

/**
*
*/
Class.enhanceSingleton = function(oSingleton, oInterface) {
    Claim.check(oTargetClass && typeof (oTargetClass) == 'object' || typeof (oTargetClass) == 'function'
				, "Class.enhance(oSingleton)"
				, "oTargetClass must be a function"
				);
    Claim.check(oInterface && typeof (oInterface) == 'object'
				, "Class.enhancePrototype(fClass,oInterface) - oInterface"
				, "oInterface must be an object"
				);

    return Object.extend(oSingleton, oInterface);
}
Class.enhance = function(fClass /*, param1, param2, param3 ... */) {
    var oInterface;
    for (var i = 1; i < arguments.length; i++) {
        oInterface = arguments[i];
        try { fClass = this.enhanceSingleton(fClass, oInterface); } catch (ex) { }
        try { fClass.prototype = this.enhancePrototype(fClass, oInterface); } catch (ex) { }
    }
    return fClass;
}
//-=-=-=-=-=- /Enhances on Class -=-=-=-=-=-
//-=-=-=-=-=- Enhances on Element -=-=-=-=-=-
/**
* sets the text of the provided element, according to its tag-name
* input fields, text-area  - by .value
* the rest - innerHMTL
*
* @param {Element} e - the DOM element ID
* @param {string}	sText
*/
Element.setText = function(e, sText) {
    var tag = e.tagName.toUpperCase();
    switch (tag) {
        case "INPUT":
        case "TEXTAREA":
            e.value = sText;
            break;
        case "SELECT":
            //TODO: - decide what to do if the sText doesnt match any value of the select element
            e.value = sText;
            break;
        default: /*DIV, SPAN, TD, A, H1-H5, and all the rest*/
            try {
                e.innerHTML = sText;
            } catch (ex) {
                try {
                    if (typeof e.innerText == 'undefined')
                        e.textContent = sText;
                    else
                        e.innerText = sText;
                } catch (ex) {
                    this.log.error("Element.setText: failed to set to element the text: " + sText);
                }
            }
    }
}
/**
* gets the text of the provided element, according to its tag-name
* input fields, text-area  - by .value
* the rest - innerHMTL
*
* @param {Element} oElement - the DOM element ID
*/
Element.getText = function(oElement) {
    switch (oElement.tagName) {
        case "INPUT":
            if (oElement.type == "checkbox")
                return (oElement.checked) ? oElement.value : "";
            //no break! deliberated case sliding!
        case "TEXTAREA":
        case "SELECT":
            strTemplate = oElement.value;
            break;
        default: /*DIV,SPAN,H1-6,TD,CETNER,B,I,U,and all the rest*/
            strTemplate = oElement.innerHTML;
    }
}
//-=-=-=-=-=- /Enhances on Element -=-=-=-=-=-
//-=-=-=-=-=- Enhances on Log4Js -=-=-=-=-=-
/**
* Initiates a general cookie.
* To be pasted in the address bar like this:
*    Javascript:Log4Js.pop();
*
* @param {object(optional)} conf 
* The configuration object. When not provided - initiates a default one for popup.
*/
// - new.
Log4Js.pop = function(conf) {
    if (!conf || typeof (conf) != 'object') {
        conf = { anchorsByName: { "*": ["t1"]
                                  , Claim: ["t2"]
        }
                , targetByAnchor: { t1: new Log4Js.PopupTarget(Log4Js.ALL, "log4js-%U-%T", true)
                                  , t2: new Log4Js.PopupTarget(Log4Js.FATAL, "log4js-%U-%T", true)
                }
        };
    }
    Cookies.set("log4js.config", conf, {});
    this.fromConfig(conf);
}
/**
* Adds a logging anchor by name
*
* @param {string} sClassName
* The name of the logged element
* 
* @param {string} enLEVEL
* The "enum" name of the warn level
*/
// - new.
Log4Js.add = function(sClassName, enLEVEL) {
    Claim.isString(sClassName, "Log4Js.add(sClassName, enLEVEL) - sClassName must be a string");
    Claim.isString(enLEVEL, "Log4Js.add(sClassName, enLEVEL) - enLEVEL must Log Level ALL, DEBUG, WARN, ...");
    var iLevel = this[enLEVEL.toUpperCase()];
    Claim.isNumber(iLevel, "Log4Js.add(sClassName, enLEVEL) - Log4Js." + enLEVEL + " is not a valid warn-level");
    Claim.check(iLevel >= 0 && iLevel <= 6, "0 <= iLevel <= 6", "Log4Js.add(sClassName, enLEVEL) - Log4Js[enLEVEL must be between 0 to 6");

    var conf = this.toConfig();
    conf.targetByAnchor.newAnchor = new Log4Js.PopupTarget(iLevel, "log4js-%U-%T", true)
    conf.anchorsByName[sClassName] = ["newAnchor"];
    this.pop(conf);
}
/**
* Removes an anchor by name
*
* @param {string} sClassName
* The name of the logged element
*/
// - new.
Log4Js.clear = function(sClassName) {
    Claim.isString(sClassName, "Log4Js.clear(sClassName) - sClassName must be a string");
    var conf = this.toConfig();
    delete conf.anchorsByName[sClassName];
    this.pop(conf);
}
/**
* stops the logging by clearing the log4js configuration.
* Done by setting the configuration to a single anchor - all, pointed to NONE.
*
*/
// - new.
Log4Js.stop = function() {
    var conf = { anchorsByName: { "*": ["t1"]
    }
                , targetByAnchor: { t1: new Log4Js.PopupTarget(Log4Js.NONE, "log4js-%U-%T", true)
                }
    };
    Cookies.set("log4js.config", conf, {});
    this.fromConfig(conf);
}
//-=-=-=-=-=- /Enhances on Log4Js -=-=-=-=-=-
//-=-=-=-=-=- Enhances on Claim -=-=-=-=-=-
/**
* Claims the provided object to be a function
* Throws an error if its not
*
* @param {object} object
* The tested object
*
* @param {string} comment
* String comment for the Error and for the log
*/
// - new.
Claim.isFunction = function(object, comment) {
    
    {
        Claim.check(typeof (object) == 'function'
               , "isFunction(" + Claim.valueType(object) + ")"
               , comment)
    } 
}
Claim.isLiveObject = function(object, comment) {
    Claim.check(null != object
				&& typeof (object) == 'object'
				, "isLiveObject(" + object + ")"
				, comment)
}
//-=-=-=-=-=- /Enhances on Claim -=-=-=-=-=-
//-=-=-=-=-=- Enhances on Cookies -=-=-=-=-=-
Cookies.pop = function() {
    var each, s = [];
    for (each in this.rawByName) {
        s[s.length] = each
        s[s.length] = ":"
        s[s.length] = this.rawByName[each]
        s[s.length] = "\n"
    }
    alert(unescape(s.join("")));
}
//-=-=-=-=-=- /Enhances on Cookies -=-=-=-=-=-
/* === /TMP FIXES ON PRODUCT UTILS === */

// --- Enhance String.prototype -----------------------------------
/**
* An empty string constant
*/
String.empty = String.Empty = "";
/**
* Populates a template: replaces all provided place-holders in a string, with values.
*
* @param {object} oMapping
* A hash in which every key represents a place-holder in the string to be replaced with its correlating value
*/
String.prototype.populateTemplate = function(oMapping) {
    Claim.isObject(oMapping, "String.populateTemplate(..,oMapping,..)");

    var sTemplate, placehoder, replacement;

    sTemplate = String(this);

    for (placeholder in oMapping) {
        replacement = oMapping[placeholder];
        sTemplate = sTemplate.replace(new RegExp(placeholder, "g"), replacement);
    }
    return sTemplate;
}
String.prototype.beutifySerialization = function() {
    var out = []
	  , indent = ""
	  , i
	  , arr = this.split("");

    for (i = 0; i < arr.length; i++) {
        switch (arr[i]) {
            case "{":
                indent += "\t";
                out[out.length] = "\n" + indent;
                out[out.length] = arr[i] + "\t";
                break;
            case "}":
                out[out.length] = "\n" + indent;
                out[out.length] = arr[i] + "\t";
                indent = indent.substr(1);
                break;
            case "[":
                indent += "\t";
                out[out.length] = "\n" + indent;
                out[out.length] = arr[i] + "\t";
                break;
            case "]":
                out[out.length] = "\n" + indent;
                out[out.length] = arr[i] + "\t";
                indent = indent.substr(1);
                break;
            case ",":
                out[out.length] = "\n" + indent;
                out[out.length] = arr[i] + "\t";
                break;
            default:
                out[out.length] = arr[i];
        }
    }
    return out.join("");
}
/**
* Binds a template: replaces all indicated placeholders with data. 
* Data comes from data-properties on the oDataSource, 
* and the mapping between placeholders in the string and the data-properties 
* is provided in the oMapping parameter.
*
* @param {object} oMapping
* A hash, in which every key is a placeholder in the string, 
* and its correlating value can be:
* - A string representing a data-property on the data-srource in oDataSource
* - A function that returns value as a function of the oDataSource
* - Any other value will be casted to string to return the value, and the returned value will be used, regardles to the data-source.
*
* @param {object} oDataSource
* A data-object by which to bind the template
*
* @param {object(optional)} oLog
* When provided - the logging of this execution is emitted to the provided instance.
* Otherwise - to a casual instance, named "String.bindTemplate".
*/
String.prototype.bindTemplate = function(oMapping, oData, oLog) {
    Claim.isObject(oMapping, "String.bindTemplate(..,oMapping,..)");
    Claim.isObject(oData, "String.bindTemplate(..,oData)");

    var oDataSource = ('object' == typeof (oData.dataItem)) ? oData.dataItem : oData;

    var sTemplate, placehoder, attribute, replacment;
    var log = (oLog && oLog instanceof Log4Js.Logger) ? oLog : new Log4Js.Logger("String.bindTemplate");

    sTemplate = this.toString();

    for (placehoder in oMapping) {
        if (this.indexOf(placehoder) == -1) {
            log.debug("in bindTemplate(...) - placeholder '" + placehoder + "' is not found in bound template");
            continue;
        }

        attribute = oMapping[placehoder];
        if (undefined == attribute || null == attribute) {
            log.warn("in bindTemplate(...) oMapping dictionary specifies a placeholder without providing its data-attribute name: " + placehoder);
            continue;
        }

        switch (typeof (attribute)) {
            case 'function':
                try {
                    replacement = attribute(oDataSource, log);
                } catch (ex) {
                    log.error("String.bindTemplate - Error in mapping-handler for " + placehoder + " : " + attribute.toString());
                    throw ex;
                }
                break;

            case 'string':
                replacement = oDataSource[attribute];
                if ('function' == typeof (replacement)) {
                    replacement = replacement.apply(oDataSource);
                }
                else if (null == replacement) {
                    if (oData != oDataSource && null != oData[attribute]) {
                        replacement = oData[attribute];
                        if ('function' == typeof (replacement)) {
                            replacement = replacement.apply(oData)
                        }

                    }

                    if (null == replacement) {
                        log.warn("in bindTemplate(...) oMapping dictionary specifies a property that does not exist on the provided oDataSource. Placehoder: " + placehoder + ", using the name of the attribute: " + attribute);
                        replacement = attribute;
                    }

                }
                break;

            default:
                replacement = String(attribute);

        }

        //replacment = replacment.replace(/\$/g,"");
        sTemplate = sTemplate.replace(new RegExp(placehoder, "g"), replacement);
    }
    return sTemplate;
}
/**
* returns the string without spaces in the start or at the end.
*/
String.prototype.trim = function() {
    var iStart = -1, iEnd = this.length;
    while (this.charAt(++iStart) == ' ');
    while (this.charAt(--iEnd) == ' ');
    if (iStart == iEnd && this.charAt(iStart) != ' ') return this.substr(iStart, 1);
    return this.substring(iStart, iEnd + 1);
}

/**
* returns the current string padded on the left with the provided padding char to the specified length
* @param {string} c - the padding char
* @param {number} iLength - the length the padded string should reach
*/
String.prototype.leftPad = function(c, iLength) {
    s = this.toString();
    while (s.length < iLength) s = c + s;
    return s;
}
/**
* @param {String} substr The string to search
*/
String.prototype.contains = function(substr) {
    if (substr === undefined || substr === null) return false;
    return this.indexOf(substr) != -1;
}
// --- /Enhance String.prototype -----------------------------------

// --- Enhance Number.prototype -----------------------------------
//TODO: handle formatting of decimals. (0.34874873)
/**
* returns the formatted string swith comas.
**/
Number.milleSeperator = ",";
//Number.fragmentsSeperator = ".";
Number.prototype.format = function() {
    var iNumber = this;
    var sFormatted = "", psik = "";
    var s3Digits, i3Digits;
    while (iNumber > 0) {
        i3Digits = iNumber % 1000;

        s3Digits = String(i3Digits)

        iNumber = Math.floor(iNumber / 1000);
        if (iNumber > 0) {
            if (i3Digits < 100) {
                s3Digits = "0" + s3Digits;
                if (i3Digits < 10) {
                    s3Digits = "0" + s3Digits;
                }
            }
        }

        sFormatted = s3Digits + psik + sFormatted;
        psik = Number.milleSeperator;

    }

    return (sFormatted.length) ? sFormatted : "0";
}

/**
* returns the current number padded on the left with the provided padding char to the specified length
* @param {string} c - the padding char
* @param {number} iLength - the length the padded string should reach
* @param {number} iBase - the count base to format by it to string 
*/
Number.prototype.leftPad = function(c, iLength, iBase) {
    if (iBase === undefined) return this.toString().leftPad(c, iLength);

    iBase == parseInt(iBase);
    if (!iBase || iBase == NaN || iBase < 2) iBase == 10;

    return this.toString(iBase).leftPad(c, iLength);
}
// --- /Enhance Number.prototype -----------------------------------

// --- Enhance Array.prototype------------------------------------------------------------
/**
* gets a part of the array of a maximum size.<br>
* <a target="_blank" href="/Js/units/reference/_Infra/Array.htm#cut">see Ref-Impl</a>
* @returns a slice of the array, starting in the provided iStart, and of maximum iCount elements.
*
* @param {number} iStart    index to start from 
* @param {number} iCount    maximum elements to fetch
* 
* @type Array
*/
Array.prototype.cut = function(iStart, iCount) {
    var iEnd = undefined;
    if (iStart == undefined) iStart = 0;
    iEnd = (iCount == undefined) ? this.length : iStart + iCount;
    return this.slice(iStart, iEnd);
}
// --- /Enhance Array.prototype------------------------------------------------------------

if (!window.Const) Const = {};
Object.extend(Const,
				{ UNSET_STRING: "-UNSET-STRING-"
				, UNSET_NUMBER: NaN
				, UNSET_OBJECT: undefined
				}
			 );



/* === TC Namesapce ============================================================ */
if (!window["TC"])
    window.TC = {};

/**
* Synonym for accessing the catalog by-sky hash
*/
TC.SKUs = GameCatalog.Game.All.BySku;

/**
* Synonym for accessing the catalog all-games-on-client array
*/
TC.SKUs.All = GameCatalog.Game.All;


/**
* Expects a data-object, with a property named "sku".
* If such sku exists in the catalog - it copies all game properties 
* from the catalog game instance to the provided object.
*
* @param {object} oTarget
* The data-object to extend
*
* @param {number(optional)} sku
* When no property "sku" defined on parameter oTarget - used as the sku to search by 
*
* @returns the enhanced object, or null when the sku does not exist in the catalog
*/
TC.SKUs.extendDataFromSKU = function(oTarget, sku) {
    if (oTarget.sku) sku = oTarget.sku;
    Claim.isNumber(parseInt(sku), 'TC.SKUs.extendDataFromSKU(...) - the sku of the game to enhance from should be provided ither as a property "sku" on the provided oTarget, or as a second parameter');

    var oGame = this[sku];
    if (!oGame)
        return null;

    return Object.extend(oTarget, oGame);
}



/**
* Synonym for accessing the catalog tags by internal-name hash
*/
if (GameCatalog.Tag) TC.Tags = GameCatalog.Tag.All;



// --- TC.OnlinePlayers -----------------------------------
/**
*
*/
TC.OnlinePlayers = {}
/**
*
*/
TC.OnlinePlayers.log = new Log4Js.Logger("TC.OnlinePlayers");
/*
* Defaults settings of the behavious of this component. For customization override
* the required property in the projectal phase
*/
TC.OnlinePlayers.settings = { onlinePlayersUnavailable: "N/A"
};
/**
*
*/
TC.OnlinePlayers.writeCommunity = function() {
    this.prv_writeOnlineNumber(PresenceCatalog);
}
/**
*
*/
TC.OnlinePlayers.writeByCategory = function(categoryCode) {
    var oByCat;
    try {
        oByCat = PresenceCatalog.Rooms.All.ByCategory[categoryCode];
    }
    catch (ex) {
        this.log.error("Exception in access to PresenceCatalog.Rooms.All.ByCategory[" + categoryCode + "]: " + ex.message);
    }
    this.prv_writeOnlineNumber(oByCat);

}
/**
*
*/
TC.OnlinePlayers.writeBySku = function(skuCode) {
    var oBySku;
    try {
        oBySku = PresenceCatalog.Lobbies.All.BySku[skuCode];
    }
    catch (ex) {
        this.log.error("Exception in access to PresenceCatalog.Lobbies.All.BySku[" + skuCode + " ]: " + ex.message);
    }

    this.prv_writeOnlineNumber(oBySku);

}
/**
*
*/
TC.OnlinePlayers.prv_writeOnlineNumber = function(oDataObject) {
    var sOut = this.settings.onlinePlayersUnavailable
    if (oDataObject && null != oDataObject.NumberOfPlayers) {
        sOut = oDataObject.NumberOfPlayers;
        this.log.info("Number Of ActivePlayers: " + sOut);
    }
    else {
        this.log.info("Number Of ActivePlayers not found. oDataObject:" + Object.serialize(oDataObject));
    }

    document.write(sOut);
}
TC.OnlinePlayers.writeByRoom = function(roomGuid) {
    
    {
        var oByRoom;
        try {
            oByRoom = PresenceCatalog.Rooms.All.ByRoom[roomGuid];
        }
        catch (ex) {
            this.log.error("Exception in access to PresenceCatalog.Rooms.All.ByRoom[" + roomGuid + "]: " + ex.message);
        }
        this.prv_writeOnlineNumber(oByRoom);
    } 
}
//----------------------------------------------------------------------------
TC.Omniture = {}
TC.Omniture.trackRemoteUrl = Const.UNSET_STRING;
//----------------------------------------------------------------------------


/**
* @requires Class => from prototype
* @requires Log4Net.Logger => from common
* @requires Object.serialize => currenly a projectile cross-project enhancement (attached).
* @interface
* Interface-implementation to enhance classes with event dispathching mechanism.
* The mechanism allows a single handler that returns a value, or an event stack.
* The mechanism has an error capturing mechanism that directs them to log.
*
* @CodeSampleStart
* //Usage:
* MyEventingClass = Class.create();
* MyEventingClass.prototype = Object.extend(MyEventingClass.prototype, IEventDispatcher);
*
* MyEventingClass.doSomethingThreeTimes = function(i)
* {
*	   i = (i)?i:0;
 
*     this.dispatch("onSomething",i);
*     this.dispatch("onSomething",i + 1, i);
*     this.r = this.dispatch("onSomething",i + 2, i + 1, i);
*	   this.dispatch("onFinish", this.r);
* }
* //example 1:
* obj = new MyEventingClass();
* obj.onSomething = function(){
*	  alert(arguments.toString());
*    return arguments[2];
* }
* obj.onFinish = function(result){
*    if(0 == result % 2 )
*		this.r += 1;
*
*	  alert("finishing with : "  + this.r);
* }
* obj.doSomethingThreeTimes( 23 );
*
* //example 2:
* obj = new MyEventingClass();
* obj.attachEvent("onSomething", function(){ alert("handler 1: " + arguments.toString());} );
* obj.attachEvent("onSomething", function(){ alert("handler 2: " + arguments.toString());} );
*
* obj.doSomethingThreeTimes( 23 );
* @CodeSampleEnd
*/

IEventDispatcher = {};

/**
* Accept the event name as the first parameter, and dispatches it with the rest of the arguments stack.
* Check for a registered event handler. 
* A handler could be a simple handler, or a handlers-stack.
* When the event has a single handler ? it can return value.
*
* Execution flow:
* When no event handler is found - nothing is done, and null is returned.
* When event handler is found -
* 1 - convert all arguments without the event name to a new array
* 2 - execute the handler with all the arguments on the new array
* 3 - when an event returns a value - it returns it.
*
* Throws: when the execution of the handler throws, what the handler thew.
*
* When the dispatched object features a Log4Js.Logger, 
* the following log entries are written on the objects logger:
*   - [info] no event handler is found
*	 - [info] success of the dispathed event, 
*	 - [error] error on execution of the event handler, 
*
* TODO: allow the event be not only a hanler but a handlers array too
*
* @param {string} sEventName
* The name of the hadler-reference property
*
* @param {*} arguments[1],arguments[2],arguments[3]...
* The arguments for the event handler
*/
IEventDispatcher.dispatch = function(sEventName/*, param1, param2, param3 ... */) {
    Claim.isString(sEventName, "IEventDispatcher.dispatch(sEventName, ...) - sEventName must be a string");

    //check for a registered event handler
    var fEventHandler = this[sEventName];
    var isHandlerStack = 'object' == typeof (fEventHandler)
						&& fEventHandler.constructor == Array;


    if ('function' != typeof (fEventHandler) && !isHandlerStack) {
        if (this.log instanceof Log4Js.Logger) this.log.info("Dispatch: Event " + sEventName + " is not implemented.");
        return;
    }

    //when event handler is found - convert all arguments without the event name to a new array
    var args = [];
    for (var i = 1; i < arguments.length; i++) {
        args[i - 1] = arguments[i];
    }

    // if the found handler is an event-stack - dispatch all of them, and there is no returned value.		
    if (isHandlerStack) {
        this.log.info("detected handlers stack for event: " + sEventName);
        for (var i = 0; i < fEventHandler.length; i++) {
            this.dispatchHandler(sEventName, fEventHandler[i], args);
        }
        return;
    }

    // if the found handler is a single function-reference - dispatch it, and there is no returned value.
    return this.dispatchHandler(sEventName, fEventHandler, args);
}
/**
* @private
* applies the provided handler on the current instance, with the provided argument-stack
* Errors and exceptions buble up, however, before that, if the current instance has a this.log as Log4Js.Logger - they are written to that log.
*
* @param {function} fEventHandler
* The function-reference to apply on the current instance
*
* @param {object} args
* The arguments stack of the function * 
*/
IEventDispatcher.dispatchHandler = function(sEventName, fEventHandler, args) {
    // execute the handler with all the rest of the arguments
    try {
        var retVal = fEventHandler.apply(this, args);
        //if(this.log instanceof Log4Js.Logger) this.log.info("after event " +sEventName+ ": " + Object.serialize(args) + ". returned value: " + retVal);
        return retVal;
    }
    catch (ex) {
        if (this.log instanceof Log4Js.Logger) this.log.error("event " + sEventName + " failed:" + Object.serialize(ex));
        if (this.ignoreEventErrors == true) return;
        throw ex;
    }
}

/**
* attaches the hanlder to the named event, using an event stack.
* The IEventDispatcher.dispatch knows to recognize this, and 
* applies the event stack by its registration order (LIFO).
* 
* @param {string} sEventName
* The name of the event
*
* @param {function} fHandler
* The handler function
*/
IEventDispatcher.attachEvent = function(sEventName, fHandler) {
    Claim.isString(sEventName, "IEventDispatcher.attachEvent(sEventName,..) - sEventName is expected to be a string representing the event name");
    Claim.isFunction(fHandler, "IEventDispatcher.attachEvent(...,fHandler) - fHandler is expected to be the event handler function");
    var oEvent = this[sEventName];

    if (oEvent === undefined || oEvent === null) {
        this[sEventName] = fHandler;
        return;
    }

    switch (typeof (oEvent)) {
        case 'function':
            oEvent = this[sEventName] = [this[sEventName]];
            /* !!no break!! deliberate case sliding. */
        case 'object':
            if (oEvent instanceof Array) {
                this[sEventName][this[sEventName].length] = fHandler;
                return;
            }

        default: //string, boolean, number, objects, and so on...
            sEventName += " is not an event, but: " + Object.serialize(oEvent);
            this.log.error(sEventName);
            throw new Error(sEventName);
    }
}

/**
* @namespace TC.Controls
*
*/
TC.Controls = {}
/**
* @private
* @returns a RegExp instance to execute a search of a simple containing tag in an HTML string
*
* @param {string} sTagName
* The name of the simple containinig tag to find
*/
TC.Controls.tagRegExpFinder = function(sTagName) {
    return new RegExp("\<" + sTagName + "\>([\\w\\W]*)\<\/" + sTagName + "\>", "gi");
}
/**
* @returns the HTML contained by the specified tag.
* The tag has to be simple, means - with no attributes or spaces between its tringular braces.
*
* @param {string} sHTMLString
* The HTML string to be searched in
*
* @param {string} sInnerTag
* The tag containing the text to extract from the big HTML string
*/
TC.Controls.getInnerTag = function(sHTMLString, sInnerTag) {
    try {
        return this.tagRegExpFinder(sInnerTag).exec(sHTMLString)[1];
    }
    catch (ex) {
        return null;
    }
}
/**
* @class TC.Controls.Repeater
* 
*
*/
TC.Controls.Repeater = Class.create();
TC.Controls.Repeater = Class.enhance(TC.Controls.Repeater, IEventDispatcher);
/**
* mapping of tag-names to template elements
*
*/
TC.Controls.Repeater.defaultParseTags = { header: "header"
										, item: "item"
										, alternateItem: "alternate"
										, seperator: "seperator"
										, footer: "footer"
										, noData: "noData"
};
/**
* @constructor
*
* @param {string} sTemplateString
*
* @param {Log4Js.Logger(optional)} oLog
*
* @param {object(optional)} oParseTags
*
*/
TC.Controls.Repeater.prototype.initialize = function(sTemplateString, oLog, oParseTags) {
    this.log = (oLog && oLog instanceof Log4Js.Logger) ? oLog : new Log4Js.Logger("Repeater");

    Claim.isString(sTemplateString, "sTemplateString is expected to be the template HTML string");
    this.templateString = sTemplateString;

    if (!oParseTags)
        oParseTags = Object.clone(this.constructor.defaultParseTags);
    else
        oParseTags = Object.extend(Object.clone(this.constructor.defaultParseTags), oParseTags);

    this.dispatch("onInit", oParseTags);

    this.templates = {};
    var each;
    for (each in oParseTags) {
        this.templates[each] = TC.Controls.getInnerTag(this.templateString, oParseTags[each]) || "";
        this.log.debug(each + "-template:" + this.templates[each].replace(/</g, "&lt;"));
    }

    this.dispatch("onLoad");
}
/**
*
*
*/
TC.Controls.Repeater.prototype.dataBind = function(oMapping, oDataSource) {
    if (oDataSource) this.dataSource = oDataSource;
    if (oMapping) this.bindMapping = oMapping;

    Claim.isLiveObject(this.bindMapping, "Mapping must be an object. Ither provide it as a first argument, or set the property: rpt.mapping");
    Claim.isArray(this.dataSource, "DataSource must be an array. Ither provide it as a second argument, or set the property: rpt.dataSource");
    var i, iIndex, arrBoundItems = [];

    this.dispatch("onDataBind", this.dataSource);

    for (i = 0; i < oDataSource.length; i++) {
        iIndex = arrBoundItems.length;
        var item = { dataItemIndex: i
					, itemIndex: iIndex
					, dataItem: oDataSource[i]
					, template: (this.templates.alternateItem && iIndex % 2) ? this.templates.alternateItem : this.templates.item
					, mapping: Object.clone(this.bindMapping)
					, skipItem: false
        }

        this.dispatch("onItemDataBound", item);
        if (true == item.skipItem)
            continue;

        arrBoundItems[arrBoundItems.length] = item.template.bindTemplate(item.mapping, item.dataItem);
    }

    this.content = { header: this.templates.header
					, seperator: this.templates.seperator
					, footer: this.templates.footer
					, items: arrBoundItems
					, noData: this.templates.noData
					, toString: function() {
					    return this.header
										 + ((this.items.length) ?
											 this.items.join(this.seperator) : this.noData
										   )
										 + this.footer;
					}
    };

    if (0 == this.content.items.length) {
        this.dispatch("onNoDataFound");
    }

    this.dispatch("onDataBound", this.content);

    return this.content;
}
/**
*
*
*/
TC.Controls.Repeater.prototype.render = function(oTargetElement, oMapping, oDataSource) {
    this.log.debug("Repeater - rendering");
    if (oTargetElement !== null) Claim.isObject(oTargetElement, "oTargetElement can be an HTML element or the document object, or null");

    if (!this.content
	   || oMapping && oDataSource)
        this.content = this.dataBind(oMapping, oDataSource);

    this.targetElement = oTargetElement;

    this.dispatch("onRender", this.content);

    var strHTML = this.content.toString();
    if (oTargetElement) {
        if (oTargetElement.write === document.write) {
            oTargetElement.write(strHTML);
        } else {
            Element.setText(oTargetElement, strHTML);
        }
    }

    this.log.info("Repeater - render complete");
    return strHTML;
}

/**
* Adds the specified url to the favorites list of IE or to the bookmark of Mozilla/Firefox
* @param {string} url
* the url to add to the favorites list of the cross-browser
* @param {string} displayName
* the display text of the url
*/
TC.AddFavorite = function(url, displayName) {

    if (window.external) {/* IE */
        window.external.AddFavorite(url, displayName);
    } else if (window.sidebar) { /* Mozilla */
        window.sidebar.addPanel(displayName, url, "");
    }
}


if (!window.UI) UI = {};
if (!UI.Avatar) UI.Avatar = {};
/**
*
* enum for avatar sizes
*/
UI.Avatar.Size = {};
UI.Avatar.Size.Studio = { name: "Studio" };
UI.Avatar.Size.Size150x200 = { width: 150, height: 200, name: "Size150x200" };
UI.Avatar.Size.Size124x165 = { width: 124, height: 165, name: "Size124x165" };
UI.Avatar.Size.Size86x115 = { width: 86, height: 115, name: "Size86x115" };
UI.Avatar.Size.Size98x131 = { width: 98, height: 131, name: "Size98x131" };
UI.Avatar.Size.Size65x87 = { width: 65, height: 87, name: "Size65x87" };
UI.Avatar.Size.Size24x24 = { width: 24, height: 24, name: "Size24x24" };
UI.Avatar.Size.Size48x48 = { width: 48, height: 48, name: "Size48x48" };

/************ END /javascript/2100/TC.Utils.js ***********/

/************ START /Javascript/2100/ClientMgr.js ***********/
/**
* General Constants
*/
if (!window.Const) Const = {};
Object.extend(Const,
				{ UNSET_STRING: "-UNSET-STRING-"
				}
			 );

/**
* ElementsGroup - a group of HTML elements distincted in the program by a provided 
* name that may be different from thier Html-Element ID.
* The elements are gathered on the this.elements collection, while the element IDs 
* are in this.elementIDs.
* 
* It features:
*  - managment of elements by logical names
*  - show and hide elements 
*  - onload events stack executed on window.onload
*/
ElementsGroup = Class.create();
/**
* The constructor expects a dictionary, pointing every element's programatic name 
* to its ID on the screen.
* The constructor scheduels a task for the window's load event, and once the HTML 
* document is loaded, it parses the provided dictionary, and obtains references to 
* all specified elements.
* Missing elements are reported in the log in WARN level.
* 
* @param {string}	p_screenElementsDictionary
*  dictionary of program-names as keys, and HTML element-ids as values.
*
* @param {string(optional)}  sInstanceName
*  The name of the ClientMgr instance (usually a singletone utilities class)
*  used for the Log4Js.Logger and for on-the-fly creation of an onload function
*  - Optional: when not provided, a random unique identifier is generated for internal use.
*/
ElementsGroup.prototype.initialize = function(p_elementsDictionary, sInstanceName) {
    //default sInstanceName - for "anonymous"
    if (!sInstanceName) sInstanceName = "ElementsGroup" + ((new Date()).getTime() + "_" + Math.random()).replace(".", "_");

    ElementsGroup.all[ElementsGroup.all.length] = this;
    if (parseInt(sInstanceName) != Number(sInstanceName)) {
        ElementsGroup.all[sInstanceName] = this;
    }

    this.log = new Log4Js.Logger(sInstanceName);
    this.instanceName = sInstanceName;
    this.elements = {};
    this.elementIDs = {};

    //prepare to and attach its onload
    this.prv_constructorTmpDictionary = p_elementsDictionary;
    this.onLoadHandlers = [function() {
        var oConstrDictionary = this.prv_constructorTmpDictionary;
        delete this.prv_constructorTmpDictionary;

        var anythingInDictionary;
        for (anythingInDictionary in oConstrDictionary) break;
        if (anythingInDictionary) {
            this.setElementIDs(oConstrDictionary);
        }
    }
						  ];
}
/**
* @private
* A dictionary of all element-groups, named by thier provided instance name
*/
ElementsGroup.all = [];
/**
* adds new or overrides an existing element to the 
* this.elements and this.elementIDs dictionaries
*
* @param {string} sElementName
*  Name of the element in the program
*
* @param {string} sElementID
*  projectal HTML element ID of the element
*/
ElementsGroup.prototype.setElementID = function(sElementName, sElementID) {
    this.elementIDs[sElementName] = sElementID;
    this.elements[sElementName] = $(sElementID);
}
/**
* adds or overrides managed elements names and thier HTML ids in the elementIDs dictionary
*
* @param {object} p_screenElementsDictionary
*  a dictionary of the managed element names as keys, and thier HTML element-ids as values.
*/
ElementsGroup.prototype.setElementIDs = function(p_elementsDictionary) {
    //if the preload has not occuded yet - add it to the constructor dictionary
    if (this.prv_constructorTmpDictionary) {
        Object.extend(this.prv_constructorTmpDictionary, p_elementsDictionary);
        return;
    }
    var element;
    for (element in p_elementsDictionary) {
        this.setElementID(element, p_elementsDictionary[element]);
    }
}
/**
* @private
*
* @param {string} sElementName
*	the name of the element in the program
*
* @param {string} sCallerInstance
* the caller function (for logging}
* - optional : Default value: "[ClientMgr].getMyElement(...)"
*/
ElementsGroup.prototype.getMyElement = function(sElementName, sCallerInstance) {	//default sCallerInstance
    if (!sCallerInstance) sCallerInstance = "[ElementsGroup].getMyElement(...)";

    //first - check the this.elements collection
    if (this.elements[sElementName]) {
        return this.elements[sElementName];
    }
    this.log.info(sCallerInstance + " doesn't have " + sCallerInstance + ".elements." + sElementName);

    //get managed element ID
    var sElementID = this.elementIDs[sElementName];
    if (sElementID == null) {
        this.log.warn(sCallerInstance + " was asked to show an unknown element: " + sElementName);
        return;
    }
    //get element
    var oElement = $(sElementID);
    if (oElement == null) {
        this.log.warn(sCallerInstance + " was asked to show an element that does not exist: " + sElementID);
        return;
    }

    return oElement;
}
/**
* shows a managed element by its logical name in the program.
*
* @param {string} sElementName
*  the name of the element in the program
*/
ElementsGroup.prototype.showElement = function(sElementName, displayVal) {

    var e = this.getMyElement(sElementName, "showElement");
    if (!e) return;
    if (displayVal == null)
        displayVal = "block";
    e.style.display = displayVal;

}
/**
* hides a managed element by its logical name in the program.
*
* @param {string} sElementName
*  the name of the element in the program
*/
ElementsGroup.prototype.hideElement = function(sElementName) {
    var e = this.getMyElement(sElementName, "hideElement");
    if (!e) return;
    e.style.display = "none";
}
/**
* API to add handlers to the onload events
*
* @param {function} fHandler
* A handler to dispatch from window.onload
*/
ElementsGroup.prototype.addOnLoadHandler = function(fHandler) {
    Claim.isFunction(fHandler, "[ElementsGroup].addOnloadHandler(fHandler) - fHandler must be a function");
    this.onLoadHandlers[this.onLoadHandlers.length] = fHandler;
}
/**
* @private
* Used in on-the-fly generated functions, attached to the window.onload event.
* The goal of this function is to allow sub-classes to have window.onload event 
* listenerss of thier own, and assure the execution sequence of the event handlers
* between events of the parent and events of the subclass.
* The first listener that is registered in the constructor is 
* ElementsGroup.prv_onLoad_handler_ref
*/
ElementsGroup.prototype.prv_onPageLoad = function() {
    var i;
    for (i = 0; i < this.onLoadHandlers.length; i++) {
        this.onLoadHandlers[i].call(this);
    }
}
/**
* @private
* static behavior, called from a function attached to Window.onload
* dispatches onPageLoad to all instances
*/
ElementsGroup.prv_observeWindowLoad_callback = function() {
    for (var i = 0; i < this.all.length; i++) {
        this.all[i].prv_onPageLoad();
    }
}

// Call onPageLoad on all instances created untill page-load event
Event.observe(window
			 , "load"
			 , function() {
			     ElementsGroup.prv_observeWindowLoad_callback();
			 }
			 );


//============================================================
/**
* LayersGroup is an ElementGroup that all its layers share the same screen space, 
* hence, a single layer is visible at a time, or non at all.
*/
LayersGroup = Class.create("ElementsGroup");
/**
*
*/
LayersGroup.prototype.initialize = function(p_screenElementsDictionary, sInstanceName) {
    this.layersIDs = this.elementsIDs;
    this.layers = this.elements;
}
/**
*
*/
LayersGroup.prototype.hideAll = function() {
    var each;
    for (each in this.elementIDs) {
        this.hideElement(each);
    }
}
/**
*
*/
LayersGroup.prototype.showLayer = function(sLayerName) {
    this.hideAll();
    this.showElement(sLayerName);
}
//==============================================
/**
* ClientMgr - class for managing client-side UI.
* Features utilities for:
*  - post/get/redirections
*  - show/hide HTML elements
*
* @param {string}  sInstanceName
*  The name of the ClientMgr instance (usually a singletone utilities class)
*  used for the Log4Js.Logger and for on-the-fly creation of an onload function
* 
* @param {string}	p_screenElementsDictionary
*  dictionary of program-names as keys, and HTML element-ids as values.
*/
ClientMgr = Class.create("ElementsGroup");
ClientMgr.prototype.initialize = function(p_globalElementsDictionary, sInstanceName) {
    //init the current URL
    var sUrl = location.href;
    //PATCH: - remove #anchor - overcome a bug of the infrastructure
    i = sUrl.lastIndexOf("#");
    if (i > -1 && i > sUrl.lastIndexOf("?") && i > sUrl.lastIndexOf("=")) {
        sUrl = sUrl.substr(0, i);
    }

    this.Url = Url.parse(sUrl);

    //windows collection
    this.windows = {};
    this.templates = {};
    //infra for close all windows in unload
    this.onPageUnloadHandlers = [ClientMgr.onPageUnload_handler_ref];
    Event.observe(window
				 , "unload"
				 , new Function("try{\n\t"
								+ this.instanceName + ".onPageUnload();\n"
								+ "}catch(ex){\n\t"
								+ "(new Log4Js.Logger('" + this.instanceName + "')).error('Error or Exception in " + this.instanceName + ".onPageUnload(): ' + (ex.description)?ex.description:ex );\n"
								+ "}"
								)
				 );
}
//===============================================
//---- PAGE NAVIGATION AND WINDOWS MANAGMENT ----
/**
* @private
* This is a dictionary for name in the program as key, and page-settings dictionary as values
* for windows the managed page uses.
* each window settings can contain URL and winSettings in case its used in a window.
* This collection is managed by the API: 
*	- ClientMgr.prototype.addManagedPage(...) 
*/
ClientMgr.prototype.pages = {};
/**
* Adds deffinition for a page in the managed window-deffinitions collection.
*
* @param {string} sName
*  the name of the page in the program
*
* @param {string} sUrl
*  the Url of the page
*
* @param {string(optional)} sWinSettings
* - optional: when not provided - the page does not open in a window, 
* but replaces the current page
*/
ClientMgr.prototype.addManagedPage = function(sName, sUrl, sWinSettings) {
    this.pages[sName] = { URL: sUrl
						, winSettings: sWinSettings
    };
}
/**
* Usefull for:
* - send the page to _top without conflicting IFrames security.
* - Submit a form to a provided URL with the provided parameters and form settings.
*
* @param {object|string} oFormAttributes
*  a key-value dictionary of form HTML attributes to be used to add or override to the default settings.
*  When the parameter is provided as string - it is assumed to be the 
*  'action' attribute, and the rest of the settings are taken from the default settings.
*  Default settings: 
*			- target = "_top"
*			- method = if oAdditionalParams is provided - "POST", otherwise - "GET"
*			- action = when oFormAttributes is provided as string
* 
* @param {object} oAdditionalParams
*	a key-value dictionary of required query-string parametes.
*  when an argument exists both in oParameters and in the sUrl 
*  as query-string parameter - the parameter in sUrl overrides.
*  - optional : functionality ignored when not provided.
*  when this parameter is provided, the default form-method is "POST"
*  otherwise - "GET".
*
*/
ClientMgr.prototype.submitToPage = function go(oFormAttributes, oAdditionalParams) {
    if (typeof (oFormAttributes) == 'string') {
        this.log.debug("ClientMgr.submitToPage got 'oFormAttributes' as string, assumed to be the oFormAttributes.action");
        oFormAttributes = { action: oFormAttributes };
    }
    else {
        if (oFormAttributes.URL && !oFormAttributes.action)
            oFormAttributes.action = oFormAttributes.URL;
        Claim.isString(oFormAttributes.action, "..submitToPage(oFormAttributes.action)");
    }

    //PATCH: - remove #anchor - overcome a bug of the infrastructure
    var sUrl = oFormAttributes.action;
    i = sUrl.lastIndexOf("#");
    if (i > -1 && i > sUrl.lastIndexOf("?") && i > sUrl.lastIndexOf("=")) {
        sUrl = sUrl.substr(0, i);
    }

    var oUrl = Url.parse(sUrl);
    oFormAttributes.action = oUrl.base;
    // use default settings for all settings not in oFormAttributes
    if (null == oFormAttributes.target) oFormAttributes.target = "_top";
    if (null == oFormAttributes.method) oFormAttributes.method = (oAdditionalParams != null) ? "POST" : "GET";

    //copy all settings to a newly created <FORM>
    var f = Object.extend(document.createElement("FORM")
						 , oFormAttributes
						 );
    //copy all parameters found in action URL to oAdditionalParams
    if (oAdditionalParams == null) oAdditionalParams = {};
    var oParams = Object.extend(oAdditionalParams, oUrl.params)

    //populate <FORM> with all fields found
    var e, paramName;
    for (paramName in oParams) {
        if (paramName == "") continue;

        e = Object.extend(document.createElement("INPUT")
						 , { type: "hidden"
							, name: paramName
							, value: oParams[paramName]
						 }
						 );
        f.appendChild(e);
    }

    //append and submit
    document.body.appendChild(f)
    f.submit();
}

/**
* @private
*  parses window settings string (as passed to window.open)
*
* @param {string} sSettings
*/
ClientMgr.prototype.prv_parseWindowSettingsString = function(sSettings) {
    if (!sSettings) return;
    Claim.isString(sSettings, "prv_parseWindowSettingsString(sSettings)");

    sSettings = sSettings.split(",");
    var oProps = {};
    for (var i = 0; i < sSettings.length; i++) {
        try {
            sSettings[i] = sSettings[i].split("=");
            oProps[sSettings[i][0].toLowerCase()] = sSettings[i][1];
        } catch (ex) { }
    }
    return oProps;
}
/**
* Opens a managed window
* - centalizes all windows to the center of the screen
* - focuses every opened window
* - allow supply window name from managed windows or directly a URL
* - allows page names and windows reuse, and allows anonymous windows
* - hold a reference to all used windows, so that when the page unloads, all windows can be closed
*
* @param {string} sWindowPage
*  The URL to populate the window with. The Url can contain Query-String parameters
* 
* @oParams {object} oQSParams
*  Parameters for to add to the URL Query-String.
*  When a parameter appears in the QS of the URL and in the oParams, 
*  the value in oParams overrides the one in the QS.
* 
* 
*/
ClientMgr.prototype.openWindow = function(sWindowPage, oQSParams, sWinID, sDefaultWinSettings) {
    Claim.isString(sWindowPage, this.instanceName + ".openWindow(sWindowPage) - sWindowPage is expected to be a URL in a string");

    if (!oQSParams) oQSParams = {};

    if (!sWinID) sWinID = sWindowPage;

    //TODO:
    var sUrl;
    if (this.pages[sWindowPage]) {
        sUrl = this.pages[sWindowPage].URL;
    } else {
        sUrl = sWindowPage;
        sWindowPage = sWindowPage.replace(/[^A-Z^a-z^0-9]*/g, "_");
    }

    //PATCH: - remove #anchor - overcome a bug of the infrastructure
    i = sUrl.lastIndexOf("#");
    if (i > -1 && i > sUrl.lastIndexOf("?") && i > sUrl.lastIndexOf("=")) {
        sUrl = sUrl.substr(0, i);
    }

    sUrl = Url.parse(sUrl);
    oQSParams = Object.extend(sUrl.params, oQSParams);
    delete oQSParams[""]; // work around 
    sUrl = Url.appendParams(sUrl.base, oQSParams);

    var sWinSettings;
    if (sDefaultWinSettings) {
        sWinSettings = sDefaultWinSettings;
    } else if (this.pages[sWindowPage]) {
        sWinSettings = this.pages[sWindowPage].winSettings;
    } //	else - do nothing...

    if (sWinSettings) {
        var oProps = this.prv_parseWindowSettingsString(sWinSettings);
        if (oProps.width && oProps.height) {
            var h = parseInt((screen.height - oProps.height) / 2);
            var w = parseInt((screen.width - oProps.width) / 2);
            sWinSettings += ",top=" + h + ",left=" + w;
        }
    }

    if (this.windows[sWinID] && !this.windows[sWinID].closed)
        this.windows[sWinID].close();
    this.windows[sWinID] = window.open(sUrl, sWindowPage, sWinSettings);
}
/**
* 
*/
ClientMgr.prototype.onPageUnload = function() {
    var i;
    for (i = 0; i < this.onPageUnloadHandlers.length; i++) {
        this.onPageUnloadHandlers[i].call(this);
    }
}
/**
* @private
* this is a STATIC member - a handler referece that is attached 
* dynamicly later to each instance
*/
ClientMgr.onPageUnload_handler_ref = function() {
    var sWinID;
    for (sWinID in this.windows) {
        try {
            this.windows[sWinID].close();
        } catch (e) { }
    }
}
//=========================================
//---- DATA_SOURCE-TO-SCREEN UTILITIES ----
ClientMgr.prototype.populateElement = function(sElementID, varValue) {
    var oElement = $(sElementID);
    if (!oElement) {
        this.log.warn("populateElement(..) sElementID specifies and element which does not exist:" + sElementID);
        return;
    }
    Element.setText(oElement, varValue);
}
/**
* populates the HTML elements whos IDs are the keys in the parameter oElementsDictionary
* while thier correlating values are the property-names on the parameter oDataSource.
*
* @param {object} oElementsDictionary
*  dictionary with HTML IDs as keys, and names of properties on oDataSource as values.
*
* @param {object} oDataSource
*  dictionary with property names as keys, and thier fetched data as values.
*/
ClientMgr.prototype.populateElements = function(oElementsDictionary, oDataSource) {
    Claim.isObject(oElementsDictionary, "[ClientMgr].populateElements(oElementsDictionary)");
    Claim.isObject(oDataSource, "[ClientMgr].populateElements(oDataSource)");
    var each, oElement, value;
    for (each in oElementsDictionary) {
        oElement = $(each);
        if (!oElement) {
            this.log.warn("populateElements(..) properties-dictionary specifies and element which does not exist:" + each);
            continue;
        }
        value = oDataSource[oElementsDictionary[each]];
        if (null == value) {
            this.log.warn("populateElements properties-dictionary askes for a property which does not exist. Element: " + each + ", Property: " + oElementsDictionary[each]);
            continue;
        }
        Element.setText(oElement, value);
    }
}
/**
* Populates the provided string-template by replacing the placeholders in the sTemplate 
* with values from the oDataSource. 
* The searched placeholders and the correlating values are matched according to the 
* provided oPlaceHoldersAttributesDictionary.
*
* @param {string} sTemplate
*  The template to populate. can be the template istelf as a string, or a template logical name
*
* @param {object} oPlaceHoldersAttributes
*  Dictionary that correlates place-holders in sTemplate as keys, and properties of oDataSource as values.
*
* @param {object} oDataSource
*  Data-Source object
*/
ClientMgr.prototype.populateStringTemplate = function(sTemplate, oPlaceHoldersAttributes, oDataSource) {
    Claim.isString(sTemplate, "[ClientMgr].populateStringTemplace(sTemplate,...)");
    Claim.isObject(oPlaceHoldersAttributes, "[ClientMgr].populateStringTemplace(..,oPlaceHoldersAttributes,..)");
    Claim.isObject(oDataSource, "[ClientMgr].populateStringTemplace(..,oDataSource)");


    //The template can be a string, or a template logical name
    if (this.templates[sTemplate])
        sTemplate = this.templates[sTemplate];

    var placehoder, attribute, replacment;

    for (placehoder in oPlaceHoldersAttributes) {
        attribute = oPlaceHoldersAttributes[placehoder];
        if (null == attribute) {
            this.log.warn("in populateStringTemplace(...) oPlaceHoldersAttributes dictionary specifies a placeholder without providing its data-attribute name: " + placehoder);
            continue;
        }
        replacement = oDataSource[attribute];
        if (null == replacement) {
            this.log.warn("in populateStringTemplace(...) oPlaceHoldersAttributes dictionary specifies a property that does not exist on the provided oDataSource. Placehoder: " + placehoder + ", attribute: " + attribute);
            continue;
        }
        //replacment = replacment.replace(/\$/g,"");
        sTemplate = sTemplate.replace(new RegExp(placehoder, "g"), replacement);
    }
    return sTemplate;
}
ClientMgr.openLink = function(link) {
    var wn = window.open(link, 'GameCenterMainWindow');
    wn.focus();
}
/************ END /Javascript/2100/ClientMgr.js ***********/


/************ START /Javascript/2100/Diamond/Profile.js ***********/
//Claim.isFunction(ClientMgr,"Missing script reference: /Javascript/ClientMgr.js\n required for Profile.js");
if (!ClientMgr) throw new Error('Missing script reference: src="/Javascript/ClientMgr.js\"n required for Profile.js');

if (!window.Const) Const = {};
Object.extend(Const,
				{ UNSET_STRING: "-UNSET-STRING-"
				, UNSET_NUMBER: NaN
				}
			 );
/**
* ProfileMgr
* 
* ProfileMgr.sendToAdapter(sCommand)
* ProfileMgr.sendToProfile()
* ProfileMgr.openGameHighScore(iSku)
* ProfileMgr.getUserDetails(p_propsDictionary)
* ProfileMgr.getAvatar(sHtmlElementID,eAvatarSize,sNoDataFoundHTML,sNotAvailableHTML)
* ProfileMgr.getGameBestScore(iSku, sScoreElementID, sNoDataFoundHTML, sNotAvailableHTML)
* ProfileMgr.getUserBestScore(iSku, sStringTemplate, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML)
* ProfileMgr.getUserOnlineGames(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, iMaxShownGames)
* ProfileMgr.getUserDownloadGames( sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, iMaxShownGames))
* ProfileMgr.getUserWornBadge(sBadgeTemplateString, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML)
*
* TODO - ProfileMgr.getInstalledGames(...) - TODO
*/
ProfileMgr = new ClientMgr({}
						  , "ProfileMgr");
/**
* contains default settings untill the ProfileMgr is initiated.
* Initiation must contain channel, and authenticationAdapter
* @type Object
*/
ProfileMgr.settings = {}
/**
* The channel. Its expected to be overide by ProfileMgr.init(settings)
* @type Number
*/
ProfileMgr.settings.channel = Const.UNSET_NUMBER;
/**
* The URL for the authentication adapter
* Its expected to be overide by ProfileMgr.init(settings)
* @type String
*/
ProfileMgr.settings.authenticationAdapter = Const.UNSET_STRING;
/**
* The URL of the page that the redirection to the profile sends to
* @type string
*/
ProfileMgr.settings.userProfile = "/Profile/ProfileSummary.aspx";
/**
* The size of the avatar in the page the ProfileMgr runs in
* @type UA.User.Avatar
*/
ProfileMgr.settings.avatarSize = "Size150x200";
/**
*
*/
ProfileMgr.settings.loginTarget = "_top";
/**
* A general handler for Failure on asynchronous calls from ProfileMgr
* @type Function
*/
ProfileMgr.settings.onProfileCallFailure = null;
/**
* A general handler for Timeout on asynchronous calls from ProfileMgr
* @type Function
*/
ProfileMgr.settings.onProfileCallTimeout = null;
/**
* The Url of the channel Homepage.
* Used when the Mgr sends to the adapter from a popup, while the parent window is closed.
*/
ProfileMgr.settings.channelHomePage = Const.UNSET_STRING;
/**
* A general error message, used when a connection error or server error occures.
*/
ProfileMgr.settings.noDataMessage = "<b>No data available</b>";
/**
* The current User - access to UserAccounts API
*/
ProfileMgr.user = new UA.User();
/**
* Returns true if the current user is logged as member, otherwise - false
* 
* @type boolean
*/
ProfileMgr.isMember = function() {
    return Clearance.isMember();
}

/**
* @param {object} oSettingsDictionary
* A settings dictionary specifying at least "channel" and "authenticationAdapter"
* can include any of the documented properties on the Profile.settings inner object
*/
ProfileMgr.init = function(oSettingsDictionary) {
    if (!this.isInitiated) {
        Claim.isObject(oSettingsDictionary, "ProfileMgr.init(oSettingsDictionary) - oSettingsDictionary must be an object");
        Claim.isNumber(oSettingsDictionary.channel, "ProfileMgr.init(oSettingsDictionary) - oSettingsDictionary.channel must be a number - describing the channel-id");
        Claim.isString(oSettingsDictionary.authenticationAdapter, "ProfileMgr.init(oSettingsDictionary) - oSettingsDictionary.authenticationAdapter must be a string - describing the authentication-adapter URL");
        Claim.isString(oSettingsDictionary.channelHomePage, "ProfileMgr.init(oSettingsDictionary) - oSettingsDictionary.channelHomePage must be a string - expected to be : the  URL for the homepage of the channel");

        this.log = new Log4Js.Logger("ProfileMgr")
        this.isInitiated = true;
    }

    this.set(oSettingsDictionary);

}
/**
* Logs-Off the current User, and redirects
* to the current page to dispose all cookies
*/
ProfileMgr.logOffCurrentUser = function() {
    this.log.info("logging off current user...");

    // clear any cookie-related QS parts
    var oUrl = Url.parse(location.href);
    var oRemovedQS = String("ui,cx,rx,ux,ax,cn,rn,un,an").split(",");
    for (var i = 0; i < oRemovedQS.length; i++)
        delete oUrl.params[oRemovedQS[i]];

    //patch over bug of Url.parse on no QS URLs
    delete oUrl.params[""]

    var sUrl = Url.appendParams(oUrl.base, oUrl.params);
    this.log.info("sending to URL: " + sUrl);

    Clearance.forget(sUrl);
}
/**
* @param {object} oSettingsDictionary
* can include any of the documented properties on the ProfileMgr.settings inner object
*/
ProfileMgr.set = function(oSettingsDictionary) {
    Object.extend(this.settings, oSettingsDictionary);
}
/**
* Sends the current page to the Authentication Adapter
*
* @param {string} sCommand
* Command passed to the adapter
*/
ProfileMgr.sendToAdapter = function(sCommand) {
    //assure userProfile 
    Claim.check(this.settings.authenticationAdapter != Const.UNSET_STRING, "ProfileMgr.sendToAdapter used without defining ProfileMgr.settings.authenticationAdapter");
    if (this.settings.authenticationAdapter == Const.UNSET_STRING)
        return alert("sendToAdapter used without defining settings.authenticationAdapter");

    if (sCommand == null || typeof (sCommand) != 'string') {
        sCommand = "login";
    }

    var submitSettings = { action: this.settings.authenticationAdapter
						 , method: "GET"
						 , target: this.settings.loginTarget
    }

    var sUrl = Url.parse(this.getReturnUrl());
    delete sUrl.params.channel;
    delete sUrl.params.lc;
    sUrl = Url.appendParams(sUrl.base, sUrl.params);

    var params = { command: sCommand.toLowerCase()
					, retUrl: sUrl
					, channel: this.settings.channel
    };

    //applicative submit to TOP or Opener-window without conflicting IFrames/Windows security
    this.submitToPage(submitSettings, params);

    //in case the method is called from A.onclick
    return false;
}
/**
* Sends the current page to the User-Profile page
*/
ProfileMgr.sendToProfile = function() {
    //assure userProfile 
    Claim.check(this.settings.userProfile != Const.UNSET_STRING, "ProfileMgr.settings.userProfile", "ProfileMgr.settings.userProfile is not set");

    //applicative submit to TOP or Opener-window  
    //without conflicting IFrames/Windows security
    this.submitToPage({ action: this.settings.userProfile
						, target: this.settings.loginTarget
    }
					 );
}
/**
* @private
* When the Mgr runs in the GC - returns the location of the current page.
* When the Mgr runs in popup - tries to retrieve the Url of the parent, 
* or returns ProfileMgr.settings.channelHomePage on failure.
* Used when the sendToAdapter is called on the popup, to retrieve the return URL.
*
* Also - @private.
* wrap function - in cirtain browser versions and settings security issues 
* hide inner attributes of variables on parent and opener windows.
* This wrap allows calling a function on the window itself.
*/
ProfileMgr_getReturnUrl = function() { return ProfileMgr.getReturnUrl(); }
ProfileMgr.getReturnUrl = function() {
    Claim.isTrue(this.isInitiated, "ProfileMgr.getReturnUrl() was called before initiating ProfileMgr. \n\nSee ProfileMgr.init(oSettingsDictionary)");
    // when running in popup - use opener
    if (window.opener) {
        try {
            return window.opener.ProfileMgr_getReturnUrl()
        }
        catch (ex) {
            this.log.warn("ProfileMgr.getReturnUrl() failed to retrieve location from the opener window. channel-home used instead: " + this.settings.channelHomePage + ". Exception: " + Object.serialize(ex));
            return this.settings.channelHomePage;
        }
    }
    // Use highest IFRAME with a ProfileMgr instance
    if (window.parent != window) {
        this.log.info("ProfileMgr.getReturnUrl() - Parent window detected");
        try {
            return window.parent.ProfileMgr_getReturnUrl()
        }
        catch (ex) {
            switch (typeof (ex)) {
                case 'object': /*explorer*/
                    this.log.debug("ProfileMgr.getReturnUrl() - Parent window detected, assumed Explorer-based browser ");
                    if (ex.number == -2146827850 /*doesn't support this property*/
						|| ex.number == -2146823281 /*is null or not an object*/
						) {
                        this.log.warn("widow.parent.ProfileMgr_getReturnUrl() is not found on parent window. Code runs in IFrame on a page of the partner. Exception: " + Object.serialize(ex));
                    }
                    else {
                        this.log.warn("ProfileMgr.getReturnUrl() failed to retrieve location from the parent window for unexpected reason. Channel-home used instead: " + this.settings.channelHomePage + ". Exception: " + Object.serialize(ex));
                        return this.settings.channelHomePage;
                    }
                    break;
                case 'string': /* FireFox/Mozilla */
                    this.log.debug("ProfileMgr.getReturnUrl() - Parent window detected, assumed Mozilla-based browser ");

                    /** 
                    * the identifier of the exception is the message FF/Mozila use for permission denied:
                    * "Permission denied to get property Window.ProfileMgr_getReturnUrl"
                    * However, the words "Permission denied to get property" can be localized, 
                    * that leaves us only the property name...
                    */
                    if (ex.indexOf("Window.ProfileMgr_getReturnUrl") != -1) {
                        this.log.warn("widow.parent.ProfileMgr_getReturnUrl() is not found on parent window. Code runs in IFrame on a page of the partner. Exception: " + ex);
                    }
                    else {
                        this.log.warn("ProfileMgr.getReturnUrl() failed to retrieve location from the parent window for unexpected reason. Channel-home used instead: " + this.settings.channelHomePage + ". Exception: " + ex);
                        return this.settings.channelHomePage;
                    }
                    break;
            }
        }
    }

    var sUrl = this.Url.full;
    //PATCH: - remove #anchor - overcome a bug of the infrastructure
    i = sUrl.lastIndexOf("#");
    if (i > -1 && i > sUrl.lastIndexOf("?") && i > sUrl.lastIndexOf("=")) {
        sUrl = sUrl.substr(0, i);
    }
    return sUrl;


}
/**
* High-Score - to open popup of user high-score of his worn badge
*/
ProfileMgr.addManagedPage("HighScore", "/Orange2.0/App/GameHighScore.aspx", "width=611,height=440,status=no,scrollbars=yes,toolbar=no,menubar=no,location=no,resizeable=no");
/**
* Opens the high-score Page
*/
ProfileMgr.openGameHighScore = function(iSku) {
    var oParams = Object.extend({}, this.Url.params);
    if (iSku) {
        oParams.sku = iSku;
    }
    this.openWindow("HighScore", oParams, { method: "GET" });
}
/**
* Fetches and Populates the User-Details to the HTML elements, 
* as specified by the provided dictionary.
* The dictionary is expected to contain HTML element-IDs as keys, 
* and User-Details properties as values.
*
* @param {object} p_propsDictionary
* Supported properties as values 
* according to the product UA.User.getDetails.
* Known by the time of this update:
*  - age            - gender
*  - nickname       - birthDayOfMonth
*  - birthMonth     - birthYear
*  - country        - zipCode
*
* Uses a subclass of UA.USer as worker class.
* It is described right bellow.
*/
ProfileMgr.getUserDetails = function(p_propsDictionary, oEvents) {
    var ud = new ProfileMgr.UserDetails(p_propsDictionary);
    ud = Object.extend(ud, oEvents);
    ud.apply();
}
//--ProfileMgr.UserDetails-----------------------------------------------------------------
/**
* A worker class that fetches user details.
*/
ProfileMgr.UserDetails = Class.create("UA.User");
ProfileMgr.UserDetails = Class.enhance(ProfileMgr.UserDetails, IEventDispatcher);
ProfileMgr.UserDetails.prototype.initialize = function(pPropsDictionary, fFailure, fTimeout) {
    Claim.isObject(pPropsDictionary, "UserDetails.get(pPropsDictionary) - pPropsDictionary is expected to be an object");

    this.log = new Log4Js.Logger("ProfileMgr.UserDetails");

    this.detailsPropDictionary = pPropsDictionary;
}
ProfileMgr.UserDetails.prototype.apply = function() {
    this.GetUserDetails(this.onSuccess
							, this.onFailure
							, this.onTimeout);
}
ProfileMgr.UserDetails.prototype.onSuccess = function(data) {
    this.log.debug("onSuccess(" + Object.serialize(data) + ")");

    this.dispatch("onDataBind", data);

    ProfileMgr.populateElements(/*oElementsDictionary*/this.detailsPropDictionary
									, /*oDataSource		  */data
									);
    this.log.debug("onSuccess is complete");
}
ProfileMgr.UserDetails.prototype.onFailure = function(r) { this.log.error('FAILURE on ProfileMgr.UserDetails.get()'); }
ProfileMgr.UserDetails.prototype.onTimeout = function(r) { this.log.error('TIMEOUT on ProfileMgr.UserDetails.get()'); }
ProfileMgr.UserDetails.get = function(pPropsDictionary, fFailure, fTimeout, oUser) {
    new ProfileMgr.UserDetails(pPropsDictionary, fFailure, fTimeout, oUser);
}
//--/ProfileMgr.UserDetails------------------------------------------------------------
/**
* ProfileMgr.getAvatar
* gets the avatar of the user, and sets it's HTML to the provided sHtmlElementID.
* The size of the avatar can be specified by the optional eAvatarSize
*
* @param {string} sHtmlElementID
*
* @param {Object(optional)} oSettings
* Any settings, configurations, HTML-attributes or Flash-Params we want to pass on.
*
*/
ProfileMgr.getAvatar = function(sHtmlElementID, oSettings, oEvents) {
    Claim.isString(sHtmlElementID, "sHtmlElementID is expected to be the ID of the target element");
    oSettings = oSettings || {};

    ua = new GameCatalog.AvatarViewer(oSettings);
    ua = Object.extend(ua, oEvents);
    ua.render(sHtmlElementID);
}

/**
* ProfileMgr.getAvatarStudio
* gets the avatar of the user, and sets it's HTML to the provided sHtmlElementID.
* The size of the avatar can be specified by the optional eAvatarSize
*
* @param {string} sHtmlElementID
*
* @param {Object(optional)} oSettings
* Any settings, configurations, HTML-attributes or Flash-Params we want to pass on.
*
*/
ProfileMgr.getAvatarStudio = function(sHtmlElementID, oSettings, oEvents) {
    Claim.isString(sHtmlElementID, "sHtmlElementID is expected to be the ID of the target element");
    oSettings = oSettings || {};

    ua = new GameCatalog.AvatarStudio(sHtmlElementID, oSettings);
    ua = Object.extend(ua, oEvents);
    ua.apply();

}

/**
* ProfileMgr.getGameBestScore
* Populates the cummunity best score of the provided SKU in to the element specified by ID.
*
* @param {number} iSku
* The Sku of the queried game
*
* @param {string} sElementID
* The HTML element ID to feed the top-score into 
*
*  @param {string(optional)} sNoDataFoundHTML
*  HTML to populate target-element when server returms with no data
*  - optional: When not provided, ProfileMgr.settings.noDataMessage is used
*
*  @param {string(optional)} sNotAvailableHTML
*  HTML to populate target-element when there is a problem with the server's response
*  - optional: When not provided, ProfileMgr.settings.noDataMessage is used
*/
ProfileMgr.getGameBestScore = function(iSku, sScoreElementID, sNoDataFoundHTML, sNotAvailableHTML, oEvents) {
    var gbs = new ProfileMgr.GameBestScore(iSku
										  , sScoreElementID
										  , sNoDataFoundHTML || this.settings.noDataMessage
										  , sNotAvailableHTML || this.settings.noDataMessage
										  );
    gbs = Object.extend(gbs, oEvents);
    gbs.apply();
}
//--ProfileMgr.GameBestScore------------------------------------------------------------
/**
* A worker class that feches game community high-score
*/
ProfileMgr.GameBestScore = Class.create("UA.Game");
ProfileMgr.GameBestScore = Class.enhance(ProfileMgr.GameBestScore, IEventDispatcher);
ProfileMgr.GameBestScore.prototype.toString = function() {
    return "[UA.Game] extension: GameBestScore";
}
ProfileMgr.GameBestScore.prototype.initialize = function(iSku, sScoreElementID, sNoDataFoundHTML, sNotAvailableHTML) {
    Claim.isString(sScoreElementID, "ProfileMgr.GameBestScore(sScoreElementID,...) - sScoreElementID must be a string")
    Claim.isObject($(sScoreElementID), "ProfileMgr.GameBestScore(sScoreElementID,...) - sScoreElementID must be a string representing an HTML element ID")
    Claim.isString(sNoDataFoundHTML, "ProfileMgr.GameBestScore(...,sNoDataFoundHTML,...) - must be a string, expected HTML for no-data-found case")
    Claim.isString(sNotAvailableHTML, "ProfileMgr.GameBestScore(...,sNotAvailableHTML) - must be a string, expected HTML for no-data-available case")

    this.log = new Log4Js.Logger("ProfileMgr.GameBestScore");

    this.oTargetElement = $(sScoreElementID);
    this.noDataFound = sNoDataFoundHTML;
    this.notAvailable = sNotAvailableHTML;

}
ProfileMgr.GameBestScore.prototype.apply = function() {
    this.GetGameHighScores( /*mode	*/""
								, /*iAmount	*/1
								, /*period	*/UA.Game.Scores.Periods.EVER
								, /*fSuccess*/this.onSuccess
								, /*fFailure*/this.onFailureOrTimeout
								, /*fTimeout*/this.onFailureOrTimeout);
}
ProfileMgr.GameBestScore.prototype.onSuccess = function(data) {
    this.log.info("onSuccess with this data: " + Object.serialize(data));
    if (!data || !data.TopScores || !data.TopScores[0] || !data.TopScores[0].Score) {
        this.log.error("GameBestScore did not get game best-score data. Object.serialize(data): " + Object.serialize(data));
        Element.setText(this.oTargetElement, this.noDataFound);
        return;
    }

    this.dispatch("onDataBind", data);

    Element.setText(this.oTargetElement, Number(data.TopScores[0].Score).format());
}
ProfileMgr.GameBestScore.prototype.onFailureOrTimeout = function(r) {
    this.log.error('FAILURE or TIMEOUT on ProfileMgr.GameBestScore.get()');
    Element.setText(this.oTargetElement, this.sNotAvailableHTML);
}
//--/ProfileMgr.GameBestScore------------------------------------------------------------

/**
* ProfileMgr.getUserBestScore
* Gets the user's best score to the provided game, and populates the target element
* using the provided template
*	
* @param {number} iSku
* The Sku of the queried game
*
* @param {string} sStringTemplate
* The template of the populated element
* 
* @param {object} oPlaceHoldersDictionary
* A dictionary with place-holders in the template as keys, 
* and the expected value-propreties for these places from the server's response as values
* 
* @param {string} sTargetElementID
* The HTML element ID to feed the top-score into 
*
* @param {string(optional)} sNoDataFoundHTML
* HTML to populate target-element when server returms with no data
* - optional: When not provided, ProfileMgr.settings.noDataMessage is used
*
* @param {string(optional)} sNotAvailableHTML
* HTML to populate target-element when there is a problem with the server's response
* - optional: When not provided, ProfileMgr.settings.noDataMessage is used
*/
ProfileMgr.getUserBestScore = function(iSku, sStringTemplate, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML, oEvents) {
    var ubs = new ProfileMgr.UserBestScore(iSku
											, sStringTemplate
											, oPlaceHoldersDictionary
											, sTargetElementID
											, sNoDataFoundHTML || this.settings.noDataMessage
											, sNotAvailableHTML || this.settings.noDataMessage
											);
    ubs = Object.extend(ubs, oEvents);
    ubs.apply();
}
//--ProfileMgr.getUserBestScore------------------------------------------------------------
/**
* A worker class that feches game user high-score
*/
ProfileMgr.UserBestScore = Class.create("UA.Game");
ProfileMgr.UserBestScore = Class.enhance(ProfileMgr.UserBestScore, IEventDispatcher);
ProfileMgr.UserBestScore.prototype.toString = function() {
    return "[UA.Game] extension: UserBestScore";
}
ProfileMgr.UserBestScore.prototype.initialize = function(iSku, sStringTemplate, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML) {
    Claim.isString(sStringTemplate, "UserBestScore.initialize - sStringTemplate must be a string");
    Claim.isObject(oPlaceHoldersDictionary, "UserBestScore.initialize - oPlaceHoldersDictionary  must be an object");
    Claim.isString(sTargetElementID, "UserBestScore.prototype.initialize - sTargetElementID must be a string");
    Claim.isObject($(sTargetElementID), "UserBestScore.prototype.initialize - sTargetElementID must be a string describing an HTML element ID");
    Claim.isString(sNoDataFoundHTML, "ProfileMgr.UserBestScore(...,sNoDataFoundHTML,...) - must be a string, expected HTML for no-data-found case")
    Claim.isString(sNotAvailableHTML, "ProfileMgr.UserBestScore(...,sNotAvailableHTML) - must be a string, expected HTML for no-data-available case")

    this.log = new Log4Js.Logger("ProfileMgr.UserBestScore");


    this.userBestScoreTemplate = sStringTemplate;
    this.userBestScorePlaceHoldersDictionary = oPlaceHoldersDictionary;
    this.oTargetElement = $(sTargetElementID);
    this.noDataFound = sNoDataFoundHTML;
    this.notAvailable = sNotAvailableHTML;


}
/**
* sends the request
*/
ProfileMgr.UserBestScore.prototype.apply = function() {
    this.GetUserHighScore( /* mode:		*/null
							 , /* fSuccess: */this.onSuccess
							 , /* fFailure: */this.onFailureOrTimeout
							 , /* fTimeout: */this.onFailureOrTimeout
							 );
}
/**
* @param {object} data
* expeced properties on data (provided by infra): 
*   - userHighScore    - userRanking
*   - userPosition
*/
ProfileMgr.UserBestScore.prototype.onSuccess = function(dataUA) {

    this.log.info("onSuccess with this Data: " + Object.serialize(dataUA));

    if (!dataUA.userPosition && !dataUA.userHighScore && !dataUA.userRanking) {
        Element.setText(this.oTargetElement, this.noDataFound);
        return;
    }

    var data = Object.extend({}, dataUA);

    data.userPosition = (!data.userPosition) ? "&nbsp" : "(" + data.userPosition + ")";
    data.userRankingImgUrl = (data.userRanking == null) ? "" : TC.UserMedals.getMedalByRanking(data.userRanking).img;
    data.userHighScoreFormatted = Number(data.userHighScore).format();

    this.log.debug("pre populating template with : " + Object.serialize(data));

    this.dispatch("onDataBind", data);

    var strHTML = ProfileMgr.populateStringTemplate(this.userBestScoreTemplate
														, this.userBestScorePlaceHoldersDictionary
														, data
														);
    Element.setText(this.oTargetElement, strHTML);
}
ProfileMgr.UserBestScore.prototype.onFailureTimeout = function() {
    this.log.error('FAILURE or TIMEOUT on UserBestScore.get()');
    Element.setText(this.oTargetElement, this.notAvailable);
}
//--/ProfileMgr.GameBestScore------------------------------------------------------------
/**
* ProfileMgr.getUserOnlineGames
* Gets the user's recent online games, and populates them into the target element, 
* in the format of the provided game-template. 
*
* @param {string} sTemplatesString
* The template for each found game 
* 
* @param {object} oPlaceHoldersDictionary
* A dictionary with place-holders in the template as keys, 
* and the expected value-propreties for these places from the server's response as values
*
* @param {string} sTargetElementID
* The HTML element ID to feed the top-score into 
*
* @param {number(optional)} oParams
* The max displayed games.
* - optiona: When not provided - all fetched games are shown.
*
*/
ProfileMgr.getUserOnlineGames = function(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, oParams, oEvents) {
    var uog = new ProfileMgr.UserOnlineGames(sTemplatesString
											, oPlaceHoldersDictionary
											, sTargetElementID
											, oParams
											);
    uog = Object.extend(uog, oEvents);
    uog.apply();
}
//--ProfileMgr.UserOnlineGames------------------------------------------------------------
ProfileMgr.UserOnlineGames = Class.create("UA.User");
ProfileMgr.UserOnlineGames = Class.enhance(ProfileMgr.UserOnlineGames, IEventDispatcher);
ProfileMgr.UserOnlineGames.prototype.initialize = function(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, oParams) {
    Claim.isString(sTemplatesString, "ProfileMgr.UserOnlineGames(GameTemplateString,...) must be a string");
    Claim.isObject(oPlaceHoldersDictionary, "ProfileMgr.UserOnlineGames(...,oPlaceHoldersDictionary,...) must be an object");
    Claim.isString(sTargetElementID, "ProfileMgr.UserOnlineGames(...,sTargetElementID,...) must be a string");
    Claim.isObject($(sTargetElementID), "ProfileMgr.UserOnlineGames(...,sTargetElementID,...) must be a string describing an HTML element");

    if (!oParams) oParams = {};

    //backward compatibility - iMaxShownGames as a "default" parameter
    if (parseInt(oParams)) oParams = { maxGames: parseInt(oParams) };

    this.params = Object.extend(this.params, oParams);

    if (oParams.maxGames) this.maxDisplayedGames = oParams.maxGames;

    this.log = new Log4Js.Logger("ProfileMgr.UserOnlineGames");

    this.repeater = new TC.Controls.Repeater(sTemplatesString
												, this.log
												, { error: "error" }
												);
    this.repeater.boss = this;
    this.repeater._dispatch = this.repeater.dispatch;
    this.repeater.dispatch = function() {
        this.log.info("ProfileMgr.UserOnlineGames.repeater - dispatching " + arguments[0]);
        if (this[arguments[0]])
            return this._dispatch.apply(this, arguments);

        return this.boss.dispatch.apply(this.boss, arguments);
    }

    this.templates = this.repeater.templates;

    if (0 == this.templates.noData.length) this.templates.noData = ProfileMgr.settings.noDataMessage;
    if (0 == this.templates.error.length) this.templates.error = ProfileMgr.settings.noDataMessage;

    this.templatePlaceHoldersDictionary = oPlaceHoldersDictionary;
    this.oTargetElement = $(sTargetElementID);
}
ProfileMgr.UserOnlineGames.prototype.apply = function() {
    this.GetUserGames(this.onSuccess
						 , this.onFailureOrTimeout
						 , this.onFailureOrTimeout);
}
ProfileMgr.UserOnlineGames.prototype.toString = function() {
    return "[UA.User] extension: UserOnlineGames";
}
ProfileMgr.UserOnlineGames.prototype.prv_repeater_onItemDataBound = function(item) {
    if (!TC.SKUs.extendDataFromSKU(item.dataItem, item.dataItem.gameSku)) {
        item.skipItem = true;
        this.log.info(item.dataItem.sku + " was reported as recent user online game, but is not found in games catalog");
    }

    this.boss.dispatch("onItemDataBound", item);
}
ProfileMgr.UserOnlineGames.prototype.onSuccess = function(data) {
    this.log.info("onSuccess with this Data: " + Object.serialize(data));

    var arrGames = data.Games;
    if (this.maxDisplayedGames && arrGames.length > this.maxDisplayedGames)
        arrGames = arrGames.slice(0, this.maxDisplayedGames);

    this.repeater.onItemDataBound = this.prv_repeater_onItemDataBound;
    this.repeater.dataBind(this.templatePlaceHoldersDictionary, arrGames);

    this.repeater.render(this.oTargetElement);
    return;
}
ProfileMgr.UserOnlineGames.prototype.onFailureOrTimeout = function() {
    this.log.error("FAILURE or TIMEOUT on ProfileMgr.UserOnlineGames");
    Element.setText(this.oTargetElement, this.templates.error);
}
//--/ProfileMgr.UserOnlineGames------------------------------------------------------------

/**
*
*/
ProfileMgr.getUserDownloadGames = function(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, oSettings, oEvents) {
    if (!oSettings.channel) oSettings.channel = this.settings.channel;

    var udg = new ProfileMgr.UserDownloadGames(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, oSettings);
    udg = Object.extend(udg, oEvents);
    udg.apply();
}

//--ProfileMgr.UserDownloadGames------------------------------------------------------------
ProfileMgr.UserDownloadGames = Class.create();
ProfileMgr.UserDownloadGames = Class.enhance(ProfileMgr.UserDownloadGames, IEventDispatcher);
ProfileMgr.UserDownloadGames.prototype.toString = function() {
    return "[ProfileMgr.UserDownloadGames]";
}
ProfileMgr.UserDownloadGames.prototype.initialize = function(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, oSettings) {
    Claim.isString(sTemplatesString, "ProfileMgr.UserDownloadGames(...,GameTemplateString,...) must be a string");
    Claim.isObject(oPlaceHoldersDictionary, "ProfileMgr.UserDownloadGames(...,oPlaceHoldersDictionary,...) must be an object");
    Claim.isString(sTargetElementID, "ProfileMgr.UserDownloadGames(...,sTargetElementID,...) must be a string");
    Claim.isObject($(sTargetElementID), "ProfileMgr.UserDownloadGames(...,sTargetElementID,...) must be a string describing an HTML element");

    if (!oSettings) oSettings = {};
    Claim.isScalar(oSettings.channel, "ProfileMgr.UserDownloadGames(.../oSettings.channel) must be the channel-code or codes");
    this.channel = oSettings.channel;

    this.log = new Log4Js.Logger("ProfileMgr.UserDownloadGames");

    this.maxDisplayedGames = oSettings.showMaxGames || 10;

    this.repeater = new TC.Controls.Repeater(sTemplatesString, this.log);
    this.repeater.boss = this;
    this.repeater._dispatch = this.repeater.dispatch;
    this.repeater.dispatch = function() {
        this.log.info("ProfileMgr.UserOnlineGames.repeater - dispatching " + arguments[0]);
        if (this[arguments[0]])
            return this._dispatch.apply(this, arguments);

        return this.boss.dispatch.apply(this.boss, arguments);
    }

    this.templatePlaceHoldersDictionary = oPlaceHoldersDictionary;
    this.oTargetElement = $(sTargetElementID);
}
ProfileMgr.UserDownloadGames.prototype.apply = function() {
    var data = ProfileMgr.getInstalledGames(this.channel)
    if (!data.games.length) {
        this.log.info("No downloadable games are found.");
    }
    this.onPopulate(data);
}
ProfileMgr.UserDownloadGames.prototype.prv_repeater_onItemDataBound = function(item) {
    if (!TC.SKUs.extendDataFromSKU(item.dataItem)) {
        this.log.info(item.dataItem.sku + " is installed for channel " + ProfileMgr.settings.channel + " but is not found in games catalog");
        item.skipItem = true;
    }

    this.boss.dispatch("onItemDataBound", item);
}
ProfileMgr.UserDownloadGames.prototype.onPopulate = function(data) {

    this.log.info("populating downloadable games with this Data: " + Object.serialize(data));

    var arrGames = data.games;
    if (this.maxDisplayedGames && arrGames.length > this.maxDisplayedGames)
        arrGames = arrGames.slice(0, this.maxDisplayedGames);

    this.repeater.onItemDataBound = this.prv_repeater_onItemDataBound;
    this.repeater.dataBind(this.templatePlaceHoldersDictionary, arrGames);

    this.repeater.render(this.oTargetElement);
    return;
}
//--/ProfileMgr.UserDownloadGames------------------------------------------------------------

/**
* ProfileMgr.getUserWornBadge
* Gets the user worn badge, and populates the target element using the worn 
* badge's properties and the badge HTML template.
*
* @param {string} sBadgeTemplateString
* The template for the user's worn badge 
*
* @param {object} oPlaceHoldersDictionary
* A dictionary with place-holders in the template as keys, 
* and the expected value-propreties for these places from the server's response as values

* @param {string} sTargetElementID
* The HTML element ID to feed the top-score into 
*
* @param {string(optional)} sNoDataFoundHTML
* HTML to populate target-element when server returms with no data
* - optional: When not provided, ProfileMgr.settings.noDataMessage is used
*
* @param {string(optional)} sNotAvailableHTML
* HTML to populate target-element when there is a problem with the server's response
* - optional: When not provided, ProfileMgr.settings.noDataMessage is used
*/
ProfileMgr.getUserWornBadge = function(sBadgeTemplateString, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML, oEvents) {
    var ub = new ProfileMgr.UserBadge(sBadgeTemplateString, oPlaceHoldersDictionary, sTargetElementID
									, sNoDataFoundHTML || this.settings.noDataMessage
									, sNotAvailableHTML || this.settings.noDataMessage
									);
    ub = Object.extend(ub, oEvents);
    ub.apply();
}
//--ProfileMgr.UserBadge------------------------------------------------------------
ProfileMgr.UserBadge = Class.create("UA.User");
ProfileMgr.UserBadge = Class.enhance(ProfileMgr.UserBadge, IEventDispatcher);
ProfileMgr.UserBadge.prototype.toString = function() {
    return "[UA.User] extension: UserBadge";
}
ProfileMgr.UserBadge.prototype.initialize = function(sBadgeTemplateString, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML) {
    Claim.isString(sBadgeTemplateString, "UserBadge.prototype.initialize(sTargetElementID, oPlaceHoldersDictionary, sBadgeTargetElementID) - sBadgeTemplateString must be a string");
    Claim.isObject(oPlaceHoldersDictionary, "UserBadge.prototype.initialize(sTargetElementID, oPlaceHoldersDictionary, sBadgeTargetElementID) - oPlaceHoldersDictionary must be an object");
    Claim.isString(sTargetElementID, "UserBadge.prototype.initialize(sTargetElementID, oPlaceHoldersDictionary, sBadgeTargetElementID) - sBadgeTargetElementID must be a string");
    Claim.isObject($(sTargetElementID), "UserBadge.prototype.initialize(sTargetElementID, oPlaceHoldersDictionary, sBadgeTargetElementID) - sBadgeTargetElementID must be a string describing an HTML element ID");
    Claim.isString(sNoDataFoundHTML, "ProfileMgr.UserBadge(...,sNoDataFoundHTML,...) - must be a string, expected HTML for no-data-found case")
    Claim.isString(sNotAvailableHTML, "ProfileMgr.UserBadge(...,sNotAvailableHTML) - must be a string, expected HTML for no-data-available case")

    this.log = new Log4Js.Logger("ProfileMgr.UserBadge");

    this.oTargetElement = $(sTargetElementID);
    this.noDataFound = sNoDataFoundHTML;
    this.notAvailable = sNotAvailableHTML;
    this.medalsStringTemplate = sBadgeTemplateString;
    this.medalsPlaceHoldersDictionary = oPlaceHoldersDictionary;

}
ProfileMgr.UserBadge.prototype.apply = function() {
    this.GetHighestMedal(this.onSuccess
							, this.onFailure
							, this.onTimeout);
}
ProfileMgr.UserBadge.prototype.onSuccess = function(data) {
    this.log.info("ProfileMgr.serBadge.onSuccess - got data: " + Object.serialize(data));

    var game = TC.SKUs[data.gameSku];
    if (!game) {
        this.log.error("Game sku " + data.gameSku + " is not found.");
        Element.setText(this.oTargetElement, this.notAvailable);
        return;
    }
    this.log.info("getUserWornBadge - user badge game: " + Object.serialize(game));
    this.log.info("data.userRanking:" + data.userRanking + ", TC.UserMedals.getMedalByRanking(data.userRanking):" + Object.serialize(TC.UserMedals.getMedalByRanking(data.userRanking)));

    data.badgeGameSku = game.sku;
    data.badgeGameName = game.name;
    data.badgeGameUrl = game.gamePageURL;
    data.badgeImgUrl = TC.UserMedals.getMedalByRanking(data.userRanking).img;

    this.dispatch("onDataBind", data);

    var sHTML = ProfileMgr.populateStringTemplate(this.medalsStringTemplate
													 , this.medalsPlaceHoldersDictionary
													 , data
													 );
    Element.setText(this.oTargetElement, sHTML);
}
ProfileMgr.UserBadge.prototype.onFailure = function(response) {
    this.log.error("FAILURE on ProfileMgr.UserBadge");

    if (response.Status == 'PERSONAL_DETAILS_NOT_FOUND') {
        this.log.warn("PERSONAL_DETAILS_NOT_FOUND on UserBadge");
        Element.setText(this.oTargetElement, this.noDataFound);
    }
    else {
        this.log.warn("Error on UserBadge: " + response.Status);
        Element.setText(this.oTargetElement, this.notAvailable);
    }
}
ProfileMgr.UserBadge.prototype.onTimeout = function(request) {
    this.log.error("TIMEOUT on ProfileMgr.UserBadge");
    Element.setText(this.oTargetElement, this.notAvailable);
}
//--/ProfileMgr.UserBadge------------------------------------------------------------
/**
* ProfileMgr.getInstalledGames
* 
* @param {Number|String(optional)} The channel-code or comma-delimited-string of channel-codes
* When not provided - the channel that is initiated into ProfileMgr is used.
*/
ProfileMgr.getInstalledGames = function(channel) {
    channel = channel || this.settings.channel;
    return getGamesListByChannel(channel)
}
//----------------------------------------------------------------------------------

/**
* Centralizes the applicativity of the user's Avatar
*/
ProfileMgr.Avatar = {}
/**
* id of the HTML id
*/
ProfileMgr.Avatar.id = "mainFAV"
/**
* supported emotions array
*/
ProfileMgr.Avatar.Emotions = ["Happy"
							 , "Sad"
							 ];
ProfileMgr.Avatar.Emotions.Happy = 0
ProfileMgr.Avatar.Emotions.Sad = 1


ProfileMgr.Avatar = {};


/**
* initiates the ProfileMgr.Avatar object
* 
* @param {string(optional)} sAvatarID
* - optional: when not provided, the default in ProfileMgr.Avatar.id is used.
*/
ProfileMgr.Avatar.init = function(sAvatarID) {
    if (!this.log) this.log = new Log4Js.Logger("ProfileMgr.Avatar");

    if (sAvatarID) this.id = sAvatarID;
    if (!this.id) {
        this.log.warn("avatar object ID is not set");
        return;
    }
    if (navigator.appName.indexOf("Netscape") != -1) {
        this.log.info("netscape detected.");
        this.objFAV = document.embeds[this.id];
        return;
    }
    else {
        this.objFAV = $(this.id);
    }
}
ProfileMgr.addOnLoadHandler(
	function() {
	    ProfileMgr.Avatar.init();
	}
);
/**
* Sets emotion to the active avater
*
* @param {string} sEmotion
* The emotion be to set
*/
ProfileMgr.Avatar.be = function(sEmotion) {
    Claim.isString(sEmotion, "ProfileMgr.Avatar.be(sEmotion) - sEmotion must be a string, expectedly - describing a supported emotion");
    if (null == this.Emotions[sEmotion]) {
        this.log.warn("ProfileMgr.Avatar.be(sEmotion) - invalid emotion is used: " + sEmotion);
        return;
    }
    this.objFAV.SetVariable("val", sEmotion);
    this.objFAV.SetVariable("command", "changeEmotion");
}
/**
* sets the zoom of the avatar
* 
* @param {string} sZoom
* The zoom to be set
*/
ProfileMgr.Avatar.zoom = function(sZoom) {
    Claim.isString(zoom, "ProfileMgr.Avatar.be(zoom) - zoom must be a string, expectedly - describing a supported zoom rate");

    this.objFAV.SetVariable("val", sZoom);
    this.objFAV.SetVariable("command", "setZoom");
}
/**
* Sets the avatar emotion to Happy
*/
ProfileMgr.Avatar.beHappy = function() {
    this.be("Happy");
}
/**
* Sets the avatar emotion to Sad
*/
ProfileMgr.Avatar.beSad = function() {
    this.be("Sad");
}



//--------------------------------------------------------
// SEATLE PORTLET AVATAR ON CLICK API
avatarOnClick = function() { }
/************ END /Javascript/2100/Diamond/Profile.js ***********/


/************ START /Javascript/2100/UserMedals.js ***********/
//-------------------------------------------------------
/** 
*  TC = Type C namespace
*/
if (window["TC"] == null) {
    TC = {};
}
//-------------------------------------------------------
TC.UserMedals = Class.create();
/**
* Normal  Ranking: 0 = best 1 = last
* Reverse Ranking: 1 = best 0 = last
**/
TC.UserMedals.reverseRanking = true;
/**
* Array of all medal-levels
**/
TC.UserMedals.All = [];
/**
* adds a new ranking level
*
* @param {double} sImg
* a number between 0 to 1 that ranks level of users in comparison to 
* thier community
*
* @param {string} sImg
* Relative path to the user-medal image
**/
TC.UserMedals.addRankingLevel = function(dblRanking, sImg) {
    var oLevel = new TC.UserMedals(dblRanking, sImg)
    this.All[this.All.length] = oLevel;
    this.All.sort();
}
/**
* Returns the Ranking Level by the user ranking
*
* @param {double} dblRanking
* The ranking of the user
**/
TC.UserMedals.getMedalByRanking = function(dblRanking) {
    var i;

    if (this.reverseRanking)
        dblRanking = 1 - dblRanking;

    for (i = 0; i < this.All.length; i++)
        if (dblRanking <= this.All[i].ranking)
        return this.All[i];
}
/**
*@private
* Constructor of Ranking-Level object
*
* @param {double} dblRanking
* @param {string} sImg
* The ranking of the user
**/
TC.UserMedals.prototype.initialize = function(dblRanking, sImg) {
    this.img = sImg;
    this.ranking = dblRanking;
}
/**
* @private
* override of  Object.toString(), for the Array.sort()
**/
TC.UserMedals.prototype.toString = function() {
    return this.ranking;
}
/**
* MpRanking class stores the images of the ranking levels for the mp
**/
TC.MpRanking = Class.create();
/**
* Array of all ranking-levels
**/
TC.MpRanking.All = [];
/**
* Holds the maximum upper bound for the ranking (2000+)
*/
TC.MpRanking.MaximumRanking = {};
/**
*@private
* Constructor of Ranking-Level object
*
* @param {integer} score
* @param {string} image
* The ranking of the user
**/
TC.MpRanking.prototype.initialize = function(score, image) {
    this.score = score;
    this.image = image;
}
/**
* adds a new ranking level for multiplayer game
*
* @param {integer} score
* @param {string} image
**/
TC.MpRanking.addRankingLevel = function(score, image) {
    var oLevel = new TC.MpRanking(score, image);
    this.All[this.All.length] = oLevel;
}
/**
* adds a the upper bound ranking level for multiplayer game
*
* @param {integer} score
* @param {string} image
**/
TC.MpRanking.addMaximumRankingLevel = function(score, image) {
    this.MaximumRanking = new TC.MpRanking(score, image);
}
/**
* Returns the Ranking Level by the user score
*
* @param {integer} score
* The ranking of the user
**/
TC.MpRanking.getMpRankingByScore = function(score) {
    for (var i = 0; i < this.All.length; i++) {
        if (score <= this.All[i].score)
            return this.All[i];
    }
    if (this.MaximumRanking && score >= this.MaximumRanking.score)
        return this.MaximumRanking;
    return null;
}

/************ END /Javascript/2100/UserMedals.js ***********/


//:::Membership Static 00:00:01.1560280

Membership={};Membership.AccountReturnedStatus={};Membership.AccountReturnedStatus.OK=0;Membership.AccountReturnedStatus.ACCOUNT_ERROR=1;Membership.AccountReturnedStatus.INVALID_PARAMETERS=2;Membership.AccountReturnedStatus.USER_LOGGED_OFF=4;Membership.AccountReturnedStatus.USERNAME_PASSWORD_MISMATCH=8;Membership.AccountReturnedStatus.USER_BLOCKED=16;Membership.AccountReturnedStatus.USERNAME_USED=32;Membership.AccountReturnedStatus.NICKNAME_USED=64;Membership.AccountReturnedStatus.ACCOUNT_NOT_CREATED=128;Membership.AccountReturnedStatus.CAPTCHA_MISMATCH=256;Membership.Params={};Membership.Params.ERROR_CODE='errorCode';Membership.Params.CHANNEL_CODE='channel';Membership.Params.LANGUAGE_CODE='lc';Membership.Params.USERNAME='username';Membership.Params.EMAIL='email';Membership.Params.PASSWORD='password';Membership.Params.CURRENT_PASSWORD='currentPassword';Membership.Params.REMEMBER='remember';Membership.Params.RETURN_URL='retUrl';Membership.Params.FAIL_URL='failUrl';Membership.Params.THANK_URL='thankUrl';Membership.Params.COMMAND='cmd';Membership.Params.TAB='tab';Membership.Params.VERIFY_EMAIL='verifyEmail';Membership.Params.IS_BASIC='isBasic';Membership.loginUrl;Membership.directLoginUrl;Membership.createAccountUrl;Membership.resetPasswordUrl;Membership.guestLoginUrl;Membership.userInfo={};Membership.userInfo.profileSummaryUrl;Membership.userInfo.personalInfoUrl;Membership.userInfo.fasUrl;Membership.userInfo.tokensUrl;Membership.userInfo.recentGamesUrl;Membership.userInfo.highscoresUrl;Membership.userInfo.userPassUrl;Membership.userInfo.billingDetails
Membership.userInfo.editBillingDetails
Membership.emailRegex;Membership.loginPasswordRegex;Membership.channelCode;Membership.languageCode;Membership.getFinalUrl=function(target,thankUrl,retUrl,failUrl,additionalParameters)
{var params;if(additionalParameters)
params=additionalParameters;else
params={};if(thankUrl)
params[Membership.Params.THANK_URL]=thankUrl;if(retUrl)
params[Membership.Params.RETURN_URL]=retUrl;if(failUrl)
params[Membership.Params.FAIL_URL]=failUrl;params[Membership.Params.CHANNEL_CODE]=Membership.channelCode;params[Membership.Params.LANGUAGE_CODE]=Membership.languageCode;var oTarget=Url.parse(target);oTarget.withClearanceParams=true;Object.extend(oTarget.params,params);var finalTarget=Url.relativeUrl(oTarget);var user=new UA.User();if(!user.IsLoggedOn())
finalTarget+='&ui=none';return finalTarget;}
Membership.getFinalDirectLoginUrl=function(target,thankUrl,retUrl,failUrl,username,password,remember,additionalParameters)
{var params;if(additionalParameters)
params=additionalParameters;else
params={};params[Membership.Params.USERNAME]=username;params[Membership.Params.PASSWORD]=password;params[Membership.Params.REMEMBER]=remember;var finalTarget=Membership.getFinalUrl(target,thankUrl,retUrl,failUrl,params);return finalTarget;}
Membership.isValidUsername=function(username)
{var isValid=Membership.usernameRegex.test(username);return isValid;}
Membership.isValidLoginPassword=function(password)
{var isValid=Membership.loginPasswordRegex.test(password);return isValid;}
Membership.DirectLogin=function(retUrl,failUrl,username,password,rememberMe,isBasic)
{var params={};params[Membership.Params.IS_BASIC]=isBasic;var directLoginUrl=Membership.getFinalDirectLoginUrl(Membership.directLoginUrl,null,retUrl,failUrl,username,password,rememberMe,params);location.href=directLoginUrl;}
Membership.DirectBasicRegistration=function(retUrl,failUrl,useInternalThankPage,username,password,rememberMe,email)
{var params={};params[Membership.Params.USERNAME]=username;params[Membership.Params.PASSWORD]=password;params[Membership.Params.EMAIL]=email;params[Membership.Params.REMEMBER]=rememberMe;params[Membership.Params.IS_BASIC]=true;var thankUrl=useInternalThankPage?null:retUrl;var directCreateAccountUrl=Membership.getFinalUrl(Membership.directCreateAccountUrl,thankUrl,retUrl,failUrl,params);location.href=directCreateAccountUrl;}
Membership.DirectChangePassword=function(retUrl,failUrl,oldPass,newPass)
{var params={};params[Membership.Params.CURRENT_PASSWORD]=oldPass;params[Membership.Params.PASSWORD]=newPass;var directUpdateUrl=Membership.getFinalUrl(Membership.directUpdateUrl,null,retUrl,failUrl,params);location.href=directUpdateUrl;}
Membership.DirectForgotPassword=function(retUrl,failUrl,useInternalThankPage,username,verifyEmail)
{var params={};params[Membership.Params.USERNAME]=username;params[Membership.Params.VERIFY_EMAIL]=verifyEmail;var thankUrl=useInternalThankPage?null:retUrl;var directForgotPasswordUrl=Membership.getFinalUrl(Membership.directForgotPasswordUrl,thankUrl,retUrl,failUrl,params);location.href=directForgotPasswordUrl;}
//:::Membership Init 00:00:01.1716500

// TODO: Change the hard coded strings to use the consts
Membership.loginUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=login";
Membership.logoutUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=logout";
Membership.directLoginUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=directlogin";
Membership.createAccountUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=createaccount";
Membership.directCreateAccountUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=directcreateaccount";
Membership.forgotPasswordUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=forgotpass";
Membership.directForgotPasswordUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=directforgotpass";
Membership.guestLoginUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=loginguest";
Membership.directUpdateUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=directupdate";
Membership.userInfo.profileSummaryUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=edit&tab=profilesummary";
Membership.userInfo.personalInfoUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=edit&tab=personalinfo";
Membership.userInfo.fasUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=edit&tab=fas";
Membership.userInfo.tokensUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=edit&tab=tokens";
Membership.userInfo.recentGamesUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=edit&tab=recentgames";
Membership.userInfo.highscoresUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=edit&tab=highscores";
Membership.userInfo.userPassUrl = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=edit&tab=userpass";
Membership.userInfo.billingDetails = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=edit&tab=billingdetails";
Membership.userInfo.editBillingDetails = "https://secure.betaregion.omiverify.com/membership/3000/App/JCT/EntryPoint.aspx?cmd=edit&tab=editbillingdetails";

Membership.usernameRegex = new RegExp('([a-zA-Z0-9_\\-\\.]+)@(([[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})$');
Membership.loginPasswordRegex = new RegExp('/^\\S.{5,11}$/');

Membership.channelCode = 110035530;
var lowerCaseLangCode = 'en';
lowerCaseLangCode = lowerCaseLangCode.toLowerCase();
Membership.languageCode = lowerCaseLangCode;


//::: Omniture Web Analysis 00:00:01.1716500


/************* DO NOT ALTER ANYTHING BELOW THIS LINE ! **************/
var s_objectID;function s_c2fe(f){var x='',s=0,e,a,b,c;while(1){e=
f.indexOf('"',s);b=f.indexOf('\\',s);c=f.indexOf("\n",s);if(e<0||(b>=
0&&b<e))e=b;if(e<0||(c>=0&&c<e))e=c;if(e>=0){x+=(e>s?f.substring(s,e):
'')+(e==c?'\\n':'\\'+f.substring(e,e+1));s=e+1}else return x
+f.substring(s)}return f}function s_c2fa(f){var s=f.indexOf('(')+1,e=
f.indexOf(')'),a='',c;while(s>=0&&s<e){c=f.substring(s,s+1);if(c==',')
a+='","';else if(("\n\r\t ").indexOf(c)<0)a+=c;s++}return a?'"'+a+'"':
a}function s_c2f(cc){cc=''+cc;var fc='var f=new Function(',s=
cc.indexOf(';',cc.indexOf('{')),e=cc.lastIndexOf('}'),o,a,d,q,c,f,h,x
fc+=s_c2fa(cc)+',"var s=new Object;';c=cc.substring(s+1,e);s=
c.indexOf('function');while(s>=0){d=1;q='';x=0;f=c.substring(s);a=
s_c2fa(f);e=o=c.indexOf('{',s);e++;while(d>0){h=c.substring(e,e+1);if(
q){if(h==q&&!x)q='';if(h=='\\')x=x?0:1;else x=0}else{if(h=='"'||h=="'"
)q=h;if(h=='{')d++;if(h=='}')d--}if(d>0)e++}c=c.substring(0,s)
+'new Function('+(a?a+',':'')+'"'+s_c2fe(c.substring(o+1,e))+'")'
+c.substring(e+1);s=c.indexOf('function')}fc+=s_c2fe(c)+';return s");'
eval(fc);return f}function s_gi(un,pg,ss){var c="function s_c(un,pg,s"
+"s){var s=this;s.wd=window;if(!s.wd.s_c_in){s.wd.s_c_il=new Array;s."
+"wd.s_c_in=0;}s._il=s.wd.s_c_il;s._in=s.wd.s_c_in;s._il[s._in]=s;s.w"
+"d.s_c_in++;s.m=function(m){return (''+m).indexOf('{')<0};s.fl=funct"
+"ion(x,l){return x?(''+x).substring(0,l):x};s.co=function(o){if(!o)r"
+"eturn o;var n=new Object,x;for(x in o)if(x.indexOf('select')<0&&x.i"
+"ndexOf('filter')<0)n[x]=o[x];return n};s.num=function(x){x=''+x;for"
+"(var p=0;p<x.length;p++)if(('0123456789').indexOf(x.substring(p,p+1"
+"))<0)return 0;return 1};s.rep=function(x,o,n){var i=x.indexOf(o);wh"
+"ile(x&&i>=0){x=x.substring(0,i)+n+x.substring(i+o.length);i=x.index"
+"Of(o,i+n.length)}return x};s.ape=function(x){var s=this,i;x=x?s.rep"
+"(escape(''+x),'+','%2B'):x;if(x&&s.charSet&&s.em==1&&x.indexOf('%u'"
+")<0&&x.indexOf('%U')<0){i=x.indexOf('%');while(i>=0){i++;if(('89ABC"
+"DEFabcdef').indexOf(x.substring(i,i+1))>=0)return x.substring(0,i)+"
+"'u00'+x.substring(i);i=x.indexOf('%',i)}}return x};s.epa=function(x"
+"){var s=this;return x?unescape(s.rep(''+x,'+',' ')):x};s.pt=functio"
+"n(x,d,f,a){var s=this,t=x,z=0,y,r;while(t){y=t.indexOf(d);y=y<0?t.l"
+"ength:y;t=t.substring(0,y);r=s.m(f)?s[f](t,a):f(t,a);if(r)return r;"
+"z+=y+d.length;t=x.substring(z,x.length);t=z<x.length?t:''}return ''"
+"};s.isf=function(t,a){var c=a.indexOf(':');if(c>=0)a=a.substring(0,"
+"c);if(t.substring(0,2)=='s_')t=t.substring(2);return (t!=''&&t==a)}"
+";s.fsf=function(t,a){var s=this;if(s.pt(a,',','isf',t))s.fsg+=(s.fs"
+"g!=''?',':'')+t;return 0};s.fs=function(x,f){var s=this;s.fsg='';s."
+"pt(x,',','fsf',f);return s.fsg};s.c_d='';s.c_gdf=function(t,a){var "
+"s=this;if(!s.num(t))return 1;return 0};s.c_gd=function(){var s=this"
+",d=s.wd.location.hostname,n=s.fpCookieDomainPeriods,p;if(!n)n=s.coo"
+"kieDomainPeriods;if(d&&!s.c_d){n=n?parseInt(n):2;n=n>2?n:2;p=d.last"
+"IndexOf('.');if(p>=0){while(p>=0&&n>1){p=d.lastIndexOf('.',p-1);n--"
+"}s.c_d=p>0&&s.pt(d,'.','c_gdf',0)?d.substring(p):d}}return s.c_d};s"
+".c_r=function(k){var s=this;k=s.ape(k);var c=' '+s.d.cookie,i=c.ind"
+"exOf(' '+k+'='),e=i<0?i:c.indexOf(';',i),v=i<0?'':s.epa(c.substring"
+"(i+2+k.length,e<0?c.length:e));return v!='[[B]]'?v:''};s.c_w=functi"
+"on(k,v,e){var s=this,d=s.c_gd(),l=s.cookieLifetime,t;v=''+v;l=l?(''"
+"+l).toUpperCase():'';if(e&&l!='SESSION'&&l!='NONE'){t=(v!=''?parseI"
+"nt(l?l:0):-60);if(t){e=new Date;e.setTime(e.getTime()+(t*1000))}}if"
+"(k&&l!='NONE'){s.d.cookie=k+'='+s.ape(v!=''?v:'[[B]]')+'; path=/;'+"
+"(e&&l!='SESSION'?' expires='+e.toGMTString()+';':'')+(d?' domain='+"
+"d+';':'');return s.c_r(k)==v}return 0};s.eh=function(o,e,r,f){var s"
+"=this,b='s_'+e+'_'+s._in,n=-1,l,i,x;if(!s.ehl)s.ehl=new Array;l=s.e"
+"hl;for(i=0;i<l.length&&n<0;i++){if(l[i].o==o&&l[i].e==e)n=i}if(n<0)"
+"{n=i;l[n]=new Object}x=l[n];x.o=o;x.e=e;f=r?x.b:f;if(r||f){x.b=r?0:"
+"o[e];x.o[e]=f}if(x.b){x.o[b]=x.b;return b}return 0};s.cet=function("
+"f,a,t,o,b){var s=this,r;if(s.apv>=5&&(!s.isopera||s.apv>=7))eval('t"
+"ry{r=s.m(f)?s[f](a):f(a)}catch(e){r=s.m(t)?s[t](e):t(e)}');else{if("
+"s.ismac&&s.u.indexOf('MSIE 4')>=0)r=s.m(b)?s[b](a):b(a);else{s.eh(s"
+".wd,'onerror',0,o);r=s.m(f)?s[f](a):f(a);s.eh(s.wd,'onerror',1)}}re"
+"turn r};s.gtfset=function(e){var s=this;return s.tfs};s.gtfsoe=new "
+"Function('e','var s=s_c_il['+s._in+'];s.eh(window,\"onerror\",1);s."
+"etfs=1;var c=s.t();if(c)s.d.write(c);s.etfs=0;return true');s.gtfsf"
+"b=function(a){return window};s.gtfsf=function(w){var s=this,p=w.par"
+"ent,l=w.location;s.tfs=w;if(p&&p.location!=l&&p.location.host==l.ho"
+"st){s.tfs=p;return s.gtfsf(s.tfs)}return s.tfs};s.gtfs=function(){v"
+"ar s=this;if(!s.tfs){s.tfs=s.wd;if(!s.etfs)s.tfs=s.cet('gtfsf',s.tf"
+"s,'gtfset',s.gtfsoe,'gtfsfb')}return s.tfs};s.ca=function(){var s=t"
+"his,imn='s_i_'+s.fun;if(s.d.images&&s.apv>=3&&(!s.isopera||s.apv>=7"
+")&&(s.ns6<0||s.apv>=6.1)){s.ios=1;if(!s.d.images[imn]&&(!s.isns||(s"
+".apv<4||s.apv>=5))){s.d.write('<im'+'g name=\"'+imn+'\" height=1 wi"
+"dth=1 border=0 alt=\"\">');if(!s.d.images[imn])s.ios=0}}};s.mr=func"
+"tion(sess,q,ta){var s=this,dc=s.dc,t1=s.trackingServer,t2=s.trackin"
+"gServerSecure,ns=s.visitorNamespace,unc=s.rep(s.fun,'_','-'),imn='s"
+"_i_'+s.fun,im,b,e,rs='http'+(s.ssl?'s':'')+'://'+(t1?(s.ssl&&t2?t2:"
+"t1):((ns?ns:(s.ssl?'102':unc))+'.'+(s.dc?s.dc:112)+'.2o7.net'))+'/b"
+"/ss/'+s.un+'/1/H.9-pdv-2/'+sess+'?[AQB]&ndh=1'+(q?q:'')+(s.q?s.q:''"
+")+'&[AQE]';if(s.isie&&!s.ismac){if(s.apv>5.5)rs=s.fl(rs,4095);else "
+"rs=s.fl(rs,2047)}if(s.ios||s.ss){if (!s.ss)s.ca();im=s.wd[imn]?s.wd"
+"[imn]:s.d.images[imn];if(!im)im=s.wd[imn]=new Image;im.src=rs;if(rs"
+".indexOf('&pe=')>=0&&(!ta||ta=='_self'||ta=='_top'||(s.wd.name&&ta="
+"=s.wd.name))){b=e=new Date;while(e.getTime()-b.getTime()<500)e=new "
+"Date}return ''}return '<im'+'g sr'+'c=\"'+rs+'\" width=1 height=1 b"
+"order=0 alt=\"\">'};s.gg=function(v){var s=this;return s.wd['s_'+v]"
+"};s.glf=function(t,a){if(t.substring(0,2)=='s_')t=t.substring(2);va"
+"r s=this,v=s.gg(t);if(v)s[t]=v};s.gl=function(v){var s=this;s.pt(v,"
+"',','glf',0)};s.gv=function(v){var s=this;return s['vpm_'+v]?s['vpv"
+"_'+v]:(s[v]?s[v]:'')};s.havf=function(t,a){var s=this,b=t.substring"
+"(0,4),x=t.substring(4),n=parseInt(x),k='g_'+t,m='vpm_'+t,q=t,v=s.li"
+"nkTrackVars,e=s.linkTrackEvents;s[k]=s.gv(t);if(s.lnk||s.eo){v=v?v+"
+"','+s.vl_l:'';if(v&&!s.pt(v,',','isf',t))s[k]='';if(t=='events'&&e)"
+"s[k]=s.fs(s[k],e)}s[m]=0;if(t=='visitorID')q='vid';else if(t=='page"
+"URL')q='g';else if(t=='referrer')q='r';else if(t=='vmk')q='vmt';els"
+"e if(t=='charSet'){q='ce';if(s[k]&&s.em==2)s[k]='UTF-8'}else if(t=="
+"'visitorNamespace')q='ns';else if(t=='cookieDomainPeriods')q='cdp';"
+"else if(t=='cookieLifetime')q='cl';else if(t=='variableProvider')q="
+"'vvp';else if(t=='currencyCode')q='cc';else if(t=='channel')q='ch';"
+"else if(t=='campaign')q='v0';else if(s.num(x)) {if(b=='prop')q='c'+"
+"n;else if(b=='eVar')q='v'+n;else if(b=='hier'){q='h'+n;s[k]=s.fl(s["
+"k],255)}}if(s[k]&&t!='linkName'&&t!='linkType')s.qav+='&'+q+'='+s.a"
+"pe(s[k]);return ''};s.hav=function(){var s=this;s.qav='';s.pt(s.vl_"
+"t,',','havf',0);return s.qav};s.lnf=function(t,h){t=t?t.toLowerCase"
+"():'';h=h?h.toLowerCase():'';var te=t.indexOf('=');if(t&&te>0&&h.in"
+"dexOf(t.substring(te+1))>=0)return t.substring(0,te);return ''};s.l"
+"n=function(h){var s=this,n=s.linkNames;if(n)return s.pt(n,',','lnf'"
+",h);return ''};s.ltdf=function(t,h){t=t?t.toLowerCase():'';h=h?h.to"
+"LowerCase():'';var qi=h.indexOf('?');h=qi>=0?h.substring(0,qi):h;if"
+"(t&&h.substring(h.length-(t.length+1))=='.'+t)return 1;return 0};s."
+"ltef=function(t,h){t=t?t.toLowerCase():'';h=h?h.toLowerCase():'';if"
+"(t&&h.indexOf(t)>=0)return 1;return 0};s.lt=function(h){var s=this,"
+"lft=s.linkDownloadFileTypes,lef=s.linkExternalFilters,lif=s.linkInt"
+"ernalFilters;lif=lif?lif:s.wd.location.hostname;h=h.toLowerCase();i"
+"f(s.trackDownloadLinks&&lft&&s.pt(lft,',','ltdf',h))return 'd';if(s"
+".trackExternalLinks&&(lef||lif)&&(!lef||s.pt(lef,',','ltef',h))&&(!"
+"lif||!s.pt(lif,',','ltef',h)))return 'e';return ''};s.lc=new Functi"
+"on('e','var s=s_c_il['+s._in+'],b=s.eh(this,\"onclick\");s.lnk=s.co"
+"(this);s.t();s.lnk=0;if(b)return this[b](e);return true');s.bc=new "
+"Function('e','var s=s_c_il['+s._in+'],f;if(s.d&&s.d.all&&s.d.all.cp"
+"pXYctnr)return;s.eo=e.srcElement?e.srcElement:e.target;eval(\"try{i"
+"f(s.eo&&(s.eo.tagName||s.eo.parentElement||s.eo.parentNode))s.t()}c"
+"atch(f){}\");s.eo=0');s.ot=function(o){var a=o.type,b=o.tagName;ret"
+"urn (a&&a.toUpperCase?a:b&&b.toUpperCase?b:o.href?'A':'').toUpperCa"
+"se()};s.oid=function(o){var s=this,t=s.ot(o),p=o.protocol,c=o.oncli"
+"ck,n='',x=0;if(!o.s_oid){if(o.href&&(t=='A'||t=='AREA')&&(!c||!p||p"
+".toLowerCase().indexOf('javascript')<0))n=o.href;else if(c){n=s.rep"
+"(s.rep(s.rep(s.rep(''+c,\"\\r\",''),\"\\n\",''),\"\\t\",''),' ','')"
+";x=2}else if(o.value&&(t=='INPUT'||t=='SUBMIT')){n=o.value;x=3}else"
+" if(o.src&&t=='IMAGE')n=o.src;if(n){o.s_oid=s.fl(n,100);o.s_oidt=x}"
+"}return o.s_oid};s.rqf=function(t,un){var s=this,e=t.indexOf('='),u"
+"=e>=0?','+t.substring(0,e)+',':'';return u&&u.indexOf(','+un+',')>="
+"0?s.epa(t.substring(e+1)):''};s.rq=function(un){var s=this,c=un.ind"
+"exOf(','),v=s.c_r('s_sq'),q='';if(c<0)return s.pt(v,'&','rqf',un);r"
+"eturn s.pt(un,',','rq',0)};s.sqp=function(t,a){var s=this,e=t.index"
+"Of('='),q=e<0?'':s.epa(t.substring(e+1));s.sqq[q]='';if(e>=0)s.pt(t"
+".substring(0,e),',','sqs',q);return 0};s.sqs=function(un,q){var s=t"
+"his;s.squ[un]=q;return 0};s.sq=function(q){var s=this,k='s_sq',v=s."
+"c_r(k),x,c=0;s.sqq=new Object;s.squ=new Object;s.sqq[q]='';s.pt(v,'"
+"&','sqp',0);s.pt(s.un,',','sqs',q);v='';for(x in s.squ)s.sqq[s.squ["
+"x]]+=(s.sqq[s.squ[x]]?',':'')+x;for(x in s.sqq)if(x&&s.sqq[x]&&(x=="
+"q||c<2)){v+=(v?'&':'')+s.sqq[x]+'='+s.ape(x);c++}return s.c_w(k,v,0"
+")};s.wdl=new Function('e','var s=s_c_il['+s._in+'],r=true,b=s.eh(s."
+"wd,\"onload\"),i,o,oc;if(b)r=this[b](e);for(i=0;i<s.d.links.length;"
+"i++){o=s.d.links[i];oc=o.onclick?\"\"+o.onclick:\"\";if((oc.indexOf"
+"(\"s_gs(\")<0||oc.indexOf(\".s_oc(\")>=0)&&oc.indexOf(\".tl(\")<0)s"
+".eh(o,\"onclick\",0,s.lc);}return r');s.wds=function(){var s=this;i"
+"f(s.apv>3&&(!s.isie||!s.ismac||s.apv>=5)){if(s.b&&s.b.attachEvent)s"
+".b.attachEvent('onclick',s.bc);else if(s.b&&s.b.addEventListener)s."
+"b.addEventListener('click',s.bc,false);else s.eh(s.wd,'onload',0,s."
+"wdl)}};s.vs=function(x){var s=this,v=s.visitorSampling,g=s.visitorS"
+"amplingGroup,k='s_vsn_'+s.un+(g?'_'+g:''),n=s.c_r(k),e=new Date,y=e"
+".getYear();e.setYear(y+10+(y<1900?1900:0));if(v){v*=100;if(!n){if(!"
+"s.c_w(k,x,e))return 0;n=x}if(n%10000>v)return 0}return 1};s.dyasmf="
+"function(t,m){if(t&&m&&m.indexOf(t)>=0)return 1;return 0};s.dyasf=f"
+"unction(t,m){var s=this,i=t?t.indexOf('='):-1,n,x;if(i>=0&&m){var n"
+"=t.substring(0,i),x=t.substring(i+1);if(s.pt(x,',','dyasmf',m))retu"
+"rn n}return 0};s.uns=function(){var s=this,x=s.dynamicAccountSelect"
+"ion,l=s.dynamicAccountList,m=s.dynamicAccountMatch,n,i;s.un.toLower"
+"Case();if(x&&l){if(!m)m=s.wd.location.host;if(!m.toLowerCase)m=''+m"
+";l=l.toLowerCase();m=m.toLowerCase();n=s.pt(l,';','dyasf',m);if(n)s"
+".un=n}i=s.un.indexOf(',');s.fun=i<0?s.un:s.un.substring(0,i)};s.sa="
+"function(un){s.un=un;if(!s.oun)s.oun=un;else if((','+s.oun+',').ind"
+"exOf(un)<0)s.oun+=','+un;s.uns()};s.t=function(){var s=this,trk=1,t"
+"m=new Date,sed=Math&&Math.random?Math.floor(Math.random()*100000000"
+"00000):tm.getTime(),sess='s'+Math.floor(tm.getTime()/10800000)%10+s"
+"ed,yr=tm.getYear(),vt=tm.getDate()+'/'+tm.getMonth()+'/'+(yr<1900?y"
+"r+1900:yr)+' '+tm.getHours()+':'+tm.getMinutes()+':'+tm.getSeconds("
+")+' '+tm.getDay()+' '+tm.getTimezoneOffset(),tfs=s.gtfs(),ta='',q='"
+"',qs='';s.uns();if(!s.q){var tl=tfs.location,x='',c='',v='',p='',bw"
+"='',bh='',j='1.0',k=s.c_w('s_cc','true',0)?'Y':'N',hp='',ct='',pn=0"
+",ps;if(s.apv>=4)x=screen.width+'x'+screen.height;if(s.isns||s.isope"
+"ra){if(s.apv>=3){j='1.1';v=s.n.javaEnabled()?'Y':'N';if(s.apv>=4){j"
+"='1.2';c=screen.pixelDepth;bw=s.wd.innerWidth;bh=s.wd.innerHeight;i"
+"f(s.apv>=4.06)j='1.3'}}s.pl=s.n.plugins}else if(s.isie){if(s.apv>=4"
+"){v=s.n.javaEnabled()?'Y':'N';j='1.2';c=screen.colorDepth;if(s.apv>"
+"=5){bw=s.d.documentElement.offsetWidth;bh=s.d.documentElement.offse"
+"tHeight;j='1.3';if(!s.ismac&&s.b){s.b.addBehavior('#default#homePag"
+"e');hp=s.b.isHomePage(tl)?\"Y\":\"N\";s.b.addBehavior('#default#cli"
+"entCaps');ct=s.b.connectionType}}}else r=''}if(s.pl)while(pn<s.pl.l"
+"ength&&pn<30){ps=s.fl(s.pl[pn].name,100)+';';if(p.indexOf(ps)<0)p+="
+"ps;pn++}s.q=(x?'&s='+s.ape(x):'')+(c?'&c='+s.ape(c):'')+(j?'&j='+j:"
+"'')+(v?'&v='+v:'')+(k?'&k='+k:'')+(bw?'&bw='+bw:'')+(bh?'&bh='+bh:'"
+"')+(ct?'&ct='+s.ape(ct):'')+(hp?'&hp='+hp:'')+(p?'&p='+s.ape(p):'')"
+"}if(s.usePlugins)s.doPlugins(s);var l=s.wd.location,r=tfs.document."
+"referrer;if(!s.pageURL)s.pageURL=s.fl(l?l:'',255);if(!s.referrer)s."
+"referrer=s.fl(r?r:'',255);if(s.lnk||s.eo){var o=s.eo?s.eo:s.lnk;if("
+"!o)return '';var p=s.gv('pageName'),w=1,t=s.ot(o),n=s.oid(o),x=o.s_"
+"oidt,h,l,i,oc;if(s.eo&&o==s.eo){while(o&&!n&&t!='BODY'){o=o.parentE"
+"lement?o.parentElement:o.parentNode;if(!o)return '';t=s.ot(o);n=s.o"
+"id(o);x=o.s_oidt}oc=o.onclick?''+o.onclick:'';if((oc.indexOf(\"s_gs"
+"(\")>=0&&oc.indexOf(\".s_oc(\")<0)||oc.indexOf(\".tl(\")>=0)return "
+"''}ta=n?o.target:1;h=o.href?o.href:'';i=h.indexOf('?');h=s.linkLeav"
+"eQueryString||i<0?h:h.substring(0,i);l=s.linkName?s.linkName:s.ln(h"
+");t=s.linkType?s.linkType.toLowerCase():s.lt(h);if(t&&(h||l))q+='&p"
+"e=lnk_'+(t=='d'||t=='e'?s.ape(t):'o')+(h?'&pev1='+s.ape(h):'')+(l?'"
+"&pev2='+s.ape(l):'');else trk=0;if(s.trackInlineStats){if(!p){p=s.g"
+"v('pageURL');w=0}t=s.ot(o);i=o.sourceIndex;if(s.gg('objectID')){n=s"
+".gg('objectID');x=1;i=1}if(p&&n&&t)qs='&pid='+s.ape(s.fl(p,255))+(w"
+"?'&pidt='+w:'')+'&oid='+s.ape(s.fl(n,100))+(x?'&oidt='+x:'')+'&ot='"
+"+s.ape(t)+(i?'&oi='+i:'')}}if(!trk&&!qs)return '';if(s.p_r)s.p_r();"
+"var code='';if(trk&&s.vs(sed))code=s.mr(sess,(vt?'&t='+s.ape(vt):''"
+")+s.hav()+q+(qs?qs:s.rq(s.un)),ta);s.sq(trk?'':qs);s.lnk=s.eo=s.lin"
+"kName=s.linkType=s.wd.s_objectID=s.ppu='';return code};s.tl=functio"
+"n(o,t,n){var s=this;s.lnk=s.co(o);s.linkType=t;s.linkName=n;s.t()};"
+"s.ssl=(s.wd.location.protocol.toLowerCase().indexOf('https')>=0);s."
+"d=document;s.b=s.d.body;s.n=navigator;s.u=s.n.userAgent;s.ns6=s.u.i"
+"ndexOf('Netscape6/');var apn=s.n.appName,v=s.n.appVersion,ie=v.inde"
+"xOf('MSIE '),o=s.u.indexOf('Opera '),i;if(v.indexOf('Opera')>=0||o>"
+"0)apn='Opera';s.isie=(apn=='Microsoft Internet Explorer');s.isns=(a"
+"pn=='Netscape');s.isopera=(apn=='Opera');s.ismac=(s.u.indexOf('Mac'"
+")>=0);if(o>0)s.apv=parseFloat(s.u.substring(o+6));else if(ie>0){s.a"
+"pv=parseInt(i=v.substring(ie+5));if(s.apv>3)s.apv=parseFloat(i)}els"
+"e if(s.ns6>0)s.apv=parseFloat(s.u.substring(s.ns6+10));else s.apv=p"
+"arseFloat(v);s.em=0;if(String.fromCharCode){i=escape(String.fromCha"
+"rCode(256)).toUpperCase();s.em=(i=='%C4%80'?2:(i=='%U0100'?1:0))}s."
+"sa(un);s.vl_l='visitorID,vmk,ppu,charSet,visitorNamespace,cookieDom"
+"ainPeriods,cookieLifetime,pageName,pageURL,referrer,currencyCode,pu"
+"rchaseID';s.vl_t=s.vl_l+',variableProvider,channel,server,pageType,"
+"campaign,state,zip,events,products,linkName,linkType';for(var n=1;n"
+"<51;n++)s.vl_t+=',prop'+n+',eVar'+n+',hier'+n;s.vl_g=s.vl_t+',track"
+"DownloadLinks,trackExternalLinks,trackInlineStats,linkLeaveQueryStr"
+"ing,linkDownloadFileTypes,linkExternalFilters,linkInternalFilters,l"
+"inkNames';if(pg)s.gl(s.vl_g);s.ss=ss;if(!ss){s.wds();s.ca()}}",
l=window.s_c_il,n=navigator,u=n.userAgent,v=n.appVersion,e=v.indexOf(
'MSIE '),m=u.indexOf('Netscape6/'),a,i,s;if(l)for(i=0;i<l.length;i++){
s=l[i];if(s.oun==un)return s;else if(s.fs(s.oun,un)){s.sa(un);return s
}}if(e>0){a=parseInt(i=v.substring(e+5));if(a>3)a=parseFloat(i)}
else if(m>0)a=parseFloat(u.substring(m+10));else a=parseFloat(v);if(a
>=5&&v.indexOf('Opera')<0&&u.indexOf('Opera')<0){eval(c);return new
s_c(un,pg,ss)}else s=s_c2f(c);return s(un,pg,ss)}



//::: Omniture Web Analysis 00:00:01.2028940

String.prototype.trim=function(){var spacesRegEx=/^[ \t\n]+|[ \t\n]+$/g;return this.replace(spacesRegEx,"");}
if(!window.GameCatalog)
GameCatalog={};if(!GameCatalog.WebAnalysis)
GameCatalog.WebAnalysis={};if(!GameCatalog.WebAnalysis.SiteTracking)
GameCatalog.WebAnalysis.SiteTracking={};GameCatalog.WebAnalysis.SiteTracking.GetInternalID=function()
{return Url.here.params.intID||'';}
GameCatalog.WebAnalysis.SiteTracking.Replacer=function(str)
{this.rep=function(a)
{var result=GameCatalog.WebAnalysis.SiteTracking.Replacer.symbols[a]();if(result==null||result==undefined)
return a;else
return result;}
if(str===undefined||str===null)
return'';return(str+'').replace(/(%%[^%]*%%)/g,this.rep).trim();}
GameCatalog.WebAnalysis.SiteTracking.hashCurrentSParams={};GameCatalog.WebAnalysis.SiteTracking.PreparePageParams=function(pageName,data)
{var pageData=GameCatalog.WebAnalysis.SiteTracking[pageName];if(pageData==null&&data!=null)
pageData=data;else if(pageData==null&&data==null)
return;GameCatalog.WebAnalysis.SiteTracking.ClearParams();for(p in pageData)
{if(typeof(pageData[p])=='function')
{try{s[p]=pageData[p]();}
catch(ex)
{s[p]="";}}
else
s[p]=pageData[p];GameCatalog.WebAnalysis.SiteTracking.hashCurrentSParams[p]="";}}
GameCatalog.WebAnalysis.SiteTracking.trackCustomLinkClicked=function(obj,linkName,data)
{if(obj==null||obj==undefined)
return;GameCatalog.WebAnalysis.SiteTracking.PreparePageParams("GameShellCustomLink",data);var lt=obj.href!=null?s.lt(obj.href):"";if(lt==""){s.tl(obj,'o',linkName);}}
GameCatalog.WebAnalysis.SiteTracking.submitEvent=function(pageName,data)
{GameCatalog.WebAnalysis.SiteTracking.PreparePageParams(pageName,data);s.t();}
GameCatalog.WebAnalysis.SiteTracking.ClearParams=function()
{for(p in GameCatalog.WebAnalysis.SiteTracking.hashCurrentSParams)
{delete s[p];}
GameCatalog.WebAnalysis.SiteTracking.hashCurrentSParams={};}
function GetScriptSrcQueryString()
{var src="";var pageName=GetPageName();src="pagefilename="+pageName;src+="&"+document.location.search.substr(1);return src;}
function GetPageName()
{var name=document.location.pathname.split("/")[document.location.pathname.split("/").length-1].split(".")[0];if(name)
name=name.toLowerCase();return name||"homepage";}
function getCookie(name){var index=document.cookie.indexOf(name+"=");if(index==-1)return null;index=document.cookie.indexOf("=",index)+1;var endstr=document.cookie.indexOf(";",index);if(endstr==-1)endstr=document.cookie.length;return unescape(document.cookie.substring(index,endstr));}
function setCookie(name,value,expiration){GameCatalog.WebAnalysis.SiteTracking.setCookie(name,value,expiration)}
GameCatalog.WebAnalysis.SiteTracking.setCookie=function(name,value,expiration)
{try{var strDate=new String();strDate=value.toString();while(strDate.indexOf(" ")!=-1){strDate=strDate.replace(" ","%20");}
while(strDate.indexOf(":")!=-1){strDate=strDate.replace(":","%3A");}
strDate=strDate.replace("+","%2B");strDate=strDate.replace("-","%2D");var today=new Date();var expiry=new Date(today.getTime()+expiration*24*60*60*1000);if(strDate!=null&&strDate!=""){document.cookie=name+"="+strDate+"; expires="+expiry.toGMTString();}}
catch(er){}}
function omnitureLogDownloadCover(gameCode,gameName)
{GameCatalog.WebAnalysis.SiteTracking.omnitureLogDownloadCover(gameCode,gameName);}
GameCatalog.WebAnalysis.SiteTracking.omnitureLogDownloadCover=function(gameCode,gameName)
{var expirationPeriod=180
var today=new Date();try{GameCatalog.WebAnalysis.SiteTracking.setCookie(gameCode,today,expirationPeriod);s.linkType="d";s.events="event1";s.eVar11=GameCatalog.WebAnalysis.SiteTracking.DownloadOmnitureFormattedDate();s.tl(this,"d",gameName);}
catch(er){}}
function DownloadOmnitureFormattedDate()
{return GameCatalog.WebAnalysis.SiteTracking.DownloadOmnitureFormattedDate();}
GameCatalog.WebAnalysis.SiteTracking.DownloadOmnitureFormattedDate=function()
{var date=new Date();hours=date.getUTCHours();minutes=date.getUTCMinutes();seconds=date.getUTCSeconds();var suffix="AM";if(hours>=12){suffix="PM";hours=hours-12;}
if(hours==0){hours=12;}
if(minutes<10)
minutes="0"+minutes
if(seconds<10)
seconds="0"+seconds
return(date.getUTCMonth()+1)+"/"+date.getUTCDate()+"/"+date.getUTCFullYear()+" "+hours+":"+minutes+":"+seconds+" "+suffix;}
function logDownload(gameCode,omnitureChannel){GameCatalog.WebAnalysis.SiteTracking.logDownload(gameCode,omnitureChannel);}
GameCatalog.WebAnalysis.SiteTracking.logDownload=function(gameCode,omnitureChannel)
{s.linkName=gameCode;s.products=";"+gameCode;GameCatalog.WebAnalysis.SiteTracking.omnitureLogDownloadCover(gameCode,gameCode);}
function omnitureLogDownload(gameCode,omnitureChannel,gameReportName){return GameCatalog.WebAnalysis.SiteTracking.omnitureLogDownload(gameCode,omnitureChannel,gameReportName);}
GameCatalog.WebAnalysis.SiteTracking.omnitureLogDownload=function(gameCode,omnitureChannel,gameReportName)
{try{s.linkName=gameReportName;s.products=";"+gameReportName;GameCatalog.WebAnalysis.SiteTracking.omnitureLogDownloadCover(gameCode,gameReportName);}
catch(er){}
return true;}
function omnitureLogDownload_Real(gameCode,omnitureChannel,gameName,catName,dlDateTime){return GameCatalog.WebAnalysis.SiteTracking.omnitureLogDownload_Real(gameCode,omnitureChannel,gameName,catName,dlDateTime);}
GameCatalog.WebAnalysis.SiteTracking.omnitureLogDownload_Real=function(gameCode,omnitureChannel,gameName,catName,dlDateTime)
{try{s.linkName=gameName;s.products=catName+";"+gameName;GameCatalog.WebAnalysis.SiteTracking.omnitureLogDownloadCover(gameCode,gameName);}
catch(e){}
return true;}
function getTimeBucket(oDate)
{try{var today=new Date();var downloadDate=new Date(oDate);var timeGap
timeGap=((today.getTime()-downloadDate.getTime())/(60*60*1000))
var timeBucket
if(downloadDate.getTime()==0||isNaN(timeGap)){timeBucket="Unknown";}else if(timeGap>=0&&timeGap<1){timeBucket="0-1 Hours";}else if(timeGap>=1&&timeGap<2){timeBucket="1-2 Hours";}else if(timeGap>=2&&timeGap<4){timeBucket="2-4 Hours";}else if(timeGap>=4&&timeGap<6){timeBucket="4-6 Hours";}else if(timeGap>=6&&timeGap<12){timeBucket="6-12 Hours";}else if(timeGap>=12&&timeGap<24){timeBucket="1 Day";}else if(timeGap>=1*24&&timeGap<2*24){timeBucket="2 Days";}else if(timeGap>=2*24&&timeGap<3*24){timeBucket="3 Days";}else if(timeGap>=3*24&&timeGap<4*24){timeBucket="4 Days";}else if(timeGap>=4*24&&timeGap<5*24){timeBucket="5 Days";}else if(timeGap>=5*24&&timeGap<6*24){timeBucket="6 Days";}else if(timeGap>=6*24&&timeGap<7*24){timeBucket="7 Days";}else if(timeGap>=1*24*7&&timeGap<2*24*7){timeBucket="1-2 Weeks";}else if(timeGap>=2*24*7&&timeGap<4*24*7){timeBucket="2-4 Weeks";}else if(timeGap>=1*24*7*4&&timeGap<2*24*7*4){timeBucket="1-2 Months";}else{timeBucket=" > 2 Months";}
return timeBucket;}
catch(er){return"Unknown";}}

// Report downloads using WebAnalysis 
function GameCenterOmnitureLogDownload(gameCode, gameName,catName) {
	return omnitureLogDownload_Real(gameCode, null, gameName, catName, null);
}

//::: DynamicGizmos
var O = window.O || {};
O.Model = O.Model || {};

