The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
<style> .editing { background-color: lightyellow; border: solid 2px black; padding-right: 10px; min-width:100px; } 
    .edit_allowed { padding-right: 10px; }
</style>

<script type="text/template" class="yote_template_definition" template_name="checkbox">
    <??? function( ctx ) { 
           if( ctx.args.length > 1 ) { 
               var obj = ctx.parse( ctx.args[ 0 ] );
               ctx.set( 'object', obj );
               var fld = ctx.args[ 1 ];
               var lbl = ctx.args[ 2 ] || '';
               ctx.set( 'field', fld );
               return '<label for="<?? function(c){return c.controls.checkbox.substring(1);}??>"><$$$ checkbox <input type="checkbox" ' + ( 1*obj.get( fld ) > 0 ? ' checked ' : '' ) + '>$$$>' + lbl + '<label>';
           } else {
               console.log( "error in template 'checkbox' : not enough arguments." );
               return '';
           }
        return '';
    } ???> 
    <? function( ctx ) {
        $( ctx.controls.checkbox ).click( function() {
            ctx.vars.object.set( ctx.vars.field, $( this ).is( ':checked' ) ? 1 : 0 );
            ctx.refresh();
        } );
    } ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="CreateLogin">
   <$$$ messages <span></span> $$$><BR>
   <$$$ handle   <input placeholder="handle"   type="text"> $$$>
   <$$$ email    <input placeholder="email"    type="text"> $$$>
   <$$$ password <input placeholder="password" type="password"> $$$>
   <$$$ create   <button type="button">Create Accout</button> $$$>
   <$$$ cancel   <a href="#">[X]</a> $$$>
   <? 
     function( ctx ) {
         $( ctx.controls.cancel ).click( function() {
             ctx.scratch.create_login = false;
             ctx.refresh();
         } );
         $.yote.util.button_actions( { 
             button :  ctx.controls.create,
             texts  :  [ ctx.controls.handle, ctx.controls.email, ctx.controls.password ],
             action : function() {
                 ctx._app_.create_login( { h : $( ctx.controls.handle ).val(),
                                           e : $( ctx.controls.email ).val(),
                                           p : $( ctx.controls.password ).val() },
                                         function(msg) {
					                         ctx.scratch.create_login = false;
					                         $.yote.login( $( ctx.controls.handle ).val(),
							                               $( ctx.controls.password ).val(),
							                               function(msg) {
							                                   if( ctx.scratch.requires_admin && ! $.yote.has_root_permissions() ) {
								                                   $( ctx.controls.messages ).empty().append( "Error : root login required" );
								                                   $.yote.logout();
								   $.yote.need_reinit = true;
								                                   $.yote.reinit();
							                                   }
							                                   ctx.refresh();
							                               },
							                               function(err) {
							                                   $( ctx.controls.messages ).empty().append( err );
							                               } );
					                     },
                                         function(err) {
                                             $( ctx.controls.messages ).empty().append( err );
                                         }
                                       );
             } } );
     }
   ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="edit_hash_with_select_scalars">
    <# edit takes an object and a field to edit and builds a way to edit this #>
    <??? function( ctx ) { 
           if( ctx.args.length == 4 ) { 
               var list   = ctx.parse( ctx.args[ 0 ] );
               ctx.vars.object = ctx.parse( ctx.args[ 1 ] );
               ctx.vars.hash = ctx.args[ 2 ];
               ctx.vars.field = ctx.parse( ctx.args[ 3 ] );
               var curval = ctx.vars.object.hash_fetch( { name : ctx.vars.hash, key : ctx.vars.field } );
               // TODO - escap the value there
               return '<$$$ sel <select> $$$>' + list.map(function(it,idx) { return '<option ' + ( curval == it ? ' selected ' : '' ) + ' value="' + it + '">' + it + '</option>' } ).join('') + '</select>';
           } else {
               console.log( "error in template 'edit_select_scalars' : wrong number of arguments." );
               return '';
           }
        return '';
    } ???> 
    <? function( ctx ) {
        $( ctx.controls.sel ).change( function() { 
            ctx.vars.object.hash( { name : ctx.vars.hash, key : ctx.vars.field, value : $( ctx.controls.sel ).val() } );
            ctx.refresh();
        } );
    } ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="edit">
    <# edit takes an object and a field to edit and builds a way to edit this #>
    <??? function( ctx ) { 
           if( ctx.args.length > 1 ) { 
               ctx.vars.object = ctx.parse( ctx.args[ 0 ] );
               ctx.vars.field = ctx.args[ 1 ];
               return '<$$$ input_div <div class="input_div"> $$$><$$$ noedit_span <span class="edit_allowed"> $$$></span><$$$ edit_span <span class="edit_allowed" style="display:none">$$$><$$$ editarea <textarea>$$$></textarea><br><$$$ cancel_button <button class="cancel" type="button">cancel</button>$$$><$$$ go_button <button class="go" type="button">go</button>$$$></span></div>';
           } else {
               console.log( "error in template 'edit' : not enough arguments." );
               return '';
           }
        return '';
    } ???> 
    <? function( ctx ) {
        if( ctx.vars.object ) {
            $( ctx.controls.editarea ).text( ctx.vars.object.get( ctx.vars.field ) );
            $( ctx.controls.noedit_span ).text( ctx.vars.object.get( ctx.vars.field ) );
        }
        $( ctx.controls.input_div ).mouseleave( function() { 
            $( ctx.controls.noedit_span ).removeClass( 'editing' );
        } ).mouseenter( function() { 
            $( ctx.controls.noedit_span ).addClass( 'editing' );
        } );

        if( $( ctx.controls.noedit_span ).width() > 100 ) {
            $( ctx.controls.noedit_span ).width( 100 );
        }
        
        $( ctx.controls.noedit_span ).click( function() { 
            $( this ).hide();
            $( ctx.controls.edit_span ).show();
        } );

        $( ctx.controls.cancel_button ).click( function() {
            $( ctx.controls.edit_span ).hide();
            $( ctx.controls.noedit_span ).show();
        } );
        $( ctx.controls.go_button ).click( function() {
            ctx.vars.object.set( ctx.vars.field, $( ctx.controls.editarea ).val() );
            ctx.refresh();
        } );
    } ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="show_or_edit_old">
    <# edit takes an object and a field to edit and builds a way to edit this #>
    <??? function( ctx ) { 
           if( ctx.args.length > 1 ) { 
               ctx.vars.object = ctx.parse( ctx.args[ 0 ] );
               ctx.vars.field = ctx.args[ 1 ];
               return $.yote.has_root_permissions() ?  '<$$$ input_div <div class="input_div"> $$$><$$$ noedit_span <span class="edit_allowed"> $$$></span><$$$ edit_span <span class="edit_allowed" style="display:none">$$$><$$$ editarea <textarea>$$$></textarea><br><$$$ cancel_button <button class="cancel" type="button">cancel</button>$$$><$$$ go_button <button class="go" type="button">go</button>$$$></span></div>' : '<$ ' + ctx.args[ 0 ] + '.' + ctx.args[ 1 ] + ' $>';
           } else {
               console.log( "error in template 'edit' : not enough arguments." );
               return '';
           }
        return '';
    } ???> 
    <? function( ctx ) {
        if( ctx.vars.object ) {
            $( ctx.controls.editarea ).text( ctx.vars.object.get( ctx.vars.field ) );
            $( ctx.controls.noedit_span ).text( ctx.vars.object.get( ctx.vars.field ) );
        }
        $( ctx.controls.input_div ).mouseleave( function() { 
            $( ctx.controls.noedit_span ).removeClass( 'editing' );
        } ).mouseenter( function() { 
            $( ctx.controls.noedit_span ).addClass( 'editing' );
        } );

        if( $( ctx.controls.noedit_span ).width() > 100 ) {
            $( ctx.controls.noedit_span ).width( 100 );
        }
        
        $( ctx.controls.noedit_span ).click( function() { 
            $( this ).hide();
            $( ctx.controls.edit_span ).show();
        } );

        $( ctx.controls.cancel_button ).click( function() {
            $( ctx.controls.edit_span ).hide();
            $( ctx.controls.noedit_span ).show();
        } );
        $( ctx.controls.go_button ).click( function() {
            ctx.vars.object.set( ctx.vars.field, $( ctx.controls.editarea ).val() );
            ctx.refresh();
        } );
    } ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="show_or_edit_html">
  <??? function( ctx ) { 
       return $.yote.has_root_permissions() ?
	  '<$$ edit_html ' + ctx.args.join( ' ' ) + ' $$>' : '<$ ' + ctx.args.join('.') + '$>'; 
  } ???>
</script>

<script type="text/template" class="yote_template_definition" template_name="show_or_edit">
  <??? function( ctx ) { return $.yote.has_root_permissions() ? '<$$ edit ' + ctx.args.join( ' ' ) + ' $$>' : '<$ ' + ctx.args.join('.') + '$>'; } ???>
</script>

<script type="text/template" class="yote_template_definition" template_name="escape_html">
  <??? function( ctx ) {
          if( ctx.args.length*1 == 1 ) {
	      var val = ctx.parse( ctx.args[ 0 ] );
	      console.log( val );
	      return val;
	  }
          return 'xxxx';
       } ???>
</script>

<script type="text/template" class="yote_template_definition" template_name="edit_html">
    <# edit takes an object and a field to edit and builds a way to edit this #>
    <??? function( ctx ) { 
           if( ctx.args.length > 1 ) { 
               var fld = ctx.args[ 1 ];
	       var obj =  ctx.parse( ctx.args[ 0 ] );
               ctx.set( 'object', obj );
               var fld = ctx.args[ 1 ];
	       ctx.set( 'escaped', obj.get( fld ) );
               ctx.set( 'field', fld );
               return '<$$$ input_div <div class="input_div"> $$$><$$$ noedit_span <span class="edit_allowed"> $$$><$ object.' + fld + ' $></span><$$$ edit_span <span class="edit_allowed" style="display:none">$$$><$$$ editarea <textarea>$$$></textarea><br><$$$ cancel_button <button class="cancel" type="button">cancel</button>$$$><$$$ go_button <button class="go" type="button">go</button>$$$></span></div>';
           } else {
               console.log( "error in template 'edit' : not enough arguments." );
               return '';
           }
        return '';
    } ???> 
    <? function( ctx ) {

	$( ctx.controls.editarea ).text( ctx.vars.escaped );

        $( ctx.controls.input_div ).mouseleave( function() { 
            $( ctx.controls.noedit_span ).removeClass( 'editing' );
        } ).mouseenter( function() { 
            $( ctx.controls.noedit_span ).addClass( 'editing' );
        } );

        if( $( ctx.controls.noedit_span ).width() > 100 ) {
            $( ctx.controls.noedit_span ).width( 100 );
        }
        
        $( ctx.controls.noedit_span ).click( function() { 
            $( this ).hide();
            $( ctx.controls.edit_span ).show();
        } );

        $( ctx.controls.cancel_button ).click( function() {
            $( ctx.controls.edit_span ).hide();
            $( ctx.controls.noedit_span ).show();
        } );
        $( ctx.controls.go_button ).click( function() {
            ctx.vars.object.set( ctx.vars.field, $( ctx.controls.editarea ).val() );
            ctx.refresh();
        } );
    } ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="list_remove_button">
    <??? function( ctx ) { 
        var collection_to_remove_from = ctx.args[ 0 ] || ctx.vars.__;
        ctx.set( 'collection_to_remove_from', collection_to_remove_from );
        
        var key_to_remove = ctx.args[ 1 ] || ctx.hashkey_or_index;
        ctx.set( 'remove_key', key_to_remove );
        
        var lbl = ctx.args[ 2 ] || 'Remove';
        return '<$$$ remove_button <button type="button">$$$>' + lbl + '</button>';
    } ???> 
    <? function( ctx ) {
        $( ctx.controls.remove_button ).click( function() {
            ctx.vars.collection_to_remove_from.remove( ctx.vars.remove_key );
            ctx.refresh();
        } );
     } ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="list_remove_ask">
    <??? function( ctx ) { 
        var collection_to_remove_from = ctx.args[ 0 ] || ctx.vars.__;
        ctx.set( 'collection_to_remove_from', collection_to_remove_from );
        var key_to_remove = ctx.args[ 1 ] || ctx.hashkey_or_index;
        ctx.set( 'remove_key', key_to_remove );
        
        var lbl = ctx.args[ 2 ] || 'Remove';
        return '<$$$ remove_button <button type="button">$$$>' + lbl + '</button>';
    } ???> 
    <? function( ctx ) {
        $( ctx.controls.remove_button ).click( function() {
            if( confirm( "Are you sure you want to delete this?" ) ) {
                ctx.vars.collection_to_remove_from.remove( ctx.vars.remove_key );
                ctx.refresh();
            }
        } );
     } ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="Logged_in">
   Logged in as <$ _acct_.handle $><BR>
   <$$$ logout <a href="#">Log Out</a> $$$>
   <? function( ctx ) {
       $( ctx.controls.logout ).click( function() {
           $.yote.logout();
           $.yote.reinit();
           ctx.refresh();
       } );
      } ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="Login">
   <$$$ messages <span><$ _app_.login_message "Please Log In" $></span> $$$><BR>
   <$$$ handle <input placeholder="handle" type="text"> $$$>
   <$$$ password <input placeholder="password" type="password"> $$$>
   <$$$ login <button type="BUTTON">Log In</button> $$$>
     <BR>
   <$$$ forgot <a href="#">Forgot Account</a> $$$>
   <$$$ create <a href="#">Create Account</a> $$$>
   <? function(ctx) {
       $.yote.util.button_actions({
           button :  ctx.controls.login,
           texts  :  [ ctx.controls.handle, ctx.controls.password ],
           action : function() {
               $.yote.login( $( ctx.controls.handle ).val(),
                             $( ctx.controls.password ).val(),
                             function(msg) {
                                 if( ctx.scratch.requires_admin && ! $.yote.has_root_permissions() ) {
                                     $( ctx.controls.messages ).empty().append( "Error : root login required" );
                                     $.yote.logout();
                                     $.yote.need_reinit = true;
                                 }
                                 $.yote.reinit();
                                 ctx.refresh();
                             },
                             function(err) {
                                 $( ctx.controls.messages ).empty().append( err );
                             } );
           }
           } );
         $( ctx.controls.forgot ).click( function() {
             ctx.scratch.forgot_login = true;
             ctx.refresh();
         } );
         $( ctx.controls.create ).click( function() {
             ctx.scratch.create_login = true;
             ctx.refresh();
         } );
      } ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="Logged_out">
    <??? function( ctx ) { return '<$$' + ( ctx.scratch.forgot_login ? 'RecoverPassword' : ctx.scratch.create_login ? 'CreateLogin' : 'Login' ) + '$$>'; } ???>
