Portfolio
Tout comme le CV, le portfolio est complètement architecturé autour d'une base de données, qui définit les projets regroupés en groupes et classes. Ces deux derniers fournissent les menus et sous-menus. Chaque élément est assorti outre d'un libellé et d'un logo, d'une baseline (description courte) et d'un texte descriptif long qui peut contenir du HTML.
Enfin, chaque groupe ou projet peut être accompagné d'une liste d'éléments à afficher dans un slide-show en bas de page, le plus souvent des images, mais aussi du code source avec coloration syntaxique (directement produit des fichiers).
Certains types de blocs comme des blocs de détails ou des slide-show supplémentaires peuvent être insérés dans le HTML en base de données, leur logique étant codée dans le programme PHP principal.


Modèle Conceptuel de la base Portfolio
Code HTML/JavaScript/PHP du Portfolio

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="Portfolio.css">
    <link rel="stylesheet" type="text/css" href="MainMenu.css">
  </head>
  <body>

    <div style="display:flex;justify-content: center;">
      <div class="side"></div>

      <div id="MainPage">

        <script type="text/javascript">
var last_target="";

function close_detail()
{
  if (last_target!="")
  document.getElementById(last_target).style.display = 'none';
  return false;
}
function show_detail(el)
{
  close_detail();
  last_target=el;
  document.getElementById(last_target).style.display = 'block';
  return false;
}

var slideIndex = 1;

function plusDivs(n,slider="")
{
  showDivs(slideIndex += n,slider);
}

function showDivs(n,slider="") {
  var i;

  var slid_list=document.getElementById("slide_list"+slider);
  var x = slid_list.getElementsByClassName("slides");
  if  (x.length==0) return 0;
  var slid=document.getElementById("slide_header"+slider);
  if  (x.length==1)
  {
    x2=slid.getElementsByClassName("slide-button");
    for (i = 0; i < x2.length; i++) x2[i].style.display = "none";
  }
  if (n > x.length) {slideIndex = 1}
  else if (n < 1) {slideIndex = x.length} 
  else slideIndex=n;
  for (i = 0; i < x.length; i++) {
    x[i].style.display = "none";
  }
  slid.style.display = "flex";
  var img=x[slideIndex-1].cloneNode(true);
  img.style.display = "block";
  var slide_img=document.getElementById("slide_vid"+slider);
  var slide_img=document.getElementById("slide_img"+slider);
  slide_img.innerHTML="";
  slide_img.appendChild(img);
  document.getElementById("slide_content"+slider).innerHTML=slid_list.getElementsByClassName("slide-desc")[slideIndex-1].innerHTML;
}

function ScrollToSlider(){
  document.getElementById('slide_img').scrollIntoView();
}
        </script>

        <?php
require ($_SERVER['DOCUMENT_ROOT'].'/Inc/DB.inc.php');
$DBCnx=DBConnect();

function Comment($c)
{
  echo "<!--".$c."--!>".PHP_EOL;
}

function ListSliders($wher)
{
  global $DBCnx;
  Comment($wher);
  $result=$DBCnx->query("SELECT IMG,CODE_FILE,TEXT,COALESCE(SUB_SLIDER, '') AS SUB_SLIDER FROM PF_IMG WHERE ".$wher." ORDER BY SUB_SLIDER, ORD");
  echo '<div id="slide_list'.$slider.'">'.PHP_EOL;
  $slider="";
  $list_sliders=array();
  foreach($result as $res)
  {
    if ($res["SUB_SLIDER"]!=$slider)
    {
      $slider=$res["SUB_SLIDER"];
      $list_sliders[]=$slider;
      echo '</div>'.PHP_EOL;
      echo '<div id="slide_list'.$slider.'">'.PHP_EOL;
    }
    echo '<div class="slide-desc">'.$res["TEXT"].'</div>'.PHP_EOL;
    if ($res["IMG"]!=NULL) 
    {
      if (file_exists("Img/$res[IMG].mkv"))
        echo "<video id='my-video' controls class='slides slides-img' width='640' height='480' autoplay preload='auto' poster='Img/$res[IMG].png'><source src='Img/$res[IMG].mkv' type='video/MP4'>Your browser does not support the video tag.</video>".PHP_EOL;
      else
        echo "<img class='slides slides-img' src='Img/$res[IMG].png'>".PHP_EOL;
    }
    if ($res["CODE_FILE"]!=NULL)
    {
      echo '<div class="slides slides-codebox"><pre><code data-language="html">'.PHP_EOL;
      echo htmlentities (str_replace("\t", "  ", file_get_contents ($_SERVER['DOCUMENT_ROOT'].$res["CODE_FILE"])));
      echo '</code></pre></div>'.PHP_EOL;
    }
  }
  echo '</div>'.PHP_EOL;
  
  echo '<script type="text/javascript">'.PHP_EOL;
  $slider="";
  $imgid=$_GET["img"];
  if (empty($imgid))
    $imgid=1;
  echo "showDivs($imgid,'$slider');".PHP_EOL;
  foreach($list_sliders as $slider)
  {
    echo "showDivs(1,'$slider');".PHP_EOL;
  }
  if (!empty($_GET["img"]))
    echo "window.onload=ScrollToSlider;";
  echo '</script>';

}

function Main()
{
  global $DBCnx;
  echo '<ul id="MainMenu">';
  $clas=$DBCnx->query('SELECT ID,LABEL,IMG FROM PF_CLASSE ORDER BY ORD');
  foreach($clas as $cls)
  {
    echo '<li><a href="?cls='.$cls["ID"].'&grp=0"><div class="menu_item"><img src="'.$cls["IMG"].'.png">'.$cls["LABEL"].'</div></a><div class="sub">'.PHP_EOL;
    $group=$DBCnx->query('SELECT ID,LABEL,IMG FROM PF_GROUP WHERE ID_CLASSE='.$cls["ID"].' ORDER BY ORD');
    foreach($group as $grp)
    {
      echo '<a href="?cls='.$cls["ID"].'&grp='.$grp["ID"].'"><div class="menu_item"><img src="'.$grp["IMG"].'.png">'.$grp["LABEL"].'</div></a>'.PHP_EOL;
    }
    echo '</div></li>';
  }
  echo '</ul>'.PHP_EOL;
  echo '<div id="GroupPage">';
  $clsid=$_GET["cls"];
  $grpid=$_GET["grp"];
  $projid=$_GET["proj"];
  if ($clsid===NULL) $clsid=1;
  if ($grpid===NULL) $grpid=0;
  if ($projid===NULL) $projid=0;
  //echo 'classe='.$clsid.'  group='.$grpid.'  proj='.$projid;
  if ($grpid!=0)
  {
    $back='cls='.$clsid;
    if ($projid!=0) $back=$back.'&grp='.$grpid;
  }
  else
    $back='cls=1';
  if ($projid==0)
  {
    if ($grpid==0)
    {
      $result=$DBCnx->query('SELECT IMG,LABEL,BASELINE,TEXT FROM PF_CLASSE WHERE ID='.$clsid.' ORDER BY ORD');
    }
    else
    {
      $result=$DBCnx->query('SELECT IMG,LABEL,BASELINE,TEXT FROM PF_GROUP WHERE ID='.$grpid.' ORDER BY ORD');
    }
  }
  else
  {
    $result=$DBCnx->query('SELECT IMG,LABEL,BASELINE,TEXT FROM PF_PROJECT WHERE ID='.$projid.' ORDER BY ORD');
  }
  foreach($result as $res)
  {
    echo '<div class="header"><span style="display:flex;align-items: center"><img src="'.$res["IMG"].'.png"><div class="title"';
    if (strlen($res["LABEL"].$res["BASELINE"])>40) 
      echo ' style="max-width:250px"';
    echo '>'.$res["LABEL"].'</div></span><span class="baseln">'.$res["BASELINE"].'</span>';
    if ($clsid!=1)
      echo '<a href="/Portfolio/?'.$back.'"><IMG src="Back.png"></a>';
    else
      echo '<br>';
    
    echo '</div><div class="content">'.$res["TEXT"].'</div></div>'.PHP_EOL;
  }
  if ($projid==0)
  {
    if ($grpid==0)
    {
      $grp_proj=0;
      $result=$DBCnx->query('SELECT ID,IMG,LABEL,BASELINE FROM PF_GROUP WHERE ID_CLASSE='.$clsid.' ORDER BY ORD');
    }
    else
    {
      $grp_id=$grpid;
      $grp_proj=1;
      $result=$DBCnx->query('SELECT ID,IMG,LABEL,BASELINE FROM PF_PROJECT WHERE ENABLED AND ID_GROUP='.$grpid.' ORDER BY ORD');
    }
    foreach($result as $res)
    {
      if ($grp_proj==0)
      $grp_id=$res["ID"];
      else
      $proj_id=$res["ID"];
      echo '<a href="/Portfolio/?cls='.$clsid.'&grp='.$grp_id.'&proj='.$proj_id.'" class="a_topic"><div class="topic"><img src="'.$res["IMG"].'.png"><div class="topic_title">'.$res["LABEL"].'</div><div class="topic_baseln_center"><div class="topic_baseln">'.$res["BASELINE"].'</div></div></div></a>'.PHP_EOL;
    }
  }
  echo '<br><div id="slide_header" class="slide_header"><button class="slide-button " onclick="plusDivs(-1)">&#10094;</button><div id="slide_content" class="slide_content"></div>';
  echo '<button class="slide-button " onclick="plusDivs(+1)">&#10095;</button></div><br><div id="slide_img" class="display-container"></div>';
  if ($projid!=0)
  {
    ListSliders(" ID_PROJECT=".$projid);
  } else
  {
    ListSliders(" ID_GROUP=".$grpid);
  }
}

Main();
        ?>
        <link href="/Rainbow/dreamweaver.css" rel="stylesheet" type="text/css">
        <script src="/Rainbow/rainbow-custom.min.js"></script>
        <div class="bottom"></div>
      </div>
      <div class="side"></div>

    </div>
  </body>
</html>