analytics pixel

Client Testimonials Carousel for WebSite X5: Display Customer Reviews! - Blog: Insights and Inspiration - Gebher | Digital Company

Client Testimonials Carousel for WebSite X5: A handy slideshow where you can display customer reviews!

Go to content

Client Testimonials Carousel for WebSite X5: A handy slideshow where you can display customer reviews!

Gebher | Digital Company

In this guide we want to help you create a small optional object, completely free, inspired by a code created by Quelli del Cucuzzolo , an article which we advise you to read to have a better understanding of this object.


Our guide wants to be an update to the previously proposed code to solve any compatibility problems with the latest PHP versions, as well as wanting to propose a more modern graphic style.


The Client Testimonials Carousel code is written in PHP language which allows you to retrieve user comments stored in a database, select them based on certain options, and display them on a web page, such as the Home Page of our site. The code was written to automate the process of selecting and displaying user comments, which has become common practice for websites in many niches, such as those dedicated to ecommerce.


The logic of the code exploits the structure that sites managed with WebSite X5 generate autonomously, when a Comments object is inserted and managed via the database. From this point of view it will be necessary to set up a database and know its parameters.


To use the code, you need to set some initial variables, including the name of the database table that contains user comments and the guestbook ID, which is the identifier of the guestbook that contains user comments. In addition, you must specify database connection information, including hostname, user name, password, and database name.


To bypass any changes on the software side, we have opted to use a new connection to the database, without using the one automatically managed by WebSite X5, precisely to avoid possible conflicts and obsolescence of the code.

After establishing a connection to the database, the code selects user comments based on the guestbook ID and some specified options, such as comment numbers 0, 2 and 4, sorted according to a certain criterion. Next, the code uses a while loop to iterate through the query results and build the HTML structure to display user comments.


The HTML structure comprises a bulleted list of slideshow elements, each of which represents a single comment. Each element contains a picture of the user's avatar, the user's name, the date of the comment, the text of the comment and possibly a link to the user's website and a numerical rating.


Basically, the intent is to be able to similarly report the data entered in the comment form by the user.


For an HTML structure that is as modern and versatile as possible on the mobile side, but also graphically beautiful to look at, we decided to base ourselves on the free framework provided by our partner CodyHouse , using the library and the Free codes made available.

The Client Testimonials Carousel is the perfect plugin to integrate into WebSite X5, within an HTML Code object, in a PHP page.



Here is the PHP code:



PHP
  1. <?php
  2. // Definition of the initial variables to customize
  3. $tableName = "w5_qwerty01_2345_67_comments"; // enter the name of the database table 
  4. $guestbookId = "x5ab01234"; // Enter the guestbook ID
  5.  
  6. // Database connection information
  7. $hostname = "localhost"; // Database hostname
  8. $username = "localhost"; // Database username
  9. $password = "localhost"; // Database password
  10. $databaseName = "localhost"; // Database name
  11.  
  12. // Database connection
  13. $connection = mysqli_connect($hostname, $username, $password, $databaseName);
  14.  
  15. // Checking for successful connection
  16. if (!$connection) {
  17.     die("Failed to connect: " . mysqli_connect_error());
  18. }
  19.  
  20. // ATTENTION: SELECT ONLY ONE OPERATING MODE (Mode 1 or Mode 2) and enter '//' to disable the unchosen option.
  21.  
  22. // MODE 1: Selection of chosen comments
  23. $sql = "SELECT * FROM $tableName WHERE postid='$guestbookId' AND commentid in(0,2,4) ORDER BY FIELD(commentid,2,4,0)";
  24.  
  25. // MODE 2: Selection of random comments based on rating
  26. //$sql = "SELECT * FROM $tableName WHERE postid='$guestbookId' AND rating=5 ORDER BY RAND() LIMIT 3";
  27.  
  28. $result = mysqli_query($connection, $sql);
  29.  
  30. // Iterating the array and building the HTML structure
  31. if (mysqli_num_rows($result) > 0) {
  32.     while($row = mysqli_fetch_assoc($result)) {
  33.         echo '<li class="slideshow__item sq7-bg-light js-slideshow__item" style=""><div class="sq7-container sq7-max-width-sm"><div class="sq7-text-component">';
  34.  
  35.  
  36.         // Avatar output image
  37.         echo '<img class="gb_avatar" src="files/avatar.svg" alt="avatar" style="height: 80px; max-width: 80px; max-height: 80px; width: 80px;"/>';
  38.         // Name output
  39.         echo '<div style=" text-align: center; " class="gb_name"><strong>' . $row['name'] . '</strong></div>';
  40.  
  41. // Date output
  42. $date = date_create($row['timestamp']);
  43. echo '<p style=" text-align: center; ">' . date_format($date, 'd-m-Y') . '</p>';
  44.  
  45. // Comment output
  46. echo '<div style=" text-align: center; " class="gb_body">' . $row['body'] . '</div>';
  47.  
  48.         if ($row['url'] != '') {
  49.  
  50.             // Output of the website field
  51.             echo '<div class="gb_url"><a class="imCssLink" href="' . $row['url'] . '" target="_blank">sito web</a></div>';
  52.             // Output of the custom website field
  53.             echo '<div class="gb_url">' . str_replace('http://', '', $row['url']) . '</div>';
  54.         }
  55.  
  56.         // Output del voto
  57.         if (isset($row['rating']) && $row['rating'] > 0) {
  58.             echo '<img class="gb_rater" src="files/star' . $row['rating'] . '.svg" alt="' . $row['rating'] . ' star" style="max-width: 150px;max-height: 150px;width: 150px;"/>';
  59.         }
  60.  
  61.         echo '</div></div></li>';
  62.     }
  63. }
  64.  
  65. // Closing the database connection
  66. mysqli_close($connection);
  67. ?>


As mentioned earlier, in this PHP code, we have a script that fetches customer testimonials from a database table and displays them on a web page. Let's examine the code in more detail.


First, we have some initial variables that need to be customized based on our database and guestbook settings. The $tableNamevariable should be set to the name of the database table storing the comments, while the $guestbookIdvariable should be set to the ID of the guestbook we want to retrieve the comments from.


Next, we have the database connection information, including hostname, username, password, and database name. These details are used to establish a database connection.


We then use the mysqli_connect() function to connect to the database. If the connection fails, the script will terminate with an error message.


After establishing the database connection, we run a SQL query to retrieve the desired comments from the specified table. The query selects all rows from the table where the postid column matches the guestbook ID and the commentid column is one of 0, 2, or 4. The results are sorted in the order specified by the FIELD() function. This SQL query is stored in the $sql variable.


The mysqli_query() function is used to execute the SQL query, and the results are stored in the $result variable.


We then iterate over the rows in the result set using a while loop. For each row, we generate the HTML code to display the comment on the web page. The HTML code is stored in a string and printed to the output stream using the echo statement.




The HTML code includes the following elements for each comment:


  1. An avatar image, which is hardcoded in this example but could be replaced with an image uploaded by the user.
  2. The commenter's name, retrieved from the name column of the database table.
  3. The date the comment was posted, retrieved from the timestamp column of the database table.
  4. The comment text, retrieved from the body column of the database table.
  5. A link to the commenter's website, if provided in the url column of the database table.
  6. A star rating, if provided in the rating column of the database table.




Finally, we close the database connection using the mysqli_close() function.


Overall, this script provides an easy way to retrieve and display customer testimonials on a web page, using a database to manage the comments. The script could be further customized to add features like pagination, filtering or sorting by different criteria.


Now let's take care of the visual part, that is organizing the data taken from the database with a Carousel. To do this we have to think of the structure as if it were a sandwich, where the PHP code is the condiment, while the opening and closing HTML structure can similarly be the two slices of bread that enclose our delicacy



And here is the complete code:



HTML
  1. <link rel="stylesheet" href="./css/2_slideshow.css">
  2. <div class="slideshow js-slideshow slideshow--transition-fade" data-swipe="on" data-autoplay="on">
  3.   <p class="sq7-sr-only">Client Testimonials Carousel</p>
  4.   <ul class="slideshow__content">
  5.     <!--  INSERT THE PHP CODE HERE  -->
  6.   </ul>
  7.   <ul>
  8.     <li class="slideshow__control js-slideshow__control">
  9.       <button class="slideshow__btn js-tab-focus">
  10.         <svg class="sq7-icon" viewBox="0 0 32 32">
  11.           <title>Show previous slide</title>
  12.           <path d="M20.768,31.395L10.186,16.581c-0.248-0.348-0.248-0.814,0-1.162L20.768,0.605l1.627,1.162L12.229,16 l10.166,14.232L20.768,31.395z"></path>
  13.         </svg>
  14.       </button>
  15.     </li>
  16.     <li class="slideshow__control js-slideshow__control">
  17.       <button class="slideshow__btn js-tab-focus">
  18.         <svg class="sq7-icon" viewBox="0 0 32 32">
  19.           <title>Show next slide</title>
  20.           <path d="M11.232,31.395l-1.627-1.162L19.771,16L9.605,1.768l1.627-1.162l10.582,14.813 c0.248,0.348,0.248,0.814,0,1.162L11.232,31.395z"></path>
  21.         </svg>
  22.       </button>
  23.     </li>
  24.   </ul>
  25. </div>
  26. <script src="./js/_1_swipe-content.js"></script>
  27. <script src="./js/_2_slideshow.js"></script>


