Action: imageslider
Compatible with: R6.1 Current version: 0.9 Credits: WikiAdmin |
Repo: action/imageslider.php
CSS image slider
{{imageslider}}
action/imageslider.php
<?php if (!defined('IN_WACKO')) { exit; } /* images as slider The sole condition is that all the images must be exactly the same size. version: 0.9 https://wackowiki.org/doc/Dev/PatchesHacks/ImageSlider */ $info = <<<EOD Description: Showing images as slider for uploaded files. Usage: {{imageslider}} Options: [page="PageName" or global=1] [order="time|name_desc|size|size_desc|ext"] [owner="UserName"] [media=1] [max=number] EOD; // set defaults $global ??= 0; $help ??= 0; $max ??= null; $media ??= 1; $order ??= ''; $owner ??= ''; $page ??= ''; $track ??= 0; if ($help) { $tpl->help = $this->help($info, 'imageslider'); return; } if ($max) { $limit = $max; } else { $limit = 50; } $order_by = match($order) { 'ext' => 'file_ext ASC', 'name_desc' => 'file_name DESC', 'size' => 'file_size ASC', 'size_desc' => 'file_size DESC', 'time' => 'created ASC', 'time_desc' => 'created DESC', default => 'file_name ASC', }; $width_settings = '100%'; // 100%, 300px, etc. $files = []; $page_id = null; // default options for slider $time_on_slide = 6; $time_between_slides = 1; $animation_timing = 'ease'; $slidy_direction = 'left'; $css_animation_name = 'slidy'; // options: data-caption, alt, none $caption_source = 'data-caption'; $caption_background = 'rgba(0,0,0,0.3)'; $caption_color = '#fff'; $caption_font = 'Avenir, Avenir Next, Droid Sans, DroidSansRegular, Corbel, Tahoma, Geneva, sans-serif'; // options: top, bottom $caption_position = 'bottom'; // options: slide, perm, fade $caption_appear = 'slide'; $caption_size = '1.6rem'; // same units $caption_padding = '.6rem'; if (!$global) { if ($page == '') { $tag = $this->tag; $page_id = $this->page['page_id']; } else { $tag = $this->unwrap_link($page); if ($_page_id = $this->get_page_id($tag)) { $page_id = $_page_id; } } $can_view = $this->has_access('read', $page_id) || $this->is_admin() || $this->is_owner($page_id); } else { $can_view = true; $tag = $this->tag; } if ($can_view) { if ($global || ($tag == $this->tag)) { $filepage = $this->page; } else { $filepage = $this->load_page($tag, 0, null, LOAD_CACHE, LOAD_META); } if (!$global && !isset($filepage['page_id'])) { return; } $selector = "FROM " . $this->prefix . "file f " . "INNER JOIN " . $this->prefix . "user u ON (f.user_id = u.user_id) " . "WHERE f.page_id = " . ($global ? 0 : (int) $filepage['page_id']) . " " . "AND f.picture_w <> 0 " . ($owner ? "AND u.user_name = " . $this->db->q($owner) . " " : '') . "AND f.deleted <> 1 "; $count = $this->db->load_single( "SELECT COUNT(f.file_id) AS n " . $selector, true); $pagination = $this->pagination($count['n'], $limit, 'f'); // load files list $files = $this->db->load_all( "SELECT f.file_id, f.page_id, f.user_id, f.file_size, f.picture_w, f.picture_h, f.file_ext, f.file_lang, f.file_name, f.file_description, f.created, u.user_name AS user " . $selector . "ORDER BY f." . $order_by . " " . "LIMIT {$pagination['offset']}, {$limit}", true); // display if (!$global) { $path2 = 'file:/' . $tag . '/'; } else { $path2 = 'file:/'; } if ($factor = count($files)) { // calculate data for image slider CSS // count the number of images in the slide, including the new cloned element $img_count = $factor + 1; // calculate the total length of the animation by multiplying the number of _actual_ images by the amount of time for both static display of each image and motion between them $total_time = ($time_on_slide + $time_between_slides) * ($img_count - 1); // determine the percentage of time an individual image is held static during the animation $slide_ratio = ($time_on_slide / $total_time) * 100; // determine the percentage of time for an individual movement $move_ratio = ($time_between_slides / $total_time) * 100; // work out how wide each image should be in the slidy, as a percentage. $base_percentage = 100 / $img_count; // set the initial position of the slidy element $position = 0; $img_width = $img_count * 100; $slidy = ''; if ($slidy_direction == 'right') { $slidy .= "0% \t{ left: -" . (($img_count - 1) * 100) . "%; }\n"; for ($i = $img_count - 1; $i > 0; $i--) { $position += $slide_ratio; // make the keyframe the position of the image $slidy .= "\t\t" . $position . "% \t{ left: -" . ($i * 100) . "%; }\n"; $position += $move_ratio; // make the postion for the _next_ slide $slidy .= "\t\t" . $position . "% \t{ left: -" . (($i - 1) * 100) . "%; }\n"; } } else { $slidy .= "0% \t{ left: 0%; }\n"; // the slider is moving to the left for ($i = 0; $i < ($img_count - 1); $i++) { $position += $slide_ratio; // make the keyframe the position of the image $slidy .= "\t\t" . $position . "% \t{ left: -" . ($i * 100) . "%; }\n"; $position += $move_ratio; // make the postion for the _next_ slide $slidy .= "\t\t" . $position . "% \t{ left: -" . (($i + 1) * 100) . "%; }\n"; } } $tpl->css = <<<EOD <style> div#captioned-gallery { width: 100%; overflow: hidden; } figure { margin: 0; } figure.slider { position: relative; width: {$img_width}%; font-size: 0; animation: {$total_time}s {$animation_timing} slidy infinite; } figure.slider:hover { /* animation: animation 1s 16 ease; */ animation-play-state: paused; } figure.slider figure { width: {$base_percentage}%; height: auto; display: inline-block; position: inherit; } figure.slider img { width: {$width_settings}; height: auto; } figure.slider figure figcaption { position: absolute; bottom: 0; background: rgba(0,0,0,0.3); color: #fff; width: 100%; font-size: 1rem; padding: .6rem; } div#slider figure { position: relative; width: {$img_width}%; margin: 0; padding: 0; font-size: 0; left: 0; text-align: left; animation: {$total_time}s {$animation_timing} slidy infinite; } @media screen and (max-width: 500px) { figure.slider figure figcaption { font-size: 1.2rem; } } /* figure.slider figure figcaption { position: absolute; bottom: -3.5rem; background: rgba(0,0,0,0.3); color: #fff; width: 100%; font-size: 2rem; padding: .6rem; transition: .5s bottom; } figure.slider figure:hover figcaption { bottom: 0; } figure.slider figure:hover + figure figcaption { bottom: 0; } */ @keyframes slidy { {$slidy} } </style> EOD; // adding at the end a clone of the first array for transition loop $files[] = $files[0]; $n = 0; $tpl->enter('n_'); foreach($files as $file) { if ($file['picture_h']) // missing: svg! { $n++; $this->file_cache[$file['page_id']][$file['file_name']] = $file; $desc = $this->format($file['file_description'], 'typografica', ['lang' => $file['file_lang']]); if ($desc == '') { $desc = NBSP; // No-Break Space } $file_name = $file['file_name']; $text = $media ? '' : $file_name; $tpl->image = $this->link($path2 . $file_name, '', $text, '', $track); $tpl->n = $n; $tpl->count = $count['n']; $tpl->desc = $desc; } } $tpl->leave(); // n } else { $tpl->nofile = $this->_t('FileNotFound'); } unset($files); } else { $tpl->noaccess = true; }
action/template/imageslider.tpl
[ === main === ] [ ' help ' ] [ ' css ' ][ ' nofile ' ] <div id="captioned-gallery"> <figure class="slider"> [= n _ = <figure> [ ' image ' ] <figcaption>[ ' n ' ]/[ ' count ' ] [ ' desc ' ]</figcaption> </figure> =] </figure> </div> [= noaccess _ = [ ' _t: ActionDenied ' ] =]
1. Documentation
The sole condition is that all the images must be exactly the same size.
2. How to
%%(wacko wrapper=page wrapper_width=600)
{{imageslider}}
%%
2.1. local usage of repository
symlink the gallery action from community action folder in wacko/action and wacko/action/template folder in repo
ln -s ../../community/action/imageslider.php imageslider.php
ln -s ../../../community/action/template/imageslider.tpl imageslider.tpl
3. Changelog
0.1 Initial version
0.7 Updated to work with R.6.1 (PHP 8.0, Null coalescing assignment operator)
0.8 added order="name_desc"
and changed time field names
0.9 added template
4. To Do
- make parameters like direction, size, time and caption accessible for action
- modify the action for your purpose
Referring pages: