소스 검색

fin des corrections

Valentin 11 달 전
부모
커밋
648c737925
5개의 변경된 파일461개의 추가작업 그리고 421개의 파일을 삭제
  1. 6 0
      functions.php
  2. 5 0
      resources/scripts/app.js
  3. 409 420
      resources/scripts/front/timeline.js
  4. 40 0
      resources/styles/app.css
  5. 1 1
      resources/views/sections/header.blade.php

+ 6 - 0
functions.php

@@ -331,6 +331,12 @@ collect(['setup', 'filters'])
 
     add_action('admin_enqueue_scripts', 'log_posts_with_user_revisions');
 
+    function custom_logout_redirect() {
+        wp_redirect( home_url() );
+        exit();
+    }
+    add_action('wp_logout','custom_logout_redirect');
+
 
 // function supprimer_tous_les_articles() {
 //     $args = array(

+ 5 - 0
resources/scripts/app.js

@@ -17,6 +17,11 @@ domReady(async () => {
   window.addEventListener('resize', function() {
     setTimeout(function() {
       window.scrollTo(0, 0);
+      let editButtons = document.querySelectorAll(".edit-button");
+      for (let editButton of editButtons) {
+        let editContainer = editButton.parentElement;
+        editContainer.style.height = `${editContainer.previousElementSibling.offsetHeight}px`;
+      }
     }, 0);
   });
 

+ 409 - 420
resources/scripts/front/timeline.js

@@ -1,18 +1,42 @@
 function customTimeline() {
-    // titres de parties dans le tableau
-    let mainpartTitless = document.querySelectorAll('.isMainPart');
-    for (let mainpartTitles of mainpartTitless) {
-      if (mainpartTitles.nextElementSibling.classList.contains('isSubPart')) {
-        mainpartTitles.firstElementChild.firstElementChild.style.height = "1.5rem";
-        mainpartTitles.firstElementChild.style.marginBottom = "-0.25rem";
-        mainpartTitles.style.borderBottom = "0";
-        mainpartTitles.style.paddingBottom = "0";
-        mainpartTitles.nextElementSibling.style.paddingTop = "0";
+  let colors, titles, partTitles;
+  let partDurations = [];
+  let totalTime;
+  let tlContainer, tlContainerHeight;
+  let partBlockHeights = [];
+  let activePartIndex = 0;
+  let steps = {
+    tlElSteps: [],
+    scrollSteps: []
+  }
+  let previousScroll;
+  let grabbing = false;
+  let titresFrise;
+  let cursor = document.querySelector('#cursor');
+  let titresCursor;
+  let partRects;
+  let isScrollingFromGrab = false;
+  let prevPartIndex = 0;
+  let lastCallTimestamp = 0;
+  let timestampDebounce = 200;
+
+  // titres de parties dans le tableau
+  function setPartTitlesInPartition() {
+    let mainpartTitles = document.querySelectorAll('.isMainPart');
+    for (let mainpartTitle of mainpartTitles) {
+      if (mainpartTitle.nextElementSibling.classList.contains('isSubPart')) {
+        mainpartTitle.firstElementChild.firstElementChild.style.height = "1.5rem";
+        mainpartTitle.firstElementChild.style.marginBottom = "-0.25rem";
+        mainpartTitle.style.borderBottom = "0";
+        mainpartTitle.style.paddingBottom = "0";
+        mainpartTitle.nextElementSibling.style.paddingTop = "0";
       }
     }
-  
-    // couleurs titres
-    let colors = [
+  }
+
+  // couleurs titres
+  function setPartsColors() {
+    colors = [
       {'red' : 'cf0118'},
       {'blue1': '0101c4'},
       {'blue2': '01049e'},
@@ -27,8 +51,8 @@ function customTimeline() {
       {'pink1': 'cf0118'},
       {'pink2': 'a10418'}
     ];
-    let titles = document.querySelectorAll('.isMainPart, .isSubPart');
-    let partTitles = [];
+    titles = document.querySelectorAll('.isMainPart, .isSubPart');
+    partTitles = [];
     for (let title of titles) {
       if (!title.nextElementSibling.classList.contains('isSubPart')) {
         partTitles.push(title);
@@ -40,21 +64,23 @@ function customTimeline() {
       }
       partTitles[i].firstElementChild.firstElementChild.style.backgroundColor = "#" + Object.values(colors[i])[0];
     }
-  
-    // set parts rectangles
-    function convertToSeconds(timeStr) {
-        let [hourStr, minStr] = timeStr.split('h');
-        if (!minStr) {
-            minStr = hourStr;
-            hourStr = '0';
-        }
-        minStr = minStr.replace('’', ':');
-        minStr = minStr.replace("'", ':');
-        const [min, sec] = minStr.split(':');
-  
-        return parseInt(hourStr) * 3600 + parseInt(min) * 60 + parseInt(sec);
-    }
-  
+  }
+
+  // set parts rectangles
+  function convertToSeconds(timeStr) {
+      let [hourStr, minStr] = timeStr.split('h');
+      if (!minStr) {
+          minStr = hourStr;
+          hourStr = '0';
+      }
+      minStr = minStr.replace('’', ':');
+      minStr = minStr.replace("'", ':');
+      const [min, sec] = minStr.split(':');
+
+      return parseInt(hourStr) * 3600 + parseInt(min) * 60 + parseInt(sec);
+  }
+
+  function getPartsTimes() {
     let partTimesNodes = document.querySelectorAll('body #app main tbody tr:not(.isContentPart) + tr:not(.isSubPart) td:first-of-type');
     let partTimes = Array.from(partTimesNodes);
     for (let i = 0; i < partTimes.length; i++) {
@@ -62,98 +88,73 @@ function customTimeline() {
     }
     let lastTime = document.querySelectorAll('body #app main tbody tr:last-of-type td:first-of-type');
     partTimes.push(convertToSeconds(lastTime[0].innerText));
-    let partDurations = [];
     for (let i = 0; i < partTimes.length - 1; i++) {
       partDurations.push(partTimes[i + 1] - partTimes[i]);
     }
-    let totalTime = convertToSeconds(lastTime[0].innerText);
-  
-    let tlContainer, tlContainerHeight;
-    let partBlockHeights = [];
-    let activePartIndex = 0;
-    
-    function getAllHeights() {
-      partBlockHeights = [];
-      tlContainer = document.querySelector('#timeline_container');
-      let header = document.querySelector('header'), footer = document.querySelector('footer');
-      tlContainer.style.height = `calc(100vh - ${header.offsetHeight}px - ${footer.offsetHeight}px - 60px)`;
-      tlContainer.style.top = `${document.querySelector('header').offsetHeight + 30}px`;
-      tlContainerHeight = tlContainer.offsetHeight;
-      for (let partDuration of partDurations) {
-        partBlockHeights.push(partDuration / totalTime * tlContainerHeight);
-      }
+    totalTime = convertToSeconds(lastTime[0].innerText);
+  }
+
+  function getAllHeights() {
+    partBlockHeights = [];
+    tlContainer = document.querySelector('#timeline_container');
+    let header = document.querySelector('header');
+    let footer = document.querySelector('footer');
+    tlContainer.style.height = `calc(100vh - ${header.offsetHeight}px - ${footer.offsetHeight}px - 60px)`;
+    tlContainer.style.top = `${header.offsetHeight + 30}px`;
+    tlContainerHeight = tlContainer.offsetHeight;
+    for (let partDuration of partDurations) {
+      partBlockHeights.push(partDuration / totalTime * tlContainerHeight);
     }
-    getAllHeights();
-    
-    function drawFriseRects() {
-      for (let i = 0; i < partBlockHeights.length; i++) {
-        let partDiv = document.createElement('div');
-        partDiv.style.width = "22px";
-        partDiv.style.height = partBlockHeights[i] + "px";
-        partDiv.style.backgroundColor = "#" + Object.values(colors[i])[0];
-        partDiv.style.borderBottom = "solid 1px #010d19";
-        partDiv.style.borderTop = "solid 1px #010d19";
-        partDiv.style.transition = "width 0.3s ease-out";
-        partDiv.style.cursor = "pointer";
-        tlContainer.prepend(partDiv);
-        tlContainer.children[0].addEventListener("mouseenter", function() {
-          let el = tlContainer.children[tlContainer.children.length - 1 - i];
-          if (Array.from(el.parentNode.children).length - Array.from(el.parentNode.children).indexOf(el) - 1 != activePartIndex) {
-            el.style.width = "32px";
-            toggleTitleHover(i, 'show');
-          }
-        });
-        tlContainer.children[0].addEventListener("mouseleave", function() {
-          let el = tlContainer.children[tlContainer.children.length - 1 - i];
-          if (Array.from(el.parentNode.children).length - Array.from(el.parentNode.children).indexOf(el) - 1 != activePartIndex) {
-            el.style.width = "22px";
-          }
-          toggleTitleHover(i, 'hide');
-        });
-        tlContainer.children[0].addEventListener("click", function() {
-          isScrollingFromGrab = false;
-          titresFrise[i].el.scrollIntoView({ behavior: 'smooth', block: 'center' });
-        });
-      }
+  }
+  
+  function drawFriseRects() {
+    for (let i = 0; i < partBlockHeights.length; i++) {
+      let partDiv = document.createElement('div');
+      partDiv.classList.add('tlRectPart');
+      partDiv.style.height = partBlockHeights[i] + "px";
+      partDiv.style.backgroundColor = "#" + Object.values(colors[i])[0];
+      tlContainer.prepend(partDiv);
+      tlContainer.children[0].addEventListener("mouseenter", function() {
+        let el = tlContainer.children[tlContainer.children.length - 1 - i];
+        if (Array.from(el.parentNode.children).length - Array.from(el.parentNode.children).indexOf(el) - 1 != activePartIndex) {
+          el.style.width = "32px";
+          toggleTitleHover(i, 'show');
+        }
+      });
+      tlContainer.children[0].addEventListener("mouseleave", function() {
+        let el = tlContainer.children[tlContainer.children.length - 1 - i];
+        if (Array.from(el.parentNode.children).length - Array.from(el.parentNode.children).indexOf(el) - 1 != activePartIndex) {
+          el.style.width = "22px";
+        }
+        toggleTitleHover(i, 'hide');
+      });
+      tlContainer.children[0].addEventListener("click", function() {
+        isScrollingFromGrab = false;
+        titresFrise[i].el.scrollIntoView({ behavior: 'smooth', block: 'center' });
+      });
     }
-    drawFriseRects();
-  
-    window.addEventListener('resize', () => {
-      while(tlContainer.lastChild) {
-        tlContainer.removeChild(tlContainer.lastChild);
-      }
-      getAllHeights();
-      drawFriseRects();
-      setPartRects();
-    });
-  
-    // detect if is scrolling
-  
-    let previousScroll;
-    
-    function isWindowScrolling() {
-      let currentScroll = window.scrollY;
-      if (currentScroll !== previousScroll) {
-        previousScroll = currentScroll;
-        return true;
-      } else {
-        return false;
-      }
+  }
+
+  // detect if is scrolling
+  function isWindowScrolling() {
+    let currentScroll = window.scrollY;
+    if (currentScroll !== previousScroll) {
+      previousScroll = currentScroll;
+      return true;
+    } else {
+      return false;
     }
-    
-    // titres parties frise
-    let titreFriseEl = document.createElement('div');
-  
-    let elements = Array.from(document.querySelectorAll('.isMainPart, .isSubPart'));
+  }
   
+  // titres parties frise
+  function displayTimelineTitles() {
     let mainWithoutSubAfter = [];
     let mainWithSubAfter = [];
     let subWithoutMainBefore = [];
-  
+
+    let elements = Array.from(document.querySelectorAll('.isMainPart, .isSubPart'));
     let lastMain = null;
-  
-    let grabbing = false;
-  
+
     for (let i = 0; i < elements.length; i++) {
       let current = elements[i];
       let next = elements[i + 1];
@@ -173,7 +174,7 @@ function customTimeline() {
       }
     }
     
-    let titresFrise = [...mainWithoutSubAfter, ...mainWithSubAfter, ...subWithoutMainBefore];
+    titresFrise = [...mainWithoutSubAfter, ...mainWithSubAfter, ...subWithoutMainBefore];
   
     titresFrise.sort((a, b) => a.index - b.index);
   
@@ -185,6 +186,9 @@ function customTimeline() {
         titresFrise.splice(i, 1);
       }
     }
+
+      
+    let titreFriseEl = document.createElement('div');
   
     titreFriseEl.setAttribute('id', 'titres_frise');
     titreFriseEl.innerHTML = `
@@ -192,346 +196,331 @@ function customTimeline() {
       <p>${titresFrise[0].main}</p>
       <p class="font-authentic-60">${titresFrise[0].sub}</p>
     `;
-    titreFriseEl.style.fontSize = '0.9em';
-    titreFriseEl.style.backgroundColor = 'rgba(1, 13, 25, 0.6)';
-    titreFriseEl.style.zIndex = '20';
-    titreFriseEl.style.position = 'fixed';
-    titreFriseEl.style.left = '60px';
-    titreFriseEl.style.width = '10vw';
-    titreFriseEl.style.lineHeight = '1.2';
-    titreFriseEl.style.marginTop = '-8px';
     titreFriseEl.style.top = `${document.querySelector('#timeline_container').getBoundingClientRect().top}px`;
     let main = document.querySelector('#main');
     main.prepend(titreFriseEl);
-  
-    // création et togle des titres au survol des div de la timeline
-    function drawFixedTitles() {
-      let tlContainer = document.querySelector('#timeline_container');
-      let fixedTitlesContainer = document.createElement('div');
-      fixedTitlesContainer.setAttribute('id', 'fixedTitlesContainer');
-      main.prepend(fixedTitlesContainer);
-      for (let index = 0; index < titresFrise.length; index++) {
-        let titreFixedEl = document.createElement('div');
-        titreFixedEl.style.position = 'fixed';
-        titreFixedEl.style.zIndex = 1;
-        titreFixedEl.style.display = 'none';
-        titreFixedEl.style.opacity = '0';
-        titreFixedEl.style.transition = 'opacity 0.3s ease-out';
-        titreFixedEl.style.width = '10vw';
-        titreFixedEl.style.top = `${tlContainer.children[index].getBoundingClientRect().top - 8}px`;
-        titreFixedEl.style.left = '60px';
-        titreFixedEl.style.fontSize = '0.9em';
-        titreFixedEl.style.lineHeight = '1.2';
-        let titreFixedElContent = document.createElement('p');
-        titreFixedElContent.innerHTML = `
-          <p>${titresFrise[titresFrise.length - index - 1].main}</p>
-          <p class="font-authentic-60">${titresFrise[titresFrise.length - index - 1].sub}</p>
-        `;
-        titreFixedElContent.style.backgroundColor = '#010d19';
-        titreFixedEl.append(titreFixedElContent);
-        let topGradient = document.createElement('div');
-        topGradient.style.height = '10px';
-        topGradient.style.width = '100%';
-        topGradient.style.background = 'linear-gradient(to bottom, transparent, #010d19)';
-        titreFixedEl.prepend(topGradient);
-        let bottomGradient = document.createElement('div');
-        bottomGradient.style.height = '10px';
-        bottomGradient.style.width = '100%';
-        bottomGradient.style.background = 'linear-gradient(to top, transparent, #010d19)';
-        titreFixedEl.append(bottomGradient);
-        fixedTitlesContainer.prepend(titreFixedEl);
-      }
+
+    titresCursor = document.querySelector('#titres_frise');
+
+    setTimeout(() => {
+      titreFriseEl.firstElementChild.innerText = getCurrentTime(titresFrise[0].el);
+    }, 10);
+
+  }
+
+  // création et togle des titres au survol des div de la timeline
+  function drawFixedTitles() {
+    let tlContainer = document.querySelector('#timeline_container');
+    let fixedTitlesContainer = document.createElement('div');
+    fixedTitlesContainer.setAttribute('id', 'fixedTitlesContainer');
+    main.prepend(fixedTitlesContainer);
+    for (let index = 0; index < titresFrise.length; index++) {
+      let titreFixedEl = document.createElement('div');
+      titreFixedEl.classList.add('tlFixedTitle');
+      titreFixedEl.style.top = `${tlContainer.children[index].getBoundingClientRect().top - 8}px`;
+      let titreFixedElContent = document.createElement('p');
+      titreFixedElContent.innerHTML = `
+        <p>${titresFrise[titresFrise.length - index - 1].main}</p>
+        <p class="font-authentic-60">${titresFrise[titresFrise.length - index - 1].sub}</p>
+      `;
+      titreFixedEl.append(titreFixedElContent);
+      fixedTitlesContainer.prepend(titreFixedEl);
     }
-    drawFixedTitles();
-  
-    function toggleTitleHover(elIndex, state) {
-      let fixedTitlesContainer = document.querySelector('#fixedTitlesContainer');
-      let el = fixedTitlesContainer.children[elIndex];
-      if (state === 'show') {
-        el.style.display = 'block';
-        setTimeout(() => {
-          el.style.opacity = '1';
-        }, 1);
-      } else if (state === 'hide') {
-        el.style.opacity = '0';
-        setTimeout(() => {
-          el.style.display = 'none';
-        }, 300);
-      }
+  }
+
+  function toggleTitleHover(elIndex, state) {
+    let fixedTitlesContainer = document.querySelector('#fixedTitlesContainer');
+    let el = fixedTitlesContainer.children[elIndex];
+    if (state === 'show') {
+      el.style.display = 'block';
+      setTimeout(() => {
+        el.style.opacity = '1';
+      }, 1);
+    } else if (state === 'hide') {
+      el.style.opacity = '0';
+      setTimeout(() => {
+        el.style.display = 'none';
+      }, 300);
     }
-  
-  
-    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-    // ICI IL Y A LE GRAB DU CURSEUR DE LA TL
-    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-  
-    // make the cursor move on scroll
-    let cursor = document.querySelector('#cursor');
+  }
+
+  // make the cursor move on scroll
+  function setupCursor() {
     cursor.style.top = `${document.querySelector('#timeline_container').getBoundingClientRect().top}px`;
     cursor.style.cursor = 'grab';
-    let titres = document.querySelector('#titres_frise');
-    titres.style.cursor = 'grab';
-    let partRects;
-    function setPartRects() {
-      partRects = document.querySelectorAll('#timeline_container div');
-      partRects = Array.from(partRects);
-      partRects = partRects.reverse();
-      partRects[0].style.width = '32px';
+    titresCursor.style.cursor = 'grab';
+  }
+
+  function setPartRects() {
+    partRects = document.querySelectorAll('#timeline_container div');
+    partRects = Array.from(partRects);
+    partRects = partRects.reverse();
+    partRects[0].style.width = '32px';
+  }
+
+  document.addEventListener("scroll", () => {
+    if (!grabbing) {
+      displayCurrentPartTitle(getCurrentPartFromScroll());
+      if (document.documentElement.scrollTop === 0) {
+        let firstTimeText = document.querySelector('tbody tr:nth-of-type(2) td:first-of-type');
+        titresCursor.firstElementChild.innerText = firstTimeText.innerText;
+      } else if (document.documentElement.scrollTop + window.innerHeight >= document.body.scrollHeight) {
+        let lastTimeText = document.querySelector('tbody tr:last-of-type td:first-of-type');
+        titresCursor.firstElementChild.innerText = lastTimeText.innerText;
+      }
+      moveCursorFromScroll(getCurrentPartFromScroll());
     }
-    setPartRects();
-    document.addEventListener("scroll", () => {
-      if (!grabbing) {
-        displayCurrentPartTitle(getCurrentPartFromScroll());
-        if (document.documentElement.scrollTop === 0) {
-          let firstTimeText = document.querySelector('tbody tr:nth-of-type(2) td:first-of-type');
-          titres.firstElementChild.innerText = firstTimeText.innerText;
-        } else if (document.documentElement.scrollTop + window.innerHeight >= document.body.scrollHeight) {
+  });
+
+  function makeElementDraggable(element, relatedEl) {
+    let offsetY;
+  
+    element.addEventListener('mousedown', (e) => {
+      let elTransformY = element.style.transform ? +element.style.transform.split('(')[1].split('p')[0] : 0;
+      e.preventDefault();
+      grabbing = true;
+      offsetY = e.clientY - elTransformY;
+      element.style.cursor = 'grabbing';
+    });
+  
+    document.addEventListener('mousemove', (e) => {
+      if (grabbing) {
+        const y = e.clientY - offsetY;
+        if (e.clientY < tlContainerHeight + tlContainer.offsetTop && e.clientY > tlContainer.offsetTop && y > 0) {
+          element.style.transform = `translateY(${y}px)`;
+          relatedEl.style.transform = `translateY(${y}px)`;
+          if (!isNaN(y)) displayCurrentPartTitle(getCurrentPartFromCursor(y));
+        } else if (e.clientY < tlContainer.offsetTop || y <= 0) {
+          element.style.transform = `translateY(0px)`;
+          relatedEl.style.transform = `translateY(0px)`;
+          setTimeout(() => {
+            let firstTimeText = document.querySelector('tbody tr:nth-of-type(2) td:first-of-type');
+            titresCursor.firstElementChild.innerText = firstTimeText.innerText;
+          }, 100);
+        } else if (e.clientY >= tlContainerHeight + tlContainer.offsetTop) {
+          element.style.transform = `translateY(${tlContainerHeight}px)`;
+          relatedEl.style.transform = `translateY(${tlContainerHeight}px)`;
           let lastTimeText = document.querySelector('tbody tr:last-of-type td:first-of-type');
-          titres.firstElementChild.innerText = lastTimeText.innerText;
+          titresCursor.firstElementChild.innerText = lastTimeText.innerText;
         }
-        moveCursorFromScroll(getCurrentPartFromScroll());
       }
     });
-  
-    function makeElementDraggable(element, relatedEl) {
-      let offsetY;
-    
-      element.addEventListener('mousedown', (e) => {
-        let elTransformY;
-        if (!element.style.transform) {
-          elTransformY = 0;
-        } else {
-          elTransformY = +element.style.transform.split('(')[1].split('p')[0];
-        }
-        e.preventDefault();
-        grabbing = true;
+      
+    document.addEventListener('mouseup', (e) => {
+      if (grabbing) {
+        scrollOnGrab(element);
+        let elTransformY = element.style.transform ? +element.style.transform.split('(')[1].split('p')[0] : 0;
         offsetY = e.clientY - elTransformY;
-        element.style.cursor = 'grabbing';
-      });
-    
-      document.addEventListener('mousemove', (e) => {
-        if (grabbing) {
-          if (e.clientY < tlContainerHeight + tlContainer.offsetTop && e.clientY > tlContainer.offsetTop) {
-            const y = e.clientY - offsetY;
-            element.style.transform = `translateY(${y}px)`;
-            relatedEl.style.transform = `translateY(${y}px)`;
-            if (!isNaN(y)) displayCurrentPartTitle(getCurrentPartFromCursor(y));
-          } else if (e.clientY < tlContainer.offsetTop + 10) {
-            element.style.transform = `translateY(0px)`;
-            relatedEl.style.transform = `translateY(0px)`;
-            let firstTimeText = document.querySelector('tbody tr:nth-of-type(2) td:first-of-type');
-            titres.firstElementChild.innerText = firstTimeText.innerText;
-          } else if (e.clientY >= tlContainerHeight + tlContainer.offsetTop) {
-            element.style.transform = `translateY(${tlContainerHeight}px)`;
-            relatedEl.style.transform = `translateY(${tlContainerHeight}px)`;
-            let lastTimeText = document.querySelector('tbody tr:last-of-type td:first-of-type');
-            titres.firstElementChild.innerText = lastTimeText.innerText;
-          }
+        const y = e.clientY - offsetY;
+        if (e.clientY < tlContainer.offsetTop || y <= 0) {
+          window.scrollTo(0, 0);
+        } else {
+          setTimeout(() => {
+            titresCursor.firstElementChild.innerText = getCurrentTime(titresFrise[getCurrentPartFromCursor(y)]?.el);
+          }, 1000);
         }
-      });
-    
-      document.addEventListener('mouseup', () => {
-        if (grabbing) scrollOnGrab(element);
-        element.style.cursor = 'grab';
-        grabbing = false;
-      });
-    }
-  
-    makeElementDraggable(cursor, titres);
-    makeElementDraggable(titres, cursor);
-  
-    // get heights of parts dans le tableau et dans la timeline
-    function getSteps() {
-      let tlElSteps = [];
-      for (let i = 0; i < partRects.length; i++) {
-        tlElSteps.push(partRects[i].offsetTop);
       }
-      let titles = document.querySelectorAll('.isMainPart, .isSubPart');
-      let scrollSteps = [];
-      for (let title of titles) {
-        let nextLine = title.nextElementSibling;
-        if (!nextLine?.classList.contains('isSubPart')) {
-          scrollSteps.push(title.offsetTop);
-        }
+      element.style.cursor = 'grab';
+      grabbing = false;
+    });
+  }
+
+  // get heights of parts dans le tableau et dans la timeline
+  function getSteps() {
+    steps.tlElSteps = [];
+    steps.scrollSteps = [];
+    for (let i = 0; i < partRects.length; i++) {
+      // steps.tlElSteps.push(partRects[i].offsetTop);
+      steps.tlElSteps.push(partRects[i].getBoundingClientRect().top);
+    }
+    let titles = document.querySelectorAll('.isMainPart, .isSubPart');
+    for (let title of titles) {
+      let nextLine = title.nextElementSibling;
+      if (!nextLine?.classList.contains('isSubPart')) {
+        // steps.scrollSteps.push(title.offsetTop);
+        steps.scrollSteps.push(title.offsetTop);
       }
-      return({
-        'tlElSteps':tlElSteps,
-        'scrollSteps':scrollSteps
-      });
     }
-  
-  
-    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-    // ICI IL Y A LE SCROLL DU GRAB
-    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-    let isScrollingFromGrab = false;
-  
-    function scrollOnGrab(el) {
-     let scrollValue = 
-        ((getSteps().scrollSteps[getCursorPositionInTimelinePart(el).stepAfterMouseUp] - getSteps().scrollSteps[getCursorPositionInTimelinePart(el).stepAfterMouseUp - 1]) * getCursorPositionInTimelinePart(el).proportionInPart)
-        + getSteps().scrollSteps[getCursorPositionInTimelinePart(el).stepAfterMouseUp];
-      isScrollingFromGrab = true;
-      window.scrollTo({ top: scrollValue, behavior: 'smooth' });
-      setTimeout(() => {
-        isScrollingFromGrab = false;
-      }, 2000);
+  }
+
+  function scrollOnGrab(el) {
+    let scrollValue;
+    if (getCursorPositionInTimelinePart(el).stepAfterMouseUp === steps.scrollSteps.length - 1) {
+      scrollValue = 
+        ((document.documentElement.scrollHeight - steps.scrollSteps[getCursorPositionInTimelinePart(el).stepAfterMouseUp]) * getCursorPositionInTimelinePart(el).proportionInPart)
+        + steps.scrollSteps[getCursorPositionInTimelinePart(el).stepAfterMouseUp];
+    } else {
+      scrollValue = 
+        ((steps.scrollSteps[getCursorPositionInTimelinePart(el).stepAfterMouseUp + 1] - steps.scrollSteps[getCursorPositionInTimelinePart(el).stepAfterMouseUp]) * getCursorPositionInTimelinePart(el).proportionInPart)
+        + steps.scrollSteps[getCursorPositionInTimelinePart(el).stepAfterMouseUp];
     }
-  
-    function getCursorPositionInTimelinePart(el) {
-      let elTransformY;
-      if (!el.style.transform) {
-        elTransformY = 0;
+    isScrollingFromGrab = true;
+    window.scrollTo({ top: scrollValue, behavior: 'smooth' });
+    setTimeout(() => {
+      isScrollingFromGrab = false;
+    }, 1000);
+  }
+
+  function getCursorPositionInTimelinePart(el) {
+    let elTransformY;
+    if (!el.style.transform) {
+      elTransformY = 0;
+    } else {
+      elTransformY = +el.style.transform.split('(')[1].split('p')[0];
+    }
+
+    let tlPartHeight, tlPartBottom, tlPartTop, proportionInPart, stepAfterMouseUp;
+    tlPartHeight = partRects[getCurrentPartFromCursor(elTransformY) || 0].getBoundingClientRect().height;
+    tlPartBottom = partRects[getCurrentPartFromCursor(elTransformY) || 0].getBoundingClientRect().bottom - tlContainer.getBoundingClientRect().top;
+    tlPartTop = steps.tlElSteps[getCurrentPartFromCursor(elTransformY) || 0] - steps.tlElSteps[0];
+    proportionInPart = 1 - ((tlPartHeight - (elTransformY - tlPartTop)) / tlPartHeight);
+
+    if (proportionInPart > 0 && proportionInPart < 1) {
+      stepAfterMouseUp = getCurrentPartFromCursor(elTransformY);
+      return {stepAfterMouseUp, proportionInPart};
+    } else {
+      stepAfterMouseUp = getCurrentPartFromCursor(elTransformY);
+      proportionInPart = 0;
+      return {stepAfterMouseUp, proportionInPart};
+    }
+  }
+
+  function moveCursorFromScroll(currentPartIndex) {
+    if (!isScrollingFromGrab) {
+      let currentScroll = window.scrollY;
+      let tlPartHeight = parseInt(partRects[currentPartIndex].style.height);
+      let cursorTopValue = partRects[currentPartIndex].getBoundingClientRect().top - parseInt(tlContainer.style.top);
+
+      let currentScrollPartTop = steps.scrollSteps[currentPartIndex] || 0;
+      let currentScrollPartHeight;
+      if (steps.scrollSteps[currentPartIndex + 1]) {
+        currentScrollPartHeight = steps.scrollSteps[currentPartIndex + 1] - currentScrollPartTop;
       } else {
-        elTransformY = +el.style.transform.split('(')[1].split('p')[0];
+        currentScrollPartHeight = document.querySelector('body').scrollHeight - currentScrollPartTop;
       }
-  
-      let tlPartHeight, tlPartBottom, tlPartTop, proportionInPart, stepAfterMouseUp;
-      for (let j = 0; j < partRects.length; j++) {
-        if (j === getCurrentPartFromCursor(elTransformY)) {
-          tlPartHeight = partRects[j].getBoundingClientRect().height;
-          tlPartBottom = partRects[j].getBoundingClientRect().top - tlContainer.getBoundingClientRect().top;
-          tlPartTop = tlPartBottom - tlPartHeight;
-          proportionInPart = ((tlPartHeight - (elTransformY - tlPartTop)) / tlPartHeight) * -1;
-          if (proportionInPart > 0 && proportionInPart < 1) {
-            stepAfterMouseUp = j;
-            return {stepAfterMouseUp, proportionInPart};
-          } else {
-            stepAfterMouseUp = j;
-            proportionInPart = 0;
-            return {stepAfterMouseUp, proportionInPart};
-          }
-        } 
+
+      let currentScrollSincePartBottom = currentScroll - currentScrollPartTop;
+      let scrollPartProportion = currentScrollSincePartBottom / currentScrollPartHeight;
+
+      cursorTopValue = cursorTopValue + tlPartHeight * scrollPartProportion;
+      
+      if (cursorTopValue > 0) {
+        cursor.style.transform = `translateY(${cursorTopValue}px)`;
+        titresCursor.style.transform = `translateY(${cursorTopValue}px)`;
+      } else {
+        cursor.style.transform = `translateY(0px)`;
+        titresCursor.style.transform = `translateY(0px)`;
       }
     }
-  
-  
-    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-    // ICI IL Y A LE RAPPORT SCROLL / TIMELINE
-    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-  
-    function moveCursorFromScroll(currentPartIndex) {
-      if (!isScrollingFromGrab) {
-        let currentScroll = window.scrollY;
-        
-        let cursorTopValue = 0;
-        let tlPartHeight, tlPartBottom;
-        
-        for (let j = 0; j < partRects.length; j++) {
-          tlPartHeight = partRects[j].getBoundingClientRect().height
-          tlPartBottom = partRects[j].getBoundingClientRect().top - tlContainer.getBoundingClientRect().top;
-          cursorTopValue = tlPartBottom;
-          // get the amount of the current scrollpart scrolled
-          if (j === currentPartIndex) break;
-        }
-    
-        let currentScrollPartBottom = getSteps().scrollSteps[currentPartIndex - 1] ? getSteps().scrollSteps[currentPartIndex - 1] : 0;
-        let currentScrollPartHeight;
-        if (getSteps().scrollSteps[currentPartIndex + 1]) {
-          currentScrollPartHeight = getSteps().scrollSteps[currentPartIndex + 1] - currentScrollPartBottom;
-        } else {
-          currentScrollPartHeight = document.querySelector('body').scrollHeight - currentScrollPartBottom;
-        }
-        let currentScrollSincePartBottom = currentScroll - currentScrollPartBottom;
-        let scrollPartProportion = currentScrollSincePartBottom / currentScrollPartHeight;
-  
-        cursorTopValue = cursorTopValue + tlPartHeight * (tlPartHeight / tlPartHeight * (scrollPartProportion - 0.3));
-        
-        if (cursorTopValue > 0) {
-          cursor.style.transform = `translateY(${cursorTopValue}px)`;
-          titres.style.transform = `translateY(${cursorTopValue}px)`;
-        } else {
-          cursor.style.transform = `translateY(0px)`;
-          titres.style.transform = `translateY(0px)`;
-        }
-      }
+  }
+
+  function displayCurrentPartTitle(currentPartIndex) {
+    if (isNaN(currentPartIndex)) currentPartIndex = 0;
+    const currentTime = performance.now();
+    if (currentTime - lastCallTimestamp >= timestampDebounce) {
+      lastCallTimestamp = currentTime;
+      if (titresCursor) titresCursor.firstElementChild.innerText = getCurrentTime(titresFrise[currentPartIndex]?.el); // ICI POUR METTRE LE TEMPS BIEN
     }
-  
-    let prevPartIndex = 0;
-    let lastCallTimestamp = 0;
-  
-    function displayCurrentPartTitle(currentPartIndex) {
-      if (isNaN(currentPartIndex)) currentPartIndex = 0;
-      const currentTime = performance.now();
-      if (currentTime - lastCallTimestamp >= 400) {
-        lastCallTimestamp = currentTime;
-        titres.firstElementChild.innerText = getCurrentTime(titresFrise[currentPartIndex]?.el); // ICI POUR METTRE LE TEMPS BIEN
-        setTimeout(() => {
-          if (isWindowScrolling()) {
-            setTimeout(() => {
-              titres.firstElementChild.innerText = getCurrentTime(titresFrise[currentPartIndex]?.el);
-            }, 400);
-          }
-        }, 200);
-      }
-      let mainEl = titres.children[1];
-      let subEl = titres.lastElementChild;
-      if (mainEl.innerText != titresFrise[currentPartIndex]?.main || subEl.innerText != titresFrise[currentPartIndex]?.sub) {
-        mainEl.innerText = titresFrise[currentPartIndex]?.main;
-        subEl.innerText = titresFrise[currentPartIndex]?.sub;
-        partRects[prevPartIndex].style.width = '22px';
-        partRects[currentPartIndex].style.width = '32px';
-      }
-      activePartIndex = currentPartIndex;
-      prevPartIndex = currentPartIndex;
+    let mainEl = titresCursor.children[1];
+    let subEl = titresCursor.lastElementChild;
+    if (mainEl.innerText != titresFrise[currentPartIndex]?.main || subEl.innerText != titresFrise[currentPartIndex]?.sub) {
+      mainEl.innerText = titresFrise[currentPartIndex]?.main;
+      subEl.innerText = titresFrise[currentPartIndex]?.sub;
+      partRects[prevPartIndex].style.width = '22px';
+      partRects[currentPartIndex].style.width = '32px';
     }
-  
-    function getCurrentPartFromScroll() {
-      let currentScroll = window.scrollY;
-      for (let i = 0; i < getSteps().scrollSteps.length; i++) {
-        if (
-          (currentScroll + window.innerHeight / 2 >= getSteps().scrollSteps[i]
-          && currentScroll + window.innerHeight / 2 <= getSteps().scrollSteps[i + 1]) ||
-          (currentScroll + window.innerHeight / 2 >= getSteps().scrollSteps[i]
-          && i === getSteps().scrollSteps.length - 1)
-        ) {
-          return(i);
-        }
+    activePartIndex = currentPartIndex;
+    prevPartIndex = currentPartIndex;
+  }
+
+  function getCurrentPartFromScroll() {
+    let currentScroll = window.scrollY;
+    for (let i = 0; i < steps.scrollSteps.length; i++) {
+      if (
+        (currentScroll + window.innerHeight / 2 >= steps.scrollSteps[i]
+        && currentScroll + window.innerHeight / 2 <= steps.scrollSteps[i + 1]) ||
+        (currentScroll + window.innerHeight / 2 >= steps.scrollSteps[i]
+        && i === steps.scrollSteps.length - 1)
+      ) {
+        return(i);
       }
     }
-  
-    function getCurrentPartFromCursor(cursorTransformY) {
-      for (let i = 0; i < getSteps().tlElSteps.length; i++) {
-       if (cursorTransformY >= getSteps().tlElSteps[i] && cursorTransformY < getSteps().tlElSteps[i + 1]) {
-          return(i);
-        } else if (cursorTransformY > getSteps().tlElSteps[getSteps().tlElSteps.length - 1]) {
-          return(getSteps().tlElSteps.length - 1);
-       }
+  }
+
+  function getCurrentPartFromCursor(cursorTransformY) {
+    for (let i = 0; i < steps.tlElSteps.length; i++) {
+      if (cursorTransformY >= steps.tlElSteps[i] - steps.tlElSteps[0] && cursorTransformY < steps.tlElSteps[i + 1] - steps.tlElSteps[0]) {
+        return(i);
+      } else if (cursorTransformY > steps.tlElSteps[steps.tlElSteps.length - 1] - steps.tlElSteps[0]) {
+        return(steps.tlElSteps.length - 1);
       }
     }
-  
-    ///////////////////////////////////////
-    // ICI LE GETCURRENTTIME !!!!!!!!!!!!!!
-    ///////////////////////////////////////
-  
-    function getCurrentTime(titleEl) {
-      let nextRow = titleEl?.nextElementSibling;
-      if (!grabbing) {
-        while(nextRow) {
-          if (nextRow.offsetTop - window.innerHeight / 4 > window.scrollY &&
-              nextRow.classList.contains('isContentPart')) {
-                return(nextRow.firstElementChild.innerText);
-              }
-          nextRow = nextRow.nextElementSibling;
-        }
-      } else {
-        let cursor = document.querySelector('#cursor');
-        let allRowsUnder = [];
-        nextRow = nextRow.nextElementSibling.nextElementSibling;
-        while(nextRow) {
-          if (nextRow.classList.contains('isMainPart') || nextRow.classList.contains('isSubPart')) {
-            break;
-          }
-          allRowsUnder.push(nextRow);
-          nextRow = nextRow.nextElementSibling;
-        }
-        let currentRowIndex = Math.floor(allRowsUnder.length * getCursorPositionInTimelinePart(cursor).proportionInPart);
-        if (currentRowIndex - 20 >= 0) {
-          return allRowsUnder[currentRowIndex - 20].firstElementChild.innerText;
-        } else {
-          return allRowsUnder[0].firstElementChild.innerText;
+  }
+
+  function getCurrentTime(titleEl) {
+    let nextRow = titleEl?.nextElementSibling;
+    let allRowsUnder = [];
+    if (!grabbing) {
+      while(nextRow) {
+        if (nextRow.offsetTop - window.innerHeight / 4 > window.scrollY &&
+            nextRow.classList.contains('isContentPart')) {
+              return nextRow.firstElementChild.innerText;
+            }
+        allRowsUnder.push(nextRow.firstElementChild.innerText);
+        nextRow = nextRow.nextElementSibling;
+      }
+      return allRowsUnder[allRowsUnder.length-1];
+    } else {
+      let cursor = document.querySelector('#cursor');
+      if (nextRow.classList.contains('isSubPart')) nextRow = nextRow.nextElementSibling.nextElementSibling;
+      while(nextRow) {
+        if (nextRow.classList.contains('isMainPart') || nextRow.classList.contains('isSubPart')) {
+          break;
         }
+        allRowsUnder.push(nextRow.firstElementChild.innerText);
+        nextRow = nextRow.nextElementSibling;
       }
+      let currentRowIndex = Math.floor(allRowsUnder.length * getCursorPositionInTimelinePart(cursor).proportionInPart);
+      return allRowsUnder[currentRowIndex];
     }
+  }
+  
+
+  setPartTitlesInPartition();
+  setPartsColors();
+  getPartsTimes();
+
+  setTimeout(() => {
+    getAllHeights();
+    drawFriseRects();
+    displayTimelineTitles();
+    setupCursor();
+    drawFixedTitles();
+    setPartRects();
+    makeElementDraggable(cursor, titresCursor);
+    makeElementDraggable(titresCursor, cursor);
+    getSteps();
+  }, 100);
+
+
+
+  let resizeTimeout;
+
+  window.addEventListener('resize', () => {
+    tlContainer.innerHTML = '';
+    document.querySelector("#titres_frise")?.remove();
+    clearTimeout(resizeTimeout);
+    resizeTimeout = setTimeout(() => {
+      getAllHeights();
+      drawFriseRects();
+      displayTimelineTitles();
+      setupCursor();
+      setPartRects();
+      makeElementDraggable(titresCursor, cursor);
+      getSteps();
+    }, 100);
+  });
+
 }
 
 export { customTimeline };

+ 40 - 0
resources/styles/app.css

@@ -62,6 +62,41 @@
         z-index: 10;
       }
 
+      .tlRectPart {
+        width: 22px;
+        border-bottom: solid 1px #010d19;
+        border-top: solid 1px #010d19;
+        transition: width 0.3s ease-out;
+        cursor: pointer;
+      }
+
+      .tlFixedTitle {
+        position: fixed;
+        z-index: 1;
+        display: none;
+        opacity: 0;
+        transition: opacity 0.3s ease-out;
+        width: 10vw;
+        left: 60px;
+        font-size: 0.9em;
+        line-height: 1.2;
+      }
+
+      .tlFixedTitle p {
+        background-color: #010d19;
+      }
+
+      #titres_frise {
+        font-size: 0.9em;
+        background-color: rgba(1, 13, 25, 0.6);
+        z-index: 20;
+        position: fixed;
+        left: 60px;
+        width: 10vw;
+        line-height: 1.2;
+        margin-top: -8px;
+      }
+
       .isContentPart td:last-of-type {
         position: absolute;
         width: auto !important;
@@ -238,5 +273,10 @@
         .edit-button {
           transform: translateX(70px);
         }
+
+        thead::after {
+          left: auto;
+          right: 0 !important;
+        }
       }
 }

+ 1 - 1
resources/views/sections/header.blade.php

@@ -25,7 +25,7 @@
   <a class="brand text-center leading-7 whitespace-nowrap" href="{{ home_url('/') }}">
     <!-- {!! $siteName !!} -->
     <span class="font-caslon uppercase text-2xl">Partition<br></span>
-    <span class="font-caslon italic  text-3xl">Le Livre d'Image<br></span>
+    <span class="font-caslon italic  text-3xl">Le Livre d'image<br></span>
     <span class="font-caslon text-xl pr-1">de </span><span class="font-caslon text-2xl">Jean-Luc Godard</span>
   </a>