Carousel

EH TOI LÀ !

Cette page est utilisée en interne par le Wiki SCP,

MERCI DE NE PAS MODIFIER CETTE PAGE
SANS LA PERMISSION DU STAFF.


[[iftags +theme]]

What this is

A bunch of miscellaneous CSS 'improvements' that I, CroquemboucheCroquembouche, use on a bunch of pages because I think it makes them easier to deal with.

If you're not me, which you're not (I think), then you probably shouldn't use this component because it may break, disappear, or change in a way that you don't like at any time; and I promise you that if I want to add something to this I will without asking your permission or checking whether or not it breaks your article. If you're cool with that, go wild.

The styling from this component doesn't change the look or feel of a page, so it's not important narratively. I wouldn't expect translations of articles that use this component to also use this component, unless the translator likes it.

Other personal styling components:

Personal styling themes:

Usage

[[include :scp-wiki:component:croqstyle ]]

Using this on a page tagged 'template'? You'll need to manually stop all these usage instructions from appearing:

[[div style="display: none;"]]
[[include :scp-wiki:component:croqstyle ]]
[[/div]]

Improvements

Reasonably-sized footnotes

Stops footnotes from being a million miles wide, so that you can actually read them.

.hovertip { max-width: 400px; }

I'd add a demonstration, but I've included this component to a bunch of other template pages and it messes them up. You'll just have to trust me on this one.

Monospace edit/code

Makes the edit textbox monospace, and also changes all monospace text to Fira Code, the obviously superior monospace font.

@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap');
 
:root { --mono-font: "Fira Code", Cousine, monospace; }
#edit-page-textarea, .code pre, .code p, .code, tt, .page-source { font-family: var(--mono-font); }
.code pre * { white-space: pre; }
.code *, .pre * { font-feature-settings: unset; }

Teletype backgrounds

Adds a light grey background to <tt> elements ({{text}}), so code snippets stand out more.

