Fred and Bootstrap carousel

Hi All,

Do you have any example of implementation of Bootstrap Carousel with Fred having the carousel-inner div with a data-fred-dropzone, and each carousel-item as droppable object?

I am trying to find the best way to implement this successfully, but not with big success so far…
Thanks in advance.

Env: Modx 2.7.1-pl with Fred 1.1.0 RC2

Thanks in advance

EDIT: Found this information on Fred githib:

I shall try this.
If you have other ways of Bootstrap carousel implementation with Fred, please share your ideas.
Cheers

Well, I had success implementing a carousel using the method mentioned above, but it seems that Fred has some inline editing limitations.
I am not able to pick a link like I am able to do with an image so I can have a popup for the properties changes.

Opened a github issue in order to get more details or know if this is something still missing from fred:

If it is still missing and not targeted to 1.1.0-pl, then I might go for drag and drop approach for the links

Let me know if you’re still interested in this. I have a pretty solid working example of this right now, but I’m having a tiny little issue with it in that the inner and out Fred settings controls are difficult to separate.

When I move out of the inner zone to try and activate the settings, the controls switch to the outer zone… it’s a pickle :slight_smile:

Hi @robcarey, I’d be very interested in seeing your implementation! I have a version of a Bootstrap Carousel which works pretty well at the moment, except I’d like to be able to use pthumb for the image resizing which I can’t at the moment. Right now I’m doing it without a dropzone since I think they’ve a bit fiddly for the client, but I’m considering changing it to option 2 as described here. My main priority is to make it as easy to use for the client as possible and I’d love to see a demo of how you’ve solved it!

If it’s of interest to anyone here’s what I’ve got at the moment, with great help of @inside-creative. It works really well, except that pthumb doesn’t work once you replace the placeholder image with your own image so you have to ensure the client crops and resizes the images manually first.

Fred element:

<div id="bootstrapCarousel" class="carousel slide" data-ride="carousel">
  <div class="carousel-inner">
    {% for i in 0..(items - 1) %}
            <div class="carousel-item {{ (i)? : "active"}}">
              <img class="d-block w-100" src="[[pthumb? &input=`[[++fred.theme.mytheme.theme_dir]]images/placehold.jpg` &options=`aoe=1&w=1200&h=600&dpi=72&f=jpg&zc=1`]]" alt="Image descrition" data-fred-name="image-{{i}}" data-fred-attrs="alt">
            </div>
    {% endfor %}
  </div>
  {% if items > 1 %}
  <a class="carousel-control-prev" href="#bootstrapCarousel" role="button" data-slide="prev">
    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
    <span class="sr-only">Previous</span>
  </a>
  <a class="carousel-control-next" href="#bootstrapCarousel" role="button" data-slide="next">
    <span class="carousel-control-next-icon" aria-hidden="true"></span>
    <span class="sr-only">Next</span>
  </a>
  {% endif %}
</div>

<div data-fred-render="false" class="editorInstructions clearfix">
    <div class="editorInstructionsInner float-right">
        Instructions here
    </div>
</div>

Fred options:

{
  "remote": true,
  "settings": [
    {
      "type": "slider",
      "name": "items",
      "label": "Number of images in slider",
      "min": 1,
      "max": 10,
      "step": 1,
      "value": 3
    }
  ]
}

When I move out of the inner zone to try and activate the settings, the controls switch to the outer zone… it’s a pickle :slight_smile:

@robcarey Perhaps adding editor instructions below the dropzone like in my above example helps with your issue? The outer zone settings will then be at the bottom of the instructions and the inner settings above the instructions, I think…

1 Like

Sorry for the delayed response here - I must have missed a notification. Stumbled back on it looking for something else! :slight_smile:

So I have inner and outer carousel elements:

OUTER MARKUP:

