diff --git a/src/pretix/presale/templates/pretixpresale/event/fragment_cart.html b/src/pretix/presale/templates/pretixpresale/event/fragment_cart.html index c9dd89050..a4323de74 100644 --- a/src/pretix/presale/templates/pretixpresale/event/fragment_cart.html +++ b/src/pretix/presale/templates/pretixpresale/event/fragment_cart.html @@ -261,7 +261,7 @@ {{ line.price|money:event.currency }} {% endif %} {% if line.discount and line.line_price_gross != line.price %} - +
{% if line.price < line.line_price_gross %} @@ -334,7 +334,7 @@ {{ line.price|money:event.currency }} {% endif %} {% if line.discount and line.line_price_gross != line.price %} - +
{% if line.price < line.line_price_gross %} diff --git a/src/pretix/static/bootstrap/js/bootstrap.js b/src/pretix/static/bootstrap/js/bootstrap.js index 170bd608f..eabbbcd68 100644 --- a/src/pretix/static/bootstrap/js/bootstrap.js +++ b/src/pretix/static/bootstrap/js/bootstrap.js @@ -1452,7 +1452,7 @@ if (typeof jQuery === 'undefined') { template: '', trigger: 'hover focus', title: '', - delay: 0, + delay: 1, html: false, container: false, viewport: { @@ -1464,6 +1464,14 @@ if (typeof jQuery === 'undefined') { whiteList : DefaultWhitelist } + Tooltip.activeTooltip = null; + + function hideOnEscapeListener(e) { + if (Tooltip.activeTooltip && e.key === 'Escape') { + Tooltip.activeTooltip.hide(); + } + } + Tooltip.prototype.init = function (type, element, options) { this.enabled = true this.type = type @@ -1476,6 +1484,8 @@ if (typeof jQuery === 'undefined') { throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') } + document.body.addEventListener('keyup', hideOnEscapeListener); + var triggers = this.options.trigger.split(' ') for (var i = triggers.length; i--;) { @@ -1483,7 +1493,7 @@ if (typeof jQuery === 'undefined') { if (trigger == 'click') { this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) - } else if (trigger != 'manual') { + } else if (trigger == 'hover' || trigger == 'focus') { var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' @@ -1547,7 +1557,8 @@ if (typeof jQuery === 'undefined') { } if (obj instanceof $.Event) { - self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true + console.log("enter",obj.currentTarget.role, obj.type, obj.currentTarget) + self.inState[(obj.currentTarget.role == 'tooltip' ? 'tip' : '') + (obj.type == 'focusin' ? 'focus' : 'hover')] = true } if (self.tip().hasClass('in') || self.hoverState == 'in') { @@ -1567,6 +1578,7 @@ if (typeof jQuery === 'undefined') { } Tooltip.prototype.isInStateTrue = function () { + console.log("state:",this.inState) for (var key in this.inState) { if (this.inState[key]) return true } @@ -1584,7 +1596,8 @@ if (typeof jQuery === 'undefined') { } if (obj instanceof $.Event) { - self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false + console.log("leave",obj.currentTarget.role, obj.type, obj.currentTarget) + self.inState[(obj.currentTarget.role == 'tooltip' ? 'tip' : '') + (obj.type == 'focusout' ? 'focus' : 'hover')] = false } if (self.isInStateTrue()) return @@ -1610,6 +1623,12 @@ if (typeof jQuery === 'undefined') { if (e.isDefaultPrevented() || !inDom) return var that = this + if (Tooltip.activeTooltip) { + Tooltip.activeTooltip.hide(); + } + + Tooltip.activeTooltip = this; + var $tip = this.tip() var tipId = this.getUID(this.type) @@ -1768,6 +1787,8 @@ if (typeof jQuery === 'undefined') { if (e.isDefaultPrevented()) return + Tooltip.activeTooltip = null; + $tip.removeClass('in') $.support.transition && $tip.hasClass('fade') ? @@ -1812,12 +1833,12 @@ if (typeof jQuery === 'undefined') { return $.extend({}, elRect, scroll, outerDims, elOffset) } - + const OVERLAP = 3; Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { - return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : - /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } + return placement == 'bottom' ? { top: pos.top + pos.height - OVERLAP, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'top' ? { top: pos.top - actualHeight + OVERLAP, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2 , left: pos.left - actualWidth + OVERLAP } : + /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width - OVERLAP } } @@ -1872,6 +1893,20 @@ if (typeof jQuery === 'undefined') { if (this.$tip.length != 1) { throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') } + + var triggers = this.options.trigger.split(' ') + + for (var i = triggers.length; i--;) { + var trigger = triggers[i] + + if (trigger == 'tiphover' || trigger == 'tipfocus') { + var eventIn = trigger == 'tiphover' ? 'mouseenter' : 'focusin' + var eventOut = trigger == 'tiphover' ? 'mouseleave' : 'focusout' + + this.$tip.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$tip.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } + } } return this.$tip } diff --git a/src/pretix/static/pretixcontrol/js/ui/main.js b/src/pretix/static/pretixcontrol/js/ui/main.js index 95b2827a1..0170ceb89 100644 --- a/src/pretix/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/static/pretixcontrol/js/ui/main.js @@ -795,9 +795,10 @@ function setup_basics(el) { }); }); - el.find('[data-toggle="tooltip"]').tooltip(); + el.find('[data-toggle="tooltip"]').tooltip({ delay: 1, trigger: 'focus hover tipfocus tiphover' }) + .filter(':not([tabindex])').attr('tabindex', '0'); el.find('[data-toggle="tooltip_html"]').tooltip({ - 'html': true, + 'html': true, delay: 1, trigger: 'focus hover tipfocus tiphover', 'whiteList': { // Global attributes allowed on any supplied element below. '*': ['class', 'dir', 'id', 'lang', 'role'], @@ -812,7 +813,7 @@ function setup_basics(el) { strong: [], u: [], } - }); + }).filter(':not([tabindex])').attr('tabindex', '0'); el.find('a.pagination-selection').click(function (e) { e.preventDefault(); diff --git a/src/pretix/static/pretixpresale/js/ui/main.js b/src/pretix/static/pretixpresale/js/ui/main.js index 6f3b9ea51..0c71a6db8 100644 --- a/src/pretix/static/pretixpresale/js/ui/main.js +++ b/src/pretix/static/pretixpresale/js/ui/main.js @@ -307,7 +307,8 @@ function setup_basics(el) { e.preventDefault(); }); - el.find('[data-toggle="tooltip"]').tooltip(); + el.find('[data-toggle="tooltip"]').tooltip({ delay: 1, trigger: 'focus hover tipfocus tiphover' }) + .filter(':not([tabindex])').attr('tabindex', '0'); // AddOns el.find('.addon-variation-description').hide();