%PDF- %PDF-
Direktori : /home/dopla/www/wp-content/plugins/ml-slider/admin/assets/js/app/slideshows/nav/ |
Current File : /home/dopla/www/wp-content/plugins/ml-slider/admin/assets/js/app/slideshows/nav/Switcher.vue |
<template> <div class="relative w-full h-full py-4"> <span> <input :placeholder="__('Search slideshows (Press ctrl + / to focus)\u200E', 'ml-slider')" @focus="focused = true;$event.target.select()" @blur="focused = false" v-model="searchTerm" data-lpignore="true" type="text" ref="switcher" id="ms-slideshow-switcher" class="h-full w-full border border-gray-light focus:bg-white focus:shadow bg-gray-lightest transition duration-300 ease-in shadow-none focus:outline-none border-transparent placeholder-gray-darker rounded m-0 px-8 block appearance-none leading-normal ds-input" /> <span @mouseover="maybeAboutToClick = true" @mouseout="maybeAboutToClick = false" :class="{ hidden: !maybeAboutToClick && !focused }" class="top-arrow absolute z-50 w-full mt-3 shadow-md" role="listbox"> <div class="relative border border-gray-light bg-white rounded pb-2"> <template v-if="!searching"> <div class="flex justify-between items-center pb-2 m-4 mb-2 border-b border-gray-lighter"> <h3 class="text-sm text-gray-dark font-hairline m-0"> {{ summaryText }} </h3> </div> <ul v-if="slideshows.length" class="overflow-scroll overflow-x-hidden" ref="switcher-view-area" style="max-height:30vh" :style="'min-height:' + minHeight + 'px'" role="navigation" aria-label="Slideshow search"> <li @mouseover="selectedSlideshow = key" :key="slideshow.id" :ref="'switch-item-' + slideshow.id" :class="{ 'bg-blue-highlight highlighted-slideshow-nav': highlighted === slideshow.id }" class="m-0" v-for="(slideshow, key) in slideshows"> <slideshow-meta :slideshow="slideshow"/> </li> </ul> <div v-else class="py-2 px-4">{{ __('No slideshows found', 'ml-slider') }}</div> </template> <template v-else> <span class="block text-sm font-hairline m-4 mb-2"> {{ __('Searching slideshows...', 'ml-slider') }} </span> </template> </div> </span> </span> <div @click="focusInput()" :class="{ 'pointer-events-none': focused }" class="absolute inset-y-0 left-0 pl-3 rtl:left-auto rtl:right-0 rtl:pr-3 rtl:pl-0 flex items-center text-gray-dark"> <svg v-if="!searching" class="mt-px w-4 cursor-pointer" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" /> </svg> <svg v-else class="mt-px w-4 ms-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" /> </svg> </div> <div @click="resetInput()" :class="{ invisible: !searchTerm.length }" class="absolute inset-y-0 right-0 rtl:right-auto rtl:left-0 pr-3 rtl:pl-3 rtl:pr-0 flex items-center text-gray-dark"> <svg class="w-4 mt-px" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> </svg> </div> </div> </template> <script> import hotkeys from 'hotkeys-js'; import SlideshowMeta from '../SlideshowMeta' import Slideshow from '../../api/Slideshow' import { mapState } from 'vuex' import { EventManager, Helpers as _ } from '../../utils' export default { components: { 'slideshow-meta': SlideshowMeta }, props: { max: { type: Number|String, default: 25 } }, data() { return { focused: false, selectedSlideshow: -1, maybeAboutToClick: false, searchTerm: '', searching: true, slideshows: {}, } }, watch: { focused() { // Reset when the user leaves if (!this.focused && this.slideshows.length && !this.maybeAboutToClick) { this.resetSelectedPosition() } }, searchTerm() { this.searching = true this.slideshows = {} this.resetSelectedPosition() this.search() } }, computed: { summaryText() { if (!this.slideshows.length) return '' const message = this.slideshows.length == 1 ? this.__('Viewing 1 slideshow', 'ml-slider') : this.__('Viewing %s out of %s slideshows', 'ml-slider') return this.sprintf(message, this.slideshows.length, this.totalSlideshows) }, highlighted() { if (!this.slideshows.length) return null return this.selectedSlideshow > -1 ? this.slideshows[this.selectedSlideshow].id : null }, minHeight() { // Because height is vh, the min-height should be 300px unless they only have a few slideshows return this.slideshows.length > 4 ? 300 : this.slideshows.length * 50 }, ...mapState({ totalSlideshows: state => state.slideshows.totalSlideshows }) }, created() { // Run the filter again if the title changes EventManager.$on('metaslider/title-saved', () => { this.search() }) }, mounted() { hotkeys('ctrl+/', () => this.focusInput()) hotkeys('escape', () => this.blurInput()) hotkeys('enter', () => this.loadSlideshow()) hotkeys('up,down', (e, h) => this.navigateSlideshows(e, h)) hotkeys.filter = event => { return true // Allow keybinding on inputs } this.search() }, methods: { // TODO: possibly delay the mouseover/out events by 200ms or add a slight transition focusInput() { this.$refs.switcher.focus() }, blurInput() { this.maybeAboutToClick = false this.focused && this.$refs.switcher.blur() }, resetInput() { this.focusInput() this.searchTerm = '' }, loadSlideshow() { if (!this.focused) return if (this.selectedSlideshow < 0) return if (!this.slideshows.length) return event.preventDefault() window.location.replace(this.metasliderPage + '&id=' + this.slideshows[this.selectedSlideshow].id) }, navigateSlideshows(event, handler) { if (!this.focused) return // Prevent the native behavior (page scroll down) event.preventDefault() switch(handler.key) { case 'down': // If the selected slideshow is in the final position, leave it there if ((this.selectedSlideshow + 1) < this.slideshows.length) { this.selectedSlideshow++ this.bringSelectedItemIntoFocus() } break case 'up': // If the selected slideshow is not in the 0 position, move it up if (this.selectedSlideshow > 0) { this.selectedSlideshow-- this.bringSelectedItemIntoFocus() } break } }, bringSelectedItemIntoFocus() { if (this.$refs['switcher-view-area']) { this.$refs['switcher-view-area'].children[this.selectedSlideshow].scrollIntoView({ block: "nearest" }) } }, resetSelectedPosition() { // Select the first in the list then scroll to it this.selectedSlideshow = 0 this.bringSelectedItemIntoFocus() // Remove the selected this.selectedSlideshow = -1 }, search:_.debounce(function() { this.searching = true Slideshow.search(this.searchTerm, this.max).then(response => { this.slideshows = response.data.data }).catch(error => { this.notifyError('metaslider/search-error', error, true) }).finally(() => { this.searching = false }) }, 500) } } </script> <style> .top-arrow::before { left: 15px !important; display: block !important; position: absolute !important; content: "" !important; width: 14px !important; height: 14px !important; background: #fff !important; z-index: 1000 !important; top: -7px !important; border-top: 1px solid #dae1e7 !important; border-right: 1px solid #dae1e7 !important; transform: rotate(-45deg) !important; border-radius: 2px !important; } [dir='rtl'] .top-arrow::before { left: auto !important; right: 15px !important; } </style>