|
28 | 28 | */
|
29 | 29 | function IntroJs(obj) {
|
30 | 30 | this._targetElement = obj;
|
| 31 | + this._introItems = []; |
31 | 32 |
|
32 | 33 | this._options = {
|
33 | 34 | /* Next button label in tooltip box */
|
|
65 | 66 | /* Precedence of positions, when auto is enabled */
|
66 | 67 | positionPrecedence: ["bottom", "top", "right", "left"],
|
67 | 68 | /* Disable an interaction with element? */
|
68 |
| - disableInteraction: false |
| 69 | + disableInteraction: false, |
| 70 | + /* Default hint position */ |
| 71 | + hintPosition: 'top', |
| 72 | + /* Hint button label */ |
| 73 | + hintButtonLabel: 'Got it', |
69 | 74 | };
|
70 | 75 | }
|
71 | 76 |
|
|
694 | 699 | * @api private
|
695 | 700 | * @method _disableInteraction
|
696 | 701 | */
|
697 |
| - function _disableInteraction () { |
| 702 | + function _disableInteraction() { |
698 | 703 | var disableInteractionLayer = document.querySelector('.introjs-disableInteraction');
|
699 | 704 | if (disableInteractionLayer === null) {
|
700 | 705 | disableInteractionLayer = document.createElement('div');
|
|
1132 | 1137 | }, 10);
|
1133 | 1138 |
|
1134 | 1139 | return true;
|
1135 |
| - } |
| 1140 | + }; |
| 1141 | + |
| 1142 | + |
| 1143 | + /** |
| 1144 | + * Start parsing hint items |
| 1145 | + * |
| 1146 | + * @api private |
| 1147 | + * @param {Object} targetElm |
| 1148 | + * @method _startHint |
| 1149 | + */ |
| 1150 | + function _populateHints(targetElm) { |
| 1151 | + var self = this; |
| 1152 | + |
| 1153 | + if (this._options.hints) { |
| 1154 | + for (var i = 0, l = this._options.hints.length; i < l; i++) { |
| 1155 | + var currentItem = _cloneObject(this._options.hints[i]); |
| 1156 | + |
| 1157 | + if (typeof(currentItem.element) === 'string') { |
| 1158 | + //grab the element with given selector from the page |
| 1159 | + currentItem.element = document.querySelector(currentItem.element); |
| 1160 | + } |
| 1161 | + |
| 1162 | + if (currentItem.element != null) { |
| 1163 | + this._introItems.push(currentItem); |
| 1164 | + } |
| 1165 | + } |
| 1166 | + } else { |
| 1167 | + var hints = targetElm.querySelectorAll('*[data-hint]'); |
| 1168 | + |
| 1169 | + if (hints.length < 1) { |
| 1170 | + return false; |
| 1171 | + } |
| 1172 | + |
| 1173 | + //first add intro items with data-step |
| 1174 | + for (var i = 0, l = hints.length; i < l; i++) { |
| 1175 | + var currentElement = hints[i]; |
| 1176 | + |
| 1177 | + this._introItems.push({ |
| 1178 | + element: currentElement, |
| 1179 | + hint: currentElement.getAttribute('data-hint'), |
| 1180 | + hintPosition: currentElement.getAttribute('data-hintPosition') || this._options.hintPosition, |
| 1181 | + position: currentElement.getAttribute('data-position') || this._options.tooltipPosition |
| 1182 | + }); |
| 1183 | + } |
| 1184 | + } |
| 1185 | + |
| 1186 | + _addHints.call(this); |
| 1187 | + }; |
| 1188 | + |
| 1189 | + /** |
| 1190 | + * Add all available hints to the page |
| 1191 | + * |
| 1192 | + * @api private |
| 1193 | + * @method _addHints |
| 1194 | + */ |
| 1195 | + function _addHints() { |
| 1196 | + var hintsWrapper = document.createElement('div'); |
| 1197 | + hintsWrapper.className = 'introjs-hints'; |
| 1198 | + |
| 1199 | + for (var i = 0, l = this._introItems.length; i < l; i++) { |
| 1200 | + var item = this._introItems[i]; |
| 1201 | + |
| 1202 | + var hint = document.createElement('a'); |
| 1203 | + hint.href = "javascript:void(0);"; |
| 1204 | + |
| 1205 | + // when user clicks on the hint element |
| 1206 | + hint.onclick = _hintClick.bind(this, hint, item); |
| 1207 | + |
| 1208 | + hint.className = 'introjs-hint'; |
| 1209 | + var hintDot = document.createElement('div'); |
| 1210 | + hintDot.className = 'introjs-hint-dot'; |
| 1211 | + var hintPulse = document.createElement('div'); |
| 1212 | + hintPulse.className = 'introjs-hint-pulse'; |
| 1213 | + |
| 1214 | + hint.appendChild(hintDot); |
| 1215 | + hint.appendChild(hintPulse); |
| 1216 | + hint.setAttribute('data-step', i); |
| 1217 | + |
| 1218 | + // get/calculate offset of target element |
| 1219 | + var offset = _getOffset.call(this, item.element); |
| 1220 | + |
| 1221 | + // we swap the hint element with target element |
| 1222 | + // because _setHelperLayerPosition uses `element` property |
| 1223 | + item.targetElement = item.element; |
| 1224 | + item.element = hint; |
| 1225 | + |
| 1226 | + // align the hint element |
| 1227 | + switch (item.hintPosition) { |
| 1228 | + default: |
| 1229 | + case 'top-left': |
| 1230 | + hint.style.left = offset.left + 'px'; |
| 1231 | + hint.style.top = offset.top + 'px'; |
| 1232 | + break; |
| 1233 | + case 'top-right': |
| 1234 | + hint.style.left = (offset.left + offset.width) + 'px'; |
| 1235 | + hint.style.top = offset.top + 'px'; |
| 1236 | + break; |
| 1237 | + case 'bottom-left': |
| 1238 | + hint.style.left = offset.left + 'px'; |
| 1239 | + hint.style.top = (offset.top + offset.height) + 'px'; |
| 1240 | + break; |
| 1241 | + case 'bottom-right': |
| 1242 | + hint.style.left = (offset.left + offset.width) + 'px'; |
| 1243 | + hint.style.top = (offset.top + offset.height) + 'px'; |
| 1244 | + break; |
| 1245 | + case 'bottom-middle': |
| 1246 | + hint.style.left = (offset.left + (offset.width / 2)) + 'px'; |
| 1247 | + hint.style.top = (offset.top + offset.height) + 'px'; |
| 1248 | + break; |
| 1249 | + case 'top-middle': |
| 1250 | + hint.style.left = (offset.left + (offset.width / 2)) + 'px'; |
| 1251 | + hint.style.top = offset.top + 'px'; |
| 1252 | + break; |
| 1253 | + } |
| 1254 | + |
| 1255 | + hintsWrapper.appendChild(hint); |
| 1256 | + } |
| 1257 | + |
| 1258 | + // adding the hints wrapper |
| 1259 | + document.body.appendChild(hintsWrapper); |
| 1260 | + }; |
| 1261 | + |
| 1262 | + /** |
| 1263 | + * Triggers when user clicks on the hint element |
| 1264 | + * |
| 1265 | + * @api private |
| 1266 | + * @method _hintClick |
| 1267 | + * @param {Object} hintElement |
| 1268 | + * @param {Object} item |
| 1269 | + */ |
| 1270 | + function _hintClick(hintElement, item) { |
| 1271 | + var tooltipLayer = document.createElement('div'); |
| 1272 | + var tooltipTextLayer = document.createElement('div'); |
| 1273 | + var arrowLayer = document.createElement('div'); |
| 1274 | + var referenceLayer = document.createElement('div'); |
| 1275 | + |
| 1276 | + tooltipLayer.className = 'introjs-tooltip'; |
| 1277 | + |
| 1278 | + tooltipTextLayer.className = 'introjs-tooltiptext'; |
| 1279 | + |
| 1280 | + var tooltipWrapper = document.createElement('p'); |
| 1281 | + tooltipWrapper.innerHTML = item.hint; |
| 1282 | + |
| 1283 | + var closeButton = document.createElement('a'); |
| 1284 | + closeButton.className = 'introjs-button'; |
| 1285 | + closeButton.innerHTML = this._options.hintButtonLabel; |
| 1286 | + |
| 1287 | + tooltipTextLayer.appendChild(tooltipWrapper); |
| 1288 | + tooltipTextLayer.appendChild(closeButton); |
| 1289 | + |
| 1290 | + arrowLayer.className = 'introjs-arrow'; |
| 1291 | + tooltipLayer.appendChild(arrowLayer); |
| 1292 | + |
| 1293 | + tooltipLayer.appendChild(tooltipTextLayer); |
| 1294 | + |
| 1295 | + // set current step for _placeTooltip function |
| 1296 | + this._currentStep = hintElement.getAttribute('data-step'); |
| 1297 | + |
| 1298 | + // align reference layer position |
| 1299 | + referenceLayer.className = 'introjs-tooltipReferenceLayer introjs-hintTooltip'; |
| 1300 | + referenceLayer.setAttribute('data-step', hintElement.getAttribute('data-step')); |
| 1301 | + _setHelperLayerPosition.call(this, referenceLayer); |
| 1302 | + |
| 1303 | + referenceLayer.appendChild(tooltipLayer); |
| 1304 | + document.body.appendChild(referenceLayer); |
| 1305 | + |
| 1306 | + //set proper position |
| 1307 | + _placeTooltip.call(this, hintElement, tooltipLayer, arrowLayer); |
| 1308 | + }; |
1136 | 1309 |
|
1137 | 1310 | /**
|
1138 | 1311 | * Get an element position on the page
|
|
1166 | 1339 | elementPosition.left = _x;
|
1167 | 1340 |
|
1168 | 1341 | return elementPosition;
|
1169 |
| - } |
| 1342 | + }; |
1170 | 1343 |
|
1171 | 1344 | /**
|
1172 | 1345 | * Gets the current progress percentage
|
|
1179 | 1352 | // Steps are 0 indexed
|
1180 | 1353 | var currentStep = parseInt((this._currentStep + 1), 10);
|
1181 | 1354 | return ((currentStep / this._introItems.length) * 100);
|
1182 |
| - } |
| 1355 | + }; |
1183 | 1356 |
|
1184 | 1357 | /**
|
1185 | 1358 | * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
|
|
1194 | 1367 | for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
|
1195 | 1368 | for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
|
1196 | 1369 | return obj3;
|
1197 |
| - } |
| 1370 | + }; |
1198 | 1371 |
|
1199 | 1372 | var introJs = function (targetElm) {
|
1200 | 1373 | if (typeof (targetElm) === 'object') {
|
|
1300 | 1473 | throw new Error('Provided callback for onexit was not a function.');
|
1301 | 1474 | }
|
1302 | 1475 | return this;
|
| 1476 | + }, |
| 1477 | + addHints: function() { |
| 1478 | + _populateHints.call(this, this._targetElement); |
| 1479 | + return this; |
1303 | 1480 | }
|
1304 | 1481 | };
|
1305 | 1482 |
|
|
0 commit comments