@@ -283,7 +283,7 @@ export function updateActiveElement(
283
283
void updateWordsInputPosition ( ) ;
284
284
}
285
285
if ( ! initial && Config . tapeMode !== "off" ) {
286
- scrollTape ( ) ;
286
+ void scrollTape ( ) ;
287
287
}
288
288
}
289
289
@@ -425,11 +425,10 @@ export function showWords(): void {
425
425
}
426
426
427
427
updateActiveElement ( undefined , true ) ;
428
+ updateWordWrapperClasses ( ) ;
428
429
setTimeout ( ( ) => {
429
430
void Caret . updatePosition ( ) ;
430
431
} , 125 ) ;
431
-
432
- updateWordWrapperClasses ( ) ;
433
432
}
434
433
435
434
export function appendEmptyWordElement ( ) : void {
@@ -575,7 +574,7 @@ export function updateWordsWrapperHeight(force = false): void {
575
574
576
575
function updateWordsMargin ( ) : void {
577
576
if ( Config . tapeMode !== "off" ) {
578
- scrollTape ( true ) ;
577
+ void scrollTape ( true ) ;
579
578
} else {
580
579
setTimeout ( ( ) => {
581
580
$ ( "#words" ) . css ( "margin-left" , "unset" ) ;
@@ -933,7 +932,7 @@ export async function updateActiveWordLetters(
933
932
"<div class='beforeNewline'></div><div class='newline'></div><div class='afterNewline'></div>"
934
933
) ;
935
934
if ( Config . tapeMode !== "off" ) {
936
- scrollTape ( ) ;
935
+ await scrollTape ( ) ;
937
936
}
938
937
}
939
938
@@ -964,15 +963,18 @@ function getNlCharWidthFromPreviousWord(
964
963
}
965
964
966
965
let allowWordRemoval = true ;
967
- export function scrollTape ( noRemove = false ) : void {
966
+ export async function scrollTape ( noRemove = false ) : Promise < void > {
968
967
if ( ActivePage . get ( ) !== "test" || resultVisible ) return ;
969
968
970
969
const waitForLineJumpAnimation = lineTransition && ! allowWordRemoval ;
971
970
if ( waitForLineJumpAnimation ) {
972
- setTimeout ( ( ) => scrollTape ( true ) , 50 ) ;
971
+ setTimeout ( ( ) => void scrollTape ( true ) , 50 ) ;
973
972
return ;
974
973
}
975
974
975
+ const currentLang = await JSONData . getCurrentLanguage ( Config . language ) ;
976
+ const isLanguageRTL = currentLang . rightToLeft ;
977
+
976
978
// index of the active word in the collection of .word elements
977
979
const wordElementIndex = TestState . activeWordIndex - activeWordElementOffset ;
978
980
const wordsWrapperWidth = (
@@ -1050,7 +1052,11 @@ export function scrollTape(noRemove = false): void {
1050
1052
const wordOuterWidth = $ ( child ) . outerWidth ( true ) ?? 0 ;
1051
1053
const forWordLeft = Math . floor ( child . offsetLeft ) ;
1052
1054
const forWordWidth = Math . floor ( child . offsetWidth ) ;
1053
- if ( ! noRemove && forWordLeft < 0 - forWordWidth ) {
1055
+ if (
1056
+ ! noRemove &&
1057
+ ( ( ! isLanguageRTL && forWordLeft < 0 - forWordWidth ) ||
1058
+ ( isLanguageRTL && forWordLeft > wordsWrapperWidth ) )
1059
+ ) {
1054
1060
toRemove . push ( child ) ;
1055
1061
widthRemoved += wordOuterWidth ;
1056
1062
wordsToRemoveCount ++ ;
@@ -1090,30 +1096,43 @@ export function scrollTape(noRemove = false): void {
1090
1096
parseFloat ( afterNewlineEl . style . marginLeft ) || 0 ;
1091
1097
afterNewlineEl . style . marginLeft = `${ currentLineIndent - width } px` ;
1092
1098
} ) ;
1099
+ if ( isLanguageRTL ) widthRemoved *= - 1 ;
1093
1100
const currentWordsMargin = parseFloat ( wordsEl . style . marginLeft ) || 0 ;
1094
1101
wordsEl . style . marginLeft = `${ currentWordsMargin + widthRemoved } px` ;
1095
1102
}
1096
1103
1097
1104
/* calculate current word width to add to #words margin */
1098
1105
let currentWordWidth = 0 ;
1099
- if ( Config . tapeMode === "letter" ) {
1100
- if ( TestInput . input . current . length > 0 ) {
1101
- const letters = activeWordEl . querySelectorAll ( "letter" ) ;
1102
- for ( let i = 0 ; i < TestInput . input . current . length ; i ++ ) {
1103
- const letter = letters [ i ] as HTMLElement ;
1104
- if (
1105
- ( Config . blindMode || Config . hideExtraLetters ) &&
1106
- letter . classList . contains ( "extra" )
1107
- ) {
1108
- continue ;
1109
- }
1110
- currentWordWidth += $ ( letter ) . outerWidth ( true ) ?? 0 ;
1106
+ const inputLength = TestInput . input . current . length ;
1107
+ if ( Config . tapeMode === "letter" && inputLength > 0 ) {
1108
+ const letters = activeWordEl . querySelectorAll ( "letter" ) ;
1109
+ let lastPositiveLetterWidth = 0 ;
1110
+ for ( let i = 0 ; i < inputLength ; i ++ ) {
1111
+ const letter = letters [ i ] as HTMLElement ;
1112
+ if (
1113
+ ( Config . blindMode || Config . hideExtraLetters ) &&
1114
+ letter . classList . contains ( "extra" )
1115
+ ) {
1116
+ continue ;
1111
1117
}
1118
+ const letterOuterWidth = $ ( letter ) . outerWidth ( true ) ?? 0 ;
1119
+ currentWordWidth += letterOuterWidth ;
1120
+ if ( letterOuterWidth > 0 ) lastPositiveLetterWidth = letterOuterWidth ;
1112
1121
}
1122
+ // if current letter has zero width move the tape to previous positive width letter
1123
+ if ( $ ( letters [ inputLength ] as Element ) . outerWidth ( true ) === 0 )
1124
+ currentWordWidth -= lastPositiveLetterWidth ;
1113
1125
}
1126
+
1114
1127
/* change to new #words & .afterNewline margins */
1115
- const tapeMargin = wordsWrapperWidth * ( Config . tapeMargin / 100 ) ;
1116
- const newMargin = tapeMargin - ( wordsWidthBeforeActive + currentWordWidth ) ;
1128
+ let newMargin = wordsWrapperWidth * ( Config . tapeMargin / 100 ) ;
1129
+ if ( isLanguageRTL )
1130
+ newMargin +=
1131
+ wordsWidthBeforeActive +
1132
+ currentWordWidth -
1133
+ wordsEl . offsetWidth +
1134
+ wordRightMargin ;
1135
+ else newMargin -= wordsWidthBeforeActive + currentWordWidth ;
1117
1136
1118
1137
const jqWords = $ ( wordsEl ) ;
1119
1138
if ( Config . smoothLineScroll ) {
@@ -1125,7 +1144,7 @@ export function scrollTape(noRemove = false): void {
1125
1144
duration : SlowTimer . get ( ) ? 0 : 125 ,
1126
1145
queue : "leftMargin" ,
1127
1146
complete : ( ) => {
1128
- if ( noRemove ) scrollTape ( ) ;
1147
+ if ( noRemove ) void scrollTape ( ) ;
1129
1148
} ,
1130
1149
}
1131
1150
) ;
@@ -1145,7 +1164,7 @@ export function scrollTape(noRemove = false): void {
1145
1164
afterNewlinesNewMargins . forEach ( ( margin , index ) => {
1146
1165
( afterNewLineEls [ index ] as HTMLElement ) . style . marginLeft = `${ margin } px` ;
1147
1166
} ) ;
1148
- if ( noRemove ) scrollTape ( ) ;
1167
+ if ( noRemove ) void scrollTape ( ) ;
1149
1168
}
1150
1169
}
1151
1170
0 commit comments