|
1180 | 1180 | */
|
1181 | 1181 | function _populateHints(targetElm) {
|
1182 | 1182 | var self = this;
|
| 1183 | + this._introItems = [] |
1183 | 1184 |
|
1184 | 1185 | if (this._options.hints) {
|
1185 | 1186 | for (var i = 0, l = this._options.hints.length; i < l; i++) {
|
|
1209 | 1210 | element: currentElement,
|
1210 | 1211 | hint: currentElement.getAttribute('data-hint'),
|
1211 | 1212 | hintPosition: currentElement.getAttribute('data-hintPosition') || this._options.hintPosition,
|
| 1213 | + tooltipClass: currentElement.getAttribute('data-tooltipClass'), |
1212 | 1214 | position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
|
1213 | 1215 | });
|
1214 | 1216 | }
|
|
1219 | 1221 | if (document.addEventListener) {
|
1220 | 1222 | document.addEventListener('click', _removeHintTooltip.bind(this), false);
|
1221 | 1223 | //for window resize
|
1222 |
| - //window.addEventListener('resize', this._onResize, true); |
| 1224 | + window.addEventListener('resize', _reAlignHints.bind(this), true); |
1223 | 1225 | } else if (document.attachEvent) { //IE
|
1224 | 1226 | //for window resize
|
1225 |
| - document.attachEvent('onclick', _removeHintTooltip.bind(this)); |
1226 |
| - //document.attachEvent('onresize', self._onResize); |
| 1227 | + document.attachEvent('onclick', _removeHintTooltip.bind(this)); |
| 1228 | + document.attachEvent('onresize', _reAlignHints.bind(this)); |
1227 | 1229 | }
|
1228 | 1230 | };
|
1229 | 1231 |
|
| 1232 | + /** |
| 1233 | + * Re-aligns all hint elements |
| 1234 | + * |
| 1235 | + * @api private |
| 1236 | + * @method _reAlignHints |
| 1237 | + */ |
| 1238 | + function _reAlignHints() { |
| 1239 | + for (var i = 0, l = this._introItems.length; i < l; i++) { |
| 1240 | + var item = this._introItems[i]; |
| 1241 | + _alignHintPosition.call(this, item.hintPosition, item.element, item.targetElement) |
| 1242 | + } |
| 1243 | + } |
| 1244 | + |
1230 | 1245 | /**
|
1231 | 1246 | * Remove single hint from the page
|
1232 | 1247 | *
|
|
1240 | 1255 | if (hint) {
|
1241 | 1256 | hint.parentNode.removeChild(hint);
|
1242 | 1257 | }
|
| 1258 | + |
| 1259 | + // call the callback function (if any) |
| 1260 | + if (typeof (this._hintRemoveCallback) !== 'undefined') { |
| 1261 | + this._hintRemoveCallback.call(this, stepId); |
| 1262 | + } |
| 1263 | + }; |
| 1264 | + |
| 1265 | + /** |
| 1266 | + * Hide a hint |
| 1267 | + * |
| 1268 | + * @api private |
| 1269 | + * @method _hideHint |
| 1270 | + */ |
| 1271 | + function _hideHint(stepId) { |
| 1272 | + _removeHintTooltip.call(this); |
| 1273 | + var hint = this._targetElement.querySelector('.introjs-hint[data-step="' + stepId + '"]'); |
| 1274 | + |
| 1275 | + if (hint) { |
| 1276 | + hint.className += ' introjs-hidehint'; |
| 1277 | + } |
| 1278 | + |
| 1279 | + // call the callback function (if any) |
| 1280 | + if (typeof (this._hintCloseCallback) !== 'undefined') { |
| 1281 | + this._hintCloseCallback.call(this, stepId); |
| 1282 | + } |
| 1283 | + }; |
| 1284 | + |
| 1285 | + /** |
| 1286 | + * Remove all hints from the page |
| 1287 | + * |
| 1288 | + * @api private |
| 1289 | + * @method _removeHints |
| 1290 | + */ |
| 1291 | + function _removeHints() { |
| 1292 | + var hints = this._targetElement.querySelectorAll('.introjs-hint'); |
| 1293 | + |
| 1294 | + for (var i = 0, l = hints.length; i < l; i++) { |
| 1295 | + _removeHint.call(this, hints[i].getAttribute('data-step')); |
| 1296 | + } |
1243 | 1297 | };
|
1244 | 1298 |
|
1245 | 1299 | /**
|
|
1250 | 1304 | */
|
1251 | 1305 | function _addHints() {
|
1252 | 1306 | var self = this;
|
1253 |
| - var hintsWrapper = document.createElement('div'); |
1254 |
| - hintsWrapper.className = 'introjs-hints'; |
| 1307 | + |
| 1308 | + var oldHintsWrapper = document.querySelector('.introjs-hints'); |
| 1309 | + |
| 1310 | + if (oldHintsWrapper != null) { |
| 1311 | + hintsWrapper = oldHintsWrapper; |
| 1312 | + } else { |
| 1313 | + var hintsWrapper = document.createElement('div'); |
| 1314 | + hintsWrapper.className = 'introjs-hints'; |
| 1315 | + } |
1255 | 1316 |
|
1256 | 1317 | for (var i = 0, l = this._introItems.length; i < l; i++) {
|
1257 | 1318 | var item = this._introItems[i];
|
1258 | 1319 |
|
| 1320 | + // avoid append a hint twice |
| 1321 | + if (document.querySelector('.introjs-hint[data-step="' + i + '"]')) |
| 1322 | + continue; |
| 1323 | + |
1259 | 1324 | var hint = document.createElement('a');
|
1260 | 1325 | hint.href = "javascript:void(0);";
|
1261 | 1326 |
|
|
1280 | 1345 | hint.appendChild(hintPulse);
|
1281 | 1346 | hint.setAttribute('data-step', i);
|
1282 | 1347 |
|
1283 |
| - // get/calculate offset of target element |
1284 |
| - var offset = _getOffset.call(this, item.element); |
1285 |
| - |
1286 | 1348 | // we swap the hint element with target element
|
1287 | 1349 | // because _setHelperLayerPosition uses `element` property
|
1288 | 1350 | item.targetElement = item.element;
|
1289 | 1351 | item.element = hint;
|
1290 | 1352 |
|
1291 |
| - // align the hint element |
1292 |
| - switch (item.hintPosition) { |
1293 |
| - default: |
1294 |
| - case 'top-left': |
1295 |
| - hint.style.left = offset.left + 'px'; |
1296 |
| - hint.style.top = offset.top + 'px'; |
1297 |
| - break; |
1298 |
| - case 'top-right': |
1299 |
| - hint.style.left = (offset.left + offset.width) + 'px'; |
1300 |
| - hint.style.top = offset.top + 'px'; |
1301 |
| - break; |
1302 |
| - case 'bottom-left': |
1303 |
| - hint.style.left = offset.left + 'px'; |
1304 |
| - hint.style.top = (offset.top + offset.height) + 'px'; |
1305 |
| - break; |
1306 |
| - case 'bottom-right': |
1307 |
| - hint.style.left = (offset.left + offset.width) + 'px'; |
1308 |
| - hint.style.top = (offset.top + offset.height) + 'px'; |
1309 |
| - break; |
1310 |
| - case 'bottom-middle': |
1311 |
| - hint.style.left = (offset.left + (offset.width / 2)) + 'px'; |
1312 |
| - hint.style.top = (offset.top + offset.height) + 'px'; |
1313 |
| - break; |
1314 |
| - case 'top-middle': |
1315 |
| - hint.style.left = (offset.left + (offset.width / 2)) + 'px'; |
1316 |
| - hint.style.top = offset.top + 'px'; |
1317 |
| - break; |
1318 |
| - } |
| 1353 | + // align the hint position |
| 1354 | + _alignHintPosition.call(this, item.hintPosition, hint, item.targetElement); |
1319 | 1355 |
|
1320 | 1356 | hintsWrapper.appendChild(hint);
|
1321 | 1357 | }
|
1322 | 1358 |
|
1323 | 1359 | // adding the hints wrapper
|
1324 | 1360 | document.body.appendChild(hintsWrapper);
|
| 1361 | + |
| 1362 | + // call the callback function (if any) |
| 1363 | + if (typeof (this._hintsAddedCallback) !== 'undefined') { |
| 1364 | + this._hintsAddedCallback.call(this); |
| 1365 | + } |
| 1366 | + }; |
| 1367 | + |
| 1368 | + /** |
| 1369 | + * Aligns hint position |
| 1370 | + * |
| 1371 | + * @api private |
| 1372 | + * @method _alignHintPosition |
| 1373 | + * @param {String} position |
| 1374 | + * @param {Object} hint |
| 1375 | + * @param {Object} element |
| 1376 | + */ |
| 1377 | + function _alignHintPosition(position, hint, element) { |
| 1378 | + // get/calculate offset of target element |
| 1379 | + var offset = _getOffset.call(this, element); |
| 1380 | + |
| 1381 | + // align the hint element |
| 1382 | + switch (position) { |
| 1383 | + default: |
| 1384 | + case 'top-left': |
| 1385 | + hint.style.left = offset.left + 'px'; |
| 1386 | + hint.style.top = offset.top + 'px'; |
| 1387 | + break; |
| 1388 | + case 'top-right': |
| 1389 | + hint.style.left = (offset.left + offset.width) + 'px'; |
| 1390 | + hint.style.top = offset.top + 'px'; |
| 1391 | + break; |
| 1392 | + case 'bottom-left': |
| 1393 | + hint.style.left = offset.left + 'px'; |
| 1394 | + hint.style.top = (offset.top + offset.height) + 'px'; |
| 1395 | + break; |
| 1396 | + case 'bottom-right': |
| 1397 | + hint.style.left = (offset.left + offset.width) + 'px'; |
| 1398 | + hint.style.top = (offset.top + offset.height) + 'px'; |
| 1399 | + break; |
| 1400 | + case 'bottom-middle': |
| 1401 | + hint.style.left = (offset.left + (offset.width / 2)) + 'px'; |
| 1402 | + hint.style.top = (offset.top + offset.height) + 'px'; |
| 1403 | + break; |
| 1404 | + case 'top-middle': |
| 1405 | + hint.style.left = (offset.left + (offset.width / 2)) + 'px'; |
| 1406 | + hint.style.top = offset.top + 'px'; |
| 1407 | + break; |
| 1408 | + } |
1325 | 1409 | };
|
1326 | 1410 |
|
1327 | 1411 | /**
|
|
1334 | 1418 | * @param {Number} stepId
|
1335 | 1419 | */
|
1336 | 1420 | function _hintClick(hintElement, item, stepId) {
|
| 1421 | + // call the callback function (if any) |
| 1422 | + if (typeof (this._hintClickCallback) !== 'undefined') { |
| 1423 | + this._hintClickCallback.call(this, hintElement, item, stepId); |
| 1424 | + } |
| 1425 | + |
1337 | 1426 | // remove all open tooltips
|
1338 | 1427 | var removedStep = _removeHintTooltip.call(this);
|
1339 | 1428 |
|
|
1368 | 1457 | var closeButton = document.createElement('a');
|
1369 | 1458 | closeButton.className = 'introjs-button';
|
1370 | 1459 | closeButton.innerHTML = this._options.hintButtonLabel;
|
1371 |
| - closeButton.onclick = _removeHint.bind(this, stepId); |
| 1460 | + closeButton.onclick = _hideHint.bind(this, stepId); |
1372 | 1461 |
|
1373 | 1462 | tooltipTextLayer.appendChild(tooltipWrapper);
|
1374 | 1463 | tooltipTextLayer.appendChild(closeButton);
|
|
1568 | 1657 | }
|
1569 | 1658 | return this;
|
1570 | 1659 | },
|
| 1660 | + onhintclose: function(providedCallback) { |
| 1661 | + if (typeof (providedCallback) === 'function') { |
| 1662 | + this._hintCloseCallback = providedCallback; |
| 1663 | + } else { |
| 1664 | + throw new Error('Provided callback for onhintclose was not a function.'); |
| 1665 | + } |
| 1666 | + return this; |
| 1667 | + }, |
1571 | 1668 | onhintremove: function(providedCallback) {
|
1572 | 1669 | if (typeof (providedCallback) === 'function') {
|
1573 | 1670 | this._hintRemoveCallback = providedCallback;
|
|
0 commit comments