<commit_before><script>
import { throttle } from 'lodash'

export default {
  props: {
    firstSlide: {default: 1},
    startStep: {default: 1},
    lastSlide: {default: null},
    embedded: {default: false},
    inserted: {default: false},
    keyboardNavigation: {default: true},
    mouseNavigation: {default: true},
    onStartExit: {default: () => function () {}},
    onEndExit: {default: () => function () {}},
    skip: {default: false},
    backBySlide: {default: false}
  },
  data: function () {
    return {
      currentSlideIndex: 1,
      currentSlide: null,
      step: this.startStep,
      slideshowTimer: 0,
      slideTimer: 0,
      slides: [],
      active: true
    }
  },
  computed: {
    fullPageStyle: function () {
      var size = 0.04 * Math.min(this.fullPageWidth, this.fullPageHeight)
      return { fontSize: size + 'px' }
    },
    embeddedStyle: function () {
      var size = 0.04 * Math.min(this.parentWidth, this.parentHeight)
      return { fontSize: size + 'px' }
    },
    computedActive: function () {
      return this.slides.some(function (slide) { return slide.active })
    }
  },
  mounted: function () {
    // LIST ALL SLIDES
    this.isSlideshow = true
    var self = this
    this.findSlides()

    if (this.$root.direction === 'prev') {
      this.currentSlideIndex = this.slides.length
    }

    if (!this.inserted) {
      this.currentSlide = this.slides[this.currentSlideIndex - 1]
      this.currentSlide.step = this.startStep

      // ADD NAVIGATION EVENTS
      if (this.keyboardNavigation) {
        window.addEventListener('keydown', this.keydown)
      }
      if (this.mouseNavigation) {
        window.addEventListener('click', this.click)
        window.addEventListener('wheel', this.wheel)
      }
      if (this.embedded) {
        this.$el.className += ' embedded-slideshow'
      }
    }
    window.addEventListener('resize', this.handleResize)

    // PRELOAD PICTURES IF ANY
    if (this.preloadedImages) {
      setTimeout(function () {
        for (var image in self.preloadedImages) {
          (new Image()).src = self.preloadedImages[image]
        }
      }, 1000)
    }

    // LAST INITIALIZATIONS
    this.handleResize()
    this.timerUpdater = setInterval(function () {
      self.slideshowTimer++
      self.slideTimer++
    }, 1000)
    this.afterMounted()
  },
  beforeDestroy: function () {
    window.removeEventListener('keydown', this.keydown)
    window.removeEventListener('click', this.click)
    window.removeEventListener('wheel', this.wheel)
    clearInterval(this.timerUpdater)
  },
  methods: {
    nextStep: function () {
      this.slides.forEach(function (slide) {
        slide.direction = 'next'
      })
      this.$root.direction = 'next'
      var self = this
      this.$nextTick(function () {
        if (self.step >= self.currentSlide.steps) {
          self.nextSlide()
        } else {
          self.step++
        }
      })
    },
    previousStep: function () {
      this.slides.forEach(function (slide) {
        slide.direction = 'prev'
      })
      this.$root.direction = 'prev'
      var self = this
      this.$nextTick(function () {
        if (self.step <= 1) {
          self.previousSlide()
        } else {
          self.step--
        }
      })
    },
    nextSlide: function () {
      var nextSlideIndex = this.currentSlideIndex + 1
      while ((nextSlideIndex < this.slides.length + 1) &&
             (this.slides[nextSlideIndex - 1].skip ||
              this.slides[nextSlideIndex - 1].$parent.skip)) {
        nextSlideIndex++
      }
      if (nextSlideIndex < this.slides.length + 1) {
        this.currentSlideIndex = nextSlideIndex
      } else if (!this.embedded) {
        this.onEndExit()
      }
    },
    previousSlide: function () {
      var previousSlideIndex = this.currentSlideIndex - 1
      while ((previousSlideIndex >= 1) &&
             (this.slides[previousSlideIndex - 1].skip ||
              (this.slides[previousSlideIndex - 1].$parent.skip))) {
        previousSlideIndex--
      }
      if (previousSlideIndex >= 1) {
        this.currentSlideIndex = previousSlideIndex
      } else if (!this.embedded) {
        this.onStartExit()
      }
    },
    handleResize: throttle(function (event) {
      var width = 0
      var height = 0
      if (this.embedded) {
        width = this.$el.parentElement.clientWidth
        height = this.$el.parentElement.clientHeight
      } else {
        width = document.documentElement.clientWidth
        height = document.documentElement.clientHeight
      }
      this.$el.style.fontSize = (0.04 * Math.min(height, width)) + 'px'
    }, 16),
    click: function (evt) {
      if (this.mouseNavigation && this.currentSlide.mouseNavigation) {
        if (evt.clientX < (0.25 * document.documentElement.clientWidth)) {
          evt.preventDefault()
          this.previousStep()
        } else if (evt.clientX > (0.75 * document.documentElement.clientWidth)) {
          evt.preventDefault()
          this.nextStep()
        }
      }
    },
    wheel: throttle(function (evt) {
      if (this.mouseNavigation && this.currentSlide.mouseNavigation) {
        evt.preventDefault()
        if ((evt.wheelDeltaY > 0) || (evt.deltaY > 0)) {
          this.nextStep()
        } else if ((evt.wheelDeltaY < 0) || (evt.deltaY < 0)) {
          this.previousStep()
        }
      }
    }, 1000),
    keydown: function (evt) {
      if (this.keyboardNavigation &&
          (this.currentSlide.keyboardNavigation || evt.ctrlKey || evt.metaKey)) {
        evt.preventDefault()
        if (evt.key === 'ArrowLeft') {
          this.previousStep()
        } else if (evt.key === 'ArrowRight') {
          this.nextStep()
        }
      }
    },
    afterMounted: function (evt) {
      // useful in some instances
      return
    },
    findSlides: function () {
      var self = this
      var i = 0
      this.$children.forEach(function (el) {
        if (el.isSlide) {
          i++
          if ((i >= self.firstSlide) && ((!self.lastSlide) || (i <= self.lastSlide))) {
            self.slides.push(el)
          }
        } else if (el.isSlideshow) {
          el.active = false
          el.slides.forEach(function (slide) {
            i++
            slide.active = false
            if ((i >= self.firstSlide) &&
                (!self.lastSlide || (i <= self.lastSlide))) {
              self.slides.push(slide)
            }
          })
        }
      })
    },
    updateSlideshowVisibility: function (val) {
      if (val) {
        this.$el.style.visibility = 'visible'
      } else {
        this.$el.style.visibility = 'hidden'
      }
    }
  },
  watch: {
    currentSlide: function (newSlide, oldSlide) {
      if (oldSlide) {
        oldSlide.active = false
        if ((oldSlide.$parent !== newSlide.$parent) &&
            (oldSlide.$parent !== this)) {
          oldSlide.$parent.active = false
        }
      }
      this.slideTimer = 0
      if (this.backBySlide || newSlide.direction === 'next') {
        this.step = 1
        newSlide.step = 1
        newSlide.$parent.step = 1
      } else if (newSlide.direction === 'prev') {
        this.step = newSlide.steps
        newSlide.step = newSlide.steps
        newSlide.$parent.step = newSlide.steps
      }
      newSlide.active = true
      newSlide.$parent.active = true
    },
    currentSlideIndex: function (index) {
      this.currentSlide = this.slides[index - 1]
    },
    step: function (val) {
      if (this.currentSlide) {
        this.currentSlide.step = val
        this.currentSlide.$parent.step = val
      }
    },
    active: 'updateSlideshowVisibility',
    computedActive: 'updateSlideshowVisibility'
  }

}
</script>