</script>


<script type="text/template" class="yote_template_definition" template_name="Paginator">
 <??? function( ctx ) { 
     var collection = ctx.parent.parse( ctx.args[ 0 ] );
     if( collection.can_rewind() || collection.can_fast_forward() ) {
         return '<$$$ paginate_to_beginning_button <button type="BUTTON">&laquo;</button> $$$>' + 
      '<$$$ paginate_back_button <button type="BUTTON">&lsaquo;</button> $$$>' + 
      '<$$$ paginate_forward_button <button type="BUTTON">&rsaquo;</button> $$$>' +
      '<$$$ paginate_to_end_button <button type="BUTTON">&raquo;</button> $$$>';
     }
      return '';
      } ???>
 <? function( ctx ) {
        if( ctx.args.length < 1 ) return;

        var collection = ctx.parent.parse( ctx.args[ 0 ] );

        if( ! collection || ! collection.can_rewind ) { //test if it has that function
            console.log( 'warning : init_paginator called for something not a list or hash' );
            return;
        }
        var pag_begin_button_id    = ctx.controls.paginate_to_beginning_button,
             pag_back_button_id    =  ctx.controls.paginate_back_button,
             pag_forward_button_id =  ctx.controls.paginate_forward_button,
             pag_end_button_id     =  ctx.controls.paginate_to_end_button;

        if( collection.can_rewind() ) {
            $( pag_begin_button_id ).attr( 'disabled', false );
            $(  pag_back_button_id ).attr( 'disabled', false );
            $(  pag_begin_button_id ).click( function() { collection.first();   
                                                          $.yote.reinit();
                                                          ctx.refresh(); } );
            $(  pag_back_button_id ).click( function() { collection.back(); 
                                                         $.yote.reinit();
                                                         ctx.refresh(); } );
        } else {
            $(  pag_begin_button_id ).attr( 'disabled', true );
            $(  pag_back_button_id ).attr( 'disabled', true );
        }
        if( collection.can_fast_forward() ) {
            $(  pag_forward_button_id ).attr( 'disabled', false );
            $(  pag_end_button_id ).attr( 'disabled', false );
            $(  pag_forward_button_id ).click( function() {
                collection.forwards();
                $.yote.reinit();
                ctx.refresh();
            } );
            $(  pag_end_button_id ).click( function() { collection.last(); 
                                                        $.yote.reinit();
                                                        ctx.refresh(); } );
        } else {
            $(  pag_forward_button_id ).attr( 'disabled', true );
            $(  pag_end_button_id ).attr( 'disabled', true );
        }
   } ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="RecoverPassword">
   <$$$ messages <span></span> $$$><BR>
   <$$$ email <input placeholder="email" type="text"> $$$>
   <$$$ recover <button type="button">Recover Password</button> $$$>
   <$$$ cancel <a href="#">[X]</a> $$$>
   <? 
     function( ctx ) {
         $( ctx.controls.cancel ).click( function() {
             ctx.scratch.forgot_login = false;
             ctx.refresh();
         } );
         $.yote.util.button_actions( { 
             button :  ctx.controls.recover,
             texts  :  [ ctx.controls.email ],
             action : function() {
                 var app = $.yote.fetch_default_app();
                 app.recover_password( $( ctx.controls.email ).val(),
                                       function(msg) {
                                           ctx.scratch.forgot_login = false;
                                           $.yote.reinit();
                                           ctx.refresh();
                                       },
                                       function(err) {
                                           $( ctx.controls.messages ).empty().append( err );
                                       }
                                     );
             } } );
     }
    ?>
