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
val = strReplaceAll( val, "<br></p>", "</p>" ) ;
while ( val.substring( val.length-4 ) === "<br>" )
val = val.substring( 0, val.length-4 ).trim() ;
return val ;
return _tidyHTML( val ) ;
}
// --------------------------------------------------------------------
@ -355,6 +350,12 @@ function onEditHtmlTextbox( $ctrl, objName ) {
} ) ;
}
function unloadHtmlTextbox( $ctrl )
{
// unload the HTML textbox
return _tidyHTML( $ctrl.html() ) ;
}
// --------------------------------------------------------------------
function sanitizeParams( params )
@ -379,3 +380,41 @@ function sanitizeHTML( val )
{ 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" ) )
val = unloadTrumbowyg( $elem, false ) ;
else if ( $elem.hasClass( "html-textbox" ) )
val = $elem.html() ;
val = unloadHtmlTextbox( $elem ) ;
else
val = $elem.val() ;
params[ $elem.attr("name") ] = val ;

@ -23,8 +23,8 @@ function _do_edit_ob_vo( $entry, player_no, vo_type )
return data ;
}
function get_default_capabilities( vo_entry, params, show_warnings ) {
return make_capabilities(
function get_default_capabilities( vo_entry, params, show_warnings, translate ) {
var caps = make_capabilities(
false,
vo_entry, vo_type,
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,
show_warnings
) ;
if ( translate ) {
caps.forEach( function( comment, index ) {
caps[index] = translateHTML( comment ) ;
} ) ;
}
return caps ;
}
function get_default_comments( vo_entry ) {
return vo_entry.comments ? vo_entry.comments : [] ;
function get_default_comments( vo_entry, translate ) {
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 ) {
@ -46,9 +58,7 @@ function _do_edit_ob_vo( $entry, player_no, vo_type )
function unload_entries( $sortable ) {
var entries = [] ;
$sortable.find( "div.html-textbox" ).each( function() {
var val = $(this).html().trim() ;
while ( val.substr( val.length-4 ) === "<br>" )
val = val.substr( 0, val.length-4 ) ;
var val = unloadHtmlTextbox( $(this) ) ;
if ( val.length > 0 )
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 capabilities = $entry.data( "sortable2-data" ).custom_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 comments = $entry.data( "sortable2-data" ).custom_comments ;
if ( ! comments )
comments = get_default_comments( vo_entry ) ;
comments = get_default_comments( vo_entry, false ) ;
// load the dialog
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" ) ;
$dlg.find( ".header .vo-name" ).html( make_vo_name( curr_vo_entry.name, false ) ) ;
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 ) ;
}
@ -155,7 +165,7 @@ function _do_edit_ob_vo( $entry, player_no, vo_type )
$reset_comments.data( { vo_entry: vo_entry, params: params } ) ;
function on_reset_comments() {
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 ) {
@ -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" ).elite = data.elite ;
// 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 ;
else {
// the capabilities are the same as the default - no need to retain these custom settings
delete $entry.data( "sortable2-data" ).custom_capabilities ;
}
// 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 ;
}
else {

@ -16,15 +16,15 @@ from vasl_templates.webapp.tests.utils import \
def test_ob_setup( webapp, webdriver ):
"""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 ):
"""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."""
# 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 )
)
check_snippet( sortable1, 0,
"[German] [{}{} #1{}] (col=[OBCOL:german/OBCOL-BORDER:german]) (width=[100px])".format(
"<p>" if has_para else "",
ob_type,
"</p>" if has_para else ""
)
)
"[German] [{} #1] (col=[OBCOL:german/OBCOL-BORDER:german]) (width=[100px])".format( ob_type ) )
# delete an OB setup/note by dragging it into the trash
assert get_sortable_entry_count( sortable1 ) == 2

Loading…
Cancel
Save