// -------------------------------------------------------------------- function init_extras() { // initialize the layout Split( [ "#tabs-extras .left-panel", "#tabs-extras .right-panel" ], { direction: "horizontal", sizes: [ 1, 99 ], gutterSize: 8, } ) ; addSplitterGripper( $( "#tabs-extras .left-panel + .gutter" ), true, 8, { margin: "5px 2px", "background-color": "inherit" } ) ; // identify the extras templates var extra_templates = [] ; for ( var template_id in gTemplatePack.templates ) { if ( template_id.substr( 0, 7 ) === "extras/" ) { extra_templates.push( _parse_extra_template( template_id, gTemplatePack.templates[template_id] ) ) ; } } // sort the extras templates by name extra_templates.sort( function( lhs, rhs ) { return lhs.name.localeCompare( rhs.name, "en", { sensitivity: "base" } ) ; } ) ; // build the side-panel showing the available templates var $index = $( "" ) ; for ( var i=0 ; i < extra_templates.length ; ++i ) { var buf = [] ; buf.push( "
  • ", "
    ", extra_templates[i].name, "
    " ) ; if ( extra_templates[i].caption ) buf.push( "
    ", extra_templates[i].caption, "
    " ) ; buf.push( "", "
  • " ) ; var $entry = $( buf.join("") ) ; if ( i === 0 ) $entry.addClass( "ui-selecting" ) ; $entry.data( "template_id", extra_templates[i].template_id ) ; $index.append( $entry ) ; } $index.selectable( { selected: function( evt, ui ) { _show_extra_template( $(ui.selected).data( "template_id" ) ) ; }, selecting: function( evt, ui ) { // nb: prevent multiple selections if ( $index.find( ".ui-selected, .ui-selecting" ).length > 1 ) $(ui.selecting).removeClass( "ui-selecting" ) ; }, } ) ; $index.data( "ui-selectable" )._mouseStop( null ) ; // nb: trigger the selection $( "#tabs-extras .left-panel .content" ).empty().append( $index ) ; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function _show_extra_template( template_id ) { // parse the template (nb: we do this every time since the user may have changed it in the UI) var template_info = _parse_extra_template( template_id, gTemplatePack.templates[template_id] ) ; function add_player_nats( buf ) { var nats = get_sorted_nats() ; for ( var i=0 ; i < nats.length ; ++i ) { var nat_info = gTemplatePack.nationalities[ nats[i] ] ; buf.push( "" ) ; } } // generate the form for entering the template parameters var buf = [ "
    " ] ; buf.push( "
    ", template_info.name, "
    " ) ; if ( template_info.caption ) buf.push( "
    ", template_info.caption, "
    " ) ; if ( template_info.description ) buf.push( "
    ", template_info.description, "
    " ) ; if ( template_info.params.length > 0 ) { buf.push( "" ) ; for ( var i=0 ; i < template_info.params.length ; ++i ) { buf.push( "" ) ; var display_name = template_info.params[i].caption || template_info.params[i].name ; buf.push( "
    ", escapeHTML(display_name)+":" ) ; buf.push( "" ) ; if ( template_info.params[i].type === "input" ) { buf.push( "" ) ; } else if ( template_info.params[i].type == "html_textbox" ) { buf.push( "
    " ) ; if ( template_info.params[i].default ) buf.push( sanitizeHTML( template_info.params[i].default ) ) ; buf.push( "
    " ) ; } else if ( template_info.params[i].type === "select" ) { buf.push( "" ) ; } else if ( template_info.params[i].type === "player-droplist" ) { buf.push( "" ) ; } else if ( template_info.params[i].type === "player-color-droplist" ) { buf.push( "" ) ; // FUDGE! We create some hidden textboxes that contain the actual player colors (these will be updated // as the user changes the selected player). for ( var j=0 ; j <= 2 ; ++j ) buf.push( "" ) ; } } buf.push( "
    " ) ; } buf.push( "" ) ; if ( template_info.footer ) { buf.push( "" ) ; } buf.push( "
    " ) ; buf = buf.join( "" ) ; // pass some basic parameters through to the form // NOTE: We should really re-generate the form every time it gets focus (since the scenario parameters // might have changed) but this would be horribly expensive (not to mention mostly un-necessary). // The user can always click on the navbar to re-generate it. try { func = jinja.compile( buf ).render ; } catch( ex ) { showErrorMsg( "Can't compile template:
    " + escapeHTML(ex) + "
    " ) ; return ; } var params = unload_snippet_params( true, null ) ; try { buf = func( params, { autoEscape: false } ) ; } catch( ex ) { showErrorMsg( "Can't process template: " + template_id + "
    " + escapeHTML(ex) + "
    " ) ; return ; } function on_player_droplist_change( $sel ) { // update the hidden player colors var nat = $sel.val() ; var colors ; if ( nat === ":black:" ) colors = [ "#f0f0f0", "black", "black" ] ; else if ( nat === ":gray:" ) colors = [ "#f0f0f0", "#c0c0c0", "#c0c0c0" ] ; else colors = gTemplatePack.nationalities[ nat ].ob_colors ; for ( var i=0 ; i <= 2 ; ++i ) $form.find( "input[name='PLAYER_COLOR" + i + "']" ).val( colors[i] ) ; } // generate the form var $form = $( buf ) ; $form.find( "select" ).select2( { minimumResultsForSearch: -1 } ).on( "select2:open", function() { restrict_droplist_height( $(this) ) ; } ) ; $form.find( "div.html-textbox" ).each( function() { var title = $(this).attr( "title" ) ; if ( title ) title = title[0].toLowerCase() + title.substring(1) ; initHtmlTextbox( $(this), title, false ) ; } ) ; fixup_external_links( $form ) ; var $sel = $form.find( "select[name='_PLAYER_DROPLIST_']" ) ; if ( $sel.length > 0 ) { $sel.on( "change", function() { on_player_droplist_change( $(this) ) ; } ) ; on_player_droplist_change( $sel ) ; } // initialize the "generate" button init_snippet_button( $form.find( "button.generate" ) ) ; // install the form $( "#tabs-extras .right-panel" ).empty().append( $form ) ; } // -------------------------------------------------------------------- function _parse_extra_template( template_id, template ) { // extract the main details var result = { template_id: template_id, name: template_id } ; function extract_val( key ) { var ch = (key === "footer") ? "[^]" : "." ; // FUDGE! Allow multi-line values for "footer" :-/ var match = template.match( new RegExp( "" ) ) ; if ( match ) result[key] = match[1].trim() ; } extract_val( "name" ) ; extract_val( "caption" ) ; extract_val( "description" ) ; extract_val( "footer" ) ; // extract the template parameters result.params = [] ; var params_regex = new RegExp( /\{\{(.*?)\}\}/g ) ; while( (match = params_regex.exec( template )) !== null ) { // extract the parameter name and default value var words = match[1].split( "|" ) ; var param = { name: words[0] } ; var pos = param.name.indexOf( ":" ) ; if ( pos === -1 ) continue ; var val = param.name.substr( pos+1 ) ; param.name = param.name.substr( 0, pos ) ; if ( param.name === "CSS" ) continue ; // figure out what type of parameter we have if ( val.indexOf( "::" ) !== -1 ) { // we have a or HTML textbox if ( param.name.substring( param.name.length-1 ) === "*" ) { param.type = "html_textbox" ; param.name = param.name.substring( 0, param.name.length-1 ) ; } else param.type = "input" ; // extract the default value and field width pos = val.indexOf( "/" ) ; if ( pos === -1 ) param.default = val ; else { param.default = val.substr( 0, pos ) ; param.width = val.substr( pos+1 ) ; } } // extract the caption and description if ( words.length >= 2 ) param.caption = words[1] ; if ( words.length >= 3 ) param.description = words[2] ; result.params.push( param ) ; } return result ; } // -------------------------------------------------------------------- function fixup_template_parameters( template ) { // identify any non-standard template parameters var regex = /\{\{([A-Z0-9_]+?)\*?:.*?\}\}/g ; var matches = [] ; var match ; while( (match = regex.exec( template )) !== null ) matches.push( [ regex.lastIndex-match[0].length, match[0].length, match[1] ] ) ; // fix them up var i ; if ( matches.length > 0 ) { for ( i=matches.length-1 ; i >= 0 ; --i ) template = template.substr(0,matches[i][0]) + "{{"+matches[i][2]+"}}" + template.substr(matches[i][0]+matches[i][1]) ; } // remove all our special comments, except for the snippet ID regex = /\n*/g ; // nb: we use "[^]" to match newline as well matches = [] ; while( (match = regex.exec( template )) !== null ) { if ( match[1] !== "id" ) matches.push( [ regex.lastIndex-match[0].length, match[0].length ] ) ; } if ( matches.length > 0 ) { for ( i=matches.length-1 ; i >= 0 ; --i ) template = template.substr(0,matches[i][0]) + template.substr(matches[i][0]+matches[i][1]) ; } return template ; }