Commit 8dce5882 by Manzar Hussain

view slide show

parent 98dbbff2
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>Views Slideshow</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="views-slideshow">Views Slideshow</h1>
<h2 id="introduction">INTRODUCTION</h2>
<p>Views Slideshow can create slideshows out any content on your Drupal site - whether that is images, images on content or full rendered entities. The <code>views_slideshow</code> module provides a base/plugin system/api for building full featured slideshows within the Views UI. This project also includes a module implementing that base; <code>views_slideshow_cycle</code>. For most users, you’ll just want to enable both of them and install pre-reqs. For advanced users you can create your own implementation - and there are other implementations for Drupal 7 available (see below).</p>
<p>Built in and most/all of the implementations are powered by jQuery, and are highly customizable: you may choose slideshow settings for each View display you create.</p>
<h3 id="potential-uses">Potential Uses</h3>
<ul>
<li>News item slideshow (such as the title, image and teaser of the last 5 news articles submitted)</li>
<li>The Last X number of X submitted (images, videos, blog entries, forum posts, comments, testimonials, etc.).</li>
<li>Rotate any image, based on any filters you can apply in views.</li>
<li>Hottest new products for any ecommerce drupal site.</li>
<li>Rotate contact links, share links, etc.</li>
<li>You can even rotate entire nodes, categories, image galleries, etc.</li>
<li>It’s also a great space saver. Places where you had multiple images or items such as RSS feeds or category listings can now be presented in a slideshow.</li>
</ul>
<h2 id="requirements">REQUIREMENTS</h2>
<ul>
<li>Views Slideshow 8.x-4.x requires Drupal 8 &amp; the core Views module enabled.</li>
<li>There is no upgrade path from Views Slideshow for Drupal 7.</li>
<li>Views Slideshow Cycle (Which most users should use) requires some JavaScript libraries:
<ul>
<li><a href="https://github.com/malsup/cycle">jQuery Cycle 3.x</a></li>
<li><a href="https://github.com/douglascrockford/JSON-js">JSON2</a></li>
<li><a href="https://github.com/briancherne/jquery-hoverIntent">jQuery HoverIntent</a></li>
<li><a href="https://github.com/tobia/Pause">jQuery Pause</a></li>
</ul></li>
</ul>
<h2 id="installation">INSTALLATION</h2>
<p>Install as you would normally install a contributed Drupal module. See the <a href="https://drupal.org/documentation/install/modules-themes/modules-8">Drupal 8 Instructions</a> if required in the Drupal documentation for further information. Note there are two modules included in this project; Views Slideshow &amp; Views Slideshow Cycle. In most cases you will need/want to enable both of them.</p>
<p>If you are using the Views Slideshow Cycle sub-module, you will also need to install some JavaScript libraries. The required libraries are:</p>
<ul>
<li><a href="https://github.com/malsup/cycle">jQuery Cycle 3.x</a> in <code>/libraries/jquery.cycle</code></li>
<li><a href="https://github.com/douglascrockford/JSON-js">JSON2</a> in <code>/libraries/json2</code></li>
<li><a href="https://github.com/briancherne/jquery-hoverIntent">jQuery HoverIntent</a> in <code>/libraries/jquery.hoverIntent</code></li>
<li><a href="https://github.com/tobia/Pause">jQuery Pause</a> in <code>/libraries/jquery.pause</code></li>
</ul>
<p>It is recommended to use <a href="https://drush.org">Drush</a> to automatically install the requirements to the right spot. To install all of the libraries to the right places, run <code>drush dl-cycle-lib</code>.</p>
<p>If you don’t have Drush available, or would prefer to install manually, you can do so. An example of code you could run in your Drupal root dir to download to the right place:</p>
<pre><code> mkdir -p libraries/jquery.cycle &amp;&amp; cd $_ &amp;&amp; wget https://malsup.github.io/jquery.cycle.all.js \
&amp;&amp; mkdir -p ../../libraries/jquery.hoverIntent &amp;&amp; cd $_ &amp;&amp; wget https://raw.githubusercontent.com/briancherne/jquery-hoverIntent/master/jquery.hoverIntent.js \
&amp;&amp; mkdir -p ../../libraries/json2 &amp;&amp; cd $_ &amp;&amp; wget https://raw.githubusercontent.com/douglascrockford/JSON-js/master/json2.js \
&amp;&amp; mkdir -p ../../libraries/jquery.pause &amp;&amp; cd $_ &amp;&amp; wget https://raw.githubusercontent.com/tobia/Pause/master/jquery.pause.js</code></pre>
<h2 id="configuration">CONFIGURATION</h2>
<p>Configuration is on a per view/display basis.</p>
<p>Most standard views settings will work fine in conjunction with Views Slideshow. However, grouping may or may not work. Under most use cases the pager should be set to either <code>Display a specified number of items</code> or <code>Display all</code>.</p>
<p>To get started configuring your slideshow, set <code>Slideshow</code> as the display format and configure the slideshow as desired under Format Settings. Next select the <em>Skin</em> - usually <code>Default</code> (only one provided with the module). Then select the <em>Slideshow Type</em>; for most users, this will just be <code>cycle</code> with the <code>views_slideshow_cycle</code> module.</p>
<p>Below that, there is a lot of different options which should have better documentation.</p>
<h3 id="see-also">See also:</h3>
<ul>
<li><a href="https://www.ostraining.com/blog/drupal/drupal-8-slideshows">OS Training tutorial on Views Slideshow</a></li>
</ul>
<h2 id="contributors">CONTRIBUTORS</h2>
<p>Current maintainer:</p>
<ul>
<li><a href="https://www.drupal.org/u/neslee-canil-pinto">Neslee Canil Pinto</a></li>
</ul>
<p>Past maintainers:</p>
<ul>
<li><p><a href="https://www.drupal.org/u/vbouchet">vbouchet</a> Initial 8.x port</p></li>
<li><p><a href="https://www.drupal.org/u/redndahead">Adam Moore</a></p></li>
<li><a href="https://www.drupal.org/u/nickwilde">Nick Wilde</a></li>
</ul>
<p>Also, thanks to the many contributors via the issue queues.</p>
</body>
</html>
# Views Slideshow
## INTRODUCTION
Views Slideshow can create slideshows out any content on your Drupal site -
whether that is images, images on content or full rendered entities. The
`views_slideshow` module provides a base/plugin system/api for building full
featured slideshows within the Views UI. This project also includes a module
implementing that base; `views_slideshow_cycle`. For most users, you'll just
want to enable both of them and install pre-reqs. For advanced users you can
create your own implementation - and there are other implementations for Drupal
7 available (see below).
Built in and most/all of the implementations are powered by jQuery, and are
highly customizable: you may choose slideshow settings for each View display
you create.
### Potential Uses
* News item slideshow (such as the title, image and teaser of the last 5 news
articles submitted)
* The Last X number of X submitted (images, videos, blog entries, forum posts,
comments, testimonials, etc.).
* Rotate any image, based on any filters you can apply in views.
* Hottest new products for any ecommerce drupal site.
* Rotate contact links, share links, etc.
* You can even rotate entire nodes, categories, image galleries, etc.
* It's also a great space saver. Places where you had multiple images or items
such as RSS feeds or category listings can now be presented in a slideshow.
## REQUIREMENTS
* Views Slideshow 8.x-4.x requires Drupal 8 & the core Views module enabled.
* There is no upgrade path from Views Slideshow for Drupal 7.
* Views Slideshow Cycle (Which most users should use) requires some JavaScript
libraries:
* [jQuery Cycle 3.x](https://github.com/malsup/cycle)
* [JSON2](https://github.com/douglascrockford/JSON-js)
* [jQuery HoverIntent](https://github.com/briancherne/jquery-hoverIntent)
* [jQuery Pause](https://github.com/tobia/Pause)
## INSTALLATION
Install as you would normally install a contributed Drupal module. See the
[Drupal 8 Instructions](https://drupal.org/documentation/install/modules-themes/modules-8)
if required in the Drupal documentation for further information. Note there are
two modules included in this project; Views Slideshow & Views Slideshow Cycle.
In most cases you will need/want to enable both of them.
If you are using the Views Slideshow Cycle sub-module, you will also need to
install some JavaScript libraries. The required libraries are:
* [jQuery Cycle 3.x](https://github.com/malsup/cycle) in
`/libraries/jquery.cycle`
* [JSON2](https://github.com/douglascrockford/JSON-js) in `/libraries/json2`
* [jQuery HoverIntent](https://github.com/briancherne/jquery-hoverIntent)
in `/libraries/jquery.hoverIntent`
* [jQuery Pause](https://github.com/tobia/Pause) in `/libraries/jquery.pause`
It is recommended to use [Drush](https://drush.org) to automatically install
the requirements to the right spot. To install all of the libraries to the
right places, run `drush dl-cycle-lib`.
If you don't have Drush available, or would prefer to install manually, you can
do so. An example of code you could run in your Drupal root dir to download to
the right place:
```
mkdir -p libraries/jquery.cycle && cd $_ && wget https://malsup.github.io/jquery.cycle.all.js \
&& mkdir -p ../../libraries/jquery.hoverIntent && cd $_ && wget https://raw.githubusercontent.com/briancherne/jquery-hoverIntent/master/jquery.hoverIntent.js \
&& mkdir -p ../../libraries/json2 && cd $_ && wget https://raw.githubusercontent.com/douglascrockford/JSON-js/master/json2.js \
&& mkdir -p ../../libraries/jquery.pause && cd $_ && wget https://raw.githubusercontent.com/tobia/Pause/master/jquery.pause.js
```
## CONFIGURATION
Configuration is on a per view/display basis.
Most standard views settings will work fine in conjunction with Views Slideshow.
However, grouping may or may not work. Under most use cases the pager should be
set to either `Display a specified number of items` or `Display all`.
To get started configuring your slideshow, set `Slideshow` as the display
format and configure the slideshow as desired under Format Settings. Next
select the *Skin* - usually `Default` (only one provided with the module).
Then select the *Slideshow Type*; for most users, this will just be `cycle`
with the `views_slideshow_cycle` module.
Below that, there is a lot of different options which should have better
documentation.
### See also:
* [OS Training tutorial on Views Slideshow](https://www.ostraining.com/blog/drupal/drupal-8-slideshows)
## CONTRIBUTORS
Current maintainer:
* [Neslee Canil Pinto](https://www.drupal.org/u/neslee-canil-pinto)
Past maintainers:
* [vbouchet](https://www.drupal.org/u/vbouchet) Initial 8.x port
* [Adam Moore](https://www.drupal.org/u/redndahead)
* [Nick Wilde](https://www.drupal.org/u/nickwilde)
Also, thanks to the many contributors via the issue queues.
{
"name": "drupal/views_slideshow",
"description": "Describes relationships between entities.",
"type": "drupal-module",
"license": "GPL-2.0-or-later",
"homepage": "https://www.drupal.org/project/views_slideshow",
"authors": [
{
"name": "Neslee Canil Pinto",
"homepage": "https://www.drupal.org/u/neslee-canil-pinto",
"role": "Maintainer"
}
],
"support": {
"issues": "https://www.drupal.org/project/issues/views_slideshow",
"irc": "irc://irc.freenode.org/drupal-contribute",
"source": "https://git.drupalcode.org/project/views_slideshow"
},
"require": {
"drupal/core": "^8 || ^9"
}
}
views.style.slideshow:
type: views_style
label: 'Slideshow'
mapping:
slideshow_skin:
type: string
label: 'Skin to apply to the slideshow'
slideshow_type:
type: string
label: 'Main frame plugin to use to render the slideshow'
widgets:
type: mapping
label: 'Control widgets for the slideshow'
mapping:
top:
type: views_slideshow_control_group
label: 'Widget configuration for above the slideshow'
bottom:
type: views_slideshow_control_group
label: 'Widget configuration for below the slideshow'
# Basic data types for views slideshows.
views_slideshow_widget:
type: mapping
label: 'widget'
mapping:
enable:
type: boolean
label: 'Show widget'
weight:
type: string
label: 'Sort order'
hide_on_single_slide:
type: string
label: 'Hide if only one slide'
views_slideshow_control_group:
type: mapping
label: 'Group of widget settings for slideshow region'
mapping:
views_slideshow_controls:
type: views_slideshow_widget
label: 'Slideshow controls'
mapping:
enable:
type: boolean
label: 'Show widget'
weight:
type: string
label: 'Sort order'
hide_on_single_slide:
type: string
label: 'Hide if only one slide'
type:
type: string
label: 'The control type'
views_slideshow_slide_counter:
type: views_slideshow_widget
label: 'Slide Counter'
views_slideshow_pager:
type: views_slideshow_widget
label: 'Slideshow pager'
mapping:
enable:
type: boolean
label: 'Show widget'
weight:
type: string
label: 'Sort order'
hide_on_single_slide:
type: string
label: 'Hide if only one slide'
type:
type: string
label: 'The control type'
.views_slideshow_controls_text span:hover {
text-decoration: underline;
cursor: pointer;
}
.views-slideshow-controls-bottom .views-slideshow-pager-bullets {
text-align: center;
}
.views-slideshow-controls-bottom .views-slideshow-pager-bullets li {
text-indent: -9999px;
cursor: pointer;
display: inline-block;
border-radius: 6px;
padding: 0 6px;
background: #222;
margin: 0.4em;
line-height: 12px;
}
.views-slideshow-controls-bottom .views-slideshow-pager-bullets li.active {
background: #aaa;
cursor: default;
}
.views-slideshow-controls-bottom .views-slideshow-pager-bullets li:hover {
background: #555;
}
#views-slideshow-form-wrapper .form-item.dependent-options {
padding-left: 5px;
}
#views-slideshow-form-wrapper .vs-dependent {
padding-left: 30px;
}
/**
* @file
*/
(function ($, Drupal, drupalSettings) {
'use strict';
Drupal.viewsSlideshow = Drupal.viewsSlideshow || {};
var pagerLocation;
var slideNum;
var error;
var excludeMethods;
/**
* Views Slideshow Controls.
*/
Drupal.viewsSlideshowControls = Drupal.viewsSlideshowControls || {};
/**
* Implement the play hook for controls.
*/
Drupal.viewsSlideshowControls.play = function (options) {
// Route the control call to the correct control type.
// Need to use try catch so we don't have to check to make sure every part
// of the object is defined.
try {
if (typeof drupalSettings.viewsSlideshowControls[options.slideshowID].top.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowControls[options.slideshowID].top.type].play == 'function') {
Drupal[drupalSettings.viewsSlideshowControls[options.slideshowID].top.type].play(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
try {
if (typeof drupalSettings.viewsSlideshowControls[options.slideshowID].bottom.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowControls[options.slideshowID].bottom.type].play == 'function') {
Drupal[drupalSettings.viewsSlideshowControls[options.slideshowID].bottom.type].play(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
};
/**
* Implement the pause hook for controls.
*/
Drupal.viewsSlideshowControls.pause = function (options) {
// Route the control call to the correct control type.
// Need to use try catch so we don't have to check to make sure every part
// of the object is defined.
try {
if (typeof drupalSettings.viewsSlideshowControls[options.slideshowID].top.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowControls[options.slideshowID].top.type].pause == 'function') {
Drupal[drupalSettings.viewsSlideshowControls[options.slideshowID].top.type].pause(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
try {
if (typeof drupalSettings.viewsSlideshowControls[options.slideshowID].bottom.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowControls[options.slideshowID].bottom.type].pause == 'function') {
Drupal[drupalSettings.viewsSlideshowControls[options.slideshowID].bottom.type].pause(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
};
/**
* Views Slideshow Text Controls.
*/
// Add views slieshow api calls for views slideshow text controls.
Drupal.behaviors.viewsSlideshowControlsText = {
attach: function (context) {
// Process previous link.
$('.views_slideshow_controls_text_previous:not(.views-slideshow-controls-text-previous-processed)', context).addClass('views-slideshow-controls-text-previous-processed').each(function () {
var uniqueID = $(this).attr('id').replace('views_slideshow_controls_text_previous_', '');
$(this).click(function () {
Drupal.viewsSlideshow.action({"action": 'previousSlide', "slideshowID": uniqueID});
return false;
});
});
// Process next link.
$('.views_slideshow_controls_text_next:not(.views-slideshow-controls-text-next-processed)', context).addClass('views-slideshow-controls-text-next-processed').each(function () {
var uniqueID = $(this).attr('id').replace('views_slideshow_controls_text_next_', '');
$(this).click(function () {
Drupal.viewsSlideshow.action({"action": 'nextSlide', "slideshowID": uniqueID});
return false;
});
});
// Process pause link.
$('.views_slideshow_controls_text_pause:not(.views-slideshow-controls-text-pause-processed)', context).addClass('views-slideshow-controls-text-pause-processed').each(function () {
var uniqueID = $(this).attr('id').replace('views_slideshow_controls_text_pause_', '');
$(this).click(function () {
if (drupalSettings.viewsSlideshow[uniqueID].paused) {
Drupal.viewsSlideshow.action({"action": 'play', "slideshowID": uniqueID, "force": true});
}
else {
Drupal.viewsSlideshow.action({"action": 'pause', "slideshowID": uniqueID, "force": true});
}
return false;
});
});
}
};
Drupal.viewsSlideshowControlsText = Drupal.viewsSlideshowControlsText || {};
/**
* Implement the pause hook for text controls.
*/
Drupal.viewsSlideshowControlsText.pause = function (options) {
var pauseText = Drupal.theme.viewsSlideshowControlsPause ? Drupal.theme('viewsSlideshowControlsPause') : '';
var $element = $('#views_slideshow_controls_text_pause_' + options.slideshowID);
$element.find('a').text(pauseText);
$element.removeClass('views-slideshow-controls-text-status-play');
$element.addClass('views-slideshow-controls-text-status-pause');
};
/**
* Implement the play hook for text controls.
*/
Drupal.viewsSlideshowControlsText.play = function (options) {
var playText = Drupal.theme.viewsSlideshowControlsPlay ? Drupal.theme('viewsSlideshowControlsPlay') : '';
var $element = $('#views_slideshow_controls_text_pause_' + options.slideshowID);
$element.find('a').text(playText);
$element.removeClass('views-slideshow-controls-text-status-pause');
$element.addClass('views-slideshow-controls-text-status-play');
};
// Theme the resume control.
Drupal.theme.viewsSlideshowControlsPause = function () {
return Drupal.t('Resume');
};
// Theme the pause control.
Drupal.theme.viewsSlideshowControlsPlay = function () {
return Drupal.t('Pause');
};
/**
* Views Slideshow Pager.
*/
Drupal.viewsSlideshowPager = Drupal.viewsSlideshowPager || {};
/**
* Implement the transitionBegin hook for pagers.
*/
Drupal.viewsSlideshowPager.transitionBegin = function (options) {
// Route the pager call to the correct pager type.
// Need to use try catch so we don't have to check to make sure every part
// of the object is defined.
try {
if (typeof drupalSettings.viewsSlideshowPager != "undefined" && typeof drupalSettings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].top.type].transitionBegin == 'function') {
Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].top.type].transitionBegin(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
try {
if (typeof drupalSettings.viewsSlideshowPager != "undefined" && typeof drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type].transitionBegin == 'function') {
Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type].transitionBegin(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
};
/**
* Implement the goToSlide hook for pagers.
*/
Drupal.viewsSlideshowPager.goToSlide = function (options) {
// Route the pager call to the correct pager type.
// Need to use try catch so we don't have to check to make sure every part
// of the object is defined.
try {
if (typeof drupalSettings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].top.type].goToSlide == 'function') {
Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].top.type].goToSlide(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
try {
if (typeof drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type].goToSlide == 'function') {
Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type].goToSlide(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
};
/**
* Implement the previousSlide hook for pagers.
*/
Drupal.viewsSlideshowPager.previousSlide = function (options) {
// Route the pager call to the correct pager type.
// Need to use try catch so we don't have to check to make sure every part
// of the object is defined.
try {
if (typeof drupalSettings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].top.type].previousSlide == 'function') {
Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].top.type].previousSlide(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
try {
if (typeof drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type].previousSlide == 'function') {
Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type].previousSlide(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
};
/**
* Implement the nextSlide hook for pagers.
*/
Drupal.viewsSlideshowPager.nextSlide = function (options) {
// Route the pager call to the correct pager type.
// Need to use try catch so we don't have to check to make sure every part
// of the object is defined.
try {
if (typeof drupalSettings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].top.type].nextSlide == 'function') {
Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].top.type].nextSlide(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
try {
if (typeof drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type].nextSlide == 'function') {
Drupal[drupalSettings.viewsSlideshowPager[options.slideshowID].bottom.type].nextSlide(options);
}
}
catch (err) {
// Don't need to do anything on error.
}
};
/**
* Views Slideshow Pager Fields.
*/
// Add views slieshow api calls for views slideshow pager fields.
Drupal.behaviors.viewsSlideshowPagerFields = {
attach: function (context) {
// Process pause on hover.
$('.views_slideshow_pager_field:not(.views-slideshow-pager-field-processed)', context).addClass('views-slideshow-pager-field-processed').each(function () {
// Parse out the location and unique id from the full id.
var pagerInfo = $(this).attr('id').split('_');
var location = pagerInfo[2];
pagerInfo.splice(0, 3);
var uniqueID = pagerInfo.join('_');
// Add the activate and pause on pager hover event to each pager item.
if (drupalSettings.viewsSlideshowPagerFields[uniqueID][location].activatePauseOnHover) {
$(this).children().each(function (index, pagerItem) {
var mouseIn = function () {
Drupal.viewsSlideshow.action({"action": 'goToSlide', "slideshowID": uniqueID, "slideNum": index});
Drupal.viewsSlideshow.action({"action": 'pause', "slideshowID": uniqueID});
};
var mouseOut = function () {
Drupal.viewsSlideshow.action({"action": 'play', "slideshowID": uniqueID});
};
if (jQuery.fn.hoverIntent) {
$(pagerItem).hoverIntent(mouseIn, mouseOut);
}
else {
$(pagerItem).hover(mouseIn, mouseOut);
}
});
}
else {
$(this).children().each(function (index, pagerItem) {
$(pagerItem).click(function () {
Drupal.viewsSlideshow.action({"action": 'goToSlide', "slideshowID": uniqueID, "slideNum": index});
});
});
}
});
}
};
Drupal.viewsSlideshowPagerFields = Drupal.viewsSlideshowPagerFields || {};
/**
* Implement the transitionBegin hook for pager fields pager.
*/
Drupal.viewsSlideshowPagerFields.transitionBegin = function (options) {
for (pagerLocation in drupalSettings.viewsSlideshowPager[options.slideshowID]) {
if (drupalSettings.viewsSlideshowPager[options.slideshowID]) {
// Remove active class from pagers.
$('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active');
// Add active class to active pager.
$('#views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_' + options.slideNum).addClass('active');
}
}
};
/**
* Implement the goToSlide hook for pager fields pager.
*/
Drupal.viewsSlideshowPagerFields.goToSlide = function (options) {
for (pagerLocation in drupalSettings.viewsSlideshowPager[options.slideshowID]) {
if (drupalSettings.viewsSlideshowPager[options.slideshowID]) {
// Remove active class from pagers.
$('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active');
// Add active class to active pager.
$('#views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_' + options.slideNum).addClass('active');
}
}
};
/**
* Implement the previousSlide hook for pager fields pager.
*/
Drupal.viewsSlideshowPagerFields.previousSlide = function (options) {
for (pagerLocation in drupalSettings.viewsSlideshowPager[options.slideshowID]) {
if (drupalSettings.viewsSlideshowPager[options.slideshowID]) {
// Get the current active pager.
var pagerNum = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"].active').attr('id').replace('views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_', '');
// If we are on the first pager then activate the last pager.
// Otherwise activate the previous pager.
if (pagerNum === 0) {
pagerNum = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').length() - 1;
}
else {
pagerNum--;
}
// Remove active class from pagers.
$('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active');
// Add active class to active pager.
$('#views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_' + pagerNum).addClass('active');
}
}
};
/**
* Implement the nextSlide hook for pager fields pager.
*/
Drupal.viewsSlideshowPagerFields.nextSlide = function (options) {
for (pagerLocation in drupalSettings.viewsSlideshowPager[options.slideshowID]) {
if (drupalSettings.viewsSlideshowPager[options.slideshowID]) {
// Get the current active pager.
var pagerNum = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"].active').attr('id').replace('views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_', '');
var totalPagers = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').length();
// If we are on the last pager then activate the first pager.
// Otherwise activate the next pager.
pagerNum++;
if (pagerNum === totalPagers) {
pagerNum = 0;
}
// Remove active class from pagers.
$('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active');
// Add active class to active pager.
$('#views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_' + slideNum).addClass('active');
}
}
};
// Copy the pager hooks from fields pager to the bullets one.
Drupal.viewsSlideshowPagerBullets = Drupal.viewsSlideshowPagerFields || {};
/**
* Views Slideshow Slide Counter.
*/
Drupal.viewsSlideshowSlideCounter = Drupal.viewsSlideshowSlideCounter || {};
/**
* Implement the transitionBegin for the slide counter.
*/
Drupal.viewsSlideshowSlideCounter.transitionBegin = function (options) {
$('#views_slideshow_slide_counter_' + options.slideshowID + ' .num').text(options.slideNum + 1);
};
/**
* This is used as a router to process actions for the slideshow.
*/
Drupal.viewsSlideshow.action = function (options) {
// Set default values for our return status.
var status = {
'value': true,
'text': ''
};
// If an action isn't specified return false.
if (typeof options.action == 'undefined' || options.action === '') {
status.value = false;
status.text = Drupal.t('There was no action specified.');
return error;
}
// If we are using pause or play switch paused state accordingly.
if (options.action === 'pause') {
drupalSettings.viewsSlideshow[options.slideshowID].paused = 1;
// If the calling method is forcing a pause then mark it as such.
if (options.force) {
drupalSettings.viewsSlideshow[options.slideshowID].pausedForce = 1;
}
}
else if (options.action === 'play') {
// If the slideshow isn't forced pause or we are forcing a play then play
// the slideshow.
// Otherwise return telling the calling method that it was forced paused.
if (!drupalSettings.viewsSlideshow[options.slideshowID].pausedForce || options.force) {
drupalSettings.viewsSlideshow[options.slideshowID].paused = 0;
drupalSettings.viewsSlideshow[options.slideshowID].pausedForce = 0;
}
else {
status.value = false;
status.text += ' ' + Drupal.t('This slideshow is forced paused.');
return status;
}
}
// We use a switch statement here mainly just to limit the type of actions
// that are available.
switch (options.action) {
case "goToSlide":
case "transitionBegin":
case "transitionEnd":
// The three methods above require a slide number. Checking if it is
// defined and it is a number that is an integer.
if (typeof options.slideNum == 'undefined' || typeof options.slideNum !== 'number' || parseInt(options.slideNum) !== (options.slideNum - 0)) {
status.value = false;
status.text = Drupal.t('An invalid integer was specified for slideNum.');
}
case "pause":
case "play":
case "nextSlide":
case "previousSlide":
// Grab our list of methods.
var methods = drupalSettings.viewsSlideshow[options.slideshowID]['methods'];
// If the calling method specified methods that shouldn't be called then
// exclude calling them.
var excludeMethodsObj = {};
if (typeof options.excludeMethods !== 'undefined') {
// We need to turn the excludeMethods array into an object so we can use the in
// function.
for (var i = 0; i < excludeMethods.length; i++) {
excludeMethodsObj[excludeMethods[i]] = '';
}
}
// Call every registered method and don't call excluded ones.
for (var i = 0; i < methods[options.action].length; i++) {
if (Drupal[methods[options.action][i]] !== 'undefined' && typeof Drupal[methods[options.action][i]][options.action] == 'function' && !(methods[options.action][i] in excludeMethodsObj)) {
Drupal[methods[options.action][i]][options.action](options);
}
}
break;
// If it gets here it's because it's an invalid action.
default:
status.value = false;
status.text = Drupal.t('An invalid action "@action" was specified.', {"@action": options.action});
}
return status;
};
})(jQuery, Drupal, drupalSettings);
{
"name": "drupal/views_slideshow_cycle",
"description": "Cycle plugin for Views Slideshow.",
"type": "drupal-module",
"license": "GPL-2.0+",
"homepage": "https://www.drupal.org/project/views_slideshow",
"authors": [
{
"name": "See contributors",
"homepage": "https://www.drupal.org/node/160350/committers"
}
],
"support": {
"issues": "https://www.drupal.org/project/issues/views_slideshow",
"irc": "irc://irc.freenode.org/drupal-contribute",
"source": "https://git.drupalcode.org/project/views_slideshow"
},
"require": {},
"extra": {
"drush": {
"services": {
"drush.services.yml": "^9"
}
}
}
}
.views_slideshow_cycle_no_display,
.views_slideshow_cycle_hidden,
.views_slideshow_cycle_controls,
.views_slideshow_cycle_image_count {
display: none;
}
/* Pager Settings */
.views_slideshow_cycle_pager div a img {
width: 75px;
height: 75px;
}
.views_slideshow_pager_numbered div,
.views_slideshow_pager_thumbnails div {
display: inline;
padding-left: 10px;
}
.views_slideshow_cycle_pager.thumbnails a.activeSlide img {
border: 3px solid #000;
}
.views_slideshow_cycle_pager.numbered a.activeSlide {
text-decoration: underline;
}
services:
views_slideshow_cycle.commands:
class: \Drupal\views_slideshow_cycle\Commands\ViewsSlideshowCycleCommands
tags:
- { name: drush.command }
/**
* @file
* Javascript to enhance the views slideshow cycle form options.
*/
/**
* This will set our initial behavior, by starting up each individual slideshow.
*/
(function ($) {
// Since Drupal 7 doesn't support having a field based on one of 3 values of
// a select box we need to add our own JavaScript handling.
Drupal.behaviors.viewsSlideshowCycleAmountAllowedVisible = {
attach: function (context) {
// If necessary at start hide the amount allowed visible box.
var type = $(":input[name='style_options[views_slideshow_cycle][pause_when_hidden_type]']").val();
if (type == 'full') {
$(":input[name='style_options[views_slideshow_cycle][amount_allowed_visible]']").parent().hide();
}
// Handle dependency on action advanced checkbox.
$(":input[name='style_options[views_slideshow_cycle][action_advanced]']").change(function () {
processValues('action_advanced');
});
// Handle dependency on pause when hidden checkbox.
$(':input[name="style_options[views_slideshow_cycle][pause_when_hidden]"]').change(function () {
processValues('pause_when_hidden');
});
// Handle dependency on pause when hidden type select box.
$(":input[name='style_options[views_slideshow_cycle][pause_when_hidden_type]']").change(function () {
processValues('pause_when_hidden_type');
});
// Process our dependencies.
function processValues(field) {
switch (field) {
case 'action_advanced':
if (!$(':input[name="style_options[views_slideshow_cycle][action_advanced]"]').is(':checked')) {
$(":input[name='style_options[views_slideshow_cycle][amount_allowed_visible]']").parent().hide();
break;
}
case 'pause_when_hidden':
if (!$(':input[name="style_options[views_slideshow_cycle][pause_when_hidden]"]').is(':checked')) {
$(":input[name='style_options[views_slideshow_cycle][amount_allowed_visible]']").parent().hide();
break;
}
case 'pause_when_hidden_type':
if ($(":input[name='style_options[views_slideshow_cycle][pause_when_hidden_type]']").val() == 'full') {
$(":input[name='style_options[views_slideshow_cycle][amount_allowed_visible]']").parent().hide();
}
else {
$(":input[name='style_options[views_slideshow_cycle][amount_allowed_visible]']").parent().show();
}
}
}
}
}
// Manage advanced options.
Drupal.behaviors.viewsSlideshowCycleOptions = {
attach: function (context) {
if ($(":input[name='style_options[views_slideshow_cycle][advanced_options]']").length) {
$(":input[name='style_options[views_slideshow_cycle][advanced_options]']").parent().hide();
$(":input[name='style_options[views_slideshow_cycle][advanced_options_entry]']").parent().after(
'<div style="margin-left: 10px; padding: 10px 0;">' +
'<a id="edit-style-options-views-slideshow-cycle-advanced-options-update-link" href="#">' + Drupal.t('Update Advanced Option') + '</a>' +
'</div>'
);
$("#edit-style-options-views-slideshow-cycle-advanced-options-table").append('<tr><th colspan="2">' + Drupal.t('Applied Options') + '</th><tr>')
var initialValue = $(":input[name='style_options[views_slideshow_cycle][advanced_options]']").val();
var advancedOptions = JSON.parse(initialValue);
for (var option in advancedOptions) {
viewsSlideshowCycleAdvancedOptionsAddRow(option);
}
// Add the remove event to the advanced items.
viewsSlideshowCycleAdvancedOptionsRemoveEvent();
$(":input[name='style_options[views_slideshow_cycle][advanced_options_choices]']").change(function () {
var selectedValue = $(":input[name='style_options[views_slideshow_cycle][advanced_options_choices]'] option:selected").val();
if (typeof advancedOptions[selectedValue] !== 'undefined') {
$(":input[name='style_options[views_slideshow_cycle][advanced_options_entry]']").val(advancedOptions[selectedValue]);
}
else {
$(":input[name='style_options[views_slideshow_cycle][advanced_options_entry]']").val('');
}
});
$('#edit-style-options-views-slideshow-cycle-advanced-options-update-link').click(function () {
var option = $(":input[name='style_options[views_slideshow_cycle][advanced_options_choices]']").val();
if (option) {
var value = $(":input[name='style_options[views_slideshow_cycle][advanced_options_entry]']").val();
if (typeof advancedOptions[option] == 'undefined') {
viewsSlideshowCycleAdvancedOptionsAddRow(option);
viewsSlideshowCycleAdvancedOptionsRemoveEvent()
}
advancedOptions[option] = value;
viewsSlideshowCycleAdvancedOptionsSave();
}
return false;
});
}
function viewsSlideshowCycleAdvancedOptionsAddRow(option) {
$("#edit-style-options-views-slideshow-cycle-advanced-options-table").append(
'<tr id="views-slideshow-cycle-advanced-options-table-row-' + option + '">' +
'<td>' + option + '</td>' +
'<td style="width: 20px;">' +
'<a style="margin-top: 6px" title="Remove ' + option + '" alt="Remove ' + option + '" class="views-hidden views-button-remove views-slideshow-cycle-advanced-options-table-remove" id="views-slideshow-cycle-advanced-options-table-remove-' + option + '" href="#"><span>Remove</span></a>' +
'</td>' +
'</tr>'
);
}
function viewsSlideshowCycleAdvancedOptionsRemoveEvent() {
$('.views-slideshow-cycle-advanced-options-table-remove').unbind().click(function () {
var itemID = $(this).attr('id');
var uniqueID = itemID.replace('views-slideshow-cycle-advanced-options-table-remove-', '');
delete advancedOptions[uniqueID];
$('#views-slideshow-cycle-advanced-options-table-row-' + uniqueID).remove();
viewsSlideshowCycleAdvancedOptionsSave();
return false;
});
}
function viewsSlideshowCycleAdvancedOptionsSave() {
var advancedOptionsString = JSON.stringify(advancedOptions);
$(":input[name='style_options[views_slideshow_cycle][advanced_options]']").val(advancedOptionsString);
}
}
}
})(jQuery, Drupal);
/**
* @file
* A simple jQuery Cycle Div Slideshow Rotator.
*/
/**
* This will set our initial behavior, by starting up each individual slideshow.
*/
(function ($, Drupal, drupalSettings) {
Drupal.behaviors.viewsSlideshowCycle = {
attach: function (context) {
$('.views_slideshow_cycle_main:not(.viewsSlideshowCycle-processed)', context).addClass('viewsSlideshowCycle-processed').each(function () {
var fullId = '#' + $(this).attr('id');
var settings = drupalSettings.viewsSlideshowCycle[fullId];
settings.targetId = '#' + $(fullId + " :first").attr('id');
settings.slideshowId = settings.targetId.replace('#views_slideshow_cycle_teaser_section_', '');
// Pager after function.
var pager_after_fn = function (curr, next, opts) {
// Need to do some special handling on first load.
var slideNum = opts.currSlide;
if (typeof settings.processedAfter == 'undefined' || !settings.processedAfter) {
settings.processedAfter = 1;
slideNum = (typeof settings.opts.startingSlide == 'undefined') ? 0 : settings.opts.startingSlide;
}
Drupal.viewsSlideshow.action({ "action": 'transitionEnd', "slideshowID": settings.slideshowId, "slideNum": slideNum });
}
// Pager before function.
var pager_before_fn = function (curr, next, opts) {
var slideNum = opts.nextSlide;
// Remember last slide.
if (settings.remember_slide) {
createCookie(settings.vss_id, slideNum, settings.remember_slide_days);
}
// Make variable height.
if (!settings.fixed_height) {
// Get the height of the current slide.
var $ht = $(next).height();
// Set the container's height to that of the current slide.
$(next).parent().animate({height: $ht});
}
// Need to do some special handling on first load.
if (typeof settings.processedBefore == 'undefined' || !settings.processedBefore) {
settings.processedBefore = 1;
slideNum = (typeof opts.startingSlide == 'undefined') ? 0 : opts.startingSlide;
}
Drupal.viewsSlideshow.action({ "action": 'transitionBegin', "slideshowID": settings.slideshowId, "slideNum": slideNum });
}
settings.loaded = false;
settings.opts = {
speed:settings.speed,
timeout:settings.timeout,
delay:settings.delay,
sync:settings.sync,
random:settings.random,
nowrap:settings.nowrap,
after:pager_after_fn,
before:pager_before_fn,
cleartype:(settings.cleartype) ? true : false,
cleartypeNoBg:(settings.cleartypenobg) ? true : false
}
// Set the starting slide if we are supposed to remember the slide.
if (settings.remember_slide) {
var startSlide = readCookie(settings.vss_id);
if (startSlide == null) {
startSlide = 0;
}
settings.opts.startingSlide = parseInt(startSlide);
}
if (settings.effect == 'none') {
settings.opts.speed = 1;
}
else {
settings.opts.fx = settings.effect;
}
// Take starting item from fragment.
var hash = location.hash;
if (hash) {
var hash = hash.replace('#', '');
var aHash = hash.split(';');
var aHashLen = aHash.length;
// Loop through all the possible starting points.
for (var i = 0; i < aHashLen; i++) {
// Split the hash into two parts. One part is the slideshow id the
// other is the slide number.
var initialInfo = aHash[i].split(':');
// The id in the hash should match our slideshow.
// The slide number chosen shouldn't be larger than the number of
// slides we have.
if (settings.slideshowId == initialInfo[0] && settings.num_divs > initialInfo[1]) {
settings.opts.startingSlide = parseInt(initialInfo[1]);
}
}
}
// Pause on hover.
if (settings.pause) {
var mouseIn = function () {
Drupal.viewsSlideshow.action({ "action": 'pause', "slideshowID": settings.slideshowId });
}
var mouseOut = function () {
Drupal.viewsSlideshow.action({ "action": 'play', "slideshowID": settings.slideshowId });
}
if (jQuery.fn.hoverIntent) {
$('#views_slideshow_cycle_teaser_section_' + settings.vss_id).hoverIntent(mouseIn, mouseOut);
}
else {
$('#views_slideshow_cycle_teaser_section_' + settings.vss_id).hover(mouseIn, mouseOut);
}
}
// Pause on clicking of the slide.
if (settings.pause_on_click) {
$('#views_slideshow_cycle_teaser_section_' + settings.vss_id).click(function () {
Drupal.viewsSlideshow.action({ "action": 'pause', "slideshowID": settings.slideshowId, "force": true });
});
}
if (typeof JSON != 'undefined' && typeof settings.advanced_options != 'undefined') {
var advancedOptions = JSON.parse(settings.advanced_options);
for (var option in advancedOptions) {
switch (option) {
// Standard Options.
case "activePagerClass":
case "allowPagerClickBubble":
case "autostop":
case "autostopCount":
case "backwards":
case "bounce":
case "cleartype":
case "cleartypeNoBg":
case "containerResize":
case "continuous":
case "delay":
case "easeIn":
case "easeOut":
case "easing":
case "fastOnEvent":
case "fit":
case "fx":
case "height":
case "manualTrump":
case "metaAttr":
case "next":
case "nowrap":
case "pager":
case "pagerEvent":
case "pause":
case "pauseOnPagerHover":
case "prev":
case "prevNextEvent":
case "random":
case "randomizeEffects":
case "requeueOnImageNotLoaded":
case "requeueTimeout":
case "rev":
case "slideExpr":
case "slideResize":
case "speed":
case "speedIn":
case "speedOut":
case "startingSlide":
case "sync":
case "timeout":
case "width":
var optionValue = advancedOptions[option];
optionValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(optionValue);
settings.opts[option] = optionValue;
break;
// These process options that look like {top:50, bottom:20}.
case "animIn":
case "animOut":
case "cssBefore":
case "cssAfter":
case "shuffle":
var cssValue = advancedOptions[option];
cssValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(cssValue);
settings.opts[option] = eval('(' + cssValue + ')');
break;
// These options have their own functions.
case "after":
var afterValue = advancedOptions[option];
afterValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(afterValue);
// Transition callback (scope set to element that was shown): function(currSlideElement, nextSlideElement, options, forwardFlag)
settings.opts[option] = function (currSlideElement, nextSlideElement, options, forwardFlag) {
pager_after_fn(currSlideElement, nextSlideElement, options);
eval(afterValue);
}
break;
case "before":
var beforeValue = advancedOptions[option];
beforeValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(beforeValue);
// Transition callback (scope set to element to be shown): function(currSlideElement, nextSlideElement, options, forwardFlag)
settings.opts[option] = function (currSlideElement, nextSlideElement, options, forwardFlag) {
pager_before_fn(currSlideElement, nextSlideElement, options);
eval(beforeValue);
}
break;
case "end":
var endValue = advancedOptions[option];
endValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(endValue);
// Callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options)
settings.opts[option] = function (options) {
eval(endValue);
}
break;
case "fxFn":
var fxFnValue = advancedOptions[option];
fxFnValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(fxFnValue);
// Function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag)
settings.opts[option] = function (currSlideElement, nextSlideElement, options, afterCalback, forwardFlag) {
eval(fxFnValue);
}
break;
case "onPagerEvent":
var onPagerEventValue = advancedOptions[option];
onPagerEventValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(onPagerEventValue);
settings.opts[option] = function (zeroBasedSlideIndex, slideElement) {
eval(onPagerEventValue);
}
break;
case "onPrevNextEvent":
var onPrevNextEventValue = advancedOptions[option];
onPrevNextEventValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(onPrevNextEventValue);
settings.opts[option] = function (isNext, zeroBasedSlideIndex, slideElement) {
eval(onPrevNextEventValue);
}
break;
case "pagerAnchorBuilder":
var pagerAnchorBuilderValue = advancedOptions[option];
pagerAnchorBuilderValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(pagerAnchorBuilderValue);
// Callback fn for building anchor links: function(index, DOMelement)
settings.opts[option] = function (index, DOMelement) {
var returnVal = '';
eval(pagerAnchorBuilderValue);
return returnVal;
}
break;
case "pagerClick":
var pagerClickValue = advancedOptions[option];
pagerClickValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(pagerClickValue);
// Callback fn for pager clicks: function(zeroBasedSlideIndex, slideElement)
settings.opts[option] = function (zeroBasedSlideIndex, slideElement) {
eval(pagerClickValue);
}
break;
case "paused":
var pausedValue = advancedOptions[option];
pausedValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(pausedValue);
// Undocumented callback when slideshow is paused: function(cont, opts, byHover)
settings.opts[option] = function (cont, opts, byHover) {
eval(pausedValue);
}
break;
case "resumed":
var resumedValue = advancedOptions[option];
resumedValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(resumedValue);
// Undocumented callback when slideshow is resumed: function(cont, opts, byHover)
settings.opts[option] = function (cont, opts, byHover) {
eval(resumedValue);
}
break;
case "timeoutFn":
var timeoutFnValue = advancedOptions[option];
timeoutFnValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(timeoutFnValue);
settings.opts[option] = function (currSlideElement, nextSlideElement, options, forwardFlag) {
eval(timeoutFnValue);
}
break;
case "updateActivePagerLink":
var updateActivePagerLinkValue = advancedOptions[option];
updateActivePagerLinkValue = Drupal.viewsSlideshowCycle.advancedOptionCleanup(updateActivePagerLinkValue);
// Callback fn invoked to update the active pager link (adds/removes activePagerClass style)
settings.opts[option] = function (pager, currSlideIndex) {
eval(updateActivePagerLinkValue);
}
break;
}
}
}
// If selected wait for the images to be loaded.
// otherwise just load the slideshow.
if (settings.wait_for_image_load) {
// For IE/Chrome/Opera we if there are images then we need to make
// sure the images are loaded before starting the slideshow.
settings.totalImages = $(settings.targetId + ' img').length;
if (settings.totalImages) {
settings.loadedImages = 0;
// Add a load event for each image.
$(settings.targetId + ' img').each(function () {
var $imageElement = $(this);
$imageElement.bind('load', function () {
Drupal.viewsSlideshowCycle.imageWait(fullId);
});
// Removing the source and adding it again will fire the load event.
var imgSrc = $imageElement.attr('src');
$imageElement.attr('src', '');
$imageElement.attr('src', imgSrc);
});
// We need to set a timeout so that the slideshow doesn't wait
// indefinitely for all images to load.
setTimeout("Drupal.viewsSlideshowCycle.load('" + fullId + "')", settings.wait_for_image_load_timeout);
}
else {
Drupal.viewsSlideshowCycle.load(fullId);
}
}
else {
Drupal.viewsSlideshowCycle.load(fullId);
}
});
}
};
Drupal.viewsSlideshowCycle = Drupal.viewsSlideshowCycle || {};
// Cleanup the values of advanced options.
Drupal.viewsSlideshowCycle.advancedOptionCleanup = function (value) {
value = $.trim(value);
value = value.replace(/\n/g, '');
if (!isNaN(parseInt(value))) {
value = parseInt(value);
}
else if (value.toLowerCase() == 'true') {
value = true;
}
else if (value.toLowerCase() == 'false') {
value = false;
}
return value;
}
// This checks to see if all the images have been loaded.
// If they have then it starts the slideshow.
Drupal.viewsSlideshowCycle.imageWait = function (fullId) {
if (++drupalSettings.viewsSlideshowCycle[fullId].loadedImages == drupalSettings.viewsSlideshowCycle[fullId].totalImages) {
Drupal.viewsSlideshowCycle.load(fullId);
}
};
// Start the slideshow.
Drupal.viewsSlideshowCycle.load = function (fullId) {
var settings = drupalSettings.viewsSlideshowCycle[fullId];
// Make sure the slideshow isn't already loaded.
if (!settings.loaded) {
$(settings.targetId).cycle(settings.opts);
settings.loaded = true;
// Start Paused.
if (settings.start_paused) {
Drupal.viewsSlideshow.action({ "action": 'pause', "slideshowID": settings.slideshowId, "force": true });
}
// Pause if hidden.
if (settings.pause_when_hidden) {
var checkPause = function (settings) {
// If the slideshow is visible and it is paused then resume.
// otherwise if the slideshow is not visible and it is not paused then
// pause it.
var visible = viewsSlideshowCycleIsVisible(settings.targetId, settings.pause_when_hidden_type, settings.amount_allowed_visible);
if (visible) {
Drupal.viewsSlideshow.action({ "action": 'play', "slideshowID": settings.slideshowId });
}
else {
Drupal.viewsSlideshow.action({ "action": 'pause', "slideshowID": settings.slideshowId });
}
}
// Check when scrolled.
$(window).scroll(function () {
checkPause(settings);
});
// Check when the window is resized.
$(window).resize(function () {
checkPause(settings);
});
}
}
};
Drupal.viewsSlideshowCycle.pause = function (options) {
// Eat TypeError, cycle doesn't handle pause well if options isn't defined.
try {
if (options.pause_in_middle && $.fn.pause) {
$('#views_slideshow_cycle_teaser_section_' + options.slideshowID).pause();
}
else {
$('#views_slideshow_cycle_teaser_section_' + options.slideshowID).cycle('pause');
}
}
catch (e) {
if (!e instanceof TypeError) {
throw e;
}
}
};
Drupal.viewsSlideshowCycle.play = function (options) {
drupalSettings.viewsSlideshowCycle['#views_slideshow_cycle_main_' + options.slideshowID].paused = false;
if (options.pause_in_middle && $.fn.resume) {
$('#views_slideshow_cycle_teaser_section_' + options.slideshowID).resume();
}
else {
$('#views_slideshow_cycle_teaser_section_' + options.slideshowID).cycle('resume');
}
};
Drupal.viewsSlideshowCycle.previousSlide = function (options) {
$('#views_slideshow_cycle_teaser_section_' + options.slideshowID).cycle('prev');
};
Drupal.viewsSlideshowCycle.nextSlide = function (options) {
$('#views_slideshow_cycle_teaser_section_' + options.slideshowID).cycle('next');
};
Drupal.viewsSlideshowCycle.goToSlide = function (options) {
$('#views_slideshow_cycle_teaser_section_' + options.slideshowID).cycle(options.slideNum);
};
// Verify that the value is a number.
function IsNumeric(sText) {
var ValidChars = "0123456789";
var IsNumber = true;
var Char;
for (var i = 0; i < sText.length && IsNumber == true; i++) {
Char = sText.charAt(i);
if (ValidChars.indexOf(Char) == -1) {
IsNumber = false;
}
}
return IsNumber;
}
/**
* Cookie Handling Functions.
*/
function createCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
var expires = "; expires=" + date.toGMTString();
}
else {
var expires = "";
}
document.cookie = name + "=" + value + expires + "; path=/";
}
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1,c.length);
}
if (c.indexOf(nameEQ) == 0) {
return c.substring(nameEQ.length,c.length);
}
}
return null;
}
function eraseCookie(name) {
createCookie(name,"",-1);
}
/**
* Checks to see if the slide is visible enough.
*
* A elem = element to check.
*
* A type = The way to calculate how much is visible.
*
* A amountVisible = amount that should be visible. Either in percent or px.
*
* If it's not defined then all of the slide must be visible.
*
* Returns true or false.
*/
function viewsSlideshowCycleIsVisible(elem, type, amountVisible) {
// Get the top and bottom of the window;.
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var docViewLeft = $(window).scrollLeft();
var docViewRight = docViewLeft + $(window).width();
// Get the top, bottom, and height of the slide;.
var elemTop = $(elem).offset().top;
var elemHeight = $(elem).height();
var elemBottom = elemTop + elemHeight;
var elemLeft = $(elem).offset().left;
var elemWidth = $(elem).width();
var elemRight = elemLeft + elemWidth;
var elemArea = elemHeight * elemWidth;
// Calculate what's hiding in the slide.
var missingLeft = 0;
var missingRight = 0;
var missingTop = 0;
var missingBottom = 0;
// Find out how much of the slide is missing from the left.
if (elemLeft < docViewLeft) {
missingLeft = docViewLeft - elemLeft;
}
// Find out how much of the slide is missing from the right.
if (elemRight > docViewRight) {
missingRight = elemRight - docViewRight;
}
// Find out how much of the slide is missing from the top.
if (elemTop < docViewTop) {
missingTop = docViewTop - elemTop;
}
// Find out how much of the slide is missing from the bottom.
if (elemBottom > docViewBottom) {
missingBottom = elemBottom - docViewBottom;
}
// If there is no amountVisible defined then check to see if the whole slide
// is visible.
if (type == 'full') {
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
&& (elemBottom <= docViewBottom) && (elemTop >= docViewTop)
&& (elemLeft >= docViewLeft) && (elemRight <= docViewRight)
&& (elemLeft <= docViewRight) && (elemRight >= docViewLeft));
}
else if (type == 'vertical') {
var verticalShowing = elemHeight - missingTop - missingBottom;
// If user specified a percentage then find out if the current shown percent
// is larger than the allowed percent.
// Otherwise check to see if the amount of px shown is larger than the
// allotted amount.
if (amountVisible.indexOf('%')) {
return (((verticalShowing / elemHeight) * 100) >= parseInt(amountVisible));
}
else {
return (verticalShowing >= parseInt(amountVisible));
}
}
else if (type == 'horizontal') {
var horizontalShowing = elemWidth - missingLeft - missingRight;
// If user specified a percentage then find out if the current shown percent
// is larger than the allowed percent.
// Otherwise check to see if the amount of px shown is larger than the
// allotted amount.
if (amountVisible.indexOf('%')) {
return (((horizontalShowing / elemWidth) * 100) >= parseInt(amountVisible));
}
else {
return (horizontalShowing >= parseInt(amountVisible));
}
}
else if (type == 'area') {
var areaShowing = (elemWidth - missingLeft - missingRight) * (elemHeight - missingTop - missingBottom);
// If user specified a percentage then find out if the current shown percent
// is larger than the allowed percent.
// Otherwise check to see if the amount of px shown is larger than the
// allotted amount.
if (amountVisible.indexOf('%')) {
return (((areaShowing / elemArea) * 100) >= parseInt(amountVisible));
}
else {
return (areaShowing >= parseInt(amountVisible));
}
}
}
})(jQuery, Drupal, drupalSettings);
<?php
namespace Drupal\views_slideshow_cycle\Commands;
use Drush\Commands\DrushCommands;
use Drush\Drush;
/**
* Drush commands for Views Slideshow Cycle.
*/
class ViewsSlideshowCycleCommands extends DrushCommands {
/**
* Download and install the jQuery Cycle library.
*
* @command views:slideshow:cycle
* @aliases dl-cycle,views-slideshow-cycle-cycle
*/
public function downloadCycle() {
$this->installLibrary(
'jQuery Cycle',
'libraries/jquery.cycle',
'jquery.cycle.all.js',
'https://raw.githubusercontent.com/malsup/cycle/3.0.3/jquery.cycle.all.js'
);
}
/**
* Download and install the JSON2 library.
*
* @command views:slideshow:json2
* @aliases dl-json2,views-slideshow-cycle-json2
*/
public function downloadJson2() {
$this->installLibrary(
'JSON2',
'libraries/json2',
'json2.js',
'https://raw.githubusercontent.com/douglascrockford/JSON-js/master/json2.js'
);
}
/**
* Download and install the jquery.hoverIntent library.
*
* @command views:slideshow:hoverintent
* @aliases dl-hoverintent,views-slideshow-cycle-hoverintent
*/
public function downloadHoverIntent() {
$this->installLibrary(
'jQuery HoverIntent',
'libraries/jquery.hoverIntent',
'jquery.hoverIntent.js',
'https://raw.githubusercontent.com/briancherne/jquery-hoverIntent/master/jquery.hoverIntent.js'
);
}
/**
* Download and install the jQuery.pause library.
*
* @command views:slideshow:pause
* @aliases dl-pause,views-slideshow-cycle-pause
*/
public function downloadPause() {
$this->installLibrary(
'jQuery Pause',
'libraries/jquery.pause',
'jquery.pause.js',
'https://raw.githubusercontent.com/tobia/Pause/master/jquery.pause.js'
);
}
/**
* Download and install the jQuery Cycle.
*
* Download and install JQuery hoverIntent, JSON2 and Pause libraries.
*
* @command views:slideshow:lib
* @aliases dl-cycle-lib,views-slideshow-cycle-lib
*/
public function downloadLib() {
$this->downloadCycle();
$this->downloadHoverIntent();
$this->downloadJson2();
$this->downloadPause();
}
/**
* Helper function to download a library in the given directory.
*/
protected function installLibrary($name, $path, $filename, $url) {
// Create the path if it does not exist.
if (!is_dir($path)) {
drush_op('mkdir', $path, 0755, TRUE);
$this->logger()->info(dt('Directory @path was created', ['@path' => $path]));
}
// Be sure we can write in the directory.
$perms = substr(sprintf('%o', fileperms($path)), -4);
if ($perms !== '0755') {
Drush::process('chmod 755 ' . $path);
}
else {
$perms = NULL;
}
$dir = getcwd();
// Download the JavaScript file.
if (is_file($path . '/' . $filename)) {
$this->logger()->notice(dt('@name appears to be already installed.', [
'@name' => $name,
]));
}
elseif (drush_op('chdir', $path) && Drush::process('wget ' . $url)) {
$this->logger()->success(dt('The latest version of @name has been downloaded to @path', [
'@name' => $name,
'@path' => $path,
]));
}
else {
$this->logger()->warning(dt('Drush was unable to download the @name library to @path', [
'@name' => $name,
'@path' => $path,
]));
}
chdir($dir);
// Restore the previous permissions.
if ($perms) {
Drush::process('chmod ' . $perms . ' ' . $path);
}
}
}
<?php
namespace Drupal\views_slideshow_cycle\Plugin\ViewsSlideshowType;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\views_slideshow\ViewsSlideshowTypeBase;
use Drupal\Core\Link;
/**
* Provides a slideshow type based on jquery cycle.
*
* @ViewsSlideshowType(
* id = "views_slideshow_cycle",
* label = @Translation("Cycle"),
* accepts = {
* "goToSlide",
* "nextSlide",
* "pause",
* "play",
* "previousSlide"
* },
* calls = {
* "transitionBegin",
* "transitionEnd",
* "goToSlide",
* "pause",
* "play",
* "nextSlide",
* "previousSlide"
* }
* )
*/
class Cycle extends ViewsSlideshowTypeBase {
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'contains' => [
// Transition.
'effect' => ['default' => 'fade'],
'transition_advanced' => ['default' => 0],
'timeout' => ['default' => 5000],
'speed' => ['default' => 700],
'delay' => ['default' => 0],
'sync' => ['default' => 1],
'random' => ['default' => 0],
// Action.
'pause' => ['default' => 1],
'pause_on_click' => ['default' => 0],
'action_advanced' => ['default' => 0],
'start_paused' => ['default' => 0],
'remember_slide' => ['default' => 0],
'remember_slide_days' => ['default' => 1],
'pause_in_middle' => ['default' => 0],
'pause_when_hidden' => ['default' => 0],
'pause_when_hidden_type' => ['default' => 'full'],
'amount_allowed_visible' => ['default' => ''],
'nowrap' => ['default' => 0],
'fixed_height' => ['default' => 1],
'items_per_slide' => ['default' => 1],
'items_per_slide_first' => ['default' => FALSE],
'items_per_slide_first_number' => ['default' => 1],
'wait_for_image_load' => ['default' => 1],
'wait_for_image_load_timeout' => ['default' => 3000],
// Internet Explorer Tweaks.
'cleartype' => ['default' => 'true'],
'cleartypenobg' => ['default' => 'false'],
// Advanced.
'advanced_options' => ['default' => '{}'],
],
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$cycle = \Drupal::service('library.discovery')->getLibraryByName('views_slideshow_cycle', 'jquery_cycle');
if (!isset($cycle['js'][0]['data']) || !file_exists($cycle['js'][0]['data'])) {
$form['views_slideshow_cycle']['no_cycle_js'] = [
'#markup' => '<div style="color: red">' . $this->t('You need to install the @url plugin. If you have installed it check file paths. See the readme for more details.',
[
'@url' => Link::fromTextAndUrl('jQuery Cycle', Url::FromUri('http://malsup.com/jquery/cycle', [
'attributes' => ['target' => '_blank'],
]))->toString(),
]) . '</div>',
];
}
// Transition.
$form['views_slideshow_cycle']['transition'] = [
'#markup' => '<h2>' . $this->t('Transition') . '</h2>',
];
$effects = [
'none' => 'none',
'blindX' => 'blindX',
'blindY' => 'blindY',
'blindZ' => 'blindZ',
'cover' => 'cover',
'curtainX' => 'curtainX',
'curtainY' => 'curtainY',
'fade' => 'fade',
'fadeZoom' => 'fadeZoom',
'growX' => 'growX',
'growY' => 'growY',
'scrollUp' => 'scrollUp',
'scrollDown' => 'scrollDown',
'scrollLeft' => 'scrollLeft',
'scrollRight' => 'scrollRight',
'scrollHorz' => 'scrollHorz',
'scrollVert' => 'scrollVert',
'shuffle' => 'shuffle',
'slideX' => 'slideX',
'slideY' => 'slideY',
'toss' => 'toss',
'turnUp' => 'turnUp',
'turnDown' => 'turnDown',
'turnLeft' => 'turnLeft',
'turnRight' => 'turnRight',
'uncover' => 'uncover',
'wipe' => 'wipe',
'zoom' => 'zoom',
];
$form['views_slideshow_cycle']['effect'] = [
'#type' => 'select',
'#title' => $this->t('Effect'),
'#options' => $effects,
'#default_value' => $this->getConfiguration()['effect'],
'#description' => $this->t('The transition effect that will be used to change between images. Not all options below may be relevant depending on the effect. <a href="http://jquery.malsup.com/cycle/browser.html" target="_black">Follow this link to see examples of each effect.</a>'),
];
// Transition advanced options.
$form['views_slideshow_cycle']['transition_advanced'] = [
'#type' => 'checkbox',
'#title' => $this->t('View Transition Advanced Options'),
'#default_value' => $this->getConfiguration()['transition_advanced'],
];
// Need to wrap this so it indents correctly.
$form['views_slideshow_cycle']['transition_advanced_wrapper'] = [
'#markup' => '<div class="vs-dependent">',
];
$form['views_slideshow_cycle']['timeout'] = [
'#type' => 'textfield',
'#title' => $this->t('Timer delay'),
'#default_value' => $this->getConfiguration()['timeout'],
'#description' => $this->t('Amount of time in milliseconds between transitions. Set the value to 0 to not rotate the slideshow automatically.'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][transition_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['speed'] = [
'#type' => 'textfield',
'#title' => $this->t('Speed'),
'#default_value' => $this->getConfiguration()['speed'],
'#description' => $this->t('Time in milliseconds that each transition lasts. Numeric only!'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][transition_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['delay'] = [
'#type' => 'textfield',
'#title' => $this->t('Initial slide delay offset'),
'#default_value' => $this->getConfiguration()['delay'],
'#description' => $this->t('Amount of time in milliseconds for the first slide to transition. This number will be added to Timer delay to create the initial delay. For example if Timer delay is 4000 and Initial delay is 2000 then the first slide will change at 6000ms (6 seconds). If Initial delay is -2000 then the first slide will change at 2000ms (2 seconds).'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][transition_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['sync'] = [
'#type' => 'checkbox',
'#title' => $this->t('Sync'),
'#default_value' => $this->getConfiguration()['sync'],
'#description' => $this->t('The sync option controls whether the slide transitions occur simultaneously. The default is selected which means that the current slide transitions out as the next slide transitions in. By unselecting this option you can get some interesting twists on your transitions.'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][transition_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['random'] = [
'#type' => 'checkbox',
'#title' => $this->t('Random'),
'#description' => $this->t('This option controls the order items are displayed. The default setting, unselected, uses the views ordering. Selected will cause the images to display in a random order.'),
'#default_value' => $this->getConfiguration()['random'],
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][transition_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['transition_advanced_wrapper_close'] = [
'#markup' => '</div>',
];
// Action.
$form['views_slideshow_cycle']['action'] = [
'#markup' => '<h2>' . $this->t('Action') . '</h2>',
];
$form['views_slideshow_cycle']['pause'] = [
'#type' => 'checkbox',
'#title' => $this->t('Pause on hover'),
'#default_value' => $this->getConfiguration()['pause'],
'#description' => $this->t('Pause when hovering on the slideshow image.'),
];
$form['views_slideshow_cycle']['pause_on_click'] = [
'#type' => 'checkbox',
'#title' => $this->t('Pause On Click'),
'#default_value' => $this->getConfiguration()['pause_on_click'],
'#description' => $this->t('Pause when the slide is clicked.'),
];
// Action Advanced Options.
$form['views_slideshow_cycle']['action_advanced'] = [
'#type' => 'checkbox',
'#title' => $this->t('View Action Advanced Options'),
'#default_value' => $this->getConfiguration()['action_advanced'],
];
// Need to wrap this so it indents correctly.
$form['views_slideshow_cycle']['action_advanced_wrapper'] = [
'#markup' => '<div class="vs-dependent">',
];
$form['views_slideshow_cycle']['start_paused'] = [
'#type' => 'checkbox',
'#title' => $this->t('Start Slideshow Paused'),
'#default_value' => $this->getConfiguration()['start_paused'],
'#description' => $this->t('Start the slideshow in the paused state.'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['remember_slide'] = [
'#type' => 'checkbox',
'#title' => $this->t('Start On Last Slide Viewed'),
'#default_value' => $this->getConfiguration()['remember_slide'],
'#description' => $this->t('When the user leaves a page with a slideshow and comes back start them on the last slide viewed.'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['remember_slide_days'] = [
'#type' => 'textfield',
'#title' => $this->t('Length of Time to Remember Last Slide'),
'#default_value' => $this->getConfiguration()['remember_slide_days'],
'#description' => $this->t('The number of days to have the site remember the last slide. Default is 1'),
'#prefix' => '<div class="vs-dependent">',
'#suffix' => '</div>',
'#size' => 4,
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
':input[name="style_options[views_slideshow_cycle][remember_slide]"]' => ['checked' => TRUE],
],
],
];
// @todo Check if there is a better way to detect optional libraries.
$pause = \Drupal::service('library.discovery')->getLibraryByName('views_slideshow_cycle', 'jquery_pause');
if (isset($pause['js'][0]['data']) && file_exists($pause['js'][0]['data'])) {
$form['views_slideshow_cycle']['pause_in_middle'] = [
'#type' => 'checkbox',
'#title' => $this->t('Pause The Slideshow In The Middle of the Transition'),
'#default_value' => $this->getConfiguration()['pause_in_middle'],
'#description' => $this->t('When pausing the slideshow allow it to pause in the middle of tranistioning and not finish the transition until unpaused.'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][transition_advanced]"]' => ['checked' => TRUE],
],
],
];
}
$form['views_slideshow_cycle']['pause_when_hidden'] = [
'#type' => 'checkbox',
'#title' => $this->t('Pause When the Slideshow is Not Visible'),
'#default_value' => $this->getConfiguration()['pause_when_hidden'],
'#description' => $this->t('When the slideshow is scrolled out of view or when a window is resized that hides the slideshow, this will pause the slideshow.'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['pause_when_hidden_type'] = [
'#type' => 'select',
'#title' => $this->t('How to Calculate Amount of Slide that Needs to be Shown'),
'#options' => [
'full' => $this->t('Entire slide'),
'vertical' => $this->t('Set amount of vertical'),
'horizontal' => $this->t('Set amount of horizontal'),
'area' => $this->t('Set total area of the slide'),
],
'#default_value' => $this->getConfiguration()['pause_when_hidden_type'],
'#description' => $this->t('Choose how to calculate how much of the slide has to be shown. Entire Slide: All the slide has to be shown. Vertical: Set amount of height that has to be shown. Horizontal: Set amount of width that has to be shown. Area: Set total area that has to be shown.'),
'#prefix' => '<div class="vs-dependent">',
'#suffix' => '</div>',
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
':input[name="style_options[views_slideshow_cycle][pause_when_hidden]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['amount_allowed_visible'] = [
'#type' => 'textfield',
'#title' => $this->t('Amount of Slide Needed to be Shown'),
'#default_value' => $this->getConfiguration()['amount_allowed_visible'],
'#description' => $this->t("The amount of the slide that needs to be shown to have it rotate. You can set the value in percentage (ex: 50%) or in pixels (ex: 250). The slidehsow will not rotate until it's height/width/total area, depending on the calculation method you have chosen above, is less than the value you have entered in this field."),
'#size' => 4,
];
$form['views_slideshow_cycle']['#attached']['library'][] = 'views_slideshow_cycle/formoptions';
$form['views_slideshow_cycle']['nowrap'] = [
'#type' => 'checkbox',
'#title' => $this->t('End slideshow after last slide'),
'#default_value' => $this->getConfiguration()['nowrap'],
'#description' => $this->t('If selected the slideshow will end when it gets to the last slide.'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['fixed_height'] = [
'#type' => 'checkbox',
'#title' => $this->t('Make the slide window height fit the largest slide'),
'#default_value' => $this->getConfiguration()['fixed_height'],
'#description' => $this->t('If unselected then if the slides are different sizes the height of the slide area will change as the slides change.'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['items_per_slide'] = [
'#type' => 'textfield',
'#title' => $this->t('Items per slide'),
'#default_value' => $this->getConfiguration()['items_per_slide'],
'#description' => $this->t('The number of items per slide'),
'#size' => 4,
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['items_per_slide_first'] = [
'#type' => 'checkbox',
'#title' => $this->t('Different first slide'),
'#default_value' => $this->getConfiguration()['items_per_slide_first'],
'#description' => $this->t('Different number of items for the first slide'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['items_per_slide_first_number'] = [
'#type' => 'textfield',
'#title' => $this->t('Items for first slide'),
'#default_value' => $this->getConfiguration()['items_per_slide_first_number'],
'#description' => $this->t('The number of items for the first slide'),
'#size' => 4,
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
':input[name="style_options[views_slideshow_cycle][items_per_slide_first]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['wait_for_image_load'] = [
'#type' => 'checkbox',
'#title' => $this->t('Wait for all the slide images to load'),
'#default_value' => $this->getConfiguration()['wait_for_image_load'],
'#description' => $this->t('If selected the slideshow will not start unless all the slide images are loaded. This will fix some issues on IE7/IE8/Chrome/Opera.'),
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
],
],
];
$form['views_slideshow_cycle']['wait_for_image_load_timeout'] = [
'#type' => 'textfield',
'#title' => $this->t('Timeout'),
'#default_value' => $this->getConfiguration()['wait_for_image_load_timeout'],
'#description' => $this->t('How long should it wait until it starts the slideshow anyway. Time is in milliseconds.'),
'#prefix' => '<div class="vs-dependent">',
'#suffix' => '</div>',
'#states' => [
'visible' => [
':input[name="style_options[views_slideshow_cycle][action_advanced]"]' => ['checked' => TRUE],
':input[name="style_options[views_slideshow_cycle][wait_for_image_load]"]' => ['checked' => TRUE],
],
],
];
// Need to wrap this so it indents correctly.
$form['views_slideshow_cycle']['action_advanced_wrapper_close'] = [
'#markup' => '</div>',
];
// Internet Explorer Tweaks.
$form['views_slideshow_cycle']['ie_tweaks'] = [
'#markup' => '<h2>' . $this->t('Internet Explorer Tweaks') . '</h2>',
];
$form['views_slideshow_cycle']['cleartype'] = [
'#type' => 'checkbox',
'#title' => $this->t('ClearType'),
'#default_value' => $this->getConfiguration()['cleartype'],
'#description' => $this->t('Select if clearType corrections should be applied (for IE). Some background issues could be fixed by unselecting this option.'),
];
$form['views_slideshow_cycle']['cleartypenobg'] = [
'#type' => 'checkbox',
'#title' => $this->t('ClearType Background'),
'#default_value' => $this->getConfiguration()['cleartypenobg'],
'#description' => $this->t('Select to disable extra cleartype fixing. Unselect to force background color setting on slides)'),
];
// Advanced Options.
$form['views_slideshow_cycle']['advanced_options_header'] = [
'#markup' => '<h2>' . $this->t('jQuery Cycle Custom Options') . '</h2>',
];
// @todo Check if there is a better way to detect optional libraries.
$json2 = \Drupal::service('library.discovery')->getLibraryByName('views_slideshow_cycle', 'json2');
if (!isset($json2['js'][0]['data']) || !file_exists($json2['js'][0]['data'])) {
// @todo Check if there is a better way to create this target _blank link.
$form['views_slideshow_cycle']['no_json_js'] = [
'#markup' => '<div>' . $this->t('To use the advanced options you need to download json2.js. You can do this by clicking the download button at <a href="https://github.com/douglascrockford/JSON-js" target="_black">https://github.com/douglascrockford/JSON-js</a> and extract json2.js to libraries/json2') . '</div>',
];
}
else {
// @todo Check if there is a better way to create this target _blank link.
$form['views_slideshow_cycle']['advanced_options_info'] = [
'#markup' => '<p>' . $this->t('You can find a list of all the available options at <a href="http://malsup.com/jquery/cycle/options.html" target="_blank">http://malsup.com/jquery/cycle/options.html</a>. If one of the options you add uses a function, example fxFn, then you need to only enter what goes inside the function call. The variables that are in the documentation on the jquery cycle site will be available to you.') . '</p>',
];
// All the jquery cycle options according to
// http://malsup.com/jquery/cycle/options.html
$cycle_options = [
0 => 'Select One',
'activePagerClass' => 'activePagerClass',
'after' => 'after',
'allowPagerClickBubble' => 'allowPagerClickBubble',
'animIn' => 'animIn',
'animOut' => 'animOut',
'autostop' => 'autostop',
'autostopCount' => 'autostopCount',
'backwards' => 'backwards',
'before' => 'before',
'bounce' => 'bounce',
'cleartype' => 'cleartype',
'cleartypeNoBg' => 'cleartypeNoBg',
'containerResize' => 'containerResize',
'continuous' => 'continuous',
'cssAfter' => 'cssAfter',
'cssBefore' => 'cssBefore',
'delay' => 'delay',
'easeIn' => 'easeIn',
'easeOut' => 'easeOut',
'easing' => 'easing',
'end' => 'end',
'fastOnEvent' => 'fastOnEvent',
'fit' => 'fit',
'fx' => 'fx',
'fxFn' => 'fxFn',
'height' => 'height',
'manualTrump' => 'manualTrump',
'metaAttr' => 'metaAttr',
'next' => 'next',
'nowrap' => 'nowrap',
'onPagerEvent' => 'onPagerEvent',
'onPrevNextEvent' => 'onPrevNextEvent',
'pager' => 'pager',
'pagerAnchorBuilder' => 'pagerAnchorBuilder',
'pagerEvent' => 'pagerEvent',
'pause' => 'pause',
'paused' => 'paused',
'pauseOnPagerHover' => 'pauseOnPagerHover',
'prev' => 'prev',
'prevNextEvent' => 'prevNextEvent',
'random' => 'random',
'randomizeEffects' => 'randomizeEffects',
'requeueOnImageNotLoaded' => 'requeueOnImageNotLoaded',
'requeueTimeout' => 'requeueTimeout',
'resumed' => 'resumed',
'rev' => 'rev',
'shuffle' => 'shuffle',
'slideExpr' => 'slideExpr',
'slideResize' => 'slideResize',
'speed' => 'speed',
'speedIn' => 'speedIn',
'speedOut' => 'speedOut',
'startingSlide' => 'startingSlide',
'sync' => 'sync',
'timeout' => 'timeout',
'timeoutFn' => 'timeoutFn',
'updateActivePagerLink' => 'updateActivePagerLink',
'width' => 'width',
];
$form['views_slideshow_cycle']['advanced_options_choices'] = [
'#type' => 'select',
'#title' => $this->t('Advanced Options'),
'#options' => $cycle_options,
];
$form['views_slideshow_cycle']['advanced_options_entry'] = [
'#type' => 'textarea',
'#title' => $this->t('Advanced Option Value'),
'#description' => $this->t('It is important that you click the Update link when you make any changes to the options or those changes will not be saved when you save the form.'),
];
$form['views_slideshow_cycle']['advanced_options'] = [
'#type' => 'textarea',
'#default_value' => $this->getConfiguration()['advanced_options'],
];
// @todo: Review how to create this table.
$form['views_slideshow_cycle']['advanced_options_table'] = [
'#markup' => '<table style="width: 400px; margin-left: 10px;" id="edit-style-options-views-slideshow-cycle-advanced-options-table"></table>',
];
}
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
$values = $form_state->getValue(['style_options', 'views_slideshow_cycle']);
if (!is_numeric($values['timeout'])) {
$form_state->setErrorByName('style_options][views_slideshow_cycle][timeout', $this->t('@setting must be numeric!',
['@setting' => $this->t('Timeout')]
));
}
if (!is_numeric($values['speed'])) {
$form_state->setErrorByName('style_options][views_slideshow_cycle][speed', $this->t('@setting must be numeric!',
['@setting' => $this->t('Speed')]
));
}
if (!is_numeric($values['remember_slide_days'])) {
$form_state->setErrorByName('style_options][views_slideshow_cycle][remember_slide_days', $this->t('@setting must be numeric!',
['@setting' => $this->t('Slide days')]
));
}
}
}
{#
/**
* @file
* Default theme implementation for an item on a views slideshow cycle slide.
*
* Available variables:
* - classes: Classes to apply to the element.
* - count: The slide number.
* - item: Rendeder field(s) making up item.
* - item_count: nth item on slide.
* - length: Total number of slides.
* - view: The view.
*
* @see template_preprocess_views_slideshow_cycle_main_frame_row_item()
*
* @ingroup vss_templates
*/
#}
<div {{ attributes.addClass(classes) }}>
{{ item }}
</div>
{#
/**
* @file
* Default theme implementation for an individual views slideshow cycle slide.
*
* Available variables:
* - classes: Classes to apply to the element.
* - count: The slide number.
* - rendered_items: Rendered items for slide.
* - vss_id: The slideshow's id.
*
* @see template_preprocess_views_slideshow_()
*
* @ingroup vss_templates
*/
#}
<div id="views_slideshow_cycle_div_{{ vss_id }}_{{ count }}" {{ attributes.addClass(classes) }}>
{% for rendered_item in rendered_items %}
{{ rendered_item }}
{% endfor %}
</div>
{#
/**
* @file
* Default theme implementation for an views slideshow cycle main frame.
*
* Available variables:
* - classes: Classes to apply to the element.
* - rendered_rows: The slides.
* - vss_id: The slideshow id.
*
* @see template_preprocess_views_slideshow_cycle_main_frame()
*
* @ingroup vss_templates
*/
#}
<div id="views_slideshow_cycle_teaser_section_{{ vss_id }}" {{ attributes.addClass(classes) }}>
{% for rendered_row in rendered_rows %}
{{ rendered_row }}
{% endfor %}
</div>
{#
/**
* @file
* Default theme implementation for a views slideshow with cycle main plugin.
*
* Available variables:
* - bottom_widget_rendered: Widget under the slideshow with controls/data.
* - skin: The skin being applied to the slideshow.
* - slideshow: The slideshow.
* - top_widget_rendered: Widget above the slideshow with controls/data.
*
* @see _views_slideshow_preprocess_views_view_slideshow()
*
* @ingroup vss_templates
*/
#}
<div class="skin-{{ skin }}">
{% if top_widget_rendered %}
<div class="views-slideshow-controls-top clearfix">
{{ top_widget_rendered }}
</div>
{% endif %}
{{ slideshow }}
{% if bottom_widget_rendered %}
<div class="views-slideshow-controls-bottom clearfix">
{{ bottom_widget_rendered }}
</div>
{% endif %}
</div>
<?php
/**
* @file
* Drush integration for Views Slideshow.
*
* Specifically downloading of required and optional JavaScript libraries.
*/
use Drush\Drush;
/**
* Implements hook_drush_command().
*/
function views_slideshow_cycle_drush_command() {
$items = [];
// The key in the $items array is the name of the command.
$items['views-slideshow-cycle-cycle'] = [
'description' => dt('Download and install the jQuery Cycle library.'),
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
'arguments' => [
'path' => dt('Optional. The path to install the jQuery Cycle library in. If omitted Drush will use the default location.'),
],
'aliases' => ['dl-cycle'],
];
$items['views-slideshow-cycle-json2'] = [
'description' => dt('Download and install the JSON2 library.'),
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
'arguments' => [
'path' => dt('Optional. The path to install the JSON2 library in. If omitted Drush will use the default location.'),
],
'aliases' => ['dl-json2'],
];
$items['views-slideshow-cycle-hoverintent'] = [
'description' => dt('Download and install the jquery.hoverIntent library.'),
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
'arguments' => [
'path' => dt('Optional. The path to install the jquery.hoverIntent library in. If omitted Drush will use the default location.'),
],
'aliases' => ['dl-hoverintent'],
];
$items['views-slideshow-cycle-pause'] = [
'description' => dt('Download and install the jQuery.pause library.'),
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
'arguments' => [
'path' => dt('Optional. The path to install the jQuery.pause library in. If omitted Drush will use the default location.'),
],
'aliases' => ['dl-pause'],
];
$items['views-slideshow-cycle-lib'] = [
'description' => dt('Download and install the jQuery Cycle, jQuery hoverIntent and JSON2 libraries.'),
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
'aliases' => ['dl-cycle-lib'],
];
return $items;
}
/**
* Implements hook_drush_help().
*/
function views_slideshow_cycle_drush_help($section) {
switch ($section) {
case 'drush:views-slideshow-cycle-cycle':
return dt('Download and install the jQuery Cycle library from http://malsup.github.com/jquery.cycle.all.js, default location is libraries/jquery.cycle.');
case 'drush:views-slideshow-cycle-hoverintent':
return dt('Download and install the jQuery hoverIntent library from https://raw.githubusercontent.com/briancherne/jquery-hoverIntent/master/jquery.hoverIntent.js, default location is libraries/jquery.cycle.');
case 'drush:views-slideshow-cycle-pause':
return dt('Download and install the jQuery pause library from https://raw.githubusercontent.com/tobia/Pause/master/jquery.pause.js, default location is libraries/jquery.pause.');
case 'drush:views-slideshow-cycle-json2':
return dt('Download and install the JSON2 library from https://github.com/douglascrockford/JSON-js/, default location is libraries/json2.');
case 'drush:views-slideshow-cycle-lib':
return dt('Download and install the jQuery Cycle, jQuery hoverIntent and JSON2 libraries.');
}
}
/**
* Command to download the jQuery Cycle library.
*/
function drush_views_slideshow_cycle_cycle() {
_drush_views_slideshow_cycle_install_library(
'jQuery Cycle',
'libraries/jquery.cycle',
'jquery.cycle.all.js',
'https://raw.githubusercontent.com/malsup/cycle/3.0.3/jquery.cycle.all.js',
func_get_args()
);
}
/**
* Command to download the JSON2 library.
*/
function drush_views_slideshow_cycle_json2() {
_drush_views_slideshow_cycle_install_library(
'JSON2',
'libraries/json2',
'json2.js',
'https://raw.githubusercontent.com/douglascrockford/JSON-js/master/json2.js',
func_get_args()
);
}
/**
* Command to download the jQuery.hoverIntent library.
*/
function drush_views_slideshow_cycle_hoverintent() {
_drush_views_slideshow_cycle_install_library(
'jQuery HoverIntent',
'libraries/jquery.hoverIntent',
'jquery.hoverIntent.js',
'https://raw.githubusercontent.com/briancherne/jquery-hoverIntent/master/jquery.hoverIntent.js',
func_get_args()
);
}
/**
* Command to download the jQuery.pause library.
*/
function drush_views_slideshow_cycle_pause() {
_drush_views_slideshow_cycle_install_library(
'jQuery Pause',
'libraries/jquery.pause',
'jquery.pause.js',
'https://raw.githubusercontent.com/tobia/Pause/master/jquery.pause.js',
func_get_args()
);
}
/**
* Command to download all libraries.
*/
function drush_views_slideshow_cycle_lib() {
drush_views_slideshow_cycle_cycle();
drush_views_slideshow_cycle_json2();
drush_views_slideshow_cycle_hoverintent();
drush_views_slideshow_cycle_pause();
}
/**
* Implements drush_MODULE_pre_pm_enable().
*/
function drush_views_slideshow_cycle_pre_pm_enable() {
$modules = drush_get_context('PM_ENABLE_MODULES');
if (in_array('views_slideshow_cycle', $modules) && !drush_get_option('skip')) {
drush_views_slideshow_cycle_lib();
}
}
/**
* Helper function to download a library in the given directory.
*/
function _drush_views_slideshow_cycle_install_library($name, $path, $filename, $url, $args) {
// Check if path provided as an arg and use that instead of default if so.
if (!empty($args[0])) {
$path = $args[0];
}
// Create the path if it does not exist.
if (!is_dir($path)) {
drush_op('mkdir', $path, 0755, TRUE);
\Drupal::logger(dt('Directory @path was created', ['@path' => $path]), 'success');
}
// Be sure we can write in the directory.
$perms = substr(sprintf('%o', fileperms($path)), -4);
if ($perms !== '0755') {
Drush::process('chmod 755 ' . $path);
}
$dir = getcwd();
// Download the JavaScript file.
if (is_file($path . '/' . $filename)) {
\Drupal::logger(dt('@name appears to be already installed.', [
'@name' => $name,
]), 'ok');
}
elseif (drush_op('chdir', $path) && Drush::process('wget --no-check-certificate ' . $url)) {
\Drupal::logger(dt('The latest version of @name has been downloaded to @path', [
'@name' => $name,
'@path' => $path,
]), 'success');
}
else {
\Drupal::logger(dt('Drush was unable to download the @name library to @path', [
'@name' => $name,
'@path' => $path,
]), 'error');
}
chdir($dir);
// Restore the previous permissions.
Drush::process('chmod ' . $perms . ' ' . $path);
}
name: Views Slideshow Cycle
type: module
description: 'Adds a Rotating slideshow mode to Views Slideshow.'
package: Views
core: 8.x
core_version_requirement: ^8 || ^9
dependencies:
- views_slideshow:views_slideshow
# Information added by Drupal.org packaging script on 2020-09-28
version: '8.x-4.8'
project: 'views_slideshow'
datestamp: 1601309227
formoptions:
js:
js/formoptions.js: {}
dependencies:
- core/jquery
- core/drupal
views_slideshow_cycle:
css:
component:
css/views_slideshow_cycle.css: {}
js:
js/views_slideshow_cycle.js: {}
dependencies:
- core/jquery
- core/drupal
- core/drupalSettings
jquery_cycle:
remote: http://malsup.github.io/jquery.cycle.all.js
version: 3.0.3
license:
name: MIT
url: http://jquery.malsup.com/license.html
gpl-compatible: true
js:
/libraries/jquery.cycle/jquery.cycle.all.js: {}
dependencies:
- core/jquery
json2:
remote: https://raw.githubusercontent.com/douglascrockford/JSON-js/master/json2.js
version: 2.0
license:
name: MIT
url: https://github.com/douglascrockford/JSON-js/blob/master/README
gpl-compatible: true
js:
/libraries/json2/json2.js: {}
jquery_pause:
remote: https://github.com/tobia/Pause
version: 3.0.3
license:
name: GNU
url: https://raw.githubusercontent.com/tobia/Pause/master/LICENSE.txt
gpl-compatible: true
js:
/libraries/jquery.pause/jquery.pause.js: {}
dependencies:
- core/jquery
<?php
/**
* @file
* Views Slideshow: cycle is typically used for field views.
*/
use Drupal\Core\Url;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Link;
/**
* Implements hook_help().
*/
function views_slideshow_cycle_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.views_slideshow_cycle':
if (\Drupal::moduleHandler()->moduleExists('advanced_help')) {
$output = '<p>' . Link::fromTextAndUrl(t('Click here to view the documentation for Views Slideshow Cycle.'), Url::fromRoute('advanced_help.module_index', ['module' => 'views_slideshow_cycle'])->toString()) . '</p>';
}
else {
$output = '<p>' . t('Views Slideshow Cycle help can be found by installing and enabling the @advanced_help', ['@advanced_help' => Link::fromTextAndUrl(t('Advanced Help module'), Url::fromUri('http://drupal.org/project/advanced_help'))->toString()]) . '</p>';
}
return $output;
}
}
/**
* Implements hook_theme().
*/
function views_slideshow_cycle_theme($existing, $type, $theme, $path) {
return [
'views_slideshow_cycle' => [
'variables' => [
'view' => NULL,
'settings' => [],
'rows' => [],
'title' => '',
],
'template' => 'views-slideshow-cycle',
'file' => 'views_slideshow_cycle.theme.inc',
],
'views_slideshow_cycle_main_frame' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => NULL,
'rows' => NULL,
],
'template' => 'views-slideshow-cycle-main-frame',
'file' => 'views_slideshow_cycle.theme.inc',
],
'views_slideshow_cycle_main_frame_row' => [
'variables' => [
'vss_id' => NULL,
'items' => NULL,
'count' => NULL,
'view' => NULL,
],
'template' => 'views-slideshow-cycle-main-frame-row',
'file' => 'views_slideshow_cycle.theme.inc',
],
'views_slideshow_cycle_main_frame_row_item' => [
'variables' => [
'item' => NULL,
'item_count' => NULL,
'count' => NULL,
'view' => NULL,
'length' => NULL,
],
'template' => 'views-slideshow-cycle-main-frame-row-item',
'file' => 'views_slideshow_cycle.theme.inc',
],
];
}
/**
* Implements hook_preprocess_views_slideshow_pager_fields().
*
* As it is a preprocess function, store it with other functions in theme.inc.
*/
function views_slideshow_cycle_preprocess_views_slideshow_pager_fields(&$vars) {
\Drupal::moduleHandler()->loadInclude('views_slideshow_cycle', 'inc', 'views_slideshow_cycle.theme');
_views_slideshow_cycle_preprocess_views_slideshow_pager_fields($vars);
}
/**
* Implements hook_preprocess_views_slideshow_slide_counter().
*
* As it is a preprocess function, store it with other functions in theme.inc.
*/
function views_slideshow_cycle_preprocess_views_slideshow_slide_counter(&$vars) {
\Drupal::moduleHandler()->loadInclude('views_slideshow_cycle', 'inc', 'views_slideshow_cycle.theme');
_views_slideshow_cycle_preprocess_views_slideshow_slide_counter($vars);
}
<?php
/**
* @file
* Theme & preprocess functions for the Views Slideshow: cycle module.
*/
use Drupal\Component\Utility\Html;
/**
* Views Slideshow: Theme the main frame wrapper.
*
* @ingroup vss_theme
*/
function template_preprocess_views_slideshow_cycle_main_frame(&$vars) {
$settings = $vars['settings'];
$rows = $vars['rows'];
$vss_id = $vars['vss_id'];
// Cast the strings into int or bool as necessary.
$new_settings = [];
foreach ($settings as $key => $value) {
if (is_string($value)) {
$value = str_replace("\n", ' ', $value);
$value = trim($value);
if (is_numeric($value)) {
$value = (int) $value;
}
elseif (strtolower($value) == 'true') {
$value = TRUE;
}
elseif (strtolower($value) == 'false') {
$value = FALSE;
}
}
$new_settings[$key] = $value;
}
$num_divs = count($rows);
if ($settings['items_per_slide_first']) {
$num_divs -= $settings['items_per_slide_first_number'];
$num_divs = $num_divs / $settings['items_per_slide'];
$num_divs += 1;
}
else {
$num_divs = $num_divs / $settings['items_per_slide'];
}
$settings = array_merge(
[
'num_divs' => ceil($num_divs),
'id_prefix' => '#views_slideshow_cycle_main_',
'div_prefix' => '#views_slideshow_cycle_div_',
'vss_id' => $vss_id,
],
$new_settings
);
// We need to go through the current js setting values to make sure the one we
// want to add is not already there. If it is already there then append -[num]
// to the id to make it unique.
$slideshow_count = 1;
global $_views_slideshow_processedCycles;
if (is_array($_views_slideshow_processedCycles)) {
foreach ($_views_slideshow_processedCycles as $processedCycle) {
if (stristr($processedCycle, '#views_slideshow_cycle_main_' . $vss_id)) {
$slideshow_count++;
}
}
}
if ($slideshow_count > 1) {
$vss_id .= '-' . $slideshow_count;
$settings['vss_id'] = $vss_id;
}
// Load the json2 library.
if (!empty($settings['advanced_options'])) {
$vars['#attached']['library'][] = 'views_slideshow_cycle/json2';
}
// Load the pause library.
if (!empty($settings['pause_in_middle'])) {
$vars['#attached']['library'][] = 'views_slideshow_cycle/jquery_pause';
}
// Load jQuery Cycle library.
$vars['#attached']['library'][] = 'views_slideshow_cycle/jquery_cycle';
// Load our custom cycle library.
$vars['#attached']['library'][] = 'views_slideshow_cycle/views_slideshow_cycle';
$vars['#attached']['drupalSettings']['viewsSlideshowCycle']['#views_slideshow_cycle_main_' . $vss_id] = $settings;
$_views_slideshow_processedCycles['#views_slideshow_cycle_main_' . $vss_id] = '#views_slideshow_cycle_main_' . $vss_id;
// Add hover intent library.
if ($settings['pause']) {
$vars['#attached']['library'][] = 'views_slideshow/jquery_hoverIntent';
}
// Add the slideshow elements.
$vars['attributes']['class'][] = 'views_slideshow_cycle_teaser_section';
$vars['items_per_slide'] = $settings['items_per_slide'];
$items = [];
$index = 0;
$vars['rendered_rows'] = [];
foreach ($rows as $count => $item) {
$items[] = $item;
if ($settings['items_per_slide_first'] && empty($vars['rendered_rows'])) {
if (count($items) == $settings['items_per_slide_first_number'] || $count == (count($rows) - 1)) {
$vars['rendered_rows'][] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_cycle_main_frame_row'),
'#vss_id' => $vss_id,
'#items' => $items,
'#count' => $index,
'#view' => $vars['view'],
];
$items = [];
$index++;
}
}
elseif (count($items) == $settings['items_per_slide'] || $count == (count($rows) - 1)) {
$vars['rendered_rows'][] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_cycle_main_frame_row'),
'#vss_id' => $vss_id,
'#items' => $items,
'#count' => $index,
'#view' => $vars['view'],
];
$items = [];
$index++;
}
}
}
/**
* Views Slideshow slideshow rows.
*
* @ingroup vss_theme
*/
function template_preprocess_views_slideshow_cycle_main_frame_row(&$vars) {
$current = $vars['count'] + 1;
$vars['attributes']['class'][] = 'views_slideshow_cycle_slide';
$vars['attributes']['class'][] = 'views_slideshow_slide views-row-' . $current;
if ($vars['count']) {
$vars['attributes']['class'][] = 'views_slideshow_cycle_hidden';
}
$vars['attributes']['class'][] = ($vars['count'] % 2) ? 'views-row-even' : 'views-row-odd';
$vars['rendered_items'] = [];
foreach ($vars['items'] as $item_count => $item) {
$vars['rendered_items'][] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_cycle_main_frame_row_item'),
'#item' => $item,
'#item_count' => $item_count,
'#count' => $vars['count'],
'#view' => $vars['view'],
'#length' => count($vars['view']->result),
];
}
}
/**
* Views Slideshow slideshow row items.
*
* @ingroup vss_theme
*/
function template_preprocess_views_slideshow_cycle_main_frame_row_item(&$vars) {
$vars['attributes']['class'][] = 'views-row views-row-' . $vars['count'];
$vars['attributes']['class'][] = ($vars['count'] % 2) ? 'views-row-even' : 'views-row-odd';
if ($vars['count'] == 0) {
$vars['attributes']['class'][] = 'views-row-first';
}
elseif ($vars['count'] == $vars['length'] - 1) {
$vars['attributes']['class'][] = 'views-row-last';
}
// Support custom row classes.
if ($row_class = $vars['view']->style_plugin->getRowClass($vars['count'])) {
$vars['attributes']['class'][] = $row_class;
}
}
/**
* Implements hook_preprocess_views_slideshow_pager_fields().
*
* @ingroup vss_theme
*/
function _views_slideshow_cycle_preprocess_views_slideshow_pager_fields(&$vars) {
$slide_count = count($vars['view']->result);
$options = $vars['view']->style_plugin->options['views_slideshow_cycle'];
$items_per_slide = $options['items_per_slide'];
if ($vars['settings']['hide_on_single_slide'] && $slide_count == 1) {
return;
}
$vars['rendered_field_items'] = [];
for ($slide = 0, $count = 0; $slide < $slide_count; $count++) {
$rendered_fields = [];
foreach ($vars['settings']['views_slideshow_pager_fields']['views_slideshow_pager_fields_fields'] as $field => $use) {
if ($use !== 0 && is_object($vars['view']->field[$field])) {
$rendered_fields[] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_pager_field_field'),
'#view' => $vars['view'],
'#label' => $vars['view']->field[$field]->options['label'],
'#output' => $vars['view']->style_plugin->getField($slide, $field),
'#css_identifier' => Html::cleanCssIdentifier($vars['view']->field[$field]->field),
];
}
}
if (empty($vars['rendered_field_items']) && $options['items_per_slide_first']) {
$slide += $options['items_per_slide_first_number'];
}
elseif ($options['items_per_slide']) {
$slide += $options['items_per_slide'];
}
else {
$slide += 1;
}
$vars['rendered_field_items'][] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_pager_field_item'),
'#vss_id' => $vars['vss_id'],
'#item' => $rendered_fields,
'#count' => $count,
'#location' => $vars['location'],
];
}
}
/**
* Implements hook_preprocess_views_slideshow_slide_counter().
*
* @ingroup vss_theme
*/
function _views_slideshow_cycle_preprocess_views_slideshow_slide_counter(&$vars) {
$options = $vars['view']->style_plugin->options['views_slideshow_cycle'];
if ($options['items_per_slide_first']) {
$slide_count = $vars['slide_count'] - $options['items_per_slide_first_number'];
$slide_count = $slide_count / $options['items_per_slide'];
$slide_count += 1;
}
else {
$slide_count = $vars['slide_count'] / $options['items_per_slide'];
}
$vars['slide_count'] = ceil($slide_count);
}
<?php
namespace Drupal\views_slideshow\Annotation;
use Drupal\Component\Annotation\Plugin;
/**
* Defines a slideshow skin annotation object.
*
* @Annotation
*/
class ViewsSlideshowSkin extends Plugin {
/**
* The plugin ID.
*
* @var string
*/
public $id;
/**
* The human-readable name of the slideshow skin.
*
* @var \Drupal\Core\Annotation\Translation
*
* @ingroup plugin_translatable
*/
public $label;
/**
* A list of libraries this slideshow skin needs to attach.
*
* @var string[]
*/
public $libraries;
}
<?php
namespace Drupal\views_slideshow\Annotation;
use Drupal\Component\Annotation\Plugin;
/**
* Defines a slideshow type annotation object.
*
* @Annotation
*/
class ViewsSlideshowType extends Plugin {
/**
* The plugin ID.
*
* @var string
*/
public $id;
/**
* The human-readable name of the slideshow type.
*
* @var \Drupal\Core\Annotation\Translation
*
* @ingroup plugin_translatable
*/
public $label;
/**
* A list of actions this slideshow type accepts.
*
* @var string[]
*/
public $accepts;
/**
* A list of actions this slideshow type implements.
*
* @var string[]
*/
public $calls;
}
<?php
namespace Drupal\views_slideshow\Annotation;
use Drupal\Component\Annotation\Plugin;
/**
* Defines a widget annotation object.
*
* @Annotation
*/
class ViewsSlideshowWidget extends Plugin {
/**
* The plugin ID.
*
* @var string
*/
public $id;
/**
* The human-readable name of the widget.
*
* @var \Drupal\Core\Annotation\Translation
*
* @ingroup plugin_translatable
*/
public $label;
/**
* The widget type used by the widget.
*
* @var string
*/
public $type;
}
<?php
namespace Drupal\views_slideshow\Annotation;
use Drupal\Component\Annotation\Plugin;
/**
* Defines a widget type annotation object.
*
* @Annotation
*/
class ViewsSlideshowWidgetType extends Plugin {
/**
* The plugin ID.
*
* @var string
*/
public $id;
/**
* The human-readable name of the widget type.
*
* @var \Drupal\Core\Annotation\Translation
*
* @ingroup plugin_translatable
*/
public $label;
/**
* A list of actions this widget type accepts.
*
* @var array
*/
public $accepts;
/**
* A list of actions this widget type implements.
*
* @var array
*/
public $calls;
}
<?php
namespace Drupal\views_slideshow;
/**
* Provides a class to manipulate addons names.
*/
class FormatAddonsName implements FormatAddonsNameInterface {
/**
* Format callback to move from underscore separated words to camelCase.
*/
public function format($subject) {
return preg_replace_callback('/_(.?)/', function ($matches) {
if (isset($matches[1])) {
return strtoupper($matches[1]);
}
}, $subject);
}
}
<?php
namespace Drupal\views_slideshow;
/**
* Provides a class for CRUD operations on path aliases.
*/
interface FormatAddonsNameInterface {
/**
* Format callback manipulate addons names.
*/
public function format($subject);
}
<?php
namespace Drupal\views_slideshow\Plugin\ViewsSlideshowSkin;
use Drupal\views_slideshow\ViewsSlideshowSkinBase;
/**
* Provides a default basic skin.
*
* @ViewsSlideshowSkin(
* id = "default",
* label = @Translation("Default"),
* libraries = {}
* )
*/
class DefaultSkin extends ViewsSlideshowSkinBase {}
<?php
namespace Drupal\views_slideshow\Plugin\ViewsSlideshowWidget;
use Drupal\views_slideshow\ViewsSlideshowWidgetBase;
/**
* Provides some controls in text format.
*
* @ViewsSlideshowWidget(
* id = "views_slideshow_controls_text",
* type = "views_slideshow_controls",
* label = @Translation("Text"),
* )
*/
class ControlsText extends ViewsSlideshowWidgetBase {
}
<?php
namespace Drupal\views_slideshow\Plugin\ViewsSlideshowWidget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views_slideshow\ViewsSlideshowWidgetBase;
/**
* Provides a pager using bullets.
*
* @ViewsSlideshowWidget(
* id = "views_slideshow_pager_bullets",
* type = "views_slideshow_pager",
* label = @Translation("Bullets"),
* )
*/
class PagerBullets extends ViewsSlideshowWidgetBase {
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'views_slideshow_pager_bullets_hover' => ['default' => 0],
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
// Add field to see if they would like to activate slide and pause on pager
// hover.
$form['views_slideshow_pager_bullets_hover'] = [
'#type' => 'checkbox',
'#title' => $this->t('Activate Slide and Pause on Pager Hover'),
'#default_value' => $this->getConfiguration()['views_slideshow_pager_bullets_hover'],
'#description' => $this->t('Should the slide be activated and paused when hovering over a pager item.'),
'#states' => [
'visible' => [
':input[name="' . $this->getConfiguration()['dependency'] . '[enable]"]' => ['checked' => TRUE],
':input[name="' . $this->getConfiguration()['dependency'] . '[type]"]' => ['value' => 'views_slideshow_pager_bullets'],
],
],
];
return $form;
}
}
<?php
namespace Drupal\views_slideshow\Plugin\ViewsSlideshowWidget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views_slideshow\ViewsSlideshowWidgetBase;
/**
* Provides a pager using fields.
*
* @ViewsSlideshowWidget(
* id = "views_slideshow_pager_fields",
* type = "views_slideshow_pager",
* label = @Translation("Fields"),
* )
*/
class PagerFields extends ViewsSlideshowWidgetBase {
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'views_slideshow_pager_fields_fields' => ['default' => []],
'views_slideshow_pager_fields_hover' => ['default' => 0],
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
// Settings for fields pager.
$options = [];
// Get each field and it's name.
foreach ($this->getConfiguration()['view']->display_handler->getHandlers('field') as $field_name => $field) {
$options[$field_name] = $field->adminLabel();
}
// Need to wrap this so it indents correctly.
$form['views_slideshow_pager_fields_wrapper'] = [
'#markup' => '<div class="vs-dependent">',
];
// Add ability to choose which fields to show in the pager.
$form['views_slideshow_pager_fields_fields'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Pager fields'),
'#options' => $options,
'#default_value' => $this->getConfiguration()['views_slideshow_pager_fields_fields'],
'#description' => $this->t('Choose the fields that will appear in the pager.'),
'#states' => [
'visible' => [
':input[name="' . $this->getConfiguration()['dependency'] . '[enable]"]' => ['checked' => TRUE],
':input[name="' . $this->getConfiguration()['dependency'] . '[type]"]' => ['value' => 'views_slideshow_pager_fields'],
],
],
];
// Add field to see if they would like to activate slide and pause on pager
// hover.
$form['views_slideshow_pager_fields_hover'] = [
'#type' => 'checkbox',
'#title' => $this->t('Activate Slide and Pause on Pager Hover'),
'#default_value' => $this->getConfiguration()['views_slideshow_pager_fields_hover'],
'#description' => $this->t('Should the slide be activated and paused when hovering over a pager item.'),
'#states' => [
'visible' => [
':input[name="' . $this->getConfiguration()['dependency'] . '[enable]"]' => ['checked' => TRUE],
':input[name="' . $this->getConfiguration()['dependency'] . '[type]"]' => ['value' => 'views_slideshow_pager_fields'],
],
],
];
$form['views_slideshow_pager_fields_wrapper_close'] = [
'#markup' => '</div>',
];
return $form;
}
/**
* {@inheritdoc}
*/
public function checkCompatiblity($view) {
return $view->getStyle()->usesFields();
}
}
<?php
namespace Drupal\views_slideshow\Plugin\ViewsSlideshowWidgetType;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views_slideshow\ViewsSlideshowWidgetTypeBase;
/**
* Provides a control widget type.
*
* @ViewsSlideshowWidgetType(
* id = "views_slideshow_controls",
* label = @Translation("Controls"),
* accepts = {"pause" = {"required" = TRUE}, "play" = {"required" = TRUE}},
* calls = {"nextSlide", "pause", "play", "previousSlide"}
* )
*/
class Controls extends ViewsSlideshowWidgetTypeBase {
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return parent::defaultConfiguration() + [
'type' => ['default' => 0],
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
/* @var \Drupal\Component\Plugin\PluginManagerInterface */
$widgetManager = \Drupal::service('plugin.manager.views_slideshow.widget');
$widgets = $widgetManager->getDefinitions($this->getPluginId());
if (!empty($widgets)) {
$options = [];
foreach ($widgets as $widgetId => $widgetInfo) {
$options[$widgetId] = $widgetInfo['label'];
}
// Need to wrap this so it indents correctly.
$form['views_slideshow_controls_wrapper'] = [
'#markup' => '<div class="vs-dependent">',
];
// Create the widget type field.
$form['type'] = [
'#type' => 'select',
'#title' => $this->t('Controls Type'),
'#description' => $this->t('Style of the controls'),
'#default_value' => $this->getConfiguration()['type'],
'#options' => $options,
'#states' => [
'visible' => [
':input[name="' . $this->getConfiguration()['dependency'] . '[enable]"]' => ['checked' => TRUE],
],
],
];
foreach ($widgets as $widget_id => $widget_info) {
// Get the current configuration of this widget.
$configuration = [];
if (!empty($this->getConfiguration()[$widget_id])) {
$configuration = $this->getConfiguration()[$widget_id];
}
$configuration['dependency'] = $this->getConfiguration()['dependency'];
$instance = $widgetManager->createInstance($widget_id, $configuration);
// Get the configuration form of this widget type.
$form[$widget_id] = isset($form[$widget_id]) ? $form[$widget_id] : [];
$form[$widget_id] = $instance->buildConfigurationForm($form[$widget_id], $form_state);
}
$form['controls_wrapper_close'] = [
'#markup' => '</div>',
];
}
else {
$form['enable_controls'] = [
'#markup' => 'There are no controls available.',
];
}
return $form;
}
}
<?php
namespace Drupal\views_slideshow\Plugin\ViewsSlideshowWidgetType;
use Drupal\views_slideshow\ViewsSlideshowWidgetTypeBase;
/**
* Provides a counter widget type.
*
* @ViewsSlideshowWidgetType(
* id = "views_slideshow_slide_counter",
* label = @Translation("Slide counter"),
* accepts = {
* "transitionBegin" = {"required" = TRUE},
* "goToSlide",
* "previousSlide",
* "nextSlide"
* },
* calls = {}
* )
*/
class Counter extends ViewsSlideshowWidgetTypeBase {
}
<?php
namespace Drupal\views_slideshow\Plugin\ViewsSlideshowWidgetType;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views_slideshow\ViewsSlideshowWidgetTypeBase;
/**
* Provides a pager widget type.
*
* @ViewsSlideshowWidgetType(
* id = "views_slideshow_pager",
* label = @Translation("Pager"),
* accepts = {
* "transitionBegin" = {"required" = TRUE},
* "goToSlide",
* "previousSlide",
* "nextSlide"
* },
* calls = {"goToSlide", "pause", "play"}
* )
*/
class Pager extends ViewsSlideshowWidgetTypeBase {
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
$options = parent::defaultConfiguration() + [
'type' => ['default' => 0],
'views_slideshow_pager_numbered_hover' => ['default' => 0],
'views_slideshow_pager_numbered_click_to_page' => ['default' => 0],
'views_slideshow_pager_thumbnails_hover' => ['default' => 0],
'views_slideshow_pager_thumbnails_click_to_page' => ['default' => 0],
];
/* @var \Drupal\Component\Plugin\PluginManagerInterface */
$widgetManager = \Drupal::service('plugin.manager.views_slideshow.widget');
// Get default configuration of all Pager plugins.
foreach ($widgetManager->getDefinitions($this->getPluginId()) as $widget_id => $widget_info) {
$options += $widgetManager->createInstance($widget_id, [])->defaultConfiguration();
}
return $options;
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$view = $form_state->get('view')->get('executable');
/* @var \Drupal\Component\Plugin\PluginManagerInterface */
$widgetManager = \Drupal::service('plugin.manager.views_slideshow.widget');
// Determine if this widget type is compatible with any slideshow type.
$widgets = [];
foreach ($widgetManager->getDefinitions($this->getPluginId()) as $widget_id => $widget_info) {
if ($widgetManager->createInstance($widget_id, [])->checkCompatiblity($view)) {
$widgets[$widget_id] = $widget_info['label'];
}
}
if (!empty($widgets)) {
// Need to wrap this so it indents correctly.
$form['views_slideshow_pager_wrapper'] = [
'#markup' => '<div class="vs-dependent">',
];
// Create the widget type field.
$form['type'] = [
'#type' => 'select',
'#title' => $this->t('Pager Type'),
'#description' => $this->t('Style of the pager'),
'#default_value' => $this->getConfiguration()['type'],
'#options' => $widgets,
'#states' => [
'visible' => [
':input[name="' . $this->getConfiguration()['dependency'] . '[enable]"]' => ['checked' => TRUE],
],
],
];
foreach ($widgetManager->getDefinitions() as $widget_id => $widget_info) {
// Get the current configuration of this widget.
$configuration = [];
if (!empty($this->getConfiguration()[$widget_id])) {
$configuration = $this->getConfiguration()[$widget_id];
}
$configuration['dependency'] = $this->getConfiguration()['dependency'];
$configuration['view'] = $view;
$instance = $widgetManager->createInstance($widget_id, $configuration);
// Get the configuration form of this widget type.
$form[$widget_id] = isset($form[$widget_id]) ? $form[$widget_id] : [];
$form[$widget_id] = $instance->buildConfigurationForm($form[$widget_id], $form_state);
}
$form['views_slideshow_pager_wrapper_close'] = [
'#markup' => '</div>',
];
}
else {
$form['enable_pager'] = [
'#markup' => 'There are no pagers available.',
];
}
return $form;
}
}
<?php
namespace Drupal\views_slideshow\Plugin\views\style;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\style\StylePluginBase;
use Drupal\Core\Url;
use Drupal\Core\Link;
/**
* Style plugin to render each item in a slideshow.
*
* @ingroup views_style_plugins
*
* @ViewsStyle(
* id = "slideshow",
* title = @Translation("Slideshow"),
* help = @Translation("Display the results as a slideshow."),
* theme = "views_view_slideshow",
* display_types = {"normal"}
* )
*/
class Slideshow extends StylePluginBase {
/**
* Does the style plugin allows to use style plugins.
*
* @var bool
*/
protected $usesRowPlugin = TRUE;
/**
* Does the style plugin support custom css class for the rows.
*
* @var bool
*/
protected $usesRowClass = TRUE;
/**
* Does the style plugin support grouping of rows.
*
* @var bool
*/
protected $usesGrouping = FALSE;
/**
* Does the style plugin for itself support to add fields to it's output.
*
* This option only makes sense on style plugins without row plugins, like
* for example table.
*
* @var bool
*/
protected $usesFields = TRUE;
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['row_class_custom'] = ['default' => ''];
$options['row_class_default'] = ['default' => TRUE];
$options['slideshow_type'] = ['default' => 'views_slideshow_cycle'];
$options['slideshow_skin'] = ['default' => 'default'];
$typeManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_type');
foreach ($typeManager->getDefinitions() as $id => $definition) {
$instance = $typeManager->createInstance($id, []);
$options[$id] = $instance->defaultConfiguration();
}
$widgetTypeManager = \Drupal::service('plugin.manager.views_slideshow.widget_type');
$widgetTypes = $widgetTypeManager->getDefinitions();
foreach (['top', 'bottom'] as $location) {
foreach ($widgetTypes as $widgetTypeId => $widgetTypeDefinition) {
$options['widgets']['contains'][$location]['contains'][$widgetTypeId]['contains'] = $widgetTypeManager->createInstance($widgetTypeId, [])->defaultConfiguration();
}
}
return $options;
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
// Wrap all the form elements to help style the form.
$form['views_slideshow_wrapper'] = [
'#markup' => '<div id="views-slideshow-form-wrapper">',
];
// Skins.
$form['slideshow_skin_header'] = [
'#markup' => '<h2>' . $this->t('Style') . '</h2>',
];
/* @var \Drupal\Component\Plugin\PluginManagerInterface */
$skinManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_skin');
// Get all skins to create the option list.
$skins = [];
foreach ($skinManager->getDefinitions() as $id => $definition) {
$skins[$id] = $definition['label'];
}
asort($skins);
// Create the drop down box so users can choose an available skin.
$form['slideshow_skin'] = [
'#type' => 'select',
'#title' => $this->t('Skin'),
'#options' => $skins,
'#default_value' => $this->options['slideshow_skin'],
'#description' => $this->t('Select the skin to use for this display. Skins allow for easily swappable layouts of things like next/prev links and thumbnails. Note that not all skins support all widgets, so a combination of skins and widgets may lead to unpredictable results in layout.'),
];
// Slides.
$form['slides_header'] = [
'#markup' => '<h2>' . $this->t('Slides') . '</h2>',
];
// Get all slideshow types.
$typeManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_type');
$types = $typeManager->getDefinitions();
if ($types) {
// Build our slideshow options for the form.
$slideshow_options = [];
foreach ($types as $id => $definition) {
$slideshow_options[$id] = $definition['label'];
}
$form['slideshow_type'] = [
'#type' => 'select',
'#title' => $this->t('Slideshow Type'),
'#options' => $slideshow_options,
'#default_value' => $this->options['slideshow_type'],
];
// @todo: check if default values are properly passed to the buildConfigurationForm().
foreach ($types as $id => $definition) {
$configuration = [];
if (!empty($this->options[$id])) {
$configuration = $this->options[$id];
}
$instance = $typeManager->createInstance($id, $configuration);
$form[$id] = [
'#type' => 'fieldset',
'#title' => $this->t('@module options', ['@module' => $definition['label']]),
'#collapsible' => TRUE,
'#attributes' => ['class' => [$id]],
'#states' => [
'visible' => [
':input[name="style_options[slideshow_type]"]' => ['value' => $id],
],
],
];
$form = $instance->buildConfigurationForm($form, $form_state);
}
}
else {
$form['enable_module'] = [
'#markup' => $this->t('There is no Views Slideshow plugin enabled. Go to the @modules and enable a Views Slideshow plugin module. For example Views Slideshow Cycle.', ['@modules' => Link::fromTextAndUrl($this->t('Modules Page'), Url::fromRoute('system.modules_list'))->toString()]),
];
}
// Widgets.
// @todo: Improve the UX by using Ajax.
$form['widgets_header'] = [
'#markup' => '<h2>' . $this->t('Widgets') . '</h2>',
];
// Define the available locations.
$location = ['top' => $this->t('Top'), 'bottom' => $this->t('Bottom')];
// Loop through all locations so we can add header for each location.
foreach ($location as $location_id => $location_name) {
$form['widgets'][$location_id]['header'] = [
'#markup' => '<h3>' . $this->t('@location Widgets', ['@location' => $location_name]) . '</h3>',
];
}
/* @var \Drupal\Component\Plugin\PluginManagerInterface */
$widgetTypeManager = \Drupal::service('plugin.manager.views_slideshow.widget_type');
// Get all widgets types that are registered.
$widgets = $widgetTypeManager->getDefinitions();
if (!empty($widgets)) {
// Build our weight values by number of widgets.
$weights = [];
for ($i = 1; $i <= count($widgets); $i++) {
$weights[$i] = $i;
}
// Loop through our widgets and locations to build our form values for
// each widget.
foreach ($widgets as $widget_id => $widget_info) {
// Determine if this widget type is compatible with any slideshow type.
$compatible_slideshows = [];
foreach ($types as $slideshow_id => $slideshow_info) {
if ($widgetTypeManager->createInstance($widget_id, [])->checkCompatiblity($slideshow_info)) {
$compatible_slideshows[] = $slideshow_id;
}
}
// Display the widget config form only if the widget type is compatible
// with at least one slideshow type.
if (!empty($compatible_slideshows)) {
foreach ($location as $location_id => $location_name) {
// Use Widget Checkbox.
$form['widgets'][$location_id][$widget_id]['enable'] = [
'#type' => 'checkbox',
'#title' => $widget_info['label'],
'#default_value' => $this->options['widgets'][$location_id][$widget_id]['enable'],
'#description' => $this->t('Should @name be rendered at the @location of the slides.', ['@name' => $widget_info['label'], '@location' => $location_name]),
'#dependency' => [
'edit-style-options-slideshow-type' => $compatible_slideshows,
],
];
// Need to wrap this so it indents correctly.
$form['widgets'][$location_id][$widget_id]['wrapper'] = [
'#markup' => '<div class="vs-dependent">',
];
// Widget weight.
// We check to see if the default value is greater than the number
// of widgets just in case a widget has been removed and the form
// hasn't been saved again.
$weight = (isset($this->options['widgets'][$location_id][$widget_id]['weight'])) ? $this->options['widgets'][$location_id][$widget_id]['weight'] : 0;
if ($weight > count($widgets)) {
$weight = count($widgets);
}
$form['widgets'][$location_id][$widget_id]['weight'] = [
'#type' => 'select',
'#title' => $this->t('Weight of the @name', ['@name' => $widget_info['label']]),
'#default_value' => $weight,
'#options' => $weights,
'#description' => $this->t('Determines in what order the @name appears. A lower weight will cause the @name to be above higher weight items.', ['@name' => $widget_info['label']]),
'#prefix' => '<div class="vs-dependent">',
'#suffix' => '</div>',
'#states' => [
'visible' => [
':input[name="style_options[widgets][' . $location_id . '][' . $widget_id . '][enable]"]' => ['checked' => TRUE],
],
],
];
// Build the appropriate array for the states API.
$widget_dependency = 'style_options[widgets][' . $location_id . '][' . $widget_id . ']';
// Get the current configuration of this widget type.
$configuration = [];
if (!empty($this->options['widgets'][$location_id][$widget_id])) {
$configuration = $this->options['widgets'][$location_id][$widget_id];
}
$configuration['dependency'] = $widget_dependency;
$instance = $widgetTypeManager->createInstance($widget_id, $configuration);
// Get the configuration form of this widget type.
$form['widgets'][$location_id][$widget_id] = $instance->buildConfigurationForm($form['widgets'][$location_id][$widget_id], $form_state);
// Close the vs-dependent wrapper.
$form['widgets'][$location_id][$widget_id]['wrapper_close'] = [
'#markup' => '</div>',
];
}
}
}
}
// Browse locations and remove the header if no widget is available.
foreach ($location as $location_id => $location_name) {
// If no widget is available, the only key is "header".
if (count(array_keys($form['widgets'][$location_id])) == 1) {
unset($form['widgets'][$location_id]);
}
}
// Remove the widget section header if there is no widget available.
if (empty($form['widgets'])) {
unset($form['widgets']);
unset($form['widgets_header']);
}
$form['views_slideshow_wrapper_close'] = [
'#markup' => '</div>',
];
// Add a library to style the form.
$form['#attached']['library'] = ['views_slideshow/form'];
}
/**
* {@inheritdoc}
*/
public function validateOptionsForm(&$form, FormStateInterface $form_state) {
// Validate all slideshow type plugins values.
$typeManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_type');
foreach ($typeManager->getDefinitions() as $id => $definition) {
$type = $typeManager->createInstance($id);
$type->validateConfigurationForm($form, $form_state);
}
}
/**
* {@inheritdoc}
*/
public function submitOptionsForm(&$form, FormStateInterface $form_state) {
// Submit all slideshow type plugins values.
$typeManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_type');
foreach ($typeManager->getDefinitions() as $id => $definition) {
$type = $typeManager->createInstance($id);
$type->submitConfigurationForm($form, $form_state);
}
}
}
<?php
namespace Drupal\views_slideshow\Tests\Plugin;
use Drupal\views\Entity\View;
use Drupal\Tests\views\Functional\ViewTestBase;
use Drupal\views\Tests\ViewTestData;
/**
* Tests the slideshow style views plugin.
*
* @group views
*/
class StyleSlideshowTest extends ViewTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = [
'views',
'views_slideshow',
'views_slideshow_cycle',
'views_test_config',
'views_slideshow_test',
];
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_style_slideshow'];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp();
$this->enableViewsTestModule();
if ($import_test_views) {
ViewTestData::createTestViews(get_class($this), ['views_slideshow_test']);
}
}
/**
* Test slideshow display.
*/
public function testSlideshow() {
$this->drupalGet('test-style-slideshow');
$result = $this->cssSelect('.views_slideshow_main');
$this->assertEqual(count($result), 1, 'Slideshow displayed on page');
}
/**
* Test slideshow control widgets.
*/
public function testSlideshowWidgets() {
$this->drupalGet('test-style-slideshow');
// Ensure no controls are displayed.
$this->assertFalse(count($this->cssSelect('.views-slideshow-controls-top')));
$this->assertFalse(count($this->cssSelect('.views-slideshow-controls-bottom')));
// Test top widget position.
$view = View::load('test_style_slideshow');
$display = &$view->getDisplay('default');
$display['display_options']['style']['options']['widgets'] = [
'top' => [
'views_slideshow_controls' => [
'enable' => TRUE,
'weight' => 1,
'hide_on_single_slide' => 0,
'type' => 'views_slideshow_controls_text',
],
],
];
$view->save();
$this->drupalGet('test-style-slideshow');
$this->assertTrue(count($this->cssSelect('.views-slideshow-controls-top')));
$this->assertFalse(count($this->cssSelect('.views-slideshow-controls-bottom')));
// Test bottom widget position.
$view = View::load('test_style_slideshow');
$display = &$view->getDisplay('default');
$display['display_options']['style']['options']['widgets'] = [
'bottom' => [
'views_slideshow_controls' => [
'enable' => TRUE,
'weight' => 1,
'hide_on_single_slide' => 0,
'type' => 'views_slideshow_controls_text',
],
],
'top' => [],
];
$view->save();
$this->drupalGet('test-style-slideshow');
$this->assertFalse(count($this->cssSelect('.views-slideshow-controls-top')));
$this->assertTrue(count($this->cssSelect('.views-slideshow-controls-bottom')));
}
}
<?php
namespace Drupal\views_slideshow;
use Drupal\Component\Plugin\PluginBase;
/**
* Provides basic functionality for Views slideshow skins.
*/
abstract class ViewsSlideshowSkinBase extends PluginBase implements ViewsSlideshowSkinInterface {
/**
* {@inheritdoc}
*/
public function getLabel() {
return $this->pluginDefinition['label'];
}
/**
* {@inheritdoc}
*/
public function getClass() {
return $this->pluginDefinition['id'];
}
/**
* {@inheritdoc}
*/
public function getLibraries() {
return $this->pluginDefinition['libraries'];
}
}
<?php
namespace Drupal\views_slideshow;
/**
* Provides an interface for Views slideshow skins.
*/
interface ViewsSlideshowSkinInterface {
/**
* Returns a array of libraries to attach when the skin is used.
*
* @return array
* The libraries to be attached.
*/
public function getLibraries();
/**
* Returns a class to be added to templates.
*
* @return string
* The class name.
*/
public function getClass();
}
<?php
namespace Drupal\views_slideshow;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
/**
* Manager for Views Slideshow Skin plugins.
*/
class ViewsSlideshowSkinPluginManager extends DefaultPluginManager {
/**
* Constructs a new ViewsSlideshowSkinPluginManager.
*
* @param \Traversable $namespaces
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
parent::__construct('Plugin/ViewsSlideshowSkin', $namespaces, $module_handler, 'Drupal\views_slideshow\ViewsSlideshowSkinInterface', 'Drupal\views_slideshow\Annotation\ViewsSlideshowSkin');
$this->alterInfo('views_slideshow_skin_info');
$this->setCacheBackend($cache_backend, 'views_slideshow_skin');
}
}
<?php
namespace Drupal\views_slideshow;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* Provides basic functionality for Views slideshow types.
*/
abstract class ViewsSlideshowTypeBase extends PluginBase implements ViewsSlideshowTypeInterface {
use StringTranslationTrait;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->setConfiguration($configuration);
}
/**
* {@inheritdoc}
*/
public function getTitle() {
return $this->pluginDefinition['title'];
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [];
}
/**
* {@inheritdoc}
*/
public function getConfiguration() {
return [
'id' => $this->getPluginId(),
] + $this->configuration;
}
/**
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
$this->configuration = $configuration + $this->defaultConfiguration();
return $this;
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
return [];
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
}
}
<?php
namespace Drupal\views_slideshow;
use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Core\Plugin\PluginFormInterface;
/**
* Provides an interface for Views slideshow types.
*/
interface ViewsSlideshowTypeInterface extends PluginInspectionInterface, ConfigurableInterface, PluginFormInterface, DependentPluginInterface {}
<?php
namespace Drupal\views_slideshow;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
/**
* Manager for Views Slideshow Type plugins.
*/
class ViewsSlideshowTypePluginManager extends DefaultPluginManager {
/**
* Constructs a new ViewsSlideshowTypePluginManager.
*
* @param \Traversable $namespaces
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
parent::__construct('Plugin/ViewsSlideshowType', $namespaces, $module_handler, 'Drupal\views_slideshow\ViewsSlideshowTypeInterface', 'Drupal\views_slideshow\Annotation\ViewsSlideshowType');
$this->alterInfo('views_slideshow_type_info');
$this->setCacheBackend($cache_backend, 'views_slideshow_type');
}
}
<?php
namespace Drupal\views_slideshow;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* Provides basic functionality for Views slideshow widgets.
*/
abstract class ViewsSlideshowWidgetBase extends PluginBase implements ViewsSlideshowWidgetInterface {
use StringTranslationTrait;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->setConfiguration($configuration);
}
/**
* {@inheritdoc}
*/
public function getTitle() {
return $this->pluginDefinition['title'];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
return [];
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [];
}
/**
* {@inheritdoc}
*/
public function getConfiguration() {
return [
'id' => $this->getPluginId(),
] + $this->configuration;
}
/**
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
$this->configuration = $configuration + $this->defaultConfiguration();
return $this;
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
return [];
}
/**
* {@inheritdoc}
*/
public function checkCompatiblity($view) {
return TRUE;
}
}
<?php
namespace Drupal\views_slideshow;
use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Core\Plugin\PluginFormInterface;
/**
* Provides an interface for a Views slideshow widget.
*/
interface ViewsSlideshowWidgetInterface extends PluginInspectionInterface, ConfigurableInterface, PluginFormInterface, DependentPluginInterface {
/**
* Check if the widget is compatible with the current view configuration.
*
* @return bool
* TRUE if the widget is compatible with the view.
*/
public function checkCompatiblity($view);
}
<?php
namespace Drupal\views_slideshow;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
/**
* Manager for Views Slideshow Widget plugins.
*/
class ViewsSlideshowWidgetPluginManager extends DefaultPluginManager {
/**
* Constructs a new ViewsSlideshowWidgetPluginManager.
*
* @param \Traversable $namespaces
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
parent::__construct('Plugin/ViewsSlideshowWidget', $namespaces, $module_handler, 'Drupal\views_slideshow\ViewsSlideshowWidgetInterface', 'Drupal\views_slideshow\Annotation\ViewsSlideshowWidget');
$this->alterInfo('views_slideshow_widget_info');
$this->setCacheBackend($cache_backend, 'views_slideshow_widget');
}
/**
* Gets the definition of all or filtered plugins for this type.
*
* @param mixed $type
* A string or an array of types to filter on.
*
* @return mixed
* An array of plugin definitions. Keys are plugin IDs.
*/
public function getDefinitions($type = NULL) {
$definitions = parent::getDefinitions();
// Filter widgets to keep only required types.
if (!empty($type)) {
foreach ($definitions as $widgetId => $widgetInfo) {
if ((is_array($type) && !in_array($widgetInfo['type'], $type)) || (is_string($type) && $widgetInfo['type'] !== $type)) {
unset($definitions[$widgetId]);
}
}
}
return $definitions;
}
}
<?php
namespace Drupal\views_slideshow;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* Base class for a Views slideshow widget type.
*/
abstract class ViewsSlideshowWidgetTypeBase extends PluginBase implements ViewsSlideshowWidgetTypeInterface {
use StringTranslationTrait;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->setConfiguration($configuration);
}
/**
* {@inheritdoc}
*/
public function getTitle() {
return $this->pluginDefinition['title'];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
// Add field to see if they would like to hide controls if there is only
// one slide.
$form['hide_on_single_slide'] = [
'#type' => 'checkbox',
'#title' => $this->t('Hide controls if there is only one slide'),
'#default_value' => $this->getConfiguration()['hide_on_single_slide'],
'#description' => $this->t('Should the controls be hidden if there is only one slide.'),
'#states' => [
'visible' => [
':input[name="' . $this->getConfiguration()['dependency'] . '[enable]"]' => ['checked' => TRUE],
],
],
];
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'enable' => ['default' => 0],
'weight' => ['default' => 1],
'hide_on_single_slide' => ['default' => 0],
];
}
/**
* {@inheritdoc}
*/
public function getConfiguration() {
return [
'id' => $this->getPluginId(),
] + $this->configuration;
}
/**
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
$this->configuration = $configuration + $this->defaultConfiguration();
return $this;
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
return [];
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function checkCompatiblity($slideshow) {
$is_compatible = 1;
// Check if every required accept value in the widget has a
// corresponding calls value in the slideshow.
foreach ($this->pluginDefinition['accepts'] as $accept_key => $accept_value) {
if (is_array($accept_value) && !empty($accept_value['required']) && !in_array($accept_key, $slideshow['calls'])) {
$is_compatible = 0;
break;
}
}
// No need to go through this if it's not compatible.
if ($is_compatible) {
// Check if every required calls value in the widget has a
// corresponding accepts call.
foreach ($this->pluginDefinition['calls'] as $calls_key => $calls_value) {
if (is_array($calls_value) && !empty($calls_value['required']) && !in_array($calls_key, $slideshow['accepts'])) {
$is_compatible = 0;
break;
}
}
}
return $is_compatible;
}
}
<?php
namespace Drupal\views_slideshow;
use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Core\Plugin\PluginFormInterface;
/**
* Provides an interface for a Views slideshow widget type.
*/
interface ViewsSlideshowWidgetTypeInterface extends PluginInspectionInterface, ConfigurableInterface, PluginFormInterface, DependentPluginInterface {
/**
* Check if the widget type is compatible with the selected slideshow.
*
* @return bool
* TRUE if the widget type is compatible with the slideshow.
*/
public function checkCompatiblity($slideshow);
}
<?php
namespace Drupal\views_slideshow;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
/**
* Manager for Views Slideshow widget type plugins.
*/
class ViewsSlideshowWidgetTypePluginManager extends DefaultPluginManager {
/**
* Constructs a new ViewsSlideshowWidgetTypePluginManager.
*
* @param \Traversable $namespaces
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
parent::__construct('Plugin/ViewsSlideshowWidgetType', $namespaces, $module_handler, 'Drupal\views_slideshow\ViewsSlideshowWidgetTypeInterface', 'Drupal\views_slideshow\Annotation\ViewsSlideshowWidgetType');
$this->alterInfo('views_slideshow_widget_type_info');
$this->setCacheBackend($cache_backend, 'views_slideshow_widget_type');
}
}
{#
/**
* @file
* Default theme implementation for a views slideshow text next control.
*
* Available variables:
* - classes: Classes to apply to the control.
* - vss_id: The slideshow's id.
*
* @see template_preprocess_views_slideshow_controls_text_next()
*
* @ingroup vss_templates
*/
#}
<span id="views_slideshow_controls_text_next_{{ vss_id }}" {{ attributes.addClass(classes) }}>
<a href="#">{{ 'Next'|t }}</a>
</span>
{#
/**
* @file
* Default theme implementation for a views slideshow text pause control.
*
* Available variables:
* - classes: Classes to apply to the control.
* - start_text: Text to display while playing.
* - vss_id: The slideshow's id.
*
* @see template_preprocess_views_slideshow_controls_text_pause()
*
* @ingroup vss_templates
*/
#}
<span id="views_slideshow_controls_text_pause_{{ vss_id }}" {{ attributes.addClass(classes) }}>
<a href="#">{{ start_text }}</a>
</span>
{#
/**
* @file
* Default theme implementation for a views slideshow text previous control.
*
* Available variables:
* - classes: Classes to apply to the control.
* - vss_id: The slideshow's id.
*
* @see template_preprocess_views_slideshow_controls_text_previous()
*
* @ingroup vss_templates
*/
#}
<span id="views_slideshow_controls_text_previous_{{ vss_id }}" {{ attributes.addClass(classes) }}>
<a href="#">{{ 'Previous'|t }}</a>
</span>
{#
/**
* @file
* Default theme implementation for a views slideshow text controls.
*
* Available variables:
* - classes: Classes to apply to the control.
* - rendered_control_next: Text next control.
* - rendered_control_pause: Text pause control.
* - rendered_control_previous: Text previous control.
* - vss_id: The slideshow's id.
*
* @see template_preprocess_views_slideshow_controls_text()
*
* @ingroup vss_templates
*/
#}
<div id="views_slideshow_controls_text_{{ vss_id }}" {{ attributes.addClass(classes) }}>
{{ rendered_control_previous }}
{{ rendered_control_pause }}
{{ rendered_control_next }}
</div>
{#
/**
* @file
* Default theme implementation for a views slideshow controls.
*
* Available variables:
* - widget: The rendered widget.
*
* @see template_preprocess_views_slideshow_controls_widget()
*
* @ingroup vss_templates
*/
#}
{{ widget }}
{#
/**
* @file
* Default theme implementation for a views slideshow pager item.
*
* Available variables:
* - plugin: The main frame slideshow plugin.
* - slides: The slides.
* - vss_id: The slideshow's id.
*
* @ingroup vss_templates
*/
#}
<div id="{{ plugin }}_main_{{ vss_id }}" class="{{ plugin }}_main views_slideshow_main">
{{ slides }}
</div>
{#
/**
* @file
* Default theme implementation for a views slideshow bullets pager.
*
* Available variables:
* - bullet_items: Renderable array of pager items
*
* @ingroup vss_templates
*/
#}
{{ bullet_items }}
{#
/**
* @file
* Default theme implementation for a views slideshow pager field field data.
*
* Available variables:
* - css_identifier: css identified for the field..
* - label: Label for the field.
* - output: The field data.
*
* @see template_preprocess_views_slideshow_pager_field_field()
*
* @ingroup vss_templates
*/
#}
<div class="views-field-{{ css_identifier }}">
{% if label %}
<label class="view-label-{{ css_identifier }}">
{{ label }}:
</label>
{% endif %}
<div class="views-content-{{ css_identifier }}">
{{ output }}
</div>
</div>
{#
/**
* @file
* Default theme implementation for a views slideshow pager item.
*
* Available variables:
* - classes: Classes to apply to the element.
* - count: The page number.
* - location: Location of pager.
* - item: Rendered field(s) making up item.
* - vss_id: The slideshow's id.
*
* @see template_preprocess_views_slideshow_pager_field_item()
*
* @ingroup vss_templates
*/
#}
<div id="views_slideshow_pager_field_item_{{ location }}_{{ vss_id }}_{{ count }}" {{ attributes.addClass(classes) }}>
{{ item }}
</div>
{#
/**
* @file
* Default theme implementation for a views slideshow pager item.
*
* Available variables:
* - classes: Classes to apply to the element.
* - rendered_field_items: The individual pager elements.
* - widget_id: The pager id.
*
* @see template_preprocess_views_slideshow_pager_field_item()
*
* @ingroup vss_templates
*/
#}
<div id="{{ widget_id }}" {{ attributes.addClass(classes) }}>
{{ rendered_field_items }}
</div>
{#
/**
* @file
* Default theme implementation for a views slideshow pager.
*
* Available variables:
* - widget: The rendered widget.
*
* @see template_preprocess_views_slideshow_pager_widget()
*
* @ingroup vss_templates
*/
#}
{{ widget }}
{#
/**
* @file
* Default theme implementation for a views slideshow counter.
*
* Available variables:
* - widget: The rendered widget.
*
* @see template_preprocess_views_slideshow_slide_counter_widget()
*
* @ingroup vss_templates
*/
#}
{{ widget }}
{#
/**
* @file
* Default theme implementation for a views slideshow slide counter.
*
* Available variables:
* - classes: Classes to apply to the counter's div element.
* - slide_count: Total number of slides.
* - vss_id: The slideshow's id.
*
* @see template_preprocess_views_slideshow_slide_counter()
*
* @ingroup vss_templates
*/
#}
<div id="views_slideshow_slide_counter_{{ vss_id }}" {{ attributes.addClass(classes) }}>
<span class="num">1</span> {{ 'of'|t }} <span class="total">{{ slide_count }}</span>
</div>
{#
/**
* @file
* Default theme implementation for a views slideshow.
*
* Available variables:
* - bottom_widget_rendered: Widget under the slideshow with controls/data.
* - skin: The skin being applied to the slideshow.
* - slideshow: The slideshow.
* - top_widget_rendered: Widget above the slideshow with controls/data.
*
* @see _views_slideshow_preprocess_views_view_slideshow()
*
* @ingroup vss_templates
*/
#}
{% if slideshow %}
<div class="skin-{{ skin }}">
{% if top_widget_rendered %}
<div class="views-slideshow-controls-top clearfix">
{{ top_widget_rendered }}
</div>
{% endif %}
{{ slideshow }}
{% if bottom_widget_rendered %}
<div class="views-slideshow-controls-bottom clearfix">
{{ bottom_widget_rendered }}
</div>
{% endif %}
</div>
{% endif %}
langcode: en
status: true
dependencies:
module:
- views_slideshow
- views_slideshow_cycle
id: test_style_slideshow
label: ''
module: views
description: ''
tag: ''
base_table: views_test_data
base_field: id
core: 8.x
display:
default:
display_plugin: page
id: default
display_title: Master
position: null
display_options:
path: test-style-slideshow
access:
type: none
options: { }
cache:
type: tag
options: { }
query:
type: views_query
options: { }
exposed_form:
type: basic
options: { }
pager:
type: full
options: { }
style:
type: slideshow
options:
row_class: ''
default_row_class: true
slideshow_skin: default
slideshow_type: views_slideshow_cycle
row:
type: fields
options: { }
fields:
name:
id: name
table: views_test_data
field: name
name: 'Views Slideshow Test Config'
type: module
description: 'Provides default views for tests.'
package: Testing
core: 8.x
core_version_requirement: ^8 || ^9
dependencies:
- drupal:views
- views_slideshow:views_slideshow
- views_slideshow:views_slideshow_cycle
# Information added by Drupal.org packaging script on 2020-09-28
version: '8.x-4.8'
project: 'views_slideshow'
datestamp: 1601309227
<?php
/**
* @file
* Provides API homepage for Views Slideshow.
*/
/**
* Views slide show.
*
* @mainpage Views Slideshow API & Developer Documentation
* Welcome to the Views Slideshow developer's documentation.
*
* Newcomers to Drupal development should read the conceptual information
* in @link https://www.drupal.org/docs/8/api/ Drupal API Introduction @endlink
* or @link https://api.drupal.org/api/drupal/8.2.x Drupal API Docs @endlink.
* The heavily documented
* @link https://api.drupal.org/api/examples/8.x-1.x Example modules @endlink
* may also be helpful.
*
* For tutorials and examples for acheiving specific tasks, also see the
* @link https://drupal.org/docs/8/modules/views-slideshow/developer-tutorials Developer Guide @endlink.
*
* For any comments, support or questions see the
* @link https://drupal.org/project/views_slideshow module page @endlink.
* Also, feel free to comment here if it is specific to one function/file.
*
* - Primary components of Views Slideshow
* - @link vss_theme Theme Functions @endlink
* - @link vss_templates Templates @endlink
* - @link modules/views_slideshow_cycle/views_slideshow_cycle.module Cycle Module @endlink
*/
name: 'Views Slideshow'
type: module
description: 'Provides a View style that displays rows as a jQuery slideshow. This is an API and requires Views Slideshow Cycle or another module that supports the API.'
package: Views
core: 8.x
core_version_requirement: ^8 || ^9
dependencies:
- drupal:views
# Information added by Drupal.org packaging script on 2020-09-28
version: '8.x-4.8'
project: 'views_slideshow'
datestamp: 1601309227
form:
version: VERSION
css:
theme:
css/views_slideshow.css: {}
widget_info:
version: VERSION
js:
js/views_slideshow.js: {}
dependencies:
- core/jquery
- core/drupal
- core/drupalSettings
controls_text:
version: VERSION
css:
theme:
css/controls_text.css: {}
pager_bullets:
version: VERSION
css:
component:
css/views-slideshow-pager-bullets.css: {}
jquery_hoverIntent:
remote: https://github.com/briancherne/jquery-hoverIntent
version: 1.9
license:
name: MIT
gpl-compatible: true
js:
/libraries/jquery.hoverIntent/jquery.hoverIntent.js: {}
dependencies:
- core/jquery
<?php
/**
* @file
* Provides Slideshow style options for Views.
*/
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function views_slideshow_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the gss module.
case 'help.page.views_slideshow':
$output = '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Views Slideshow can be used to create a slideshow of any content (not just images) that can appear in a View. Powered by jQuery, it is heavily customizable: you may choose slideshow settings for each View you create.') . '</p>';
$output .= '<h3>' . t('More Information') . '</h3>';
$output .= '<p>' . t('For more information about this module visit the <a href="@link">Views Slideshow</a> module page.', ['@link' => 'https://www.drupal.org/project/views_slideshow']) . '</p>';
return $output;
}
}
/**
* Implements hook_theme().
*/
function views_slideshow_theme() {
return [
'views_slideshow_main_section' => [
'variables' => [
'vss_id' => NULL,
'slides' => NULL,
'plugin' => NULL,
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_pager_widget' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => [],
'location' => NULL,
'rows' => [],
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_pager_fields' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => [],
'location' => NULL,
'attributes' => [],
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_pager_field_field' => [
'variables' => [
'view' => NULL,
'css_identifier' => NULL,
'label' => NULL,
'output' => NULL,
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_pager_field_item' => [
'variables' => [
'vss_id' => NULL,
'item' => NULL,
'count' => NULL,
'location' => NULL,
'length' => NULL,
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_pager_bullets' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => [],
'location' => NULL,
'attributes' => [],
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_controls_widget' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => [],
'location' => NULL,
'rows' => [],
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_controls_text' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => [],
'location' => NULL,
'rows' => [],
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_controls_text_previous' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => [],
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_controls_text_pause' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => [],
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_controls_text_next' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => [],
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_slide_counter_widget' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => [],
'location' => NULL,
'rows' => [],
],
'file' => 'views_slideshow.theme.inc',
],
'views_slideshow_slide_counter' => [
'variables' => [
'vss_id' => NULL,
'view' => NULL,
'settings' => [],
'location' => NULL,
'rows' => [],
],
'file' => 'views_slideshow.theme.inc',
],
];
}
/**
* Views Slideshow: Slideshow.
*
* As it is a preprocess function, store it with other functions in theme.inc.
*/
function template_preprocess_views_view_slideshow(&$vars) {
\Drupal::moduleHandler()->loadInclude('views_slideshow', 'inc', 'views_slideshow.theme');
_views_slideshow_preprocess_views_view_slideshow($vars);
}
services:
plugin.manager.views_slideshow.slideshow_skin:
class: Drupal\views_slideshow\ViewsSlideshowSkinPluginManager
parent: default_plugin_manager
plugin.manager.views_slideshow.slideshow_type:
class: Drupal\views_slideshow\ViewsSlideshowTypePluginManager
parent: default_plugin_manager
plugin.manager.views_slideshow.widget_type:
class: Drupal\views_slideshow\ViewsSlideshowWidgetTypePluginManager
parent: default_plugin_manager
plugin.manager.views_slideshow.widget:
class: Drupal\views_slideshow\ViewsSlideshowWidgetPluginManager
parent: default_plugin_manager
views_slideshow.format_addons_name:
class: Drupal\views_slideshow\FormatAddonsName
<?php
/**
* @file
* The theme system, which controls the output of views slideshow.
*/
/**
* @defgroup vss_templates Templates
* @{
* Slideshow and component templates.
*
* @see vss_theme
* @}
*/
/**
* @defgroup vss_theme Theme Functions
* @{
* Theme processing and display generation.
*
* Most of the logic behind the generation of the slideshow is here.
*
* @see vss_templates
*/
use Drupal\Component\Utility\Html;
/**
* Views Slideshow: slideshow.
*/
function _views_slideshow_preprocess_views_view_slideshow(&$vars) {
$options = $vars['view']->style_plugin->options;
$vars['skin'] = 'default';
$vars['slideshow'] = '';
$main_frame_module = $options['slideshow_type'];
if (empty($main_frame_module)) {
// Get all slideshow types.
$typeManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_type');
$types = $typeManager->getDefinitions();
if ($types) {
foreach ($types as $id => $definition) {
$main_frame_module = $id;
break;
}
}
}
// Make sure the main slideshow settings are defined before building the
// slideshow.
if (empty($main_frame_module)) {
\Drupal::messenger()->addMessage(
t('No main frame module is enabled for views slideshow. This is often because another module which Views Slideshow needs is not enabled. For example, 4.x needs a module like "Views Slideshow: Cycle" enabled.'),
'error'
);
}
elseif (empty($options[$main_frame_module])) {
\Drupal::messenger()->addMessage(t('The options for @module does not exists.', ['@module' => $main_frame_module]), 'error');
}
elseif (!empty($vars['rows'])) {
$settings = $options[$main_frame_module];
$view = $vars['view'];
$rows = $vars['rows'];
// The #name element is not available on Views edit pages.
$view_element_name = (isset($view->element['#name'])) ? $view->element['#name'] : '';
$vss_id = $view_element_name . '-' . $view->current_display;
// Give each slideshow a unique id if there are more than one on the page.
static $instances = [];
if (isset($instances[$vss_id])) {
$instances[$vss_id]++;
$vss_id .= "_" . $instances[$vss_id];
}
else {
$instances[$vss_id] = 1;
}
// Building our default methods.
$methods = [
'goToSlide' => [],
'nextSlide' => [],
'pause' => [],
'play' => [],
'previousSlide' => [],
'transitionBegin' => [],
'transitionEnd' => [],
];
// Pull all widget info and slideshow info and merge them together.
$widgetTypeManager = \Drupal::service('plugin.manager.views_slideshow.widget_type');
$widgetTypes = $widgetTypeManager->getDefinitions();
$slideshowTypeManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_type');
$slideshowTypes = $slideshowTypeManager->getDefinitions();
$addons = array_merge($widgetTypes, $slideshowTypes);
// Loop through all the addons and call their methods if needed.
foreach ($addons as $addon_id => $addon_info) {
foreach ($addon_info['accepts'] as $imp_key => $imp_value) {
if (is_array($imp_value)) {
$methods[$imp_key][] = \Drupal::service('views_slideshow.format_addons_name')->format($addon_id);
}
else {
$methods[$imp_value][] = \Drupal::service('views_slideshow.format_addons_name')->format($addon_id);
}
}
}
$vars['#attached']['library'][] = 'views_slideshow/widget_info';
$vars['#attached']['drupalSettings']['viewsSlideshow'][$vss_id] = [
'methods' => $methods,
'paused' => 0,
];
// Process Skins.
$skinManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_skin');
$skin = $skinManager->createInstance($options['slideshow_skin']);
$vars['skin'] = $skin->getClass();
foreach ($skin->getLibraries() as $library) {
$vars['#attached']['library'][] = $library;
}
// Process Widgets.
// Build weights.
$weight = [];
for ($i = 1; $i <= count($widgetTypes); $i++) {
$weight['top'][$i] = [];
$weight['bottom'][$i] = [];
}
$slide_count = count($view->result);
if ($slide_count && $vars['view']->style_plugin->options['slideshow_type'] == 'views_slideshow_cycle') {
$items_per_slide = $vars['view']->style_plugin->options['views_slideshow_cycle']['items_per_slide'];
$slide_count = $slide_count / $items_per_slide;
}
foreach ($widgetTypes as $widgetTypeId => $widgetTypeName) {
foreach ($weight as $location => $order) {
if ($options['widgets'][$location][$widgetTypeId]['enable']) {
// If hide on single slide and only a single slide skip rendering.
if ($options['widgets'][$location][$widgetTypeId]['hide_on_single_slide'] && $slide_count <= 1) {
continue;
}
$widgetWeight = ($options['widgets'][$location][$widgetTypeId]['weight'] > count($widgetTypes)) ? count($widgetTypes) : $options['widgets'][$location][$widgetTypeId]['weight'];
$weight[$location][$widgetWeight][] = [
'widgetId' => $widgetTypeId,
'widgetSettings' => $options['widgets'][$location][$widgetTypeId],
];
}
}
}
// Build our widgets.
foreach ($weight as $location => $order) {
$vars[$location . '_widget_rendered'] = [];
foreach ($order as $widgets) {
if (is_array($widgets)) {
foreach ($widgets as $widgetData) {
$vars[$location . '_widget_rendered'][] = [
'#theme' => $view->buildThemeFunctions($widgetData['widgetId'] . '_widget'),
'#vss_id' => $vss_id,
'#view' => $view,
'#settings' => $widgetData['widgetSettings'],
'#location' => $location,
'#rows' => $rows,
];
}
}
}
}
// Process Slideshow.
$slides = [
'#theme' => $view->buildThemeFunctions($main_frame_module . '_main_frame'),
'#vss_id' => $vss_id,
'#view' => $view,
'#settings' => $settings,
'#rows' => $rows,
];
$vars['slideshow'] = [
'#theme' => $view->buildThemeFunctions('views_slideshow_main_section'),
'#vss_id' => $vss_id,
'#slides' => $slides,
'#plugin' => $main_frame_module,
];
}
}
/**
* Views Slideshow: pager.
*/
function template_preprocess_views_slideshow_pager_widget(&$vars) {
// Add JavaScript settings for the pager type.
$vars['#attached']['library'][] = 'views_slideshow/widget_info';
$vars['#attached']['drupalSettings']['viewsSlideshowPager'][$vars['vss_id']] = [
$vars['location'] => [
'type' => \Drupal::service('views_slideshow.format_addons_name')->format($vars['settings']['type']),
],
];
// Create some attributes.
$attributes['class'][] = 'widget_pager widget_pager_' . $vars['location'];
$attributes['id'] = 'widget_pager_' . $vars['location'] . '_' . $vars['vss_id'];
$vars['widget'] = [
'#theme' => $vars['view']->buildThemeFunctions($vars['settings']['type']),
'#vss_id' => $vars['vss_id'],
'#view' => $vars['view'],
'#settings' => $vars['settings'],
'#location' => $vars['location'],
'#attributes' => $attributes,
];
}
/**
* Theme pager fields.
*/
function template_preprocess_views_slideshow_pager_fields(&$vars) {
// Add JavaScript settings for the field.
$vars['#attached']['library'][] = 'views_slideshow/widget_info';
$vars['#attached']['drupalSettings']['viewsSlideshowPagerFields'][$vars['vss_id']] = [
$vars['location'] => [
'activatePauseOnHover' => $vars['settings']['views_slideshow_pager_fields']['views_slideshow_pager_fields_hover'],
],
];
// Add hover intent library.
if ($vars['settings']['views_slideshow_pager_fields']['views_slideshow_pager_fields_hover']) {
$vars['#attached']['library'][] = 'views_slideshow/jquery_hoverIntent';
}
$vars['widget_id'] = $vars['attributes']['id'];
// Add our class to the wrapper.
$vars['attributes']['class'][] = 'views_slideshow_pager_field';
// Render all the fields unless there is only 1 slide and the user specified
// to hide them when there is only one slide.
$vars['rendered_field_items'] = [];
foreach ($vars['view']->result as $count => $node) {
$rendered_fields = [];
foreach ($vars['settings']['views_slideshow_pager_fields']['views_slideshow_pager_fields_fields'] as $field => $use) {
if ($use !== 0 && is_object($vars['view']->field[$field])) {
$rendered_fields[] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_pager_field_field'),
'#view' => $vars['view'],
'#label' => $vars['view']->field[$field]->options['label'],
'#output' => $vars['view']->style_plugin->getField($count, $field),
'#css_identifier' => Html::cleanCssIdentifier($vars['view']->field[$field]->field),
];
}
}
$vars['rendered_field_items'][] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_pager_field_item'),
'#vss_id' => $vars['vss_id'],
'#item' => $rendered_fields,
'#count' => $count,
'#location' => $vars['location'],
'#length' => count($vars['view']->result),
];
}
}
/**
* Views Slideshow: pager item.
*/
function template_preprocess_views_slideshow_pager_field_item(&$vars) {
$vars['attributes']['class'][] = 'views_slideshow_pager_field_item';
$vars['attributes']['class'][] = ($vars['count'] % 2) ? 'views-row-even' : 'views-row-odd';
if ($vars['count'] == 0) {
$vars['attributes']['class'][] = 'views-row-first';
}
elseif ($vars['count'] == $vars['length'] - 1) {
$vars['attributes']['class'][] = 'views-row-last';
}
}
/**
* Views Slideshow: Bullets pager.
*/
function template_preprocess_views_slideshow_pager_bullets(&$vars) {
$vars['#attached']['library'][] = 'views_slideshow/widget_info';
$vars['#attached']['library'][] = 'views_slideshow/pager_bullets';
$vars['#attached']['drupalSettings']['viewsSlideshowPagerFields'][$vars['vss_id']] = [
$vars['location'] => [
'activatePauseOnHover' => $vars['settings']['views_slideshow_pager_bullets']['views_slideshow_pager_bullets_hover'] ?? '',
],
];
$vars['bullet_items'] = [
'#theme' => 'item_list',
'#items' => [],
'#attributes' => $vars['attributes'],
];
$vars['bullet_items']['#attributes']['class'][] = 'views-slideshow-pager-bullets';
$vars['bullet_items']['#attributes']['class'][] = 'views_slideshow_pager_field';
for ($i = 0; $i < count($vars['view']->result); $i++) {
$vars['bullet_items']['#items'][] = [
'#markup' => $i,
'#wrapper_attributes' => [
'id' => 'views_slideshow_pager_field_item_' . $vars['location'] . '_' . $vars['vss_id'] . '_' . $i,
],
];
}
}
/**
* Views Slideshow: Controls.
*/
function template_preprocess_views_slideshow_controls_widget(&$vars) {
// Add JavaScript settings for the controls type.
$vars['#attached']['library'][] = 'views_slideshow/widget_info';
$vars['#attached']['drupalSettings']['viewsSlideshowControls'][$vars['vss_id']] = [
$vars['location'] => [
'type' => \Drupal::service('views_slideshow.format_addons_name')->format($vars['settings']['type']),
],
];
$vars['widget'] = [
'#theme' => $vars['view']->buildThemeFunctions($vars['settings']['type']),
'#vss_id' => $vars['vss_id'],
'#view' => $vars['view'],
'#settings' => $vars['settings'],
'#location' => $vars['location'],
'#rows' => $vars['rows'],
];
}
/**
* The slideshow controls.
*/
function template_preprocess_views_slideshow_controls_text(&$vars) {
$vars['#attached']['library'][] = 'views_slideshow/controls_text';
$vars['attributes']['class'][] = 'views_slideshow_controls_text';
$vars['rendered_control_previous'] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_controls_text_previous'),
'#vss_id' => $vars['vss_id'],
'#view' => $vars['view'],
'#settings' => $vars['settings'],
];
$vars['rendered_control_pause'] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_controls_text_pause'),
'#vss_id' => $vars['vss_id'],
'#view' => $vars['view'],
'#settings' => $vars['settings'],
];
$vars['rendered_control_next'] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_controls_text_next'),
'#vss_id' => $vars['vss_id'],
'#view' => $vars['view'],
'#settings' => $vars['settings'],
];
}
/**
* Views Slideshow: "previous" control.
*/
function template_preprocess_views_slideshow_controls_text_previous(&$vars) {
$vars['attributes']['class'][] = 'views_slideshow_controls_text_previous';
}
/**
* Views Slideshow: "pause" control.
*/
function template_preprocess_views_slideshow_controls_text_pause(&$vars) {
$vars['attributes']['class'][] = 'views_slideshow_controls_text_pause views-slideshow-controls-text-status-play';
$vars['start_text'] = t('Pause');
}
/**
* Views Slideshow: "next" control.
*/
function template_preprocess_views_slideshow_controls_text_next(&$vars) {
$vars['attributes']['class'][] = 'views_slideshow_controls_text_next';
}
/**
* Views Slideshow: Slide Counter.
*/
function template_preprocess_views_slideshow_slide_counter_widget(&$vars) {
$vars['widget'] = [
'#theme' => $vars['view']->buildThemeFunctions('views_slideshow_slide_counter'),
'#vss_id' => $vars['vss_id'],
'#view' => $vars['view'],
'#settings' => $vars['settings'],
'#location' => $vars['location'],
'#rows' => $vars['rows'],
];
}
/**
* Views Slideshow: slide counter.
*/
function template_preprocess_views_slideshow_slide_counter(&$vars) {
$vars['attributes']['class'][] = 'views_slideshow_slide_counter';
$vars['slide_count'] = count($vars['rows']);
}
/**
* @} End of "defgroup vss_theme".
*/
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment