j1-template 2023.9.1 → 2023.9.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -4595,7 +4595,7 @@ module.exports = function parseContent(options) {
4595
4595
  var chunkCounter = 0;
4596
4596
  var userStoppedSpeaking = false;
4597
4597
  var chunkSpoken = false;
4598
- var scrollOnce = true;
4598
+ var lastScrollPosition = false;
4599
4599
  var rateUserDefault;
4600
4600
  var pitchUserDefault;
4601
4601
  var volumeUserDefault;
@@ -4652,18 +4652,19 @@ module.exports = function parseContent(options) {
4652
4652
  'de-DE': 'Microsoft Katja Online (Natural) - German (Germany)'
4653
4653
  };
4654
4654
 
4655
- // -------------------------------------------------------------------------
4655
+ // ---------------------------------------------------------------------------
4656
4656
  // Internal functions
4657
- // -------------------------------------------------------------------------
4657
+ // ---------------------------------------------------------------------------
4658
4658
 
4659
4659
  // scan a page to get correct positions for scrolling and highlightning
4660
4660
  //
4661
4661
  function scanPage(options) {
4662
4662
  // see: https://stackoverflow.com/questions/3163615/how-to-scroll-an-html-page-to-a-given-anchor
4663
4663
  // see: https://stackoverflow.com/questions/22154129/how-to-make-setinterval-behave-more-in-sync-or-how-to-use-settimeout-instea
4664
- var line = 0;
4664
+ var line = options.startLine;
4665
4665
  var lines;
4666
4666
  function scanSection(counter) {
4667
+ // jadams, 2023-09-28:
4667
4668
  // because of the current translation in progress, the length
4668
4669
  // of a page may change to higher or lower values (asian)
4669
4670
  //
@@ -4683,11 +4684,20 @@ module.exports = function parseContent(options) {
4683
4684
  setTimeout(function () {
4684
4685
  scanFinished = true;
4685
4686
  $('#content').attr("style", "opacity: 1");
4686
- $(window).scrollTop(0);
4687
+
4688
+ // jadams, 2023-09-28:
4689
+ // do NOT scroll on stop if paused
4690
+ // disabled
4691
+ // -------------------------------------------------------------------
4692
+ // if (!myOptions.isPaused) {
4693
+ // window.scrollTo({top: 0, behavior: 'smooth'});
4694
+ // }
4687
4695
  }, pageScanCycle);
4688
4696
  }
4689
4697
  }
4690
- scanSection(0);
4698
+ scanSection({
4699
+ startLine: 0
4700
+ });
4691
4701
  } // END scanPage
4692
4702
 
4693
4703
  // merge (configuration) objects
@@ -4815,26 +4825,31 @@ module.exports = function parseContent(options) {
4815
4825
  var voiceLanguageDefault = voiceLanguageFirefoxDefault[currentLanguage];
4816
4826
  }
4817
4827
 
4818
- // -------------------------------------------------------------------------
4828
+ // ---------------------------------------------------------------------------
4819
4829
  // Public functions (methods)
4820
- // -------------------------------------------------------------------------
4830
+ // ---------------------------------------------------------------------------
4821
4831
  //
4822
4832
  var methods = {
4823
4833
  // main speak2me method.
4824
4834
  //
4825
4835
  speak: function (options) {
4826
- var opts = $.extend({}, $.fn.speak2me.defaults, options);
4827
4836
  var toSpeak = '';
4828
4837
  var voiceTags = new Array();
4829
4838
  var _this = this;
4830
4839
  var obj, processed, finished;
4831
4840
  var ignoreTags;
4832
4841
  scanFinished = false;
4833
- myOptions = extend(defaultOptions, customOptions || {});
4842
+ myOptions = extend(options, defaultOptions, customOptions || {});
4834
4843
 
4835
4844
  // scan page to find correct positions for scrolling and highlightning
4836
4845
  //
4837
- scanPage();
4846
+ if (!myOptions.isPaused) {
4847
+ scanPage({
4848
+ startLine: 0
4849
+ });
4850
+ } else {
4851
+ scanFinished = true;
4852
+ }
4838
4853
 
4839
4854
  // Default values
4840
4855
  //
@@ -4847,19 +4862,16 @@ module.exports = function parseContent(options) {
4847
4862
  voiceTags['img'] = new voiceTag('Start of an embedded image with the description,', ', ');
4848
4863
  voiceTags['table'] = new voiceTag('Start of an embedded table,', 'This element ist not spoken.');
4849
4864
  voiceTags['card-header'] = new voiceTag('', '');
4850
- voiceTags['doc-example'] = new voiceTag('Start of an embedded example element,', 'This element ist not spoken.');
4851
- voiceTags['admonitionblock'] = new voiceTag('Start of an attention element of type, ', ':');
4852
- voiceTags['listingblock'] = new voiceTag('Start of an embedded structured text block,', 'This element ist not spoken.');
4853
- voiceTags['carousel'] = new voiceTag('Start of an embedded carousel element,', 'This element ist not spoken.');
4854
- voiceTags['slider'] = new voiceTag('Start of an embedded slider element,', 'This element ist not spoken.');
4855
- voiceTags['masonry'] = new voiceTag('Start of an embedded masonry element,', 'This element ist not spoken.');
4856
- voiceTags['lightbox'] = new voiceTag('Start of an embedded lightbox element,', 'This element ist not spoken.');
4857
- voiceTags['gallery'] = new voiceTag('Start of an embedded gallery element,', 'This element ist not spoken.');
4865
+ voiceTags['.doc-example'] = new voiceTag('Start of an embedded example element,', 'This element ist not spoken.');
4866
+ voiceTags['.admonitionblock'] = new voiceTag('Start of an attention element of type, ', ':');
4867
+ voiceTags['.listingblock'] = new voiceTag('Start of an embedded structured text block,', 'This element ist not spoken.');
4868
+ voiceTags['.slider'] = new voiceTag('Start of an embedded slider element,', 'This element ist not spoken.');
4869
+ voiceTags['.masonry'] = new voiceTag('Start of an embedded masonry element,', 'This element ist not spoken.');
4870
+ voiceTags['.lightbox-block'] = new voiceTag('Start of an embedded lightbox element,', 'This element ist not spoken.');
4871
+ voiceTags['.gallery'] = new voiceTag('Start of an embedded gallery element,', 'This element ist not spoken.');
4858
4872
  voiceTags['figure'] = new voiceTag('Start of an embedded figure with the caption,', '');
4859
4873
  voiceTags['blockquote'] = new voiceTag('Blockquote start.', 'Blockquote end.');
4860
4874
  voiceTags['quoteblock'] = new voiceTag('Start of an embedded quote block element,', 'Quote block element end.');
4861
-
4862
- // ignoreTags = ['masonry', 'carousel', 'slider', 'pre','audio','button','canvas','code','del','dialog','embed','form','head','iframe','meter','nav','noscript','object','s','script','select','style','textarea','video'];
4863
4875
  ignoreTags = ['audio', 'button', 'canvas', 'code', 'del', 'pre', 'dialog', 'embed', 'form', 'head', 'iframe', 'meter', 'nav', 'noscript', 'object', 's', 'script', 'select', 'style', 'textarea', 'video'];
4864
4876
 
4865
4877
  // TODO: NOT working for multiple 'tab' windows
@@ -5124,6 +5136,7 @@ module.exports = function parseContent(options) {
5124
5136
  if (speaker.offsetTop >= speaker.previousScrollPosition) {
5125
5137
  speaker.previousScrollPosition = speaker.offsetTop;
5126
5138
  }
5139
+ lastScrollPosition = speaker.offsetTop - scrollBlockOffset;
5127
5140
  }
5128
5141
 
5129
5142
  // remove highlightning for the paragraph already spoken
@@ -5137,6 +5150,7 @@ module.exports = function parseContent(options) {
5137
5150
 
5138
5151
  // loop to prepare ALL chunks to speak or STOP the voice output
5139
5152
  //
5153
+ var wasRunOnce = false;
5140
5154
  var speechMonitor = setInterval(function () {
5141
5155
  // check if all chunks (text) are spoken
5142
5156
  //
@@ -5145,13 +5159,24 @@ module.exports = function parseContent(options) {
5145
5159
  userStoppedSpeaking = false;
5146
5160
  chunkSpoken = false;
5147
5161
  speaker.$paragraph !== undefined && speaker.$paragraph.removeClass('speak-highlighted');
5148
- window.scrollTo({
5149
- top: 0,
5150
- behavior: 'smooth'
5151
- });
5162
+
5163
+ // jadams, 2023-09-28:
5164
+ // do NOT scroll on stop if paused
5165
+ // disabled
5166
+ // -----------------------------------------------------------------
5167
+ // if (!myOptions.isPaused) {
5168
+ // window.scrollTo({top: 0, behavior: 'smooth'});
5169
+ // }
5170
+
5171
+ // remove speak indication;
5152
5172
  $('.mdib-speaker').removeClass('mdib-spin');
5153
5173
  clearInterval(speechMonitor);
5154
5174
  } else {
5175
+ if (!wasRunOnce && myOptions.isPaused) {
5176
+ chunkCounter = myOptions.lastChunk;
5177
+ wasRunOnce = true;
5178
+ }
5179
+
5155
5180
  // prepare speaker data and start the voice
5156
5181
  //
5157
5182
  speaker.text = chunks[chunkCounter].text;
@@ -5315,22 +5340,20 @@ module.exports = function parseContent(options) {
5315
5340
  copy = anchor[0].innerText;
5316
5341
  prepend = voiceTags['a'].prepend;
5317
5342
  appended = voiceTags['a'].append;
5318
-
5319
- // jQuery('<div>' + prepend + copy + '</div>').insertBefore(this);
5320
5343
  jQuery('<div>' + copy + '</div>').insertBefore(this);
5321
5344
  jQuery('<div>' + appended + '</div>').insertBefore(this);
5322
5345
  jQuery(this).remove();
5323
5346
  });
5324
5347
 
5325
- // Search for admonitionblock elements and extract the type and
5348
+ // Search for admonition block elements and extract the type and
5326
5349
  // content. Insert type and content and then remove the DOM object.
5327
5350
  //
5328
- jQuery(clone).find('.admonitionblock').addBack('admonitionblock').each(function () {
5351
+ jQuery(clone).find('.admonitionblock').addBack('.admonitionblock').each(function () {
5329
5352
  content_type = this.classList[1];
5330
5353
  content_element = jQuery(this).find('.content');
5331
5354
  content = content_element[0].innerText;
5332
- prepend = voiceTags['admonitionblock'].prepend + content_type + '. ';
5333
- appended = voiceTags['admonitionblock'].append;
5355
+ prepend = voiceTags['.admonitionblock'].prepend + content_type + '. ';
5356
+ appended = voiceTags['.admonitionblock'].append;
5334
5357
  if (content !== undefined && content != '') {
5335
5358
  jQuery('<div>' + prepend + ' ' + content + '</div>').insertBefore(this);
5336
5359
  jQuery('<div>' + appended + '</div>').insertBefore(this);
@@ -5353,7 +5376,7 @@ module.exports = function parseContent(options) {
5353
5376
  jQuery(this).remove();
5354
5377
  });
5355
5378
 
5356
- // Search for <table>, check for <caption>, insert text
5379
+ // Search for <table> tags, check for <caption>, insert text
5357
5380
  // if exists and then remove the DOM object.
5358
5381
  //
5359
5382
  jQuery(clone).find('table').addBack('table').each(function () {
@@ -5385,27 +5408,27 @@ module.exports = function parseContent(options) {
5385
5408
 
5386
5409
  // Search for doc-example elements and then remove the DOM object.
5387
5410
  //
5388
- jQuery(clone).find('.doc-example').addBack('doc-example').each(function () {
5389
- prepend = voiceTags['doc-example'].prepend;
5390
- appended = voiceTags['doc-example'].append;
5411
+ jQuery(clone).find('.doc-example').addBack('.doc-example').each(function () {
5412
+ prepend = voiceTags['.doc-example'].prepend;
5413
+ appended = voiceTags['.doc-example'].append;
5391
5414
  jQuery('<div>' + prepend + '</div>').insertBefore(this);
5392
5415
  jQuery('<div>' + appended + pause_spoken + '</div>').insertBefore(this);
5393
5416
  jQuery(this).remove();
5394
5417
  });
5395
5418
 
5396
- // Search for listingblock elements, check for previous declared <div>
5419
+ // Search for listing block elements, check for previous declared <div>
5397
5420
  // container that contains the title element and insert the
5398
5421
  // text if exists and then finally remove the DOM object.
5399
5422
  //
5400
- jQuery(clone).find('.listingblock').addBack('listingblock').each(function () {
5423
+ jQuery(clone).find('.listingblock').addBack('.listingblock').each(function () {
5401
5424
  title_element = jQuery(this).find('.title');
5402
5425
  if (title_element.length) {
5403
5426
  copy = title_element[0].innerText;
5404
5427
  } else {
5405
5428
  copy = '';
5406
5429
  }
5407
- prepend = voiceTags['listingblock'].prepend;
5408
- appended = voiceTags['listingblock'].append;
5430
+ prepend = voiceTags['.listingblock'].prepend;
5431
+ appended = voiceTags['.listingblock'].append;
5409
5432
  if (copy !== undefined && copy != '') {
5410
5433
  jQuery('<div>' + prepend + ' with the caption,' + copy + pause_spoken + '</div>').insertBefore(this);
5411
5434
  jQuery('<div>' + appended + '</div>').insertBefore(this);
@@ -5416,37 +5439,11 @@ module.exports = function parseContent(options) {
5416
5439
  jQuery(this).remove();
5417
5440
  });
5418
5441
 
5419
- // Search for <carousel> tags, check for previous declared <div>
5420
- // container that contains the title element and insert the
5421
- // text if exists and finally remove the DOM object.
5422
- //
5423
- jQuery(clone).find('carousel').addBack('carousel').each(function () {
5424
- if ($(this).prev()[0].innerText !== undefined) {
5425
- title = $(this).prev()[0].innerText;
5426
- title_element = jQuery(this).prev();
5427
- // remove the title 'before' the DOM object deleted
5428
- //
5429
- jQuery(title_element).remove();
5430
- } else {
5431
- title = '';
5432
- }
5433
- prepend = voiceTags['carousel'].prepend;
5434
- appended = voiceTags['carousel'].append;
5435
- if (title !== undefined && title != '') {
5436
- jQuery('<div>' + prepend + ' with the caption,' + title + pause_spoken + '</div>').insertBefore(this);
5437
- jQuery('<div>' + appended + '</div>').insertBefore(this);
5438
- } else {
5439
- jQuery('<div>' + prepend + '</div>').insertBefore(this);
5440
- jQuery('<div>' + appended + '</div>').insertBefore(this);
5441
- }
5442
- jQuery(this).remove();
5443
- });
5444
-
5445
- // Search for <masonry> tags, check for previous declared <div>
5442
+ // Search for masonry elements, check for previous declared <div>
5446
5443
  // container that contains the title element and insert the
5447
5444
  // text if exists and finally remove the DOM object.
5448
5445
  //
5449
- jQuery(clone).find('masonry').addBack('masonry').each(function () {
5446
+ jQuery(clone).find('.masonry').addBack('.masonry').each(function () {
5450
5447
  if ($(this).prev()[0].innerText !== undefined) {
5451
5448
  title = $(this).prev()[0].innerText;
5452
5449
  title_element = jQuery(this).prev();
@@ -5456,8 +5453,8 @@ module.exports = function parseContent(options) {
5456
5453
  } else {
5457
5454
  title = '';
5458
5455
  }
5459
- prepend = voiceTags['masonry'].prepend;
5460
- appended = voiceTags['masonry'].append;
5456
+ prepend = voiceTags['.masonry'].prepend;
5457
+ appended = voiceTags['.masonry'].append;
5461
5458
  if (title !== undefined && title != '') {
5462
5459
  jQuery('<div>' + prepend + ' with the caption,' + title + pause_spoken + '</div>').insertBefore(this);
5463
5460
  jQuery('<div>' + appended + '</div>').insertBefore(this);
@@ -5468,11 +5465,11 @@ module.exports = function parseContent(options) {
5468
5465
  jQuery(this).remove();
5469
5466
  });
5470
5467
 
5471
- // Search for <slider> tags, check for previous declared <div>
5468
+ // Search for slider elements, check for previous declared <div>
5472
5469
  // container that contains the title element and insert the
5473
5470
  // text if exists and finally remove the DOM object.
5474
5471
  //
5475
- jQuery(clone).find('slider').addBack('slider').each(function () {
5472
+ jQuery(clone).find('.slider').addBack('.slider').each(function () {
5476
5473
  if ($(this).prev()[0].innerText !== undefined) {
5477
5474
  title = $(this).prev()[0].innerText;
5478
5475
  title_element = jQuery(this).prev();
@@ -5482,8 +5479,8 @@ module.exports = function parseContent(options) {
5482
5479
  } else {
5483
5480
  title = '';
5484
5481
  }
5485
- prepend = voiceTags['slider'].prepend;
5486
- appended = voiceTags['slider'].append;
5482
+ prepend = voiceTags['.slider'].prepend;
5483
+ appended = voiceTags['.slider'].append;
5487
5484
  if (title !== undefined && title != '') {
5488
5485
  jQuery('<div>' + prepend + ' with the caption, ' + title + pause_spoken + '</div>').insertBefore(this);
5489
5486
  jQuery('<div>' + appended + '</div>').insertBefore(this);
@@ -5494,11 +5491,11 @@ module.exports = function parseContent(options) {
5494
5491
  jQuery(this).remove();
5495
5492
  });
5496
5493
 
5497
- // Search for <gallery> tags, check for previous declared <div>
5494
+ // Search for gallery elements, check for previous declared <div>
5498
5495
  // container that contains the title element and insert the
5499
5496
  // text if exists and finally remove the DOM object.
5500
5497
  //
5501
- jQuery(clone).find('gallery').addBack('gallery').each(function () {
5498
+ jQuery(clone).find('.gallery').addBack('.gallery').each(function () {
5502
5499
  if ($(this).prev()[0].innerText !== undefined) {
5503
5500
  title = $(this).prev()[0].innerText;
5504
5501
  title_element = jQuery(this).prev();
@@ -5508,8 +5505,8 @@ module.exports = function parseContent(options) {
5508
5505
  } else {
5509
5506
  title = '';
5510
5507
  }
5511
- prepend = voiceTags['gallery'].prepend;
5512
- appended = voiceTags['gallery'].append;
5508
+ prepend = voiceTags['.gallery'].prepend;
5509
+ appended = voiceTags['.gallery'].append;
5513
5510
  if (title !== undefined && title != '') {
5514
5511
  prepend !== '' && jQuery('<div>' + prepend + ' with the caption ' + title + pause_spoken + '</div>').insertBefore(this);
5515
5512
  appended !== '' && jQuery('<div>' + appended + '</div>').insertBefore(this);
@@ -5520,10 +5517,10 @@ module.exports = function parseContent(options) {
5520
5517
  jQuery(this).remove();
5521
5518
  });
5522
5519
 
5523
- // Search for <slider> tags, and extract the <caption> tag data,
5520
+ // Search for a lightbox blocks and extract the <caption> tag data,
5524
5521
  // insert the text if exists and finally remove the DOM object.
5525
5522
  //
5526
- jQuery(clone).find('lightbox').addBack('gallery').each(function () {
5523
+ jQuery(clone).find('.lightbox-block').addBack('.lightbox-block').each(function () {
5527
5524
  if ($(this).prev()[0].innerText !== undefined) {
5528
5525
  title = $(this).prev()[0].innerText;
5529
5526
  title_element = jQuery(this).prev();
@@ -5533,8 +5530,8 @@ module.exports = function parseContent(options) {
5533
5530
  } else {
5534
5531
  title = '';
5535
5532
  }
5536
- prepend = voiceTags['lightbox'].prepend;
5537
- appended = voiceTags['lightbox'].append;
5533
+ prepend = voiceTags['.lightbox-block'].prepend;
5534
+ appended = voiceTags['.lightbox-block'].append;
5538
5535
  if (title !== undefined && title != '') {
5539
5536
  jQuery('<div>' + prepend + ' with the caption,' + title + pause_spoken + '</div>').insertBefore(this);
5540
5537
  jQuery('<div>' + appended + '</div>').insertBefore(this);
@@ -5716,10 +5713,12 @@ module.exports = function parseContent(options) {
5716
5713
  window.speechSynthesis.cancel();
5717
5714
  userStoppedSpeaking = true;
5718
5715
 
5719
- // jadams
5716
+ // jadams, 2023-09-28;
5717
+ // do not work
5718
+ // -----------------------------------------------------------------------
5720
5719
  // NOTE: stopping coincident active speech synthesis
5721
5720
  // in multiple browser windows (tabs) does NOT work
5722
- //
5721
+ // -----------------------------------------------------------------------
5723
5722
  // user_session.speech_synthesis_active = false;
5724
5723
  // j1.writeCookie({
5725
5724
  // name: 'user_session',
@@ -5728,8 +5727,9 @@ module.exports = function parseContent(options) {
5728
5727
  // expires: 0
5729
5728
  // });
5730
5729
 
5731
- return this;
5730
+ // return this;
5732
5731
  },
5732
+
5733
5733
  // END stop
5734
5734
 
5735
5735
  enabled: function () {
@@ -5740,8 +5740,25 @@ module.exports = function parseContent(options) {
5740
5740
  isSpeaking: function () {
5741
5741
  return window.speechSynthesis.speaking;
5742
5742
  },
5743
- // END is Speaking
5743
+ // END isSpeaking
5744
+
5745
+ isSpoken: function () {
5746
+ if (window.speechSynthesis.speaking) {
5747
+ return chunkCounter;
5748
+ } else {
5749
+ return false;
5750
+ }
5751
+ },
5752
+ // END isSpoken
5744
5753
 
5754
+ isScrolled: function () {
5755
+ if (window.speechSynthesis.speaking) {
5756
+ return lastScrollPosition;
5757
+ } else {
5758
+ return false;
5759
+ }
5760
+ },
5761
+ // END isSpoken
5745
5762
  isPaused: function () {
5746
5763
  return window.speechSynthesis.paused;
5747
5764
  },
@@ -5891,7 +5908,7 @@ module.exports = function parseContent(options) {
5891
5908
  }
5892
5909
  } else {
5893
5910
  if (voices[i].name.includes(voiceUserDefault)) {
5894
- // option.setAttribute('selected', 'selected');
5911
+ // option.setAttribute('selected', 'selected');
5895
5912
  }
5896
5913
  }
5897
5914
  option.setAttribute('data-speak2me-language', voices[i].language);
@@ -5899,7 +5916,7 @@ module.exports = function parseContent(options) {
5899
5916
  }
5900
5917
  return i - skippedVoices;
5901
5918
  },
5902
- // END get Voiuces
5919
+ // END getVoiuces
5903
5920
 
5904
5921
  setVoice: function () {
5905
5922
  // The setVoice function has to have two attributes
@@ -5946,8 +5963,8 @@ module.exports = function parseContent(options) {
5946
5963
  }
5947
5964
  }
5948
5965
  return this;
5949
- } // END set Voice
5950
- }; // END methods
5966
+ } // END setVoice
5967
+ }; // END public methods
5951
5968
 
5952
5969
  // main speak2me method
5953
5970
  //
@@ -5959,7 +5976,7 @@ module.exports = function parseContent(options) {
5959
5976
  } else {
5960
5977
  jQuery.error('Method ' + method + ' does not exist on jQuery.speak2me');
5961
5978
  }
5962
- };
5979
+ }; // END main
5963
5980
  })(jQuery);
5964
5981
 
5965
5982
  /***/ }),