var JSON_TYPE='JSON';var DEBUG_OFF='Off';var DEBUG_ON='On';class TPusa{constructor(){this.Events=[];this.Requests=[];this.Groups=[];this.Debug=DEBUG_OFF;this.LastRequests=[];this.EventTimeouts=[];this.Pile=[];this.CountJob=0;this.Arguments=[];this.Focus=[];}static Create(){return new TPusa();}Request ( APrm ){if( MatchData( APrm.Filter, APrm.Event ) ){if( APrm.Timeout ){var Key=( APrm.Event ? APrm.Event.type + '.':'' ) + APrm.Class + '.' + APrm.Method + '.' + ( APrm.Element && APrm.Element.id ? APrm.Element.id + '.':'' ) + ( APrm.Element && APrm.Element.className ? APrm.Element.className + '.':'' );if( this.Events[Key]){clearInterval( this.Events[Key]);}this.Events[Key]=setTimeout ( ()=> this.Send( APrm ), APrm.Timeout );}else{this.Send( APrm );}}return this;}Send ( APrm ){var EventName=APrm.Event ? APrm.Event.type:null;var IDRequest=APrm.IDRequest ? APrm.IDRequest:clGUID();var Data=null;var AttributesString=null;var ElementString=null;var Data=new FormData();var Request=this.RequestNew ({Element:APrm.Element, EventName:EventName, ID:IDRequest});if( Request ){if( APrm.Arguments ){for( let Key in APrm.Arguments ){Data.append ( Key, ( typeof APrm.Arguments[Key]==='object' ) ? JSON.stringify( APrm.Arguments[Key]):APrm.Arguments[Key])}}Data.append( 'IDRequest' , IDRequest );Data.append( 'TypeContent' , JSON_TYPE );Data.append( 'Pusa' , APrm.Class );Data.append( 'Method' , APrm.Method );Data.append( 'URL' , window.location.href );if( APrm.Element && APrm.Element instanceof File ){Data.append( 'Blob', APrm.Element );}Request.Self=APrm.Element;if( APrm.Events ){APrm.Events.forEach ( Rule=>{let EventName=Rule['Event'];let Class=Rule['Class'];let Method=Rule['Method'];if( EventName && Class && Method ){Request.upload.addEventListener ( EventName, e=>{this.Request ({Event:e, Class:Class, Method:Method, Element:APrm.Element})});}})}Request.addEventListener ( 'loadend', Event=>{this.JobEnd();this.RequestRemove( Request );var Content=Event.target.response;var Result=null;try{Result=JSON.parse( Content );Request.Result=Result;}catch( e ){this.Warning( 'Error in JSON result' );}if( Result && Result.Header ){this.Commands ( Request.Result.Pusa, Request.Self, null, Event, APrm );if( Result.Header.Code!='Ok' ){this.Warning( Result.Header.Message );}}else{this.Warning( 'Unknown answer.' );}});Request.addEventListener ( 'error', ()=>{this.JobEnd();this.Warning( 'Pusa request error' );this.RequestRemove( Request );});Request.addEventListener ( 'abort', ()=>{this.RequestRemove( Request );this.Warning( 'Pusa request abort' );});this.Info( 'Pusa AJAX call ' + APrm.Class + '.' + APrm.Method );this.JobBegin();Request.open( 'POST', '?pusa=' + APrm.Class + '.' + APrm.Method );Request.send( Data );}return this;};SelectElements ( ASelf, AFrom, APrm ){var Result=[];function Push( AElement ){if( Result.indexOf( AElement )==-1 ){Result.push( AElement );}}AFrom=AFrom ? AFrom:[ASelf];switch( APrm.Target ){case 'Self':if( ASelf ) Push( ASelf );break;case 'Body':Push( window.document.body );break;case 'Window':Push( window );break;case 'Parent':for( var i in AFrom ){Push( AFrom[i].parentNode );}break;case 'Parents':for( var i in AFrom ){AFrom[i].Parents( APrm.Filter, e=> Push( e ));}break;case 'ParentFirst':for( var i in AFrom ){AFrom[i].Parent( APrm.Filter, e=> Push( e ));}break;case 'Children':for( var i in AFrom ){AFrom[i].Childs( APrm.Filter, e=> Push( e ));}break;case 'ChildrenOfThis':for( var i in AFrom ){AFrom[i].Childs( APrm.Filter, e=>( e ), 1 );}break;}return Result;}Commands ( ACommands, ASelf, AFocus, AEvent, ARequest ){var that=this;var Focuses=[];var Focus=AFocus ? AFocus:[ASelf];var Index=0;function CommandWarning( AMessage ){that.Warning ( AMessage + '.' + ( ARequest && ARequest.Class ? ' Class[' + ARequest.Class:'' ) + ']' + ( ARequest && ARequest.Method ? ' Method[' + ARequest.Method:'' ) + ']' + ' Directive[' + Index + ']' + JSON.stringify( ACommands[Index]) );}function SetFocus( $AFocus ){Focus=$AFocus;}function FocusIsFull(){if( Focus.length==0 ){CommandWarning( 'Focus is empty' );}return Focus.length!=0;}ACommands.forEach ( Line=>{var Command=Line[0]? Line[0]:'';var Prm=Line[1]? Line[1]:{};switch( Command ){default:CommandWarning( 'Unknown directive' );break;case 'Debug':this.Debug=Prm['Level'];break;case 'FocusPush':Focuses.push( Focus.slice() );break;case 'FocusPop':if( Focuses.length > 0 ){Focus=Focuses.pop();}else{Focus=[];CommandWarning( 'Focus stack is empty' );}break;case 'Set':if( Prm.Values && FocusIsFull()){Focus.forEach ( e=>{if( typeof e==='object' ){for( let Key in Prm.Values ){e[Key]=Prm.Values[Key];}}});}break;case 'Arg':if( Prm.Statics ){for( let Key in Prm.Statics ){this.Arguments[Key]=Prm.Statics[Key];}}if( Prm.Fields && FocusIsFull() ){Focus.forEach ( e=>{if( typeof e==='object' ){if( e.tagName=='FORM' ){for( let i=0;i < e.elements.length;i++ ){let Field=e.elements[i];let Key=Field.name;switch( Field.type){case 'checkbox':this.Arguments[Key]=Field.checked;break;case 'file':if( Prm.Class && Prm.Method ){let IDGroup=clGUID();this.Arguments[Key]=this.SendFiles( Field, IDGroup, Prm.Class, Prm.Method );this.Arguments['IDGroup']=IDGroup;}else{CommandWarning( 'No class or method for files upload' );}break;case 'radio':if( Field.checked ){this.Arguments[Key]=Field.value;}break;case 'button':break;default:this.Arguments[Key]=Field.value;break;}}}}});}if( Prm.Name ){if( Prm.JS ){this.Arguments[Prm.Name]=eval( Prm.JS );}if( Prm.Event && AEvent ){this.Arguments[Prm.Name]=AEvent[Prm.Event];}if(( Prm.Property || Prm.Method ) && FocusIsFull() ){Focus.forEach ( e=>{if( typeof e==='object' ){if( Prm.Property ){this.Arguments[Prm.Name]=e[Prm.Property];}if( Prm.Method && typeof e[Prm.Method]==='function' ){this.Arguments[Prm.Name]=e[Prm.Method].apply( e, Prm.Arguments );}else{CommandWarning( 'Method not exists' );}}});}}break;case 'Call':if( Prm.Method && FocusIsFull() ){Focus.forEach ( e=>{if ( typeof e=='object' && e[Prm.Method]&& typeof e[Prm.Method]=='function' ){e[Prm.Method].apply( e, Prm.Arguments );}});}break;case 'JS':eval( Prm );break;case 'Loop':if( Prm.Tasks && typeof Prm.Tasks==='object' && Prm.Commands ){Prm.Tasks.forEach ( r=>{var Commands=JSON.parse(JSON.stringify( Prm.Commands ));ReplaceInObject( Commands, r );TPusa.Create().Commands ( Commands, null, Focus, AEvent );})}break;case 'Event':if( !Prm.Event ) Prm.Event='click';if( !Prm.Timeout ) Prm.Timeout=0;if( FocusIsFull() ){Focus.forEach ( e=>{if( typeof e==='object' ){if( e.ReplaceEventListener ){e.ReplaceEventListener ( Prm.Event, event=>{if( MatchData( Prm.Filter, event )){let Arguments=[];if( Prm.Commands ){Arguments=TPusa.Create().Commands( Prm.Commands, e, null, event ).Arguments;}if( Prm.Class && Prm.Method && Prm.Event ){this.Request ({Event:event, Class:Prm.Class, Method:Prm.Method, Timeout:Prm.Timeout, Element:e, Filter:Prm.Filter, Arguments:Arguments});}if( Prm.JS ){eval( Prm.JS );}}if( Prm.Catch ) event.stopPropagation();});}else{e.addEventListener ( Prm.Event, event=>{let Arguments=[];if( Prm.Commands ){Arguments=TPusa.Create().Commands( Prm.Commands, e, null ).Arguments;}this.Request ({Event:event, Class:Prm.Class, Method:Prm.Method, Timeout:Prm.Timeout, Element:e, Filter:Prm.Filter, Arguments:Arguments})});}}});}break;case 'Focus':if( Prm.Target ){SetFocus ( this.SelectElements ( ASelf, Focus,{Target:Prm.Target, Filter:Prm.Filter}) );}if( ( Prm.Property || Prm.Method ) && FocusIsFull() ){var NewFocus=[];Focus.forEach ( e=>{if( Prm.Property && typeof e==='object' && e[Prm.Property]){NewFocus.push( e[Prm.Property]);}if( Prm.Method && typeof e==='object' && e[Prm.Method]){NewFocus.push( e[Prm.Method].apply( e, Prm.Arguments ));}});SetFocus( NewFocus );}break;case 'Create':if( FocusIsFull() ){var NewElements=[];Focus.forEach ( e=>{var New=document.createElement( Prm.TagName );NewElements.push( New );switch( Prm.Position ){default:case 'Last':e.append( New );break;case 'First':e.prepend( New );break;case 'Before':e.before( New );break;case 'After':e.after( New );break;}});Focus=NewElements;}break;case 'If':let Condition=null;switch( Prm.Condition ){case 'FocusIsEmpty':Condition=Focus.length==0;break;default:CommandWarning( 'Unknown condition' );break;}if( Condition===true && Prm.True ){Focus=TPusa.Create().Commands( Prm.True, ASelf, null, AEvent ).Focus;}if( Condition===false && Prm.False ){Focus=TPusa.Create().Commands( Prm.False, ASelf, Focus, AEvent ).Focus;}break;case 'Timer':if( FocusIsFull() ){Focus.forEach ( e=>{let TimerName='Timer.' + Prm.ID + '.' + Prm.Class + '.' + Prm.Method;if( e[TimerName]){clearTimeout( e[TimerName]);}if( ! Prm.Stop ){if( Prm.Timeout ){e[TimerName]=setTimeout ( ()=>{let Arguments=[];if( Prm.Commands ){Arguments=TPusa.Create() .Commands( Prm.Commands, e, null, AEvent ) .Arguments;}if( Prm.Class && Prm.Method ){this.Send ({Element:e, Class:Prm.Class, Method:Prm.Method, Events:[], Arguments:Arguments});}}, Prm.Timeout )}}});}break;case 'Replace':if( FocusIsFull()){Focus.forEach ( e=>{for( var i=0;i < e.attributes.length;i++ ){var s=e.attributes[i].value;for( var Key in Prm.Values ){var r=new RegExp( Key );s=s.replace( r, Prm.Values[Key]);}e.attributes[i].value=s;}});}break;case 'CSSAttr':clCSSRuleBySelector ( Prm.Name, ( Rule )=>{for( var Key in Prm.Values ){Rule.style[Key]=Prm.Values[Key];}});break;case 'PileFrom':if( Prm.Name ){if( Prm.Value ){this.WritePile( Prm.Name, Prm.Value, Prm.Operator );}if( Prm.Property && FocusIsFull()){Focus.forEach ( e=>{this.WritePile( Prm.Name, e[Prm.Property], Prm.Operator );});}if( Prm.Method && FocusIsFull()){Focus.forEach ( e=>{if( Prm.Method && e[Prm.Method]){this.WritePile ( Prm.Name, e[Prm.Method].apply( e, Prm.Arguments ), Prm.Operator );}});}}break;case 'PileTo':if( Prm.Name && FocusIsFull() ){Focus.forEach ( e=>{if( Prm.Property ){e[Prm.Property]=this.Pile[Prm.Name];}if( Prm.Method && e[Prm.Method]){e[Prm.Method].apply( e,[this.Pile[Prm.Name]]);}});}break;case 'PileEqual':if( FocusIsFull() ){Focus.forEach ( e=>{if( this.Pile[Prm.Name]==Prm.Value ){TPusa.Create().Commands( Prm.Equal, e, null, AEvent );}else{TPusa.Create().Commands( Prm.NotEqual, e, null, AEvent );}});}break;case 'PileReplace':break;}Index++;});this.Focus=Focus;return this;}WritePile ( AName, AValue, AOperator ){switch( AOperator ){case 'Set':this.Pile[AName]=AValue;break;case 'Add':this.Pile[AName]+=AValue;break;}return this;}SendFiles ( AElement, AIDGroup, AClass, AMethod ){let Files=[];let c=AElement.files.length;for( let i=0;i < c;i++ ){let IDFile=clGUID();let File=AElement.files[i];this.Send ({Element:File, Class:AClass, Method:AMethod, IDRequest:IDFile, Arguments:{IDGroup:AIDGroup, Count:c}});Files.push( IDFile );}return Files;}RequestNew( APrm ){var Result=null;if( this.RequestCheck( APrm.EventName )){this.RequestsClose ({EventName:APrm.EventName, Element:APrm.Element, IDGroup:APrm.IDGroup});Result=new XMLHttpRequest();Result.Params=APrm;this.Requests.push( Result );}return Result;}RequestCheck( AEventName ){var Result=true;var Now=Date.now();AEventName=AEventName ? AEventName:'any';var Timeout=this.EventTimeouts[AEventName];if( !Timeout ) Timeout=0;var LastRequest=this.LastRequests[AEventName];if( LastRequest && LastRequest + Timeout > Now ){Result=false;}else{this.LastRequests[AEventName]=Now;}return Result;}RequestsClose( APrm ){var Requests=this.RequestsFind( APrm );for( Request of Requests ) Request.abort();return true;}RequestsFind( APrm ){var Result=[];for( Request of this.Requests ){if ( ( !APrm.Element || APrm.Element && ( APrm.Element==Request.Params.Element )) && ( !APrm.EventName || APrm.EventName && ( APrm.EventName==Request.Params.EventName )) && ( !APrm.IDGroup || APrm.IDGroup && ( APrm.IDGroup==Request.Params.IDGroup )) && ( !APrm.ID || APrm.ID && ( APrm.ID==Request.Params.ID )) ){Result.push( Request );}}return Result;}RequestRemove( ARequest ){let Index=this.Requests.indexOf( ARequest );this.Requests.splice( Index, 1 );return this;}Info( AMsg ){if( this.Debug==DEBUG_ON ){console.info( AMsg );}return this;}Warning( AMsg ){if( this.Debug==DEBUG_ON ){console.warn( AMsg );}return this;}GetIndicator(){var Result=document.getElementById( 'clIndicator' );if( !Result ){Result=document.createElement( 'div' );Result.id='clIndicator';Result.className='PostIndicator';Result.style.display='none';Result.style.opacity='0';document.body.append( Result );}return Result;}JobBegin(){var Indicator=this.GetIndicator();this.CountJob++;if( this.CountJob==1 && Indicator.Timer==null ){Indicator.Timer=setTimeout ( ()=>{Indicator.style.display=null;Indicator.style.opacity='1';Indicator.Timer=null;}, 500 );}Indicator.innerHTML=this.CountJob;return this;}JobEnd(){var Indicator=this.GetIndicator();this.CountJob--;Indicator.innerHTML=this.CountJob;if( this.CountJob < 1){Indicator.style.display='none';Indicator.style.opacity='0';this.CountJob=0;if( Indicator.Timer ){clearTimeout( Indicator.Timer );Indicator.Timer=null;}}return this;}}function clGUID(){return 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace ( /[xy]/g, function( c ){var r=Math.random()*16|0, v=c=='x' ? r:(r&0x3|0x8);return v.toString( 16 );});}function GetValuesOnly ( AObject, AInclude, AExclude ){var Result={};if( !AInclude ) AInclude=[];if( !AExclude ) AExclude=[];for( var Key in AObject ){if ( Key!='webkitStorageInfo' ){try{switch( typeof( AObject[Key])){case 'boolean':case 'number':case 'string':case 'symbol':if ( ( AInclude.length==0 || AInclude.indexOf( Key ) > -1 ) && ( AExclude.length==0 || AExclude.indexOf( Key )==-1 ) ){Result[Key]=AObject[Key];}break;}}catch( e ){}}}return Result;}Element.prototype.Parent=function ( AFilter, ACallback ){var Result=null;var e=this;while( e && e.nodeType===1 && !Result ){if( MatchData( AFilter, e ) ){Result=e;if( ACallback ) ACallback( Result );}e=e.parentNode;}return Result;};Element.prototype.Parents=function ( AFilter, ACallback ){var Result=[];var e=this;while( e && e.nodeType===1 ){if( MatchData( AFilter, e ) ){Result.push( e );}e=e.parentNode;}if( ACallback ) Result.forEach( e=> ACallback( e ) );return Result;};Element.prototype.ChildRecursion=function( AParams, AMaxDepth, ADepth ){AMaxDepth=AMaxDepth ? AMaxDepth:0;ADepth=ADepth ? ADepth:0;if ( AParams.OnBefore ) AParams.OnBefore( this, AParams );if( AMaxDepth==0 || AMaxDepth > ADepth ){for (var i in this.childNodes ){var iNode=this.childNodes[i];if (iNode.nodeType==1) iNode.ChildRecursion( AParams, AMaxDepth, ADepth+1 );}}if ( AParams.OnAfter ) AParams.OnAfter( this, AParams );return this;};Element.prototype.Childs=function ( AFilter, ACallback, AMaxDepth ){var Result=[];AMaxDepth=AMaxDepth ? AMaxDepth:0;this.ChildRecursion ({OnBefore:e=>{if( MatchData( AFilter, e )){Result.push( e );}}}, AMaxDepth );if( ACallback ) Result.forEach( e=> ACallback( e ) );return Result;};Element.prototype.ReplaceEventListener=function ( AEvent, AFunction ){if( this.LastEventListener ){this.removeEventListener( AEvent, this.LastEventListener );}this.LastEventListener=AFunction;this.addEventListener( AEvent, AFunction );return this;};function clCSSRuleBySelector( ASelector, ACallback ){if( ACallback ){for( const Sheet of document.styleSheets ){for( const Rule of Sheet.rules ){if( Rule.selectorText==ASelector ){ACallback( Rule );}}}}}function MatchData ( AFilter, AData ){return Match ( AFilter, function( AArg ){let Result=AArg;if( AArg.substr( 0,1 )=='@' ){let Key=AArg.slice( 1 );Result=AData[Key];}return Result;});}function Match ( AFilter, ACallback ){let Val=function( AArg ){let Result=AArg;switch( typeof( AArg )){case 'string':Result=ACallback ? ACallback( AArg ):AArg;break;case 'object':Result=Match( AArg, ACallback );break;}return Result;};let Result=false;if( AFilter ){let Operator=AFilter[0];switch( Operator ){case '=':case '<>':case '>':case '<':case '<=':case '>=':case 'in':case '+':case '-':case '*':case '/':var a1=Val( AFilter[1]);var a2=Val( AFilter[2]);break;}switch( Operator ){case 'in':Result=a2.split( ' ' ).indexOf( a1 ) > -1;break;case '=':Result=a1==a2;break;case '!=':Result=a1!=a2;break;case '>':Result=a1 > a2;break;case '<':Result=a1 < a2;break;case '<=':Result=a1<=a2;break;case '>=':Result=a1>=a2;break;case '+':Result=a1 + a2;break;case '-':Result=a1 - a2;break;case '*':Result=a1 * a2;break;case '/':Result=a1 / a2;break;case 'or':Result=false;for( let i=1;i < AFilter.length;i++ ){Result=Result || Val( AFilter[i]);}break;case 'and':Result=true;for( let i=1;i < AFilter.length;i++ ){Result=Result && Val( AFilter[i]);}break;}}else{Result=true;}return Result;}function ReplaceInObject ( AObject, AValues ){for( var Prop in AObject ){var Value=AObject[Prop];switch( typeof Value ){case 'object':ReplaceInObject( Value, AValues );break;case 'string':if( Value.indexOf( '%' )>=0 ){let Content=AObject[Prop];for( var Key in AValues ){Content=Content.replace( '%' + Key + '%', AValues[Key]);}AObject[Prop]=Content;}break;}}}function clValuesFromObject( AObject, AConteiner, ACreate ){for (var Key in AObject){var Element=AConteiner.ChildByID( Key );if( !Element && ACreate){Element=document.createElement( 'input' );Element.type='hidden';Element.name=Key;AConteiner.append( Element );}if (Element!=null){try{var KeyValue=decodeURIComponent( AObject[Key]);}catch (ex){var KeyValue=null;}if ( KeyValue!=null && KeyValue!='null' ){switch( Element.tagName ){case 'INPUT':switch( Element.type ){case 'checkbox':Element.checked=AObject[Key]=='on' || AObject[Key]=='true' || AObject[Key]=='1';break;case 'text':Element.value=KeyValue;break;case 'hidden':Element.value=KeyValue;break;}break;case 'SELECT':Element.value=KeyValue;break;case 'TEXTAREA':Element.innerHTML=KeyValue;break;default:Element.innerHTML=KeyValue;break;}}}}}window.onload=()=> TPusa.Create().Request({Class:'Main', Method:'Init'});