Tightened up how we detect if HTML content has been changed.

master
Pacman Ghost 2 years ago
parent e7888e88e0
commit 4ae19ca212
  1. 51
      vasl_templates/webapp/static/html-editor.js
  2. 2
      vasl_templates/webapp/static/snippets.js
  3. 36
      vasl_templates/webapp/static/vo2.js
  4. 13
      vasl_templates/webapp/tests/test_ob.py

@ -170,12 +170,7 @@ function unloadTrumbowyg( $ctrl, removeFirstPara )
} }
} }
// remove superfluous <br> tags return _tidyHTML( val ) ;
val = strReplaceAll( val, "<br></p>", "</p>" ) ;
while ( val.substring( val.length-4 ) === "<br>" )
val = val.substring( 0, val.length-4 ).trim() ;
return val ;
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@ -355,6 +350,12 @@ function onEditHtmlTextbox( $ctrl, objName ) {
} ) ; } ) ;
} }
function unloadHtmlTextbox( $ctrl )
{
// unload the HTML textbox
return _tidyHTML( $ctrl.html() ) ;
}
// -------------------------------------------------------------------- // --------------------------------------------------------------------
function sanitizeParams( params ) function sanitizeParams( params )
@ -379,3 +380,41 @@ function sanitizeHTML( val )
{ USE_PROFILES: { html: true } } { USE_PROFILES: { html: true } }
) ; ) ;
} }
// --------------------------------------------------------------------
var $gTranslateHtmlDiv = null ;
function translateHTML( val )
{
// FUDGE! Allowing users to edit content in an HTML textbox introduced a problem when checking
// if they had made any changes. We have a lot of HTML content in data files (e.g. vehicle/ordnance
// capabilities and comments), and when we load them into an HTML textbox, we don't always get
// exactly the same thing back e.g. "&times;2" comes back as "\xd72" :-/
// Fixing up this kind of thing in the data files would be a big job, and wouldn't even be guaranteed
// to work, since what happens is surely browser-dependent, and so the only way to detect if this
// is happening is to load the content into a contenteditable and see what we get back. Sigh...
if ( $gTranslateHtmlDiv === null ) {
$gTranslateHtmlDiv = $( "<div contenteditable='true' style='display:none;'></div>" ) ;
$( "body" ).append( $gTranslateHtmlDiv ) ;
}
$gTranslateHtmlDiv.html( val ) ;
return $gTranslateHtmlDiv.html() ;
}
function _tidyHTML( val )
{
val = val.trim() ;
// remove superfluous <br> tags
val = strReplaceAll( val, "<br></p>", "</p>" ) ;
while ( val.substring( val.length-4 ) === "<br>" )
val = val.substring( 0, val.length-4 ).trim() ;
// remove superfluous <p> blocks
if ( val.substring(0,3) === "<p>" && val.substring(val.length-4) === "</p>" && val.indexOf("<p>",1) === -1 )
val = val.substring( 3, val.length-4 ) ;
return val ;
}

@ -971,7 +971,7 @@ function unload_snippet_params( unpack_scenario_date, template_id )
if ( $elem.hasClass( "trumbowyg-editor" ) ) if ( $elem.hasClass( "trumbowyg-editor" ) )
val = unloadTrumbowyg( $elem, false ) ; val = unloadTrumbowyg( $elem, false ) ;
else if ( $elem.hasClass( "html-textbox" ) ) else if ( $elem.hasClass( "html-textbox" ) )
val = $elem.html() ; val = unloadHtmlTextbox( $elem ) ;
else else
val = $elem.val() ; val = $elem.val() ;
params[ $elem.attr("name") ] = val ; params[ $elem.attr("name") ] = val ;

