Skip to content

Commit

Permalink
first commit - hint feature
Browse files Browse the repository at this point in the history
  • Loading branch information
afshinm committed Oct 30, 2015
1 parent 49e98bb commit 8ae5227
Show file tree
Hide file tree
Showing 3 changed files with 348 additions and 6 deletions.
72 changes: 72 additions & 0 deletions example/hint/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hints</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Intro.js - Better introductions for websites and features with a step-by-step guide for your projects.">
<meta name="author" content="Afshin Mehrabani (@afshinmeh) in usabli.ca group">

<!-- styles -->
<link href="../assets/css/bootstrap.min.css" rel="stylesheet">
<link href="../assets/css/demo.css" rel="stylesheet">

<!-- Add IntroJs styles -->
<link href="../../introjs.css" rel="stylesheet">

<link href="../assets/css/bootstrap-responsive.min.css" rel="stylesheet">
</head>

<body>

<div class="container-narrow">

<div class="masthead">
<ul class="nav nav-pills pull-right" data-hint="Get it, use it." data-hintPosition="top-middle" data-position="right">
<li><a href="https://github.com/usablica/intro.js/tags"><i class='icon-black icon-download-alt'></i> Download</a></li>
<li><a href="https://github.com/usablica/intro.js">Github</a></li>
<li><a href="https://twitter.com/usablica">@usablica</a></li>
</ul>
<h3 class="muted">Intro.js</h3>
</div>

<hr>

<div class="jumbotron">
<h1 data-hint="This is a tooltip!" data-hintPosition="top-middle">Hints</h1>
<p class="lead">Add hints using <code>data-hint</code> attribute.</p>
<a class="btn btn-large btn-success" href="javascript:void(0);" onclick="javascript:introJs().addHints();">Add hints</a>
</div>

<hr>

<div class="row-fluid marketing">
<div class="span6">
<h4>Section One</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis mollis augue a neque cursus ac blandit orci faucibus. Phasellus nec metus purus.</p>

<h4>Section Two</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis mollis augue a neque cursus ac blandit orci faucibus. Phasellus nec metus purus.</p>

<h4>Section Three</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis mollis augue a neque cursus ac blandit orci faucibus. Phasellus nec metus purus.</p>
</div>

<div class="span6">
<h4>Section Four</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis mollis augue a neque cursus ac blandit orci faucibus. Phasellus nec metus purus.</p>

<h4>Section Five</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis mollis augue a neque cursus ac blandit orci faucibus. Phasellus nec metus purus.</p>

<h4>Section Six</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis mollis augue a neque cursus ac blandit orci faucibus. Phasellus nec metus purus.</p>

</div>
</div>

<hr>
</div>
<script type="text/javascript" src="../../intro.js"></script>
</body>
</html>
189 changes: 183 additions & 6 deletions intro.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
*/
function IntroJs(obj) {
this._targetElement = obj;
this._introItems = [];

this._options = {
/* Next button label in tooltip box */
Expand Down Expand Up @@ -65,7 +66,11 @@
/* Precedence of positions, when auto is enabled */
positionPrecedence: ["bottom", "top", "right", "left"],
/* Disable an interaction with element? */
disableInteraction: false
disableInteraction: false,
/* Default hint position */
hintPosition: 'top',
/* Hint button label */
hintButtonLabel: 'Got it',
};
}

Expand Down Expand Up @@ -694,7 +699,7 @@
* @api private
* @method _disableInteraction
*/
function _disableInteraction () {
function _disableInteraction() {
var disableInteractionLayer = document.querySelector('.introjs-disableInteraction');
if (disableInteractionLayer === null) {
disableInteractionLayer = document.createElement('div');
Expand Down Expand Up @@ -1132,7 +1137,175 @@
}, 10);

return true;
}
};


/**
* Start parsing hint items
*
* @api private
* @param {Object} targetElm
* @method _startHint
*/
function _populateHints(targetElm) {
var self = this;

if (this._options.hints) {
for (var i = 0, l = this._options.hints.length; i < l; i++) {
var currentItem = _cloneObject(this._options.hints[i]);

if (typeof(currentItem.element) === 'string') {
//grab the element with given selector from the page
currentItem.element = document.querySelector(currentItem.element);
}

if (currentItem.element != null) {
this._introItems.push(currentItem);
}
}
} else {
var hints = targetElm.querySelectorAll('*[data-hint]');

if (hints.length < 1) {
return false;
}

//first add intro items with data-step
for (var i = 0, l = hints.length; i < l; i++) {
var currentElement = hints[i];

this._introItems.push({
element: currentElement,
hint: currentElement.getAttribute('data-hint'),
hintPosition: currentElement.getAttribute('data-hintPosition') || this._options.hintPosition,
position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
});
}
}

_addHints.call(this);
};

/**
* Add all available hints to the page
*
* @api private
* @method _addHints
*/
function _addHints() {
var hintsWrapper = document.createElement('div');
hintsWrapper.className = 'introjs-hints';

for (var i = 0, l = this._introItems.length; i < l; i++) {
var item = this._introItems[i];

var hint = document.createElement('a');
hint.href = "javascript:void(0);";

// when user clicks on the hint element
hint.onclick = _hintClick.bind(this, hint, item);

hint.className = 'introjs-hint';
var hintDot = document.createElement('div');
hintDot.className = 'introjs-hint-dot';
var hintPulse = document.createElement('div');
hintPulse.className = 'introjs-hint-pulse';

hint.appendChild(hintDot);
hint.appendChild(hintPulse);
hint.setAttribute('data-step', i);

// get/calculate offset of target element
var offset = _getOffset.call(this, item.element);

// we swap the hint element with target element
// because _setHelperLayerPosition uses `element` property
item.targetElement = item.element;
item.element = hint;

// align the hint element
switch (item.hintPosition) {
default:
case 'top-left':
hint.style.left = offset.left + 'px';
hint.style.top = offset.top + 'px';
break;
case 'top-right':
hint.style.left = (offset.left + offset.width) + 'px';
hint.style.top = offset.top + 'px';
break;
case 'bottom-left':
hint.style.left = offset.left + 'px';
hint.style.top = (offset.top + offset.height) + 'px';
break;
case 'bottom-right':
hint.style.left = (offset.left + offset.width) + 'px';
hint.style.top = (offset.top + offset.height) + 'px';
break;
case 'bottom-middle':
hint.style.left = (offset.left + (offset.width / 2)) + 'px';
hint.style.top = (offset.top + offset.height) + 'px';
break;
case 'top-middle':
hint.style.left = (offset.left + (offset.width / 2)) + 'px';
hint.style.top = offset.top + 'px';
break;
}

hintsWrapper.appendChild(hint);
}

// adding the hints wrapper
document.body.appendChild(hintsWrapper);
};

/**
* Triggers when user clicks on the hint element
*
* @api private
* @method _hintClick
* @param {Object} hintElement
* @param {Object} item
*/
function _hintClick(hintElement, item) {
var tooltipLayer = document.createElement('div');
var tooltipTextLayer = document.createElement('div');
var arrowLayer = document.createElement('div');
var referenceLayer = document.createElement('div');

tooltipLayer.className = 'introjs-tooltip';

tooltipTextLayer.className = 'introjs-tooltiptext';

var tooltipWrapper = document.createElement('p');
tooltipWrapper.innerHTML = item.hint;

var closeButton = document.createElement('a');
closeButton.className = 'introjs-button';
closeButton.innerHTML = this._options.hintButtonLabel;

tooltipTextLayer.appendChild(tooltipWrapper);
tooltipTextLayer.appendChild(closeButton);

arrowLayer.className = 'introjs-arrow';
tooltipLayer.appendChild(arrowLayer);

tooltipLayer.appendChild(tooltipTextLayer);

// set current step for _placeTooltip function
this._currentStep = hintElement.getAttribute('data-step');

// align reference layer position
referenceLayer.className = 'introjs-tooltipReferenceLayer introjs-hintTooltip';
referenceLayer.setAttribute('data-step', hintElement.getAttribute('data-step'));
_setHelperLayerPosition.call(this, referenceLayer);

referenceLayer.appendChild(tooltipLayer);
document.body.appendChild(referenceLayer);

//set proper position
_placeTooltip.call(this, hintElement, tooltipLayer, arrowLayer);
};

/**
* Get an element position on the page
Expand Down Expand Up @@ -1166,7 +1339,7 @@
elementPosition.left = _x;

return elementPosition;
}
};

/**
* Gets the current progress percentage
Expand All @@ -1179,7 +1352,7 @@
// Steps are 0 indexed
var currentStep = parseInt((this._currentStep + 1), 10);
return ((currentStep / this._introItems.length) * 100);
}
};

/**
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
Expand All @@ -1194,7 +1367,7 @@
for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
return obj3;
}
};

var introJs = function (targetElm) {
if (typeof (targetElm) === 'object') {
Expand Down Expand Up @@ -1300,6 +1473,10 @@
throw new Error('Provided callback for onexit was not a function.');
}
return this;
},
addHints: function() {
_populateHints.call(this, this._targetElement);
return this;
}
};

Expand Down
Loading

0 comments on commit 8ae5227

Please sign in to comment.