From 0488d44cc2cc55808cf5aa17cb1b0c5423c958db Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Wed, 21 Mar 2018 18:23:33 +0000 Subject: [PATCH] Add popover --- app/assets/javascripts/shared/popover.js | 84 ++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 app/assets/javascripts/shared/popover.js diff --git a/app/assets/javascripts/shared/popover.js b/app/assets/javascripts/shared/popover.js new file mode 100644 index 00000000000..48894c2b100 --- /dev/null +++ b/app/assets/javascripts/shared/popover.js @@ -0,0 +1,84 @@ +export default class Popover { + constructor(trigger, content) { + this.isOpen = false; + + this.$popover = $(trigger).popover({ + content, + html: true, + placement: 'bottom', + trigger: 'manual', + }); + } + + init() { + this.registerClickOpenListener(); + } + + openPopover() { + if (this.isOpen) return; + + this.$popover.popover('show'); + this.$popover.one('shown.bs.popover', this.enableClose.bind(this)); + this.isOpen = true; + } + + closePopover() { + if (!this.isOpen) return; + + this.$popover.popover('hide'); + this.disableClose(); + this.isOpen = false; + } + + closePopoverClick(event) { + const $target = $(event.target); + + if ($target.is(this.$popover) || + $target.is('.popover') || + $target.parents('.popover').length > 0) return; + + this.closePopover(); + } + + closePopoverMouseleave() { + setTimeout(() => { + if (this.$popover.is(':hover') || + (this.$popover.siblings('.popover').length > 0 && + this.$popover.siblings('.popover').is(':hover'))) return; + + this.closePopover(); + }, 1500); + } + + registerClickOpenListener() { + this.$popover.on('click.glPopover.open', this.openPopover.bind(this)); + } + + registerClickCloseListener() { + $(document.body).on('click.glPopover.close', this.closePopoverClick.bind(this)); + } + + registerMouseleaveCloseListener() { + this.$popover.on('mouseleave.glPopover.close', this.closePopoverMouseleave.bind(this)); + this.$popover.siblings('.popover').on('mouseleave.glPopover.close', this.closePopoverMouseleave.bind(this)); + } + + destroyMouseleaveCloseListener() { + this.$popover.off('mouseleave.glPopover.close'); + this.$popover.siblings('.popover').on('mouseleave.glPopover.close'); + } + + enableClose() { + this.registerClickCloseListener(); + this.registerMouseleaveCloseListener(); + } + + disableClose() { + Popover.destroyClickCloseListener(); + this.destroyMouseleaveCloseListener(); + } + + static destroyClickCloseListener() { + $(document.body).off('click.glPopover.close'); + } +}