1
- import { makeid , log } from "../monks-enhanced-journal.js" ;
1
+ import { MonksEnhancedJournal , makeid , log , i18n } from "../monks-enhanced-journal.js" ;
2
2
import { SlideConfig } from "../apps/slideconfig.js"
3
3
import { DCConfig } from "../apps/dc-config.js"
4
4
import { TrapConfig } from "../apps/trap-config.js"
@@ -78,22 +78,28 @@ export class SubSheet {
78
78
else if ( ! ctrl . conditional )
79
79
continue ;
80
80
}
81
+ let div = '' ;
81
82
switch ( ctrl . type || 'button' ) {
82
83
case 'button' :
83
- html . append (
84
- $ ( '<div>' )
84
+ div = $ ( '<div>' )
85
85
. addClass ( 'nav-button ' + ctrl . id )
86
86
. attr ( 'title' , ctrl . text )
87
87
. append ( $ ( '<i>' ) . addClass ( 'fas ' + ctrl . icon ) )
88
- . on ( 'click' , $ . proxy ( ctrl . callback , this . object . sheet ) ) ) ;
88
+ . on ( 'click' , $ . proxy ( ctrl . callback , this . object . sheet ) ) ;
89
89
break ;
90
90
case 'input' :
91
- html . append ( $ ( '<input>' ) . addClass ( 'nav-input ' + ctrl . id ) . attr ( mergeObject ( { 'type' : 'text' , 'autocomplete' : 'off' , 'placeholder' : ctrl . text } , ( ctrl . attributes || { } ) ) ) ) ;
91
+ div = $ ( '<input>' ) . addClass ( 'nav-input ' + ctrl . id ) . attr ( mergeObject ( { 'type' : 'text' , 'autocomplete' : 'off' , 'placeholder' : ctrl . text } , ( ctrl . attributes || { } ) ) ) ;
92
92
break ;
93
93
case 'text' :
94
- html . append ( $ ( '<div>' ) . addClass ( 'nav-text ' + ctrl . id ) . html ( ctrl . text ) ) ;
94
+ div = $ ( '<div>' ) . addClass ( 'nav-text ' + ctrl . id ) . html ( ctrl . text ) ;
95
95
break ;
96
96
}
97
+
98
+ if ( div != '' ) {
99
+ if ( ctrl . visible === false )
100
+ div . hide ( ) ;
101
+ html . append ( div ) ;
102
+ }
97
103
//<div class="nav-button search" title="Search"><i class="fas fa-search"></i><input class="search" type="text" name="search-entry" autocomplete="off"></div>
98
104
}
99
105
}
@@ -110,17 +116,24 @@ export class SubSheet {
110
116
if ( $ ( 'div.tox-tinymce' , this . element ) . length > 0 ) {
111
117
//close the editor
112
118
const name = $ ( '.editor-content' , this . element ) . attr ( "data-edit" ) ;
113
- this . saveEditor ( name ) ;
114
- /*
119
+ //this.saveEditor(name);
115
120
const editor = this . editors [ name ] ;
116
121
if ( ! editor || ! editor . mce ) throw new Error ( `${ name } is not an active editor name!` ) ;
117
122
editor . active = false ;
118
- editor.changed = false;
119
123
const mce = editor . mce ;
124
+
125
+ const submit = this . _onSubmit ( new Event ( "mcesave" ) ) ;
126
+
120
127
mce . remove ( ) ;
121
- mce.destroy();
122
- editor.mce = null;
123
- $('.sheet-body', this.element).removeClass('editing');*/
128
+ if ( editor . hasButton ) editor . button . style . display = "block" ;
129
+
130
+ return submit . then ( ( ) => {
131
+ mce . destroy ( ) ;
132
+ editor . mce = null ;
133
+ this . render ( true , { data : { content : editor . initial } } ) ; //need to send this so that the render looks to the subsheet instead
134
+ editor . changed = false ;
135
+ $ ( '.sheet-body' , this . element ) . removeClass ( 'editing' ) ;
136
+ } ) ;
124
137
} else {
125
138
$ ( '.sheet-body .editor-edit' , this . element ) . click ( ) ;
126
139
$ ( '.sheet-body' , this . element ) . addClass ( 'editing' ) ;
@@ -444,6 +457,7 @@ export class SlideshowSubSheet extends SubSheet {
444
457
data = super . getData ( data ) ;
445
458
data . showasOptions = { canvas : "Canvas" , fullscreen : "Full Screen" , window : "Window" } ;
446
459
460
+ let idx = 0 ;
447
461
for ( let slide of data . content . slides ) {
448
462
if ( slide . background ?. color == '' )
449
463
slide . background = `background-image:url(\'${ slide . img } \');` ;
@@ -455,16 +469,43 @@ export class SlideshowSubSheet extends SubSheet {
455
469
slide . topText = ( slide . text ?. valign == 'top' ? slide . text ?. content : '' ) ;
456
470
slide . middleText = ( slide . text ?. valign == 'middle' ? slide . text ?. content : '' ) ;
457
471
slide . bottomText = ( slide . text ?. valign == 'bottom' ? slide . text ?. content : '' ) ;
472
+
473
+ slide . active = ( idx == this . object . data . content . slideAt ) ;
474
+
475
+ idx ++ ;
476
+ }
477
+
478
+ if ( this . object . data . content . playing ) {
479
+ data . slideshowing = this . object . data . content . slides [ this . object . data . content . slideAt ] ;
480
+
481
+ if ( data . slideshowing . background ?. color == '' )
482
+ data . slideshowing . background = `background-image:url(\'${ data . slideshowing . img } \');` ;
483
+ else
484
+ data . slideshowing . background = `background-color:${ data . slideshowing . background . color } ` ;
485
+
486
+ data . slideshowing . textbackground = hexToRGBAString ( colorStringToHex ( data . slideshowing . text ?. background || '#000000' ) , 0.5 ) ;
487
+
488
+ data . slideshowing . topText = ( data . slideshowing . text ?. valign == 'top' ? data . slideshowing . text ?. content : '' ) ;
489
+ data . slideshowing . middleText = ( data . slideshowing . text ?. valign == 'middle' ? data . slideshowing . text ?. content : '' ) ;
490
+ data . slideshowing . bottomText = ( data . slideshowing . text ?. valign == 'bottom' ? data . slideshowing . text ?. content : '' ) ;
491
+
492
+ if ( data . slideshowing . transition ?. duration > 0 ) {
493
+ let time = data . slideshowing . transition . duration * 1000 ;
494
+ let timeRemaining = time - ( ( new Date ( ) ) . getTime ( ) - data . slideshowing . transition . startTime ) ;
495
+ data . slideshowing . durprog = ( timeRemaining / time ) * 100 ;
496
+ } else
497
+ data . slideshowing . durlabel = i18n ( "MonksEnhancedJournal.ClickForNext" ) ;
458
498
}
459
499
460
500
return data ;
461
501
}
462
502
463
503
get _entityControls ( ) {
464
504
return [
465
- { id : 'add' , text : 'Add Slide' , icon : 'fa-plus' , conditional : game . user . isGM , callback : function ( ) { this . addSlide ( ) ; } } ,
466
- { id : 'clear' , text : 'Clear All' , icon : 'fa-dumpster' , conditional : game . user . isGM , callback : function ( ) { } } ,
467
- { id : 'play' , text : 'Play' , icon : 'fa-play' , conditional : game . user . isGM , callback : function ( ) { } }
505
+ { id : 'add' , text : 'Add Slide' , icon : 'fa-plus' , conditional : game . user . isGM , callback : this . addSlide } ,
506
+ { id : 'clear' , text : 'Clear All' , icon : 'fa-dumpster' , conditional : game . user . isGM , callback : this . deleteAll } ,
507
+ { id : 'play' , text : 'Play' , icon : 'fa-play' , conditional : game . user . isGM , visible : ! this . object . data . content . playing , callback : this . playSlideshow } ,
508
+ { id : 'stop' , text : 'Play' , icon : 'fa-stop' , conditional : game . user . isGM , visible : this . object . data . content . playing , callback : this . stopSlideshow }
468
509
] ;
469
510
}
470
511
@@ -473,18 +514,26 @@ export class SlideshowSubSheet extends SubSheet {
473
514
474
515
const slideshowOptions = this . _getSlideshowContextOptions ( ) ;
475
516
Hooks . call ( `getMonksEnhancedJournalSlideshowContext` , html , slideshowOptions ) ;
476
- if ( slideshowOptions ) new ContextMenu ( $ ( html ) , ".slide" , slideshowOptions ) ;
517
+ if ( slideshowOptions ) new ContextMenu ( $ ( html ) , ".slideshow-body .slide" , slideshowOptions ) ;
518
+
519
+ html . find ( '.slideshow-body .slide' ) . click ( this . activateSlide . bind ( this ) ) ;
520
+ html . find ( '.slide-showing' ) . click ( this . advanceSlide . bind ( this , 1 ) ) . contextmenu ( this . advanceSlide . bind ( this , - 1 ) ) ;
477
521
}
478
522
479
523
addSlide ( data = { } , options = { showdialog : true } ) {
480
524
if ( this . object . data . content . slides == undefined )
481
525
this . object . data . content . slides = [ ] ;
482
526
483
- let slide = mergeObject ( { sizing : 'contain' , background : { color : '' } } , data ) ;
527
+ let slide = mergeObject ( {
528
+ sizing : 'contain' ,
529
+ background : { color : '' } ,
530
+ text : { color : '#FFFFFF' , background : '#000000' , align : 'center' , valign : 'middle' } ,
531
+ transition : { duration : 5 , effect : 'fade' }
532
+ } , data ) ;
484
533
slide . id = makeid ( ) ;
485
534
this . object . data . content . slides . push ( slide ) ;
486
535
487
- $ ( '<div>' ) . addClass ( " slide" ) . attr ( 'data-slide-id' , slide . id ) . append ( $ ( '<img>' ) . attr ( 'src' , slide . img ) ) . appendTo ( $ ( '.slideshow-body' , this . element ) ) ;
536
+ MonksEnhancedJournal . createSlide ( slide , $ ( '.slideshow-body' , this . element ) ) ;
488
537
489
538
if ( options . showdialog )
490
539
new SlideConfig ( slide ) . render ( true ) ;
@@ -514,6 +563,140 @@ export class SlideshowSubSheet extends SubSheet {
514
563
new SlideConfig ( slide , options ) . render ( true ) ;
515
564
}
516
565
566
+ activateSlide ( event ) {
567
+ if ( this . object . data . content . playing ) {
568
+ let idx = $ ( event . currentTarget ) . index ( ) ;
569
+ this . playSlide ( idx ) ;
570
+ }
571
+ }
572
+
573
+ playSlideshow ( refresh = true ) {
574
+ this . object . data . content . playing = true ;
575
+ this . object . data . content . slideAt = 0 ;
576
+ this . object . data . content . sound = undefined ;
577
+
578
+ $ ( '.slide-showing .duration' , this . element ) . show ( ) ;
579
+ $ ( '.slideshow-container' , this . element ) . toggleClass ( 'playing' , this . object . data . content . playing ) ;
580
+ $ ( '.navigation .play' , this . element ) . toggle ( ! this . object . data . content . playing ) ;
581
+ $ ( '.navigation .stop' , this . element ) . toggle ( this . object . data . content . playing ) ;
582
+
583
+ if ( this . object . data . content . audiofile != undefined && this . object . data . content . audiofile != '' )
584
+ this . object . data . content . sound = AudioHelper . play ( { src : this . object . data . content . audiofile } , true ) ;
585
+
586
+ //inform players
587
+ game . socket . emit (
588
+ MonksEnhancedJournal . SOCKET ,
589
+ {
590
+ action : 'playSlideshow' ,
591
+ args : { id : this . object . id , idx : 0 }
592
+ }
593
+ ) ;
594
+
595
+ if ( this . object . data . content . playing ) {
596
+ if ( refresh )
597
+ $ ( '.slide-showing .slide' , this . element ) . remove ( ) ;
598
+ this . subsheet . playSlide ( 0 ) ;
599
+ }
600
+ }
601
+
602
+ stopSlideshow ( ) {
603
+ this . object . data . content . playing = false ;
604
+ this . object . data . content . slideAt = 0 ;
605
+ $ ( '.slide-showing .slide' , this . element ) . remove ( ) ;
606
+ $ ( '.slide-showing .duration' , this . element ) . hide ( ) ;
607
+ $ ( '.slideshow-container' , this . object . sheet . element ) . toggleClass ( 'playing' , this . object . data . content . playing ) ;
608
+ $ ( '.navigation .play' , this . object . sheet . element ) . toggle ( ! this . object . data . content . playing ) ;
609
+ $ ( '.navigation .stop' , this . object . sheet . element ) . toggle ( this . object . data . content . playing ) ;
610
+
611
+ if ( this . object . data . content ?. sound ?. _src != undefined ) {
612
+ game . socket . emit ( "stopAudio" , { src : this . object . data . content . audiofile } ) ;
613
+ this . object . data . content . sound . stop ( ) ;
614
+ this . object . data . content . sound = undefined ;
615
+ }
616
+
617
+ //inform players
618
+ game . socket . emit (
619
+ MonksEnhancedJournal . SOCKET ,
620
+ {
621
+ action : 'stopSlideshow' ,
622
+ args : { }
623
+ }
624
+ ) ;
625
+ }
626
+
627
+ playSlide ( idx , animate = true ) {
628
+ let slide = this . object . data . content . slides [ idx ] ;
629
+
630
+ //remove any that are still on the way out
631
+ $ ( '.slide-showing .slide.out' , this . element ) . remove ( ) ;
632
+
633
+ //remove any old slides
634
+ let oldSlide = $ ( '.slide-showing .slide' , this . element ) ;
635
+ oldSlide . addClass ( 'out' ) . animate ( { opacity : 0 } , 1000 , 'linear' , function ( ) { $ ( this ) . remove ( ) } ) ;
636
+
637
+ //bring in the new slide
638
+ let newSlide = MonksEnhancedJournal . createSlide ( slide , $ ( '.slide-showing' , this . element ) ) ;
639
+ newSlide . css ( { opacity : 0 } ) . animate ( { opacity : 1 } , 1000 , 'linear' ) ;
640
+
641
+ /*
642
+ let background = '';
643
+
644
+ this.object.data.content.slideAt = idx;
645
+
646
+ if (slide.background?.color == '')
647
+ background = `background-image:url(\'${slide.img}\');`;
648
+ else
649
+ background = `background-color:${slide.background?.color}`;
650
+
651
+ let textBackground = hexToRGBAString(colorStringToHex(slide.text?.background || '#000000'), 0.5);
652
+
653
+ let slideShowing = $('.slide-showing', this.element);
654
+ $('.slide-background > div', slideShowing).attr({ style: background });
655
+ $('.slide > img', slideShowing).attr('src', slide.img).css({ 'object-fit': (slide.sizing || 'contain') });
656
+ $('.slide-text > div', slideShowing).css({ 'text-align': slide.text?.align, color: slide.text?.color });
657
+ $('.text-upper > div', slideShowing).css({ 'background-color': textBackground }).html(slide.text?.valign == 'top' ? slide.text?.content : '');
658
+ $('.text-middle > div', slideShowing).css({ 'background-color': textBackground }).html(slide.text?.valign == 'middle' ? slide.text?.content : '');
659
+ $('.text-lower > div', slideShowing).css({ 'background-color': textBackground }).html(slide.text?.valign == 'bottom' ? slide.text?.content : '');
660
+ */
661
+
662
+ $ ( `.slideshow-body .slide:eq(${ idx } )` , this . element ) . addClass ( 'active' ) . siblings ( ) . removeClass ( 'active' ) ;
663
+ $ ( '.slideshow-body' , this . element ) . scrollLeft ( ( idx * 116 ) ) ;
664
+ $ ( '.slide-showing .duration' , this . element ) . empty ( ) ;
665
+
666
+ window . clearTimeout ( slide . transition . timer ) ;
667
+
668
+ if ( slide . transition ?. duration > 0 ) {
669
+ //set up the transition
670
+ let time = slide . transition . duration * 1000 ;
671
+ slide . transition . startTime = ( new Date ( ) ) . getTime ( ) ;
672
+ slide . transition . timer = window . setTimeout ( this . advanceSlide . bind ( this , 1 ) , time ) ;
673
+ $ ( '.slide-showing .duration' , this . element ) . append ( $ ( '<div>' ) . addClass ( 'duration-bar' ) . css ( { width : '0' } ) . show ( ) . animate ( { width : '100%' } , time , 'linear' ) ) ;
674
+ } else {
675
+ $ ( '.slide-showing .duration' , this . element ) . append ( $ ( '<div>' ) . addClass ( 'duration-label' ) . html ( i18n ( "MonksEnhancedJournal.ClickForNext" ) ) ) ;
676
+ }
677
+
678
+ game . socket . emit (
679
+ MonksEnhancedJournal . SOCKET ,
680
+ {
681
+ action : 'playSlide' ,
682
+ args : {
683
+ id : this . object . id ,
684
+ idx : idx
685
+ }
686
+ }
687
+ ) ;
688
+ }
689
+
690
+ advanceSlide ( dir , event ) {
691
+ this . object . data . content . slideAt = this . object . data . content . slideAt + dir ;
692
+ if ( this . object . data . content . slideAt < 0 )
693
+ this . object . data . content . slideAt = 0 ;
694
+ else if ( this . object . data . content . slideAt >= this . object . data . content . slides . length )
695
+ this . stopSlideshow ( ) ;
696
+ else
697
+ this . playSlide ( this . object . data . content . slideAt , dir > 0 ) ;
698
+ }
699
+
517
700
_getSlideshowContextOptions ( ) {
518
701
return [
519
702
{
0 commit comments