Added a WYSIWYG editor for HTML content.

master
Pacman Ghost 11 months ago committed by Pacman Ghost
parent d5021f7960
commit c420c168d1
  1. 7
      conftest.py
  2. 5
      vasl_templates/main_window.py
  3. 45
      vasl_templates/webapp/main.py
  4. 4
      vasl_templates/webapp/static/css/edit-simple-note-dialog.css
  5. 62
      vasl_templates/webapp/static/css/html-editor.css
  6. 3
      vasl_templates/webapp/static/css/main.css
  7. 2
      vasl_templates/webapp/static/css/tabs-scenario.css
  8. 2
      vasl_templates/webapp/static/css/tabs.css
  9. 218
      vasl_templates/webapp/static/html-editor.js
  10. 0
      vasl_templates/webapp/static/images/color-picker.png
  11. BIN
      vasl_templates/webapp/static/images/trumbowyg/back-color.png
  12. BIN
      vasl_templates/webapp/static/images/trumbowyg/fore-color.png
  13. BIN
      vasl_templates/webapp/static/images/trumbowyg/smile.png
  14. 2
      vasl_templates/webapp/static/jQueryHandlers.js
  15. 26
      vasl_templates/webapp/static/main.js
  16. 47
      vasl_templates/webapp/static/simple_notes.js
  17. 38
      vasl_templates/webapp/static/snippets.js
  18. 67
      vasl_templates/webapp/static/trumbowyg/langs/ar.js
  19. 11
      vasl_templates/webapp/static/trumbowyg/langs/ar.min.js
  20. 54
      vasl_templates/webapp/static/trumbowyg/langs/bg.js
  21. 8
      vasl_templates/webapp/static/trumbowyg/langs/bg.min.js
  22. 62
      vasl_templates/webapp/static/trumbowyg/langs/bn.js
  23. 9
      vasl_templates/webapp/static/trumbowyg/langs/bn.min.js
  24. 61
      vasl_templates/webapp/static/trumbowyg/langs/by.js
  25. 8
      vasl_templates/webapp/static/trumbowyg/langs/by.min.js
  26. 57
      vasl_templates/webapp/static/trumbowyg/langs/ca.js
  27. 11
      vasl_templates/webapp/static/trumbowyg/langs/ca.min.js
  28. 63
      vasl_templates/webapp/static/trumbowyg/langs/cs.js
  29. 8
      vasl_templates/webapp/static/trumbowyg/langs/cs.min.js
  30. 64
      vasl_templates/webapp/static/trumbowyg/langs/da.js
  31. 9
      vasl_templates/webapp/static/trumbowyg/langs/da.min.js
  32. 57
      vasl_templates/webapp/static/trumbowyg/langs/de.js
  33. 9
      vasl_templates/webapp/static/trumbowyg/langs/de.min.js
  34. 59
      vasl_templates/webapp/static/trumbowyg/langs/el.js
  35. 12
      vasl_templates/webapp/static/trumbowyg/langs/el.min.js
  36. 63
      vasl_templates/webapp/static/trumbowyg/langs/es.js
  37. 9
      vasl_templates/webapp/static/trumbowyg/langs/es.min.js
  38. 56
      vasl_templates/webapp/static/trumbowyg/langs/es_ar.js
  39. 10
      vasl_templates/webapp/static/trumbowyg/langs/es_ar.min.js
  40. 65
      vasl_templates/webapp/static/trumbowyg/langs/et.js
  41. 9
      vasl_templates/webapp/static/trumbowyg/langs/et.min.js
  42. 58
      vasl_templates/webapp/static/trumbowyg/langs/fa.js
  43. 10
      vasl_templates/webapp/static/trumbowyg/langs/fa.min.js
  44. 58
      vasl_templates/webapp/static/trumbowyg/langs/fi.js
  45. 9
      vasl_templates/webapp/static/trumbowyg/langs/fi.min.js
  46. 66
      vasl_templates/webapp/static/trumbowyg/langs/fr.js
  47. 12
      vasl_templates/webapp/static/trumbowyg/langs/fr.min.js
  48. 57
      vasl_templates/webapp/static/trumbowyg/langs/he.js
  49. 9
      vasl_templates/webapp/static/trumbowyg/langs/he.min.js
  50. 54
      vasl_templates/webapp/static/trumbowyg/langs/hr.js
  51. 9
      vasl_templates/webapp/static/trumbowyg/langs/hr.min.js
  52. 58
      vasl_templates/webapp/static/trumbowyg/langs/hu.js
  53. 10
      vasl_templates/webapp/static/trumbowyg/langs/hu.min.js
  54. 57
      vasl_templates/webapp/static/trumbowyg/langs/id.js
  55. 11
      vasl_templates/webapp/static/trumbowyg/langs/id.min.js
  56. 62
      vasl_templates/webapp/static/trumbowyg/langs/it.js
  57. 8
      vasl_templates/webapp/static/trumbowyg/langs/it.min.js
  58. 63
      vasl_templates/webapp/static/trumbowyg/langs/ja.js
  59. 10
      vasl_templates/webapp/static/trumbowyg/langs/ja.min.js
  60. 66
      vasl_templates/webapp/static/trumbowyg/langs/ko.js
  61. 11
      vasl_templates/webapp/static/trumbowyg/langs/ko.min.js
  62. 59
      vasl_templates/webapp/static/trumbowyg/langs/lt.js
  63. 8
      vasl_templates/webapp/static/trumbowyg/langs/lt.min.js
  64. 49
      vasl_templates/webapp/static/trumbowyg/langs/mn.js
  65. 8
      vasl_templates/webapp/static/trumbowyg/langs/mn.min.js
  66. 54
      vasl_templates/webapp/static/trumbowyg/langs/my.js
  67. 8
      vasl_templates/webapp/static/trumbowyg/langs/my.min.js
  68. 61
      vasl_templates/webapp/static/trumbowyg/langs/nl.js
  69. 9
      vasl_templates/webapp/static/trumbowyg/langs/nl.min.js
  70. 56
      vasl_templates/webapp/static/trumbowyg/langs/no_nb.js
  71. 10
      vasl_templates/webapp/static/trumbowyg/langs/no_nb.min.js
  72. 54
      vasl_templates/webapp/static/trumbowyg/langs/ph.js
  73. 8
      vasl_templates/webapp/static/trumbowyg/langs/ph.min.js
  74. 55
      vasl_templates/webapp/static/trumbowyg/langs/pl.js
  75. 9
      vasl_templates/webapp/static/trumbowyg/langs/pl.min.js
  76. 65
      vasl_templates/webapp/static/trumbowyg/langs/pt.js
  77. 11
      vasl_templates/webapp/static/trumbowyg/langs/pt.min.js
  78. 65
      vasl_templates/webapp/static/trumbowyg/langs/pt_br.js
  79. 11
      vasl_templates/webapp/static/trumbowyg/langs/pt_br.min.js
  80. 58
      vasl_templates/webapp/static/trumbowyg/langs/ro.js
  81. 12
      vasl_templates/webapp/static/trumbowyg/langs/ro.min.js
  82. 53
      vasl_templates/webapp/static/trumbowyg/langs/rs.js
  83. 8
      vasl_templates/webapp/static/trumbowyg/langs/rs.min.js
  84. 54
      vasl_templates/webapp/static/trumbowyg/langs/rs_latin.js
  85. 9
      vasl_templates/webapp/static/trumbowyg/langs/rs_latin.min.js
  86. 61
      vasl_templates/webapp/static/trumbowyg/langs/ru.js
  87. 8
      vasl_templates/webapp/static/trumbowyg/langs/ru.min.js
  88. 54
      vasl_templates/webapp/static/trumbowyg/langs/sk.js
  89. 8
      vasl_templates/webapp/static/trumbowyg/langs/sk.min.js
  90. 56
      vasl_templates/webapp/static/trumbowyg/langs/sl.js
  91. 8
      vasl_templates/webapp/static/trumbowyg/langs/sl.min.js
  92. 65
      vasl_templates/webapp/static/trumbowyg/langs/sq.js
  93. 8
      vasl_templates/webapp/static/trumbowyg/langs/sq.min.js
  94. 58
      vasl_templates/webapp/static/trumbowyg/langs/sv.js
  95. 12
      vasl_templates/webapp/static/trumbowyg/langs/sv.min.js
  96. 55
      vasl_templates/webapp/static/trumbowyg/langs/th.js
  97. 9
      vasl_templates/webapp/static/trumbowyg/langs/th.min.js
  98. 63
      vasl_templates/webapp/static/trumbowyg/langs/tr.js
  99. 12
      vasl_templates/webapp/static/trumbowyg/langs/tr.min.js
  100. 54
      vasl_templates/webapp/static/trumbowyg/langs/ua.js
  101. Some files were not shown because too many files have changed in this diff Show More