tt {
  background-color: var(--swatch-something-idk-will-fix-later, #f4f4f4);
  font-size: 85%;
  padding: 0.2em 0.4em;
  margin: 0;
  border-radius: 6px;
}

No more bigfaces

Stops big pictures from appearing when you hover over someone's avatar image, because they're stupid and really annoying.

.avatar-hover { display: none !important; }

Breaky breaky

Stuff wrapped in a .nobreak div or span line-wraps betweene every letter.

.nobreak { word-break: break-all; }

Code colours

Add my terminal's code colours as variables. Maybe I'll change this to a more common terminal theme like Monokai or something at some point, but for now it's just my personal theme, which is derived from Tomorrow Night Eighties.

Also, adding the .terminal class to a fake code block as [[div class="code terminal"]] gives it a sort of pseudo-terminal look with a dark background. Doesn't work with [[code]], because Wikidot inserts a bunch of syntax highlighting that you can't change yourself without a bunch of CSS. Use it for non-[[code]] code snippets only.

:root {
  --c-bg: #393939;
  --c-syntax: #e0e0e0;
  --c-comment: #999999;
  --c-error: #f2777a;
  --c-value: #f99157;
  --c-symbol: #ffcc66;
  --c-string: #99cc99;
  --c-operator: #66cccc;
  --c-builtin: #70a7df;
  --c-keyword: #cc99cc;
}
 
.terminal.code, .terminal > .code {
  color: var(--c-syntax);
  background: var(--c-bg);
  border: 0.5rem solid var(--c-comment);
  border-radius: 2rem;
}

Debug mode

Draw lines around anything inside .debug-mode. The colour of the lines is red but defers to CSS variable --debug-colour.

You can also add div.debug-info.over and div.debug-info.under inside an element to annotate the debug boxes — though you'll need to make sure to leave enough vertical space that the annotation doesn't overlap the thing above or below it.

…like this!

.debug-mode, .debug-mode *, .debug-mode *::before, .debug-mode *::after {
  outline: 1px solid var(--debug-colour, red);
  position: relative;
}
.debug-info {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-family: 'Fira Code', monospace;
  font-size: 1rem;
  white-space: nowrap;
}
.debug-info.over { top: -2.5rem; }
.debug-info.under { bottom: -2.5rem; }
.debug-info p { margin: 0; }

[[/iftags]]

Qu'est-ce que c'est ?

Un code pour créer un carrousel d'images, qui en fait défiler une série au lieu de simplement en afficher une.

Utilisation

Collez ce code au lieu de celui du bloc d'image standard là où vous voulez utiliser le carrousel d'images.

Assurez-vous d'avoir téléversé toutes les images utilisées sur la page. Si vous voulez ignorer ce sage conseil et ne les téléverser qu'après avoir ajouté le carrousel, vos images ne marcheront pas avant un rafraîchissement complet de la page (Ctrl+Maj+R).

[[include component:carousel
| images=photo.png,vieille-carte.png,screamer.gif
| caption=Une sélection d'images.
| interval=5
| wiki=fondationscp
| page=SCP-173
| width=300px
| height=240px
| position=right
| no-caption=false
| background=white
| options=yes
]]

Ce que fait chaque option

Tout ce qui est en italique est optionnel. Le reste est obligatoire.

Si vous omettez un paramètre optionnel, elle aura sa valeur par défaut. Si vous omettez un paramètre non optionnel, le carrousel ne marchera pas correctement.

images : Une liste des noms des fichiers image à afficher, séparés par des virgules. Assurez-vous que toutes sont téléversées sur la page avec le bon nom.
Ces images apparaîtront dans le carousel dans l'ordre où vous les listez.
caption :
(Optionnel)
La légende qui va sous le carrousel.
Si vous n'utilisez pas de légende, assurez-vous de mettre "true" après le paramètre no-caption.
Valeur par défaut : "{$caption}"
interval :
(Optionnel)
Si vous définissez cette valeur à un nombre positif, le carrousel passera automatiquement à l'image suivante après ce nombre de secondes.
Si l'utilisateur a cliqué sur une flèche pour changer manuellement d'image ou si sa souris est placée au-dessus du carrousel, l'image ne défilera pas.
Valeur par défaut : "0"
wiki : Le nom du wiki où vous utilisez le carrousel. Par exemple, fondationscp ou sandboxscpfr.
page : Le nom de la page où vous voulez placer le carrousel. Incluez la catégorie s'il y en a une.
width :
(Optionnel)
La largeur de la plus large image du carrousel.
Valeur par défaut : "300px"
height :
(Optional)
La hauteur de la plus haute image du carrousel.
Valeur par défaut dépendant du navigateur
position :
(Optionnel)
Où vous voulez le placer sur votre page : "left" pour l'aligner à gauche, "right" pour à droite et "center" pour au milieu.
Valeur par défaut : "right"
no-caption :
(Optionnel)
Définissez ce paramètre sur "true" i vous ne voulez pas de légende. Sinon, laissez-le vide, définissez-le sur "false", laissez-le vide ou enlevez-le simplement.
Valeur par défaut : "false"
background :
(Optionnel)
La couleur d'arrière-plan derrière les images, en anglais ou en code hexadécimal.
Valeur par défaut : "transparent"
options :
(Optionnel)
Est-ce que gous voulez afficher les options avancées (bouton arrêt/défilement et les petits cercles qui indiquent la position dans la série d'images) ? Si non, définissez ce paramètre sur n'importe quoi d'autre que "yes" (même des noms de meubles Ikea).
Valeur par défaut : "yes"

Je veux afficher le carrousel sur toute la largeur de la page !
Définissez width sur "100%" et position sur "center".

J'ai défini la largeur/hauteur à la taille de ma plus grande image mais c'est beaucoup trop grand !
Choisissez un plus petit nombre ou réduisez la taille de vos images.



Code

Structure HTML du carrousel

<html ng-app="carousel" ng-controller="CarouselController">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
  <script src="https://fondationscp.wikidot.com/local--code/component%3Acarousel/2"></script>
  <link href="https://d3g0gp89917ko0.cloudfront.net/v--edac79f846ba/common--theme/base/css/style.css" rel="stylesheet">
  <link href="https://www.fondationscp.wikidot.com/component:theme/code/1" rel="stylesheet">
  <link href="https://fondationscp.wikidot.com/local--code/component%3Acarousel/4" rel="stylesheet">
</head>
<body>
  <div class="wrapper" id="background">
    <div class="carousel">
      <div class="horsie" ng-repeat="image in images track by $index"
           ng-class="[index > $index ? 'past' : null,
                      index === $index ? 'present' : null,
                      index < $index ? 'future' : null]">
        <img ng-src="{{image}}">
      </div>
    </div>
    <div class="arrow decrementor"
         ng-class="index === 0 ? 'inactive' : 'active'"
         ng-click="increment(-1)">
      <div class="image"></div>
    </div>
    <div class="arrow incrementor"
         ng-class="index === images.length-1 ? 'inactive' : 'active'"
         ng-click="increment(1)">
      <div class="image"></div>
    </div>
    <div class="bubble-holder" ng-class="[options === 'yes' ? null : 'invisible']">
      <div class="bubble" ng-repeat="image in images track by $index"
           ng-class="[index === $index ? 'present' : null]"
           ng-click="selectImage($index)">
      </div>
    </div>
    <div class="control play" ng-click="control('play')"
         ng-class="[state === 'play' ? 'active' : null,
                    options === 'yes' ? null : 'invisible']"></div>
    <div class="control pause" ng-click="control('pause')"
         ng-class="[state === 'pause' ? 'active' : null,
                    options === 'yes' ? null : 'invisible']"></div>
  </div>
</body>
</html>

JS pour faire fonctionner le carrousel

function getQueryVariable(variable) {
  var query = document.location.href.match(/\?.*$/g)[0].substring(1);
  var vars = query.split("&");
  for(var i = 0; i < vars.length; i++) { // >
    var pair = vars[i].split("=");
    if(pair[0] === variable) return pair[1];
  }
  return false;
}
 
(function(){
  var carousel = angular
    .module('carousel',[])
    .controller('CarouselController',CarouselController);
 
  CarouselController.$inject = ['$scope','$timeout'];
  function CarouselController($scope,$timeout){
    $scope.images = getQueryVariable("images").split(",");
    var wiki = getQueryVariable("wiki") || "scp-wiki";
    var page = getQueryVariable("page");
 
    for(var i = 0; i < $scope.images.length; i++) { // >
      $scope.images[i] = `https://${wiki}.wdfiles.com/local--files/${page}/${$scope.images[i]}`;
    }
    // $scope.images is an array of image URLs
 
    $scope.index = 0;
    $scope.increment = function(amount) {
      if(amount > 0 && $scope.index < $scope.images.length-1) {
        $scope.index += amount;
      }
      if(amount < 0 && $scope.index > 0) {
        $scope.index += amount;
      }
      $scope.state = "pause";
    }
 
    var interval = getQueryVariable("interval") || 0;
    if(interval === "{$interval}") interval = 0;
    $scope.state = "play";
    if(interval === 0) $scope.state = "pause";
    function oscillate() {
      $timeout(function() {
        if(!mouseover && $scope.state === "play") {
          if($scope.index < $scope.images.length-1) {
            $scope.index++;
          } else {
            $scope.index = 0;
          }
        }
        if($scope.state === "play") {
          oscillate();
        }
      }, interval*1000, true);
    }
 
    var mouseover = false;
    document.documentElement.onmouseover = function () {
      mouseover = true;
    }
    document.documentElement.onmouseout = function () {
      mouseover = false;
    }
 
    if($scope.state === "play") {
      oscillate();
    }
    document.getElementById('background').style.background = getQueryVariable("background");
 
    $scope.selectImage = function(index) {
      $scope.index = index;
      $scope.state = "pause";
    }
 
    $scope.control = function(direction) {
      switch(direction) {
        case "play":
          $scope.state = "play";
          oscillate();
          break;
        case "pause":
          $scope.state = "pause";
          break;
      }
    }
 
    $scope.options = getQueryVariable("options");
    if($scope.options === "{$options}") $scope.options = "yes";
  }
})();

Styles de la boîte de légende

