Slider - Vanilla JS

horizontal Slider

horizontal Fader

vertical Slider

Slider auf JavaScript Basis habe ich schon einige geschrieben, nun aber versuche ich es mit einem anderen Ansatz, für das Sliden möchte ich das über CSS gestaltete Scrollen nutzen, dadurch ist die Umsetzung der Touch- und Wheel-Events nicht erforderlich, da es im Standard schon funktioniert.

Als Methoden zur Animierung sollen dann zusätzlich zum Wischen und Mousewheel/Mouspad (2-Finger), noch Pfeile (vorwärts/rückwärts), Bubbes (Punkte zur Steuerung und Anzeige aktiver Slide) oder Thumbnails (Bilder zur Steuerung und Anzeige aktiver Slide) und eine Autoplay Funktion (optional mit Play & Pause Button).

Das Sliden soll in horizontaler aber auch vertikaler Richtung funktionieren und Hintergrund-Bilder unterstützen.

Für ältere Browser wie den Internet Explorer habe ich noch den smooth scroll über requestAnimationFrame realisiert.

  • class="slider" : assign this object
  • class="horizontal" : horizontal Slider
  • class="vertical" : vertical Slider
  • class="arrows-outside" : position of arrows outside the slider
  • class="fade" : use fading not slide to change item
  • class="ratio44" : use aspect ratio of 44%, for silder with no content only background images
  • data-options="bubbles" : display small active links (for example circles) for navigation
  • data-options="thumbs" : display small active thumbnails for navigation
  • data-options="arrows" : display arrows to navigate
  • data-options="autoplay" : use interval to change slide
  • data-options="play_pause" : display play/pause button to interrupt sliding
  • data-options="loop" : loop endless default disabled (on autoplay also loop is enabled)
  • data-interval="3000" : time for autoplay to move to next slide
HTML:
slider.htm HTML (1,76 kByte) 11.12.2021 14:19
<!DOCTYPE html >
<html lang="de">
  <head>
    <meta charset="utf-8" />
    <title>Slider/Fader</title>
    <link rel="stylesheet" id="slider.css" href="slider.css" />
  </head>
  <body>
    <h4>horizontal Slider</h4>
    <div class="slider horizontal ratio44" data-options="thumbs arrows">
      <ul>
        <li data-backgroundimage="/media/IMG_6867.jpg"></li>
        <li data-backgroundimage="/media/IMG_6868.jpg"></li>
        <li data-backgroundimage="/media/IMG_6869.jpg"></li>
        <li data-backgroundimage="/media/IMG_6870.jpg"></li>
        <li data-backgroundimage="/media/IMG_6871.jpg"></li>
        <li data-backgroundimage="/media/IMG_6872.jpg"></li>
      </ul>
    </div>
    <h4>horizontal Fader</h4>
    <div class="slider fade horizontal arrows-outside ratio44" data-options="thumbs arrows autoplay play_pause">
      <ul>
        <li data-backgroundimage="/media/IMG_6867.jpg"></li>
        <li data-backgroundimage="/media/IMG_6868.jpg"></li>
        <li data-backgroundimage="/media/IMG_6869.jpg"></li>
        <li data-backgroundimage="/media/IMG_6870.jpg"></li>
        <li data-backgroundimage="/media/IMG_6871.jpg"></li>
        <li data-backgroundimage="/media/IMG_6872.jpg"></li>
      </ul>
    </div>
    <h4>vertical Slider</h4>
    <div class="slider vertical ratio44" data-options="thumbs arrows autoplay">
      <ul>
        <li data-backgroundimage="/media/IMG_6867.jpg"></li>
        <li data-backgroundimage="/media/IMG_6868.jpg"></li>
        <li data-backgroundimage="/media/IMG_6869.jpg"></li>
        <li data-backgroundimage="/media/IMG_6870.jpg"></li>
        <li data-backgroundimage="/media/IMG_6871.jpg"></li>
        <li data-backgroundimage="/media/IMG_6872.jpg"></li>
      </ul>
    </div>
    <script src="slider.js"></script>
  </body>
</html>
JavaScript:
slider.js JavaScript (15,13 kByte) 04.01.2022 18:32
// coding: utf-8
/*! Created by: Udo Schmal | https://www.gocher.me/ */
(function() {
  'use strict';

  function Slider(el) {
    var slider = el; // slider div
    var slides = el.querySelector('ul'); // slides ul list
    if (!slides.classList.contains('slides')) {
      slides.classList.add('slides');
    }
    var items = slides.children; // slides li items
    if (items.length > 1) {
      var controls = null; // bubbles/thumbs ul list
      var controlItems = []; // bubbles/thumbs li items
      var prev = null; // previous div button
      var next = null; // next div button
      var play = null; // play and pause div button
      var active = 0; // active slide position counter
      var slideshow = null;
      var isAuto = true; // is triggered by autoplay event

      // get settings from dom
      var direction = el.classList.contains('vertical') ? 'vertical' : 'horizontal';
      if ((direction == 'horizontal') && !el.classList.contains('horizontal')) {
        el.classList.add('horizontal');
      }
      var fade = el.classList.contains('fade');
      var thumbs = false, bubbles = false, autoplay = false, arrows = false, playpause = false, loop = false;
      if (el.dataset.options) {
        thumbs = el.dataset.options.indexOf('thumbs') !== -1;
        bubbles = el.dataset.options.indexOf('bubbles') !== -1;
        autoplay = el.dataset.options.indexOf('autoplay') !== -1;
        arrows = el.dataset.options.indexOf('arrows') !== -1;
        playpause = el.dataset.options.indexOf('play_pause') !== -1;
        loop = autoplay || (el.dataset.options.indexOf('loop') !== -1);
      }
      var interval = 3000;
      if (autoplay) {
        if (el.dataset.interval) {
          interval = parseInt(el.dataset.interval, 10);
          if (isNaN(interval)) {
            interval = 3000;
          }
        }
      }

      // set background image if no viewport support
      for(let i = 0; i < items.length; i++) {
        if (items[i].dataset.backgroundimage) {
          items[i].style.backgroundImage = "url('" + items[i].dataset.backgroundimage + "')";
        }
      }

      function activate (itemId) {
        isAuto = true;
        if (fade) {
          // fade in/out
          if (itemId >= items.length) {
            itemId = 0;
          } else if (itemId < 0) {
            itemId = items.length-1;
          }
          for (let i = 0; i < items.length; i++) {
            if (i == itemId) {
              items[i].classList.add('active');
              if (controls) {
                controlItems[i].classList.add('active');
              }
              active = i;
            } else {
              items[i].classList.remove('active');
              if (controls) {
                controlItems[i].classList.remove('active');
              }
            }
          }
        } else {
          // scroll into parent view
          el = items[itemId];
          if ('scrollBehavior' in document.documentElement.style) {
            slides.scrollTo({top: el.offsetTop, left: el.offsetLeft, behavior: 'smooth'});
          } else {
            slides.style.scrollSnapType = 'none';
            var top = el.offsetTop, left = el.offsetLeft, parent = el.parentNode, attr;
            attr = (direction == 'vertical' ? 'scrollTop' : 'scrollLeft');
            var from = parent[attr] || 0, to = (attr == 'scrollLeft' ? left : top);
            if (from == to) { return; }
            var start = Date.now();
            var tick = function () {
              var t = Math.min(1, ((Date.now() - start) / 1000));
              var eased =  t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1;
              var val = (eased * (to - from)) + from;
              parent[attr] = Math.floor(val);
              if (t<1) {
                window.requestAnimationFrame(tick);
              } else {
                slides.style.scrollSnapType = '';
              }
            };
            tick();
          }
        }
      }

      // add slide and snap scroll event (touch event)
      var scrollTimer;
      function startScroll() {
        if (isAuto) {
          isAuto = false;
        } else {
          if (slideshow) {
            pauseSlideshow();
          }
        }
        for (let i = 0; i < items.length; i++) {
          items[i].classList.remove('active');
          if (controls) {
            if (loop) {
              if (i>0 && i<items.length-1) {
                controlItems[i-1].classList.remove('active');
              }
            } else {
              controlItems[i].classList.remove('active');
            }
          }
        }
      }
      function stopScroll() {
        clearTimeout(scrollTimer);
        scrollTimer = null;
        // find new active slide
        let slidesCenter = {
          y: slides.scrollTop + slides.offsetHeight/2,
          x: slides.scrollLeft + slides.offsetWidth/2
        };
        for (let i = 0; i < items.length; i++) {
          if (items[i].offsetTop < slidesCenter.y &&
              items[i].offsetTop + items[i].offsetHeight > slidesCenter.y &&
              items[i].offsetLeft < slidesCenter.x &&
              items[i].offsetLeft + items[i].offsetWidth > slidesCenter.x) {
            let u = i;
            if (loop) {
              if (u == 0) {
                u = items.length-2;
              } else if (u == items.length-1) {
                u = 1;
              }
            }
            if (controls) {
              if (loop) {
                controlItems[u-1].classList.add('active');
              } else {
                controlItems[u].classList.add('active');
              }
            }
            if (!loop && arrows) {
              prev.style.display = (u == 0) ? 'none' : 'block';
              next.style.display = (u == items.length-1) ? 'none' : 'block';
            }
            items[u].classList.add('active');
            if (i != u) {
              isAuto = true;
              slides.style.scrollBehavior = 'auto';
              slides.scrollTo(items[u].offsetLeft, items[u].offsetTop);
              slides.style.scrollBehavior = '';
            }
            active = u;
            break;
          }
        }
      }
      function sliderScroll(event) {
        if (scrollTimer) {
          clearTimeout(scrollTimer);
        } else {
          startScroll();
        }
        scrollTimer = setTimeout(stopScroll, 100);
      }
      slides.addEventListener('scroll', sliderScroll);

      // add slideshow
      var restartTimer;
      var startSlideshow = function () {
        if (restartTimer) {
          clearTimeout(restartTimer);
        }
        if (!slideshow) {
          slideshow = setInterval(function () {
            if (active+1 < items.length) {
              activate(++active);
            } else {
              activate(0);
            }
          }, interval);
        }
      }
      this.start = function () {
        if (!slideshow) {
          startSlideshow();
        }
      };
      var stopSlideShow = function () {
        if (slideshow) {
          clearInterval(slideshow);
          slideshow = null;
        }
      }
      this.stop = function () { stopSlideShow(); };
      function pauseSlideshow () {
        if (slideshow) {
          clearInterval(slideshow);
          slideshow = null;
          restartTimer = setTimeout(startSlideshow, 5000);
        };
      }
      function toggleSlideshow (event) {
        if (play.classList.contains('play')) {
          startSlideshow();
          slider.dataset.stop = 'false';
          play.classList.remove('play');
          play.classList.add('pause');
        } else {
          stopSlideShow();
          slider.dataset.stop = 'true';
          play.classList.remove('pause');
          play.classList.add('play');
        }
        event.stopPropagation();
      }

      // add play and pause button
      if (playpause) {
        play = document.createElement('div');
        play.className = autoplay ? 'pause' : 'play';
        play.setAttribute('tabindex', '0');
        play.addEventListener('click', toggleSlideshow);
        el.appendChild(play);
      }

      // add mouse event listeners
      var posInitial, posLast, diff, threshold = 100;
      function dragStart(event) {
        diff = 0;
        event.preventDefault();
        if (direction == 'horizontal') {
          posInitial = slides.scrollLeft;
          posLast = event.clientX;
        } else {
          posInitial = slides.scrollTop;
          posLast = event.clientY;
        }
        slides.style.scrollSnapType = 'none';
        document.addEventListener('mouseup', dragEnd);
        slides.addEventListener('mousemove', dragAction);
      }
      function dragAction(event) {
        if (direction == 'horizontal') {
          diff = diff + (posLast - event.clientX);
          posLast = event.clientX;
          slides.scroll(posInitial + diff, 0);
        } else {
          diff = diff + (posLast - event.clientY);
          posLast = event.clientY;
          slides.scroll(0, posInitial + diff);
        }
      }
      function dragEnd(event) {
        slides.style.scrollSnapType = '';
        if (diff < -threshold) {
          activate(active-1);
        } else if (diff > threshold) {
          activate(active+1);
        } else {
          if (direction == 'horizontal') {
            slides.scroll(posInitial, 0);
          } else {
            slides.scroll(0, posInitial);
          }
        }
        document.removeEventListener('mouseup', dragEnd);
        slides.removeEventListener('mousemove', dragAction);
      }
      slides.addEventListener('mousedown', dragStart, true);

      // add control bubbles/thumbs
      if (bubbles || thumbs) {
        controls = document.createElement('ul');
        controls.classList.add('controls');
        controls.classList.add(thumbs ? 'thumbs' : 'bubbles');
        el.appendChild(controls);
        function controlClick(event) {
          if (autoplay) {
            pauseSlideshow();
          }
          let slide = this.dataset.slide;
          // respect clone slides
          if (!fade && loop) {
            slide++;
          }
          activate(slide);
        }
        for(let i = 0; i < items.length; i++) {
          let li = document.createElement('li');
          li.dataset.slide = i;
          li.setAttribute('tabindex', '0');
          if (thumbs) {
            let file = null;
            if (items[i].dataset.thumbimage) {
              file = items[i].dataset.thumbimage;
            } else if (items[i].dataset.backgroundimage) {
              file = items[i].dataset.backgroundimage;
            } else {
              let img = items[i].querySelector('img');
              if (img) {
                if (img.src && (img.src != 'data:,')) {
                  file = img.src;
                } else if (img.dataset.src) {
                  file = img.dataset.src;
                }
              }
            }
            if (file) {
              // load thumbnails
              //file = file.substr(0, file.lastIndexOf('.')) + '~120' + file.substr(file.lastIndexOf('.'));
              li.style.backgroundImage = "url('" + file + "')";
            }
          }
          li.addEventListener('click', controlClick);
          controls.appendChild(li);
        }
        controlItems = controls.children;
        controlItems[active].classList.add('active');
      }

      // add previous and next button
      if (arrows) {
        prev = document.createElement('div');
        prev.className = 'prev';
        prev.setAttribute('tabindex', '0');
        function prevClick() {
          if (autoplay) {
            pauseSlideshow();
          }
          activate(active-1);
        }
        prev.addEventListener('click', prevClick);
        el.appendChild(prev);

        next = document.createElement('div');
        next.className = 'next';
        next.setAttribute('tabindex', '0');
        function nextClick() {
          if (autoplay) {
            pauseSlideshow();
          }
          activate(active+1);
        }
        next.addEventListener('click', nextClick);
        el.appendChild(next);
      }

      if (fade || !loop) {
        active = 0;
        if (arrows && !loop) {
          prev.style.display = 'none';
        }
      } else {
        // clone slides
        slides.appendChild(items[0].cloneNode(true));
        slides.insertBefore(items[items.length-2].cloneNode(true), items[0]);
        items[0].classList.add('clone');
        items[items.length-1].classList.add('clone');
        // remove links for popup
        let link = items[0].querySelector('a.hires');
        if (link) {
          items[0].insertBefore(link.querySelector('figure'), link);
          items[0].removeChild(link);
        }
        link = items[items.length-1].querySelector('a.hires');
        if (link) {
          items[items.length-1].insertBefore(link.querySelector('figure'), link);
          items[items.length-1].removeChild(link);
        }
        // goto first slider item
        if (direction == 'vertical') {
          slides.scrollTo(0, slides.offsetHeight);
        } else {
          slides.scrollTo(slides.offsetWidth, 0);
        }
        active = 1;
      }
      activate(active);
    }
  }

  var els = document.querySelectorAll('.slider'), cnt = els.length, i;
  if (els.length > 0) {
    // load stylesheet if not already loaded
    if (!document.getElementById('slider.css')) {
      var style = document.createElement("link");
      style.type = 'text/css';
      style.addEventListener('load', function () {
        init();
      });
      style.href = '/code/slider/slider.css';
      style.id = 'slider.css';
      style.rel = 'stylesheet';
      document.head.appendChild(style);
    } else {
      init();
    }
    function init () {
      console.log('slider: Slider lazy loading by IntersectionObserver');
      // only show and do autoplay interval if slider is in viewport
      function loadSlider(el, start) {
        if (el.obj) {
          if (start) {
            el.obj.start();
          } else {
            el.obj.stop();
          }
        } else if (start) {
          el.obj = new Slider(el);
        }
      }
      // create intersection observer
      let lazyobserver = new IntersectionObserver(function(entries, observer) {
        for (var i=0; i < entries.length; i++) {
          if (entries[i].isIntersecting) {
            if (entries[i].target.dataset.stop !== 'true') {
              loadSlider(entries[i].target, true);
            }
            if (entries[i].target.dataset.options.indexOf('autoplay') === -1) {
              lazyobserver.unobserve(entries[i].target);
            }
          } else {
            loadSlider(entries[i].target, false);
          }
        }
      }, {});
      // start observing
      for (var i=0; i < els.length; i++) {
        lazyobserver.observe(els[i]);
      }
      // accessibility: handle tabindex enter keydown event
      document.addEventListener('keydown', function(event) {
        if (event.key === "Enter") {
          if ((event.target.parentNode && event.target.parentNode.classList.contains('controls')) ||
              event.target.classList.contains('prev') ||
              event.target.classList.contains('next') ||
              event.target.classList.contains('pause') ||
              event.target.classList.contains('play')) {
            event.target.click();
          }
        }
      });
    }
  }
})();
StyleSheet:
slider.css StyleSheet (6,08 kByte) 03.01.2022 20:30
.slider {
  position: relative;
  width: 100%;
}
/* slider with ratio 44% */
.slider.ratio44 {
  height: 0;
  min-height: 1px;
  padding-top: 44%;
}
.slider.horizontal {
  overflow-y: clip;
  overflow-x: visible;
}
.slider.vertical {
  overflow-x: clip;
  overflow-y: visible;
}
.slider.horizontal.arrows-outside {
  margin: 0 auto;
  width: calc(100% - 100px);
}
.slider.vertical.arrows-outside {
  margin: auto 0;
  height: calc(100% - 100px);
}
.slider > .slides {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 0;
  list-style-type: none;
  /*overflow-scrolling: auto;*/
  /* hide IE and old Edge scrollbar */
  -ms-overflow-style: none;
  /* hide Firefox scrollbar */
  scrollbar-width: none;
}
/* hide Chrome, Safari and Opoera (WebKit) scrollbar */
.slider > .slides::-webkit-scrollbar {
  display: none;
}
.slider.horizontal > .slides {
  bottom: -12px; /* scrollbar fix */
  display: flex;
  scroll-snap-type: x mandatory;
  -ms-scroll-snap-type: x mandatory;
  overflow-x: scroll;
  overflow-y: hidden;
}
.slider.vertical > .slides {
  right: -12px; /* scrollbar fix */
  scroll-snap-type: y mandatory;
  -ms-scroll-snap-type: y mandatory;
  overflow-y: scroll;
  overflow-x: hidden;
}
.slider .slides > li {
  position: relative;
  margin: 0;
  padding: 0;
  scroll-snap-align: start;
  /* for background-image */
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
}
.slider.horizontal .slides > li {
  width: 100%;
  height: auto;
  display: inline-block;
  flex-shrink: 0;
}
.slider.vertical > .slides > li {
  height: 100%;
  width: auto;
}
.slider.fade > .slides > li {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 0;
  visibility: hidden;
  opacity: 0;
  transition: visibility 3s linear,opacity 3s linear;
}
.slider.fade > .slides > li.active {
  visibility: visible;
  opacity: 1;
  transition: visibility 3s linear,opacity 3s linear;
}
.slider > .slides > li > img {
  width: 100%;
  height: auto;
}

.slider > .controls {
  margin: 0;
  padding: 0;
}
.slider.horizontal > .controls {
  position: absolute;
  right: 0;
  left: 0;
  bottom: 5%;
  text-align: center;
}
.slider.vertical > .controls {
  position: absolute;
  top: 50%;
  right: 2%;
  transform: translate(0, -50%);
  display: block;
}
.slider.vertical > .controls::after {
  display: table;
  content: '';
  clear: both;
}
.slider.horizontal > .controls.thumbs {
  height: 10%;
}
.slider.vertical > .controls.thumbs {
  width: 10%;
}
.slider > .controls > li {
  display: inline-block;
  outline: none;
  background-color: #fff;
  opacity: 0.8;
  cursor: pointer;
}
.slider.horizontal > .controls > li {
  display: inline-block;
  margin: 0 5px;
}
.slider.vertical > .controls > li {
  display: block;
  margin: 5px 0;
}

.slider > .controls.bubbles > li {
  border: 1px solid #000;
  transition: border 500ms ease-out;
  width: 0.85em;
  height: 0.85em;
  border-radius: 50%;
}
.slider > .controls.thumbs > li {
  border: 2px solid #000;
  transition: border 500ms ease-out;
}
.slider > .controls.bubbles > li.active {
  background-color: #000;
}
.slider > .controls.thumbs > li.active {
  border-color: #fff;
}
.slider > .controls.thumbs > li {
  position: relative;
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
}
.slider.horizontal > .controls.thumbs > li {
  width: 10%;
  height: 100%;
}
.slider.vertical > .controls.thumbs > li {
  padding-top: 44%;
  width: 100%;
}

.slider > .prev, .slider > .next, .slider > .play, .slider > .pause {
  cursor: pointer;
  position: absolute;
  text-shadow: 1px 1px 1px #000;
}
.slider.horizontal > .prev, .slider.horizontal > .next {
  top: 50%;
  transform: translate(0, -50%);
}
.slider.vertical > .prev, .slider.vertical > .next {
  left: 50%;
  transform: translate(-50%, 0);
}
.slider.horizontal > .prev {
  left: 15px;
}
.slider.horizontal.arrows-outside > .prev {
  left: -35px;
}
.slider.horizontal > .next {
  right: 15px;
}
.slider.horizontal.arrows-outside > .next {
  right: -35px;
}
.slider.vertical > .prev {
  top: 15px;
}
.slider.vertical.arrows-outside > .prev {
  top: -35px;
}
.slider.vertical > .next {
  bottom: 15px;
}
.slider.vertical.arrows-outside > .next {
  bottom: -35px;
}

.slider.arrows-outside > .prev::after, .slider.arrows-outside > .next::after {
  color: #000;
}

.slider > .prev.hidden, .slider > .next.hidden {
  display: none;
}
.slider > .prev::after, .slider > .next::after, .slider > .play::after, .slider > .pause::after {
  display: inline-block;
  color: #fff;
  font-size: 2em;
}
.slider > .prev::after, .slider > .next::after {
  border: solid white;
  border-width: 0 3px 3px 0;
  padding: 12px;
  content: ' ';
  box-shadow: 5px 5px 0px 0px rgba(0, 0, 0, 0.5);
}
.slider.horizontal > .prev::after {
  transform: rotate(135deg);
  margin: 6px 0 6px 12px;
}
.slider.horizontal > .next::after {
  transform: rotate(-45deg);
  margin: 6px 12px 6px 0;
}
.slider.vertical > .prev::after {
  transform: rotate(-135deg);
  margin: 12px 6px 0 6px;
}
.slider.vertical > .next::after {
  transform: rotate(45deg);
  margin: 0 6px 12px 6px;
}

