]> _ Git - fluidbook-toolbox.git/commitdiff
wip #7600 @1.5
authorVincent Vanwaelscappel <vincent@cubedesigners.com>
Thu, 26 Jun 2025 12:55:17 +0000 (14:55 +0200)
committerVincent Vanwaelscappel <vincent@cubedesigners.com>
Thu, 26 Jun 2025 12:55:17 +0000 (14:55 +0200)
app/Models/ELearningMedia.php
app/Models/ElearningTranslate.php
resources/elearningmedia/js/app.js
resources/elearningmedia/sass/app.sass
resources/views/elearningmedia/index.blade.php

index d2adf93ccacf231846c0a2feab5f2ca370fa0d7e..0fdf3b9629e3207e0f227ba705848919303b717e 100644 (file)
@@ -79,8 +79,6 @@ class ELearningMedia extends ToolboxModel
         $this->addField('', FormSeparator::class);
         $this->addField('complete_button', Checkbox::class, __('Marquer terminer après un clic sur un bouton'), ['default' => false, 'when' => ['type' => 'pdf']]);
         $this->addField('complete_pct', Percent::class, __('Marquer terminé quand ce pourcentage est lu'), ['default' => 75, 'when' => ['complete_button' => 0, 'type' => ['logical_operator' => 'OR', 'values' => ['video', 'audio']]]]);
-
-
     }
 
     public function preSave()
@@ -109,7 +107,7 @@ class ELearningMedia extends ToolboxModel
 
         /** @var Media $file */
         $file = $this->getMediaInField('file')->first()->getPath();
-        self::compileFromFile($file, $dest, $this->title, $organization, 'MEDIA_' . $this->id, $this->scorm_version, 75);
+        self::compileFromFile($file, $dest, $this->title, $organization, 'MEDIA_' . $this->id, $this->scorm_version, $this->type === 'pdf' && $this->complete_button ? "'button'" : $this->complete_pct);
     }
 
     /**
@@ -118,7 +116,7 @@ class ELearningMedia extends ToolboxModel
      * @param $title string
      * @param $organization string
      * @param $reference string
-     * @param $complete_pct int
+     * @param $complete_pct int|string
      * @return string
      * @throws \Exception
      */
@@ -151,7 +149,7 @@ class ELearningMedia extends ToolboxModel
             $vdir->file_put_contents('pdfjs/web/viewer.css', $css);
         }
         $vdir->copy($file, 'media.' . $ext);
-        $vdir->file_put_contents('index.html', view('elearningmedia.index', ['complete_pct' => $complete_pct, 'title' => $title, 'type' => $type]));
+        $vdir->file_put_contents('index.html', view('elearningmedia.index', ['complete_pct' => $complete_pct,'title' => $title, 'type' => $type]));
         $vdir->sync(true);
         return $title;
     }
index c37debb3005371d358caaeae960f747a7a0b4d7f..6022cb974774371e347cc49959553fc1c4212374 100644 (file)
@@ -34,6 +34,7 @@ class ElearningTranslate extends ToolboxContentTranslate
     public function getPaths()
     {
         $res = parent::getPaths();
+        $res['Elearning Media'] = 'resources/view/elearningmedia';
         $res['OpenBadges'] = 'resources/badge/translate';
         return $res;
     }
index 6fd66aa879164d2c7b460267593960aa45cabd97..8d6717636aba99a31c430f19297bd2f8cd6bea6b 100644 (file)
@@ -7,6 +7,14 @@ window.cubeSCORM = new CubeSCORM();
 window.$ = window.jQuery = $;
 window.openTime = Date.now();
 
+window.playerIframe = document.getElementById('player');
+window.playerWindow = playerIframe.contentWindow;
+
+
+window.addEventListener("resize", function () {
+    resize();
+});
+
 document.addEventListener("DOMContentLoaded", function () {
     var media = document.getElementById('player');
     if (media.tagName.toLowerCase() === 'audio') {
@@ -31,7 +39,10 @@ document.addEventListener("DOMContentLoaded", function () {
 
     cubeSCORM.initScorm();
 
-    var pc = (parseInt(window.progressComplete) / 100);
+    var pc = window.progressComplete;
+    if (pc !== 'button') {
+        pc = (parseInt(window.progressComplete) / 100);
+    }
     var interval;
     if (window.type === 'audio' || window.type === 'video') {
         interval = setInterval(function () {
@@ -40,34 +51,60 @@ document.addEventListener("DOMContentLoaded", function () {
             }
         }, 1000);
     } else if (window.type === 'pdf') {
-        var playerIframe = document.getElementById('player');
+
         playerIframe.addEventListener('load', function () {
-            var playerWindow = playerIframe.contentWindow;
+            var interval;
 
+            if (pc === 'button') {
+                interval = setInterval(function () {
+                    try {
+                        var app = playerWindow.PDFViewerApplication;
+                        if (app === undefined || app === null) {
+                            return;
+                        }
+                        var pdfViewer = app.pdfViewer;
+                        if (pdfViewer === undefined || pdfViewer === null) {
+                            return;
+                        }
 
-            var interval = setInterval(function () {
-                console.log('Check pdf progress');
-                try {
-                    var app = playerWindow.PDFViewerApplication;
-                    if (app === undefined || app === null) {
-                        return;
-                    }
-                    var pdfViewer = app.pdfViewer;
-                    if (pdfViewer === undefined || pdfViewer === null) {
-                        return;
+                        let container = pdfViewer.container;
+                        container.addEventListener('scroll', function () {
+                            if (container.scrollTop / (container.scrollHeight - container.offsetHeight) > 0.95) {
+                                resize();
+                                showCompleteButton();
+                            }
+                        });
+                        clearInterval(interval);
+                    } catch (e) {
+                        console.error('Error while updating pdf course status');
+                        console.error(e);
                     }
+                }, 200);
+            } else {
+                interval = setInterval(function () {
+                    console.log('Check pdf progress');
+                    try {
+                        var app = playerWindow.PDFViewerApplication;
+                        if (app === undefined || app === null) {
+                            return;
+                        }
+                        var pdfViewer = app.pdfViewer;
+                        if (pdfViewer === undefined || pdfViewer === null) {
+                            return;
+                        }
 
-                    var total = pdfViewer.pagesCount;
-                    var current = pdfViewer._currentPageNumber;
-                    if (total > 0 && current / total >= pc) {
-                        markComplete(interval);
-                    }
+                        var total = pdfViewer.pagesCount;
+                        var current = pdfViewer._currentPageNumber;
+                        if (total > 0 && current / total >= pc) {
+                            markComplete(interval);
+                        }
 
-                } catch (e) {
-                    console.error('Error while updating pdf course status');
-                    console.error(e);
-                }
-            }, 1000);
+                    } catch (e) {
+                        console.error('Error while updating pdf course status');
+                        console.error(e);
+                    }
+                }, 1000);
+            }
         });
     }
 
@@ -76,7 +113,16 @@ document.addEventListener("DOMContentLoaded", function () {
     });
 });
 
+function showCompleteButton() {
+    document.getElementById('completeButton').classList.add('visible')
+}
+
 function markComplete(interval) {
     cubeSCORM.scormMarkAsComplete();
     clearInterval(interval);
 }
+
+function resize() {
+    let v = (playerWindow.innerWidth - playerWindow.document.querySelector('.page').getBoundingClientRect().width) / 2 + 30;
+    document.getElementById("completeButton").style.right = v + 'px';
+}
index 0b1213172657261b7f542554f73b445d76f9796e..d7adc616e72f680c1b7a7a524cb8e184136d5c17 100644 (file)
@@ -22,6 +22,30 @@ video, audio, iframe
 #audiobigplay
     display: block
 
+#completeButton
+    opacity: 0
+    pointer-events: none
+    position: absolute
+    display: flex
+    right: 30px
+    bottom: 30px
+    width: 130px
+    height: 130px
+    padding: 10px 10px 40px 10px
+    transition: opacity 600ms
+    background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAxMDQgMTA0Ij4KICA8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMjkuNi4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogMi4xLjEgQnVpbGQgMjA3KSAgLS0+CiAgPGRlZnM+CiAgICA8c3R5bGU+CiAgICAgIC5zdDAgewogICAgICAgIGZpbGw6ICM3MTJjZmQ7CiAgICAgIH0KCiAgICAgIC5zdDEgewogICAgICAgIGZpbGw6ICNlNGZmMTk7CiAgICAgIH0KCiAgICAgIC5zdDIgewogICAgICAgIGZpbGw6ICMyNTBjNjY7CiAgICAgIH0KCiAgICAgIC5zdDMgewogICAgICAgIGZpbGw6ICMzMzM7CiAgICAgIH0KICAgIDwvc3R5bGU+CiAgPC9kZWZzPgogIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjUyIiBjeT0iNTEuOSIgcj0iNDUiLz4KICA8cGF0aCBjbGFzcz0ic3QyIiBkPSJNNTIsMTAyLjRDMjQuMiwxMDIuNCwxLjUsNzkuNywxLjUsNTEuOVMyNC4yLDEuNCw1MiwxLjRzNTAuNSwyMi42LDUwLjUsNTAuNS0yMi42LDUwLjUtNTAuNSw1MC41Wk01MiwzQzI1LDMsMy4xLDI0LjksMy4xLDUxLjlzMjEuOSw0OC45LDQ4LjksNDguOSw0OC45LTIxLjksNDguOS00OC45Uzc5LDMsNTIsM1oiLz4KICA8Zz4KICAgIDxnPgogICAgICA8cGF0aCBjbGFzcz0ic3QxIiBkPSJNODEuMyw5NS44YzAsMy44LTMsNi44LTYuOCw2LjhzLTYuOC0zLTYuOC02LjgsMy02LjgsNi44LTYuOCw2LjgsMyw2LjgsNi44Ii8+CiAgICAgIDxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik03Ni44LDk5LjNoLTMuNGMwLDAtLjEsMC0uMiwwLS42LS44LTEuOS0zLjQtMi0zLjUtLjItLjMtLjItLjYsMC0uOC4yLS4yLjYtLjMuOSwwbC42LjZ2LTMuOGMwLS40LjQtLjguOC0uOHMuOC40LjguOHYxLjNoLjVjLjMsMCwuNS4xLjYuM2guNmMuMywwLC41LjIuNi40aC4zYy40LDAsMSwuNCwxLC44djEuM2MwLC40LDAsLjctLjIsMS4xbC0uOCwyLjNjMCwwLS4xLjEtLjIuMVpNNzMuNCw5OC45aDMuMmwuNy0yLjFjMC0uMy4xLS43LjEtMXYtMS4zYzAtLjItLjMtLjQtLjUtLjRoLS40Yy0uMSwwLS4yLDAtLjItLjJzLS4xLS4yLS4yLS4yaC0uN2MtLjEsMC0uMiwwLS4yLS4ycy0uMSwwLS4yLDBoLS43Yy0uMSwwLS4yLDAtLjItLjJ2LTEuNWMwLS4yLS4yLS40LS40LS40cy0uNC4yLS40LjR2NC4zYzAsMCwwLC4yLS4xLjIsMCwwLS4yLDAtLjIsMGwtLjktLjljMCwwLS4yLDAtLjMsMCwwLDAsMCwuMiwwLC4zLDAsMCwxLjMsMi41LDEuOSwzLjRaIi8+CiAgICA8L2c+CiAgICA8cGF0aCBjbGFzcz0ic3QzIiBkPSJNNzYuNSw5NC45Yy0uMSwwLS4yLDAtLjItLjJ2LS44YzAtLjEsMC0uMi4yLS4ycy4yLDAsLjIuMnYuOGMwLC4xLDAsLjItLjIuMlpNNzUuMyw5NC41Yy0uMSwwLS4yLDAtLjItLjJ2LS45YzAtLjEsMC0uMi4yLS4ycy4yLDAsLjIuMnYuOWMwLC4xLDAsLjItLjIuMlpNNzQuMSw5NC41Yy0uMSwwLS4yLDAtLjItLjJ2LTEuM2MwLS4xLDAtLjIuMi0uMnMuMiwwLC4yLjJ2MS4zYzAsLjEsMCwuMi0uMi4yWiIvPgogIDwvZz4KICA8Zz4KICAgIDxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik01Ni4yLDc4LjNjLTEuNiwxLjgtMy4yLDMuNy00LjgsNS41LS4yLjItLjQuNC0uNS42LTEtLjktMi0xLjctMy0yLjYtLjItLjItLjYuMS0uNC40LDEuMS45LDIuMSwxLjgsMy4yLDIuOCwwLDAsLjMuMS40LDAsMS42LTEuOCwzLjItMy43LDQuOC01LjUuMi0uMy41LS41LjctLjguMi0uMi0uMS0uNi0uNC0uNFoiLz4KICAgIDxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik01NS4zLDcyLjhjLTMuNy0xLjQtOC0uMi0xMC42LDIuOS0yLjUsMy4xLTIuOCw3LjUtLjgsMTAuOSwyLDMuNCw2LjEsNS4xLDkuOSw0LjQsMy44LS44LDYuOS0zLjksNy41LTcuOCwwLS41LjEtMSwuMS0xLjUsMC0zLjktMi41LTcuNS02LjItOC45Wk01NSw5MGMtMy41LDEuMy03LjUuMi05LjktMi43LTIuNC0yLjktMi43LTcuMS0uOC0xMC4zLDEuOS0zLjIsNS44LTQuOSw5LjQtNC4yLDMuNi43LDYuNSwzLjcsNy4xLDcuNCwwLC41LjEuOS4xLDEuNCwwLDMuNy0yLjQsNy4xLTUuOSw4LjRaIi8+CiAgPC9nPgo8L3N2Zz4=")
+    background-size: cover
+    color: #fff
+    text-decoration: none
+    align-items: center
+    justify-content: center
+
+    &.visible
+        transition: opacity 600ms
+        opacity: 1
+        pointer-events: all
+
+
 .plyr
     position: absolute
     top: 0
index 27e725996831495253f18def0501354053815837..22a63b83a7460db7ade14f3f2882aeae2a0328f3 100644 (file)
@@ -7,12 +7,14 @@
     <title>{{$title}}</title>
     <script>
         var type = '{{$type}}';
-        var progressComplete = {{$complete_pct}};
+        var progressComplete = {!! $complete_pct !!};
     </script>
 </head>
 <body>
 @if($type==='pdf')
     <iframe id="player" frameborder="0" src="pdfjs/web/viewer.html?file=../../media.pdf#page=1"></iframe>
+    <a href="javascript:markComplete();"
+       id="completeButton">{{ __('Click here once you have completed your learning session') }}</a>
 @elseif($type==='audio')
     <button type="button" id="audiobigplay" class="plyr__control plyr__control--overlaid" data-plyr="play"
             aria-label="Play">