bootstrap-tour.js 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. /* ========================================================================
  2. * bootstrap-tour - v0.10.3
  3. * http://bootstraptour.com
  4. * ========================================================================
  5. * Copyright 2012-2015 Ulrich Sossou
  6. *
  7. * ========================================================================
  8. * Licensed under the MIT License (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * https://opensource.org/licenses/MIT
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. * ========================================================================
  20. */
  21. (function (window, factory) {
  22. if (typeof define === 'function' && define.amd) {
  23. return define(['jquery'], function (jQuery) {
  24. return window.Tour = factory(jQuery);
  25. });
  26. } else if (typeof exports === 'object') {
  27. return module.exports = factory(require('jQuery'));
  28. } else {
  29. return window.Tour = factory(window.jQuery);
  30. }
  31. })(window, function ($) {
  32. var Tour, document;
  33. document = window.document;
  34. Tour = (function () {
  35. function Tour(options) {
  36. var storage;
  37. try {
  38. storage = window.localStorage;
  39. } catch (_error) {
  40. storage = false;
  41. }
  42. this._options = $.extend({
  43. name: 'tour',
  44. steps: [],
  45. container: 'body',
  46. autoscroll: true,
  47. keyboard: true,
  48. storage: false,
  49. // storage: window.localStorage,
  50. debug: false,
  51. backdrop: false,
  52. backdropContainer: 'body',
  53. backdropPadding: 0,
  54. redirect: true,
  55. orphan: false,
  56. duration: false,
  57. delay: false,
  58. basePath: '',
  59. template: '<div class="popover" role="tooltip"> <div class="arrow"></div> <h3 class="popover-title"></h3> <div class="popover-content"></div> <div class="popover-navigation"> <div class="btn-group"> <button class="btn btn-sm btn-default btn-prev" data-role="prev">&laquo; 上一步</button> <button class="btn btn-sm btn-default btn-next" data-role="next">下一步 &raquo;</button> <button class="btn btn-sm btn-default" data-role="pause-resume" data-pause-text="Pause" data-resume-text="Resume">Pause</button> </div> <button class="btn btn-sm btn-default btn-end" data-role="end">关闭</button> </div> </div>',
  60. afterSetState: function (key, value) {
  61. },
  62. afterGetState: function (key, value) {
  63. },
  64. afterRemoveState: function (key) {
  65. },
  66. onStart: function (tour) {
  67. },
  68. onEnd: function (tour) {
  69. },
  70. onShow: function (tour) {
  71. },
  72. onShown: function (tour) {
  73. },
  74. onHide: function (tour) {
  75. },
  76. onHidden: function (tour) {
  77. },
  78. onNext: function (tour) {
  79. },
  80. onPrev: function (tour) {
  81. },
  82. onPause: function (tour, duration) {
  83. },
  84. onResume: function (tour, duration) {
  85. },
  86. onRedirectError: function (tour) {
  87. }
  88. }, options);
  89. this._force = false;
  90. this._inited = false;
  91. this._current = null;
  92. this.backdrop = {
  93. overlay: null,
  94. $element: null,
  95. $background: null,
  96. backgroundShown: false,
  97. overlayElementShown: false
  98. };
  99. this;
  100. }
  101. Tour.prototype.addSteps = function (steps) {
  102. var step, _i, _len;
  103. for (_i = 0, _len = steps.length; _i < _len; _i++) {
  104. step = steps[_i];
  105. this.addStep(step);
  106. }
  107. return this;
  108. };
  109. Tour.prototype.addStep = function (step) {
  110. this._options.steps.push(step);
  111. return this;
  112. };
  113. Tour.prototype.getStep = function (i) {
  114. if (this._options.steps[i] != null) {
  115. return $.extend({
  116. id: "step-" + i,
  117. path: '',
  118. host: '',
  119. placement: 'right',
  120. title: '',
  121. content: '<p></p>',
  122. next: i === this._options.steps.length - 1 ? -1 : i + 1,
  123. prev: i - 1,
  124. animation: true,
  125. container: this._options.container,
  126. autoscroll: this._options.autoscroll,
  127. backdrop: this._options.backdrop,
  128. backdropContainer: this._options.backdropContainer,
  129. backdropPadding: this._options.backdropPadding,
  130. redirect: this._options.redirect,
  131. reflexElement: this._options.steps[i].element,
  132. backdropElement: this._options.steps[i].element,
  133. orphan: this._options.orphan,
  134. duration: this._options.duration,
  135. delay: this._options.delay,
  136. template: this._options.template,
  137. onShow: this._options.onShow,
  138. onShown: this._options.onShown,
  139. onHide: this._options.onHide,
  140. onHidden: this._options.onHidden,
  141. onNext: this._options.onNext,
  142. onPrev: this._options.onPrev,
  143. onPause: this._options.onPause,
  144. onResume: this._options.onResume,
  145. onRedirectError: this._options.onRedirectError
  146. }, this._options.steps[i]);
  147. }
  148. };
  149. Tour.prototype.init = function (force) {
  150. this._force = force;
  151. if (this.ended()) {
  152. this._debug('Tour ended, init prevented.');
  153. return this;
  154. }
  155. this.setCurrentStep();
  156. this._initMouseNavigation();
  157. this._initKeyboardNavigation();
  158. this._onResize((function (_this) {
  159. return function () {
  160. return _this.showStep(_this._current);
  161. };
  162. })(this));
  163. if (this._current !== null) {
  164. this.showStep(this._current);
  165. }
  166. this._inited = true;
  167. return this;
  168. };
  169. Tour.prototype.start = function (force) {
  170. var promise;
  171. if (force == null) {
  172. force = false;
  173. }
  174. if (!this._inited) {
  175. this.init(force);
  176. }
  177. if (this._current === null) {
  178. promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);
  179. this._callOnPromiseDone(promise, this.showStep, 0);
  180. }
  181. return this;
  182. };
  183. Tour.prototype.next = function () {
  184. var promise;
  185. promise = this.hideStep(this._current, this._current + 1);
  186. return this._callOnPromiseDone(promise, this._showNextStep);
  187. };
  188. Tour.prototype.prev = function () {
  189. var promise;
  190. promise = this.hideStep(this._current, this._current - 1);
  191. return this._callOnPromiseDone(promise, this._showPrevStep);
  192. };
  193. Tour.prototype.goTo = function (i) {
  194. var promise;
  195. promise = this.hideStep(this._current, i);
  196. return this._callOnPromiseDone(promise, this.showStep, i);
  197. };
  198. Tour.prototype.end = function () {
  199. /*this.ended();*/
  200. var endHelper, promise;
  201. endHelper = (function (_this) {
  202. return function (e) {
  203. addcookie('gentle',1);
  204. $(document).off("click.tour-" + _this._options.name);
  205. $(document).off("keyup.tour-" + _this._options.name);
  206. $(window).off("resize.tour-" + _this._options.name);
  207. _this._setState('end', 'yes');
  208. _this._inited = false;
  209. _this._force = false;
  210. _this._clearTimer();
  211. if (_this._options.onEnd != null) {
  212. return _this._options.onEnd(_this);
  213. }
  214. };
  215. })(this);
  216. promise = this.hideStep(this._current);
  217. return this._callOnPromiseDone(promise, endHelper);
  218. };
  219. Tour.prototype.ended = function () {
  220. return !this._force && !!this._getState('end');
  221. };
  222. Tour.prototype.restart = function () {
  223. this._removeState('current_step');
  224. this._removeState('end');
  225. this._removeState('redirect_to');
  226. return this.start();
  227. };
  228. Tour.prototype.pause = function () {
  229. var step;
  230. step = this.getStep(this._current);
  231. if (!(step && step.duration)) {
  232. return this;
  233. }
  234. this._paused = true;
  235. this._duration -= new Date().getTime() - this._start;
  236. window.clearTimeout(this._timer);
  237. this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining).");
  238. if (step.onPause != null) {
  239. return step.onPause(this, this._duration);
  240. }
  241. };
  242. Tour.prototype.resume = function () {
  243. var step;
  244. step = this.getStep(this._current);
  245. if (!(step && step.duration)) {
  246. return this;
  247. }
  248. this._paused = false;
  249. this._start = new Date().getTime();
  250. this._duration = this._duration || step.duration;
  251. this._timer = window.setTimeout((function (_this) {
  252. return function () {
  253. if (_this._isLast()) {
  254. return _this.next();
  255. } else {
  256. return _this.end();
  257. }
  258. };
  259. })(this), this._duration);
  260. this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration);
  261. if ((step.onResume != null) && this._duration !== step.duration) {
  262. return step.onResume(this, this._duration);
  263. }
  264. };
  265. Tour.prototype.hideStep = function (i, iNext) {
  266. var hideDelay, hideStepHelper, promise, step;
  267. step = this.getStep(i);
  268. if (!step) {
  269. return;
  270. }
  271. this._clearTimer();
  272. promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);
  273. hideStepHelper = (function (_this) {
  274. return function (e) {
  275. var $element, next_step;
  276. $element = $(step.element);
  277. if (!($element.data('bs.popover') || $element.data('popover'))) {
  278. $element = $('body');
  279. }
  280. $element.popover('destroy').removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element").removeData('bs.popover').focus();
  281. if (step.reflex) {
  282. $(step.reflexElement).removeClass('tour-step-element-reflex').off("" + (_this._reflexEvent(step.reflex)) + ".tour-" + _this._options.name);
  283. }
  284. if (step.backdrop) {
  285. next_step = (iNext != null) && _this.getStep(iNext);
  286. if (!next_step || !next_step.backdrop || next_step.backdropElement !== step.backdropElement) {
  287. _this._hideBackdrop();
  288. }
  289. }
  290. if (step.onHidden != null) {
  291. return step.onHidden(_this);
  292. }
  293. };
  294. })(this);
  295. hideDelay = step.delay.hide || step.delay;
  296. if ({}.toString.call(hideDelay) === '[object Number]' && hideDelay > 0) {
  297. this._debug("Wait " + hideDelay + " milliseconds to hide the step " + (this._current + 1));
  298. window.setTimeout((function (_this) {
  299. return function () {
  300. return _this._callOnPromiseDone(promise, hideStepHelper);
  301. };
  302. })(this), hideDelay);
  303. } else {
  304. this._callOnPromiseDone(promise, hideStepHelper);
  305. }
  306. return promise;
  307. };
  308. Tour.prototype.showStep = function (i) {
  309. var path, promise, showDelay, showStepHelper, skipToPrevious, step;
  310. if (this.ended()) {
  311. this._debug('Tour ended, showStep prevented.');
  312. return this;
  313. }
  314. step = this.getStep(i);
  315. if (!step) {
  316. return;
  317. }
  318. skipToPrevious = i < this._current;
  319. promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);
  320. this.setCurrentStep(i);
  321. path = (function () {
  322. switch ({}.toString.call(step.path)) {
  323. case '[object Function]':
  324. return step.path();
  325. case '[object String]':
  326. return this._options.basePath + step.path;
  327. default:
  328. return step.path;
  329. }
  330. }).call(this);
  331. if (step.redirect && this._isRedirect(step.host, path, document.location)) {
  332. this._redirect(step, i, path);
  333. if (!this._isJustPathHashDifferent(step.host, path, document.location)) {
  334. return;
  335. }
  336. }
  337. showStepHelper = (function (_this) {
  338. return function (e) {
  339. var showPopoverAndOverlay;
  340. if (_this._isOrphan(step)) {
  341. if (step.orphan === false) {
  342. _this._debug("Skip the orphan step " + (_this._current + 1) + ".\nOrphan option is false and the element does not exist or is hidden.");
  343. if (skipToPrevious) {
  344. _this._showPrevStep();
  345. } else {
  346. _this._showNextStep();
  347. }
  348. return;
  349. }
  350. _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true.");
  351. }
  352. if (step.backdrop) {
  353. _this._showBackdrop(step);
  354. }
  355. showPopoverAndOverlay = function () {
  356. if (_this.getCurrentStep() !== i || _this.ended()) {
  357. return;
  358. }
  359. if ((step.element != null) && step.backdrop) {
  360. _this._showOverlayElement(step, true);
  361. }
  362. _this._showPopover(step, i);
  363. if (step.onShown != null) {
  364. step.onShown(_this);
  365. }
  366. return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length);
  367. };
  368. if (step.autoscroll) {
  369. _this._scrollIntoView(step, showPopoverAndOverlay);
  370. } else {
  371. showPopoverAndOverlay();
  372. }
  373. if (step.duration) {
  374. return _this.resume();
  375. }
  376. };
  377. })(this);
  378. showDelay = step.delay.show || step.delay;
  379. if ({}.toString.call(showDelay) === '[object Number]' && showDelay > 0) {
  380. this._debug("Wait " + showDelay + " milliseconds to show the step " + (this._current + 1));
  381. window.setTimeout((function (_this) {
  382. return function () {
  383. return _this._callOnPromiseDone(promise, showStepHelper);
  384. };
  385. })(this), showDelay);
  386. } else {
  387. this._callOnPromiseDone(promise, showStepHelper);
  388. }
  389. return promise;
  390. };
  391. Tour.prototype.getCurrentStep = function () {
  392. return this._current;
  393. };
  394. Tour.prototype.setCurrentStep = function (value) {
  395. if (value != null) {
  396. this._current = value;
  397. this._setState('current_step', value);
  398. } else {
  399. this._current = this._getState('current_step');
  400. this._current = this._current === null ? null : parseInt(this._current, 10);
  401. }
  402. return this;
  403. };
  404. Tour.prototype.redraw = function () {
  405. return this._showOverlayElement(this.getStep(this.getCurrentStep()).element, true);
  406. };
  407. Tour.prototype._setState = function (key, value) {
  408. var e, keyName;
  409. if (this._options.storage) {
  410. keyName = "" + this._options.name + "_" + key;
  411. try {
  412. this._options.storage.setItem(keyName, value);
  413. } catch (_error) {
  414. e = _error;
  415. if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {
  416. this._debug('LocalStorage quota exceeded. State storage failed.');
  417. }
  418. }
  419. return this._options.afterSetState(keyName, value);
  420. } else {
  421. if (this._state == null) {
  422. this._state = {};
  423. }
  424. return this._state[key] = value;
  425. }
  426. };
  427. Tour.prototype._removeState = function (key) {
  428. var keyName;
  429. if (this._options.storage) {
  430. keyName = "" + this._options.name + "_" + key;
  431. this._options.storage.removeItem(keyName);
  432. return this._options.afterRemoveState(keyName);
  433. } else {
  434. if (this._state != null) {
  435. return delete this._state[key];
  436. }
  437. }
  438. };
  439. Tour.prototype._getState = function (key) {
  440. var keyName, value;
  441. if (this._options.storage) {
  442. keyName = "" + this._options.name + "_" + key;
  443. value = this._options.storage.getItem(keyName);
  444. } else {
  445. if (this._state != null) {
  446. value = this._state[key];
  447. }
  448. }
  449. if (value === void 0 || value === 'null') {
  450. value = null;
  451. }
  452. this._options.afterGetState(key, value);
  453. return value;
  454. };
  455. Tour.prototype._showNextStep = function () {
  456. var promise, showNextStepHelper, step;
  457. step = this.getStep(this._current);
  458. showNextStepHelper = (function (_this) {
  459. return function (e) {
  460. return _this.showStep(step.next);
  461. };
  462. })(this);
  463. promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);
  464. return this._callOnPromiseDone(promise, showNextStepHelper);
  465. };
  466. Tour.prototype._showPrevStep = function () {
  467. var promise, showPrevStepHelper, step;
  468. step = this.getStep(this._current);
  469. showPrevStepHelper = (function (_this) {
  470. return function (e) {
  471. return _this.showStep(step.prev);
  472. };
  473. })(this);
  474. promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);
  475. return this._callOnPromiseDone(promise, showPrevStepHelper);
  476. };
  477. Tour.prototype._debug = function (text) {
  478. if (this._options.debug) {
  479. return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text);
  480. }
  481. };
  482. Tour.prototype._isRedirect = function (host, path, location) {
  483. var currentPath;
  484. if ((host != null) && host !== '' && (({}.toString.call(host) === '[object RegExp]' && !host.test(location.origin)) || ({}.toString.call(host) === '[object String]' && this._isHostDifferent(host, location)))) {
  485. return true;
  486. }
  487. currentPath = [location.pathname, location.search, location.hash].join('');
  488. return (path != null) && path !== '' && (({}.toString.call(path) === '[object RegExp]' && !path.test(currentPath)) || ({}.toString.call(path) === '[object String]' && this._isPathDifferent(path, currentPath)));
  489. };
  490. Tour.prototype._isHostDifferent = function (host, location) {
  491. switch ({}.toString.call(host)) {
  492. case '[object RegExp]':
  493. return !host.test(location.origin);
  494. case '[object String]':
  495. return this._getProtocol(host) !== this._getProtocol(location.href) || this._getHost(host) !== this._getHost(location.href);
  496. default:
  497. return true;
  498. }
  499. };
  500. Tour.prototype._isPathDifferent = function (path, currentPath) {
  501. return this._getPath(path) !== this._getPath(currentPath) || !this._equal(this._getQuery(path), this._getQuery(currentPath)) || !this._equal(this._getHash(path), this._getHash(currentPath));
  502. };
  503. Tour.prototype._isJustPathHashDifferent = function (host, path, location) {
  504. var currentPath;
  505. if ((host != null) && host !== '') {
  506. if (this._isHostDifferent(host, location)) {
  507. return false;
  508. }
  509. }
  510. currentPath = [location.pathname, location.search, location.hash].join('');
  511. if ({}.toString.call(path) === '[object String]') {
  512. return this._getPath(path) === this._getPath(currentPath) && this._equal(this._getQuery(path), this._getQuery(currentPath)) && !this._equal(this._getHash(path), this._getHash(currentPath));
  513. }
  514. return false;
  515. };
  516. Tour.prototype._redirect = function (step, i, path) {
  517. var href;
  518. if ($.isFunction(step.redirect)) {
  519. return step.redirect.call(this, path);
  520. } else {
  521. href = {}.toString.call(step.host) === '[object String]' ? "" + step.host + path : path;
  522. this._debug("Redirect to " + href);
  523. if (this._getState('redirect_to') === ("" + i)) {
  524. this._debug("Error redirection loop to " + path);
  525. this._removeState('redirect_to');
  526. if (step.onRedirectError != null) {
  527. return step.onRedirectError(this);
  528. }
  529. } else {
  530. this._setState('redirect_to', "" + i);
  531. return document.location.href = href;
  532. }
  533. }
  534. };
  535. Tour.prototype._isOrphan = function (step) {
  536. return (step.element == null) || !$(step.element).length || $(step.element).is(':hidden') && ($(step.element)[0].namespaceURI !== 'http://www.w3.org/2000/svg');
  537. };
  538. Tour.prototype._isLast = function () {
  539. return this._current < this._options.steps.length - 1;
  540. };
  541. Tour.prototype._showPopover = function (step, i) {
  542. var $element, $tip, isOrphan, options, shouldAddSmart;
  543. $(".tour-" + this._options.name).remove();
  544. options = $.extend({}, this._options);
  545. isOrphan = this._isOrphan(step);
  546. step.template = this._template(step, i);
  547. if (isOrphan) {
  548. step.element = 'body';
  549. step.placement = 'top';
  550. }
  551. $element = $(step.element);
  552. $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element");
  553. if (step.options) {
  554. $.extend(options, step.options);
  555. }
  556. if (step.reflex && !isOrphan) {
  557. $(step.reflexElement).addClass('tour-step-element-reflex').off("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name).on("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name, (function (_this) {
  558. return function () {
  559. if (_this._isLast()) {
  560. return _this.next();
  561. } else {
  562. return _this.end();
  563. }
  564. };
  565. })(this));
  566. }
  567. shouldAddSmart = step.smartPlacement === true && step.placement.search(/auto/i) === -1;
  568. $element.popover({
  569. placement: shouldAddSmart ? "auto " + step.placement : step.placement,
  570. trigger: 'manual',
  571. title: step.title,
  572. content: step.content,
  573. html: true,
  574. animation: step.animation,
  575. container: step.container,
  576. template: step.template,
  577. selector: step.element
  578. }).popover('show');
  579. $tip = $element.data('bs.popover') ? $element.data('bs.popover').tip() : $element.data('popover').tip();
  580. $tip.attr('id', step.id);
  581. this._focus($tip, $element, step.next < 0);
  582. this._reposition($tip, step);
  583. if (isOrphan) {
  584. return this._center($tip);
  585. }
  586. };
  587. Tour.prototype._template = function (step, i) {
  588. var $navigation, $next, $prev, $resume, $template, template;
  589. template = step.template;
  590. if (this._isOrphan(step) && {}.toString.call(step.orphan) !== '[object Boolean]') {
  591. template = step.orphan;
  592. }
  593. $template = $.isFunction(template) ? $(template(i, step)) : $(template);
  594. $navigation = $template.find('.popover-navigation');
  595. $prev = $navigation.find('[data-role="prev"]');
  596. $next = $navigation.find('[data-role="next"]');
  597. $resume = $navigation.find('[data-role="pause-resume"]');
  598. if (this._isOrphan(step)) {
  599. $template.addClass('orphan');
  600. }
  601. $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i);
  602. if (step.reflex) {
  603. $template.addClass("tour-" + this._options.name + "-reflex");
  604. }
  605. if (step.prev < 0) {
  606. $prev.addClass('disabled').prop('disabled', true).prop('tabindex', -1);
  607. }
  608. if (step.next < 0) {
  609. $next.addClass('disabled').prop('disabled', true).prop('tabindex', -1);
  610. }
  611. if (!step.duration) {
  612. $resume.remove();
  613. }
  614. return $template.clone().wrap('<div>').parent().html();
  615. };
  616. Tour.prototype._reflexEvent = function (reflex) {
  617. if ({}.toString.call(reflex) === '[object Boolean]') {
  618. return 'click';
  619. } else {
  620. return reflex;
  621. }
  622. };
  623. Tour.prototype._focus = function ($tip, $element, end) {
  624. var $next, role;
  625. role = end ? 'end' : 'next';
  626. $next = $tip.find("[data-role='" + role + "']");
  627. return $element.on('shown.bs.popover', function () {
  628. return $next.focus();
  629. });
  630. };
  631. Tour.prototype._reposition = function ($tip, step) {
  632. var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
  633. offsetWidth = $tip[0].offsetWidth;
  634. offsetHeight = $tip[0].offsetHeight;
  635. tipOffset = $tip.offset();
  636. originalLeft = tipOffset.left;
  637. originalTop = tipOffset.top;
  638. offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
  639. if (offsetBottom < 0) {
  640. tipOffset.top = tipOffset.top + offsetBottom;
  641. }
  642. offsetRight = $('html').outerWidth() - tipOffset.left - $tip.outerWidth();
  643. if (offsetRight < 0) {
  644. tipOffset.left = tipOffset.left + offsetRight;
  645. }
  646. if (tipOffset.top < 0) {
  647. tipOffset.top = 0;
  648. }
  649. if (tipOffset.left < 0) {
  650. tipOffset.left = 0;
  651. }
  652. $tip.offset(tipOffset);
  653. if (step.placement === 'bottom' || step.placement === 'top') {
  654. if (originalLeft !== tipOffset.left) {
  655. return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, 'left');
  656. }
  657. } else {
  658. if (originalTop !== tipOffset.top) {
  659. return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, 'top');
  660. }
  661. }
  662. };
  663. Tour.prototype._center = function ($tip) {
  664. return $tip.css('top', $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
  665. };
  666. Tour.prototype._replaceArrow = function ($tip, delta, dimension, position) {
  667. return $tip.find('.arrow').css(position, delta ? 50 * (1 - delta / dimension) + '%' : '');
  668. };
  669. Tour.prototype._scrollIntoView = function (step, callback) {
  670. var $element, $window, counter, height, offsetTop, scrollTop, windowHeight;
  671. $element = $(step.element);
  672. if (!$element.length) {
  673. return callback();
  674. }
  675. $window = $(window);
  676. offsetTop = $element.offset().top;
  677. height = $element.outerHeight();
  678. windowHeight = $window.height();
  679. scrollTop = 0;
  680. switch (step.placement) {
  681. case 'top':
  682. scrollTop = Math.max(0, offsetTop - (windowHeight / 2));
  683. break;
  684. case 'left':
  685. case 'right':
  686. scrollTop = Math.max(0, (offsetTop + height / 2) - (windowHeight / 2));
  687. break;
  688. case 'bottom':
  689. scrollTop = Math.max(0, (offsetTop + height) - (windowHeight / 2));
  690. }
  691. this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + ".");
  692. counter = 0;
  693. return $('body, html').stop(true, true).animate({
  694. scrollTop: Math.ceil(scrollTop)
  695. }, (function (_this) {
  696. return function () {
  697. if (++counter === 2) {
  698. callback();
  699. return _this._debug("Scroll into view.\nAnimation end element offset: " + ($element.offset().top) + ".\nWindow height: " + ($window.height()) + ".");
  700. }
  701. };
  702. })(this));
  703. };
  704. Tour.prototype._onResize = function (callback, timeout) {
  705. return $(window).on("resize.tour-" + this._options.name, function () {
  706. clearTimeout(timeout);
  707. return timeout = setTimeout(callback, 100);
  708. });
  709. };
  710. Tour.prototype._initMouseNavigation = function () {
  711. var _this;
  712. _this = this;
  713. return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']", (function (_this) {
  714. return function (e) {
  715. e.preventDefault();
  716. return _this.next();
  717. };
  718. })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']", (function (_this) {
  719. return function (e) {
  720. e.preventDefault();
  721. if (_this._current > 0) {
  722. return _this.prev();
  723. }
  724. };
  725. })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function (_this) {
  726. return function (e) {
  727. e.preventDefault();
  728. return _this.end();
  729. };
  730. })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function (e) {
  731. var $this;
  732. e.preventDefault();
  733. $this = $(this);
  734. $this.text(_this._paused ? $this.data('pause-text') : $this.data('resume-text'));
  735. if (_this._paused) {
  736. return _this.resume();
  737. } else {
  738. return _this.pause();
  739. }
  740. });
  741. };
  742. Tour.prototype._initKeyboardNavigation = function () {
  743. if (!this._options.keyboard) {
  744. return;
  745. }
  746. return $(document).on("keyup.tour-" + this._options.name, (function (_this) {
  747. return function (e) {
  748. if (!e.which) {
  749. return;
  750. }
  751. switch (e.which) {
  752. case 39:
  753. e.preventDefault();
  754. if (_this._isLast()) {
  755. return _this.next();
  756. } else {
  757. return _this.end();
  758. }
  759. break;
  760. case 37:
  761. e.preventDefault();
  762. if (_this._current > 0) {
  763. return _this.prev();
  764. }
  765. }
  766. };
  767. })(this));
  768. };
  769. Tour.prototype._makePromise = function (result) {
  770. if (result && $.isFunction(result.then)) {
  771. return result;
  772. } else {
  773. return null;
  774. }
  775. };
  776. Tour.prototype._callOnPromiseDone = function (promise, cb, arg) {
  777. if (promise) {
  778. return promise.then((function (_this) {
  779. return function (e) {
  780. return cb.call(_this, arg);
  781. };
  782. })(this));
  783. } else {
  784. return cb.call(this, arg);
  785. }
  786. };
  787. Tour.prototype._showBackdrop = function (step) {
  788. if (this.backdrop.backgroundShown) {
  789. return;
  790. }
  791. this.backdrop = $('<div>', {
  792. "class": 'tour-backdrop'
  793. });
  794. this.backdrop.backgroundShown = true;
  795. return $(step.backdropContainer).append(this.backdrop);
  796. };
  797. Tour.prototype._hideBackdrop = function () {
  798. this._hideOverlayElement();
  799. return this._hideBackground();
  800. };
  801. Tour.prototype._hideBackground = function () {
  802. if (this.backdrop && this.backdrop.remove) {
  803. this.backdrop.remove();
  804. this.backdrop.overlay = null;
  805. return this.backdrop.backgroundShown = false;
  806. }
  807. };
  808. Tour.prototype._showOverlayElement = function (step, force) {
  809. var $backdropElement, $element, elementData;
  810. $element = $(step.element);
  811. $backdropElement = $(step.backdropElement);
  812. if (!$element || $element.length === 0 || this.backdrop.overlayElementShown && !force) {
  813. return;
  814. }
  815. if (!this.backdrop.overlayElementShown) {
  816. this.backdrop.$element = $backdropElement.addClass('tour-step-backdrop');
  817. this.backdrop.$background = $('<div>', {
  818. "class": 'tour-step-background'
  819. });
  820. this.backdrop.$background.appendTo(step.backdropContainer);
  821. this.backdrop.overlayElementShown = true;
  822. }
  823. elementData = {
  824. width: $backdropElement.outerWidth(true),
  825. height: $backdropElement.outerHeight(true),
  826. /*
  827. width: $backdropElement.innerWidth(),
  828. height: $backdropElement.innerHeight(),
  829. */
  830. offset: $backdropElement.offset()
  831. };
  832. if (step.backdropPadding) {
  833. elementData = this._applyBackdropPadding(step.backdropPadding, elementData);
  834. }
  835. return this.backdrop.$background.outerWidth(elementData.width).outerHeight(elementData.height).offset(elementData.offset);
  836. };
  837. Tour.prototype._hideOverlayElement = function () {
  838. if (!this.backdrop.overlayElementShown) {
  839. return;
  840. }
  841. this.backdrop.$element.removeClass('tour-step-backdrop');
  842. this.backdrop.$background.remove();
  843. this.backdrop.$element = null;
  844. this.backdrop.$background = null;
  845. return this.backdrop.overlayElementShown = false;
  846. };
  847. Tour.prototype._applyBackdropPadding = function (padding, data) {
  848. if (typeof padding === 'object') {
  849. if (padding.top == null) {
  850. padding.top = 0;
  851. }
  852. if (padding.right == null) {
  853. padding.right = 0;
  854. }
  855. if (padding.bottom == null) {
  856. padding.bottom = 0;
  857. }
  858. if (padding.left == null) {
  859. padding.left = 0;
  860. }
  861. data.offset.top = data.offset.top - padding.top;
  862. data.offset.left = data.offset.left - padding.left;
  863. data.width = data.width + padding.left + padding.right;
  864. data.height = data.height + padding.top + padding.bottom;
  865. } else {
  866. data.offset.top = data.offset.top - padding;
  867. data.offset.left = data.offset.left - padding;
  868. data.width = data.width + (padding * 2);
  869. data.height = data.height + (padding * 2);
  870. }
  871. return data;
  872. };
  873. Tour.prototype._clearTimer = function () {
  874. window.clearTimeout(this._timer);
  875. this._timer = null;
  876. return this._duration = null;
  877. };
  878. Tour.prototype._getProtocol = function (url) {
  879. url = url.split('://');
  880. if (url.length > 1) {
  881. return url[0];
  882. } else {
  883. return 'http';
  884. }
  885. };
  886. Tour.prototype._getHost = function (url) {
  887. url = url.split('//');
  888. url = url.length > 1 ? url[1] : url[0];
  889. return url.split('/')[0];
  890. };
  891. Tour.prototype._getPath = function (path) {
  892. return path.replace(/\/?$/, '').split('?')[0].split('#')[0];
  893. };
  894. Tour.prototype._getQuery = function (path) {
  895. return this._getParams(path, '?');
  896. };
  897. Tour.prototype._getHash = function (path) {
  898. return this._getParams(path, '#');
  899. };
  900. Tour.prototype._getParams = function (path, start) {
  901. var param, params, paramsObject, _i, _len;
  902. params = path.split(start);
  903. if (params.length === 1) {
  904. return {};
  905. }
  906. params = params[1].split('&');
  907. paramsObject = {};
  908. for (_i = 0, _len = params.length; _i < _len; _i++) {
  909. param = params[_i];
  910. param = param.split('=');
  911. paramsObject[param[0]] = param[1] || '';
  912. }
  913. return paramsObject;
  914. };
  915. Tour.prototype._equal = function (obj1, obj2) {
  916. var k, obj1Keys, obj2Keys, v, _i, _len;
  917. if ({}.toString.call(obj1) === '[object Object]' && {}.toString.call(obj2) === '[object Object]') {
  918. obj1Keys = Object.keys(obj1);
  919. obj2Keys = Object.keys(obj2);
  920. if (obj1Keys.length !== obj2Keys.length) {
  921. return false;
  922. }
  923. for (k in obj1) {
  924. v = obj1[k];
  925. if (!this._equal(obj2[k], v)) {
  926. return false;
  927. }
  928. }
  929. return true;
  930. } else if ({}.toString.call(obj1) === '[object Array]' && {}.toString.call(obj2) === '[object Array]') {
  931. if (obj1.length !== obj2.length) {
  932. return false;
  933. }
  934. for (k = _i = 0, _len = obj1.length; _i < _len; k = ++_i) {
  935. v = obj1[k];
  936. if (!this._equal(v, obj2[k])) {
  937. return false;
  938. }
  939. }
  940. return true;
  941. } else {
  942. return obj1 === obj2;
  943. }
  944. };
  945. return Tour;
  946. })();
  947. return Tour;
  948. });
  949. var gentle = getcookie('gentle');
  950. function addcookie(name,value,expireHours){
  951. var cookieString=name+"="+escape(value)+"; path=/";
  952. //判断是否设置过期时间 不设置过期时间则关闭浏览器后cookie失效
  953. if(expireHours>0){
  954. var date=new Date();
  955. date.setTime(date.getTime+expireHours*1*1000);
  956. cookieString=cookieString+"; expire="+date.toGMTString();
  957. }
  958. document.cookie=cookieString;
  959. }
  960. function getcookie(name){
  961. var strcookie=document.cookie;
  962. var arrcookie=strcookie.split("; ");
  963. for(var i=0;i<arrcookie.length;i++){
  964. var arr=arrcookie[i].split("=");
  965. if(arr[0]==name)return arr[1];
  966. }
  967. return "";
  968. }
  969. function delCookie(name){
  970. //删除cookie
  971. var exp = new Date();
  972. exp.setTime(exp.getTime() - 1);
  973. var cval=getcookie(name);
  974. if(cval!=null) document.cookie= name + "="+cval+"; path=/;expires="+exp.toGMTString();
  975. }