@ -42,7 +42,7 @@ def pytest_addoption( parser ):
help="Run the tests headless."
)
parser.addoption(
"--window-size", action="store", dest="window_size", default="1000x700",
"--window-size", action="store", dest="window_size", default="1020x700",
help="Browser window size."
)
@ -184,6 +184,11 @@ def _make_webapp():
elif _pytest_options.webdriver == "chrome":
app.config[ "WEBDRIVER_PATH" ] = "chromedriver"
# NOTE: Trumboyg adds a lot of buttons to the UI, which slows Selenium down a lot
# when it's searching for elements, so we run tests with a minimal configuration.
app.config[ "TRUMBOWYG_BUTTONS_VICTORY_CONDITIONS" ] = [ "viewHTML" ]
app.config[ "TRUMBOWYG_BUTTONS_SIMPLE_NOTE_DIALOG" ] = [ "viewHTML" ]
return app
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

@ -94,7 +94,10 @@ class MainWindow( QWidget ):
self.restoreGeometry( val )
else :
self.resize( 1000, 650 )
self.setMinimumSize( 1015, 630 )
# NOTE: This should be wide enough for the sortable hints to not wrap (so that
# we don't see a scrollbar when their panels are reduced to their minimum height).
# We also want the Trumbowyg button pane for the VC to wrap somewhere sensible.
self.setMinimumSize( 1030, 630 )
# initialize the layout
layout = QVBoxLayout( self )

@ -86,7 +86,9 @@ def get_app_config():
"""Get a JSON value from the app config."""
try:
val = app.config.get( key, default )
return val if isinstance(val,dict) else json.loads(val)
if isinstance( val, (dict,list) ):
return val
return json.loads( val )
except json.decoder.JSONDecodeError:
msg = "Couldn't parse app config setting: {}".format( key )
logging.error( "%s", msg )
@ -160,6 +162,47 @@ def get_app_config():
logging.error( "%s", msg )
startup_msg_store.error( msg )
# include the Trumbowyg config
# NOTE: We don't include the "insertImage" button because it doesn't seem to work when
# the Trumbowyg control is in a dialog, and given VASSAL's handling of images, we don't
# really want to be encouraging their use :-/
vals[ "trumbowyg" ] = {
"format-options": get_json_val( "TRUMBOWYG_FORMAT_OPTIONS", [
"h1", "h2", "h3",
] ),
"special-chars": get_json_val( "TRUMBOWYG_SPECIAL_CHARS", [
"2264", "2265", "2260", "00d7", "00f7", None, # math
"00bd", "00bc", "00be", "215b", "215c", "215d", "215e", None, # fractions
"25b3", "24c7", "24b7", "24ba", "2605", "221e", "b0", "b7", None, # special
"e4", "eb", "ef", "f6", "fc", "c4", "cb", "cf", "d6", "dc", None, # umlaut
"e1", "e9", "ed", "f3", "fa", "c1", "c9", "cd", "d3", "da", None, # acute
"e0", "e8", "ec", "f2", "f9", "c0", "c8", "cc", "d2", "d9", None, # grave
"e2", "ea", "ee", "f4", "fb", "c2", "ca", "ce", "d4", "db", None, # circumflex
"1f850", "1f852", "1f851", "1f853", # arrows
] ),
"victory-conditions": get_json_val( "TRUMBOWYG_BUTTONS_VICTORY_CONDITIONS", [
[ "strong", "em", "underline", "superscript", "subscript", "format" ],
[ "foreColor", "backColor", "fontfamily", "fontsize" ],
[ "outdent", "indent" ],
[ "unorderedList", "orderedList", "table" ],
[ "specialChars", "flags", "emoji" ],
[ "removeformat", "historyUndo", "historyRedo", "viewHTML", "fullscreen" ],
] ),
# NOTE: I tried having different buttons for OB setup notes (which tend to be simpler)
# and OB notes (which can be more involved), but (1) this meant we had to tear down
# and re-create the Trumbowyg control each time the dialog was opened (since there doesn't
# seem to be any way to dynamically change the buttons), which caused a noticeable delay,
# and (2) users are probaly going to complain :-/
"simple-note-dialog": get_json_val( "TRUMBOWYG_BUTTONS_SIMPLE_NOTE_DIALOG", [
[ "strong", "em", "underline", "del", "superscript", "subscript", "format" ],
[ "foreColor", "backColor", "fontfamily", "fontsize" ],
[ "align", "outdent", "indent" ],
[ "unorderedList", "orderedList", "table" ],
[ "specialChars", "flags", "emoji" ],
[ "removeformat", "historyUndo", "historyRedo", "viewHTML", "fullscreen" ],
] ),
}
return jsonify( vals )
# ---------------------------------------------------------------------

