Quellcode durchsuchen

Evolution #169: Interface d'aide

Sevajol Bastien vor 12 Jahren
Ursprung
Commit
50479f9081

+ 10 - 0
src/Muzich/CoreBundle/Entity/User.php Datei anzeigen

@@ -226,6 +226,12 @@ class User extends BaseUser
226 226
   public $avatar_path;
227 227
   
228 228
   /**
229
+   * @ORM\Column(type="text", unique=false, nullable=true)
230
+   * @var array 
231
+   */
232
+  private $help_tour;
233
+  
234
+  /**
229 235
    * 
230 236
    */
231 237
   public function __construct()
@@ -238,6 +244,10 @@ class User extends BaseUser
238 244
     $this->followed_groups = new ArrayCollection();
239 245
     $this->groups = new ArrayCollection();
240 246
     $this->groups_owned = new ArrayCollection();
247
+    $this->help_tour = json_encode(array(
248
+      'home' => true,
249
+      
250
+    ));
241 251
     parent::__construct();
242 252
   }
243 253
   

+ 1 - 0
src/Muzich/CoreBundle/Resources/views/Layout/head_css.html.twig Datei anzeigen

@@ -4,6 +4,7 @@
4 4
   'jplayer/skin/blue.monday/jplayer.blue.monday.css'
5 5
   'bundles/muzichcore/css/base.css'
6 6
   'bundles/muzichcore/css/old.css'
7
+  'css/joyride-2.0.3.css'
7 8
   'css/main.css' %}{# filter='yui_css' %}#}
8 9
   <link rel="stylesheet" href="{{ asset_url }}" />
9 10
 {% endstylesheets %}

+ 1 - 0
src/Muzich/CoreBundle/Resources/views/Layout/head_js.html.twig Datei anzeigen

@@ -8,6 +8,7 @@
8 8
   'jplayer/js/jplayer.playlist.min.js'
9 9
   'js/jquery.form-2.14.js'
10 10
   'js/jConfirmAction/jconfirmaction.jquery.js'
11
+  'js/jquery.joyride-2.0.3.js'
11 12
   '@MuzichCoreBundle/Resources/public/js/TagPrompt.js'
12 13
   '@MuzichCoreBundle/Resources/public/js/player/*'
13 14
   '@MuzichCoreBundle/Resources/public/js/play2.js'

+ 240 - 0
web/css/joyride-2.0.3.css Datei anzeigen

@@ -0,0 +1,240 @@
1
+/* Artfully masterminded by ZURB */
2
+body {
3
+  position: relative;
4
+}
5
+
6
+#joyRideTipContent { display: none; }
7
+
8
+.joyRideTipContent { display: none; }
9
+
10
+/* Default styles for the container */
11
+.joyride-tip-guide {
12
+  position: absolute;
13
+  background: #000;
14
+  background: rgba(0,0,0,0.8);
15
+  display: none;
16
+  color: #fff;
17
+  width: 300px;
18
+  z-index: 101;
19
+  top: 0; /* keeps the page from scrolling when calculating position */
20
+  left: 0;
21
+  font-family: "HelveticaNeue", "Helvetica Neue", "Helvetica", Helvetica, Arial, Lucida, sans-serif;
22
+  font-weight: normal;
23
+     -moz-border-radius: 4px;
24
+  -webkit-border-radius: 4px;
25
+          border-radius: 4px;
26
+}
27
+
28
+.joyride-content-wrapper {
29
+  padding: 10px 10px 15px 15px;
30
+}
31
+
32
+/* Mobile */
33
+@media only screen and (max-width: 767px) {
34
+  .joyride-tip-guide {
35
+    width: 95% !important;
36
+    -moz-border-radius: 0;
37
+    -webkit-border-radius: 0;
38
+    border-radius: 0;
39
+    left: 2.5% !important;
40
+  }
41
+  .joyride-tip-guide-wrapper {
42
+    width: 100%;
43
+  }
44
+}
45
+
46
+
47
+/* Add a little css triangle pip, older browser just miss out on the fanciness of it */
48
+.joyride-tip-guide span.joyride-nub {
49
+  display: block;
50
+  position: absolute;
51
+  left: 22px;
52
+  width: 0;
53
+  height: 0;
54
+  border: solid 14px;
55
+  border: solid 14px;
56
+}
57
+
58
+.joyride-tip-guide span.joyride-nub.top {
59
+  /*
60
+  IE7/IE8 Don't support rgba so we set the fallback
61
+  border color here. However, IE7/IE8 are also buggy
62
+  in that the fallback color doesn't work for
63
+  border-bottom-color so here we set the border-color
64
+  and override the top,left,right colors below.
65
+  */
66
+  border-color: #000;
67
+  border-color: rgba(0,0,0,0.8);
68
+  border-top-color: transparent !important;
69
+  border-left-color: transparent !important;
70
+  border-right-color: transparent !important;
71
+  top: -28px;
72
+  bottom: none;
73
+}
74
+
75
+.joyride-tip-guide span.joyride-nub.bottom {
76
+  /*
77
+  IE7/IE8 Don't support rgba so we set the fallback
78
+  border color here. However, IE7/IE8 are also buggy
79
+  in that the fallback color doesn't work for
80
+  border-top-color so here we set the border-color
81
+  and override the bottom,left,right colors below.
82
+  */
83
+  border-color: #000;
84
+  border-color: rgba(0,0,0,0.8) !important;
85
+  border-bottom-color: transparent !important;
86
+  border-left-color: transparent !important;
87
+  border-right-color: transparent !important;
88
+  bottom: -28px;
89
+  bottom: none;
90
+}
91
+
92
+.joyride-tip-guide span.joyride-nub.right {
93
+  border-color: #000;
94
+  border-color: rgba(0,0,0,0.8) !important;
95
+  border-top-color: transparent !important;
96
+  border-right-color: transparent !important;
97
+  border-bottom-color: transparent !important;
98
+  top: 22px;
99
+  bottom: none;
100
+  left: auto;
101
+  right: -28px;
102
+}
103
+
104
+.joyride-tip-guide span.joyride-nub.left {
105
+  border-color: #000;
106
+  border-color: rgba(0,0,0,0.8) !important;
107
+  border-top-color: transparent !important;
108
+  border-left-color: transparent !important;
109
+  border-bottom-color: transparent !important;
110
+  top: 22px;
111
+  left: -28px;
112
+  right: auto;
113
+  bottom: none;
114
+}
115
+
116
+.joyride-tip-guide span.joyride-nub.top-right {
117
+  border-color: #000;
118
+  border-color: rgba(0,0,0,0.8);
119
+  border-top-color: transparent !important;
120
+  border-left-color: transparent !important;
121
+  border-right-color: transparent !important;
122
+  top: -28px;
123
+  bottom: none;
124
+  left: auto;
125
+  right: 28px;
126
+}
127
+
128
+/* Typography */
129
+.joyride-tip-guide h1,.joyride-tip-guide h2,.joyride-tip-guide h3,.joyride-tip-guide h4,.joyride-tip-guide h5,.joyride-tip-guide h6 {
130
+  line-height: 1.25;
131
+  margin: 0;
132
+  font-weight: bold;
133
+  color: #fff;
134
+}
135
+.joyride-tip-guide h1 { font-size: 30px; }
136
+.joyride-tip-guide h2 { font-size: 26px; }
137
+.joyride-tip-guide h3 { font-size: 22px; }
138
+.joyride-tip-guide h4 { font-size: 18px; }
139
+.joyride-tip-guide h5 { font-size: 16px; }
140
+.joyride-tip-guide h6 { font-size: 14px; }
141
+.joyride-tip-guide p {
142
+  margin: 0 0 18px 0;
143
+  font-size: 14px;
144
+  line-height: 18px;
145
+}
146
+.joyride-tip-guide a {
147
+  color: rgb(255,255,255);
148
+  text-decoration: none;
149
+  border-bottom: dotted 1px rgba(255,255,255,0.6);
150
+}
151
+.joyride-tip-guide a:hover {
152
+  color: rgba(255,255,255,0.8);
153
+  border-bottom: none;
154
+}
155
+
156
+/* Button Style */
157
+.joyride-tip-guide .joyride-next-tip {
158
+  width: auto;
159
+  padding: 6px 18px 4px;
160
+  font-size: 13px;
161
+  text-decoration: none;
162
+  color: rgb(255,255,255);
163
+  border: solid 1px rgb(0,60,180);
164
+  background: rgb(0,99,255);
165
+  background: -moz-linear-gradient(top, rgb(0,99,255) 0%, rgb(0,85,214) 100%);
166
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(0,99,255)), color-stop(100%,rgb(0,85,214)));
167
+  background: -webkit-linear-gradient(top, rgb(0,99,255) 0%,rgb(0,85,214) 100%);
168
+  background: -o-linear-gradient(top, rgb(0,99,255) 0%,rgb(0,85,214) 100%);
169
+  background: -ms-linear-gradient(top, rgb(0,99,255) 0%,rgb(0,85,214) 100%);
170
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0063ff', endColorstr='#0055d6',GradientType=0 );
171
+  background: linear-gradient(top, rgb(0,99,255) 0%,rgb(0,85,214) 100%);
172
+  text-shadow: 0 -1px 0 rgba(0,0,0,0.5);
173
+  -webkit-border-radius: 2px;
174
+     -moz-border-radius: 2px;
175
+          border-radius: 2px;
176
+  -webkit-box-shadow: 0px 1px 0px rgba(255,255,255,0.3) inset;
177
+     -moz-box-shadow: 0px 1px 0px rgba(255,255,255,0.3) inset;
178
+          box-shadow: 0px 1px 0px rgba(255,255,255,0.3) inset;
179
+}
180
+
181
+.joyride-next-tip:hover {
182
+  color: rgb(255,255,255) !important;
183
+  border: solid 1px rgb(0,60,180) !important;
184
+  background: rgb(43,128,255);
185
+  background: -moz-linear-gradient(top, rgb(43,128,255) 0%, rgb(29,102,211) 100%);
186
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(43,128,255)), color-stop(100%,rgb(29,102,211)));
187
+  background: -webkit-linear-gradient(top, rgb(43,128,255) 0%,rgb(29,102,211) 100%);
188
+  background: -o-linear-gradient(top, rgb(43,128,255) 0%,rgb(29,102,211) 100%);
189
+  background: -ms-linear-gradient(top, rgb(43,128,255) 0%,rgb(29,102,211) 100%);
190
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#2b80ff', endColorstr='#1d66d3',GradientType=0 );
191
+  background: linear-gradient(top, rgb(43,128,255) 0%,rgb(29,102,211) 100%);
192
+}
193
+
194
+.joyride-timer-indicator-wrap {
195
+  width: 50px;
196
+  height: 3px;
197
+  border: solid 1px rgba(255,255,255,0.1);
198
+  position: absolute;
199
+  right: 17px;
200
+  bottom: 16px;
201
+}
202
+.joyride-timer-indicator {
203
+  display: block;
204
+  width: 0;
205
+  height: inherit;
206
+  background: rgba(255,255,255,0.25);
207
+}
208
+
209
+.joyride-close-tip {
210
+  position: absolute;
211
+  right: 10px;
212
+  top: 10px;
213
+  color: rgba(255,255,255,0.4) !important;
214
+  text-decoration: none;
215
+  font-family: Verdana, sans-serif;
216
+  font-size: 10px;
217
+  font-weight: bold;
218
+  border-bottom: none !important;
219
+}
220
+
221
+.joyride-close-tip:hover {
222
+  color: rgba(255,255,255,0.9) !important;
223
+}
224
+
225
+.joyride-modal-bg {
226
+  position: fixed;
227
+  height: 100%;
228
+  width: 100%;
229
+  background: rgb(0,0,0);
230
+  background: transparent;
231
+  background: rgba(0,0,0, 0.5);
232
+  -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
233
+  filter: alpha(opacity=50);
234
+  opacity: 0.5;
235
+  z-index: 100;
236
+  display: none;
237
+  top: 0;
238
+  left: 0;
239
+  cursor: pointer;
240
+}

