foundation.joyride.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. ;(function ($, window, document, undefined) {
  2. 'use strict';
  3. var Modernizr = Modernizr || false;
  4. Foundation.libs.joyride = {
  5. name : 'joyride',
  6. version : '5.2.2',
  7. defaults : {
  8. expose : false, // turn on or off the expose feature
  9. modal : true, // Whether to cover page with modal during the tour
  10. tip_location : 'bottom', // 'top' or 'bottom' in relation to parent
  11. nub_position : 'auto', // override on a per tooltip bases
  12. scroll_speed : 1500, // Page scrolling speed in milliseconds, 0 = no scroll animation
  13. scroll_animation : 'linear', // supports 'swing' and 'linear', extend with jQuery UI.
  14. timer : 0, // 0 = no timer , all other numbers = timer in milliseconds
  15. start_timer_on_click : true, // true or false - true requires clicking the first button start the timer
  16. start_offset : 0, // the index of the tooltip you want to start on (index of the li)
  17. next_button : true, // true or false to control whether a next button is used
  18. tip_animation : 'fade', // 'pop' or 'fade' in each tip
  19. pause_after : [], // array of indexes where to pause the tour after
  20. exposed : [], // array of expose elements
  21. tip_animation_fade_speed : 300, // when tipAnimation = 'fade' this is speed in milliseconds for the transition
  22. cookie_monster : false, // true or false to control whether cookies are used
  23. cookie_name : 'joyride', // Name the cookie you'll use
  24. cookie_domain : false, // Will this cookie be attached to a domain, ie. '.notableapp.com'
  25. cookie_expires : 365, // set when you would like the cookie to expire.
  26. tip_container : 'body', // Where will the tip be attached
  27. abort_on_close : true, // When true, the close event will not fire any callback
  28. tip_location_patterns : {
  29. top: ['bottom'],
  30. bottom: [], // bottom should not need to be repositioned
  31. left: ['right', 'top', 'bottom'],
  32. right: ['left', 'top', 'bottom']
  33. },
  34. post_ride_callback : function (){}, // A method to call once the tour closes (canceled or complete)
  35. post_step_callback : function (){}, // A method to call after each step
  36. pre_step_callback : function (){}, // A method to call before each step
  37. pre_ride_callback : function (){}, // A method to call before the tour starts (passed index, tip, and cloned exposed element)
  38. post_expose_callback : function (){}, // A method to call after an element has been exposed
  39. template : { // HTML segments for tip layout
  40. link : '<a href="#close" class="joyride-close-tip">&times;</a>',
  41. timer : '<div class="joyride-timer-indicator-wrap"><span class="joyride-timer-indicator"></span></div>',
  42. tip : '<div class="joyride-tip-guide"><span class="joyride-nub"></span></div>',
  43. wrapper : '<div class="joyride-content-wrapper"></div>',
  44. button : '<a href="#" class="small button joyride-next-tip"></a>',
  45. modal : '<div class="joyride-modal-bg"></div>',
  46. expose : '<div class="joyride-expose-wrapper"></div>',
  47. expose_cover: '<div class="joyride-expose-cover"></div>'
  48. },
  49. expose_add_class : '' // One or more space-separated class names to be added to exposed element
  50. },
  51. init : function (scope, method, options) {
  52. Foundation.inherit(this, 'throttle random_str');
  53. this.settings = this.settings || $.extend({}, this.defaults, (options || method));
  54. this.bindings(method, options)
  55. },
  56. events : function () {
  57. var self = this;
  58. $(this.scope)
  59. .off('.joyride')
  60. .on('click.fndtn.joyride', '.joyride-next-tip, .joyride-modal-bg', function (e) {
  61. e.preventDefault();
  62. if (this.settings.$li.next().length < 1) {
  63. this.end();
  64. } else if (this.settings.timer > 0) {
  65. clearTimeout(this.settings.automate);
  66. this.hide();
  67. this.show();
  68. this.startTimer();
  69. } else {
  70. this.hide();
  71. this.show();
  72. }
  73. }.bind(this))
  74. .on('click.fndtn.joyride', '.joyride-close-tip', function (e) {
  75. e.preventDefault();
  76. this.end(this.settings.abort_on_close);
  77. }.bind(this));
  78. $(window)
  79. .off('.joyride')
  80. .on('resize.fndtn.joyride', self.throttle(function () {
  81. if ($('[' + self.attr_name() + ']').length > 0 && self.settings.$next_tip) {
  82. if (self.settings.exposed.length > 0) {
  83. var $els = $(self.settings.exposed);
  84. $els.each(function () {
  85. var $this = $(this);
  86. self.un_expose($this);
  87. self.expose($this);
  88. });
  89. }
  90. if (self.is_phone()) {
  91. self.pos_phone();
  92. } else {
  93. self.pos_default(false, true);
  94. }
  95. }
  96. }, 100));
  97. },
  98. start : function () {
  99. var self = this,
  100. $this = $('[' + this.attr_name() + ']', this.scope),
  101. integer_settings = ['timer', 'scrollSpeed', 'startOffset', 'tipAnimationFadeSpeed', 'cookieExpires'],
  102. int_settings_count = integer_settings.length;
  103. if (!$this.length > 0) return;
  104. if (!this.settings.init) this.events();
  105. this.settings = $this.data(this.attr_name(true) + '-init');
  106. // non configureable settings
  107. this.settings.$content_el = $this;
  108. this.settings.$body = $(this.settings.tip_container);
  109. this.settings.body_offset = $(this.settings.tip_container).position();
  110. this.settings.$tip_content = this.settings.$content_el.find('> li');
  111. this.settings.paused = false;
  112. this.settings.attempts = 0;
  113. // can we create cookies?
  114. if (typeof $.cookie !== 'function') {
  115. this.settings.cookie_monster = false;
  116. }
  117. // generate the tips and insert into dom.
  118. if (!this.settings.cookie_monster || this.settings.cookie_monster && !$.cookie(this.settings.cookie_name)) {
  119. this.settings.$tip_content.each(function (index) {
  120. var $this = $(this);
  121. this.settings = $.extend({}, self.defaults, self.data_options($this))
  122. // Make sure that settings parsed from data_options are integers where necessary
  123. var i = int_settings_count;
  124. while (i--) {
  125. self.settings[integer_settings[i]] = parseInt(self.settings[integer_settings[i]], 10);
  126. }
  127. self.create({$li : $this, index : index});
  128. });
  129. // show first tip
  130. if (!this.settings.start_timer_on_click && this.settings.timer > 0) {
  131. this.show('init');
  132. this.startTimer();
  133. } else {
  134. this.show('init');
  135. }
  136. }
  137. },
  138. resume : function () {
  139. this.set_li();
  140. this.show();
  141. },
  142. tip_template : function (opts) {
  143. var $blank, content;
  144. opts.tip_class = opts.tip_class || '';
  145. $blank = $(this.settings.template.tip).addClass(opts.tip_class);
  146. content = $.trim($(opts.li).html()) +
  147. this.button_text(opts.button_text) +
  148. this.settings.template.link +
  149. this.timer_instance(opts.index);
  150. $blank.append($(this.settings.template.wrapper));
  151. $blank.first().attr(this.add_namespace('data-index'), opts.index);
  152. $('.joyride-content-wrapper', $blank).append(content);
  153. return $blank[0];
  154. },
  155. timer_instance : function (index) {
  156. var txt;
  157. if ((index === 0 && this.settings.start_timer_on_click && this.settings.timer > 0) || this.settings.timer === 0) {
  158. txt = '';
  159. } else {
  160. txt = $(this.settings.template.timer)[0].outerHTML;
  161. }
  162. return txt;
  163. },
  164. button_text : function (txt) {
  165. if (this.settings.next_button) {
  166. txt = $.trim(txt) || 'Next';
  167. txt = $(this.settings.template.button).append(txt)[0].outerHTML;
  168. } else {
  169. txt = '';
  170. }
  171. return txt;
  172. },
  173. create : function (opts) {
  174. var buttonText = opts.$li.attr(this.add_namespace('data-button'))
  175. || opts.$li.attr(this.add_namespace('data-text')),
  176. tipClass = opts.$li.attr('class'),
  177. $tip_content = $(this.tip_template({
  178. tip_class : tipClass,
  179. index : opts.index,
  180. button_text : buttonText,
  181. li : opts.$li
  182. }));
  183. $(this.settings.tip_container).append($tip_content);
  184. },
  185. show : function (init) {
  186. var $timer = null;
  187. // are we paused?
  188. if (this.settings.$li === undefined
  189. || ($.inArray(this.settings.$li.index(), this.settings.pause_after) === -1)) {
  190. // don't go to the next li if the tour was paused
  191. if (this.settings.paused) {
  192. this.settings.paused = false;
  193. } else {
  194. this.set_li(init);
  195. }
  196. this.settings.attempts = 0;
  197. if (this.settings.$li.length && this.settings.$target.length > 0) {
  198. if (init) { //run when we first start
  199. this.settings.pre_ride_callback(this.settings.$li.index(), this.settings.$next_tip);
  200. if (this.settings.modal) {
  201. this.show_modal();
  202. }
  203. }
  204. this.settings.pre_step_callback(this.settings.$li.index(), this.settings.$next_tip);
  205. if (this.settings.modal && this.settings.expose) {
  206. this.expose();
  207. }
  208. this.settings.tip_settings = $.extend({}, this.settings, this.data_options(this.settings.$li));
  209. this.settings.timer = parseInt(this.settings.timer, 10);
  210. this.settings.tip_settings.tip_location_pattern = this.settings.tip_location_patterns[this.settings.tip_settings.tip_location];
  211. // scroll if not modal
  212. if (!/body/i.test(this.settings.$target.selector)) {
  213. this.scroll_to();
  214. }
  215. if (this.is_phone()) {
  216. this.pos_phone(true);
  217. } else {
  218. this.pos_default(true);
  219. }
  220. $timer = this.settings.$next_tip.find('.joyride-timer-indicator');
  221. if (/pop/i.test(this.settings.tip_animation)) {
  222. $timer.width(0);
  223. if (this.settings.timer > 0) {
  224. this.settings.$next_tip.show();
  225. setTimeout(function () {
  226. $timer.animate({
  227. width: $timer.parent().width()
  228. }, this.settings.timer, 'linear');
  229. }.bind(this), this.settings.tip_animation_fade_speed);
  230. } else {
  231. this.settings.$next_tip.show();
  232. }
  233. } else if (/fade/i.test(this.settings.tip_animation)) {
  234. $timer.width(0);
  235. if (this.settings.timer > 0) {
  236. this.settings.$next_tip
  237. .fadeIn(this.settings.tip_animation_fade_speed)
  238. .show();
  239. setTimeout(function () {
  240. $timer.animate({
  241. width: $timer.parent().width()
  242. }, this.settings.timer, 'linear');
  243. }.bind(this), this.settings.tip_animation_fadeSpeed);
  244. } else {
  245. this.settings.$next_tip.fadeIn(this.settings.tip_animation_fade_speed);
  246. }
  247. }
  248. this.settings.$current_tip = this.settings.$next_tip;
  249. // skip non-existant targets
  250. } else if (this.settings.$li && this.settings.$target.length < 1) {
  251. this.show();
  252. } else {
  253. this.end();
  254. }
  255. } else {
  256. this.settings.paused = true;
  257. }
  258. },
  259. is_phone : function () {
  260. return matchMedia(Foundation.media_queries.small).matches &&
  261. !matchMedia(Foundation.media_queries.medium).matches;
  262. },
  263. hide : function () {
  264. if (this.settings.modal && this.settings.expose) {
  265. this.un_expose();
  266. }
  267. if (!this.settings.modal) {
  268. $('.joyride-modal-bg').hide();
  269. }
  270. // Prevent scroll bouncing...wait to remove from layout
  271. this.settings.$current_tip.css('visibility', 'hidden');
  272. setTimeout($.proxy(function() {
  273. this.hide();
  274. this.css('visibility', 'visible');
  275. }, this.settings.$current_tip), 0);
  276. this.settings.post_step_callback(this.settings.$li.index(),
  277. this.settings.$current_tip);
  278. },
  279. set_li : function (init) {
  280. if (init) {
  281. this.settings.$li = this.settings.$tip_content.eq(this.settings.start_offset);
  282. this.set_next_tip();
  283. this.settings.$current_tip = this.settings.$next_tip;
  284. } else {
  285. this.settings.$li = this.settings.$li.next();
  286. this.set_next_tip();
  287. }
  288. this.set_target();
  289. },
  290. set_next_tip : function () {
  291. this.settings.$next_tip = $(".joyride-tip-guide").eq(this.settings.$li.index());
  292. this.settings.$next_tip.data('closed', '');
  293. },
  294. set_target : function () {
  295. var cl = this.settings.$li.attr(this.add_namespace('data-class')),
  296. id = this.settings.$li.attr(this.add_namespace('data-id')),
  297. $sel = function () {
  298. if (id) {
  299. return $(document.getElementById(id));
  300. } else if (cl) {
  301. return $('.' + cl).first();
  302. } else {
  303. return $('body');
  304. }
  305. };
  306. this.settings.$target = $sel();
  307. },
  308. scroll_to : function () {
  309. var window_half, tipOffset;
  310. window_half = $(window).height() / 2;
  311. tipOffset = Math.ceil(this.settings.$target.offset().top - window_half + this.settings.$next_tip.outerHeight());
  312. if (tipOffset != 0) {
  313. $('html, body').animate({
  314. scrollTop: tipOffset
  315. }, this.settings.scroll_speed, 'swing');
  316. }
  317. },
  318. paused : function () {
  319. return ($.inArray((this.settings.$li.index() + 1), this.settings.pause_after) === -1);
  320. },
  321. restart : function () {
  322. this.hide();
  323. this.settings.$li = undefined;
  324. this.show('init');
  325. },
  326. pos_default : function (init, resizing) {
  327. var half_fold = Math.ceil($(window).height() / 2),
  328. tip_position = this.settings.$next_tip.offset(),
  329. $nub = this.settings.$next_tip.find('.joyride-nub'),
  330. nub_width = Math.ceil($nub.outerWidth() / 2),
  331. nub_height = Math.ceil($nub.outerHeight() / 2),
  332. toggle = init || false;
  333. // tip must not be "display: none" to calculate position
  334. if (toggle) {
  335. this.settings.$next_tip.css('visibility', 'hidden');
  336. this.settings.$next_tip.show();
  337. }
  338. if (typeof resizing === 'undefined') {
  339. resizing = false;
  340. }
  341. if (!/body/i.test(this.settings.$target.selector)) {
  342. if (this.bottom()) {
  343. if (this.rtl) {
  344. this.settings.$next_tip.css({
  345. top: (this.settings.$target.offset().top + nub_height + this.settings.$target.outerHeight()),
  346. left: this.settings.$target.offset().left + this.settings.$target.outerWidth() - this.settings.$next_tip.outerWidth()});
  347. } else {
  348. this.settings.$next_tip.css({
  349. top: (this.settings.$target.offset().top + nub_height + this.settings.$target.outerHeight()),
  350. left: this.settings.$target.offset().left});
  351. }
  352. this.nub_position($nub, this.settings.tip_settings.nub_position, 'top');
  353. } else if (this.top()) {
  354. if (this.rtl) {
  355. this.settings.$next_tip.css({
  356. top: (this.settings.$target.offset().top - this.settings.$next_tip.outerHeight() - nub_height),
  357. left: this.settings.$target.offset().left + this.settings.$target.outerWidth() - this.settings.$next_tip.outerWidth()});
  358. } else {
  359. this.settings.$next_tip.css({
  360. top: (this.settings.$target.offset().top - this.settings.$next_tip.outerHeight() - nub_height),
  361. left: this.settings.$target.offset().left});
  362. }
  363. this.nub_position($nub, this.settings.tip_settings.nub_position, 'bottom');
  364. } else if (this.right()) {
  365. this.settings.$next_tip.css({
  366. top: this.settings.$target.offset().top,
  367. left: (this.settings.$target.outerWidth() + this.settings.$target.offset().left + nub_width)});
  368. this.nub_position($nub, this.settings.tip_settings.nub_position, 'left');
  369. } else if (this.left()) {
  370. this.settings.$next_tip.css({
  371. top: this.settings.$target.offset().top,
  372. left: (this.settings.$target.offset().left - this.settings.$next_tip.outerWidth() - nub_width)});
  373. this.nub_position($nub, this.settings.tip_settings.nub_position, 'right');
  374. }
  375. if (!this.visible(this.corners(this.settings.$next_tip)) && this.settings.attempts < this.settings.tip_settings.tip_location_pattern.length) {
  376. $nub.removeClass('bottom')
  377. .removeClass('top')
  378. .removeClass('right')
  379. .removeClass('left');
  380. this.settings.tip_settings.tip_location = this.settings.tip_settings.tip_location_pattern[this.settings.attempts];
  381. this.settings.attempts++;
  382. this.pos_default();
  383. }
  384. } else if (this.settings.$li.length) {
  385. this.pos_modal($nub);
  386. }
  387. if (toggle) {
  388. this.settings.$next_tip.hide();
  389. this.settings.$next_tip.css('visibility', 'visible');
  390. }
  391. },
  392. pos_phone : function (init) {
  393. var tip_height = this.settings.$next_tip.outerHeight(),
  394. tip_offset = this.settings.$next_tip.offset(),
  395. target_height = this.settings.$target.outerHeight(),
  396. $nub = $('.joyride-nub', this.settings.$next_tip),
  397. nub_height = Math.ceil($nub.outerHeight() / 2),
  398. toggle = init || false;
  399. $nub.removeClass('bottom')
  400. .removeClass('top')
  401. .removeClass('right')
  402. .removeClass('left');
  403. if (toggle) {
  404. this.settings.$next_tip.css('visibility', 'hidden');
  405. this.settings.$next_tip.show();
  406. }
  407. if (!/body/i.test(this.settings.$target.selector)) {
  408. if (this.top()) {
  409. this.settings.$next_tip.offset({top: this.settings.$target.offset().top - tip_height - nub_height});
  410. $nub.addClass('bottom');
  411. } else {
  412. this.settings.$next_tip.offset({top: this.settings.$target.offset().top + target_height + nub_height});
  413. $nub.addClass('top');
  414. }
  415. } else if (this.settings.$li.length) {
  416. this.pos_modal($nub);
  417. }
  418. if (toggle) {
  419. this.settings.$next_tip.hide();
  420. this.settings.$next_tip.css('visibility', 'visible');
  421. }
  422. },
  423. pos_modal : function ($nub) {
  424. this.center();
  425. $nub.hide();
  426. this.show_modal();
  427. },
  428. show_modal : function () {
  429. if (!this.settings.$next_tip.data('closed')) {
  430. var joyridemodalbg = $('.joyride-modal-bg');
  431. if (joyridemodalbg.length < 1) {
  432. $('body').append(this.settings.template.modal).show();
  433. }
  434. if (/pop/i.test(this.settings.tip_animation)) {
  435. joyridemodalbg.show();
  436. } else {
  437. joyridemodalbg.fadeIn(this.settings.tip_animation_fade_speed);
  438. }
  439. }
  440. },
  441. expose : function () {
  442. var expose,
  443. exposeCover,
  444. el,
  445. origCSS,
  446. origClasses,
  447. randId = 'expose-' + this.random_str(6);
  448. if (arguments.length > 0 && arguments[0] instanceof $) {
  449. el = arguments[0];
  450. } else if(this.settings.$target && !/body/i.test(this.settings.$target.selector)){
  451. el = this.settings.$target;
  452. } else {
  453. return false;
  454. }
  455. if(el.length < 1){
  456. if(window.console){
  457. console.error('element not valid', el);
  458. }
  459. return false;
  460. }
  461. expose = $(this.settings.template.expose);
  462. this.settings.$body.append(expose);
  463. expose.css({
  464. top: el.offset().top,
  465. left: el.offset().left,
  466. width: el.outerWidth(true),
  467. height: el.outerHeight(true)
  468. });
  469. exposeCover = $(this.settings.template.expose_cover);
  470. origCSS = {
  471. zIndex: el.css('z-index'),
  472. position: el.css('position')
  473. };
  474. origClasses = el.attr('class') == null ? '' : el.attr('class');
  475. el.css('z-index',parseInt(expose.css('z-index'))+1);
  476. if (origCSS.position == 'static') {
  477. el.css('position','relative');
  478. }
  479. el.data('expose-css',origCSS);
  480. el.data('orig-class', origClasses);
  481. el.attr('class', origClasses + ' ' + this.settings.expose_add_class);
  482. exposeCover.css({
  483. top: el.offset().top,
  484. left: el.offset().left,
  485. width: el.outerWidth(true),
  486. height: el.outerHeight(true)
  487. });
  488. if (this.settings.modal) this.show_modal();
  489. this.settings.$body.append(exposeCover);
  490. expose.addClass(randId);
  491. exposeCover.addClass(randId);
  492. el.data('expose', randId);
  493. this.settings.post_expose_callback(this.settings.$li.index(), this.settings.$next_tip, el);
  494. this.add_exposed(el);
  495. },
  496. un_expose : function () {
  497. var exposeId,
  498. el,
  499. expose ,
  500. origCSS,
  501. origClasses,
  502. clearAll = false;
  503. if (arguments.length > 0 && arguments[0] instanceof $) {
  504. el = arguments[0];
  505. } else if(this.settings.$target && !/body/i.test(this.settings.$target.selector)){
  506. el = this.settings.$target;
  507. } else {
  508. return false;
  509. }
  510. if(el.length < 1){
  511. if (window.console) {
  512. console.error('element not valid', el);
  513. }
  514. return false;
  515. }
  516. exposeId = el.data('expose');
  517. expose = $('.' + exposeId);
  518. if (arguments.length > 1) {
  519. clearAll = arguments[1];
  520. }
  521. if (clearAll === true) {
  522. $('.joyride-expose-wrapper,.joyride-expose-cover').remove();
  523. } else {
  524. expose.remove();
  525. }
  526. origCSS = el.data('expose-css');
  527. if (origCSS.zIndex == 'auto') {
  528. el.css('z-index', '');
  529. } else {
  530. el.css('z-index', origCSS.zIndex);
  531. }
  532. if (origCSS.position != el.css('position')) {
  533. if(origCSS.position == 'static') {// this is default, no need to set it.
  534. el.css('position', '');
  535. } else {
  536. el.css('position', origCSS.position);
  537. }
  538. }
  539. origClasses = el.data('orig-class');
  540. el.attr('class', origClasses);
  541. el.removeData('orig-classes');
  542. el.removeData('expose');
  543. el.removeData('expose-z-index');
  544. this.remove_exposed(el);
  545. },
  546. add_exposed: function(el){
  547. this.settings.exposed = this.settings.exposed || [];
  548. if (el instanceof $ || typeof el === 'object') {
  549. this.settings.exposed.push(el[0]);
  550. } else if (typeof el == 'string') {
  551. this.settings.exposed.push(el);
  552. }
  553. },
  554. remove_exposed: function(el){
  555. var search, i;
  556. if (el instanceof $) {
  557. search = el[0]
  558. } else if (typeof el == 'string'){
  559. search = el;
  560. }
  561. this.settings.exposed = this.settings.exposed || [];
  562. i = this.settings.exposed.length;
  563. while (i--) {
  564. if (this.settings.exposed[i] == search) {
  565. this.settings.exposed.splice(i, 1);
  566. return;
  567. }
  568. }
  569. },
  570. center : function () {
  571. var $w = $(window);
  572. this.settings.$next_tip.css({
  573. top : ((($w.height() - this.settings.$next_tip.outerHeight()) / 2) + $w.scrollTop()),
  574. left : ((($w.width() - this.settings.$next_tip.outerWidth()) / 2) + $w.scrollLeft())
  575. });
  576. return true;
  577. },
  578. bottom : function () {
  579. return /bottom/i.test(this.settings.tip_settings.tip_location);
  580. },
  581. top : function () {
  582. return /top/i.test(this.settings.tip_settings.tip_location);
  583. },
  584. right : function () {
  585. return /right/i.test(this.settings.tip_settings.tip_location);
  586. },
  587. left : function () {
  588. return /left/i.test(this.settings.tip_settings.tip_location);
  589. },
  590. corners : function (el) {
  591. var w = $(window),
  592. window_half = w.height() / 2,
  593. //using this to calculate since scroll may not have finished yet.
  594. tipOffset = Math.ceil(this.settings.$target.offset().top - window_half + this.settings.$next_tip.outerHeight()),
  595. right = w.width() + w.scrollLeft(),
  596. offsetBottom = w.height() + tipOffset,
  597. bottom = w.height() + w.scrollTop(),
  598. top = w.scrollTop();
  599. if (tipOffset < top) {
  600. if (tipOffset < 0) {
  601. top = 0;
  602. } else {
  603. top = tipOffset;
  604. }
  605. }
  606. if (offsetBottom > bottom) {
  607. bottom = offsetBottom;
  608. }
  609. return [
  610. el.offset().top < top,
  611. right < el.offset().left + el.outerWidth(),
  612. bottom < el.offset().top + el.outerHeight(),
  613. w.scrollLeft() > el.offset().left
  614. ];
  615. },
  616. visible : function (hidden_corners) {
  617. var i = hidden_corners.length;
  618. while (i--) {
  619. if (hidden_corners[i]) return false;
  620. }
  621. return true;
  622. },
  623. nub_position : function (nub, pos, def) {
  624. if (pos === 'auto') {
  625. nub.addClass(def);
  626. } else {
  627. nub.addClass(pos);
  628. }
  629. },
  630. startTimer : function () {
  631. if (this.settings.$li.length) {
  632. this.settings.automate = setTimeout(function () {
  633. this.hide();
  634. this.show();
  635. this.startTimer();
  636. }.bind(this), this.settings.timer);
  637. } else {
  638. clearTimeout(this.settings.automate);
  639. }
  640. },
  641. end : function (abort) {
  642. if (this.settings.cookie_monster) {
  643. $.cookie(this.settings.cookie_name, 'ridden', { expires: this.settings.cookie_expires, domain: this.settings.cookie_domain });
  644. }
  645. if (this.settings.timer > 0) {
  646. clearTimeout(this.settings.automate);
  647. }
  648. if (this.settings.modal && this.settings.expose) {
  649. this.un_expose();
  650. }
  651. this.settings.$next_tip.data('closed', true);
  652. $('.joyride-modal-bg').hide();
  653. this.settings.$current_tip.hide();
  654. if (typeof abort === 'undefined') {
  655. this.settings.post_step_callback(this.settings.$li.index(), this.settings.$current_tip);
  656. this.settings.post_ride_callback(this.settings.$li.index(), this.settings.$current_tip);
  657. }
  658. $('.joyride-tip-guide').remove();
  659. },
  660. off : function () {
  661. $(this.scope).off('.joyride');
  662. $(window).off('.joyride');
  663. $('.joyride-close-tip, .joyride-next-tip, .joyride-modal-bg').off('.joyride');
  664. $('.joyride-tip-guide, .joyride-modal-bg').remove();
  665. clearTimeout(this.settings.automate);
  666. this.settings = {};
  667. },
  668. reflow : function () {}
  669. };
  670. }(jQuery, this, this.document));