<div class="container-fluid p-0 m-0">
<div id="{{carouselID}}" class="carousel slide {% if crossFade %}carousel-fade{% endif %}" data-ride="carousel" data-interval="{{slideDuration}}">
    <ol class="carousel-indicators" {% if showIndicators == false %}style="display:none;"{% endif %}>
        {% set k = itemCount %}{% for i in range(1, k) %}<li {% if i-1 == 0 %}class="active"{% endif %} data-target="#{{carouselID}}" data-slide-to="{{i - 1}}"></li>{% endfor %}
    </ol>
    <div class="carousel-inner">
        
        
        {% set k = itemCount %}{% for i in range(1, k) %}
        <div data-fred-dropzone="thing{{i}}" class="carousel-item {% if i-1 == 0 %}active{% endif %}" data-fred-min-height="300px" style="min-height:{{heroHeight}}px;height:{{heroHeight}}px;">

        </div>
        {% endfor %}
        
        
    </div>
    <a class="carousel-control-prev" role="button" href="#{{carouselID}}" data-slide="prev" {% if showControls == false %}style="display:none;"{% endif %}>
        <span class="carousel-control-prev-icon" aria-hidden="true">&nbsp;</span>
        <span class="sr-only">Previous</span>
    </a>
    <a class="carousel-control-next" role="button" href="#{{carouselID}}" data-slide="next" {% if showControls == false %}style="display:none;"{% endif %}>
        <span class="carousel-control-next-icon" aria-hidden="true">&nbsp;</span>
        <span class="sr-only">Next</span>
    </a>
</div>

OUTER OPTIONS:

   {
  "remote": false,
  "settings": [
    {
      "name": "carouselID",
      "label": "Page-unique Class Name",
      "type": "text",
      "value": "mainNewHeroOne"
    },
    {
      "name": "slideDuration",
      "label": "Slide Duration (ms)",
      "type": "slider",
      "min": 0,
      "max": 10000,
      "step": 100,
      "value": 5000
    },
    {
      "name": "itemCount",
      "label": "Number of Items",
      "type": "slider",
      "min": 1,
      "max": 5,
      "step": 1,
      "value": 1
    },
    {
      "name": "heroHeight",
      "label": "Height of Hero",
      "type": "text",
      "value": 300
    },
    {
      "name": "crossFade",
      "label": "Crossfade instead of slide",
      "type": "toggle",
      "value": false
    },
    {
      "name": "showControls",
      "label": "Show Controls",
      "type": "toggle",
      "value": true
    },
    {
      "name": "showIndicators",
      "label": "Show Indicators",
      "type": "toggle",
      "value": true
    }
  ]
}

The outer basically has a slider control for how many carousel items you have plus a variety of other options related to bootstrap carousels

INNER MARKUP:

<div class="m-0 p-0" style="min-height:{{heroHeight}}px;height:{{heroHeight}}px;background:{# FOREGROUND-IMG #}{%if fg_image_picker %}url({{fg_image_picker}}){%if fg_image_repeat %} {{fg_image_repeat}}{%endif%}{%if fg_image_position_val %} {{fg_image_position_val}}{%else%}{%if fg_image_position %} {{fg_image_position}}{%endif%}{%endif%},{%endif%} {# /FOREGROUND-IMG #}linear-gradient({{gradient_angle}}deg, {{gradient_first_colour}} {{gradientoffset}}%, {{gradient_second_colour}}){# BACKGROUND-IMG #}{%if bg_image_picker %}, url({{bg_image_picker}}){%if bg_image_repeat %} {{bg_image_repeat}}{%endif%}{%if bg_image_position_val %} {{bg_image_position_val}}{%else%}{%if bg_image_position %} {{bg_image_position}}{%endif%}{%endif%}{%endif%}{# /BACKGROUND-IMG #};background-size:{%if fg_image_picker %}{%if fg_image_size_val %}{{fg_image_size_val}}{%else%}{%if fg_image_size %}{{fg_image_size}}{%endif%}{%endif%},{%endif%}auto{%if bg_image_picker %}, {%if bg_image_size_val %}{{bg_image_size_val}}{%else%}{%if bg_image_size %}{{bg_image_size}}{%endif%}{%endif%};{%endif%}">
  {% if bg_video_picker != "" %}
  <video class="herovideo" style="opacity:{%if videoOpacity == "10" %}1.0{% else %}0.{{videoOpacity}}{% endif %};" poster="{{bg_video_poster_image}}" autoplay="autoplay" loop="loop" muted="muted">
        <source src="{{bg_video_picker}}" type="video/mp4" />
  </video>
  {% endif %}
  <div class="container" style="position: relative; z-index: 2 !important;height:inherit;" data-fred-name="inner-carousel-content" data-fred-rte="true" data-fred-rte-config="basic">
    <div class="d-flex py-3 h-100 align-items-center justify-content-center" style="height:inherit;">
      <div class="w-100" style="text-align: center;">
        <h6 class="display-3" style="text-align: center; font-family: 'Gotham Black';"><span style="color: #231f20;">A whatever of tech<br />
          </span></h6>
        <p class="lead mb-0" style="text-align: center;"><span style="color: #231f20; font-family: 'Gotham Black'; letter-spacing: normal;">est. 1997<br />
          </span></p>
        <a class="mt-4 btn btn-lg btn-ct-yellow">This is a button {{parent.heroHeight}}</a> </div>
    </div>
  </div>
