Skip to content
Snippets Groups Projects
Commit 8c727ad6 authored by Sean McArthur's avatar Sean McArthur
Browse files

Merge pull request #2230 from mozilla/issue_1615_tooltips

Make sure only one is ever shown at a time.  Some further cleanup because tooltip code was fugly.
parents 27ab2838 ef3c0576
No related branches found
No related tags found
No related merge requests found
...@@ -8,24 +8,23 @@ BrowserID.Tooltip = (function() { ...@@ -8,24 +8,23 @@ BrowserID.Tooltip = (function() {
"use strict"; "use strict";
var ANIMATION_TIME = 250, var ANIMATION_TIME = 250,
TOOLTIP_DISPLAY = 2000, TOOLTIP_MIN_DISPLAY = 2000,
READ_WPM = 200, READ_WPM = 200,
bid = BrowserID, bid = BrowserID,
dom = bid.DOM,
renderer = bid.Renderer, renderer = bid.Renderer,
hideTimer; hideTimer,
tooltip;
function createTooltip(el) { function createTooltip(el) {
var contents = el.html(); tooltip = renderer.append("body", "tooltip", {
contents: el.html()
var tooltip = renderer.append("body", "tooltip", { });
contents: contents
});
return tooltip; return tooltip;
} }
function positionTooltip(tooltip, target) { function anchorTooltip(target) {
target = $(target);
var targetOffset = target.offset(); var targetOffset = target.offset();
targetOffset.top -= (tooltip.outerHeight() + 5); targetOffset.top -= (tooltip.outerHeight() + 5);
targetOffset.left += 10; targetOffset.left += 10;
...@@ -33,56 +32,69 @@ BrowserID.Tooltip = (function() { ...@@ -33,56 +32,69 @@ BrowserID.Tooltip = (function() {
tooltip.css(targetOffset); tooltip.css(targetOffset);
} }
function animateTooltip(el, complete) { function calculateDisplayTime(text) {
var contents = el.text().replace(/\s+/, ' ').replace(/^\s+/, '').replace(/\s+$/, ''); // Calculate the amount of time a tooltip should display based on the
var words = contents.split(' ').length; // number of words in the content divided by the number of words an average
// person can read per minute.
var contents = text.replace(/\s+/, ' ').trim(),
words = contents.split(' ').length,
// The average person can read ± 250 wpm.
wordTimeMS = (words / READ_WPM) * 60 * 1000,
displayTimeMS = Math.max(wordTimeMS, TOOLTIP_MIN_DISPLAY);
return displayTimeMS;
}
// The average person can read ± 250 wpm. function animateTooltip(el, complete) {
var wordTimeMS = (words / READ_WPM) * 60 * 1000; var displayTimeMS = calculateDisplayTime(el.text());
var displayTimeMS = Math.max(wordTimeMS, TOOLTIP_DISPLAY);
bid.Tooltip.shown = true; bid.Tooltip.shown = true;
el.fadeIn(ANIMATION_TIME, function() { el.fadeIn(ANIMATION_TIME, function() {
hideTimer = setTimeout(function() { hideTimer = setTimeout(function() {
el.fadeOut(ANIMATION_TIME, function() { el.fadeOut(ANIMATION_TIME, complete);
bid.Tooltip.shown = false;
if(complete) complete();
});
}, displayTimeMS); }, displayTimeMS);
}); });
}
function createAndShowRelatedTooltip(el, relatedTo, complete) { return displayTimeMS;
// This means create a copy of the tooltip element and position it in
// relation to an element. Right now we are putting the tooltip directly
// above the element. Once the tooltip is no longer needed, remove it
// from the DOM.
var tooltip = createTooltip(el);
var target = $("#" + relatedTo);
positionTooltip(tooltip, target);
animateTooltip(tooltip, function() {
if (tooltip) {
tooltip.remove();
tooltip = null;
}
if (complete) complete();
});
} }
function showTooltip(el, complete) { function showTooltip(el, complete) {
el = $(el); // Only one tooltip can be shown at a time, see issue #1615
var messageFor = el.attr("for"); removeTooltips();
// By default, the element passed in is the tooltip element. If it has
// a "for" attribute, that means this tooltip should be anchored to the
// element listed in the "for" attribute. If that is the case, create a new
// tooltip and anchor it to the other element.
var tooltipEl = $(el),
tooltipAnchor = tooltipEl.attr("for");
if (tooltipAnchor) {
// The tooltip should be anchored to another element. Place the tooltip
// directly above the element and remove it when it is no longer needed.
tooltipEl = createTooltip(tooltipEl);
anchorTooltip("#" + tooltipAnchor);
}
return animateTooltip(tooltipEl, function() {
removeTooltips();
complete && complete();
});
}
// First, see if we are "for" another element, if we are, create a copy of function removeTooltips() {
// the tooltip to attach to the element. if (tooltip) {
if(messageFor) { tooltip.remove();
createAndShowRelatedTooltip(el, messageFor, complete); tooltip = null;
} }
else {
animateTooltip(el, complete); if (hideTimer) {
clearTimeout(hideTimer);
hideTimer = null;
} }
$('.tooltip').hide();
bid.Tooltip.shown = false;
} }
...@@ -90,15 +102,7 @@ BrowserID.Tooltip = (function() { ...@@ -90,15 +102,7 @@ BrowserID.Tooltip = (function() {
showTooltip: showTooltip showTooltip: showTooltip
// BEGIN TESTING API // BEGIN TESTING API
, ,
reset: function() { reset: removeTooltips
if(hideTimer) {
clearTimeout(hideTimer);
hideTimer = null;
}
$(".tooltip").hide();
bid.Tooltip.shown = false;
}
// END TESTING API // END TESTING API
}; };
......
...@@ -7,42 +7,28 @@ ...@@ -7,42 +7,28 @@
"use strict"; "use strict";
var bid = BrowserID, var bid = BrowserID,
tooltip = bid.Tooltip tooltip = bid.Tooltip,
testHelpers = bid.TestHelpers;
module("common/js/tooltip", { module("common/js/tooltip", {
setup: function() { setup: function() {
testHelpers.setup();
}, },
teardown: function() { teardown: function() {
testHelpers.teardown();
} }
}); });
asyncTest("show short tooltip, min of 2.5 seconds", function() { test("show short tooltip - shows for about 2.5 seconds", function() {
var startTime = new Date().getTime(); var displayTime = tooltip.showTooltip("#shortTooltip");
ok(2000 <= displayTime && displayTime <= 3000, displayTime + " - minimum of 2 seconds, max of 3 seconds");
tooltip.showTooltip("#shortTooltip", function() {
var endTime = new Date().getTime();
var diff = endTime - startTime;
ok(2000 <= diff && diff <= 3000, diff + " - minimum of 2 seconds, max of 3 seconds");
equal(tooltip.shown, false, "tooltip says it is no longer shown");
start();
});
equal(tooltip.shown, true, "tooltip says that it is shown"); equal(tooltip.shown, true, "tooltip says that it is shown");
}); });
asyncTest("show long tooltip, takes about 5 seconds", function() { test("show long tooltip - shows for about 5 seconds", function() {
var startTime = new Date().getTime(); var displayTime = tooltip.showTooltip("#longTooltip");
ok(displayTime >= 4500, displayTime + " - longer tooltip is on the screen for a bit longer");
tooltip.showTooltip("#longTooltip", function() {
var endTime = new Date().getTime();
var diff = endTime - startTime;
ok(diff >= 4500, diff + " - longer tooltip is on the screen for a bit longer");
start();
});
}); });
asyncTest("show tooltip, then reset - hides tooltip, resets shown status", function() { asyncTest("show tooltip, then reset - hides tooltip, resets shown status", function() {
...@@ -56,4 +42,10 @@ ...@@ -56,4 +42,10 @@
}, 100); }, 100);
}); });
test("only one tooltip shown at a time", function() {
tooltip.showTooltip("#shortTooltip");
tooltip.showTooltip("#shortTooltip");
equal($(".tooltip:visible").length, 1, "only one tooltip shown at a time");
});
}()); }());
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment