mirror of
https://github.com/a2nt/silverstripe-webpack.git
synced 2024-10-22 17:05:31 +02:00
IMPROVEMENT: Video slides
This commit is contained in:
parent
e6972464de
commit
b34f9c58cc
@ -1,15 +1,10 @@
|
||||
---
|
||||
Name: webapp
|
||||
---
|
||||
|
||||
SilverStripe\Core\Manifest\ModuleManifest:
|
||||
project: app
|
||||
|
||||
SilverStripe\View\SSViewer:
|
||||
source_file_comments: true
|
||||
themes:
|
||||
- '$public'
|
||||
- '$default'
|
||||
|
||||
Page:
|
||||
default_container_class: 'container'
|
||||
|
||||
|
@ -11,15 +11,21 @@ SilverStripe\Blog\Model\BlogPost:
|
||||
extensions:
|
||||
- Site\Extensions\BlogPostExtension
|
||||
|
||||
Sheadawson\Linkable\Models\EmbeddedObject:
|
||||
extensions:
|
||||
- Site\Extensions\EmbeddedObjectExtension
|
||||
|
||||
Dynamic\FlexSlider\Model\SlideImage:
|
||||
extensions:
|
||||
- Site\Extensions\SlideImageExtension
|
||||
- Site\Extensions\SlideImageExtension
|
||||
|
||||
SilverStripe\Core\Injector\Injector:
|
||||
SilverStripe\UserForms\Model\UserDefinedForm:
|
||||
class: Site\Extensions\CMSMain_HiddenClass
|
||||
SilverStripe\Security\MemberAuthenticator\LostPasswordHandler:
|
||||
class: Site\Extensions\LostPasswordHandlerExtension
|
||||
Sheadawson\Linkable\Forms\EmbeddedObjectField:
|
||||
class: Site\Extensions\EmbedObjectField
|
||||
|
||||
# User Forms
|
||||
SilverStripe\UserForms\Form\UserForm:
|
||||
|
9
app/_config/themes.yml
Normal file
9
app/_config/themes.yml
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
Name: webapp-themes
|
||||
---
|
||||
|
||||
SilverStripe\View\SSViewer:
|
||||
source_file_comments: true
|
||||
themes:
|
||||
- '$public'
|
||||
- '$default'
|
@ -53,6 +53,37 @@ const CarouselUI = (($) => {
|
||||
// init carousel
|
||||
$e.carousel();
|
||||
|
||||
const $youtubeSlides = $e.find('iframe[src^="https://www.youtube.com/embed/"]');
|
||||
|
||||
$e.on('slide.bs.carousel', () => {
|
||||
if ($youtubeSlides.length) {
|
||||
$youtubeSlides.each((i, e) => {
|
||||
const $e = $(e);
|
||||
try {
|
||||
$e.data('player', new YT.Player(e, {
|
||||
events: {
|
||||
'onReady': () => {
|
||||
$e.data('player').pauseVideo();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
$e.data('player').pauseVideo();
|
||||
} catch (e) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$e.find('.carousel-control-prev').on('click', (e) => {
|
||||
e.preventDefault();
|
||||
$e.carousel('prev');
|
||||
});
|
||||
|
||||
$e.find('.carousel-control-next').on('click', (e) => {
|
||||
e.preventDefault();
|
||||
$e.carousel('next');
|
||||
});
|
||||
|
||||
// init touch swipes
|
||||
$e.hammer().bind('swipeleft', (event) => {
|
||||
$(event.target).carousel('next');
|
||||
@ -70,7 +101,7 @@ const CarouselUI = (($) => {
|
||||
$(event.target).carousel('prev');
|
||||
});
|
||||
|
||||
$e.hammer().bind('tap', (event) => {
|
||||
$e.find('.carousel-item').hammer().bind('tap', (event) => {
|
||||
$(event.target).carousel('next');
|
||||
});
|
||||
});
|
||||
|
@ -82,7 +82,7 @@ const FormValidateField = (($) => {
|
||||
|
||||
isHtml(str) {
|
||||
const doc = new DOMParser().parseFromString(str, "text/html");
|
||||
return Array.from(doc.body.childNodes).some(node => node.nodeType === 1);
|
||||
return Array.from(doc.body.childNodes).some((node) => node.nodeType === 1);
|
||||
}
|
||||
|
||||
valideURL(str) {
|
||||
|
@ -246,6 +246,11 @@ const MainUI = (($) => {
|
||||
if (W.URLDetails['hash'].indexOf('printpage') > -1) {
|
||||
W.print();
|
||||
}
|
||||
|
||||
// load youtube API
|
||||
if ($('iframe[src^="https://www.youtube.com/embed/"]').length) {
|
||||
$Body.append('<script src="https://www.youtube.com/iframe_api"></script>');
|
||||
}
|
||||
}
|
||||
|
||||
static updateLocation(url) {
|
||||
|
@ -2,12 +2,32 @@
|
||||
* Bootstrap carousel improvement
|
||||
*/
|
||||
|
||||
.carousel-item {
|
||||
/*.carousel-item {
|
||||
&.active {
|
||||
display: flex !important;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}*/
|
||||
|
||||
.carousel-slide {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
|
||||
.video {
|
||||
width: 100%;
|
||||
|
||||
iframe {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
.img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.carousel-control-prev,
|
||||
|
@ -204,3 +204,35 @@ button, input, optgroup, select, textarea,
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// dark dropdowns
|
||||
.dropdown-menu.bg-dark {
|
||||
border-color: $dark;
|
||||
|
||||
.nav-link {
|
||||
color: $navbar-dark-color;
|
||||
|
||||
@include hover-focus {
|
||||
color: $navbar-dark-hover-color;
|
||||
}
|
||||
|
||||
|
||||
&.disabled {
|
||||
color: $navbar-dark-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
.show > .nav-link,
|
||||
.active > .nav-link,
|
||||
.nav-link.show,
|
||||
.nav-link.active {
|
||||
color: $navbar-dark-active-color;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
@include hover-focus {
|
||||
color: $navbar-dark-brand-hover-color;
|
||||
background: $dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,12 @@ $bg-alt: $yellow;
|
||||
$body-color: $gray-900;
|
||||
$navbar-light-active-color: $blue;
|
||||
|
||||
$navbar-dark-hover-background: $dark;
|
||||
$navbar-dark-active-background: $dark;
|
||||
|
||||
$dropdown-border-color: $white;
|
||||
|
||||
$footer-size: 16rem;
|
||||
$footer-size: 18.5rem;
|
||||
$footer-bar-size: 2.5rem;
|
||||
|
||||
/*
|
||||
|
@ -21,3 +21,6 @@ en:
|
||||
EMPTY: "Please prove you are human - check the Captcha box."
|
||||
NOSCRIPT: "You must enable JavaScript to submit this form"
|
||||
VALIDATE_ERROR: "Captcha could not be validated"
|
||||
Dynamic\FlexSlider\Model\SlideImage:
|
||||
SINGULARNAME: 'Slide'
|
||||
PLURALNAME: 'Slides'
|
||||
|
@ -14,6 +14,7 @@ use Dynamic\FlexSlider\ORM\FlexSlider;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Forms\CheckboxField;
|
||||
use SilverStripe\Forms\LiteralField;
|
||||
use SilverStripe\Forms\NumericField;
|
||||
use SilverStripe\Forms\ReadonlyField;
|
||||
use Symbiote\GridFieldExtensions\GridFieldEditableColumns;
|
||||
|
||||
@ -27,6 +28,10 @@ class SliderElement extends ElementSlideshow
|
||||
|
||||
private static $table_name = 'SliderElement';
|
||||
|
||||
private static $db = [
|
||||
'Interval' => 'Int',
|
||||
];
|
||||
|
||||
private static $extensions = [
|
||||
FlexSlider::class,
|
||||
];
|
||||
@ -60,6 +65,10 @@ class SliderElement extends ElementSlideshow
|
||||
'CarouselThumbnailCt',
|
||||
]);
|
||||
|
||||
$fields->addFieldsToTab('Root.Settings', [
|
||||
NumericField::create('Interval', 'Auto-play Interval'),
|
||||
]);
|
||||
|
||||
$grid = $fields->dataFieldByName('Slides');
|
||||
if ($grid) {
|
||||
$config = $grid->getConfig();
|
||||
@ -99,4 +108,13 @@ class SliderElement extends ElementSlideshow
|
||||
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
parent::onBeforeWrite();
|
||||
|
||||
if(!$this->getField('Interval')){
|
||||
$this->setField('Interval', 5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ class ElementRows extends DataExtension
|
||||
{
|
||||
return $this->owner->getField('ExtraClass')
|
||||
.(
|
||||
$this->isColumn()
|
||||
$this->isColumn()
|
||||
? ' '.Config::inst()->get(self::class, 'column_class').$this->owner->getField('Size')
|
||||
: ''
|
||||
);
|
||||
|
42
app/src/Extensions/EmbedObjectField.php
Normal file
42
app/src/Extensions/EmbedObjectField.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Site\Extensions;
|
||||
|
||||
|
||||
use Sheadawson\Linkable\Forms\EmbeddedObjectField;
|
||||
use SilverStripe\Forms\CheckboxField;
|
||||
use SilverStripe\Forms\CompositeField;
|
||||
use SilverStripe\Forms\LiteralField;
|
||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||
|
||||
class EmbedObjectField extends EmbeddedObjectField
|
||||
{
|
||||
/**
|
||||
* @param array $properties
|
||||
* @return mixed|DBHTMLText
|
||||
*/
|
||||
public function FieldHolder($properties = [])
|
||||
{
|
||||
$name = $this->getName();
|
||||
|
||||
$fields = [
|
||||
CheckboxField::create(
|
||||
$name . '[autoplay]',
|
||||
_t(self::CLASS.'AUTOPLAY', 'Autoplay video?')
|
||||
)->setValue($this->object->Autoplay),
|
||||
|
||||
CheckboxField::create(
|
||||
$name . '[loop]',
|
||||
_t(self::CLASS.'LOOP', 'Loop video?')
|
||||
)->setValue($this->object->Loop)
|
||||
];
|
||||
|
||||
return CompositeField::create(array_merge([
|
||||
LiteralField::create(
|
||||
$name.'Options',
|
||||
parent::FieldHolder($properties)
|
||||
)
|
||||
], $fields));
|
||||
}
|
||||
}
|
60
app/src/Extensions/EmbeddedObjectExtension.php
Normal file
60
app/src/Extensions/EmbeddedObjectExtension.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Site\Extensions;
|
||||
|
||||
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
|
||||
class EmbeddedObjectExtension extends DataExtension
|
||||
{
|
||||
private static $db = [
|
||||
'Autoplay' => 'Boolean(0)',
|
||||
'Loop' => 'Boolean(0)',
|
||||
];
|
||||
|
||||
public function Embed()
|
||||
{
|
||||
$this->owner->Embed();
|
||||
$this->setEmbedParams();
|
||||
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
public function setEmbedParams($params = [])
|
||||
{
|
||||
// YouTube params
|
||||
if(stripos($this->owner->EmbedHTML, 'https://www.youtube.com/embed/') > 0) {
|
||||
$params = array_merge([
|
||||
'feature=oembed',
|
||||
'wmode=transparent',
|
||||
'enablejsapi=1',
|
||||
'disablekb=1',
|
||||
'iv_load_policy=3',
|
||||
'modestbranding=1',
|
||||
'rel=0',
|
||||
'showinfo=0',
|
||||
], $params);
|
||||
|
||||
if ($this->owner->Autoplay) {
|
||||
$params[] = 'autoplay=1';
|
||||
}
|
||||
|
||||
if ($this->owner->Loop) {
|
||||
$params[] = 'loop=1';
|
||||
}
|
||||
|
||||
$this->owner->EmbedHTML = preg_replace(
|
||||
'/src="([A-z0-9:\/\.]+)\??(.*?)"/',
|
||||
'src="${1}?' . implode('&', $params) . '"',
|
||||
$this->owner->EmbedHTML
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
parent::onBeforeWrite();
|
||||
$this->setEmbedParams();
|
||||
}
|
||||
}
|
@ -12,11 +12,11 @@ use SilverStripe\UserForms\Model\EditableFormField;
|
||||
|
||||
class UserDefinedFormExtension extends DataExtension
|
||||
{
|
||||
private static $db = [
|
||||
/*private static $db = [
|
||||
'CustomThankYouCode' => 'HTMLText',
|
||||
'RedirectOnComplete' => 'Boolean(0)',
|
||||
'RedirectOnCompleteURL' => 'Varchar(255)',
|
||||
];
|
||||
];*/
|
||||
|
||||
private static $many_many = [
|
||||
'SubmissionColumns' => EditableFormField::class,
|
||||
@ -44,7 +44,7 @@ class UserDefinedFormExtension extends DataExtension
|
||||
|
||||
/*$tab->push(CheckboxField::create('RedirectOnComplete'));
|
||||
$tab->push(TextField::create('RedirectOnCompleteURL'));*/
|
||||
$tab->push(TextareaField::create('CustomThankYouCode'));
|
||||
//$tab->push(TextareaField::create('CustomThankYouCode'));
|
||||
|
||||
$grid = $fields->dataFieldByName('Submissions');
|
||||
|
||||
@ -65,7 +65,7 @@ class UserDefinedFormExtension extends DataExtension
|
||||
$name = $col->getField('Name');
|
||||
$columns[$name] = [
|
||||
'title' => $title,
|
||||
'callback' => function($item) use ($name) {
|
||||
'callback' => function ($item) use ($name) {
|
||||
return $item->relField($name);
|
||||
}
|
||||
];
|
||||
|
@ -9,7 +9,6 @@ use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Path;
|
||||
use SilverStripe\Core\Manifest\ManifestFileFinder;
|
||||
use SilverStripe\CMS\Controllers\CMSMain;
|
||||
|
||||
class DeferedRequirements implements TemplateGlobalProvider
|
||||
{
|
||||
@ -36,15 +35,21 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
|
||||
public static function Auto($class = false)
|
||||
{
|
||||
if (is_a(Controller::curr(), CMSMain::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$config = Config::inst()->get(self::class);
|
||||
$projectName = WebpackTemplateProvider::projectName();
|
||||
$mainTheme = WebpackTemplateProvider::mainTheme();
|
||||
$mainTheme = $mainTheme ? $mainTheme : $projectName;
|
||||
|
||||
$dir = Path::join(
|
||||
Director::publicFolder(),
|
||||
ManifestFileFinder::RESOURCES_DIR,
|
||||
$projectName,
|
||||
'client',
|
||||
'dist'
|
||||
);
|
||||
$cssPath = Path::join($dir, 'css');
|
||||
$jsPath = Path::join($dir, 'js');
|
||||
|
||||
// Initialization
|
||||
Requirements::block(THIRDPARTY_DIR.'/jquery/jquery.js');
|
||||
/*if (defined('FONT_AWESOME_DIR')) {
|
||||
@ -60,7 +65,6 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
if (!$config['nofontawesome']) {
|
||||
DeferedRequirements::loadCSS('//use.fontawesome.com/releases/v5.4.0/css/all.css');
|
||||
}
|
||||
|
||||
DeferedRequirements::loadCSS($mainTheme.'.css');
|
||||
DeferedRequirements::loadJS($mainTheme.'.js');
|
||||
|
||||
@ -78,25 +82,18 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
}
|
||||
|
||||
$class = str_replace('\\', '.', $class);
|
||||
$dir = Path::join(
|
||||
Director::publicFolder(),
|
||||
ManifestFileFinder::RESOURCES_DIR,
|
||||
$projectName,
|
||||
'client',
|
||||
'dist'
|
||||
);
|
||||
|
||||
// Controller requirements
|
||||
$themePath = Path::join($dir, 'css', $mainTheme.'_'.$class . '.css');
|
||||
$projectPath = Path::join($dir, 'css', $projectName.'_'.$class . '.css');
|
||||
$themePath = Path::join($cssPath, $mainTheme.'_'.$class . '.css');
|
||||
$projectPath = Path::join($cssPath, $projectName.'_'.$class . '.css');
|
||||
if ($mainTheme && file_exists($themePath)) {
|
||||
DeferedRequirements::loadCSS($mainTheme.'_'.$class . '.css');
|
||||
} elseif (file_exists($projectPath)) {
|
||||
DeferedRequirements::loadCSS($projectName.'_'.$class . '.css');
|
||||
}
|
||||
|
||||
$themePath = Path::join($dir, 'js', $mainTheme.'_'.$class . '.js');
|
||||
$projectPath = Path::join($dir, 'js', $projectName.'_'.$class . '.js');
|
||||
$themePath = Path::join($jsPath, $mainTheme.'_'.$class . '.js');
|
||||
$projectPath = Path::join($jsPath, $projectName.'_'.$class . '.js');
|
||||
if ($mainTheme && file_exists($themePath)) {
|
||||
DeferedRequirements::loadJS($mainTheme.'_'.$class . '.js');
|
||||
} elseif (file_exists($projectPath)) {
|
||||
|
@ -1,25 +1,27 @@
|
||||
<% with $SiteConfig %>
|
||||
<div class="container">
|
||||
<h2>Contact Us</h2>
|
||||
<div class="field row">
|
||||
<div class="title col-sm-4">Address:</div>
|
||||
<div class="value col-sm-8">$Address</div>
|
||||
</div>
|
||||
<div class="wrapper">
|
||||
<div class="container">
|
||||
<h2>Contact Us</h2>
|
||||
<div class="field row">
|
||||
<div class="title col-sm-4">Address:</div>
|
||||
<div class="value col-sm-8">$Address</div>
|
||||
</div>
|
||||
|
||||
<div class="field row">
|
||||
<div class="title col-sm-4">Phone:</div>
|
||||
<div class="value col-sm-8">$PhoneNumber</div>
|
||||
</div>
|
||||
<div class="field row">
|
||||
<div class="title col-sm-4">Phone:</div>
|
||||
<div class="value col-sm-8">$PhoneNumber</div>
|
||||
</div>
|
||||
|
||||
<div class="field row">
|
||||
<div class="title col-sm-4">Email:</div>
|
||||
<div class="value col-sm-8">$PublicEmail</div>
|
||||
</div>
|
||||
<div class="field row">
|
||||
<div class="title col-sm-4">Email:</div>
|
||||
<div class="value col-sm-8">$PublicEmail</div>
|
||||
</div>
|
||||
|
||||
<% include Objects\SocialLinks %>
|
||||
<% include Objects\SocialLinks %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="copyright">
|
||||
<div class="copyright footer">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
|
@ -12,7 +12,7 @@
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="{$NavID}Content">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<ul class="navbar-nav mr-auto w-100 nav-fill">
|
||||
<% loop $Navigation %>
|
||||
<% include NavItem %>
|
||||
<% end_loop %>
|
||||
|
@ -18,7 +18,7 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer id="Footer" class="site-footer">
|
||||
<footer id="Footer" class="site-footer footer">
|
||||
<% include Footer %>
|
||||
</footer>
|
||||
|
||||
|
@ -3,17 +3,38 @@
|
||||
<% end_if %>
|
||||
|
||||
<% if $SlideShow %>
|
||||
<div id="Carousel{$ID}" class="carousel slide js-carousel d-none d-sm-block"<% if $SlideShow.count > 1 %> data-indicators="true" data-arrows="true"<% end_if %>>
|
||||
<div id="Carousel{$ID}" class="carousel slide js-carousel d-none d-sm-block parallax"<% if $SlideShow.count > 1 %><% if $Interval %> data-interval="$Interval"<% end_if %> data-indicators="true" data-arrows="true"<% end_if %>>
|
||||
<div class="carousel-inner">
|
||||
<% loop $SlideShow %>
|
||||
<div class="carousel-item<% if $First %> active<% end_if %>">
|
||||
<% if $PageLink %><a href="$PageLink.Link" title="$PageLink.MenuTitle.XML" class="btn-primary"><% end_if %>
|
||||
<% if $Image %>
|
||||
<img class="d-block w-100" src="$Image.Fill(1200,600).URL" alt="<% if $Headline %>$Headline<% end_if %>">
|
||||
<% end_if %>
|
||||
<% if $PageLink %></a><% end_if %>
|
||||
|
||||
<div class="carousel-caption">
|
||||
|
||||
<% if $Video || $Image %>
|
||||
<div class="carousel-slide">
|
||||
<% if $Video %>
|
||||
<div class="video">
|
||||
$Video.EmbedHTML.RAW
|
||||
</div>
|
||||
<% end_if %>
|
||||
|
||||
<% if $PageLink %><a href="$PageLink.Link" title="$PageLink.MenuTitle.XML" class="btn-primary"><% end_if %>
|
||||
|
||||
<% if $Image %>
|
||||
<span class="img parallax-image">
|
||||
<img class="d-block w-100" src="$Image.Fill(1200,600).URL" alt="<% if $Headline %>$Headline<% end_if %>">
|
||||
</span>
|
||||
<% end_if %>
|
||||
<% if $PageLink %></a><% end_if %>
|
||||
</div>
|
||||
<% end_if %>
|
||||
|
||||
|
||||
<% if not $Video && not $Image %>
|
||||
<div class="carousel-slide">
|
||||
<% else %>
|
||||
<div class="carousel-caption">
|
||||
<% end_if %>
|
||||
|
||||
<div class="carousel-caption-container">
|
||||
<% if $Headline %><h2 class="carousel-title">$Headline</h2><% end_if %>
|
||||
<% if $Description %><p class="carousel-content">$Description</p><% end_if %>
|
||||
|
Loading…
Reference in New Issue
Block a user