Skip to content

Commit ca27a47

Browse files
committed
Change speaking rate to number input
Increases the breadth of options, makes the rates more discrete and customizable, Fixes #733
1 parent 836aab2 commit ca27a47

1 file changed

Lines changed: 53 additions & 39 deletions

File tree

‎scripts/preference.js‎

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@
381381
if (options.attrs) {
382382
$.extend(fieldAttrs, options.attrs);
383383
}
384-
labelPosition = options.labelPosition || (options.type === 'select' ? 'before' : 'after');
384+
labelPosition = options.labelPosition || ((options.type === 'select' || options.type === 'number') ? 'before' : 'after');
385385
checkboxValue = (typeof options.value !== 'undefined') ? options.value : 'true';
386386

387387
$wrapper = $('<div>').addClass(wrapperClass + 'able-player-setting');
@@ -395,6 +395,12 @@
395395

396396
if (options.type === 'select') {
397397
$field = $('<select>', fieldAttrs);
398+
} else if (options.type === 'number') {
399+
fieldAttrs.type = 'number';
400+
if (typeof options.value !== 'undefined') {
401+
fieldAttrs.value = options.value;
402+
}
403+
$field = $('<input>', fieldAttrs);
398404
} else {
399405
fieldAttrs.type = options.type || 'checkbox';
400406
fieldAttrs.value = checkboxValue;
@@ -545,12 +551,19 @@
545551
thisId = this.mediaId + '_' + thisPref;
546552
$thisDiv = $('<div>').addClass(thisClass + ' able-player-setting');
547553
if (form === 'captions' ) {
554+
let isCaptionRateField = (thisPref === 'prefCaptionsRate');
548555
let fieldObj = this.createField({
549-
wrapperClass: thisClass + ' able-prefs-select',
556+
wrapperClass: thisClass + ' ' + (isCaptionRateField ? 'able-prefs-number' : 'able-prefs-select'),
550557
name: thisPref,
551558
id: thisId,
552559
label: available[i]['label'],
553-
type: 'select'
560+
type: isCaptionRateField ? 'number' : 'select',
561+
value: isCaptionRateField ? this[thisPref] : undefined,
562+
attrs: isCaptionRateField ? {
563+
min: 0.5,
564+
max: 3.0,
565+
step: 0.1
566+
} : undefined
554567
});
555568
$thisDiv = fieldObj.wrapper;
556569
$thisLabel = fieldObj.label;
@@ -563,9 +576,16 @@
563576
thisObj.stylizeCaptions(thisObj.$sampleCapsDiv,changedPref);
564577
});
565578
}
566-
captionsOptions = this.getCaptionsOptions(thisPref);
567-
if ( ! ( thisPref === 'prefCaptionsVoice' && ! this.descVoices.length ) ) {
568-
$thisDiv.append($thisLabel,$thisField);
579+
if (isCaptionRateField) {
580+
if (this.synth) {
581+
$thisField.on('change',function() {
582+
let captionSample = thisObj.translate( 'sampleCaptionText', 'Sample caption text' );
583+
thisObj.announceText('captionSample',captionSample);
584+
});
585+
}
586+
captionsOptions = [];
587+
} else {
588+
captionsOptions = this.getCaptionsOptions(thisPref);
569589
}
570590
for (j=0; j < captionsOptions.length; j++) {
571591
if (thisPref === 'prefCaptionsPosition') {
@@ -662,18 +682,27 @@
662682
$thisLabel = fieldObj.label;
663683
$thisField = fieldObj.field;
664684
} else if (this.synth) {
685+
let isDescRateField = (thisPref === 'prefDescRate');
665686
// Only show these options if browser supports speech synthesis
666687
let fieldObj = this.createField({
667-
wrapperClass: thisClass + ' able-prefs-select',
688+
wrapperClass: thisClass + ' ' + (isDescRateField ? 'able-prefs-number' : 'able-prefs-select'),
668689
name: thisPref,
669690
id: thisId,
670691
label: available[i]['label'],
671-
type: 'select'
692+
type: isDescRateField ? 'number' : 'select',
693+
value: isDescRateField ? this[thisPref] : undefined,
694+
attrs: isDescRateField ? {
695+
min: 0.5,
696+
max: 3.0,
697+
step: 0.1
698+
} : undefined
672699
});
673700
$thisDiv = fieldObj.wrapper;
674701
$thisLabel = fieldObj.label;
675702
$thisField = fieldObj.field;
676-
if ( thisPref === 'prefDescVoice' && this.descVoices.length) {
703+
if (isDescRateField) {
704+
// Number field has no options to populate.
705+
} else if ( thisPref === 'prefDescVoice' && this.descVoices.length) {
677706
prefDescVoice = this.getPrefVoice();
678707
for (j=0; j < this.descVoices.length; j++) {
679708
optionValue = this.descVoices[j].name;
@@ -708,8 +737,6 @@
708737
// 2.5 - fleet
709738
// 3 - fast! (some voices don't get any faster than this
710739

711-
// Note: if these values are modified, must also modfiy them
712-
// in makePrefsValueReadable()
713740
options = [0.7,0.8,0.9,1,1.1,1.2,1.5,2,2.5,3];
714741
} else if (thisPref == 'prefDescVolume') { // 0 (mute) to 1
715742
options = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1];
@@ -776,7 +803,7 @@
776803
});
777804
}
778805
}
779-
if (thisPref === 'prefDescVoice' && !this.descVoices.length) {
806+
if ((thisPref === 'prefDescVoice' || thisPref === 'prefCaptionsVoice') && !this.descVoices.length) {
780807
// No voices are available (e.g., in Safari 15.4 on Mac OS)
781808
} else {
782809
$fieldset.append($thisDiv);
@@ -1023,32 +1050,6 @@
10231050
} else if (value === 2) {
10241051
return this.translate( 'prefDescPitch5', 'Very high' );
10251052
}
1026-
} else if (pref === 'prefDescRate' || pref === 'prefCaptionsRate' ) {
1027-
// default in the API is 0.1 to 10, where 1 is normal speaking voice
1028-
// our custom range offers several rates close to 1
1029-
// plus a couple of crazy fast ones for sport
1030-
// Our more readable options (1-10) or mapped here to API values
1031-
if (value === 0.7) {
1032-
return 1;
1033-
} else if (value === 0.8) {
1034-
return 2;
1035-
} else if (value === 0.9) {
1036-
return 3;
1037-
} else if (value === 1) {
1038-
return 4;
1039-
} else if (value === 1.1) {
1040-
return 5;
1041-
} else if (value === 1.2) {
1042-
return 6;
1043-
} else if (value === 1.5) {
1044-
return 7;
1045-
} else if (value === 2) {
1046-
return 8;
1047-
} else if (value === 2.5) {
1048-
return 9;
1049-
} else if (value === 3) {
1050-
return 10;
1051-
}
10521053
} else if (pref === 'prefDescVolume' || pref === 'prefCaptionsVolume' ) {
10531054
// values range from 0.1 to 1.0
10541055
return value * 100 + '%';
@@ -1070,7 +1071,9 @@
10701071
available = this.getAvailablePreferences();
10711072
for (i=0; i<available.length; i++) {
10721073
prefName = available[i]['name'];
1073-
if ((prefName.indexOf('Captions') !== -1) && (prefName !== 'prefCaptions')) {
1074+
if (prefName === 'prefCaptionsRate' || prefName === 'prefDescRate') {
1075+
$('input[name="' + prefName + '"]').val(preferences.preferences[prefName]);
1076+
} else if ((prefName.indexOf('Captions') !== -1) && (prefName !== 'prefCaptions')) {
10741077
// this is a caption-related select box
10751078
$('select[name="' + prefName + '"]').val(preferences.preferences[prefName]);
10761079
} else { // all others are checkboxes
@@ -1133,6 +1136,17 @@
11331136
preferences.preferences['prefDescMethod'] = this.prefDescMethod;
11341137
numChanges++;
11351138
}
1139+
} else if (prefName === 'prefCaptionsRate' || prefName === 'prefDescRate') {
1140+
newValue = parseFloat($('input[id="' + prefId + '"]').val());
1141+
if (isNaN(newValue)) {
1142+
newValue = this[prefName] || 1;
1143+
}
1144+
newValue = Math.min(3.0, Math.max(0.5, newValue));
1145+
if (preferences.preferences[prefName] !== newValue) {
1146+
preferences.preferences[prefName] = newValue;
1147+
this[prefName] = newValue;
1148+
numChanges++;
1149+
}
11361150
} else if ((prefName.indexOf('Captions') !== -1) && (prefName !== 'prefCaptions')) {
11371151
// this is one of the caption-related select fields
11381152
newValue = $('select[id="' + prefId + '"]').val();

0 commit comments

Comments
 (0)