.carousel-container { position: relative; z-index: 1; float: right; margin: 0 1em 1em 1em; }
.carousel-container.left { float: left; }
.carousel-container.center { float: none; clear: both; margin: 0 auto 1em auto; }
.carousel-container iframe { position: relative; z-index: 2; width: 334px; border: none; }
.carousel-container .carousel-caption { position: relative; background-color: #eee; border: solid 1px #666; padding: 2px 0; font-size: 80%; font-weight: bold; text-align: center; width: 300px; margin-top: -3px; box-shadow: 0 1px 6px rgba(0,0,0,.25); z-index: 3; max-width: 675px; }
 
#page-content .carousel-container .carousel-caption-wrapper { max-width: 673px; }
 
.carousel-container .carousel-caption-wrapper { padding: 0 16px; }
.carousel-container .carousel-caption p { margin: 0; padding: 0 10px; }
.carousel-container .carousel-caption.true { display: none; }

Styles du reste du carrousel

html { width: calc(100% - 32px); height: calc(100% - 4px); margin: 0; padding: 0; }
body { width: 100%; height: 100%; margin: 0; padding: 2px 16px; background: transparent; }
.wrapper { position: relative; width: 100%; height: 100%; }
.carousel { position: relative; width: calc(100% - 2px); height: calc(100% - 2px); overflow-x: hidden; border: 1px solid #666; box-shadow: 0 1px 6px rgba(0,0,0,.25); box-sizing: content-box; }
.horsie { position: absolute; height: 100%; width: 100%; top: 0; left: 0; transform: translate(0,0); transition: transform 0.3s ease-in-out; }
.horsie img { object-fit: contain; width: 100%; height: 100%; }
.horsie.past { transform: translate(-100%,0); }
.horsie.future { transform: translate(100%,0); }
.arrow { height: 30px; width: 30px; border: 1px solid #666; border-radius: 50%; position: absolute; top: 50%; background: #eee; box-shadow: 0 1px 6px rgba(0,0,0,.25); cursor: pointer; }
.arrow .image { height: 30px; width: 30px;position: absolute; top: 0; left: 0; background-position: 50% 50%; background-size: 80% 80%; background-repeat: no-repeat; opacity: 0.6; transition: opacity 0.1s ease-in-out; }
.arrow.inactive { cursor: default; }
.arrow.inactive .image { opacity: 0; }
.decrementor { left: 0; transform: translate(-50%,-50%); }
.decrementor .image { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAQAAABLCVATAAAAdElEQVR4AezQJwKAMBQD0DCOjAfD9j1BXVUdR0OxkWzCJvHvD/x5aVxEDMZBWVfAIDB1JQwOY96IUSzGYjCaxdgMJuMwOQJ4c51jlnc0HgsCUs5pPbX82csozaQsFqVuSpksSjIpg0OJBdACqlorw7AEowAAblWUrl8sD5AAAAAASUVORK5CYII='); }
.incrementor { right: 0; transform: translate(50%,-50%); }
.incrementor .image { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAQAAABLCVATAAAAcUlEQVR4Ae3QpwJAUACF4WM+sU6xV9M0TdI8mmR389j+07878PfSHOjYnYAETTdtP5Sh4VAik8pZlMSkChYlM6mSRalLKWN2FqolVLNqGgsyOE/zOZ+9i5FZTMFgJBaT34gRWUzGYAABKYMZizvm75W1TreU8DMmtioAAAAASUVORK5CYII='); }
.bubble-holder { display: flex; position: absolute; width: calc(100% - 60px); height: 20%; justify-content: center; align-items: flex-end; flex-wrap: wrap; align-content: flex-end; bottom: 0; margin: 5px 0; left: 30px; }
.bubble { border: 2px solid #666; height: 0; width: 0; margin: 5px; border-radius: 50%; transition: all 0.2s ease-in-out; background-color: white; }
.bubble.present { height: 2px; width: 2px; background-color: white; margin: 4px; }
.bubble-holder:hover .bubble { height: 6px; width: 6px; margin: 2px; cursor: pointer; }
.bubble-holder:hover .bubble.present { height: 12px; width: 12px; margin: -1px; }
.control { position: absolute; height: 10px; width: 10px; left: 5px; bottom: 5px; background-size: contain; opacity: 0.3; cursor: pointer; }
.control.active { opacity: 1; cursor: default; }
.control.play { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAQAAABLCVATAAAAgElEQVR4Ae2UQRWAIBBEJwIRjGAEI9hEG0ATaaINtIE0kAbqnrh4/M/Tzr//B7A78nzF0wvKraiAiF5ODYzIWBQIkXFpZETGqo4R2bkmRmTs6hmRERUIURsKQNSGAhBlQlSYqyXisQ/i+6tmYiA3YkUqs7SZqJHCFFtS+Lf8PZ4HilOsPBFiYmoAAAAASUVORK5CYII='); }
.control.pause { left: 20px; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAOUlEQVR4Ae3WoQ0AMAwDwY7ezdsFzKyg3EthBgdzJCl309X7opev3wMBAQEtAQEBAQEBAU09+ZL0AdrO+xGDE6h0AAAAAElFTkSuQmCC'); }
.invisible { display: none; }
Sauf mention contraire, le contenu de cette page est protégé par la licence Creative Commons Attribution-ShareAlike 3.0 License