+ 653 - 0
web/js/jquery.joyride-2.0.3.js Datei anzeigen

@@ -0,0 +1,653 @@
1
+/*
2
+ * jQuery Foundation Joyride Plugin 2.0.3
3
+ * http://foundation.zurb.com
4
+ * Copyright 2012, ZURB
5
+ * Free to use under the MIT license.
6
+ * http://www.opensource.org/licenses/mit-license.php
7
+*/
8
+
9
+/*jslint unparam: true, browser: true, indent: 2 */
10
+
11
+;(function ($, window, undefined) {
12
+  'use strict';
13
+
14
+  var defaults = {
15
+      'version'              : '2.0.3',
16
+      'tipLocation'          : 'bottom',  // 'top' or 'bottom' in relation to parent
17
+      'nubPosition'          : 'auto',    // override on a per tooltip bases
18
+      'scrollSpeed'          : 300,       // Page scrolling speed in milliseconds
19
+      'timer'                : 0,         // 0 = no timer , all other numbers = timer in milliseconds
20
+      'startTimerOnClick'    : true,      // true or false - true requires clicking the first button start the timer
21
+      'startOffset'          : 0,         // the index of the tooltip you want to start on (index of the li)
22
+      'nextButton'           : true,      // true or false to control whether a next button is used
23
+      'tipAnimation'         : 'fade',    // 'pop' or 'fade' in each tip
24
+      'pauseAfter'           : [],        // array of indexes where to pause the tour after
25
+      'tipAnimationFadeSpeed': 300,       // when tipAnimation = 'fade' this is speed in milliseconds for the transition
26
+      'cookieMonster'        : false,     // true or false to control whether cookies are used
27
+      'cookieName'           : 'joyride', // Name the cookie you'll use
28
+      'cookieDomain'         : false,     // Will this cookie be attached to a domain, ie. '.notableapp.com'
29
+      'tipContainer'         : 'body',    // Where will the tip be attached
30
+      'postRideCallback'     : $.noop,    // A method to call once the tour closes (canceled or complete)
31
+      'postStepCallback'     : $.noop,    // A method to call after each step
32
+      'template' : { // HTML segments for tip layout
33
+        'link'    : '<a href="#close" class="joyride-close-tip">X</a>',
34
+        'timer'   : '<div class="joyride-timer-indicator-wrap"><span class="joyride-timer-indicator"></span></div>',
35
+        'tip'     : '<div class="joyride-tip-guide"><span class="joyride-nub"></span></div>',
36
+        'wrapper' : '<div class="joyride-content-wrapper"></div>',
37
+        'button'  : '<a href="#" class="joyride-next-tip"></a>'
38
+      }
39
+    },
40
+
41
+    Modernizr = Modernizr || false,
42
+
43
+    settings = {},
44
+
45
+    methods = {
46
+
47
+      init : function (opts) {
48
+        return this.each(function () {
49
+
50
+          if ($.isEmptyObject(settings)) {
51
+            settings = $.extend(true, defaults, opts);
52
+
53
+            // non configurable settings
54
+            settings.document = window.document;
55
+            settings.$document = $(settings.document);
56
+            settings.$window = $(window);
57
+            settings.$content_el = $(this);
58
+            settings.body_offset = $(settings.tipContainer).position();
59
+            settings.$tip_content = $('> li', settings.$content_el);
60
+            settings.paused = false;
61
+            settings.attempts = 0;
62
+
63
+            settings.tipLocationPatterns = {
64
+              top: ['bottom'],
65
+              bottom: [], // bottom should not need to be repositioned
66
+              left: ['right', 'top', 'bottom'],
67
+              right: ['left', 'top', 'bottom']
68
+            };
69
+
70
+            // are we using jQuery 1.7+
71
+            methods.jquery_check();
72
+
73
+            // can we create cookies?
74
+            if (!$.isFunction($.cookie)) {
75
+              settings.cookieMonster = false;
76
+            }
77
+
78
+            // generate the tips and insert into dom.
79
+            if (!settings.cookieMonster || !$.cookie(settings.cookieName)) {
80
+
81
+              settings.$tip_content.each(function (index) {
82
+                methods.create({$li : $(this), index : index});
83
+              });
84
+
85
+              // show first tip
86
+              if (!settings.startTimerOnClick && settings.timer > 0) {
87
+                methods.show('init');
88
+                methods.startTimer();
89
+              } else {
90
+                methods.show('init');
91
+              }
92
+
93
+            }
94
+
95
+            settings.$document.on('click.joyride', '.joyride-next-tip, .joyride-modal-bg', function (e) {
96
+              e.preventDefault();
97
+
98
+              if (settings.$li.next().length < 1) {
99
+                methods.end();
100
+              } else if (settings.timer > 0) {
101
+                clearTimeout(settings.automate);
102
+                methods.hide();
103
+                methods.show();
104
+                methods.startTimer();
105
+              } else {
106
+                methods.hide();
107
+                methods.show();
108
+              }
109
+
110
+            });
111
+
112
+            settings.$document.on('click.joyride', '.joyride-close-tip', function (e) {
113
+              e.preventDefault();
114
+              methods.end();
115
+            });
116
+
117
+            settings.$window.bind('resize.joyride', function (e) {
118
+              if (methods.is_phone()) {
119
+                methods.pos_phone();
120
+              } else {
121
+                methods.pos_default();
122
+              }
123
+            });
124
+          } else {
125
+            methods.restart();
126
+          }
127
+
128
+        });
129
+      },
130
+
131
+      // call this method when you want to resume the tour
132
+      resume : function () {
133
+        methods.set_li();
134
+        methods.show();
135
+      },
136
+
137
+      nextTip: function(){
138
+            if (settings.$li.next().length < 1) {
139
+            methods.end();
140
+            } else if (settings.timer > 0) {
141
+            clearTimeout(settings.automate);
142
+            methods.hide();
143
+            methods.show();
144
+            methods.startTimer();
145
+            } else {
146
+            methods.hide();
147
+            methods.show();
148
+            }
149
+      }, 
150
+
151
+      tip_template : function (opts) {
152
+        var $blank, content;
153
+
154
+        opts.tip_class = opts.tip_class || '';
155
+
156
+        $blank = $(settings.template.tip).addClass(opts.tip_class);
157
+        content = $.trim($(opts.li).html()) +
158
+          methods.button_text(opts.button_text) +
159
+          settings.template.link +
160
+          methods.timer_instance(opts.index);
161
+
162
+        $blank.append($(settings.template.wrapper));
163
+        $blank.first().attr('data-index', opts.index);
164
+        $('.joyride-content-wrapper', $blank).append(content);
165
+
166
+        return $blank[0];
167
+      },
168
+
169
+      timer_instance : function (index) {
170
+        var txt;
171
+
172
+        if ((index === 0 && settings.startTimerOnClick && settings.timer > 0) || settings.timer === 0) {
173
+          txt = '';
174
+        } else {
175
+          txt = methods.outerHTML($(settings.template.timer)[0]);
176
+        }
177
+        return txt;
178
+      },
179
+
180
+      button_text : function (txt) {
181
+        if (settings.nextButton) {
182
+          txt = $.trim(txt) || 'Next';
183
+          txt = methods.outerHTML($(settings.template.button).append(txt)[0]);
184
+        } else {
185
+          txt = '';
186
+        }
187
+        return txt;
188
+      },
189
+
190
+      create : function (opts) {
191
+        // backwards compatibility with data-text attribute
192
+        var buttonText = opts.$li.attr('data-button') || opts.$li.attr('data-text'),
193
+          tipClass = opts.$li.attr('class'),
194
+          $tip_content = $(methods.tip_template({
195
+            tip_class : tipClass,
196
+            index : opts.index,
197
+            button_text : buttonText,
198
+            li : opts.$li
199
+          }));
200
+
201
+        $(settings.tipContainer).append($tip_content);
202
+      },
203
+
204
+      show : function (init) {
205
+        var opts = {}, ii, opts_arr = [], opts_len = 0, p,
206
+            $timer = null;
207
+
208
+        // are we paused?
209
+        if (settings.$li === undefined || ($.inArray(settings.$li.index(), settings.pauseAfter) === -1)) {
210
+
211
+          // don't go to the next li if the tour was paused
212
+          if (settings.paused) {
213
+            settings.paused = false;
214
+          } else {
215
+            methods.set_li(init);
216
+          }
217
+
218
+          settings.attempts = 0;
219
+
220
+          if (settings.$li.length && settings.$target.length > 0) {
221
+            opts_arr = (settings.$li.data('options') || ':').split(';');
222
+            opts_len = opts_arr.length;
223
+
224
+            // parse options
225
+            for (ii = opts_len - 1; ii >= 0; ii--) {
226
+              p = opts_arr[ii].split(':');
227
+
228
+              if (p.length === 2) {
229
+                opts[$.trim(p[0])] = $.trim(p[1]);
230
+              }
231
+            }
232
+
233
+            settings.tipSettings = $.extend({}, settings, opts);
234
+
235
+            settings.tipSettings.tipLocationPattern = settings.tipLocationPatterns[settings.tipSettings.tipLocation];
236
+
237
+            // scroll if not modal
238
+            if (!/body/i.test(settings.$target.selector)) {
239
+              methods.scroll_to();
240
+            }
241
+
242
+            if (methods.is_phone()) {
243
+              methods.pos_phone(true);
244
+            } else {
245
+              methods.pos_default(true);
246
+            }
247
+
248
+            $timer = $('.joyride-timer-indicator', settings.$next_tip);
249
+
250
+            if (/pop/i.test(settings.tipAnimation)) {
251
+
252
+              $timer.outerWidth(0);
253
+
254
+              if (settings.timer > 0) {
255
+
256
+                settings.$next_tip.show();
257
+                $timer.animate({
258
+                  width: $('.joyride-timer-indicator-wrap', settings.$next_tip).outerWidth()
259
+                }, settings.timer);
260
+
261
+              } else {
262
+
263
+                settings.$next_tip.show();
264
+
265
+              }
266
+
267
+
268
+            } else if (/fade/i.test(settings.tipAnimation)) {
269
+
270
+              $timer.outerWidth(0);
271
+
272
+              if (settings.timer > 0) {
273
+
274
+                settings.$next_tip.fadeIn(settings.tipAnimationFadeSpeed);
275
+
276
+                settings.$next_tip.show();
277
+                $timer.animate({
278
+                  width: $('.joyride-timer-indicator-wrap', settings.$next_tip).outerWidth()
279
+                }, settings.timer);
280
+
281
+              } else {
282
+
283
+                settings.$next_tip.fadeIn(settings.tipAnimationFadeSpeed);
284
+
285
+              }
286
+            }
287
+
288
+            settings.$current_tip = settings.$next_tip;
289
+
290
+          // skip non-existent targets
291
+          } else if (settings.$li && settings.$target.length < 1) {
292
+
293
+            methods.show();
294
+
295
+          } else {
296
+
297
+            methods.end();
298
+
299
+          }
300
+        } else {
301
+
302
+          settings.paused = true;
303
+
304
+        }
305
+
306
+      },
307
+
308
+      // detect phones with media queries if supported.
309
+      is_phone : function () {
310
+        if (Modernizr) {
311
+          return Modernizr.mq('only screen and (max-width: 767px)');
312
+        }
313
+
314
+        return (settings.$window.width() < 767) ? true : false;
315
+      },
316
+
317
+      hide : function () {
318
+        settings.postStepCallback(settings.$li.index(), settings.$current_tip);
319
+        $('.joyride-modal-bg').hide();
320
+        settings.$current_tip.hide();
321
+      },
322
+
323
+      set_li : function (init) {
324
+        if (init) {
325
+          settings.$li = settings.$tip_content.eq(settings.startOffset);
326
+          methods.set_next_tip();
327
+          settings.$current_tip = settings.$next_tip;
328
+        } else {
329
+          settings.$li = settings.$li.next();
330
+          methods.set_next_tip();
331
+        }
332
+
333
+        methods.set_target();
334
+      },
335
+
336
+      set_next_tip : function () {
337
+        settings.$next_tip = $('.joyride-tip-guide[data-index=' + settings.$li.index() + ']');
338
+      },
339
+
340
+      set_target : function () {
341
+        var cl = settings.$li.attr('data-class'),
342
+            id = settings.$li.attr('data-id'),
343
+            $sel = function () {
344
+              if (id) {
345
+                return $(settings.document.getElementById(id));
346
+              } else if (cl) {
347
+                return $('.' + cl).first();
348
+              } else {
349
+                return $('body');
350
+              }
351
+            };
352
+
353
+        settings.$target = $sel();
354
+      },
355
+
356
+      scroll_to : function () {
357
+        var window_half, tipOffset;
358
+
359
+        window_half = settings.$window.height() / 2;
360
+        tipOffset = Math.ceil(settings.$target.offset().top - window_half + settings.$next_tip.outerHeight());
361
+
362
+        $("html, body").stop().animate({
363
+          scrollTop: tipOffset
364
+        }, settings.scrollSpeed);
365
+      },
366
+
367
+      paused : function () {
368
+        if (($.inArray((settings.$li.index() + 1), settings.pauseAfter) === -1)) {
369
+          return true;
370
+        }
371
+
372
+        return false;
373
+      },
374
+
375
+      destroy : function () {
376
+        settings.$document.off('.joyride');
377
+        $(window).off('.joyride');
378
+        $('.joyride-close-tip, .joyride-next-tip, .joyride-modal-bg').off('.joyride');
379
+        $('.joyride-tip-guide, .joyride-modal-bg').remove();
380
+        clearTimeout(settings.automate);
381
+        settings = {};
382
+      },
383
+
384
+      restart : function () {
385
+        methods.hide();
386
+        settings.$li = undefined;
387
+        methods.show('init');
388
+      },
389
+
390
+      pos_default : function (init) {
391
+        var half_fold = Math.ceil(settings.$window.height() / 2),
392
+            tip_position = settings.$next_tip.offset(),
393
+            $nub = $('.joyride-nub', settings.$next_tip),
394
+            nub_height = Math.ceil($nub.outerHeight() / 2),
395
+            toggle = init || false;
396
+
397
+        // tip must not be "display: none" to calculate position
398
+        if (toggle) {
399
+          settings.$next_tip.css('visibility', 'hidden');
400
+          settings.$next_tip.show();
401
+        }
402
+
403
+        if (!/body/i.test(settings.$target.selector)) {
404
+
405
+            if (methods.bottom()) {
406
+              settings.$next_tip.css({
407
+                top: (settings.$target.offset().top + nub_height + settings.$target.outerHeight()),
408
+                left: settings.$target.offset().left});
409
+
410
+              methods.nub_position($nub, settings.tipSettings.nubPosition, 'top');
411
+
412
+            } else if (methods.top()) {
413
+
414
+              settings.$next_tip.css({
415
+                top: (settings.$target.offset().top - settings.$next_tip.outerHeight() - nub_height),
416
+                left: settings.$target.offset().left});
417
+
418
+              methods.nub_position($nub, settings.tipSettings.nubPosition, 'bottom');
419
+
420
+            } else if (methods.right()) {
421
+
422
+              settings.$next_tip.css({
423
+                top: settings.$target.offset().top,
424
+                left: (settings.$target.outerWidth() + settings.$target.offset().left)});
425
+
426
+              methods.nub_position($nub, settings.tipSettings.nubPosition, 'left');
427
+
428
+            } else if (methods.left()) {
429
+
430
+              settings.$next_tip.css({
431
+                top: settings.$target.offset().top,
432
+                left: (settings.$target.offset().left - settings.$next_tip.outerWidth() - nub_height)});
433
+
434
+              methods.nub_position($nub, settings.tipSettings.nubPosition, 'right');
435
+
436
+            }
437
+
438
+            if (!methods.visible(methods.corners(settings.$next_tip)) && settings.attempts < settings.tipSettings.tipLocationPattern.length) {
439
+
440
+              $nub.removeClass('bottom')
441
+                .removeClass('top')
442
+                .removeClass('right')
443
+                .removeClass('left');
444
+
445
+              settings.tipSettings.tipLocation = settings.tipSettings.tipLocationPattern[settings.attempts];
446
+
447
+              settings.attempts++;
448
+
449
+              methods.pos_default(true);
450
+
451
+            }
452
+
453
+        } else if (settings.$li.length) {
454
+
455
+          methods.pos_modal($nub);
456
+
457
+        }
458
+
459
+        if (toggle) {
460
+          settings.$next_tip.hide();
461
+          settings.$next_tip.css('visibility', 'visible');
462
+        }
463
+
464
+      },
465
+
466
+      pos_phone : function (init) {
467
+        var tip_height = settings.$next_tip.outerHeight(),
468
+            tip_offset = settings.$next_tip.offset(),
469
+            target_height = settings.$target.outerHeight(),
470
+            $nub = $('.joyride-nub', settings.$next_tip),
471
+            nub_height = Math.ceil($nub.outerHeight() / 2),
472
+            toggle = init || false;
473
+
474
+        $nub.removeClass('bottom')
475
+          .removeClass('top')
476
+          .removeClass('right')
477
+          .removeClass('left');
478
+
479
+        if (toggle) {
480
+          settings.$next_tip.css('visibility', 'hidden');
481
+          settings.$next_tip.show();
482
+        }
483
+
484
+        if (!/body/i.test(settings.$target.selector)) {
485
+
486
+          if (methods.top()) {
487
+
488
+              settings.$next_tip.offset({top: settings.$target.offset().top - tip_height - nub_height});
489
+              $nub.addClass('bottom');
490
+
491
+          } else {
492
+
493
+            settings.$next_tip.offset({top: settings.$target.offset().top + target_height + nub_height});
494
+            $nub.addClass('top');
495
+
496
+          }
497
+
498
+        } else if (settings.$li.length) {
499
+
500
+          methods.pos_modal($nub);
501
+
502
+        }
503
+
504
+        if (toggle) {
505
+          settings.$next_tip.hide();
506
+          settings.$next_tip.css('visibility', 'visible');
507
+        }
508
+      },
509
+
510
+      pos_modal : function ($nub) {
511
+        methods.center();
512
+        $nub.hide();
513
+
514
+        if ($('.joyride-modal-bg').length < 1) {
515
+          $('body').append('<div class="joyride-modal-bg">').show();
516
+        }
517
+
518
+        if (/pop/i.test(settings.tipAnimation)) {
519
+          $('.joyride-modal-bg').show();
520
+        } else {
521
+          $('.joyride-modal-bg').fadeIn(settings.tipAnimationFadeSpeed);
522
+        }
523
+      },
524
+
525
+      center : function () {
526
+        var $w = settings.$window;
527
+
528
+        settings.$next_tip.css({
529
+          top : ((($w.height() - settings.$next_tip.outerHeight()) / 2) + $w.scrollTop()),
530
+          left : ((($w.width() - settings.$next_tip.outerWidth()) / 2) + $w.scrollLeft())
531
+        });
532
+
533
+        return true;
534
+      },
535
+
536
+      bottom : function () {
537
+        return /bottom/i.test(settings.tipSettings.tipLocation);
538
+      },
539
+
540
+      top : function () {
541
+        return /top/i.test(settings.tipSettings.tipLocation);
542
+      },
543
+
544
+      right : function () {
545
+        return /right/i.test(settings.tipSettings.tipLocation);
546
+      },
547
+
548
+      left : function () {
549
+        return /left/i.test(settings.tipSettings.tipLocation);
550
+      },
551
+
552
+      corners : function (el) {
553
+        var w = settings.$window,
554
+            right = w.width() + w.scrollLeft(),
555
+            bottom = w.width() + w.scrollTop();
556
+
557
+        return [
558
+          el.offset().top <= w.scrollTop(),
559
+          right <= el.offset().left + el.outerWidth(),
560
+          bottom <= el.offset().top + el.outerHeight(),
561
+          w.scrollLeft() >= el.offset().left
562
+        ];
563
+      },
564
+
565
+      visible : function (hidden_corners) {
566
+        var i = hidden_corners.length;
567
+
568
+        while (i--) {
569
+          if (hidden_corners[i]) return false;
570
+        }
571
+
572
+        return true;
573
+      },
574
+
575
+      nub_position : function (nub, pos, def) {
576
+        if (pos === 'auto') {
577
+          nub.addClass(def);
578
+        } else {
579
+          nub.addClass(pos);
580
+        }
581
+      },
582
+
583
+      startTimer : function () {
584
+        if (settings.$li.length) {
585
+          settings.automate = setTimeout(function () {
586
+            methods.hide();
587
+            methods.show();
588
+            methods.startTimer();
589
+          }, settings.timer);
590
+        } else {
591
+          clearTimeout(settings.automate);
592
+        }
593
+      },
594
+
595
+      end : function () {
596
+        if (settings.cookieMonster) {
597
+          $.cookie(settings.cookieName, 'ridden', { expires: 365, domain: settings.cookieDomain });
598
+        }
599
+
600
+        if (settings.timer > 0) {
601
+          clearTimeout(settings.automate);
602
+        }
603
+
604
+        $('.joyride-modal-bg').hide();
605
+        settings.$current_tip.hide();
606
+        settings.postStepCallback(settings.$li.index(), settings.$current_tip);
607
+        settings.postRideCallback(settings.$li.index(), settings.$current_tip);
608
+      },
609
+
610
+      jquery_check : function () {
611
+        // define on() and off() for older jQuery
612
+        if (!$.isFunction($.fn.on)) {
613
+
614
+          $.fn.on = function (types, sel, fn) {
615
+
616
+            return this.delegate(sel, types, fn);
617
+
618
+          };
619
+
620
+          $.fn.off = function (types, sel, fn) {
621
+
622
+            return this.undelegate(sel, types, fn);
623
+
624
+          };
625
+
626
+          return false;
627
+        }
628
+
629
+        return true;
630
+      },
631
+
632
+      outerHTML : function (el) {
633
+        // support FireFox < 11
634
+        return el.outerHTML || new XMLSerializer().serializeToString(el);
635
+      },
636
+
637
+      version : function () {
638
+        return settings.version;
639
+      }
640
+
641
+    };
642
+
643
+  $.fn.joyride = function (method) {
644
+    if (methods[method]) {
645
+      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
646
+    } else if (typeof method === 'object' || !method) {
647
+      return methods.init.apply(this, arguments);
648
+    } else {
649
+      $.error('Method ' +  method + ' does not exist on jQuery.joyride');
650
+    }
651
+  };
652
+
653
+}(jQuery, this));