@ -23,8 +23,8 @@ function _do_edit_ob_vo( $entry, player_no, vo_type )
return data ; return data ;
} }
function get_default_capabilities( vo_entry, params, show_warnings ) { function get_default_capabilities( vo_entry, params, show_warnings, translate ) {
return make_capabilities( var caps = make_capabilities(
false, false,
vo_entry, vo_type, vo_entry, vo_type,
params[ "PLAYER_"+player_no ], params[ "PLAYER_"+player_no ],
@ -32,9 +32,21 @@ function _do_edit_ob_vo( $entry, player_no, vo_type )
params.SCENARIO_THEATER, params.SCENARIO_YEAR, params.SCENARIO_MONTH, params.SCENARIO_THEATER, params.SCENARIO_YEAR, params.SCENARIO_MONTH,
show_warnings show_warnings
) ; ) ;
if ( translate ) {
caps.forEach( function( comment, index ) {
caps[index] = translateHTML( comment ) ;
} ) ;
}
return caps ;
} }
function get_default_comments( vo_entry ) { function get_default_comments( vo_entry, translate ) {
return vo_entry.comments ? vo_entry.comments : [] ; var comments = vo_entry.comments ? vo_entry.comments : [] ;
if ( translate ) {
comments.forEach( function( comment, index ) {
comments[index] = translateHTML( comment ) ;
} ) ;
}
return comments ;
} }
function load_entries( $sortable, entries ) { function load_entries( $sortable, entries ) {
@ -46,9 +58,7 @@ function _do_edit_ob_vo( $entry, player_no, vo_type )
function unload_entries( $sortable ) { function unload_entries( $sortable ) {
var entries = [] ; var entries = [] ;
$sortable.find( "div.html-textbox" ).each( function() { $sortable.find( "div.html-textbox" ).each( function() {
var val = $(this).html().trim() ; var val = unloadHtmlTextbox( $(this) ) ;
while ( val.substr( val.length-4 ) === "<br>" )
val = val.substr( 0, val.length-4 ) ;
if ( val.length > 0 ) if ( val.length > 0 )
entries.push( val ) ; entries.push( val ) ;
} ) ; } ) ;
@ -70,11 +80,11 @@ function _do_edit_ob_vo( $entry, player_no, vo_type )
var vo_entry = $entry.data( "sortable2-data" ).vo_entry ; var vo_entry = $entry.data( "sortable2-data" ).vo_entry ;
var capabilities = $entry.data( "sortable2-data" ).custom_capabilities ; var capabilities = $entry.data( "sortable2-data" ).custom_capabilities ;
if ( ! capabilities ) if ( ! capabilities )
capabilities = get_default_capabilities( vo_entry, params, true ).slice() ; capabilities = get_default_capabilities( vo_entry, params, true, false ).slice() ;
var elite = $entry.data( "sortable2-data" ).elite ; var elite = $entry.data( "sortable2-data" ).elite ;
var comments = $entry.data( "sortable2-data" ).custom_comments ; var comments = $entry.data( "sortable2-data" ).custom_comments ;
if ( ! comments ) if ( ! comments )
comments = get_default_comments( vo_entry ) ; comments = get_default_comments( vo_entry, false ) ;
// load the dialog // load the dialog
var vo_image_id = $entry.data( "sortable2-data" ).vo_image_id ; var vo_image_id = $entry.data( "sortable2-data" ).vo_image_id ;
@ -147,7 +157,7 @@ function _do_edit_ob_vo( $entry, player_no, vo_type )
var curr_params = $reset_capabilities.data( "params" ) ; var curr_params = $reset_capabilities.data( "params" ) ;
$dlg.find( ".header .vo-name" ).html( make_vo_name( curr_vo_entry.name, false ) ) ; $dlg.find( ".header .vo-name" ).html( make_vo_name( curr_vo_entry.name, false ) ) ;
load_entries( $capabilities, load_entries( $capabilities,
get_default_capabilities( curr_vo_entry, curr_params, false ) get_default_capabilities( curr_vo_entry, curr_params, false, false )
) ; ) ;
$elite.prop( "checked", false ) ; $elite.prop( "checked", false ) ;
} }
@ -155,7 +165,7 @@ function _do_edit_ob_vo( $entry, player_no, vo_type )
$reset_comments.data( { vo_entry: vo_entry, params: params } ) ; $reset_comments.data( { vo_entry: vo_entry, params: params } ) ;
function on_reset_comments() { function on_reset_comments() {
var curr_vo_entry = $reset_capabilities.data( "vo_entry" ) ; var curr_vo_entry = $reset_capabilities.data( "vo_entry" ) ;
load_entries( $comments, get_default_comments(curr_vo_entry) ) ; load_entries( $comments, get_default_comments( curr_vo_entry, false ) ) ;
} }
function update_for_elite( delta ) { function update_for_elite( delta ) {
@ -262,14 +272,14 @@ function _do_edit_ob_vo( $entry, player_no, vo_type )
$entry.data( "sortable2-data" ).vo_image_id = data.vo_image_id ; $entry.data( "sortable2-data" ).vo_image_id = data.vo_image_id ;
$entry.data( "sortable2-data" ).elite = data.elite ; $entry.data( "sortable2-data" ).elite = data.elite ;
// save the capabilities and comments // save the capabilities and comments
if ( data.capabilities.join() !== get_default_capabilities( vo_entry, params, false ).join() ) if ( data.capabilities.join() !== get_default_capabilities( vo_entry, params, false, true ).join() )
$entry.data( "sortable2-data" ).custom_capabilities = data.capabilities ; $entry.data( "sortable2-data" ).custom_capabilities = data.capabilities ;
else { else {
// the capabilities are the same as the default - no need to retain these custom settings // the capabilities are the same as the default - no need to retain these custom settings
delete $entry.data( "sortable2-data" ).custom_capabilities ; delete $entry.data( "sortable2-data" ).custom_capabilities ;
} }
// save the comments // save the comments
if ( data.comments.join() !== get_default_comments( vo_entry ).join() ) { if ( data.comments.join() !== get_default_comments( vo_entry, true ).join() ) {
$entry.data( "sortable2-data" ).custom_comments = data.comments ; $entry.data( "sortable2-data" ).custom_comments = data.comments ;
} }
else { else {

@ -16,15 +16,15 @@ from vasl_templates.webapp.tests.utils import \
def test_ob_setup( webapp, webdriver ): def test_ob_setup( webapp, webdriver ):
"""Test generating OB setup snippets.""" """Test generating OB setup snippets."""
_do_test_ob_entries( webapp, webdriver, "ob_setups", False ) _do_test_ob_entries( webapp, webdriver, "ob_setups" )
def test_ob_notes( webapp, webdriver ): def test_ob_notes( webapp, webdriver ):
"""Test generating OB note snippets.""" """Test generating OB note snippets."""
_do_test_ob_entries( webapp, webdriver, "ob_notes", True ) _do_test_ob_entries( webapp, webdriver, "ob_notes" )
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def _do_test_ob_entries( webapp, webdriver, ob_type, has_para ): def _do_test_ob_entries( webapp, webdriver, ob_type ):
"""Test generating OB setup/notes.""" """Test generating OB setup/notes."""
# initialize # initialize
@ -73,12 +73,7 @@ def _do_test_ob_entries( webapp, webdriver, ob_type, has_para ):
"[German] [<i>updated {} #2</i>] (col=[OBCOL:german/OBCOL-BORDER:german]) (width=[200px])".format( ob_type ) "[German] [<i>updated {} #2</i>] (col=[OBCOL:german/OBCOL-BORDER:german]) (width=[200px])".format( ob_type )
) )
check_snippet( sortable1, 0, check_snippet( sortable1, 0,
"[German] [{}{} #1{}] (col=[OBCOL:german/OBCOL-BORDER:german]) (width=[100px])".format( "[German] [{} #1] (col=[OBCOL:german/OBCOL-BORDER:german]) (width=[100px])".format( ob_type ) )
"<p>" if has_para else "",
ob_type,
"</p>" if has_para else ""
)
)
# delete an OB setup/note by dragging it into the trash # delete an OB setup/note by dragging it into the trash
assert get_sortable_entry_count( sortable1 ) == 2 assert get_sortable_entry_count( sortable1 ) == 2

Loading…
Cancel
Save