</script>


<script type="text/template" class="yote_template_definition" template_name="SearchList">
 <$$$ search_val <input type="TEXT" placeholder="Search"> $$$>
 <$$$ search_btn <button type="BUTTON">Search</button> $$$>
 <#? init_search_list ?#>
</script>


<script type="text/template" class="yote_template_definition" template_name="YoteHeader">
  <DIV class="header" id="header_div">
    <A href="/index.html" style="display:block">
      <img height="70px" width="151px" src="<$ _app_.logo /yotelogo.png $>">
    </A>
    <UL id="top_nav" class="nav"></UL>
    <div id="login_div" class="login">
      <?? function( ctx ) { return $.yote.is_logged_in() ? '<$$ Logged_in $$>' :' <$$ Logged_out $$>'; } ??>
    </div>
  </DIV>
</script>

<script type="text/template" class="yote_template_definition" template_name="YoteHeaderAdmin">
    <??? function( ctx ) { ctx.scratch.requires_admin = true; return '';} ???>
    <div class="header" id="header_div">
     <a href="/index.html" style="display:block">
      <img height="70px" width="151px" src="<$ _app_.logo /yotelogo.png $>">
     </a>
     <ul id="top_nav" class="nav"></ul>
     <div id="login_div" class="login">
       <?? function( ctx ) { return $.yote.has_root_permissions() ? '<$$ Logged_in $$>' :' <$$ Logged_out $$>'; } ??>
     </div>
  </div>
</script>