@ -1,6 +1,6 @@
#edit-simple_note { overflow: hidden ; }
#edit-simple_note { overflow: hidden ; padding-bottom: 0.75em !important ; }
.ui-dialog.edit-simple_note .ui-dialog-buttonpane { border: none ; margin-top: 0 !important ; padding-top: 0 !important ; }
.ui-dialog.edit-simple_note textarea { resize: none ; width: calc(100% - 4px) ; height: 100% ; }
.ui-dialog.edit-simple_note .container { height: 100% ; display: flex ; flex-direction: row ; }
.ui-dialog.edit-simple_note label[for="width"] { color: #444 ; }
.ui-dialog.edit-simple_note input[name="width"] { color: #444 ; }

@ -0,0 +1,62 @@
.trumbowyg-box { min-height: 2em ; border-color: #ccc ; }
.trumbowyg-editor, .trumbowyg-textarea {
padding: 0.5em 0.75em ;
min-height: 2em ;
}
.trumbowyg-button-group button::after { top: 25px !important ; }
/* custom bullets for the editor */
.trumbowyg-editor ul { margin: 0 0 0 0.85em ; list-style-image: url("../images/bullet.png") ; }
.trumbowyg-editor ul ul { margin: 0 0 0 0.85em ; list-style-image: url("../images/bullet2.png") ; }
.trumbowyg-editor ul ul ul { margin: 0 0 0 0.85em ; list-style-image: url("../images/bullet3.png") ; }
/* make tables visible in the editor */
.trumbowyg-editor table.table { width: auto ; }
.trumbowyg-editor table.table td { border: 1px dotted #888 ; }
/* FUDGE! CSS for blockquote doesn't work in VASSAL :-/, so we try to match its indent in our UI. */
.trumbowyg-editor blockquote { margin-left: 2.5em ; }
/* modal box */
.trumbowyg-modal-box { border: 1px solid #666 ; }
.trumbowyg-modal-box .trumbowyg-input-infos label { color: #444 ; font-weight: bold ; }
/* configure button */
.trumbowyg-foreColor-button {
width: 40px !important ;
background: no-repeat 12px 12px url("../images/trumbowyg/fore-color.png") !important ;
background-size: 12px 12px !important ;
filter: grayscale(100%) brightness(90%) ;
}
.trumbowyg-backColor-button {
width: 40px !important ;
background: no-repeat 12px 12px url("../images/trumbowyg/back-color.png") !important ;
background-size: 12px 12px !important ;
filter: grayscale(100%) brightness(90%) ;
}
.trumbowyg-emoji-button {
width: 40px !important ;
background: no-repeat 13px 13px url("../images/trumbowyg/smile.png") !important ;
background-size: 12px 12px !important ;
filter: grayscale(100%) brightness(40%) ;
}
.trumbowyg-removeformat-button { line-height: 33px !important ; border:1px dotted red; }
.trumbowyg-dropdown-specialChars { width: 330px ; max-width: 330px ; }
.trumbowyg-dropdown-align { max-height: 160px !important ; }
/* configure an image for our custom "flags" button */
.trumbowyg-flags-button {
width: 40px !important ;
background: no-repeat 12px 13px url("../images/nat-caps.png") !important ;
background-size: 12px 12px !important ;
filter: grayscale(100%) brightness(60%) ;
}
.trumbowyg-dropdown-flags button img { width: 13px ; }
/* FUDGE! Fix-up the appearance of some of the buttons. */
.trumbowyg-fontsize-button svg { width: 14px ; opacity: 0.9 ; }
.Xtrumbowyg-specialChars-button { color: #555 ; }
.trumbowyg-indent-button svg, .trumbowyg-outdent-button svg { width: 13px ; }
.trumbowyg-indent-button svg { transform: scaleX(-1) ; }

@ -4,6 +4,7 @@ body { height: 100% ; overflow: hidden ; }
body { font-family: Arial, Helvetica, sans-serif ; font-size: 16px ; }
p { margin-bottom: 0.5em ; }
ul, ol { margin: 0.5em 0 0 1.25em ; }
input[type="text"] { height: 20px ; border: 1px solid #c5c5c5 ; padding: 0 2px ; }
@ -58,11 +59,13 @@ input.snippet-width { width: 3.75em ; }
.sp-palette { max-width: 120px ; }
.sp-palette-row-selection { margin-top: 6px ; border-top: 1px solid #ccc ; padding-top: 6px ; }
/* growl notification balloons */
.growl-title { display: none ; }
.growl-close { position: absolute ; top: 0 ; right: 5px ; }
.growl .pre { font-family: monospace ; }
.growl div.pre { margin: 0 0 1em 1em ; font-size: 80% ; }
/* splitters */
.gutter { position: relative ; background-color: #ddd ; }
.gutter-vertical { cursor: row-resize ; }
.gutter-horizontal { cursor: col-resize ; }

@ -33,7 +33,7 @@ fieldset[name='scenario'] { min-height: 91px ; max-height: 265px ; overflow: hid
/* -------------------------------------------------------------------- */
#panel-vc { height: 100% ; display: flex ; flex-direction: column ; }
#panel-vc textarea { width: 100% ; resize: none ; flex-grow: 1 ; }
#panel-vc .trumbowyg-box { flex-grow: 1 ; min-height: 100px ; width: calc(100% - 2px) ; }
#panel-vc .footer { margin-top: 0.5em ; display: flex ; align-items: center ; }
/* -------------------------------------------------------------------- */

@ -27,7 +27,7 @@
#tabs-scenario .bl { height: 100% ; flex-grow: 1 ; }
#tabs-scenario .right { display: flex ; flex-direction: column ; }
#tabs-scenario .tr { height: 100% ; flex-grow: 1 ; }
#tabs-scenario .tr { height: 100% ; min-height: 210px ; flex-grow: 1 ; }
#tabs-scenario .br { height: 100% ; flex-grow: 1 ; min-height: 9em ; }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

@ -0,0 +1,218 @@
// --------------------------------------------------------------------
function initTrumbowyg( $elem, buttons, $parentDlg )
{
// initialize
var nats = get_sorted_nats().filter(
function( nat ) { return gHasPlayerFlag[ nat ] ; }
) ;
// initialize the Trumbowyg control
// NOTE: Trumbowyg uses the <div> we supply as the WYSIWYG editor, and creates an associated <textarea>
// for the raw HTML view (and another <div> for the button pane). Our code originally used textarea's
// to manage snippet content, so while we could transfer the "name" attribute (and "param" class)
// from the WYSIWYG control to the raw HTML textarea, it doesn't really help, since manipulating
// the content in the <textarea> directly doesn't work, we need to use Trumbowyg's "html" API, and that
// works from the WYSIWYG control.
$elem.trumbowyg( {
btnsDef: {
format: {
dropdown: gAppConfig.trumbowyg[ "format-options" ],
title: "Formatting",
ico: "p"
},
align: {
dropdown: [ "justifyLeft", "justifyCenter", "justifyRight", "justifyFull" ],
title: "Alignment",
ico: "justifyLeft",
},
fontfamily: { hasIcon: true, ico: "foreColor" },
specialChars: { hasIcon: false, text: "\u25b3", title: "Special characters" },
table: { title: "Table" },
fullscreen: { title: "Full screen" },
// FUDGE! While we can provide custom icons, they have to be SVG, so we do it in the CSS :-/
foreColor: { hasIcon: false, text: " ", title: "Text color" },
backColor: { hasIcon: false, text: " ", title: "Background color" },
removeformat: { hasIcon: false, text: "\u2a2f", title: "Remove formatting" },
emoji: { hasIcon: false, text: " ", title: "Emoji" },
// FUDGE! The indent and outdent icons are not quite the same,
// so we re-use the outdent image and flip it using CSS :-/
indent: { ico: "outdent" },
outdent: { title: "Un-indent" },
},
btns: buttons,
semantic: false,
plugins: {
specialchars: {
symbolList: gAppConfig.trumbowyg[ "special-chars" ],
},
flags: {
nationalities: nats,
makeFlagHtml: function( nat, force_local_image ) {
return make_player_flag_url( nat, true, force_local_image ) ;
},
},
},
} ) ;
var $parent = $elem.parent() ;
var $btnPane = $parent.find( ".trumbowyg-button-pane" ) ;
var $textarea = $parent.find( ".trumbowyg-textarea" ) ;
// update the flags dropdown for the current players
if ( $btnPane.find( ".trumbowyg-flags-button" ).length > 0 )
updateTrumbowygFlagsDropdown( $elem ) ;
// prepare for our jQuery event handlers
var eventHandlers = $elem.data( "eventHandlers" ) ;
if ( ! eventHandlers ) {
eventHandlers = new jQueryHandlers() ;
$elem.data( "eventHandlers", eventHandlers ) ;
}
// allow a hotkey to toggle the WYSIWYG editor
// FUDGE! While we can create a custom button to manually toggle the control, it doesn't quite work :-/
// Switching to HTML mode disables all buttons, including the "view HTML" button, and while we can
// manually enable it, hotkeys don't seem to work when we're in HTML mode :-/ We hack around this by
// adding a key handler and managing the whole process ourself. Sigh...
function onKeyDown( evt ) {
// check for Ctrl-M
if ( evt.keyCode == 77 && evt.ctrlKey ) {
$elem.trumbowyg( "toggle" ) ;
setTimeout( function() {
if ( $elem.parent().hasClass( "trumbowyg-editor-visible" ) )
$elem.focus() ;
else
$elem.parent().find( ".trumbowyg-textarea" ).focus() ;
}, 20 ) ;
evt.preventDefault() ;
return ;
}
// handle auto-dismiss if we are in a dialog
if ( $parentDlg )
auto_dismiss_dialog( $parentDlg, evt, "OK" ) ;
}
eventHandlers.addHandler( $elem, "keydown", onKeyDown ) ;
eventHandlers.addHandler( $textarea, "keydown", onKeyDown ) ;
// FUDGE! There should be spaces around the +, but this causes the tooltip to wrap on Windows :-/
$btnPane.find( ".trumbowyg-viewHTML-button" ).attr( "title", "View HTML (Ctrl+M)" ) ;
// handle resize events
if ( ! $parent.data( "resizeObserver" ) ) {
var resizeObserver = new ResizeObserver( function( entries ) {
// FUDGE! Couldn't get Trumbowyg to sit nicely inside a flexbox, so we set the height dynamically :-/
var height = "calc(100% - " + $btnPane.height() + "px)" ;
$elem.css( { height: height } ) ;
$textarea.css( { height: height } ) ;
// limit the height of dropdown's
if ( $parentDlg ) {
$parent.find( ".trumbowyg-dropdown" ).css( {
"max-height": $elem.height() + 5
} ) ;
}
} ) ;
resizeObserver.observe( $parent[0] ) ;
$parent.data( "resizeObserver", resizeObserver ) ;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function destroyTrumbowyg( $elem )
{
// destroy the Trumbowyg control and clean up
var eventHandlers = $elem.data( "eventHandlers" ) ;
if ( eventHandlers ) {
eventHandlers.cleanUp() ;
$elem.removeData( "eventHandlers" ) ;
}
$elem.trumbowyg( "destroy" ) ;
}
// --------------------------------------------------------------------
function unloadTrumbowyg( $elem, removeFirstPara )
{
// unload the Trumbowyg control
var val = $elem.trumbowyg( "html" ).trim() ;
// FUDGE! Trumbowyg really wants to wrap everything in <p> blocks, but this causes problems
// since many of the templates are expecting a bit of plain old text, not blocks of content
// e.g. OB setup notes start with a flag, and putting the content in a <p> block breaks
// the layout. We hack around this by removing the *first* <p> block.
if ( removeFirstPara ) {
var match = val.match( /<p>.*?<\/p>/s ) ; //jshint ignore:line
if ( match ) {
var pos = match.index + match[0].length ; // nb: index to end of the </p>
val = val.substring( 0, match.index ) +
val.substring( match.index+3, pos-4 ) +
val.substring( pos ) ;
}
}
// 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 ;
}
// --------------------------------------------------------------------
function initVictoryConditionsTrumbowyg()
{
// initialize the Victory Conditions Trumbowyg control
var $elem = $( "div.param[name='VICTORY_CONDITIONS']" ) ;
initTrumbowyg( $elem, gAppConfig.trumbowyg["victory-conditions"], null ) ;
if ( gPendingVictoryConditions )
$elem.trumbowyg( "html", gPendingVictoryConditions ) ;
// FUDGE! For some reason, we need to do this :shrug:
$elem.trumbowyg().on( "tbwopenfullscreen", function() {
$( "#menu" ).hide() ;
} ).on( "tbwclosefullscreen", function() {
$( "#menu" ).show() ;
} ) ;
}
function updateTrumbowygFlagsDropdown( $elem )
{
// FUDGE! For convenience, we show the flags for the current players at the start of the dropdown list,
// and while we can do this in makeDropdown() in our plugin, this only happens once for the Victory Conditions
// control. There doesn't seem to be a way to dynamically generate the list each time it drops down,
// so we do it by modifying the DOM.
// initialize
var trumbowyg = $elem.data( "trumbowyg" ) ;
if ( ! trumbowyg )
return ;
var plugin = trumbowyg.o.plugins.flags ;
var nat1 = get_player_nat( 1 ) ;
var nat2 = get_player_nat( 2 ) ;
// locate the flags dropdown
$dropdown = $elem.parent().find( ".trumbowyg-dropdown-flags" ) ;
if ( $dropdown.length === 0 )
return ;
// remove the dropdown's flag buttons from the DOM
var $btns = {} ;
$dropdown.find( "button" ).detach().each( function() {
var nat = $(this).find( "img" ).data( "nat" ) ;
$btns[ nat ] = $(this) ;
} ) ;
// add the flag buttons back into the DOM
plugin.nationalities.forEach( function( nat ) {
if ( nat === nat1 || nat === nat2 )
return ;
var $btn = $btns[ nat ] ;
if ( $btn )
$dropdown.append( $btn ) ;
} ) ;
var $btn = $btns[ nat2 ] ;
if ( $btn )
$dropdown.prepend( $btn ) ;
$btn = $btns[ nat1 ] ;
if ( $btn )
$dropdown.prepend( $btn ) ;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

@ -20,7 +20,7 @@ class jQueryHandlers
for ( var i=this.events.length-1 ; i >= 0 ; --i ) {
var evt = this.events[ i ] ;
evt[0].off( evt[1], evt[2] ) ;
}
}
}
}

@ -775,6 +775,13 @@ function update_page_load_status( id )
$("#tabs").tabs({ disabled: [] }) ;
$("#loader").fadeOut( 500 ) ;
adjust_footer_vspacers() ;
// initialize the HTML WYSIWYG editors (nb: we do it here, since we need the app config
// and template pack (for the player flags))
initVictoryConditionsTrumbowyg() ;
$( "#panel-vc .footer" ).fadeIn( 2*1000 ) ;
// FUDGE! This works around a timing problem during startup, where we unload the current parameters
// before the Victory Conditions Trumbowyg control has initialized (and so doesn't get included).
gLastSavedScenario = unload_params_for_save( false ) ;
// NOTE: The watermark image appears briefly in IE when reloading the page, but not even
// creating the watermark dynamically and removing it when the page unloads fixes it :-(
$("#watermark").fadeIn( 5*1000 ) ;
@ -826,16 +833,20 @@ function init_hotkeys()
set_focus_to( "#tabs-scenario", $("select[name='PLAYER_1']") ) ;
} ) ;
$(document).bind( "keydown", "alt+y", function() {
set_focus_to( "#tabs-scenario", $("textarea[name='VICTORY_CONDITIONS']") ) ;
var $elem = $(".trumbowyg-editor[name='VICTORY_CONDITIONS']") ;
if ( $elem.parent().hasClass( "trumbowyg-editor-visible" ) )
set_focus_to( "#tabs-scenario", $elem ) ;
else
set_focus_to( "#tabs-scenario", $elem.parent().find( ".trumbowyg-textarea" ) ) ;
} ) ;
$(document).bind( "keydown", "alt+0", function() {
set_focus_to( "#tabs-scenario", $("input[name='SCENARIO_NAME']") ) ; // nb: for consistency with Alt-1 and Alt-2
} ) ;
$(document).bind( "keydown", "alt+1", function() {
set_focus_to( "#tabs-ob1", $("textarea[name='OB_SETUP_1']") ) ;
set_focus_to( "#tabs-ob1" ) ;
} ) ;
$(document).bind( "keydown", "alt+2", function() {
set_focus_to( "#tabs-ob2", $("textarea[name='OB_SETUP_2']") ) ;
set_focus_to( "#tabs-ob2" ) ;
} ) ;
$(document).bind( "keydown", "alt+x", function() {
set_focus_to( "#tabs-extras" ) ;
@ -947,6 +958,7 @@ function on_player_change( player_no )
var player_nat = update_ob_tab_header( player_no ) ;
update_nationality_specific_buttons( player_no ) ;
$( "input[name='PLAYER_" + player_no + "_DESCRIPTION']" ).val( "" ) ;
updateTrumbowygFlagsDropdown( $( ".param[name='VICTORY_CONDITIONS']" ) ) ;
// show/hide the vehicle/ordnance multi-applicable notes controls
function update_ma_notes_controls( vo_type ) {
@ -1141,6 +1153,14 @@ function handle_escape( evt )
$(this).trigger( "click" ) ;
} ) ;
// check if there is a Trumbowyg control full-screen
var $elem = $( ".trumbowyg-fullscreen" ) ;
if ( $elem.length > 0 ) {
// yup - restore it back to normal size
$elem.children( ".trumbowyg-editor" ).trumbowyg( "execCmd", { cmd: "fullscreen" } ) ;
return ;
}
// find the top-most dialog (if any) and close it
var $topmost = findTopmostDialog() ;
if ( $topmost ) {

@ -2,27 +2,29 @@
// which is used by OB setups and OB notes (which differ only in their templates,
// the code to manage them is almost identical).
var gEditSimpleNoteDlgState = null ;
// --------------------------------------------------------------------
function add_scenario_note() { _do_edit_simple_note( "scenario_note", null, $("#scenario_notes-sortable"), null, gDefaultScenario._SCENARIO_NOTE_WIDTH ) ; }
function add_scenario_note() { _do_edit_simple_note( "scenario_note", null, $("#scenario_notes-sortable"), null, gDefaultScenario._SCENARIO_NOTE_WIDTH, false ) ; }
function do_add_scenario_note( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
function edit_scenario_note( $sortable2, $entry ) { _do_edit_simple_note( "scenario_note", null, $sortable2, $entry, null ) ; }
function edit_scenario_note( $sortable2, $entry ) { _do_edit_simple_note( "scenario_note", null, $sortable2, $entry, null, false ) ; }
function add_ssr() { _do_edit_simple_note( "ssr", null, $("#ssr-sortable"), null, null ) ; }
function add_ssr() { _do_edit_simple_note( "ssr", null, $("#ssr-sortable"), null, null, true ) ; }
function do_add_ssr( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
function edit_ssr( $sortable2, $entry ) { _do_edit_simple_note( "ssr", null, $sortable2, $entry, null ) ; }
function edit_ssr( $sortable2, $entry ) { _do_edit_simple_note( "ssr", null, $sortable2, $entry, null, true ) ; }
function add_ob_setup( player_no ) { _do_edit_simple_note( "ob_setup", player_no, $("#ob_setups-sortable_"+player_no), null, gDefaultScenario._OB_SETUP_WIDTH ) ; }
function add_ob_setup( player_no ) { _do_edit_simple_note( "ob_setup", player_no, $("#ob_setups-sortable_"+player_no), null, gDefaultScenario._OB_SETUP_WIDTH, true ) ; }
function do_add_ob_setup( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
function edit_ob_setup( $sortable2, $entry ) { _do_edit_simple_note( "ob_setup", get_player_no_for_element($sortable2), $sortable2, $entry, null ) ; }
function edit_ob_setup( $sortable2, $entry ) { _do_edit_simple_note( "ob_setup", get_player_no_for_element($sortable2), $sortable2, $entry, null, true ) ; }
function add_ob_note( player_no ) { _do_edit_simple_note( "ob_note", player_no, $("#ob_notes-sortable_"+player_no), null, gDefaultScenario._OB_NOTE_WIDTH ) ; }
function add_ob_note( player_no ) { _do_edit_simple_note( "ob_note", player_no, $("#ob_notes-sortable_"+player_no), null, gDefaultScenario._OB_NOTE_WIDTH, false ) ; }
function do_add_ob_note( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
function edit_ob_note( $sortable2, $entry ) { _do_edit_simple_note( "ob_note", get_player_no_for_element($sortable2), $sortable2, $entry, null ) ; }
function edit_ob_note( $sortable2, $entry ) { _do_edit_simple_note( "ob_note", get_player_no_for_element($sortable2), $sortable2, $entry, null, false ) ; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function _do_edit_simple_note( template_id, player_no, $sortable2, $entry, default_width )
function _do_edit_simple_note( template_id, player_no, $sortable2, $entry, default_width, remove_first_para )
{
// figure out what we're editing
var note_type = _get_note_type_for_sortable( $sortable2 ) ;
@ -73,7 +75,7 @@ function _do_edit_simple_note( template_id, player_no, $sortable2, $entry, defau
function unloadData() {
// unload the snippet data
return {
caption: $caption.val().trim(),
caption: unloadTrumbowyg( $caption, remove_first_para ),
width: $width.val().trim(),
} ;
}
@ -86,6 +88,10 @@ function _do_edit_simple_note( template_id, player_no, $sortable2, $entry, defau
title: dlgTitle,
modal: true,
closeOnEscape: false,
position: gEditSimpleNoteDlgState ? gEditSimpleNoteDlgState.position : { my: "center", at: "center", of: window },
width: gEditSimpleNoteDlgState ? gEditSimpleNoteDlgState.width : $(window).width() * 0.4,
// NOTE: Simple notes don't normally have a lot of content, but we need space for the Trumbowyg dropdowns.
height: gEditSimpleNoteDlgState ? gEditSimpleNoteDlgState.height : Math.max( $(window).height() * 0.5, 325 ),
minWidth: 600,
minHeight: 250,
create: function() {
@ -93,7 +99,7 @@ function _do_edit_simple_note( template_id, player_no, $sortable2, $entry, defau
},
open: function() {
// initialize
$caption = $(this).children( "textarea" ) ;
$caption = $(this).find( "div.caption" ) ;
on_dialog_open( $(this), $caption ) ;
add_flag_to_dialog_titlebar( $(this), get_player_no_for_element($sortable2) ) ;
var $btn_pane = $(".ui-dialog.edit-simple_note .ui-dialog-buttonpane") ;
@ -104,11 +110,21 @@ function _do_edit_simple_note( template_id, player_no, $sortable2, $entry, defau
$width = $btn_pane.find( "input[name='width']" ) ;
if ( $width.length === 0 ) {
// create the width controls
$btn_pane.prepend( $( "<div style='position:absolute;left:15px;height:28px;display:flex;align-items:center;'>" +
$btn_pane.prepend( $( "<div style='position:absolute;left:19px;height:28px;display:flex;align-items:center;'>" +
"<label for='width'>Width:</label>&nbsp;<input type='text' name='width' size='4' style='margin-top:-1px;'>" +
"</div>" ) ) ;
$width = $btn_pane.find( "input[name='width']" ) ;
}
// initialize the Trumbowyg HTML editor
if ( ! gEditSimpleNoteDlgState ) // nb: check if this is the first time the dialog has been opened
initTrumbowyg( $caption, gAppConfig.trumbowyg["simple-note-dialog"], $(this) ) ;
else {
// always start non-maximized, and in HTML mode
if ( $caption.parent().hasClass( "trumbowyg-fullscreen" ) )
$caption.trumbowyg( "execCmd", { cmd: "fullscreen" } ) ;
if ( $caption.parent().hasClass( "trumbowyg-editor-hidden" ) )
$caption.trumbowyg( "toggle" ) ;
}
// tweak the SNIPPETS button so that snippets will work
$btn.data( { id: template_id, "player-no": player_no } ) ;
var snippet_id = template_id ;
@ -136,10 +152,13 @@ function _do_edit_simple_note( template_id, player_no, $sortable2, $entry, defau
border: "1px solid "+colors[2]
} ) ;
// load the dialog
$caption.val( entryData ? entryData.caption : "" ).focus() ;
$caption.trumbowyg( "html", entryData ? entryData.caption : "" ) ;
$width.val( entryData ? entryData.width : default_width ) ;
origData = unloadData() ;
$(this).height( $(this).height() ) ; // fudge: force the textarea to resize
$(this).height( $(this).height() ) ; // fudge: force everything to resize
},
beforeClose: function() {
gEditSimpleNoteDlgState = getDialogState( $(this) ) ;
},
buttons: {
Snippet: { text:" Snippet", class: "snippet", click: makeSimpleSnippet },

@ -34,6 +34,7 @@ var gLastSavedScenario = null ;
var gLastSavedScenarioFilename = null ;
var gScenarioCreatedTime = null ;
var gEditTemplateDlgState = null ;
var gPendingVictoryConditions = null ;
// --------------------------------------------------------------------
@ -964,10 +965,10 @@ function unload_snippet_params( unpack_scenario_date, template_id )
if ( template_id === null || template_id.substr(0,7) !== "extras/" )
return ;
}
params[ $elem.attr("name") ] = $elem.val() ;
params[ $elem.attr("name") ] = $elem.hasClass("trumbowyg-editor") ? unloadTrumbowyg($elem,false) : $elem.val() ;
} ;
$("input[type='text'].param").each( function() { add_param( $(this) ) ; } ) ;
$("textarea.param").each( function() { add_param( $(this) ) ; } ) ;
$(".trumbowyg-editor.param").each( function() { add_param( $(this) ) ; } ) ;
$("select.param").each( function() { add_param( $(this) ) ; } ) ;
// fix up the turn track parameters
@ -1622,7 +1623,7 @@ function edit_template( template_id )
},
open: function() {
on_dialog_open( $(this) ) ;
$(this).height( $(this).height() ) ; // fudge: force the textarea to resize
$(this).height( $(this).height() ) ; // fudge: force everything to resize
$("#edit-template textarea").change( on_template_change ) ;
},
beforeClose: function() {
@ -1751,10 +1752,11 @@ function do_load_scenario_data( params )
}
}
else {
if ( $elem.prop( "disabled" ) )
$elem.val( "" ) ;
var val = $elem.prop("disabled") ? "" : params[key] ;
if ( $elem.hasClass( "trumbowyg-editor" ) )
$elem.trumbowyg( "html", val ) ;
else
$elem.val( params[key] ) ;
$elem.val( val ) ;
if ( key === "ASA_ID" )
updateForConnectedScenario( params[key], params.ROAR_ID ) ;
}
@ -1862,13 +1864,13 @@ function do_load_scenario_data( params )
continue ;
}
//jshint loopfunc: true
var $elem = $("input[type='text'][name='"+key+"'].param").each( function() {
var $elem = $( "input[type='text'][name='" + key + "'].param" ).each( function() {
set_param( $(this), key ) ;
} ) ;
$elem = $("textarea[type='text'][name='"+key+"'].param").each( function() {
$elem = $( ".trumbowyg-editor[name='" + key + "'].param" ).each( function() {
set_param( $(this), key ) ;
} ) ;
$elem = $("select[name='"+key+"'].param").each( function() {
$elem = $( "select[name='" + key + "'].param" ).each( function() {
if ( key !== "PLAYER_1" && key !== "PLAYER_2" )
set_param( $(this), key ).trigger( "change" ) ;
} ) ;
@ -1876,6 +1878,22 @@ function do_load_scenario_data( params )
if ( ! params.ASA_ID )
updateForConnectedScenario( null, null ) ;
// NOTE: Loading the Victory Conditions creates a Trumbowyg history entry, so we clear the history
// so that user can't accidentally undo state all the way back to an empty control.
var trumbowyg = $( ".param[name='VICTORY_CONDITIONS']" ).data( "trumbowyg" ) ;
if ( trumbowyg ) {
var plugin = trumbowyg.o.plugins.history ;
plugin._stack = [] ;
plugin._index = -1 ;
}
// FUDGE! The introduction of the Trumbowyg introduced a timing issue dring startup - the Victory Conditions
// control can't be initialized until some things arrive from the backend, but loading the default scenario
// happens before then (which is where we are now), and so we end up warning about an unused key.
// Nornally, the default scenario would never contain VC, but it's useful for testing, so we handle it here.
gPendingVictoryConditions = params.VICTORY_CONDITIONS ;
delete params.VICTORY_CONDITIONS ;
// look for unrecognized keys
var buf = [] ;
for ( key in params ) {
@ -2132,7 +2150,7 @@ function reset_scenario()
if ( ! $.contains( $("#tabs-extras")[0], $(this)[0] ) )
$(this).val( "" ) ;
} ) ;
$("textarea.param").each( function() { $(this).val("") ; } ) ;
$(".trumbowyg-editor").each( function() { $(this).trumbowyg( "empty" ) ; } ) ;
$("input[type='checkbox']").prop( "checked", false ) ;
$( "select[name='TURN_TRACK_NTURNS'].param" ).val( "" ).trigger( "change" ) ;

@ -0,0 +1,67 @@
/* ===========================================================
* ar.js
* Arabic translation for Trumbowyg
* http://alex-d.github.com/Trumbowyg
* ===========================================================
* Author : Abo Mokh ahmed (abomokhahmed)
* Github : https://github.com/abomokhahmed
* Reviewed by : Abdellah Chadidi (chadidi)
* Github : https://github.com/chadidi
*/
jQuery.trumbowyg.langs.ar = {
_dir: 'rtl',
viewHTML: 'إعرض-HTML',
undo: 'تراجع',
redo: 'إعادة',
formatting: 'تنسيق',
p: 'فقرة',
blockquote: 'اقتباس',
code: 'كود',
header: 'رأس',
bold: 'عريض',
italic: 'مائل',
strikethrough: 'مشطوب',
underline: 'خطّ سفلي',
strong: 'بارز',
em: 'تغميق',
del: 'حذف',
superscript: 'الأس',
subscript: 'أس سفلي',
unorderedList: 'قائمة غير مرتّبة',
orderedList: 'قائمة مرتّبة',
insertImage: 'إدراج صورة',
insertVideo: 'إدراج فيديو',
link: 'رابط',
createLink: 'انشاء رابط',
unlink: 'حذف رابط',
justifyLeft: 'تصحيح للشمال',
justifyCenter: 'توسيط',
justifyRight: 'تصحيح لليمين',
justifyFull: 'تصحيح لكلا الإتّجاهين',
horizontalRule: 'إدراج خطّ أفقي',
fullscreen: 'ملء الشاشة',
close: 'إغلاق',
submit: 'إرسال',
reset: 'إعادة تعيين',
required: 'إلزامي',
description: 'وصف',
title: 'عنوان',
text: 'نصّ',
target: 'الهدف'
};

@ -0,0 +1,11 @@
/* ===========================================================
* ar.js
* Arabic translation for Trumbowyg
* http://alex-d.github.com/Trumbowyg
* ===========================================================
* Author : Abo Mokh ahmed (abomokhahmed)
* Github : https://github.com/abomokhahmed
* Reviewed by : Abdellah Chadidi (chadidi)
* Github : https://github.com/chadidi
*/
jQuery.trumbowyg.langs.ar={_dir:"rtl",viewHTML:"إعرض-HTML",undo:"تراجع",redo:"إعادة",formatting:"تنسيق",p:"فقرة",blockquote:"اقتباس",code:"كود",header:"رأس",bold:"عريض",italic:"مائل",strikethrough:"مشطوب",underline:"خطّ سفلي",strong:"بارز",em:"تغميق",del:"حذف",superscript:"الأس",subscript:"أس سفلي",unorderedList:"قائمة غير مرتّبة",orderedList:"قائمة مرتّبة",insertImage:"إدراج صورة",insertVideo:"إدراج فيديو",link:"رابط",createLink:"انشاء رابط",unlink:"حذف رابط",justifyLeft:"تصحيح للشمال",justifyCenter:"توسيط",justifyRight:"تصحيح لليمين",justifyFull:"تصحيح لكلا الإتّجاهين",horizontalRule:"إدراج خطّ أفقي",fullscreen:"ملء الشاشة",close:"إغلاق",submit:"إرسال",reset:"إعادة تعيين",required:"إلزامي",description:"وصف",title:"عنوان",text:"نصّ",target:"الهدف"};

@ -0,0 +1,54 @@
/* ===========================================================
* bg.js
* Bulgarian translation for Trumbowyg
* http://alex-d.github.com/Trumbowyg
* ===========================================================
* Author : Aleksandar Dimitrov
*/
jQuery.trumbowyg.langs.bg = {
viewHTML: 'Прегледай HTML',
formatting: 'Форматиране',
p: 'Параграф',
blockquote: 'Цитат',
code: 'Код',
header: 'Заглавие',
bold: 'Удебелен',
italic: 'Наклонен',
strikethrough: 'Зачеркнат',
underline: 'Подчертан',
strong: 'Удебелен',
em: 'Наклонен',
del: 'Зачеркнат',
unorderedList: 'Обикновен списък',
orderedList: 'Номериран списък',
insertImage: 'Добави изображение',
insertVideo: 'Добави видео',
link: 'Връзка',
createLink: 'Създай връзка',
unlink: 'Премахни връзката',
justifyLeft: 'Подравни от ляво',
justifyCenter: 'Центрирай',
justifyRight: 'Подравни от дясно',
justifyFull: 'Подравни по ширина',
horizontalRule: 'Хоризонтална линия',
fullscreen: 'На цял екран',
close: 'Затвори',
submit: 'Впиши',
reset: 'Отмени',
required: 'Задължително',
description: 'Описание',
title: 'Заглавие',
text: 'Текст'
};

@ -0,0 +1,8 @@
/* ===========================================================
* bg.js
* Bulgarian translation for Trumbowyg
* http://alex-d.github.com/Trumbowyg
* ===========================================================
* Author : Aleksandar Dimitrov
*/
jQuery.trumbowyg.langs.bg={viewHTML:"Прегледай HTML",formatting:"Форматиране",p:"Параграф",blockquote:"Цитат",code:"Код",header:"Заглавие",bold:"Удебелен",italic:"Наклонен",strikethrough:"Зачеркнат",underline:"Подчертан",strong:"Удебелен",em:"Наклонен",del:"Зачеркнат",unorderedList:"Обикновен списък",orderedList:"Номериран списък",insertImage:"Добави изображение",insertVideo:"Добави видео",link:"Връзка",createLink:"Създай връзка",unlink:"Премахни връзката",justifyLeft:"Подравни от ляво",justifyCenter:"Центрирай",justifyRight:"Подравни от дясно",justifyFull:"Подравни по ширина",horizontalRule:"Хоризонтална линия",fullscreen:"На цял екран",close:"Затвори",submit:"Впиши",reset:"Отмени",required:"Задължително",description:"Описание",title:"Заглавие",text:"Текст"};

@ -0,0 +1,62 @@
/* ===========================================================
* bn.js
* Bangla translation for Trumbowyg
* http://alex-d.github.com/Trumbowyg
* ===========================================================
* Author : Ahammad Naim
* Website : https://github.com/AhammadNaim
*/
jQuery.trumbowyg.langs.bn = {
viewHTML: 'HTML দন',
undo: 'পবসিন',
redo: 'পনর করন',
formatting: 'বিস',
p: 'অনদ',
blockquote: 'উদি',
code: 'কড',
header: 'শিম',
bold: 'বড',
italic: 'ইটিক',
strikethrough: 'সইকথ',
underline: 'আনরলইন',
strong: 'বড',
em: 'ইটিক',
del: 'সইকথ',
superscript: 'সরসিট',
subscript: 'সবসিট',
unorderedList: 'অসিত তি',
orderedList: 'সি',
insertImage: 'ছবি',
link: 'লিক',
createLink: 'লিক তি করন',
unlink: 'লিক মন',
justifyLeft: 'বিইড',
justifyCenter: 'কত',
justifyRight: 'ডিইড',
justifyFull: 'জিইড',
horizontalRule: 'আনিক দগ',
removeformat: 'বিস অপসরণ করন',
fullscreen: 'সমণ পরয় দন',
close: 'বনধ',
submit: 'পরণ',
reset: 'বিল',
required: 'আবশযক',
description: 'বরনন',
title: 'শিম',
text: 'পয',
target: 'লকয'
};

@ -0,0 +1,9 @@
/* ===========================================================
* bn.js
* Bangla translation for Trumbowyg
* http://alex-d.github.com/Trumbowyg
* ===========================================================
* Author : Ahammad Naim
* Website : https://github.com/AhammadNaim
*/
jQuery.trumbowyg.langs.bn={viewHTML:"HTML দন",undo:"পবসিন",redo:"পনর করন",formatting:"বিস",p:"অনদ",blockquote:"উদি",code:"কড",header:"শিম",bold:"বড",italic:"ইটিক",strikethrough:"সইকথ",underline:"আনরলইন",strong:"বড",em:"ইটিক",del:"সইকথ",superscript:"সরসিট",subscript:"সবসিট",unorderedList:"অসিত তি",orderedList:"সি",insertImage:"ছবি",link:"লিক",createLink:"লিক তি করন",unlink:"লিক মন",justifyLeft:"বিইড",justifyCenter:"কত",justifyRight:"ডিইড",justifyFull:"জিইড",horizontalRule:"আনিক দগ",removeformat:"বিস অপসরণ করন",fullscreen:"সমণ পরয় দন",close:"বনধ",submit:"পরণ",reset:"বিল",required:"আবশযক",description:"বরনন",title:"শিম",text:"পয",target:"লকয"};

@ -0,0 +1,61 @@
/* ===========================================================
* by.js
* Belarusian translation for Trumbowyg
* http://alex-d.github.com/Trumbowyg
* ===========================================================
* Author : Yury Karalkou
*/
jQuery.trumbowyg.langs.by = {
viewHTML: 'Паглядзець HTML',
undo: 'Скасаваць',
redo: 'Паўтарыць',
formatting: 'Фарматаванне',
p: 'Звычайны',
blockquote: 'Цытата',
code: 'Код',
header: 'Загаловак',
bold: 'Паўтлусты',
italic: 'Курсіў',
strikethrough: 'Закрэслены',
underline: 'Падкрэслены',
strong: 'Паўтлусты',
em: 'Курсіў',
del: 'Закрэслены',
superscript: 'Верхні індэкс',
subscript: 'Індэкс',
unorderedList: 'Звычайны спіс',
orderedList: 'Нумараваны спіс',
insertImage: 'Уставіць выяву',
insertVideo: 'Уставіць відэа',
link: 'Спасылка',
createLink: 'Уставіць спасылку',
unlink: 'Выдаліць спасылку',
justifyLeft: 'Па леваму боку',
justifyCenter: 'У цэнтры',
justifyRight: 'Па праваму боку',
justifyFull: 'Па шырыні',
horizontalRule: 'Гарызантальная лінія',
removeformat: 'Ачысціць фарматаванне',
fullscreen: 'На ўвесь экран',
close: 'Зачыніць',
submit: 'Уставіць',
reset: 'Скасаваць',
required: 'Абавязкова',
description: 'Апісанне',
title: 'Падказка',
text: 'Тэкст'
};

@ -0,0 +1,8 @@
/* ===========================================================
* by.js
* Belarusian translation for Trumbowyg
* http://alex-d.github.com/Trumbowyg
* ===========================================================
* Author : Yury Karalkou
*/
jQuery.trumbowyg.langs.by={viewHTML:"Паглядзець HTML",undo:"Скасаваць",redo:"Паўтарыць",formatting:"Фарматаванне",p:"Звычайны",blockquote:"Цытата",code:"Код",header:"Загаловак",bold:"Паўтлусты",italic:"Курсіў",strikethrough:"Закрэслены",underline:"Падкрэслены",strong:"Паўтлусты",em:"Курсіў",del:"Закрэслены",superscript:"Верхні індэкс",subscript:"Індэкс",unorderedList:"Звычайны спіс",orderedList:"Нумараваны спіс",insertImage:"Уставіць выяву",insertVideo:"Уставіць відэа",link:"Спасылка",createLink:"Уставіць спасылку",unlink:"Выдаліць спасылку",justifyLeft:"Па леваму боку",justifyCenter:"У цэнтры",justifyRight:"Па праваму боку",justifyFull:"Па шырыні",horizontalRule:"Гарызантальная лінія",removeformat:"Ачысціць фарматаванне",fullscreen:"На ўвесь экран",close:"Зачыніць",submit:"Уставіць",reset:"Скасаваць",required:"Абавязкова",description:"Апісанне",title:"Падказка",text:"Тэкст"};

@ -0,0 +1,57 @@
/* ===========================================================
* ca.js
* Catalan translation for Trumbowyg
* http://alex-d.github.com/Trumbowyg
* ===========================================================
* Author : Àlfons Sánchez (alsanan)
* Twitter : @alsanan
* Website : about.me/alsanan
* Github : https://github.com/alsanan
*/
jQuery.trumbowyg.langs.ca = {
viewHTML: 'Veure HTML',
formatting: 'Formatar',
p: 'Paragraf',
blockquote: 'Citació',
code: 'Codi',
header: 'Títol',
bold: 'Negreta',
italic: 'Itàlica',
strikethrough: 'Suprimir',
underline: 'Subratllat',
strong: 'Forta',
em: 'Èmfasi',
del: 'Apagar',
unorderedList: 'Lista desordenada',
orderedList: 'Lista ordenada',
insertImage: 'Inserir imatge',
insertVideo: 'Inserir vídeo',
link: 'Enllaç',
createLink: 'Crear un enllaç',
unlink: 'Eliminar enllaç',
justifyLeft: 'Alinear a esquerra',
justifyCenter: 'Centrar',
justifyRight: 'Alinear a dreta',
justifyFull: 'Justificar',
horizontalRule: 'Inserir separador horitzontal',
fullscreen: 'Pantalla completa',
close: 'Tancar',
submit: 'Enviar',