Create attractive VASL scenarios, with loads of useful information embedded to assist with game play. https://vasl-templates.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
vasl-templates/vasl_templates/webapp/static/turn_track.js

309 lines
13 KiB

DEFAULT_TURN_TRACK_TURNS_MIN = 6 ;
DEFAULT_TURN_TRACK_TURNS_MAX = 10 ;
// NOTE: Reinforcement flags get clipped on turn 100, but this is unlikely to be an issue :-/
_MAX_TURN_TRACK_TURNS = 100 ;
gTurnTrackReinforcements = null ;
// --------------------------------------------------------------------
function editTurnTrackSettings()
{
// initialize
var $dlg, $iframe, iframeSeqNo=0 ;
// FUDGE! This should work as a local variable, but causes a weird problem where it doesn't get reset properly :-/
gTurnTrackReinforcements = null ;
function loadControls() {
// load the dialog controls
$dlg.find( "select[name='nturns']" ).val(
$panel.find( "select[name='TURN_TRACK_NTURNS'].param" ).val()
).trigger("change" ) ;
var width = $panel.find( "input[name='TURN_TRACK_WIDTH']" ).val() ;
$dlg.find( "select[name='width']" ).val(
isNaN( parseInt( width ) ) ? "" : width
).trigger( "change" ) ;
$dlg.find( "input[name='vertical']" ).prop( "checked",
$panel.find( "input[name='TURN_TRACK_VERTICAL']" ).prop( "checked" )
) ;
$dlg.find( "input[name='swap-players']" ).prop( "checked",
$panel.find( "input[name='TURN_TRACK_SWAP_PLAYERS']" ).prop( "checked" )
) ;
// load the reinforcements
var params = updatePreview( false ) ;
var args = parseTurnTrackParams( params ) ;
gTurnTrackReinforcements = { 1: args.reinforce1, 2: args.reinforce2 } ;
// update the UI
updateUI() ;
}
function onResetControls() {
// reset all the controls
ask( "Reset turn track", "Do you want to reset the turn track?", {
ok: function() {
setTurnTrackNTurns( DEFAULT_TURN_TRACK_TURNS_MIN ) ;
$panel.find( "input[name='TURN_TRACK_WIDTH']" ).val( "" ) ;
$panel.find( "input[name='TURN_TRACK_VERTICAL']" ).prop( "checked", false ) ;
$panel.find( "input[name='TURN_TRACK_SWAP_PLAYERS']" ).prop( "checked", false ) ;
$panel.find( "input[name='TURN_TRACK_REINFORCEMENTS_1']" ).val( "" ) ;
$panel.find( "input[name='TURN_TRACK_REINFORCEMENTS_2']" ).val( "" ) ;
gTurnTrackReinforcements = null ;
loadControls() ;
}
} ) ;
}
function initTurnCountSelect2( $sel ) {
// initialize the TURN COUNT droplist
init_select2(
$sel, "4em", false, formatTurnTrackOption
).on( "select2:open", function() {
restrict_droplist_height( $(this) ) ;
} ).on( "change", function() {
setTurnTrackNTurns( $(this).val() ) ;
if ( $dlg )
updateUI() ;
} ) ;
for ( var nTurns=1 ; nTurns <= _MAX_TURN_TRACK_TURNS ; nTurns += 0.5 )
$sel.append( $( "<option value='" + nTurns + "'>" + nTurns + "</option>" ) ) ;
}
function initWidthSelect2( $sel ) {
// initialize the WIDTH droplist
init_select2(
$sel, "3.5em", false, null
).on( "select2:open", function() {
restrict_droplist_height( $(this) ) ;
} ).on( "change", function() {
$panel.find( "input[name='TURN_TRACK_WIDTH']" ).val( $(this).val() ) ;
if ( $dlg )
updateUI() ;
} ) ;
$sel.append( $( "<option value=''>-</option>" ) ) ;
for ( var i=1 ; i <= 30 ; ++i )
$sel.append( $( "<option value='" + i + "'>" + i + "</option>" ) ) ;
}
function syncCheckbox( $elem, $target ) {
// sync the target checkbox in the SCENARIO panel with the one in this dialog
$target.prop( "checked", $elem.prop("checked") ) ;
updateUI() ;
}
function updatePreview( showAllFlags ) {
// generate the turn track snippet
var params = unload_snippet_params( true, "turn_track" ) ;
if ( showAllFlags )
params.TURN_TRACK.REINFORCEMENTS_1 = params.TURN_TRACK.REINFORCEMENTS_2 = makeCommaList( _MAX_TURN_TRACK_TURNS ) ;
params.TURN_TRACK_PREVIEW_MODE = true ;
var $btn = $( "button.generate[data-id='turn_track']" ) ;
var snippet = make_snippet( $btn, params, {}, false ).content ;
// update the preview
// NOTE: To minimize flickering, we load the snippet into a hidden <iframe>,
// then replace the preview <iframe> with it.
// FUDGE! We should be able to wait until the new iframe has finished loading before removing the old one,
// but for some inexplicable reason, the remove doesn't work on Windows, and the iframe's just build up :-/
// Instead, we remove the old iframe here, but by fiddling with opacity, we can avoid flicker. Sigh...
var style = $iframe.attr( "style" ) ;
style.opacity = 0 ;
var $newFrame = $( "<iframe></iframe>", { style: style, "data-seqno": ++iframeSeqNo } ) ;
$iframe.after( $newFrame ) ;
$iframe.remove() ;
$iframe = $newFrame ;
$newFrame.attr( "srcdoc", snippet ).on( "load", function() {
// update the state of each reinforcement flag
for ( var turnNo=1 ; turnNo <= _MAX_TURN_TRACK_TURNS ; ++turnNo ) {
for ( var playerNo=1 ; playerNo <= 2 ; ++playerNo )
updateFlag( turnNo, playerNo ) ;
}
// install the new <iframe>
$newFrame.attr( "id", "turn-track-preview" ).css( "opacity", 1 ) ;
// FUDGE! This works around a weird problem when we load a scenario with a vertical turn track
// and show it in a turn track dialog that was previously showing a horizontal turn track :-/
updateLayout() ;
} ) ;
return params ;
}
function onFlagClick( turnNo, playerNo ) {
// NOTE: This method gets called by a click handler in the snippet HTML.
// toggle the player turn reinforcements
if ( gTurnTrackReinforcements[playerNo][turnNo] )
delete gTurnTrackReinforcements[playerNo][turnNo] ;
else
gTurnTrackReinforcements[playerNo][turnNo] = true ;
$panel.find( "input[name='TURN_TRACK_REINFORCEMENTS_" + playerNo + "']" ).val(
Object.keys( gTurnTrackReinforcements[playerNo] ).join( "," )
) ;
updateFlag( turnNo, playerNo ) ;
}
function updateFlag( turnNo, playerNo ) {
// update the specified reinforcement flag
$iframe.contents().find( "#flag-" + turnNo + "_" + flipPlayerNo2(playerNo) ).css( {
opacity: gTurnTrackReinforcements && gTurnTrackReinforcements[playerNo][turnNo] ? 1 : 0.4,
} ) ;
}
function updateUI() {
// update the UI
updateLayout() ;
updatePreview( true ) ;
}
function updateLayout() {
// update the layout based on the direction of the turn track
if ( $dlg.find( "input[name='vertical']" ).prop( "checked" ) ) {
// vertical layout
$iframe.css( { position: "absolute",
top: "10px", height: "calc(100% - 20px)", left: "150px", width: "calc(100% - 160px)"
} ) ;
$dlg.addClass( "vert" ).removeClass( "horz" ) ;
$dlg.find( ".controls" ).addClass( "vert" ).removeClass( "horz" ) ;
$dlg.find( ".reset1" ).hide() ;
$dlg.find( ".reset2" ).show() ;
} else {
// horizontal layout
$iframe.css( { position: "absolute",
top: "95px", height: "calc(100% - 105px)", left: "10px", width: "calc(100% - 20px)"
} ) ;
$dlg.addClass( "horz" ).removeClass( "vert" ) ;
$dlg.find( ".controls" ).addClass( "horz" ).removeClass( "vert" ) ;
$dlg.find( ".reset1" ).show() ;
$dlg.find( ".reset2" ).hide() ;
}
}
// NOTE: Since Player 1 in the UI is Player 2 in the Turn Track template (by default),
// and vice versa, we often need to flip the player numbers.
function flipPlayerNo( playerNo ) { return parseInt(playerNo) === 1 ? 2 : 1 ; }
function flipPlayerNo2( playerNo ) {
if ( ! $panel.find("input[name='TURN_TRACK_SWAP_PLAYERS']").prop( "checked" ) )
playerNo = flipPlayerNo( playerNo ) ;
return playerNo ;
}
function makeCommaList( nVals ) {
// generate a comma-separated list of values
var vals = [] ;
for ( var i=1 ; i <= nVals ; ++i )
vals.push( i ) ;
return vals.join( "," ) ;
}
// show the TURN TRACK dialog
var $panel = $( "#panel-scenario" ) ;
$( "#turn-track" ).dialog( {
"title": "Turn track",
dialogClass: "turn-track",
modal: true,
minWidth: 500, minHeight: 250,
resizable: true,
create: function() {
// initialize the dialog
init_dialog( $(this), "OK", true ) ;
initTurnCountSelect2( $(this).find( "select[name='nturns']" ) ) ;
initWidthSelect2( $(this).find( "select[name='width']" ) ) ;
$(this).find( "button.reset" ).button().on(
"click", onResetControls
) ;
// keep the settings in the SCENARIO panel in sync with the dialog
$(this).find( "input[name='vertical']" ).on( "change", function() {
syncCheckbox( $(this), $panel.find("input[name='TURN_TRACK_VERTICAL']") ) ;
} ) ;
$(this).find( "input[name='swap-players']" ).on( "change", function() {
syncCheckbox( $(this), $panel.find("input[name='TURN_TRACK_SWAP_PLAYERS']") ) ;
} ) ;
// update the UI when the direction of the turn track is changed
$(this).find( "input[name='vertical']" ).on( "change", function() {
updateUI() ;
} ) ;
// handle clicks on reinforcement flags in the turn track preview
window.addEventListener( "message", function( evt ) {
if ( evt.data.type === "FlagClick" )
onFlagClick( evt.data.turnNo, flipPlayerNo2(evt.data.uiPlayerNo) ) ;
} ) ;
},
open: function() {
// initialize the dialog
var $btnPane = $( ".ui-dialog.turn-track .ui-dialog-buttonpane" ) ;
var $btn = $btnPane.find( "button.snippet" ) ;
$btn.prepend(
$( "<img src='" + gImagesBaseUrl+"/snippet.png" + "' style='height:0.9em;margin:0 0.35em -1px 0;'>" )
) ;
$btn.css( { position: "absolute", left: 5 } ) ;
// load the dialog
$dlg = $(this) ;
$iframe = $dlg.find( "iframe#turn-track-preview" ) ;
loadControls() ;
},
buttons: {
Snippet: { text:" Snippet", class: "snippet", click: function( evt ) {
var $btn = $( "button.generate[data-id='turn_track']" ) ;
generate_snippet( $btn, evt.shiftKey, null ) ;
} },
Close: function() { $(this).dialog( "close" ) ; },
},
} ) ;
}
// --------------------------------------------------------------------
function setTurnTrackNTurns( nTurns )
{
// select the specified number of turns
updateTurnTrackNTurns( nTurns ) ;
$( "select[name='TURN_TRACK_NTURNS']" ).val(
nTurns
).trigger( "change" ) ;
}
function updateTurnTrackNTurns( nTurns )
{
function makeExtraOption( val, caption ) {
return $( "<option class='extra' value='" + val + "'>" + caption + "</option>" ) ;
}
// initialize
var $sel = $( "select[name='TURN_TRACK_NTURNS']" ) ;
var $extra = $sel.find( "option.extra" ) ;
// check if the specified number of turns is already in the droplist
var $opt = $sel.find( "option[value='" + nTurns + "']" ) ;
if ( $opt.length > 0 ) {
// yup - check if it's the special extra entry
if ( ! $opt.hasClass( "extra" ) ) {
// nope - we don't need it any more
$extra.remove() ;
}
// check if the turn track has been disabled
if ( nTurns === "" ) {
// yup - add a special extra entry to open the turn track dialog
$sel.append( makeExtraOption( "(show-dialog)", "(more)" ) ) ;
}
} else {
// nope - add it as a special extra entry
if ( $extra.length > 0 ) {
// FUDGE! If the special entry is already there, we delete and re-create it to get the select2 to work :-/
$extra.remove() ;
}
var $opt2 = makeExtraOption( nTurns, nTurns ) ;
if ( nTurns < DEFAULT_TURN_TRACK_TURNS_MIN )
$sel.find( "option[value='']" ).after( $opt2 ) ;
else
$sel.append( $opt2 ) ;
}
}
function formatTurnTrackOption( opt ) {
// format the turn track <option> element
if ( opt.id === "(show-dialog)" )
return $( "<span style='font-size:80%;font-style:italic;color:#666;'>" + opt.text + "</span>" ) ;
if ( opt.text.substr( opt.text.length-2 ) === ".5" )
return $( "<span>" + opt.text.substr( 0, opt.text.length-2 ) + "&half;" + "</span>" ) ;
return opt.text ;
}