Permalink
Browse files

externalized styles, added comments, added hideOnMouseOut option

  • Loading branch information...
annavester committed Mar 3, 2013
1 parent 9824cb0 commit aa2c28e710d19032595749e1bdd4c2d568944a69
Showing with 117 additions and 90 deletions.
  1. +1 −0 .gitignore
  2. +1 −8 index.html
  3. +4 −1 tooltip.css
  4. +111 −81 tooltip.js
View
@@ -0,0 +1 @@
+.idea
View
@@ -26,15 +26,8 @@ <h2>Tooltip 2</h2>
<script src="tooltip.js"></script>
<script>
window.onload = function() {
-
var tt = new Tooltip();
- tt.init({
- "opacity":".95",
- "bgColor":"#333",
- "txtColor": "#fff",
- "height": "auto",
- "customCSS": "border-radius:5px;"
- });
+ tt.init({"opacity":".95", "hideOnMouseOut": false});
}
</script>
</body>
View
@@ -1,2 +1,5 @@
-.tooltip-container{padding:10px;position:absolute;margin:0;}
+.tooltip-container{padding:10px;position:absolute;margin:0;opacity:1;border-radius:5px;
+ background-color:#333;width:200px;height:auto;color:#efefef;}
+ .tooltip-container .hideTooltip{cursor:pointer;background:#989898;text-align:center;color:#efefef;border-radius:10px;position:absolute;
+ top:-5px;right:-5px;display:block;width:20px;height:20px;line-height:18px;font-size:12px;}
.tooltip{border-bottom:1px dashed #ccc;cursor:pointer;}
View
@@ -1,95 +1,38 @@
-'use strict';
+var Tooltip = (function (){
+ 'use strict';
-var Tooltip = function (){
var bodyNode = document.getElementsByTagName("body")[0],
- that = this,
- elements = this.elements,
- config = undefined;
-
- this.defaults = {
- opacity: '1',
- width: '300px',
- height: '200px',
- bgColor: '#fff',
- txtColor: '#000',
- customCSS: '',
- containerClassName: 'tooltip-container'
- };
-
- this.init = function(options) {
- var i = 0, cur;
-
- config = merge(options);
- elements = polyGetByClassName('tooltip');
-
- for ( ; i < elements.length; ++i) {
- cur = elements[i];
- cur.addEventListener('mouseover', showTooltip);
- cur.addEventListener('mouseout', hideTooltip);
- }
- };
+ elements = undefined,
+ config = undefined,
+ containerCssClass = 'tooltip-container',
+ defaults = {
+ opacity: '1',
+ hideOnMouseOut: true
+ };
function merge(options) {
- var source = that.defaults;
-
if (!isUndefined(options)) {
- for (var prop in source) {
- if (!isUndefined(options[prop])) source[prop] = options[prop];
+ for (var prop in defaults) {
+ if (!isUndefined(options[prop])) defaults[prop] = options[prop];
}
}
- return source;
- }
-
- function showTooltip(event) {
- var triggerElement = event.target,
- tooltipType = triggerElement.getAttribute('data-tt-type'),
- tooltipContainer = document.createElement('div'),
- tooltipPosX = event.pageX,
- tooltipPosY = event.pageY,
- tooltipContent;
-
- tooltipContainer.className = config.containerClassName;
- tooltipContainer.style.cssText = 'opacity:'+config.opacity+';background-color:'+config.bgColor+';width:'+config.width+';height:'+config.height+';color:'+config.txtColor+';left:'+tooltipPosX+'px;top:'+tooltipPosY+'px;'+config.customCSS+'';
-
- if (tooltipType === "element") {
- /*
- If tooltip type is set to element, tooltip's content can have html elements and is expected
- to be placed right after the parent element of the tooltip instance.
- */
- tooltipContent = triggerElement.parentNode.nextElementSibling.innerHTML;
- tooltipContainer.innerHTML = tooltipContent;
- } else {
- /*
- If tooltip type is set to attr or anything else, tooltip's content is retrieved from title
- attribute of the tooltip instance.
- */
- tooltipContent = triggerElement.getAttribute('title');
- tooltipContainer.innerHTML = tooltipContent;
- }
-
- bodyNode.appendChild(tooltipContainer);
- }
-
- function hideTooltip() {
- var elementsToRemove = polyGetByClassName('tooltip-container'),
- i = 0;
-
- for ( ; i < elementsToRemove.length; ++i) {
- bodyNode.removeChild(elementsToRemove[i]);
- }
+ return defaults;
}
/*
- Helper functions
- */
- function polyGetByClassName(classname) {
+ Helper functions
+ */
+ function polyGetByClassName(classname) { //feature detection
if (typeof document.getElementsByClassName === 'function') {
return document.getElementsByClassName(classname);
} else {
return getElementsByClassName(classname);
}
}
+ /*
+ getElementsByClassName Polyfill for IE8 and below
+ */
function getElementsByClassName(className){
var allNodes = bodyNode.getElementsByTagName('*'),
nodesLen = allNodes.length,
@@ -100,7 +43,7 @@ var Tooltip = function (){
for ( ; i < nodesLen; i++) {
cur = allNodes[i];
- if (isUndefined(cur)) break;
+ if (!isUndefined(cur)) break;
classes = cur.getAttribute('class');
if (classes !== null && classes.indexOf(className) !== -1) {
nodes.push(cur);
@@ -110,10 +53,97 @@ var Tooltip = function (){
}
function isUndefined(element) {
- return !!((typeof element === 'undefined'));
+ return !!(typeof element === 'undefined');
}
- return {
- init: this.init
- }
-};
+ return function Tooltip() {
+
+ /*
+ initialising all tooltips
+ (attaching mouseover event to all elements that have class tooltip)
+ */
+ var init = function init(options) {
+ var i = 0, cur, len;
+
+ config = merge(options);
+ elements = polyGetByClassName('tooltip');
+ len = elements.length;
+
+ for ( ; i < len; ++i) {
+ cur = elements[i];
+ cur.addEventListener('mouseover', showTooltip);
+ }
+ }
+
+ /*
+ triggered by mouseover event
+ - If tooltip type is set to element, tooltip's content can have html elements and is expected
+ to be placed right after the parent element of a given tooltip instance.
+ - If tooltip type is set to attr or anything else, tooltip's content is retrieved from title
+ attribute of a given tooltip instance.
+
+ all visible tooltips will be removed, as only one tooltip is supposed to be visible by default;
+
+ attaching mouseout/click events depending on the options specified:
+ if hideOnMouse = false - click
+ if hideOnMouse = true - mouseout
+ */
+ function showTooltip(event) {
+ if (polyGetByClassName(containerCssClass).length > 0) hideTooltip();
+
+ var triggerElement = event.target,
+ tooltipType = triggerElement.getAttribute('data-tt-type'),
+ frag = document.createDocumentFragment(),
+ tooltipContainer = document.createElement('div'),
+ tooltipPosX = event.pageX,
+ tooltipPosY = event.pageY,
+ tooltipContent;
+
+ frag.appendChild(tooltipContainer);
+ tooltipContainer.className = containerCssClass;
+ tooltipContainer.style.cssText = 'left:'+tooltipPosX+'px;top:'+tooltipPosY+'px;';
+
+ if (tooltipType === "element") {
+ tooltipContent = triggerElement.parentNode.nextElementSibling.innerHTML;
+ tooltipContainer.innerHTML = tooltipContent;
+ } else {
+ tooltipContent = triggerElement.getAttribute('title');
+ tooltipContainer.innerHTML = tooltipContent;
+ }
+
+ if (config.hideOnMouseOut) {
+ this.addEventListener('mouseout', hideTooltip);
+ } else {
+ var hideAnchor = document.createElement('a');
+ hideAnchor.innerText = 'x';
+ hideAnchor.className = 'hideTooltip';
+ hideAnchor.addEventListener('click', hideTooltip);
+ tooltipContainer.appendChild(hideAnchor);
+ }
+
+ bodyNode.appendChild(frag);
+ triggerElement.setAttribute('data-status', 'active');
+ }
+
+ /*
+ triggered by mouseout/click event and/or mouseover on the element that has class tooltip
+ */
+ function hideTooltip(event) {
+ if (!isUndefined(event) && event.type === 'click') event.preventDefault();
+
+ var elementsToRemove = polyGetByClassName(containerCssClass),
+ len = elementsToRemove.length, i = 0;
+
+ for ( ; i < len; ++i) {
+ bodyNode.removeChild(elementsToRemove[i]);
+ }
+ }
+
+ /*
+ public method(s)
+ */
+ return {
+ init: init
+ }
+ };
+})();

0 comments on commit aa2c28e

Please sign in to comment.