1const WidgetImageSlider = { 2 inheritAttrs: false, 3 description: { 4 name: 'Bild-Slider', 5 icon: '<i class="fa-solid fa-images"></i>' 6 }, 7 props: { 8 config: { type: Object, required: true }, 9 itemId : { type: Number, required: true }, 10 inherited: { type: Boolean, default: false }, 11 bp: {type: String, required: true}, 12 imageScale: { type: Boolean, default: false } 13 }, 14 components: { 15 'imageslide' : ImageSlide, 16 'base-widget-component': window.designerWidgets.BaseWidgetComponent, 17 'mediabrowser' : MediaBrowser, 18 }, 19 emits: ['update:modelValue', 'deleteslide', 'edit-slide', 'update-config'], 20 data() { 21 return { 22 localConfig: { ...this.config }, 23 widgetBaseConfiguration : { 24 slides : Vue.ref([]), 25 slidesPerView: 4, 26 headline: '', 27 autoplay: 0, 28 swiperState: 'continue', 29 grid: { 30 x: 0, y: 0, 31 w: 12, h: 4 32 }, 33 }, 34 isBackend: window.DESIGNER.base.isBackend, 35 calculatedSlideWidth: 0, 36 draggedIndex: null, 37 dragOverIndex: null, 38 dragInsertPosition: null, 39 dragCounters: {} 40 }; 41 }, 42 delimiters: ['{[', ']}'], 43 template: ` 44 <div :id="'teleportTarget_' + itemId"></div> 45 <base-widget-component v-bind="{...$props, ...$attrs}" ref="baseWidget"> 46 <template v-slot:widget-content="{ config: displayConfig }"> 47 <div v-if="displayConfig.headline?.length > 0" class="swiper-headline">{[ displayConfig.headline ]}</div> 48 <div class="swiper-container image-swiper-widget" :ref="'swiperContainer_' + itemId" :id="'swiper_' + itemId" > 49 <button class="swiper-state-btn" aria-label="Start/Stop Slider" v-if="typeof this.config.autoplay === 'number' && this.config.autoplay > 0" @click="changeSliderAutoplay"> 50 <template v-if="this.widgetBaseConfiguration.swiperState == 'continue'"> 51 <i class="fa-solid fa-circle-pause"></i> 52 </template> 53 <template v-else> 54 <i class="fa-solid fa-circle-play"></i> 55 </template> 56 </button> 57 <div class="swiper-wrapper"> 58 <div class="swiper-slide" v-for="(slide,idx) in displayConfig.slides" :key="'slide-' + itemId + '-' + idx" :class="{[slide.cicolor]: !!slide.cicolor }"> 59 <imageslide v-model="displayConfig.slides[idx]" :ref="'slide-'+idx" :targetid="itemId" @deleteslide="deleteSlideFromDisplay(idx, displayConfig)" :imageScale="imageScale"></imageslide> 60 </div> 61 </div> 62 </div> 63 <div :class="['swiper-button-prev', 'sbp_' + itemId]" :id="'sbp_' + itemId"></div> 64 <div :class="['swiper-button-next', 'sbn_' + itemId]" :id="'sbn_' + itemId"></div> 65 </template> 66 </base-widget-component> 67 `, 68 mounted() { 69 this.initializeSwiper(); 70 }, 71 watch: { 72 'config.slides': { 73 handler() { 74 this.updateSwiper(); 75 }, 76 deep: true 77 }, 78 'config.slidesPerView': { 79 handler(newVal) { 80 this.updateSwiperViewCount(newVal); 81 } 82 } 83 }, 84 methods: { 85 onDragStart(index) { 86 this.draggedIndex = index; 87 }, 88 onDragEnter(index, e) { 89 if (this.draggedIndex === null || this.draggedIndex === index) return; 90 if (!this.dragCounters[index]) this.dragCounters[index] = 0; 91 this.dragCounters[index]++; 92 if (this.dragCounters[index] === 1) { 93 // nur wenn die Maus wirklich zum ersten Mal über das Slide kommt 94 this.dragOverIndex = index; 95 this.dragInsertPosition = this.draggedIndex < index ? 'after' : 'before'; 96 } 97 }, 98 onDragLeave(index, e) { 99 if (!this.dragCounters[index]) return; 100 this.dragCounters[index]--; 101 if (this.dragCounters[index] <= 0) { 102 this.dragOverIndex = null; 103 this.dragInsertPosition = null; 104 this.dragCounters[index] = 0; 105 } 106 }, 107 onDragOver(e) { 108 e.preventDefault(); 109 }, 110 onDrop(e) { 111 if ( 112 this.draggedIndex === undefined || 113 this.dragOverIndex === undefined || 114 this.draggedIndex === this.dragOverIndex 115 ) { 116 return; 117 } 118 // Array aus BaseWidget 119 const slides = this.$refs.baseWidget?.localConfig?.slides; 120 if (!slides) return; 121 const movedItem = slides.splice(this.draggedIndex, 1)[0]; 122 slides.splice(this.dragOverIndex, 0, movedItem); 123 this.draggedIndex = undefined; 124 this.dragOverIndex = undefined; 125 //Parent-Komponente über Ãnderung informieren 126 this.$emit('update-config', this.localConfig); 127 this.$nextTick(() => { 128 if (this.swiperInstance && !this.swiperInstance.destroyed) {
129 this.swiperInstance.update(); 130 } 131 }); 132 }, 133 onDragEnd() { 134 this.draggedIndex = null; 135 this.dragOverIndex = null; 136 this.dragInsertPosition = null; 137 this.dragCounters = {}; 138 }, 139 initializeSwiper() { 140 this.$nextTick(() => { 141 const container = this.$refs['swiperContainer_' + this.itemId]; 142 if (!container) { 143 console.warn("Swiper container not found for ID:", 'swiperContainer_' + this.itemId); 144 return; 145 } 146 if (this.swiperInstance && !this.swiperInstance.destroyed) { 147 this.swiperInstance.destroy(true, true); 148 } 149 this.swiperInstance = new Swiper(container, { 150 slidesPerView: this.config.slidesPerView || this.widgetBaseConfiguration.slidesPerView, 151 autoplay: this.getAutoplayValue() || {}, 152 spaceBetween: 10, 153 centeredSlides: false, 154 observer: true, // Wichtig für dynamische Inhalte 155 observeParents: true, 156 observeSlideChildren: true, // Wichtig, wenn Inhalte in Slides sich ändern 157 navigation: { 158 nextEl: '#sbn_' + this.itemId, 159 prevEl: '#sbp_' + this.itemId, 160 }, 161 on: { 162 init: (swiper) => { 163 this.$nextTick(() => this.updateCalculatedSlideWidth()); 164 }, 165 resize: (swiper) => { 166 this.$nextTick(() => this.updateCalculatedSlideWidth()); 167 }, 168 update: (swiper) => { 169 this.$nextTick(() => this.updateCalculatedSlideWidth()); 170 }, 171 slidesUpdated: (swiper) => { 172 this.$nextTick(() => this.updateCalculatedSlideWidth()); 173 }, 174 observerUpdate: (swiper) => { 175 this.$nextTick(() => this.updateCalculatedSlideWidth()); 176 } 177 } 178 }); 179 this.$nextTick(() => { 180 if(this.swiperInstance && !this.swiperInstance.destroyed) { 181 this.updateCalculatedSlideWidth(); 182 if (this.getAutoplayValue()) { 183 this.swiperInstance.autoplay.start(); 184 } 185 else { 186 this.swiperInstance.autoplay.stop(); 187 } 188 } 189 }); 190 }); 191 }, 192 updateSwiper() { 193 this.$nextTick(() => { 194 if (this.swiperInstance && !this.swiperInstance.destroyed) { 195 this.swiperInstance.update(); 196 } else { 197 this.initializeSwiper(); 198 } 199 }); 200 }, 201 updateSwiperViewCount(newSlidesPerView) { 202 this.$nextTick(() => { 203 if (this.swiperInstance && !this.swiperInstance.destroyed) { 204 this.swiperInstance.params.slidesPerView = parseInt(newSlidesPerView) || 1; 205 this.swiperInstance.update(); 206 } else { 207 this.initializeSwiper(); 208 } 209 }); 210 }, 211 updateSwiperAutoplay(newAutoplay) { 212 this.$nextTick(() => { 213 let autoplayValue = this.getAutoplayValue(); 214 if (this.swiperInstance && !this.swiperInstance.destroyed) { 215 this.swiperInstance.params.autoplay = autoplayValue || {}; 216 if (autoplayValue) { 217 this.swiperInstance.autoplay.start(); 218 } 219 else { 220 this.swiperInstance.autoplay.stop(); 221 }
222 this.swiperInstance.update(); 223 } 224 else { 225 this.initializeSwiper(); 226 } 227 }); 228 }, 229 handleSlideUpdate(currentBaseConfig) { 230 this.$emit('update-config', this.$refs.baseWidget.localConfig); 231 this.updateSwiper(); 232 }, 233 deleteSlideFromBase(index, slidesArray) { 234 if (slidesArray && index >= 0 && index < slidesArray.length) { 235 slidesArray.splice(index, 1); 236 this.handleSlideUpdate(this.$refs.baseWidget.localConfig); 237 } else { 238 console.error('Ungültiger Index oder Array nicht gefunden beim Löschen aus Base.'); 239 } 240 }, 241 deleteSlideFromDisplay(index, displayConfig) { 242 if (displayConfig.slides && index >= 0 && index < displayConfig.slides.length) { 243 const baseSlides = this.$refs.baseWidget?.localConfig?.slides; 244 if (baseSlides && baseSlides.length > index) { 245 baseSlides.splice(index, 1); 246 this.handleSlideUpdate(this.$refs.baseWidget.localConfig); 247 } 248 } 249 }, 250 addNewSlideToBase(slidesArray) { 251 const baseConfig = this.$refs.baseWidget ? this.$refs.baseWidget.localConfig : this.localConfig; 252 if (!baseConfig.slides) { 253 baseConfig.slides = Vue.ref([]); 254 } 255 const newSlide = { id: `new_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, imagePath: null, link: '', cicolor: '' }; 256 const actualSlidesArray = Array.isArray(baseConfig.slides) ? baseConfig.slides : (baseConfig.slides.value || []); 257 actualSlidesArray.push(newSlide); 258 const newSlideIndex = actualSlidesArray.length - 1; 259 this.handleSlideUpdate(baseConfig); 260 this.$nextTick(() => { 261 this.openSpecificMediaBrowser(newSlideIndex); 262 }); 263 }, 264 openSpecificMediaBrowser(index) { 265 this.$nextTick(() => { 266 const mbRefArray = this.$refs['mediaBrowser_' + index]; 267 if (mbRefArray && mbRefArray.length > 0) { 268 const mediaBrowserInstance = mbRefArray[0]; 269 if (mediaBrowserInstance && typeof mediaBrowserInstance.openBrowser === 'function') { 270 mediaBrowserInstance.openBrowser(); 271 } else { 272 console.warn(`MediaBrowser an Index ${index} oder dessen openBrowser Methode nicht gefunden.`); 273 } 274 } 275 }); 276 }, 277 updateCalculatedSlideWidth() { 278 if (this.swiperInstance && !this.swiperInstance.destroyed && this.swiperInstance.slides && this.swiperInstance.slides.length > 0) { 279 const swiper = this.swiperInstance; 280 if (swiper.slidesSizesGrid && swiper.slidesSizesGrid.length > 0) { 281 this.calculatedSlideWidth = Math.round(swiper.slidesSizesGrid[0]); 282 } else { 283 this.calculatedSlideWidth = 0; 284 } 285 } else { 286 this.calculatedSlideWidth = 0; 287 } 288 }, 289 changeSliderAutoplay() { 290 if(this.widgetBaseConfiguration.swiperState === 'continue') { 291 this.widgetBaseConfiguration.swiperState = 'pause'; 292 this.swiperInstance.autoplay.stop(); 293 } else { 294 this.widgetBaseConfiguration.swiperState = 'continue'; 295 this.swiperInstance.autoplay.start(); 296 } 297 }, 298 getAutoplayValue() { 299 const autoplay = this.config.autoplay; 300 if (typeof autoplay === 'number' && autoplay > 0) { 301 return { delay: autoplay, pauseOnMouseEnter: true }; 302 } 303 return false; 304 }, 305 }, 306 beforeUnmount() { 307 if (this.swiperInstance && !this.swiperInstance.destroyed) { 308 this.swiperInstance.destroy(true, true); 309 this.swiperInstance = null; 310 } 311 } 312}; 313window.designerwidgets = window.designerwidgets || {}; 314window.designerwidgets.widgetimageslider = WidgetImageSlider;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.