From 6803ff70f9203595a04c5adb20d7556cd52c5923 Mon Sep 17 00:00:00 2001 From: Guillaume Gautreau Date: Sat, 26 Jan 2013 13:50:26 +0100 Subject: [PATCH 1/7] Tooltip positionning on special cases --- js/bootstrap-tooltip.js | 65 ++++++++++++++++++++++++++++++++++++++--- less/tooltip.less | 9 +++--- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/js/bootstrap-tooltip.js b/js/bootstrap-tooltip.js index c23d8267a8..0d8a20f568 100644 --- a/js/bootstrap-tooltip.js +++ b/js/bootstrap-tooltip.js @@ -152,15 +152,68 @@ break } - $tip - .offset(tp) - .addClass(placement) - .addClass('in') + this.applyPlacement(tp, placement); this.$element.trigger('shown') } } + , applyPlacement: function(offset, placement){ + var $tip + , width + , height + , actualWidth + , actualHeight + , delta + , replace = false; + + $tip = this.tip(); + + width = $tip[0].offsetWidth; + height = $tip[0].offsetHeight; + + $tip + .offset(offset) + .addClass(placement) + .addClass('in'); + + actualWidth = $tip[0].offsetWidth; + actualHeight = $tip[0].offsetHeight; + + if (placement == "top" && actualHeight != actualWidth){ + offset.top = offset.top + height - actualHeight; + replace = true; + } + + if (placement == "bottom" || placement == "top"){ + delta = 0; + + if (offset.left < 0){ + delta = -offset.left * 2; + offset.left = 0; + $tip.offset(offset); + actualWidth = $tip[0].offsetWidth; + actualHeight = $tip[0].offsetHeight; + } + + this.replaceArrow(delta - width + actualWidth, actualWidth, "left"); + }else{ + this.replaceArrow(actualHeight - height, actualHeight, "top"); + } + + if (replace) $tip.offset(offset); + } + + , replaceArrow: function(delta, dimension, position){ + var $arrow = this.arrow(); + + if (delta !== 0){ + $arrow.css(position, 50 * (1 - delta / dimension) + "%"); + }else{ + $arrow.css(position, ""); + } + } + , setContent: function () { var $tip = this.tip() , title = this.getTitle() @@ -233,6 +286,10 @@ return this.$tip = this.$tip || $(this.options.template) } + , arrow: function(){ + return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow"); + } + , validate: function () { if (!this.$element[0].parentNode) { this.hide() diff --git a/less/tooltip.less b/less/tooltip.less index 59b02cd431..d5a2bfaba6 100644 --- a/less/tooltip.less +++ b/less/tooltip.less @@ -9,15 +9,14 @@ z-index: @zindexTooltip; display: block; visibility: visible; - padding: 5px; font-size: 11px; line-height: 1.4; .opacity(0); &.in { .opacity(80); } - &.top { margin-top: -3px; } - &.right { margin-left: 3px; } - &.bottom { margin-top: 3px; } - &.left { margin-left: -3px; } + &.top { margin-top: -3px; padding: 5px 0;} + &.right { margin-left: 3px; padding: 0 5px;} + &.bottom { margin-top: 3px; padding: 5px 0;} + &.left { margin-left: -3px; padding: 0 5px;} } // Wrapper for the tooltip content From 929598784f3a2e4f706d5dcd5a41cea207dfd65e Mon Sep 17 00:00:00 2001 From: Guillaume Gautreau Date: Sat, 26 Jan 2013 14:06:58 +0100 Subject: [PATCH 2/7] Unit test for replacing tooltip inside window --- js/bootstrap-tooltip.js | 2 +- js/tests/unit/bootstrap-tooltip.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/js/bootstrap-tooltip.js b/js/bootstrap-tooltip.js index 0d8a20f568..49c3c6be42 100644 --- a/js/bootstrap-tooltip.js +++ b/js/bootstrap-tooltip.js @@ -190,7 +190,7 @@ if (offset.left < 0){ delta = -offset.left * 2; - offset.left = 0; + offset.left = .1; $tip.offset(offset); actualWidth = $tip[0].offsetWidth; actualHeight = $tip[0].offsetHeight; diff --git a/js/tests/unit/bootstrap-tooltip.js b/js/tests/unit/bootstrap-tooltip.js index ef21bd96b4..94f40f339f 100644 --- a/js/tests/unit/bootstrap-tooltip.js +++ b/js/tests/unit/bootstrap-tooltip.js @@ -251,4 +251,22 @@ $(function () { ok(!$("#qunit-fixture > .tooltip").length, 'not found in parent') tooltip.tooltip('hide') }) + + test("should place tooltip inside window", function(){ + $("#qunit-fixture").show(); + var tooltip = $("") + .css({position: "absolute", top:0, left: 0}) + .appendTo("#qunit-fixture") + .tooltip({placement: "top"}) + .tooltip("show"); + + stop(); + + setTimeout(function(){ + ok($(".tooltip").offset().left >= 0); + + start(); + $("#qunit-fixture").hide(); + }, 200) + }); }) From e5be883bb9a5a9e4eb90df7f3d2e24237a3e010a Mon Sep 17 00:00:00 2001 From: Guillaume Gautreau Date: Sat, 26 Jan 2013 14:31:33 +0100 Subject: [PATCH 3/7] lint + wrong comparison --- js/bootstrap-tooltip.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/bootstrap-tooltip.js b/js/bootstrap-tooltip.js index 49c3c6be42..8b03577442 100644 --- a/js/bootstrap-tooltip.js +++ b/js/bootstrap-tooltip.js @@ -180,7 +180,7 @@ actualWidth = $tip[0].offsetWidth; actualHeight = $tip[0].offsetHeight; - if (placement == "top" && actualHeight != actualWidth){ + if (placement == "top" && actualHeight != height){ offset.top = offset.top + height - actualHeight; replace = true; } @@ -190,7 +190,7 @@ if (offset.left < 0){ delta = -offset.left * 2; - offset.left = .1; + offset.left = 0.1; $tip.offset(offset); actualWidth = $tip[0].offsetWidth; actualHeight = $tip[0].offsetHeight; From db9ec13ce4088fc13a7ef7b07662317ea2c435c8 Mon Sep 17 00:00:00 2001 From: Guillaume Gautreau Date: Sat, 26 Jan 2013 21:39:05 +0100 Subject: [PATCH 4/7] Test for replacing tooltip when resized --- js/tests/index.html | 3 +++ js/tests/unit/bootstrap-tooltip.css | 13 +++++++++++ js/tests/unit/bootstrap-tooltip.js | 34 ++++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 js/tests/unit/bootstrap-tooltip.css diff --git a/js/tests/index.html b/js/tests/index.html index 976ca16872..e9ad01d67a 100644 --- a/js/tests/index.html +++ b/js/tests/index.html @@ -29,6 +29,9 @@ + + + diff --git a/js/tests/unit/bootstrap-tooltip.css b/js/tests/unit/bootstrap-tooltip.css new file mode 100644 index 0000000000..8614e60d7d --- /dev/null +++ b/js/tests/unit/bootstrap-tooltip.css @@ -0,0 +1,13 @@ + + +.tooltip{ + position: absolute; +} + +.tooltip-inner{ + max-width: 200px; +} + +.tooltip.top .tooltip-arrow{ + position: absolute; +} \ No newline at end of file diff --git a/js/tests/unit/bootstrap-tooltip.js b/js/tests/unit/bootstrap-tooltip.js index 94f40f339f..49c034e2ff 100644 --- a/js/tests/unit/bootstrap-tooltip.js +++ b/js/tests/unit/bootstrap-tooltip.js @@ -253,11 +253,12 @@ $(function () { }) test("should place tooltip inside window", function(){ - $("#qunit-fixture").show(); - var tooltip = $("") + var container = $("
").appendTo("body") + .css({position: "absolute", width: 200, height: 200, bottom: 0, left: 0}) + , tooltip = $("Hover me") .css({position: "absolute", top:0, left: 0}) - .appendTo("#qunit-fixture") - .tooltip({placement: "top"}) + .appendTo(container) + .tooltip({placement: "top", animate: false}) .tooltip("show"); stop(); @@ -266,7 +267,28 @@ $(function () { ok($(".tooltip").offset().left >= 0); start(); - $("#qunit-fixture").hide(); - }, 200) + container.remove(); + }, 100) }); + + test("should place tooltip on top of element", function(){ + var container = $("
").appendTo("body") + .css({position: "absolute", bottom: 0, left: 0, textAlign: "right", width: 300, height: 300}) + , p = $("

").appendTo(container) + , tooltiped = $("Hover me") + .css({marginTop: 200}) + .appendTo(p) + .tooltip({placement: "top", animate: false}) + .tooltip("show"); + + stop(); + + setTimeout(function(){ + var tooltip = container.find(".tooltip"); + + start(); + ok(tooltip.offset().top + tooltip.outerHeight() <= tooltiped.offset().top); + container.remove(); + }, 100) + }) }) From d9a0abaa06b4e94ffffc921dcb1119b3bb83f522 Mon Sep 17 00:00:00 2001 From: Guillaume Gautreau Date: Sat, 26 Jan 2013 21:39:49 +0100 Subject: [PATCH 5/7] works with fixed test --- js/bootstrap-tooltip.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/bootstrap-tooltip.js b/js/bootstrap-tooltip.js index 8b03577442..c3708744e5 100644 --- a/js/bootstrap-tooltip.js +++ b/js/bootstrap-tooltip.js @@ -190,7 +190,7 @@ if (offset.left < 0){ delta = -offset.left * 2; - offset.left = 0.1; + offset.left = 0; $tip.offset(offset); actualWidth = $tip[0].offsetWidth; actualHeight = $tip[0].offsetHeight; From 5b0f956a60d8bd41084a167f83c25e276de11705 Mon Sep 17 00:00:00 2001 From: Guillaume Gautreau Date: Sat, 26 Jan 2013 21:45:21 +0100 Subject: [PATCH 6/7] Arrow replacement --- js/tests/unit/bootstrap-tooltip.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/js/tests/unit/bootstrap-tooltip.js b/js/tests/unit/bootstrap-tooltip.js index 49c034e2ff..666c417ee1 100644 --- a/js/tests/unit/bootstrap-tooltip.js +++ b/js/tests/unit/bootstrap-tooltip.js @@ -290,5 +290,26 @@ $(function () { ok(tooltip.offset().top + tooltip.outerHeight() <= tooltiped.offset().top); container.remove(); }, 100) - }) + }); + + test("arrow should point to element", function(){ + var container = $("

").appendTo("body") + .css({position: "absolute", bottom: 0, left: 0, textAlign: "right", width: 300, height: 300}) + , p = $("

").appendTo(container) + , tooltiped = $("Hover me") + .css({marginTop: 200}) + .appendTo(p) + .tooltip({placement: "top", animate: false}) + .tooltip("show"); + + stop(); + + setTimeout(function(){ + var arrow = container.find(".tooltip-arrow"); + + start(); + ok(Math.abs(arrow.offset().left - tooltiped.offset().left - tooltiped.outerWidth()/2) <= 1); + container.remove(); + }, 100); + }); }) From ee71fb492ffc664627436431c5f7b71d2107a526 Mon Sep 17 00:00:00 2001 From: Guillaume Gautreau Date: Sun, 27 Jan 2013 10:56:01 +0100 Subject: [PATCH 7/7] No semicolumns --- js/bootstrap-tooltip.js | 46 +++++++++++++++--------------- js/tests/unit/bootstrap-tooltip.js | 42 +++++++++++++-------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/js/bootstrap-tooltip.js b/js/bootstrap-tooltip.js index c3708744e5..718f9643ee 100644 --- a/js/bootstrap-tooltip.js +++ b/js/bootstrap-tooltip.js @@ -152,7 +152,7 @@ break } - this.applyPlacement(tp, placement); + this.applyPlacement(tp, placement) this.$element.trigger('shown') } @@ -165,52 +165,52 @@ , actualWidth , actualHeight , delta - , replace = false; + , replace = false - $tip = this.tip(); + $tip = this.tip() - width = $tip[0].offsetWidth; - height = $tip[0].offsetHeight; + width = $tip[0].offsetWidth + height = $tip[0].offsetHeight $tip .offset(offset) .addClass(placement) - .addClass('in'); + .addClass('in') - actualWidth = $tip[0].offsetWidth; - actualHeight = $tip[0].offsetHeight; + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight if (placement == "top" && actualHeight != height){ - offset.top = offset.top + height - actualHeight; - replace = true; + offset.top = offset.top + height - actualHeight + replace = true } if (placement == "bottom" || placement == "top"){ - delta = 0; + delta = 0 if (offset.left < 0){ - delta = -offset.left * 2; - offset.left = 0; - $tip.offset(offset); - actualWidth = $tip[0].offsetWidth; - actualHeight = $tip[0].offsetHeight; + delta = -offset.left * 2 + offset.left = 0 + $tip.offset(offset) + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight } - this.replaceArrow(delta - width + actualWidth, actualWidth, "left"); + this.replaceArrow(delta - width + actualWidth, actualWidth, "left") }else{ - this.replaceArrow(actualHeight - height, actualHeight, "top"); + this.replaceArrow(actualHeight - height, actualHeight, "top") } - if (replace) $tip.offset(offset); + if (replace) $tip.offset(offset) } , replaceArrow: function(delta, dimension, position){ - var $arrow = this.arrow(); + var $arrow = this.arrow() if (delta !== 0){ - $arrow.css(position, 50 * (1 - delta / dimension) + "%"); + $arrow.css(position, 50 * (1 - delta / dimension) + "%") }else{ - $arrow.css(position, ""); + $arrow.css(position, "") } } @@ -287,7 +287,7 @@ } , arrow: function(){ - return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow"); + return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow") } , validate: function () { diff --git a/js/tests/unit/bootstrap-tooltip.js b/js/tests/unit/bootstrap-tooltip.js index 666c417ee1..dc4c19bcfd 100644 --- a/js/tests/unit/bootstrap-tooltip.js +++ b/js/tests/unit/bootstrap-tooltip.js @@ -259,17 +259,17 @@ $(function () { .css({position: "absolute", top:0, left: 0}) .appendTo(container) .tooltip({placement: "top", animate: false}) - .tooltip("show"); + .tooltip("show") - stop(); + stop() setTimeout(function(){ - ok($(".tooltip").offset().left >= 0); + ok($(".tooltip").offset().left >= 0) - start(); - container.remove(); + start() + container.remove() }, 100) - }); + }) test("should place tooltip on top of element", function(){ var container = $("