<style lang="sass">
@import '../themes/base.scss';
</style>
<commit_msg>Keyboard navigation for wireless presenter<commit_after><script>
import { throttle } from 'lodash'

export default {
  props: {
    firstSlide: {default: 1},
    startStep: {default: 1},
    lastSlide: {default: null},
    embedded: {default: false},
    inserted: {default: false},
    keyboardNavigation: {default: true},
    mouseNavigation: {default: true},
    onStartExit: {default: () => function () {}},
    onEndExit: {default: () => function () {}},
    skip: {default: false},
    backBySlide: {default: false}
  },
  data: function () {
    return {
      currentSlideIndex: 1,
      currentSlide: null,
      step: this.startStep,
      slideshowTimer: 0,
      slideTimer: 0,
      slides: [],
      active: true
    }
  },
  computed: {
    fullPageStyle: function () {
      var size = 0.04 * Math.min(this.fullPageWidth, this.fullPageHeight)
      return { fontSize: size + 'px' }
    },
    embeddedStyle: function () {
      var size = 0.04 * Math.min(this.parentWidth, this.parentHeight)
      return { fontSize: size + 'px' }
    },
    computedActive: function () {
      return this.slides.some(function (slide) { return slide.active })
    }
  },
  mounted: function () {
    // LIST ALL SLIDES
    this.isSlideshow = true
    var self = this
    this.findSlides()

    if (this.$root.direction === 'prev') {
      this.currentSlideIndex = this.slides.length
    }

    if (!this.inserted) {
      this.currentSlide = this.slides[this.currentSlideIndex - 1]
      this.currentSlide.step = this.startStep

      // ADD NAVIGATION EVENTS
      if (this.keyboardNavigation) {
        window.addEventListener('keydown', this.keydown)
      }
      if (this.mouseNavigation) {
        window.addEventListener('click', this.click)
        window.addEventListener('wheel', this.wheel)
      }
      if (this.embedded) {
        this.$el.className += ' embedded-slideshow'
      }
    }
    window.addEventListener('resize', this.handleResize)

    // PRELOAD PICTURES IF ANY
    if (this.preloadedImages) {
      setTimeout(function () {
        for (var image in self.preloadedImages) {
          (new Image()).src = self.preloadedImages[image]
        }
      }, 1000)
    }

    // LAST INITIALIZATIONS
    this.handleResize()
    this.timerUpdater = setInterval(function () {
      self.slideshowTimer++
      self.slideTimer++
    }, 1000)
    this.afterMounted()
  },
  beforeDestroy: function () {
    window.removeEventListener('keydown', this.keydown)
    window.removeEventListener('click', this.click)
    window.removeEventListener('wheel', this.wheel)
    clearInterval(this.timerUpdater)
  },
  methods: {
    nextStep: function () {
      this.slides.forEach(function (slide) {
        slide.direction = 'next'
      })
      this.$root.direction = 'next'
      var self = this
      this.$nextTick(function () {
        if (self.step >= self.currentSlide.steps) {
          self.nextSlide()
        } else {
          self.step++
        }
      })
    },
    previousStep: function () {
      this.slides.forEach(function (slide) {
        slide.direction = 'prev'
      })
      this.$root.direction = 'prev'
      var self = this
      this.$nextTick(function () {
        if (self.step <= 1) {
          self.previousSlide()
        } else {
          self.step--
        }
      })
    },
    nextSlide: function () {
      var nextSlideIndex = this.currentSlideIndex + 1
      while ((nextSlideIndex < this.slides.length + 1) &&
             (this.slides[nextSlideIndex - 1].skip ||
              this.slides[nextSlideIndex - 1].$parent.skip)) {
        nextSlideIndex++
      }
      if (nextSlideIndex < this.slides.length + 1) {
        this.currentSlideIndex = nextSlideIndex
      } else if (!this.embedded) {
        this.onEndExit()
      }
    },
    previousSlide: function () {
      var previousSlideIndex = this.currentSlideIndex - 1
      while ((previousSlideIndex >= 1) &&
             (this.slides[previousSlideIndex - 1].skip ||
              (this.slides[previousSlideIndex - 1].$parent.skip))) {
        previousSlideIndex--
      }
      if (previousSlideIndex >= 1) {
        this.currentSlideIndex = previousSlideIndex
      } else if (!this.embedded) {
        this.onStartExit()
      }
    },
    handleResize: throttle(function (event) {
      var width = 0
      var height = 0
      if (this.embedded) {
        width = this.$el.parentElement.clientWidth
        height = this.$el.parentElement.clientHeight
      } else {
        width = document.documentElement.clientWidth
        height = document.documentElement.clientHeight
      }
      this.$el.style.fontSize = (0.04 * Math.min(height, width)) + 'px'
    }, 16),
    click: function (evt) {
      if (this.mouseNavigation && this.currentSlide.mouseNavigation) {
        if (evt.clientX < (0.25 * document.documentElement.clientWidth)) {
          evt.preventDefault()
          this.previousStep()
        } else if (evt.clientX > (0.75 * document.documentElement.clientWidth)) {
          evt.preventDefault()
          this.nextStep()
        }
      }
    },
    wheel: throttle(function (evt) {
      if (this.mouseNavigation && this.currentSlide.mouseNavigation) {
        evt.preventDefault()
        if ((evt.wheelDeltaY > 0) || (evt.deltaY > 0)) {
          this.nextStep()
        } else if ((evt.wheelDeltaY < 0) || (evt.deltaY < 0)) {
          this.previousStep()
        }
      }
    }, 1000),
    keydown: function (evt) {
      if (this.keyboardNavigation &&
          (this.currentSlide.keyboardNavigation || evt.ctrlKey || evt.metaKey)) {
        evt.preventDefault()
        if (evt.key === 'ArrowLeft' || evt.key === 'PageUp') {
          this.previousStep()
        } else if (evt.key === 'ArrowRight' || evt.key === 'PageDown') {
          this.nextStep()
        }
      }
    },
    afterMounted: function (evt) {
      // useful in some instances
      return
    },
    findSlides: function () {
      var self = this
      var i = 0
      this.$children.forEach(function (el) {
        if (el.isSlide) {
          i++
          if ((i >= self.firstSlide) && ((!self.lastSlide) || (i <= self.lastSlide))) {
            self.slides.push(el)
          }
        } else if (el.isSlideshow) {
          el.active = false
          el.slides.forEach(function (slide) {
            i++
            slide.active = false
            if ((i >= self.firstSlide) &&
                (!self.lastSlide || (i <= self.lastSlide))) {
              self.slides.push(slide)
            }
          })
        }
      })
    },
    updateSlideshowVisibility: function (val) {
      if (val) {
        this.$el.style.visibility = 'visible'
      } else {
        this.$el.style.visibility = 'hidden'
      }
    }
  },
  watch: {
    currentSlide: function (newSlide, oldSlide) {
      if (oldSlide) {
        oldSlide.active = false
        if ((oldSlide.$parent !== newSlide.$parent) &&
            (oldSlide.$parent !== this)) {
          oldSlide.$parent.active = false
        }
      }
      this.slideTimer = 0
      if (this.backBySlide || newSlide.direction === 'next') {
        this.step = 1
        newSlide.step = 1
        newSlide.$parent.step = 1
      } else if (newSlide.direction === 'prev') {
        this.step = newSlide.steps
        newSlide.step = newSlide.steps
        newSlide.$parent.step = newSlide.steps
      }
      newSlide.active = true
      newSlide.$parent.active = true
    },
    currentSlideIndex: function (index) {
      this.currentSlide = this.slides[index - 1]
    },
    step: function (val) {
      if (this.currentSlide) {
        this.currentSlide.step = val
        this.currentSlide.$parent.step = val
      }
    },
    active: 'updateSlideshowVisibility',
    computedActive: 'updateSlideshowVisibility'
  }

}
</script>

<style lang="sass">
@import '../themes/base.scss';
</style>

{'fraction_non_alphanumeric': 0.1356755030341744, 'fraction_numerical': 0.007409773235388055, 'mean_word_length': 2.05125706489963, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5602571', 'n_tokens_mistral': 4910, 'n_tokens_neox': 4844, 'n_words': 916}