How to make bootstrap 5 carousel draggable

2.4k views Asked by At

I'm trying to make a boostrap 5 carousel draggable using drag and drop API. I have a problem when the carousel is dragged into another position where it can be dropped, it will lose all css settings that are in my vue component css and I will not be able to moove it again. How I can fix this and make the carousel and it's content draggable?

COMPONNENT HTML

    <div class="row widget-area position-absolute m-0">
      
      <div class="col-3 pt-2 pb-2 dropzone" @drop.prevent="onDrop($event)" @dragover.prevent @dragenter.prevent="onDragenter($event)" @dragleave="onDragleave($event)">
        <div id="newsCarousel" class="carousel slide position-absolute" data-ride="carousel" draggable="true" @dragstart="startDrag($event)">
          <!-- carousel inner -->
          <div class="carousel-inner" draggable="true">
            <div class="carousel-item card draggable-el position-absolute" :class="{ 'active': index === 0 }" :id="index" v-for="( news, index ) in newsfeed.articles" :key="index" draggable="true">
              <img class="card-img-top" :src="news.image" :id="index" draggable="true" @dragstart="startDrag($event)">
              <div class="card-body p-2">
                <a class="text-decoration-none text-body" :href="news.source.url">
                  <small class="d-block text-muted">{{ news.source.name }}</small>
                </a>
                <a class="h6 text-decoration-none text-body card-title stretched-link" :href="news.url">{{ news.title }}</a>
              </div>
            </div>
          </div>
          <!-- carousel controls -->
          <a class="carousel-control-prev" href="#newsCarousel" role="button" data-slide="prev" draggable="true">
            <span class="carousel-control-prev-icon" aria-hidden="true"></span>
            <span class="visually-hidden">Previous</span>
          </a>
          <a class="carousel-control-next" href="#newsCarousel" role="button" data-slide="next" draggable="true">
            <span class="carousel-control-next-icon" aria-hidden="true"></span>
            <span class="visually-hidden">Next</span>
          </a>
        </div>
      </div>
      
      <div class="col-3 pt-2 pb-2 dropzone" 
        @drop.prevent="onDrop($event)" 
        @dragover.prevent 
        @dragenter.prevent="onDragenter($event)" 
        @dragleave="onDragleave($event)">
      </div>

      <div class="col-3 pt-2 pb-2 dropzone" 
        @drop.prevent="onDrop($event)" 
        @dragover.prevent 
        @dragenter.prevent="onDragenter($event)" 
        @dragleave="onDragleave($event)">
      </div>

      <div class="col-3 pt-2 pb-2 dropzone" 
        @drop.prevent="onDrop($event)" 
        @dragover.prevent 
        @dragenter.prevent="onDragenter($event)" 
        @dragleave="onDragleave($event)">
      </div>

    </div>

JS CODE

    //drag n drop
    startDrag(e) {
      let ids = [];
      e.dataTransfer.dropEffect = 'move';
      e.dataTransfer.effectAllowed = 'move';
      const items = document.getElementsByClassName('draggable-el');
      items.forEach( (el) => {
        el.classList.add('dragging');
        ids.push(el.id);      
      });
      e.dataTransfer.setData('text/plain', JSON.stringify(ids));     
    },
    onDragenter(e) {
      e.target.classList.add('drop');
    },
    onDragleave(e) {
      e.target.classList.remove('drop');
    },
    onDrop(e) {
      let ids = JSON.parse(e.dataTransfer.getData('text/plain'));
      ids.forEach( (id) => {
        const item = document.getElementById(id);
        item.classList.remove('dragging');
        e.target.classList.remove('drop');
        e.target.appendChild(item);
      });
      // return false;
    }

SCOPED CSS

.widget-area {
  width: 100%;
  height: 350px;
  top: 8em;
  z-index: 200;

  .dropzone {
    &.drop{
      border: rgba(255,255,255,0.3) dotted 1px;
      .draggable-el {
        pointer-events: none;
      }
    }
  }
  #newsCarousel {
    // width: 18.5rem;
    // height: 330px;
    .carousel-inner {
      width: 18.5rem;
      height: 330px;
      z-index: 300;
      .draggable-el {
        height: 330px;
        width: 18.5rem;
        transition: all 0.3s cubic-bezier(0.4, 0.0, 0.2, 1);
        &:active {
          cursor: grabbing;
        }  
        &.dragging {
          opacity: .5;
          transform: scale(.8);
        }
      }
    }
    .carousel-control-prev, .carousel-control-next {
      z-index: 300;
      top: -6em;
    }
  }
}
0

There are 0 answers