").appendTo("body") @@ -279,18 +279,18 @@ $(function () { .css({marginTop: 200}) .appendTo(p) .tooltip({placement: "top", animate: false}) - .tooltip("show"); + .tooltip("show") - stop(); + stop() setTimeout(function(){ - var tooltip = container.find(".tooltip"); + var tooltip = container.find(".tooltip") - start(); - ok(tooltip.offset().top + tooltip.outerHeight() <= tooltiped.offset().top); - container.remove(); + start() + ok(tooltip.offset().top + tooltip.outerHeight() <= tooltiped.offset().top) + container.remove() }, 100) - }); + }) test("arrow should point to element", function(){ var container = $("
").appendTo("body") @@ -300,16 +300,16 @@ $(function () { .css({marginTop: 200}) .appendTo(p) .tooltip({placement: "top", animate: false}) - .tooltip("show"); + .tooltip("show") - stop(); + stop() setTimeout(function(){ - var arrow = container.find(".tooltip-arrow"); + var arrow = container.find(".tooltip-arrow") - start(); - ok(Math.abs(arrow.offset().left - tooltiped.offset().left - tooltiped.outerWidth()/2) <= 1); - container.remove(); - }, 100); - }); + start() + ok(Math.abs(arrow.offset().left - tooltiped.offset().left - tooltiped.outerWidth()/2) <= 1) + container.remove() + }, 100) + }) })