</div>

INNER OPTIONS:

{
  "remote": true,
  "settings": [
    {
      "name": "heroHeight",
      "label": "Height of Hero Item (match parent)",
      "type": "text",
      "value": 300
    },
    {
      "fred-import": "fg_image_group"
    },
    {
      "fred-import": "bg_image_group"
    },
    {
      "fred-import": "bg_gradient_group"
    },
    {
      "fred-import": "bg_video_group"
    }
  ]
}

I have some very detailed background, foreground image and video options working on this in those imported options sets. Let me know if you’d like to see the details on those, but basically you can have video backgrounds with varying opacity, gradients, solid colors, images… pretty much anything and still have a rich text area for content.

Caveat’s - it was tricky having the inner options selectable when they were the same size as the outer container. If you’ve worked with nested containers in Fred you already know what I’m talking about. I was able to make this easier by having an edit-time active css class applied to the inner container that wedged a bottom margin of like 20 or 50 or something like that so that there was space to be able to distinguish between inner and outer.

Let me know if you have any questions on this.

Cheers

1 Like

Here’s how I get around the setting selection dilema - plus a few other nice-to-haves for my FRED editing.

I have a chunk called “fred-css” with this:

<style>
.mce-content-body {
    line-height: inherit !important; /** Prevents TinyMCE messing with your line-height **/
}

div[data-fred-dropzone]{
    outline:1px dashed red;
}
.fred--active .row {
    /*margin:5px;*/
}

.carousel-inner{
    z-index:1;
    margin-bottom:20px;
}
.carousel{
    z-index:0;
}
.carousel-control-prev, .carousel-control-next{
    margin-bottom:300px;
}

.fred--active .stretched-link::after {
    position: relative !important;
   display:none;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 1;
    pointer-events: auto;
    content: "";
    background-color: rgba(0, 0, 0, 0);
}

[data-fred-render="false"] {
    color: #dedede;
    letter-spacing: 2px;
    font-family: monospace;
    font-size: 16px;
}

*[data-fred-name] {
outline: 2px solid rgba(247, 77, 77, 0.18);
}
</style>

The carousel related entries above fix most of the setting selections issues - these can be modified or expanded on to suit. All the classes are applied during editing using this custom plugin code, that is set to run on the “FredBeforeRender” system event:

<?php
$cust_styles = $modx->getChunk('fred-css');
$modx->event->_output = [
    'includes' => $cust_styles
];

This applies the styles defined in the chunk. The red dashed outlines applied to Fred dropzones has been super helpful to my editors.

1 Like

I would be really interested in the settings you are using in the imported groups:
{
“fred-import”: “fg_image_group”
},
{
“fred-import”: “bg_image_group”
},
{
“fred-import”: “bg_gradient_group”
},
{
“fred-import”: “bg_video_group”
}

RobCarey - I’ve been able to implement this to a certain degree but I cannot get any except the 1st slide to show up. The “Active” class is not triggering on the other slides.

Is this code supposed to give multiple dropzones?

Hey there @rachelmarama1 - yes the previous version above did have multiple dropzones - one for each number of carousel items you have set in the options.

I did find in practice this one was a bit of a pain in the ass to work with - the nested dropzone proved cumbersome for some of my team so I re-did this element using static HTML for each carousel item created. It’s MUCH more easy to work with even if it is a richtext item for each carousel.

I have included the element and options in separate files in the linked ZIP:

fred-bs-carousel.zip

There are placeholder images for foreground, background and even a video layer - you’ll want to customize those to defaults on your own server. The ones I have in there are PNGs with transparency so it really highlights what’s going on visually.

Also - this relies on a RTE config called “basic” being present… modify to use your own RTE config.

data-fred-rte-config=“basic”

@rachelmarama1 The group configs you asked for above:

Group config examples

robcarey - thanks so much for sharing your examples. It’s always helpful to see what others are doing!

1 Like