CSS (2_slideshow.css)
  1. *, *::after, *::before {
  2.   box-sizing: border-box;
  3. }
  4.  
  5. * {
  6.   font: inherit;
  7.   margin: 0;
  8.   padding: 0;
  9.   border: 0;
  10. }
  11.  
  12. body {
  13.   background-color: hsl(0, 0%, 100%);
  14.   font-family: system-ui, sans-serif;
  15.   color: hsl(230, 7%, 23%);
  16.   font-size: 1rem;
  17. }
  18.  
  19. h1, h2, h3, h4 {
  20.   line-height: 1.2;
  21.   color: hsl(230, 13%, 9%);
  22.   font-weight: 700;
  23. }
  24.  
  25. h1 {
  26.   font-size: 2.0736rem;
  27. }
  28.  
  29. h2 {
  30.   font-size: 1.728rem;
  31. }
  32.  
  33. h3 {
  34.   font-size: 1.25rem;
  35. }
  36.  
  37. h4 {
  38.   font-size: 1.2rem;
  39. }
  40.  
  41. ol, ul, menu {
  42.   list-style: none;
  43. }
  44.  
  45. button, input, textarea, select {
  46.   background-color: transparent;
  47.   border-radius: 0;
  48.   color: inherit;
  49.   line-height: inherit;
  50.   appearance: none;
  51. }
  52.  
  53. textarea {
  54.   resize: vertical;
  55.   overflow: auto;
  56.   vertical-align: top;
  57. }
  58.  
  59. {
  60.   color: hsl(250, 84%, 54%);
  61. }
  62.  
  63. table {
  64.   border-collapse: collapse;
  65.   border-spacing: 0;
  66. }
  67.  
  68. img, video, svg {
  69.   display: block;
  70.   max-width: 100%;
  71. }
  72.  
  73. @media (min-width: 64rem) {
  74.   body {
  75.     font-size: 1.25rem;
  76.   }
  77.  
  78.   h1 {
  79.     font-size: 3.051rem;
  80.   }
  81.  
  82.     h2 {
  83.     font-size: 2.44rem;
  84.   }
  85.  
  86.     h3 {
  87.     font-size: 1.75rem;
  88.   }
  89.  
  90.     h4 {
  91.     font-size: 1.5625rem;
  92.   }
  93. }
  94.  
  95. /* variables */
  96. :root {
  97.   /* colors */
  98.   --sq7-color-primary-hsl: 250, 84%, 54%;
  99.   --sq7-color-bg-hsl: 0, 0%, 100%;
  100.   --sq7-color-contrast-high-hsl: 230, 7%, 23%;
  101.   --sq7-color-contrast-higher-hsl: 230, 13%, 9%;
  102.   --sq7-color-bg-light-hsl: 0, 0%, 100%;
  103.   --sq7-color-black-hsl: 230, 13%, 9%;
  104.   --sq7-color-white-hsl: 0, 0%, 100%;
  105.   --sq7-color-bg-dark-hsl: 240, 4%, 95%;
  106.   --sq7-color-primary-darker-hsl: 250, 84%, 38%;
  107.   --sq7-color-primary-light-hsl: 250, 84%, 60%;
  108.   --sq7-color-accent-hsl: 342, 89%, 48%;
  109.   --sq7-color-contrast-lower-hsl: 240, 4%, 85%;
  110.  
  111.   /* spacing */
  112.   --sq7-space-3xs: 0.25rem;
  113.   --sq7-space-xs: 0.5rem;
  114.   --sq7-space-sm: 0.75rem;
  115.   --sq7-space-md: 1.25rem;
  116.   --sq7-space-2xs: 0.375rem;
  117.  
  118.   /* typography */
  119.   --sq7-text-sm: 0.833rem;
  120. }
  121.  
  122. @media(min-width: 64rem){
  123.   :root {
  124.     /* spacing */
  125.     --sq7-space-3xs: 0.375rem;
  126.     --sq7-space-xs: 0.75rem;
  127.     --sq7-space-sm: 1.125rem;
  128.     --sq7-space-md: 2rem;
  129.     --sq7-space-2xs: 0.5625rem;
  130.  
  131.     /* typography */
  132.     --sq7-text-sm: 1rem;
  133.   }
  134. }
  135.  
  136. /* buttons */
  137. .sq7-btn {
  138.   position: relative;
  139.   display: inline-flex;
  140.   justify-content: center;
  141.   align-items: center;
  142.   font-size: 1em;
  143.   white-space: nowrap;
  144.   text-decoration: none;
  145.   background: hsl(var(--sq7-color-bg-dark-hsl));
  146.   color: hsl(var(--sq7-color-contrast-higher-hsl));
  147.   cursor: pointer;
  148.   text-decoration: none;
  149.   line-height: 1.2;
  150.   -webkit-font-smoothing: antialiased;
  151.   -moz-osx-font-smoothing: grayscale;
  152.   transition: all 0.2s ease;
  153.   will-change: transform;
  154.   padding: var(--sq7-space-2xs) var(--sq7-space-sm);
  155.   border-radius: 0.25em;
  156. }
  157.  
  158. .sq7-btn:focus-visible {
  159.   box-shadow: 0px 0px 0px 2px hsl(var(--sq7-color-bg-hsl)), 0px 0px 0px 4px hsla(var(--sq7-color-contrast-higher-hsl), 0.15);
  160.   outline: none;
  161. }
  162.  
  163. .sq7-btn:active {
  164.   transform: translateY(2px);
  165. }
  166.  
  167. .sq7-btn--primary {
  168.   background: hsl(var(--sq7-color-primary-hsl));
  169.   color: hsl(var(--sq7-color-white-hsl));
  170.   box-shadow: inset 0px 1px 0px hsla(var(--sq7-color-white-hsl), 0.15), 0px 1px 3px hsla(var(--sq7-color-primary-darker-hsl), 0.25), 0px 2px 6px hsla(var(--sq7-color-primary-darker-hsl), 0.1), 0px 6px 10px -2px hsla(var(--sq7-color-primary-darker-hsl), 0.25);
  171. }
  172.  
  173. .sq7-btn--primary:hover {
  174.   background: hsl(var(--sq7-color-primary-light-hsl));
  175.   box-shadow: inset 0px 1px 0px hsla(var(--sq7-color-white-hsl), 0.15), 0px 1px 2px hsla(var(--sq7-color-primary-darker-hsl), 0.25), 0px 1px 4px hsla(var(--sq7-color-primary-darker-hsl), 0.1), 0px 3px 6px -2px hsla(var(--sq7-color-primary-darker-hsl), 0.25);
  176. }
  177.  
  178. .sq7-btn--primary:focus {
  179.   box-shadow: inset 0px 1px 0px hsla(var(--sq7-color-white-hsl), 0.15), 0px 1px 2px hsla(var(--sq7-color-primary-darker-hsl), 0.25), 0px 1px 4px hsla(var(--sq7-color-primary-darker-hsl), 0.1), 0px 3px 6px -2px hsla(var(--sq7-color-primary-darker-hsl), 0.25), 0px 0px 0px 2px hsl(var(--sq7-color-bg-hsl)), 0px 0px 0px 4px hsl(var(--sq7-color-primary-hsl));
  180. }
  181.  
  182. /* icons */
  183. .sq7-icon {
  184.   height: var(--sq7-size, 1em);
  185.   width: var(--sq7-size, 1em);
  186.   display: inline-block;
  187.   color: inherit;
  188.   fill: currentColor;
  189.   line-height: 1;
  190.   flex-shrink: 0;
  191.   max-width: initial;
  192. }
  193.  
  194. /* component */
  195. :root {
  196.   --slideshow-height: 280px;
  197.   --slideshow-fade-transition-duration: 0.25s;
  198.   --slideshow-slide-transition-duration: 0.35s;
  199.   --slideshow-prx-transition-duration: 0.5s;
  200.   --slideshow-btn-width: 1.6em;
  201.   --slideshow-btn-height: 3.2em;
  202.   --slideshow-btn-icon-size: 1.6em;
  203.   --slideshow-btn-offset: var(--sq7-space-xs);
  204. }
  205. @media (min-width: 48rem) {
  206.   :root {
  207.     --slideshow-height: 380px;
  208.   }
  209. }
  210. @media (min-width: 64rem) {
  211.   :root {
  212.     --slideshow-height: 480px;
  213.   }
  214. }
  215. @media (min-width: 80rem) {
  216.   :root {
  217.     --slideshow-height: 580px;
  218.   }
  219. }
  220.  
  221. .slideshow__item {
  222.   display: flex;
  223.   align-items: center;
  224.   justify-content: center;
  225.   height: var(--slideshow-height);
  226.   background-size: cover;
  227.   background-repeat: no-repeat;
  228.   background-position: center center;
  229. }
  230. .slideshow__item:focus {
  231.   outline: none;
  232. }
  233.  
  234. .slideshow--ratio-16\:9 .slideshow__item {
  235.   height: 0;
  236.   padding-bottom: 56.25%;
  237. }
  238.  
  239. .slideshow--ratio-4\:3 .slideshow__item {
  240.   height: 0;
  241.   padding-bottom: 75%;
  242. }
  243.  
  244. .slideshow--ratio-1\:1 .slideshow__item {
  245.   height: 0;
  246.   padding-bottom: 100%;
  247. }
  248.  
  249. .slideshow {
  250.   position: relative;
  251.   z-index: 1;
  252.   overflow: hidden;
  253. }
  254.  
  255. .slideshow__content {
  256.   overflow: hidden;
  257. }
  258.  
  259. .slideshow__item {
  260.   position: absolute;
  261.   z-index: 1;
  262.   top: 0;
  263.   left: 0;
  264.   width: 100%;
  265.   visibility: hidden;
  266. }
  267.  
  268. .slideshow__item--selected {
  269.   position: relative;
  270.   z-index: 3;
  271.   visibility: visible;
  272. }
  273.  
  274. .slideshow--transition-fade .slideshow__item {
  275.   opacity: 0;
  276.   transition: opacity 0s var(--slideshow-fade-transition-duration), visibility 0s var(--slideshow-fade-transition-duration);
  277. }
  278.  
  279. .slideshow--transition-fade .slideshow__item--selected {
  280.   opacity: 1;
  281.   transition: opacity var(--slideshow-fade-transition-duration);
  282. }
  283.  
  284. .slideshow--transition-slide .slideshow__item {
  285.   -webkit-animation-duration: var(--slideshow-slide-transition-duration);
  286.           animation-duration: var(--slideshow-slide-transition-duration);
  287.   -webkit-animation-fill-mode: forwards;
  288.           animation-fill-mode: forwards;
  289.   -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  290.           animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  291. }
  292. .slideshow--transition-slide .slideshow__item > * {
  293.   visibility: hidden;
  294. }
  295.  
  296. .slideshow--transition-slide .slideshow__item--selected > * {
  297.   visibility: visible;
  298. }
  299.  
  300. .slideshow--transition-slide .slideshow__item--slide-in-left {
  301.   -webkit-animation-name: slide-in-left;
  302.           animation-name: slide-in-left;
  303. }
  304.  
  305. .slideshow--transition-slide .slideshow__item--slide-in-right {
  306.   -webkit-animation-name: slide-in-right;
  307.           animation-name: slide-in-right;
  308. }
  309.  
  310. .slideshow--transition-slide .slideshow__item--slide-out-left {
  311.   -webkit-animation-name: slide-out-left;
  312.           animation-name: slide-out-left;
  313. }
  314.  
  315. .slideshow--transition-slide .slideshow__item--slide-out-right {
  316.   -webkit-animation-name: slide-out-right;
  317.           animation-name: slide-out-right;
  318. }
  319.  
  320. .slideshow--transition-slide .slideshow__item--slide-out-left,
  321. .slideshow--transition-slide .slideshow__item--slide-out-right {
  322.   z-index: 2;
  323. }
  324. .slideshow--transition-slide .slideshow__item--slide-out-left.slideshow__item--selected,
  325. .slideshow--transition-slide .slideshow__item--slide-out-right.slideshow__item--selected {
  326.   z-index: 3;
  327. }
  328. .slideshow--transition-slide .slideshow__item--slide-out-left > *,
  329. .slideshow--transition-slide .slideshow__item--slide-out-right > * {
  330.   visibility: visible;
  331. }
  332.  
  333. @-webkit-keyframes slide-in-left {
  334.   0% {
  335.     visibility: visible;
  336.     -webkit-transform: translateX(-100%);
  337.             transform: translateX(-100%);
  338.   }
  339.   100% {
  340.     -webkit-transform: translateX(0);
  341.             transform: translateX(0);
  342.   }
  343. }
  344.  
  345. @keyframes slide-in-left {
  346.   0% {
  347.     visibility: visible;
  348.     -webkit-transform: translateX(-100%);
  349.             transform: translateX(-100%);
  350.   }
  351.   100% {
  352.     -webkit-transform: translateX(0);
  353.             transform: translateX(0);
  354.   }
  355. }
  356. @-webkit-keyframes slide-in-right {
  357.   0% {
  358.     visibility: visible;
  359.     -webkit-transform: translateX(100%);
  360.             transform: translateX(100%);
  361.   }
  362.   100% {
  363.     -webkit-transform: translateX(0);
  364.             transform: translateX(0);
  365.   }
  366. }
  367. @keyframes slide-in-right {
  368.   0% {
  369.     visibility: visible;
  370.     -webkit-transform: translateX(100%);
  371.             transform: translateX(100%);
  372.   }
  373.   100% {
  374.     -webkit-transform: translateX(0);
  375.             transform: translateX(0);
  376.   }
  377. }
  378. @-webkit-keyframes slide-out-left {
  379.   0% {
  380.     visibility: visible;
  381.     -webkit-transform: translateX(0);
  382.             transform: translateX(0);
  383.   }
  384.   100% {
  385.     -webkit-transform: translateX(100%);
  386.             transform: translateX(100%);
  387.   }
  388. }
  389. @keyframes slide-out-left {
  390.   0% {
  391.     visibility: visible;
  392.     -webkit-transform: translateX(0);
  393.             transform: translateX(0);
  394.   }
  395.   100% {
  396.     -webkit-transform: translateX(100%);
  397.             transform: translateX(100%);
  398.   }
  399. }
  400. @-webkit-keyframes slide-out-right {
  401.   0% {
  402.     visibility: visible;
  403.     -webkit-transform: translateX(0);
  404.             transform: translateX(0);
  405.   }
  406.   100% {
  407.     -webkit-transform: translateX(-100%);
  408.             transform: translateX(-100%);
  409.   }
  410. }
  411. @keyframes slide-out-right {
  412.   0% {
  413.     visibility: visible;
  414.     -webkit-transform: translateX(0);
  415.             transform: translateX(0);
  416.   }
  417.   100% {
  418.     -webkit-transform: translateX(-100%);
  419.             transform: translateX(-100%);
  420.   }
  421. }
  422. .slideshow--transition-prx .slideshow__item {
  423.   -webkit-animation-duration: var(--slideshow-prx-transition-duration);
  424.           animation-duration: var(--slideshow-prx-transition-duration);
  425.   -webkit-animation-fill-mode: forwards;
  426.           animation-fill-mode: forwards;
  427.   -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  428.           animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  429. }
  430. .slideshow--transition-prx .slideshow__item > * {
  431.   visibility: hidden;
  432. }
  433.  
  434. .slideshow--transition-prx .slideshow__item--selected > * {
  435.   visibility: visible;
  436. }
  437.  
  438. .slideshow--transition-prx .slideshow__item--prx-in-left {
  439.   -webkit-animation-name: prx-in-left;
  440.           animation-name: prx-in-left;
  441. }
  442.  
  443. .slideshow--transition-prx .slideshow__item--prx-in-right {
  444.   -webkit-animation-name: prx-in-right;
  445.           animation-name: prx-in-right;
  446. }
  447.  
  448. .slideshow--transition-prx .slideshow__item--prx-out-left {
  449.   -webkit-animation-name: prx-out-left;
  450.           animation-name: prx-out-left;
  451. }
  452.  
  453. .slideshow--transition-prx .slideshow__item--prx-out-right {
  454.   -webkit-animation-name: prx-out-right;
  455.           animation-name: prx-out-right;
  456. }
  457.  
  458. .slideshow--transition-prx .slideshow__item--prx-out-left,
  459. .slideshow--transition-prx .slideshow__item--prx-out-right {
  460.   z-index: 2;
  461. }
  462. .slideshow--transition-prx .slideshow__item--prx-out-left.slideshow__item--selected,
  463. .slideshow--transition-prx .slideshow__item--prx-out-right.slideshow__item--selected {
  464.   z-index: 3;
  465. }
  466. .slideshow--transition-prx .slideshow__item--prx-out-left > *,
  467. .slideshow--transition-prx .slideshow__item--prx-out-right > * {
  468.   visibility: visible;
  469. }
  470.  
  471. @-webkit-keyframes prx-in-left {
  472.   0% {
  473.     visibility: visible;
  474.     -webkit-transform: translateX(-100%);
  475.             transform: translateX(-100%);
  476.   }
  477.   100% {
  478.     -webkit-transform: translateX(0);
  479.             transform: translateX(0);
  480.   }
  481. }
  482.  
  483. @keyframes prx-in-left {
  484.   0% {
  485.     visibility: visible;
  486.     -webkit-transform: translateX(-100%);
  487.             transform: translateX(-100%);
  488.   }
  489.   100% {
  490.     -webkit-transform: translateX(0);
  491.             transform: translateX(0);
  492.   }
  493. }
  494. @-webkit-keyframes prx-in-right {
  495.   0% {
  496.     visibility: visible;
  497.     -webkit-transform: translateX(100%);
  498.             transform: translateX(100%);
  499.   }
  500.   100% {
  501.     -webkit-transform: translateX(0);
  502.             transform: translateX(0);
  503.   }
  504. }
  505. @keyframes prx-in-right {
  506.   0% {
  507.     visibility: visible;
  508.     -webkit-transform: translateX(100%);
  509.             transform: translateX(100%);
  510.   }
  511.   100% {
  512.     -webkit-transform: translateX(0);
  513.             transform: translateX(0);
  514.   }
  515. }
  516. @-webkit-keyframes prx-out-left {
  517.   0% {
  518.     opacity: 1;
  519.     visibility: visible;
  520.     -webkit-transform: translateX(0);
  521.             transform: translateX(0);
  522.   }
  523.   100% {
  524.     opacity: 0.3;
  525.     -webkit-transform: translateX(40%);
  526.             transform: translateX(40%);
  527.   }
  528. }
  529. @keyframes prx-out-left {
  530.   0% {
  531.     opacity: 1;
  532.     visibility: visible;
  533.     -webkit-transform: translateX(0);
  534.             transform: translateX(0);
  535.   }
  536.   100% {
  537.     opacity: 0.3;
  538.     -webkit-transform: translateX(40%);
  539.             transform: translateX(40%);
  540.   }
  541. }
  542. @-webkit-keyframes prx-out-right {
  543.   0% {
  544.     opacity: 1;
  545.     visibility: visible;
  546.     -webkit-transform: translateX(0);
  547.             transform: translateX(0);
  548.   }
  549.   100% {
  550.     opacity: 0.3;
  551.     -webkit-transform: translateX(-40%);
  552.             transform: translateX(-40%);
  553.   }
  554. }
  555. @keyframes prx-out-right {
  556.   0% {
  557.     opacity: 1;
  558.     visibility: visible;
  559.     -webkit-transform: translateX(0);
  560.             transform: translateX(0);
  561.   }
  562.   100% {
  563.     opacity: 0.3;
  564.     -webkit-transform: translateX(-40%);
  565.             transform: translateX(-40%);
  566.   }
  567. }
  568. .slideshow[data-swipe=on] .slideshow__content {
  569.   -webkit-user-select: none;
  570.      -moz-user-select: none;
  571.       -ms-user-select: none;
  572.           user-select: none;
  573. }
  574. .slideshow[data-swipe=on] .slideshow__content img {
  575.   pointer-events: none;
  576. }
  577.  
  578. .slideshow__control {
  579.   display: none;
  580. }
  581.  
  582. .slideshow[data-controls=hover] .slideshow__control {
  583.   opacity: 0;
  584.   transition: opacity 0.3s;
  585. }
  586.  
  587. .slideshow[data-controls=hover]:hover .slideshow__control {
  588.   opacity: 1;
  589. }
  590.  
  591. .slideshow[data-swipe=on] .slideshow__control {
  592.   display: none;
  593. }
  594.  
  595. .slideshow__control {
  596.   display: block;
  597.   position: absolute;
  598.   z-index: 4;
  599.   top: 50%;
  600.   -webkit-transform: translateY(-50%);
  601.           transform: translateY(-50%);
  602. }
  603. .slideshow__control:first-of-type {
  604.   left: var(--slideshow-btn-offset);
  605. }
  606. .slideshow__control:last-of-type {
  607.   right: var(--slideshow-btn-offset);
  608. }
  609.  
  610. @media (min-width: 64rem) {
  611.   .slideshow[data-swipe=on] .slideshow__control {
  612.     display: block;
  613.   }
  614. }
  615. .slideshow__btn {
  616.   display: block;
  617.   background-color: hsla(var(--sq7-color-black-hsl), 0.75);
  618.   height: var(--slideshow-btn-height);
  619.   width: var(--slideshow-btn-width);
  620.   border-radius: 0.25em;
  621.   cursor: pointer;
  622.   transition: background 0.2s, -webkit-transform 0.2s;
  623.   transition: background 0.2s, transform 0.2s;
  624.   transition: background 0.2s, transform 0.2s, -webkit-transform 0.2s;
  625. }
  626. .slideshow__btn:hover {
  627.   background-color: hsla(var(--sq7-color-contrast-higher-hsl), 0.85);
  628. }
  629. .slideshow__btn:hover svg {
  630.   color: hsl(var(--sq7-color-bg-hsl));
  631. }
  632. .slideshow:not(.slideshow--is-animating) .slideshow__btn:active {
  633.   -webkit-transform: translateY(2px);
  634.           transform: translateY(2px);
  635. }
  636. .slideshow__btn svg {
  637.   display: block;
  638.   width: var(--slideshow-btn-icon-size);
  639.   height: var(--slideshow-btn-icon-size);
  640.   margin: 0 auto;
  641.   transition: color 0.2s;
  642.   color: hsl(var(--sq7-color-white-hsl));
  643. }
  644. @supports (grid-area: auto) {
  645.   .slideshow__btn {
  646.     background-color: transparent;
  647.   }
  648.   .slideshow__btn svg {
  649.     color: hsl(var(--sq7-color-contrast-higher-hsl));
  650.   }
  651. }
  652.  
  653. .slideshow__navigation {
  654.   position: absolute;
  655.   z-index: 4;
  656.   bottom: 0;
  657.   width: 100%;
  658.   height: 32px;
  659.   display: flex;
  660.   justify-content: center;
  661.   align-items: center;
  662.   background: transparent;
  663. }
  664.  
  665. .slideshow__nav-item {
  666.   display: inline-block;
  667.   margin: 0 var(--sq7-space-3xs);
  668. }
  669. .slideshow__nav-item button {
  670.   display: block;
  671.   position: relative;
  672.   font-size: 8px;
  673.   color: hsl(var(--sq7-color-contrast-high-hsl));
  674.   height: 1em;
  675.   width: 1em;
  676.   border-radius: 50%;
  677.   background-color: currentColor;
  678.   opacity: 0.4;
  679.   cursor: pointer;
  680.   transition: background 0.3s;
  681. }
  682. .slideshow__nav-item button::before {
  683.   content: "";
  684.   position: absolute;
  685.   top: calc(50% - 0.5em);
  686.   left: calc(50% - 0.5em);
  687.   height: 1em;
  688.   width: 1em;
  689.   font-size: 14px;
  690.   border-radius: inherit;
  691.   border: 1px solid hsl(var(--sq7-color-contrast-high-hsl));
  692.   opacity: 0;
  693.   -webkit-transform: scale(0);
  694.           transform: scale(0);
  695.   transition: 0.3s;
  696. }
  697. .slideshow__nav-item button:focus {
  698.   outline: none;
  699. }
  700. .slideshow__nav-item button:focus::before {
  701.   opacity: 1;
  702.   -webkit-transform: scale(1);
  703.           transform: scale(1);
  704. }
  705.  
  706. .slideshow__nav-item--selected button {
  707.   opacity: 1;
  708. }
  709.  
  710. @media (min-width: 64rem) {
  711.   .slideshow__navigation {
  712.     height: 40px;
  713.   }
  714.  
  715.   .slideshow__nav-item button {
  716.     font-size: 10px;
  717.   }
  718.   .slideshow__nav-item button::before {
  719.     font-size: 16px;
  720.   }
  721. }
  722.  
  723. /* utility classes */
  724. .sq7-sr-only {
  725.   position: absolute;
  726.   clip: rect(1px, 1px, 1px, 1px);
  727.   clip-path: inset(50%);
  728.   width: 1px;
  729.   height: 1px;
  730.   overflow: hidden;
  731.   padding: 0;
  732.   border: 0;
  733.   white-space: nowrap;
  734. }
  735.  
  736. .sq7-bg-light {
  737.   --sq7-bg-o: 1;
  738.   background-color: hsla(var(--sq7-color-bg-light-hsl), var(--sq7-bg-o, 1));
  739. }
  740.  
  741. .sq7-text-center {
  742.   text-align: center;
  743. }
  744.  
  745. .sq7-text-component :where(h1, h2, h3, h4) {
  746.   line-height: var(--sq7-heading-line-height, 1.2);
  747.   margin-top: calc(var(--sq7-space-md) * var(--sq7-space-multiplier, 1));
  748.   margin-bottom: calc(var(--sq7-space-sm) * var(--sq7-space-multiplier, 1));
  749. }
  750.  
  751. .sq7-text-component :where(p, blockquote, ul li, ol li) {
  752.   line-height: var(--sq7-body-line-height, 1.4);
  753. }
  754.  
  755. .sq7-text-component :where(ul, ol, p, blockquote, .sq7-text-component__block) {
  756.   margin-bottom: calc(var(--sq7-space-sm) * var(--sq7-space-multiplier, 1));
  757. }
  758.  
  759. .sq7-text-component :where(ul, ol) {
  760.   padding-left: 1.25em;
  761. }
  762.  
  763. .sq7-text-component ul :where(ul, ol), .sq7-text-component ol :where(ul, ol) {
  764.   padding-left: 1em;
  765.   margin-bottom: 0;
  766. }
  767.  
  768. .sq7-text-component ul {
  769.   list-style-type: disc;
  770. }
  771.  
  772. .sq7-text-component ol {
  773.   list-style-type: decimal;
  774. }
  775.  
  776. .sq7-text-component img {
  777.   display: block;
  778.   margin: 0 auto;
  779. }
  780.  
  781. .sq7-text-component figcaption {
  782.   margin-top: calc(var(--sq7-space-xs) * var(--sq7-space-multiplier, 1));
  783.   font-size: var(--sq7-text-sm);
  784.   text-align: center;}
  785.  
  786. .sq7-text-component em {
  787.   font-style: italic;
  788. }
  789.  
  790. .sq7-text-component strong {
  791.   font-weight: bold;
  792. }
  793.  
  794. .sq7-text-component s {
  795.   text-decoration: line-through;
  796. }
  797.  
  798. .sq7-text-component u {
  799.   text-decoration: underline;
  800. }
  801.  
  802. .sq7-text-component mark {
  803.   background-color: hsla(var(--sq7-color-accent-hsl), 0.2);
  804.   color: inherit;
  805. }
  806.  
  807. .sq7-text-component blockquote {
  808.   padding-left: 1em;
  809.   border-left: 4px solid hsl(var(--sq7-color-contrast-lower-hsl));
  810.   font-style: italic;
  811. }
  812.  
  813. .sq7-text-component hr {
  814.   margin: calc(var(--sq7-space-md) * var(--sq7-space-multiplier, 1)) auto;
  815.   background: hsl(var(--sq7-color-contrast-lower-hsl));
  816.   height: 1px;
  817. }
  818.  
  819. .sq7-text-component > *:first-child {
  820.   margin-top: 0;
  821. }
  822.  
  823. .sq7-text-component > *:last-child {
  824.   margin-bottom: 0;
  825. }
  826.  
  827. .sq7-text-component.sq7-line-height-xs {
  828.   --sq7-heading-line-height: 1;
  829.   --sq7-body-line-height: 1.1;
  830. }
  831.  
  832. .sq7-text-component.sq7-line-height-sm {
  833.   --sq7-heading-line-height: 1.1;
  834.   --sq7-body-line-height: 1.2;
  835. }
  836.  
  837. .sq7-text-component.sq7-line-height-md {
  838.   --sq7-heading-line-height: 1.15;
  839.   --sq7-body-line-height: 1.4;
  840. }
  841.  
  842. .sq7-text-component.sq7-line-height-lg {
  843.   --sq7-heading-line-height: 1.22;
  844.   --sq7-body-line-height: 1.58;
  845. }
  846.  
  847. .sq7-text-component.sq7-line-height-xl {
  848.   --sq7-heading-line-height: 1.3;
  849.   --sq7-body-line-height: 1.72;
  850. }
  851.  
  852. .sq7-max-width-sm {
  853.   max-width: 48rem;
  854. }
  855.  
  856. .sq7-container {
  857.   width: calc(100% - 2*var(--sq7-space-md));
  858.   margin-left: auto;
  859.   margin-right: auto;
  860. }
  861.  
  862. .sq7-color-inherit {
  863.   color: inherit;
  864. }
  865.  
  866. .sq7-gap-sm {
  867.   gap: var(--sq7-space-sm);
  868. }
  869.  
  870. .sq7-flex-center {
  871.   justify-content: center;
  872.   align-items: center;
  873. }
  874.  
  875. .sq7-flex-wrap {
  876.   flex-wrap: wrap;
  877. }
  878.  
  879. .sq7-flex {
  880.   display: flex;
  881. }
  882.  
  883. .sq7-margin-top-md {
  884.   margin-top: var(--sq7-space-md);
  885. }
  886.  
  887. .sq7-bg {
  888.   --sq7-bg-o: 1;
  889.   background-color: hsla(var(--sq7-color-bg-hsl), var(--sq7-bg-o, 1));
  890. }
  891.  
  892. .sq7-hide {
  893.   display: none !important;
  894. }


JavaScript (_1_swipe-content.js)
  1. // File#: _1_swipe-content
  2. (function() {
  3. var SwipeContent = function(element) {
  4. this.element = element;
  5. this.delta = [false, false];
  6. this.dragging = false;
  7. this.intervalId = false;
  8. initSwipeContent(this);
  9. };
  10.  
  11. function initSwipeContent(content) {
  12. content.element.addEventListener('mousedown', handleEvent.bind(content));
  13. content.element.addEventListener('touchstart', handleEvent.bind(content), {passive: true});
  14. };
  15.  
  16. function initDragging(content) {
  17. //add event listeners
  18. content.element.addEventListener('mousemove', handleEvent.bind(content));
  19. content.element.addEventListener('touchmove', handleEvent.bind(content), {passive: true});
  20. content.element.addEventListener('mouseup', handleEvent.bind(content));
  21. content.element.addEventListener('mouseleave', handleEvent.bind(content));
  22. content.element.addEventListener('touchend', handleEvent.bind(content));
  23. };
  24.  
  25. function cancelDragging(content) {
  26. //remove event listeners
  27. if(content.intervalId) {
  28. (!window.requestAnimationFrame) ? clearInterval(content.intervalId) : window.cancelAnimationFrame(content.intervalId);
  29. content.intervalId = false;
  30. }
  31. content.element.removeEventListener('mousemove', handleEvent.bind(content));
  32. content.element.removeEventListener('touchmove', handleEvent.bind(content));
  33. content.element.removeEventListener('mouseup', handleEvent.bind(content));
  34. content.element.removeEventListener('mouseleave', handleEvent.bind(content));
  35. content.element.removeEventListener('touchend', handleEvent.bind(content));
  36. };
  37.  
  38. function handleEvent(event) {
  39. switch(event.type) {
  40. case 'mousedown':
  41. case 'touchstart':
  42. startDrag(this, event);
  43. break;
  44. case 'mousemove':
  45. case 'touchmove':
  46. drag(this, event);
  47. break;
  48. case 'mouseup':
  49. case 'mouseleave':
  50. case 'touchend':
  51. endDrag(this, event);
  52. break;
  53. }
  54. };
  55.  
  56. function startDrag(content, event) {
  57. content.dragging = true;
  58. // listen to drag movements
  59. initDragging(content);
  60. content.delta = [parseInt(unify(event).clientX), parseInt(unify(event).clientY)];
  61. // emit drag start event
  62. emitSwipeEvents(content, 'dragStart', content.delta, event.target);
  63. };
  64.  
  65. function endDrag(content, event) {
  66. cancelDragging(content);
  67. // credits: https://css-tricks.com/simple-swipe-with-vanilla-javascript/
  68. var dx = parseInt(unify(event).clientX), 
  69.     dy = parseInt(unify(event).clientY);
  70.  
  71.   // check if there was a left/right swipe
  72. if(content.delta && (content.delta[0] || content.delta[0] === 0)) {
  73.     var s = getSign(dx - content.delta[0]);
  74.  
  75. if(Math.abs(dx - content.delta[0]) > 30) {
  76. (< 0) ? emitSwipeEvents(content, 'swipeLeft', [dx, dy]) : emitSwipeEvents(content, 'swipeRight', [dx, dy]);
  77. }
  78.  
  79.     content.delta[0] = false;
  80.   }
  81. // check if there was a top/bottom swipe
  82.   if(content.delta && (content.delta[1] || content.delta[1] === 0)) {
  83.    var y = getSign(dy - content.delta[1]);
  84.  
  85.    if(Math.abs(dy - content.delta[1]) > 30) {
  86.      (< 0) ? emitSwipeEvents(content, 'swipeUp', [dx, dy]) : emitSwipeEvents(content, 'swipeDown', [dx, dy]);
  87.     }
  88.  
  89.     content.delta[1] = false;
  90.   }
  91. // emit drag end event
  92.   emitSwipeEvents(content, 'dragEnd', [dx, dy]);
  93.   content.dragging = false;
  94. };
  95.  
  96. function drag(content, event) {
  97. if(!content.dragging) return;
  98. // emit dragging event with coordinates
  99. (!window.requestAnimationFrame) 
  100. ? content.intervalId = setTimeout(function(){emitDrag.bind(content, event);}, 250) 
  101. : content.intervalId = window.requestAnimationFrame(emitDrag.bind(content, event));
  102. };
  103.  
  104. function emitDrag(event) {
  105. emitSwipeEvents(this, 'dragging', [parseInt(unify(event).clientX), parseInt(unify(event).clientY)]);
  106. };
  107.  
  108. function unify(event) { 
  109. // unify mouse and touch events
  110. return event.changedTouches ? event.changedTouches[0] : event; 
  111. };
  112.  
  113. function emitSwipeEvents(content, eventName, detail, el) {
  114. var trigger = false;
  115. if(el) trigger = el;
  116. // emit event with coordinates
  117. var event = new CustomEvent(eventName, {detail: {x: detail[0], y: detail[1], origin: trigger}});
  118. content.element.dispatchEvent(event);
  119. };
  120.  
  121. function getSign(x) {
  122. if(!Math.sign) {
  123. return ((> 0) - (< 0)) || +x;
  124. } else {
  125. return Math.sign(x);
  126. }
  127. };
  128.  
  129. window.SwipeContent = SwipeContent;
  130.  
  131. //initialize the SwipeContent objects
  132. var swipe = document.getElementsByClassName('js-swipe-content');
  133. if( swipe.length > 0 ) {
  134. for( var i = 0; i < swipe.length; i++) {
  135. (function(i){new SwipeContent(swipe[i]);})(i);
  136. }
  137. }
  138. }());


JavaScript (_2_slideshow.js)
  1. // utility functions
  2. if(!Util) function Util () {};
  3.  
  4. Util.hasClass = function(el, className) {
  5.   return el.classList.contains(className);
  6. };
  7.  
  8. Util.addClass = function(el, className) {
  9.   var classList = className.split(' ');
  10.   el.classList.add(classList[0]);
  11.   if (classList.length > 1) Util.addClass(el, classList.slice(1).join(' '));
  12. };
  13.  
  14. Util.removeClass = function(el, className) {
  15.   var classList = className.split(' ');
  16.   el.classList.remove(classList[0]);
  17.   if (classList.length > 1) Util.removeClass(el, classList.slice(1).join(' '));
  18. };
  19.  
  20. Util.setAttributes = function(el, attrs) {
  21.   for(var key in attrs) {
  22.     el.setAttribute(key, attrs[key]);
  23.   }
  24. };
  25.  
  26. Util.moveFocus = function (element) {
  27.   if( !element ) element = document.getElementsByTagName('body')[0];
  28.   element.focus();
  29.   if (document.activeElement !== element) {
  30.     element.setAttribute('tabindex','-1');
  31.     element.focus();
  32.   }
  33. };
  34.  
  35. Util.getIndexInArray = function(array, el) {
  36.   return Array.prototype.indexOf.call(array, el);
  37. };
  38.  
  39. Util.cssSupports = function(property, value) {
  40.   return CSS.supports(property, value);
  41. };
  42.  
  43. Util.extend = function() {
  44.   var extended = {};
  45.   var deep = false;
  46.   var i = 0;
  47.   var length = arguments.length;
  48.  
  49.   if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) {
  50.     deep = arguments[0];
  51.     i++;
  52.   }
  53.  
  54.   var merge = function (obj) {
  55.     for ( var prop in obj ) {
  56.       if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) {
  57.         if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) {
  58.           extended[prop] = extend( true, extended[prop], obj[prop] );
  59.         } else {
  60.           extended[prop] = obj[prop];
  61.         }
  62.       }
  63.     }
  64.   };
  65.  
  66.   for ( ; i < length; i++ ) {
  67.     var obj = arguments[i];
  68.     merge(obj);
  69.   }
  70.  
  71.   return extended;
  72. };
  73.  
  74. // File#: _2_slideshow
  75. (function() {
  76. var Slideshow = function(opts) {
  77. this.options = Util.extend(Slideshow.defaults , opts);
  78. this.element = this.options.element;
  79. this.items = this.element.getElementsByClassName('js-slideshow__item');
  80. this.controls = this.element.getElementsByClassName('js-slideshow__control'); 
  81. this.selectedSlide = 0;
  82. this.autoplayId = false;
  83. this.autoplayPaused = false;
  84. this.navigation = false;
  85. this.navCurrentLabel = false;
  86. this.ariaLive = false;
  87. this.moveFocus = false;
  88. this.animating = false;
  89. this.supportAnimation = Util.cssSupports('transition');
  90. this.animationOff = (!Util.hasClass(this.element, 'slideshow--transition-fade') && !Util.hasClass(this.element, 'slideshow--transition-slide') && !Util.hasClass(this.element, 'slideshow--transition-prx'));
  91. this.animationType = Util.hasClass(this.element, 'slideshow--transition-prx') ? 'prx' : 'slide';
  92. this.animatingClass = 'slideshow--is-animating';
  93. initSlideshow(this);
  94. initSlideshowEvents(this);
  95. initAnimationEndEvents(this);
  96. };
  97.  
  98. Slideshow.prototype.showNext = function() {
  99. showNewItem(this, this.selectedSlide + 1, 'next');
  100. };
  101.  
  102. Slideshow.prototype.showPrev = function() {
  103. showNewItem(this, this.selectedSlide - 1, 'prev');
  104. };
  105.  
  106. Slideshow.prototype.showItem = function(index) {
  107. showNewItem(this, index, false);
  108. };
  109.  
  110. Slideshow.prototype.startAutoplay = function() {
  111. var self = this;
  112. if(this.options.autoplay && !this.autoplayId && !this.autoplayPaused) {
  113. self.autoplayId = setInterval(function(){
  114. self.showNext();
  115. }, self.options.autoplayInterval);
  116. }
  117. };
  118.  
  119. Slideshow.prototype.pauseAutoplay = function() {
  120. var self = this;
  121. if(this.options.autoplay) {
  122. clearInterval(self.autoplayId);
  123. self.autoplayId = false;
  124. }
  125. };
  126.  
  127. function initSlideshow(slideshow) { // basic slideshow settings
  128. // if no slide has been selected -> select the first one
  129. if(slideshow.element.getElementsByClassName('slideshow__item--selected').length < 1) Util.addClass(slideshow.items[0], 'slideshow__item--selected');
  130. slideshow.selectedSlide = Util.getIndexInArray(slideshow.items, slideshow.element.getElementsByClassName('slideshow__item--selected')[0]);
  131. // create an element that will be used to announce the new visible slide to SR
  132. var srLiveArea = document.createElement('div');
  133. Util.setAttributes(srLiveArea, {'class': 'sq7-sr-only js-slideshow__aria-live', 'aria-live': 'polite', 'aria-atomic': 'true'});
  134. slideshow.element.appendChild(srLiveArea);
  135. slideshow.ariaLive = srLiveArea;
  136. };
  137.  
  138. function initSlideshowEvents(slideshow) {
  139. // if slideshow navigation is on -> create navigation HTML and add event listeners
  140. if(slideshow.options.navigation) {
  141. // check if navigation has already been included
  142. if(slideshow.element.getElementsByClassName('js-slideshow__navigation').length == 0) {
  143. var navigation = document.createElement('ol'),
  144. navChildren = '';
  145.  
  146. var navClasses = slideshow.options.navigationClass+' js-slideshow__navigation';
  147. if(slideshow.items.length <= 1) {
  148. navClasses = navClasses + ' sq7-hide';
  149. }
  150.  
  151. navigation.setAttribute('class', navClasses);
  152. for(var i = 0; i < slideshow.items.length; i++) {
  153. var className = (== slideshow.selectedSlide) ? 'class="'+slideshow.options.navigationItemClass+' '+slideshow.options.navigationItemClass+'--selected js-slideshow__nav-item"' :  'class="'+slideshow.options.navigationItemClass+' js-slideshow__nav-item"',
  154. navCurrentLabel = (== slideshow.selectedSlide) ? '<span class="sq7-sr-only js-slideshow__nav-current-label">Current Item</span>' : '';
  155. navChildren = navChildren + '<li '+className+'><button><span class="sq7-sr-only">'+ (i+1) + '</span>'+navCurrentLabel+'</button></li>';
  156. }
  157. navigation.innerHTML = navChildren;
  158. slideshow.element.appendChild(navigation);
  159. }
  160.  
  161. slideshow.navCurrentLabel = slideshow.element.getElementsByClassName('js-slideshow__nav-current-label')[0]; 
  162. slideshow.navigation = slideshow.element.getElementsByClassName('js-slideshow__nav-item');
  163.  
  164. var dotsNavigation = slideshow.element.getElementsByClassName('js-slideshow__navigation')[0];
  165.  
  166. dotsNavigation.addEventListener('click', function(event){
  167. navigateSlide(slideshow, event, true);
  168. });
  169. dotsNavigation.addEventListener('keyup', function(event){
  170. navigateSlide(slideshow, event, (event.key.toLowerCase() == 'enter'));
  171. });
  172. }
  173. // slideshow arrow controls
  174. if(slideshow.controls.length > 0) {
  175. // hide controls if one item available
  176. if(slideshow.items.length <= 1) {
  177. Util.addClass(slideshow.controls[0], 'sq7-hide');
  178. Util.addClass(slideshow.controls[1], 'sq7-hide');
  179. }
  180. slideshow.controls[0].addEventListener('click', function(event){
  181. event.preventDefault();
  182. slideshow.showPrev();
  183. updateAriaLive(slideshow);
  184. });
  185. slideshow.controls[1].addEventListener('click', function(event){
  186. event.preventDefault();
  187. slideshow.showNext();
  188. updateAriaLive(slideshow);
  189. });
  190. }
  191. // swipe events
  192. if(slideshow.options.swipe) {
  193. //init swipe
  194. new SwipeContent(slideshow.element);
  195. slideshow.element.addEventListener('swipeLeft', function(event){
  196. slideshow.showNext();
  197. });
  198. slideshow.element.addEventListener('swipeRight', function(event){
  199. slideshow.showPrev();
  200. });
  201. }
  202. // autoplay
  203. if(slideshow.options.autoplay) {
  204. slideshow.startAutoplay();
  205. // pause autoplay if user is interacting with the slideshow
  206. if(!slideshow.options.autoplayOnHover) {
  207. slideshow.element.addEventListener('mouseenter', function(event){
  208. slideshow.pauseAutoplay();
  209. slideshow.autoplayPaused = true;
  210. });
  211. slideshow.element.addEventListener('mouseleave', function(event){
  212. slideshow.autoplayPaused = false;
  213. slideshow.startAutoplay();
  214. });
  215. }
  216. if(!slideshow.options.autoplayOnFocus) {
  217. slideshow.element.addEventListener('focusin', function(event){
  218. slideshow.pauseAutoplay();
  219. slideshow.autoplayPaused = true;
  220. });
  221. slideshow.element.addEventListener('focusout', function(event){
  222. slideshow.autoplayPaused = false;
  223. slideshow.startAutoplay();
  224. });
  225. }
  226. }
  227. // detect if external buttons control the slideshow
  228. var slideshowId = slideshow.element.getAttribute('id');
  229. if(slideshowId) {
  230. var externalControls = document.querySelectorAll('[data-controls="'+slideshowId+'"]');
  231. for(var i = 0; i < externalControls.length; i++) {
  232. (function(i){externalControlSlide(slideshow, externalControls[i]);})(i);
  233. }
  234. }
  235. // custom event to trigger selection of a new slide element
  236. slideshow.element.addEventListener('selectNewItem', function(event){
  237. // check if slide is already selected
  238. if(event.detail) {
  239. if(event.detail - 1 == slideshow.selectedSlide) return;
  240. showNewItem(slideshow, event.detail - 1, false);
  241. }
  242. });
  243.  
  244. // keyboard navigation
  245. slideshow.element.addEventListener('keydown', function(event){
  246. if(event.keyCode && event.keyCode == 39 || event.key && event.key.toLowerCase() == 'arrowright') {
  247. slideshow.showNext();
  248. } else if(event.keyCode && event.keyCode == 37 || event.key && event.key.toLowerCase() == 'arrowleft') {
  249. slideshow.showPrev();
  250. }
  251. });
  252. };
  253.  
  254. function navigateSlide(slideshow, event, keyNav) { 
  255. // user has interacted with the slideshow navigation -> update visible slide
  256. var target = ( Util.hasClass(event.target, 'js-slideshow__nav-item') ) ? event.target : event.target.closest('.js-slideshow__nav-item');
  257. if(keyNav && target && !Util.hasClass(target, 'slideshow__nav-item--selected')) {
  258. slideshow.showItem(Util.getIndexInArray(slideshow.navigation, target));
  259. slideshow.moveFocus = true;
  260. updateAriaLive(slideshow);
  261. }
  262. };
  263.  
  264. function initAnimationEndEvents(slideshow) {
  265. // remove animation classes at the end of a slide transition
  266. for( var i = 0; i < slideshow.items.length; i++) {
  267. (function(i){
  268. slideshow.items[i].addEventListener('animationend', function(){resetAnimationEnd(slideshow, slideshow.items[i]);});
  269. slideshow.items[i].addEventListener('transitionend', function(){resetAnimationEnd(slideshow, slideshow.items[i]);});
  270. })(i);
  271. }
  272. };
  273.  
  274. function resetAnimationEnd(slideshow, item) {
  275. setTimeout(function(){ // add a delay between the end of animation and slideshow reset - improve animation performance
  276. if(Util.hasClass(item,'slideshow__item--selected')) {
  277. if(slideshow.moveFocus) Util.moveFocus(item);
  278. emitSlideshowEvent(slideshow, 'newItemVisible', slideshow.selectedSlide);
  279. slideshow.moveFocus = false;
  280. }
  281. Util.removeClass(item, 'slideshow__item--'+slideshow.animationType+'-out-left slideshow__item--'+slideshow.animationType+'-out-right slideshow__item--'+slideshow.animationType+'-in-left slideshow__item--'+slideshow.animationType+'-in-right');
  282. item.removeAttribute('aria-hidden');
  283. slideshow.animating = false;
  284. Util.removeClass(slideshow.element, slideshow.animatingClass); 
  285. }, 100);
  286. };
  287.  
  288. function showNewItem(slideshow, index, bool) {
  289. if(slideshow.items.length <= 1) return;
  290. if(slideshow.animating && slideshow.supportAnimation) return;
  291. slideshow.animating = true;
  292. Util.addClass(slideshow.element, slideshow.animatingClass); 
  293. if(index < 0) index = slideshow.items.length - 1;
  294. else if(index >= slideshow.items.length) index = 0;
  295. // skip slideshow item if it is hidden
  296. if(bool && Util.hasClass(slideshow.items[index], 'sq7-hide')) {
  297. slideshow.animating = false;
  298. index = bool == 'next' ? index + 1 : index - 1;
  299. showNewItem(slideshow, index, bool);
  300. return;
  301. }
  302. // index of new slide is equal to index of slide selected item
  303. if(index == slideshow.selectedSlide) {
  304. slideshow.animating = false;
  305. return;
  306. }
  307. var exitItemClass = getExitItemClass(slideshow, bool, slideshow.selectedSlide, index);
  308. var enterItemClass = getEnterItemClass(slideshow, bool, slideshow.selectedSlide, index);
  309. // transition between slides
  310. if(!slideshow.animationOff) Util.addClass(slideshow.items[slideshow.selectedSlide], exitItemClass);
  311. Util.removeClass(slideshow.items[slideshow.selectedSlide], 'slideshow__item--selected');
  312. slideshow.items[slideshow.selectedSlide].setAttribute('aria-hidden', 'true'); //hide to sr element that is exiting the viewport
  313. if(slideshow.animationOff) {
  314. Util.addClass(slideshow.items[index], 'slideshow__item--selected');
  315. } else {
  316. Util.addClass(slideshow.items[index], enterItemClass+' slideshow__item--selected');
  317. }
  318. // reset slider navigation appearance
  319. resetSlideshowNav(slideshow, index, slideshow.selectedSlide);
  320. slideshow.selectedSlide = index;
  321. // reset autoplay
  322. slideshow.pauseAutoplay();
  323. slideshow.startAutoplay();
  324. // reset controls/navigation color themes
  325. resetSlideshowTheme(slideshow, index);
  326. // emit event
  327. emitSlideshowEvent(slideshow, 'newItemSelected', slideshow.selectedSlide);
  328. if(slideshow.animationOff) {
  329. slideshow.animating = false;
  330. Util.removeClass(slideshow.element, slideshow.animatingClass);
  331. }
  332. };
  333.  
  334. function getExitItemClass(slideshow, bool, oldIndex, newIndex) {
  335. var className = '';
  336. if(bool) {
  337. className = (bool == 'next') ? 'slideshow__item--'+slideshow.animationType+'-out-right' : 'slideshow__item--'+slideshow.animationType+'-out-left'; 
  338. } else {
  339. className = (newIndex < oldIndex) ? 'slideshow__item--'+slideshow.animationType+'-out-left' : 'slideshow__item--'+slideshow.animationType+'-out-right';
  340. }
  341. return className;
  342. };
  343.  
  344. function getEnterItemClass(slideshow, bool, oldIndex, newIndex) {
  345. var className = '';
  346. if(bool) {
  347. className = (bool == 'next') ? 'slideshow__item--'+slideshow.animationType+'-in-right' : 'slideshow__item--'+slideshow.animationType+'-in-left'; 
  348. } else {
  349. className = (newIndex < oldIndex) ? 'slideshow__item--'+slideshow.animationType+'-in-left' : 'slideshow__item--'+slideshow.animationType+'-in-right';
  350. }
  351. return className;
  352. };
  353.  
  354. function resetSlideshowNav(slideshow, newIndex, oldIndex) {
  355. if(slideshow.navigation) {
  356. Util.removeClass(slideshow.navigation[oldIndex], 'slideshow__nav-item--selected');
  357. Util.addClass(slideshow.navigation[newIndex], 'slideshow__nav-item--selected');
  358. slideshow.navCurrentLabel.parentElement.removeChild(slideshow.navCurrentLabel);
  359. slideshow.navigation[newIndex].getElementsByTagName('button')[0].appendChild(slideshow.navCurrentLabel);
  360. }
  361. };
  362.  
  363. function resetSlideshowTheme(slideshow, newIndex) {
  364. var dataTheme = slideshow.items[newIndex].getAttribute('data-theme');
  365. if(dataTheme) {
  366. if(slideshow.navigation) slideshow.navigation[0].parentElement.setAttribute('data-theme', dataTheme);
  367. if(slideshow.controls[0]) slideshow.controls[0].parentElement.setAttribute('data-theme', dataTheme);
  368. } else {
  369. if(slideshow.navigation) slideshow.navigation[0].parentElement.removeAttribute('data-theme');
  370. if(slideshow.controls[0]) slideshow.controls[0].parentElement.removeAttribute('data-theme');
  371. }
  372. };
  373.  
  374. function emitSlideshowEvent(slideshow, eventName, detail) {
  375. var event = new CustomEvent(eventName, {detail: detail});
  376. slideshow.element.dispatchEvent(event);
  377. };
  378.  
  379. function updateAriaLive(slideshow) {
  380. slideshow.ariaLive.innerHTML = 'Item '+(slideshow.selectedSlide + 1)+' of '+slideshow.items.length;
  381. };
  382.  
  383. function externalControlSlide(slideshow, button) { // control slideshow using external element
  384. button.addEventListener('click', function(event){
  385. var index = button.getAttribute('data-index');
  386. if(!index || index == slideshow.selectedSlide + 1) return;
  387. event.preventDefault();
  388. showNewItem(slideshow, index - 1, false);
  389. });
  390. };
  391.  
  392. Slideshow.defaults = {
  393.     element : '',
  394.     navigation : true,
  395.     autoplay : false,
  396. autoplayOnHover: false,
  397. autoplayOnFocus: false,
  398.     autoplayInterval: 5000,
  399. navigationItemClass: 'slideshow__nav-item',
  400.     navigationClass: 'slideshow__navigation',
  401.     swipe: false
  402.   };
  403.  
  404. window.Slideshow = Slideshow;
  405.  
  406. //initialize the Slideshow objects
  407. var slideshows = document.getElementsByClassName('js-slideshow');
  408. if( slideshows.length > 0 ) {
  409. for( var i = 0; i < slideshows.length; i++) {
  410. (function(i){
  411. var navigation = (slideshows[i].getAttribute('data-navigation') && slideshows[i].getAttribute('data-navigation') == 'off') ? false : true,
  412. autoplay = (slideshows[i].getAttribute('data-autoplay') && slideshows[i].getAttribute('data-autoplay') == 'on') ? true : false,
  413. autoplayOnHover = (slideshows[i].getAttribute('data-autoplay-hover') && slideshows[i].getAttribute('data-autoplay-hover') == 'on') ? true : false,
  414. autoplayOnFocus = (slideshows[i].getAttribute('data-autoplay-focus') && slideshows[i].getAttribute('data-autoplay-focus') == 'on') ? true : false,
  415. autoplayInterval = (slideshows[i].getAttribute('data-autoplay-interval')) ? slideshows[i].getAttribute('data-autoplay-interval') : 5000,
  416. swipe = (slideshows[i].getAttribute('data-swipe') && slideshows[i].getAttribute('data-swipe') == 'on') ? true : false,
  417. navigationItemClass = slideshows[i].getAttribute('data-navigation-item-class') ? slideshows[i].getAttribute('data-navigation-item-class') : 'slideshow__nav-item',
  418.           navigationClass = slideshows[i].getAttribute('data-navigation-class') ? slideshows[i].getAttribute('data-navigation-class') : 'slideshow__navigation';
  419. new Slideshow({element: slideshows[i], navigation: navigation, autoplay : autoplay, autoplayOnHover: autoplayOnHover, autoplayOnFocus: autoplayOnFocus, autoplayInterval : autoplayInterval, swipe : swipe, navigationItemClass: navigationItemClass, navigationClass: navigationClass});
  420. })(i);
  421. }
  422. }
  423. }());


Now, let's focus on the more complex part, that is, after viewing the codes and understanding their general functioning, we will now insert the codes into our WebSite X5 project.


Firstly, it will be essential to set up the page where we want to insert our PHP plugin. To do this, we can go to Step 3 > Page Properties > Expert > Generated File Extension > Select "php".


After properly setting up the PHP page, we can now go to Step 4 of our page and insert an HTML Code Object. Once inserted, we can begin by putting in our plugin. First, we copy and paste the HTML code, which is the backbone of our slider. After this step, we can proceed with the insertion of the PHP code, by copying and pasting it where the <!-- INSERT THE PHP CODE HERE --> text is present. For practical reasons, we have not inserted the code integrally but proposed it in pieces like a puzzle, as the PHP code can be inserted into other codes according to our needs.


After inserting the PHP code, it is essential to insert our database connection data, i.e., we need to replace the localhost entries from line 7 to 10 with those of our hosting service.


Now it's time for the CSS code, which we will insert inside the Expert section of our HTML Code object.


After inserting the CSS code, the penultimate step is to insert the JavaScript code. These two codes can be inserted at the end of our HTML code in two ways. We can save the codes in one or two files, for example, by creating a .txt text document and then changing the extension to .js simply by renaming it. Once the file is created, we can add it in the Expert section by attaching it with the "Add" button, selecting the "Link the file" option before confirming the upload. This way, the file will be inserted and connected correctly.


Just as done with the JavaScript code, we can do the same with the CSS code mentioned earlier. That is, we paste the code into a text file and then change the extension from .txt to .css and attach the file in the same way.


Alternatively, we can include the CSS code within the <style> CODE HERE </style> tags, but also the JavaScript code, in the tags dedicated to it <script> CODE HERE </script>, and then insert the complete code directly where we inserted the HTML code or alternatively in Step 3 > Page Properties > Expert > Custom Code.



In conclusion, the Client Testimonials Carousel code is a useful tool for managing user comments on WebSite X5 in an automated way and displaying user feedback effectively and visibly on the site's main page. However, you must have a basic understanding of PHP and database operations to use the code.




The PHP code offers further customization possibilities thanks to a simple change near line 21. To facilitate the use of the code, we have implemented two preset modes, both of which can be modified according to the user's preferences.


To avoid errors, it is important to comment out the unused mode by adding two slashes // before the code. Alternatively, you can delete the mode you don't want to use.


The two preset modes allow you to select comments based on the order in which they appear or based on the rating associated with each comment. In this way, it is possible to choose whether to show the best reviews randomly or to select the specific ones of most interest. This option is especially useful for showing site visitors the most helpful and helpful comments. We hope that the article has been useful to you and has provided you with interesting information! If you liked it, share it on social networks or with friends.


Have ideas for new posts? Contact us! Comment or write.

We are always looking for new interesting and stimulating topics to discuss and we are happy to evaluate your proposals. Comment below or send us an email and we will get back to you as soon as possible. Thanks for reading our blog!

Cat Coding








There are no reviews yet.
0
0
0
0
0
Back to content