.slider:hover > .play, .slider:hover > .pause {
  background: #333;
  border-radius: 50% / 10%;
  color: #fff;
  font-size: 2em;
  height: 1.5em;
  width: 2em;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  cursor: pointer;
  background: red;
}
.slider:hover .play::before, .slider:hover > .pause::before  {
  background: inherit;
  border-radius: 5% / 50%;
  bottom: 9%;
  content: "";
  left: -5%;
  position: absolute;
  right: -5%;
  top: 9%;
}

.slider:hover > .play::after {
  border-style: solid;
  border-width: 1em 0 1em 1.732em;
  border-color: transparent transparent transparent rgba(255, 255, 255, 0.75);
  content: " ";
  font-size: 0.35em;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 0;
}
.slider:hover > .pause::after {
  border-style: solid;
  border-width: 1em;
  border-color: rgba(255, 255, 255, 0.75);
  content: " ";
  font-size: 0.35em;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 0;
}

Author: , published: , last modified:

Kontakt

Udo Schmal

Udo Schmal
Softwareentwickler
Olvengraben 41
47608 Geldern
Nordrhein-Westfalen
Germany





+49 2831 9776557
+49 1575 0663676
+49 2831 1328709
SMS
WhatsApp

Google Maps Profile
Instagram Profile
vCard 3.0

Service Infos

CMS Info Product Name:
UDOs Webserver
Version:
0.5.0.122
Description:
All in one Webserver
Copyright:
Udo Schmal
Compilation:
Fri, 14. Jan 2022 21:55:59
Development Info Compiler:
Free Pascal FPC 3.3.1
compiled for:
OS:Linux, CPU:x86_64
System Info OS:
Ubuntu 20.04.3 LTS (Focal Fossa)
Hardware Info Model:
Hewlett-Packard HP Pavilion dv7 Notebook PC
CPU Name:
Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
CPU Type:
x86_64, 1 physical CPU(s), 2 Core(s), 4 logical CPU(s), 1600.000 MHz