diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b9f6658..b9bd53e 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,7 @@ X-editable changelog Version 1.5.1 wip ---------------------------- +[enh #396] bs3 popover: placement `auto` (vitalets) [bug #357] select2: tags mode with space separator (vitalets) [bug #374] dateui: clear button does not submit (vitalets) diff --git a/src/containers/editable-popover3.js b/src/containers/editable-popover3.js index dc37ba5..f1fac8c 100644 --- a/src/containers/editable-popover3.js +++ b/src/containers/editable-popover3.js @@ -180,16 +180,41 @@ var placement = typeof this.options.placement == 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement; + + var autoToken = /\s?auto?\s?/i; + var autoPlace = autoToken.test(placement); + if (autoPlace) placement = placement.replace(autoToken, '') || 'top'; var pos = this.getPosition(); var actualWidth = $tip[0].offsetWidth; var actualHeight = $tip[0].offsetHeight; + + if (autoPlace) { + var $parent = this.$element.parent(); + + var orgPlacement = placement; + var docScroll = document.documentElement.scrollTop || document.body.scrollTop; + var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth(); + var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight(); + var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left; + + placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' : + placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' : + placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' : + placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' : + placement; + + $tip + .removeClass(orgPlacement) + .addClass(placement); + } + + var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight); this.applyPlacement(calculatedOffset, placement); - - + }).call(this.container()); /*jshint laxcomma: false, eqeqeq: true*/ diff --git a/test/unit/common.js b/test/unit/common.js index 1360d38..a0b93c8 100644 --- a/test/unit/common.js +++ b/test/unit/common.js @@ -88,7 +88,31 @@ //check title ok(p.find(':contains("'+title+'")').length, 'title ok'); e.remove(); - }); + }); + + test("popup placement `auto` (BS3 only)", function () { + //do not test inline + if($.fn.editable.defaults.mode === 'inline' || $.fn.editableform.engine !== 'bs3') { + expect(0); + return; + } + + var title = 'abc', + //add to fx because qunit-fixture has wrong positioning + e = $('<a href="#" id="a" style="position: absolute; top: 50px; left: 10px"></a>').appendTo(fx).editable({ + placement: 'auto', + title: title + }); + + e.click(); + var p = tip(e); + ok(p.is(':visible'), 'popover shown'); + + ok(p.offset().left < e.offset().left, 'placement X ok'); + ok(p.offset().top > e.offset().top, 'placement Y ok'); + + e.remove(); + }); test("onblur: cancel", function () { var oldValue = 'abc',