Browse code

Remote Progress

Benjamin Roth authored on19/12/2022 15:18:45
Showing59 changed files
1 1
new file mode 100644
2 2
Binary files /dev/null and b/files/pub/Videos/Start/Master_AldeGott_Imagefilm_2022_1080P.mp4 differ
... ...
@@ -11,6 +11,11 @@
11 11
     vertical-align: middle;
12 12
   }
13 13
 
14
+  > video {
15
+    max-width: 100%;
16
+    height: auto;
17
+  }
18
+
14 19
   .responsive {
15 20
     overflow: hidden;
16 21
     position: relative;
... ...
@@ -138,6 +138,85 @@ html {
138 138
   }
139 139
 }
140 140
 
141
+#image-film-link {
142
+  z-index: 0;
143
+  position: absolute;
144
+  left: 40px;
145
+  bottom: 120px;
146
+  text-transform: uppercase;
147
+  font-family: $font-family-alternate;
148
+  font-weight: 700;
149
+  font-size: font-size(10px);
150
+  letter-spacing: 0.125em;
151
+  color: $color-bg-tertiary;
152
+
153
+  padding-left: 42px;
154
+  height: 32px;
155
+  line-height: 32px;
156
+
157
+  &:before {
158
+    position: absolute;
159
+    top: 0;
160
+    left: 0;
161
+    width: 32px;
162
+    height: 32px;
163
+    background-color: $color-bg-tertiary;
164
+    border-radius: 100%;
165
+    box-sizing: border-box;
166
+    content: '';
167
+    -webkit-mask-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8' standalone='no'%3F%3E%3C!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3E%3Csvg width='100%25' height='100%25' viewBox='0 0 36 36' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xml:space='preserve' xmlns:serif='http://www.serif.com/' style='fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;'%3E%3Cpath d='M36,0l0,36l-36,0l0,-36l36,0Zm-13.08,18.533c0.225,-0.398 0.225,-0.998 0,-1.396l-5.753,-9.472c-0.225,-0.397 -0.81,-0.547 -1.125,-0.3l-2.385,1.2c-0.36,0.248 -0.45,0.9 -0.225,1.297l4.808,7.973l-4.763,7.875c-0.27,0.45 -0.135,1.095 0.135,1.298l2.43,1.244c0.36,0.248 0.9,0.053 1.125,-0.3l5.753,-9.42l0,0.001Z'/%3E%3C/svg%3E");
168
+    mask-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8' standalone='no'%3F%3E%3C!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3E%3Csvg width='100%25' height='100%25' viewBox='0 0 36 36' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xml:space='preserve' xmlns:serif='http://www.serif.com/' style='fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;'%3E%3Cpath d='M36,0l0,36l-36,0l0,-36l36,0Zm-13.08,18.533c0.225,-0.398 0.225,-0.998 0,-1.396l-5.753,-9.472c-0.225,-0.397 -0.81,-0.547 -1.125,-0.3l-2.385,1.2c-0.36,0.248 -0.45,0.9 -0.225,1.297l4.808,7.973l-4.763,7.875c-0.27,0.45 -0.135,1.095 0.135,1.298l2.43,1.244c0.36,0.248 0.9,0.053 1.125,-0.3l5.753,-9.42l0,0.001Z'/%3E%3C/svg%3E");
169
+    -webkit-mask-repeat: no-repeat;
170
+    mask-repeat: no-repeat;
171
+  }
172
+  &:after {
173
+    position: absolute;
174
+    top: 0;
175
+    left: 0;
176
+    z-index: -1;
177
+    content: '';
178
+    width: 32px;
179
+    height: 32px;
180
+    box-shadow: 0 0 0 0 rgba(255, 255, 255, .1);
181
+    border-radius: 100%;
182
+    opacity: 0;
183
+    -webkit-animation: pulsate 3s infinite;
184
+    animation: pulsate 3s infinite;
185
+    box-sizing: border-box;
186
+  }
187
+
188
+  @-webkit-keyframes pulsate {
189
+    0% {
190
+      opacity: 0;
191
+    }
192
+    30% {
193
+      opacity: 1;
194
+    }
195
+    60% {
196
+      box-shadow: 0 0 0 20px rgba(255,255,255,.3);
197
+      opacity: 0;
198
+    }
199
+    100% {
200
+      opacity: 0;
201
+    }
202
+  }
203
+  @keyframes pulsate {
204
+    0% {
205
+      opacity: 0;
206
+    }
207
+    30% {
208
+      opacity: 1;
209
+    }
210
+    60% {
211
+      box-shadow: 0 0 0 20px rgba(255,255,255,.3);
212
+      opacity: 0;
213
+    }
214
+    100% {
215
+      opacity: 0;
216
+    }
217
+  }
218
+}
219
+
141 220
 #player-audio-controls {
142 221
   position: absolute;
143 222
   right: 40px;
144 223
new file mode 100644
... ...
@@ -0,0 +1,21 @@
1
+MIT License
2
+
3
+Copyright (c) 2020 Stephan Wagner
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy
6
+of this software and associated documentation files (the "Software"), to deal
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+copies of the Software, and to permit persons to whom the Software is
10
+furnished to do so, subject to the following conditions:
11
+
12
+The above copyright notice and this permission notice shall be included in all
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.
0 22
new file mode 100644
... ...
@@ -0,0 +1,1251 @@
1
+.jBox-wrapper {
2
+  text-align: left;
3
+  box-sizing: border-box;
4
+}
5
+
6
+.jBox-title,
7
+.jBox-content,
8
+.jBox-container {
9
+  position: relative;
10
+  word-break: break-word;
11
+  box-sizing: border-box;
12
+}
13
+
14
+.jBox-container {
15
+  background: #fff;
16
+}
17
+
18
+.jBox-content {
19
+  padding: 8px 12px;
20
+  overflow-x: hidden;
21
+  overflow-y: auto;
22
+  transition: opacity .2s;
23
+}
24
+
25
+.jBox-footer {
26
+  box-sizing: border-box;
27
+}
28
+
29
+.jBox-Tooltip .jBox-container,
30
+.jBox-Mouse .jBox-container {
31
+  border-radius: 4px;
32
+  box-shadow: 0 0 3px rgba(0, 0, 0, 0.25);
33
+}
34
+
35
+.jBox-Tooltip .jBox-title,
36
+.jBox-Mouse .jBox-title {
37
+  padding: 8px 10px 0;
38
+  font-weight: bold;
39
+}
40
+
41
+.jBox-Tooltip.jBox-hasTitle .jBox-content,
42
+.jBox-Mouse.jBox-hasTitle .jBox-content {
43
+  padding-top: 5px;
44
+}
45
+
46
+.jBox-Mouse {
47
+  pointer-events: none;
48
+}
49
+
50
+.jBox-pointer {
51
+  position: absolute;
52
+  overflow: hidden;
53
+  box-sizing: border-box;
54
+}
55
+
56
+.jBox-pointer:after {
57
+  content: '';
58
+  width: 20px;
59
+  height: 20px;
60
+  position: absolute;
61
+  background: #fff;
62
+  transform: rotate(45deg);
63
+  box-sizing: border-box;
64
+}
65
+
66
+.jBox-pointer-top {
67
+  top: 0;
68
+}
69
+
70
+.jBox-pointer-top:after {
71
+  left: 5px;
72
+  top: 6px;
73
+  box-shadow: -1px -1px 2px rgba(0, 0, 0, 0.15);
74
+}
75
+
76
+.jBox-pointer-right {
77
+  right: 0;
78
+}
79
+
80
+.jBox-pointer-right:after {
81
+  top: 5px;
82
+  right: 6px;
83
+  box-shadow: 1px -1px 2px rgba(0, 0, 0, 0.15);
84
+}
85
+
86
+.jBox-pointer-left {
87
+  left: 0;
88
+}
89
+
90
+.jBox-pointer-left:after {
91
+  top: 5px;
92
+  left: 6px;
93
+  box-shadow: -1px 1px 2px rgba(0, 0, 0, 0.15);
94
+}
95
+
96
+.jBox-pointer-bottom {
97
+  bottom: 0;
98
+}
99
+
100
+.jBox-pointer-bottom:after {
101
+  left: 5px;
102
+  bottom: 6px;
103
+  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.15);
104
+}
105
+
106
+.jBox-pointer-top, .jBox-pointer-bottom {
107
+  width: 30px;
108
+  height: 12px;
109
+}
110
+
111
+.jBox-pointer-left, .jBox-pointer-right {
112
+  width: 12px;
113
+  height: 30px;
114
+}
115
+
116
+.jBox-Modal .jBox-container {
117
+  border-radius: 4px;
118
+}
119
+
120
+.jBox-Modal .jBox-container, .jBox-Modal.jBox-closeButton-box:before {
121
+  box-shadow: 0 3px 15px rgba(0, 0, 0, 0.4), 0 0 5px rgba(0, 0, 0, 0.4);
122
+}
123
+
124
+.jBox-Modal .jBox-content {
125
+  padding: 15px 20px;
126
+}
127
+
128
+.jBox-Modal .jBox-title {
129
+  border-radius: 4px 4px 0 0;
130
+  padding: 15px 20px;
131
+  background: #fafafa;
132
+  border-bottom: 1px solid #eee;
133
+}
134
+
135
+.jBox-Modal.jBox-closeButton-title .jBox-title {
136
+  padding-right: 65px;
137
+}
138
+
139
+.jBox-Modal .jBox-footer {
140
+  border-radius: 0 0 4px 4px;
141
+}
142
+
143
+.jBox-closeButton {
144
+  z-index: 1;
145
+  cursor: pointer;
146
+  position: absolute;
147
+  box-sizing: border-box;
148
+}
149
+
150
+.jBox-closeButton svg {
151
+  position: absolute;
152
+  top: 50%;
153
+  right: 50%;
154
+}
155
+
156
+.jBox-closeButton path {
157
+  fill: #aaa;
158
+  transition: fill .2s;
159
+}
160
+
161
+.jBox-closeButton:hover path {
162
+  fill: #888;
163
+}
164
+
165
+.jBox-overlay .jBox-closeButton {
166
+  top: 0;
167
+  right: 0;
168
+  width: 40px;
169
+  height: 40px;
170
+}
171
+
172
+.jBox-overlay .jBox-closeButton svg {
173
+  width: 20px;
174
+  height: 20px;
175
+  margin-top: -10px;
176
+  margin-right: -10px;
177
+}
178
+
179
+.jBox-overlay .jBox-closeButton path {
180
+  fill: #ddd;
181
+}
182
+
183
+.jBox-overlay .jBox-closeButton:hover path {
184
+  fill: #fff;
185
+}
186
+
187
+.jBox-closeButton-title .jBox-closeButton {
188
+  top: 0;
189
+  right: 0;
190
+  bottom: 0;
191
+  width: 50px;
192
+}
193
+
194
+.jBox-closeButton-title svg {
195
+  width: 12px;
196
+  height: 12px;
197
+  margin-top: -6px;
198
+  margin-right: -6px;
199
+}
200
+
201
+.jBox-closeButton-box {
202
+  box-sizing: border-box;
203
+}
204
+
205
+.jBox-closeButton-box .jBox-closeButton {
206
+  top: -8px;
207
+  right: -10px;
208
+  width: 24px;
209
+  height: 24px;
210
+  background: #fff;
211
+  border-radius: 50%;
212
+}
213
+
214
+.jBox-closeButton-box .jBox-closeButton svg {
215
+  width: 10px;
216
+  height: 10px;
217
+  margin-top: -5px;
218
+  margin-right: -5px;
219
+}
220
+
221
+.jBox-closeButton-box:before {
222
+  content: '';
223
+  position: absolute;
224
+  top: -8px;
225
+  right: -10px;
226
+  width: 24px;
227
+  height: 24px;
228
+  border-radius: 50%;
229
+  box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
230
+}
231
+
232
+.jBox-closeButton-box.jBox-pointerPosition-top:before {
233
+  top: 5px;
234
+}
235
+
236
+.jBox-closeButton-box.jBox-pointerPosition-right:before {
237
+  right: 2px;
238
+}
239
+
240
+.jBox-Modal.jBox-hasTitle.jBox-closeButton-box .jBox-closeButton {
241
+  background: #fafafa;
242
+}
243
+
244
+.jBox-overlay {
245
+  position: fixed;
246
+  top: 0;
247
+  left: 0;
248
+  width: 100%;
249
+  height: 100%;
250
+  background-color: rgba(0, 0, 0, 0.82);
251
+}
252
+
253
+.jBox-footer {
254
+  background: #fafafa;
255
+  border-top: 1px solid #eee;
256
+  padding: 8px 10px;
257
+  border-radius: 0 0 3px 3px;
258
+}
259
+
260
+body[class^="jBox-blockScroll-"],
261
+body[class*=" jBox-blockScroll-"] {
262
+  overflow: hidden;
263
+}
264
+
265
+.jBox-draggable {
266
+  cursor: move;
267
+}
268
+
269
+@keyframes jBoxLoading {
270
+  to {
271
+    transform: rotate(360deg);
272
+  }
273
+}
274
+
275
+.jBox-loading .jBox-content {
276
+  opacity: .2;
277
+}
278
+
279
+.jBox-loading-spinner .jBox-content {
280
+  min-height: 38px !important;
281
+  min-width: 38px !important;
282
+  opacity: 0;
283
+}
284
+
285
+.jBox-spinner {
286
+  box-sizing: border-box;
287
+  position: absolute;
288
+  top: 50%;
289
+  left: 50%;
290
+  width: 24px;
291
+  height: 24px;
292
+  margin-top: -12px;
293
+  margin-left: -12px;
294
+}
295
+
296
+.jBox-spinner:before {
297
+  display: block;
298
+  box-sizing: border-box;
299
+  content: '';
300
+  width: 24px;
301
+  height: 24px;
302
+  border-radius: 50%;
303
+  border: 2px solid rgba(0, 0, 0, 0.2);
304
+  border-top-color: rgba(0, 0, 0, 0.8);
305
+  animation: jBoxLoading .6s linear infinite;
306
+}
307
+
308
+.jBox-countdown {
309
+  border-radius: 4px 4px 0 0;
310
+  z-index: 0;
311
+  background: #000;
312
+  opacity: .2;
313
+  position: absolute;
314
+  top: 0;
315
+  left: 0;
316
+  right: 0;
317
+  height: 3px;
318
+  overflow: hidden;
319
+}
320
+
321
+.jBox-countdown-inner {
322
+  top: 0;
323
+  right: 0;
324
+  width: 100%;
325
+  height: 3px;
326
+  position: absolute;
327
+  background: #fff;
328
+}
329
+
330
+[class^="jBox-animated-"],
331
+[class*=" jBox-animated-"] {
332
+  animation-fill-mode: both;
333
+}
334
+
335
+@keyframes jBox-tada {
336
+  0% {
337
+    transform: scale(1);
338
+  }
339
+  10%,
340
+  20% {
341
+    transform: scale(0.8) rotate(-4deg);
342
+  }
343
+  30%,
344
+  50%,
345
+  70%,
346
+  90% {
347
+    transform: scale(1.2) rotate(4deg);
348
+  }
349
+  40%,
350
+  60%,
351
+  80% {
352
+    transform: scale(1.2) rotate(-4deg);
353
+  }
354
+  100% {
355
+    transform: scale(1) rotate(0);
356
+  }
357
+}
358
+
359
+.jBox-animated-tada {
360
+  animation: jBox-tada 1s;
361
+}
362
+
363
+@keyframes jBox-tadaSmall {
364
+  0% {
365
+    transform: scale(1);
366
+  }
367
+  10%,
368
+  20% {
369
+    transform: scale(0.9) rotate(-2deg);
370
+  }
371
+  30%,
372
+  50%,
373
+  70%,
374
+  90% {
375
+    transform: scale(1.1) rotate(2deg);
376
+  }
377
+  40%,
378
+  60%,
379
+  80% {
380
+    transform: scale(1.1) rotate(-2deg);
381
+  }
382
+  100% {
383
+    transform: scale(1) rotate(0);
384
+  }
385
+}
386
+
387
+.jBox-animated-tadaSmall {
388
+  animation: jBox-tadaSmall 1s;
389
+}
390
+
391
+@keyframes jBox-flash {
392
+  0%,
393
+  50%,
394
+  100% {
395
+    opacity: 1;
396
+  }
397
+  25%,
398
+  75% {
399
+    opacity: 0;
400
+  }
401
+}
402
+
403
+.jBox-animated-flash {
404
+  animation: jBox-flash .5s;
405
+}
406
+
407
+@keyframes jBox-shake {
408
+  0%,
409
+  100% {
410
+    transform: translateX(0);
411
+  }
412
+  20%,
413
+  60% {
414
+    transform: translateX(-6px);
415
+  }
416
+  40%,
417
+  80% {
418
+    transform: translateX(6px);
419
+  }
420
+}
421
+
422
+.jBox-animated-shake {
423
+  animation: jBox-shake .4s;
424
+}
425
+
426
+@keyframes jBox-pulseUp {
427
+  0% {
428
+    transform: scale(1);
429
+  }
430
+  50% {
431
+    transform: scale(1.15);
432
+  }
433
+  100% {
434
+    transform: scale(1);
435
+  }
436
+}
437
+
438
+.jBox-animated-pulseUp {
439
+  animation: jBox-pulseUp .25s;
440
+}
441
+
442
+@keyframes jBox-pulseDown {
443
+  0% {
444
+    transform: scale(1);
445
+  }
446
+  50% {
447
+    transform: scale(0.85);
448
+  }
449
+  100% {
450
+    transform: scale(1);
451
+  }
452
+}
453
+
454
+.jBox-animated-pulseDown {
455
+  animation: jBox-pulseDown .25s;
456
+}
457
+
458
+@keyframes jBox-popIn {
459
+  0% {
460
+    transform: scale(0);
461
+  }
462
+  50% {
463
+    transform: scale(1.1);
464
+  }
465
+  100% {
466
+    transform: scale(1);
467
+  }
468
+}
469
+
470
+.jBox-animated-popIn {
471
+  animation: jBox-popIn .25s;
472
+}
473
+
474
+@keyframes jBox-popOut {
475
+  0% {
476
+    transform: scale(1);
477
+  }
478
+  50% {
479
+    transform: scale(1.1);
480
+  }
481
+  100% {
482
+    transform: scale(0);
483
+  }
484
+}
485
+
486
+.jBox-animated-popOut {
487
+  animation: jBox-popOut .25s;
488
+}
489
+
490
+@keyframes jBox-fadeIn {
491
+  0% {
492
+    opacity: 0;
493
+  }
494
+  100% {
495
+    opacity: 1;
496
+  }
497
+}
498
+
499
+.jBox-animated-fadeIn {
500
+  animation: jBox-fadeIn .2s;
501
+}
502
+
503
+@keyframes jBox-fadeOut {
504
+  0% {
505
+    opacity: 1;
506
+  }
507
+  100% {
508
+    opacity: 0;
509
+  }
510
+}
511
+
512
+.jBox-animated-fadeOut {
513
+  animation: jBox-fadeOut .2s;
514
+}
515
+
516
+@keyframes jBox-slideUp {
517
+  0% {
518
+    transform: translateY(0);
519
+  }
520
+  100% {
521
+    transform: translateY(-300px);
522
+    opacity: 0;
523
+  }
524
+}
525
+
526
+.jBox-animated-slideUp {
527
+  animation: jBox-slideUp .4s;
528
+}
529
+
530
+@keyframes jBox-slideRight {
531
+  0% {
532
+    transform: translateX(0);
533
+  }
534
+  100% {
535
+    transform: translateX(300px);
536
+    opacity: 0;
537
+  }
538
+}
539
+
540
+.jBox-animated-slideRight {
541
+  animation: jBox-slideRight .4s;
542
+}
543
+
544
+@keyframes jBox-slideDown {
545
+  0% {
546
+    transform: translateY(0);
547
+  }
548
+  100% {
549
+    transform: translateY(300px);
550
+    opacity: 0;
551
+  }
552
+}
553
+
554
+.jBox-animated-slideDown {
555
+  animation: jBox-slideDown .4s;
556
+}
557
+
558
+@keyframes jBox-slideLeft {
559
+  0% {
560
+    transform: translateX(0);
561
+  }
562
+  100% {
563
+    transform: translateX(-300px);
564
+    opacity: 0;
565
+  }
566
+}
567
+
568
+.jBox-animated-slideLeft {
569
+  animation: jBox-slideLeft .4s;
570
+}
571
+
572
+.jBox-Confirm .jBox-content {
573
+  text-align: center;
574
+  padding: 46px 35px;
575
+}
576
+
577
+@media (max-width: 500px) {
578
+  .jBox-Confirm .jBox-content {
579
+    padding: 32px 20px;
580
+  }
581
+}
582
+
583
+.jBox-Confirm-footer {
584
+  height: 46px;
585
+}
586
+
587
+.jBox-Confirm-button {
588
+  display: block;
589
+  float: left;
590
+  cursor: pointer;
591
+  text-align: center;
592
+  width: 50%;
593
+  line-height: 46px;
594
+  height: 46px;
595
+  overflow: hidden;
596
+  padding: 0 10px;
597
+  transition: color .2s, background-color .2s;
598
+  box-sizing: border-box;
599
+}
600
+
601
+.jBox-Confirm-button-cancel {
602
+  border-bottom-left-radius: 4px;
603
+  background: #ddd;
604
+  color: #666;
605
+}
606
+
607
+.jBox-Confirm-button-cancel:hover, .jBox-Confirm-button-cancel:active {
608
+  background: #ccc;
609
+}
610
+
611
+.jBox-Confirm-button-cancel:active {
612
+  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
613
+}
614
+
615
+.jBox-Confirm-button-submit {
616
+  border-bottom-right-radius: 4px;
617
+  background: #7d0;
618
+  color: #fff;
619
+}
620
+
621
+.jBox-Confirm-button-submit:hover, .jBox-Confirm-button-submit:active {
622
+  background: #6c0;
623
+}
624
+
625
+.jBox-Confirm-button-submit:active {
626
+  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
627
+}
628
+
629
+.jBox-Image .jBox-container {
630
+  background-color: transparent;
631
+}
632
+
633
+.jBox-Image .jBox-content {
634
+  padding: 0;
635
+  width: 100%;
636
+  height: 100%;
637
+}
638
+
639
+.jBox-image-container {
640
+  background: center center no-repeat;
641
+  position: absolute;
642
+  width: 100%;
643
+  height: 100%;
644
+  opacity: 0;
645
+}
646
+
647
+.jBox-image-label-wrapper {
648
+  position: absolute;
649
+  top: 100%;
650
+  left: 0;
651
+  right: 0;
652
+  height: 40px;
653
+  z-index: 100;
654
+  display: flex;
655
+}
656
+
657
+.jBox-image-label-container {
658
+  position: relative;
659
+  flex: 1;
660
+}
661
+
662
+.jBox-image-label {
663
+  box-sizing: border-box;
664
+  position: absolute;
665
+  left: 0;
666
+  bottom: 0;
667
+  width: 100%;
668
+  text-align: center;
669
+  color: #fff;
670
+  padding: 8px 12px;
671
+  font-size: 15px;
672
+  line-height: 24px;
673
+  transition: opacity .36s;
674
+  opacity: 0;
675
+  z-index: 0;
676
+  pointer-events: none;
677
+}
678
+
679
+.jBox-image-label.expanded {
680
+  background: #000;
681
+}
682
+
683
+.jBox-image-label:not(.expanded) {
684
+  text-overflow: ellipsis;
685
+  white-space: nowrap;
686
+  overflow: hidden;
687
+}
688
+
689
+.jBox-image-label.active {
690
+  opacity: 1;
691
+  pointer-events: all;
692
+}
693
+
694
+@media (max-width: 600px) {
695
+  .jBox-image-label {
696
+    font-size: 13px;
697
+  }
698
+}
699
+
700
+.jBox-image-pointer-next,
701
+.jBox-image-pointer-prev {
702
+  flex-shrink: 0;
703
+  width: 40px;
704
+  height: 40px;
705
+  cursor: pointer;
706
+  opacity: .8;
707
+  transition: opacity .2s;
708
+  background: no-repeat center center url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ijc0LjcgMjI0IDE4LjcgMzIiPg0KPHBhdGggZmlsbD0iI2ZmZmZmZiIgZD0iTTkzLDIyNy40TDgwLjQsMjQwTDkzLDI1Mi42YzAuNCwwLjQsMC40LDEuMSwwLDEuNWwtMS42LDEuNmMtMC40LDAuNC0xLDAuNS0xLjUsMEw3NSwyNDAuN2MtMC40LTAuNC0wLjUtMSwwLTEuNWwxNC45LTE0LjljMC40LTAuNCwxLTAuNCwxLjUsMGwxLjYsMS42QzkzLjUsMjI2LjQsOTMuNCwyMjcsOTMsMjI3LjR6Ii8+DQo8L3N2Zz4=);
709
+  background-size: 11px auto;
710
+  user-select: none;
711
+  z-index: 1;
712
+}
713
+
714
+.jBox-image-pointer-next:hover,
715
+.jBox-image-pointer-prev:hover {
716
+  opacity: 1;
717
+}
718
+
719
+.jBox-image-pointer-next {
720
+  transform: scaleX(-1);
721
+}
722
+
723
+.jBox-image-counter-container {
724
+  flex-shrink: 0;
725
+  white-space: nowrap;
726
+  height: 40px;
727
+  line-height: 40px;
728
+  font-size: 13px;
729
+  color: #fff;
730
+  text-align: right;
731
+  display: none;
732
+}
733
+
734
+.jBox-image-has-counter .jBox-image-counter-container {
735
+  display: block;
736
+}
737
+
738
+.jBox-overlay.jBox-overlay-Image {
739
+  background: #000;
740
+}
741
+
742
+.jBox-image-not-found {
743
+  background: #000;
744
+}
745
+
746
+.jBox-image-not-found:before {
747
+  content: '';
748
+  box-sizing: border-box;
749
+  display: block;
750
+  width: 80px;
751
+  height: 80px;
752
+  margin-top: -40px;
753
+  margin-left: -40px;
754
+  position: absolute;
755
+  top: 50%;
756
+  left: 50%;
757
+  border: 5px solid #222;
758
+  border-radius: 50%;
759
+}
760
+
761
+.jBox-image-not-found:after {
762
+  content: '';
763
+  display: block;
764
+  box-sizing: content-box;
765
+  z-index: auto;
766
+  width: 6px;
767
+  height: 74px;
768
+  margin-top: -37px;
769
+  margin-left: -3px;
770
+  position: absolute;
771
+  top: 50%;
772
+  left: 50%;
773
+  background: #222;
774
+  transform: rotateZ(45deg);
775
+  transform-origin: 50% 50% 0;
776
+}
777
+
778
+.jBox-image-download-button-wrapper {
779
+  position: absolute;
780
+  top: -40px;
781
+  right: 35px;
782
+  height: 40px;
783
+  display: flex;
784
+  cursor: pointer;
785
+  opacity: .8;
786
+  transition: opacity .2s;
787
+}
788
+
789
+.jBox-image-download-button-wrapper:hover {
790
+  opacity: 1;
791
+}
792
+
793
+.jBox-image-download-button-icon {
794
+  width: 40px;
795
+  height: 40px;
796
+  background: center center no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNjQwIj48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNNDE2IDI1NnYtMTkyaC0xOTJ2MTkyaC0xNjBsMjU2IDI1NiAyNTYtMjU2aC0xNjB6TTAgNTc2aDY0MHY2NGgtNjQwdi02NHoiPjwvcGF0aD48L3N2Zz4=);
797
+  background-size: 60%;
798
+}
799
+
800
+.jBox-image-download-button-text {
801
+  white-space: nowrap;
802
+  line-height: 40px;
803
+  padding: 0 10px 0 0;
804
+  color: #fff;
805
+  font-size: 14px;
806
+}
807
+
808
+@keyframes jBoxImageLoading {
809
+  to {
810
+    transform: rotate(360deg);
811
+  }
812
+}
813
+
814
+.jBox-image-loading:before {
815
+  content: '';
816
+  position: absolute;
817
+  top: 50%;
818
+  left: 50%;
819
+  width: 32px;
820
+  height: 32px;
821
+  margin-top: -16px;
822
+  margin-left: -16px;
823
+  border: 4px solid #333;
824
+  border-bottom-color: #666;
825
+  animation: jBoxImageLoading 1.2s linear infinite;
826
+  border-radius: 50%;
827
+}
828
+
829
+.jBox-Notice {
830
+  transition: margin .2s;
831
+}
832
+
833
+.jBox-Notice .jBox-container {
834
+  border-radius: 4px;
835
+  box-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, 0.25), inset -1px -1px 0 0 rgba(0, 0, 0, 0.1);
836
+}
837
+
838
+.jBox-Notice .jBox-content {
839
+  border-radius: 4px;
840
+  padding: 12px 20px;
841
+}
842
+
843
+@media (max-width: 768px) {
844
+  .jBox-Notice .jBox-content {
845
+    padding: 10px 15px;
846
+  }
847
+}
848
+
849
+@media (max-width: 500px) {
850
+  .jBox-Notice .jBox-content {
851
+    padding: 8px 10px;
852
+  }
853
+}
854
+
855
+.jBox-Notice.jBox-hasTitle .jBox-content {
856
+  padding-top: 5px;
857
+}
858
+
859
+@media (max-width: 500px) {
860
+  .jBox-Notice.jBox-hasTitle .jBox-content {
861
+    padding-top: 0;
862
+  }
863
+}
864
+
865
+.jBox-Notice.jBox-hasTitle .jBox-title {
866
+  padding: 12px 20px 0;
867
+  font-weight: bold;
868
+}
869
+
870
+@media (max-width: 768px) {
871
+  .jBox-Notice.jBox-hasTitle .jBox-title {
872
+    padding: 10px 15px 0;
873
+  }
874
+}
875
+
876
+@media (max-width: 500px) {
877
+  .jBox-Notice.jBox-hasTitle .jBox-title {
878
+    padding: 8px 10px 0;
879
+  }
880
+}
881
+
882
+.jBox-Notice.jBox-closeButton-title .jBox-title {
883
+  padding-right: 55px;
884
+}
885
+
886
+.jBox-Notice.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton {
887
+  width: 40px;
888
+}
889
+
890
+.jBox-Notice.jBox-Notice-black .jBox-container {
891
+  color: #fff;
892
+  background: #000;
893
+}
894
+
895
+.jBox-Notice.jBox-Notice-black.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
896
+.jBox-Notice.jBox-Notice-black.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
897
+  fill: #fff;
898
+}
899
+
900
+.jBox-Notice.jBox-Notice-gray .jBox-container {
901
+  color: #222;
902
+  background: #f6f6f6;
903
+}
904
+
905
+.jBox-Notice.jBox-Notice-gray.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
906
+.jBox-Notice.jBox-Notice-gray.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
907
+  fill: #222;
908
+}
909
+
910
+.jBox-Notice.jBox-Notice-red .jBox-container {
911
+  color: #fff;
912
+  background: #d00;
913
+}
914
+
915
+.jBox-Notice.jBox-Notice-red.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
916
+.jBox-Notice.jBox-Notice-red.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
917
+  fill: #fff;
918
+}
919
+
920
+.jBox-Notice.jBox-Notice-green .jBox-container {
921
+  color: #fff;
922
+  background: #5d0;
923
+}
924
+
925
+.jBox-Notice.jBox-Notice-green.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
926
+.jBox-Notice.jBox-Notice-green.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
927
+  fill: #fff;
928
+}
929
+
930
+.jBox-Notice.jBox-Notice-blue .jBox-container {
931
+  color: #fff;
932
+  background: #49d;
933
+}
934
+
935
+.jBox-Notice.jBox-Notice-blue.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
936
+.jBox-Notice.jBox-Notice-blue.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
937
+  fill: #fff;
938
+}
939
+
940
+.jBox-Notice.jBox-Notice-yellow .jBox-container {
941
+  color: #000;
942
+  background: #fd0;
943
+}
944
+
945
+.jBox-Notice.jBox-Notice-yellow.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
946
+.jBox-Notice.jBox-Notice-yellow.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
947
+  fill: #fff;
948
+}
949
+
950
+.jBox-NoticeFancy .jBox-content,
951
+.jBox-NoticeFancy .jBox-title {
952
+  padding-left: 25px;
953
+}
954
+
955
+.jBox-NoticeFancy.jBox-Notice-color .jBox-container {
956
+  color: #fff;
957
+  background: #000;
958
+}
959
+
960
+.jBox-NoticeFancy.jBox-Notice-color .jBox-container:after {
961
+  content: '';
962
+  position: absolute;
963
+  top: 0;
964
+  left: 0;
965
+  bottom: 0;
966
+  width: 8px;
967
+  border-radius: 4px 0 0 4px;
968
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.4) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.4) 75%, transparent 75%, transparent);
969
+  background-size: 14px 14px;
970
+}
971
+
972
+.jBox-NoticeFancy.jBox-Notice-black .jBox-container:after,
973
+.jBox-NoticeFancy.jBox-Notice-gray .jBox-container:after {
974
+  background-color: #888;
975
+}
976
+
977
+.jBox-NoticeFancy.jBox-Notice-red .jBox-container:after {
978
+  background-color: #e00;
979
+}
980
+
981
+.jBox-NoticeFancy.jBox-Notice-green .jBox-container:after {
982
+  background-color: #6c0;
983
+}
984
+
985
+.jBox-NoticeFancy.jBox-Notice-blue .jBox-container:after {
986
+  background-color: #49d;
987
+}
988
+
989
+.jBox-NoticeFancy.jBox-Notice-yellow .jBox-container:after {
990
+  background-color: #fb0;
991
+}
992
+
993
+.jBox-NoticeFancy .jBox-countdown {
994
+  left: 8px;
995
+  border-radius: 0 4px 0 0;
996
+}
997
+
998
+.jBox-TooltipBorder .jBox-container,
999
+.jBox-TooltipBorder .jBox-pointer:after {
1000
+  border: 2px solid #49d;
1001
+}
1002
+
1003
+.jBox-TooltipBorder .jBox-pointer:after {
1004
+  width: 22px;
1005
+  height: 22px;
1006
+}
1007
+
1008
+.jBox-TooltipBorder .jBox-pointer-top,
1009
+.jBox-TooltipBorder .jBox-pointer-bottom {
1010
+  width: 34px;
1011
+  height: 13px;
1012
+}
1013
+
1014
+.jBox-TooltipBorder .jBox-pointer-top:after,
1015
+.jBox-TooltipBorder .jBox-pointer-bottom:after {
1016
+  left: 6px;
1017
+}
1018
+
1019
+.jBox-TooltipBorder .jBox-pointer-left,
1020
+.jBox-TooltipBorder .jBox-pointer-right {
1021
+  width: 13px;
1022
+  height: 34px;
1023
+}
1024
+
1025
+.jBox-TooltipBorder .jBox-pointer-left:after,
1026
+.jBox-TooltipBorder .jBox-pointer-right:after {
1027
+  top: 6px;
1028
+}
1029
+
1030
+.jBox-TooltipBorder.jBox-closeButton-box:before {
1031
+  width: 28px;
1032
+  height: 28px;
1033
+  background: #49d;
1034
+}
1035
+
1036
+.jBox-TooltipBorderThick .jBox-container {
1037
+  box-shadow: none;
1038
+  border-radius: 8px;
1039
+  border: 4px solid #ccc;
1040
+}
1041
+
1042
+.jBox-TooltipBorderThick .jBox-pointer:after {
1043
+  box-shadow: none;
1044
+  border: 4px solid #ccc;
1045
+  width: 24px;
1046
+  height: 24px;
1047
+}
1048
+
1049
+.jBox-TooltipBorderThick .jBox-pointer-top,
1050
+.jBox-TooltipBorderThick .jBox-pointer-bottom {
1051
+  width: 38px;
1052
+  height: 13px;
1053
+}
1054
+
1055
+.jBox-TooltipBorderThick .jBox-pointer-left,
1056
+.jBox-TooltipBorderThick .jBox-pointer-right {
1057
+  width: 13px;
1058
+  height: 38px;
1059
+}
1060
+
1061
+.jBox-TooltipBorderThick.jBox-closeButton-box:before {
1062
+  width: 32px;
1063
+  height: 32px;
1064
+  background: #ccc;
1065
+}
1066
+
1067
+.jBox-TooltipDark .jBox-container {
1068
+  border-radius: 4px;
1069
+  background: #000;
1070
+  color: #fff;
1071
+  box-shadow: 0 0 6px rgba(0, 0, 0, 0.4);
1072
+}
1073
+
1074
+.jBox-TooltipDark .jBox-pointer:after {
1075
+  background: #000;
1076
+}
1077
+
1078
+.jBox-TooltipDark .jBox-closeButton {
1079
+  background: #000;
1080
+}
1081
+
1082
+.jBox-TooltipDark.jBox-closeButton-box:before {
1083
+  box-shadow: 0 0 6px rgba(0, 0, 0, 0.4);
1084
+}
1085
+
1086
+.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton path {
1087
+  fill: #ddd;
1088
+}
1089
+
1090
+.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:hover path {
1091
+  fill: #fff;
1092
+}
1093
+
1094
+.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:active path {
1095
+  fill: #bbb;
1096
+}
1097
+
1098
+.jBox-TooltipError {
1099
+  pointer-events: none;
1100
+}
1101
+
1102
+.jBox-TooltipError .jBox-container {
1103
+  border-radius: 2px;
1104
+  background: #d00;
1105
+  color: #fff;
1106
+  font-weight: bold;
1107
+  font-size: 13px;
1108
+}
1109
+
1110
+.jBox-TooltipError .jBox-content {
1111
+  padding: 0 10px;
1112
+  line-height: 28px;
1113
+}
1114
+
1115
+.jBox-TooltipError .jBox-pointer:after {
1116
+  background: #d00;
1117
+  width: 20px;
1118
+  height: 20px;
1119
+}
1120
+
1121
+.jBox-TooltipError .jBox-pointer-top, .jBox-TooltipError .jBox-pointer-bottom {
1122
+  width: 22px;
1123
+  height: 8px;
1124
+}
1125
+
1126
+.jBox-TooltipError .jBox-pointer-right, .jBox-TooltipError .jBox-pointer-left {
1127
+  width: 8px;
1128
+  height: 22px;
1129
+}
1130
+
1131
+.jBox-TooltipError .jBox-pointer-top:after {
1132
+  left: 1px;
1133
+  top: 6px;
1134
+}
1135
+
1136
+.jBox-TooltipError .jBox-pointer-right:after {
1137
+  top: 1px;
1138
+  right: 6px;
1139
+}
1140
+
1141
+.jBox-TooltipError .jBox-pointer-bottom:after {
1142
+  left: 1px;
1143
+  bottom: 6px;
1144
+}
1145
+
1146
+.jBox-TooltipError .jBox-pointer-left:after {
1147
+  top: 1px;
1148
+  left: 6px;
1149
+}
1150
+
1151
+.jBox-TooltipSmall {
1152
+  pointer-events: none;
1153
+}
1154
+
1155
+.jBox-TooltipSmall .jBox-container {
1156
+  border-radius: 2px;
1157
+}
1158
+
1159
+.jBox-TooltipSmall .jBox-content {
1160
+  padding: 0 10px;
1161
+  line-height: 28px;
1162
+}
1163
+
1164
+.jBox-TooltipSmall .jBox-pointer:after {
1165
+  width: 20px;
1166
+  height: 20px;
1167
+}
1168
+
1169
+.jBox-TooltipSmall .jBox-pointer-top, .jBox-TooltipSmall .jBox-pointer-bottom {
1170
+  width: 22px;
1171
+  height: 8px;
1172
+}
1173
+
1174
+.jBox-TooltipSmall .jBox-pointer-right, .jBox-TooltipSmall .jBox-pointer-left {
1175
+  width: 8px;
1176
+  height: 22px;
1177
+}
1178
+
1179
+.jBox-TooltipSmall .jBox-pointer-top:after {
1180
+  left: 1px;
1181
+  top: 6px;
1182
+}
1183
+
1184
+.jBox-TooltipSmall .jBox-pointer-right:after {
1185
+  top: 1px;
1186
+  right: 6px;
1187
+}
1188
+
1189
+.jBox-TooltipSmall .jBox-pointer-bottom:after {
1190
+  left: 1px;
1191
+  bottom: 6px;
1192
+}
1193
+
1194
+.jBox-TooltipSmall .jBox-pointer-left:after {
1195
+  top: 1px;
1196
+  left: 6px;
1197
+}
1198
+
1199
+.jBox-TooltipSmallGray {
1200
+  pointer-events: none;
1201
+}
1202
+
1203
+.jBox-TooltipSmallGray .jBox-container {
1204
+  font-size: 13px;
1205
+  line-height: 24px;
1206
+  border-radius: 12px;
1207
+  background-image: linear-gradient(to bottom, #fafafa, #f2f2f2);
1208
+}
1209
+
1210
+.jBox-TooltipSmallGray .jBox-content {
1211
+  padding: 0 10px;
1212
+}
1213
+
1214
+.jBox-TooltipSmallGray .jBox-pointer:after {
1215
+  width: 20px;
1216
+  height: 20px;
1217
+}
1218
+
1219
+.jBox-TooltipSmallGray .jBox-pointer-top, .jBox-TooltipSmallGray .jBox-pointer-bottom {
1220
+  width: 22px;
1221
+  height: 8px;
1222
+}
1223
+
1224
+.jBox-TooltipSmallGray .jBox-pointer-left, .jBox-TooltipSmallGray .jBox-pointer-right {
1225
+  width: 8px;
1226
+  height: 22px;
1227
+}
1228
+
1229
+.jBox-TooltipSmallGray .jBox-pointer-top:after {
1230
+  background: #fafafa;
1231
+  left: 1px;
1232
+  top: 6px;
1233
+}
1234
+
1235
+.jBox-TooltipSmallGray .jBox-pointer-right:after {
1236
+  top: 1px;
1237
+  right: 6px;
1238
+}
1239
+
1240
+.jBox-TooltipSmallGray .jBox-pointer-bottom:after {
1241
+  background: #f2f2f2;
1242
+  left: 1px;
1243
+  bottom: 6px;
1244
+}
1245
+
1246
+.jBox-TooltipSmallGray .jBox-pointer-left:after {
1247
+  top: 1px;
1248
+  left: 6px;
1249
+}
1250
+
1251
+/*# sourceMappingURL=jBox.all.css.map */
0 1252
new file mode 100644
... ...
@@ -0,0 +1,2910 @@
1
+/**
2
+ * jBox is a jQuery plugin that makes it easy to create customizable tooltips, modal windows, image galleries and more.
3
+ *
4
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
5
+ *
6
+ * License: MIT (https://opensource.org/licenses/MIT)
7
+ *
8
+ * Requires: jQuery 3.5.0 (https://code.jquery.com/jquery-3.5.0.min.js)
9
+ *
10
+ * Documentation: https://stephanwagner.me/jBox/documentation
11
+ *
12
+ * Demos: https://stephanwagner.me/jBox/demos
13
+ */
14
+
15
+function jBoxWrapper(jQuery) {
16
+
17
+
18
+  var jBox = function jBox(type, options) {
19
+
20
+
21
+    // Options (https://stephanwagner.me/jBox/options)
22
+
23
+    this.options = {
24
+
25
+      // jBox ID
26
+      id: null,                    // Choose a unique id, otherwise jBox will set one for you (jBox1, jBox2, ...)
27
+
28
+      // Dimensions
29
+      width: 'auto',               // The width of the content area, e.g. 'auto', 200, '80%'
30
+      height: 'auto',              // The height of the content area
31
+      minWidth: null,              // Minimal width
32
+      minHeight: null,             // Minimal height
33
+      maxWidth: null,              // Maximal width
34
+      maxHeight: null,             // Maximal height
35
+
36
+      // Responsive dimensions
37
+      responsiveWidth: true,       // Adjusts the width to fit the viewport
38
+      responsiveHeight: true,      // Adjusts the height to fit the viewport
39
+      responsiveMinWidth: 100,     // Don't adjust width below this value (in pixel)
40
+      responsiveMinHeight: 100,    // Don't adjust height below this value (in pixel)
41
+
42
+      // Attach
43
+      attach: null,                // A jQuery selector to elements that will open and close your jBox, e.g. '.tooltip'
44
+      trigger: 'click',            // The event to open or close your jBox, use 'click', 'touchclick' or 'mouseenter'
45
+      preventDefault: false,       // Prevent the default event when opening jBox, e.g. don't follow the href in a link
46
+
47
+      // Content
48
+      content: null,               // You can use HTML or a jQuery element, e.g. jQuery('#jBox-content'). The elements will be appended to the content element and then made visible, so hide them with style="display: none" beforehand
49
+      getContent: null,            // Get the content from an attribute when jBox opens, e.g. getContent: 'data-content'. Use 'html' to get the attached elements HTML as content
50
+      title: null,                 // Adds a title to your jBox
51
+      getTitle: null,              // Get the title from an attribute when jBox opens, e.g. getTitle: 'data-title'
52
+      footer: null,                // Adds a footer to your jBox
53
+      isolateScroll: true,         // Isolates scrolling to the content container
54
+
55
+      // AJAX
56
+      ajax: {                      // Setting an URL will make an AJAX request when jBox opens. Optional you can add any jQuery AJAX option (http://api.jquery.com/jquery.ajax/)
57
+        url: null,                 // The URL to send the AJAX request to
58
+        data: '',                  // Data to send with your AJAX request, e.g. {id: 82, limit: 10}
59
+        reload: false,             // Resend the AJAX request when jBox opens. Use true to send the AJAX request only once for every attached element or 'strict' to resend every time jBox opens
60
+        getURL: 'data-url',        // The attribute in the source element where the AJAX request will look for the URL, e.g. data-url="https://reqres.in/api/users"
61
+        getData: 'data-ajax',      // The attribute in the source element where the AJAX request will look for the data, e.g. data-ajax="id=82&limit=10"
62
+        setContent: true,          // Automatically set the response as new content when the AJAX request is finished
63
+        loadingClass: true,        // Add a class to the wrapper when jBox is loading, set to class name or true to use the default class name 'jBox-loading'
64
+        spinner: true,             // Hides the current content and adds a spinner while loading. You can pass HTML content to add your own spinner, e.g. spinner: '<div class="mySpinner"></div>'
65
+        spinnerDelay: 300,         // Milliseconds to wait until spinner appears
66
+        spinnerReposition: true    // Repositions jBox when the spinner is added or removed
67
+      },
68
+      cancelAjaxOnClose: true,     // Cancels the ajax call when jBox closes and it hasn't finished loading yet
69
+
70
+      // Position
71
+      target: null,                // The jQuery selector to the target element where jBox will be opened. If no element is found, jBox will use the attached element as target
72
+      position: {
73
+        x: 'center',               // Horizontal position, use a number, 'left', 'right' or 'center'
74
+        y: 'center'                // Vertical position, use a number, 'top', 'bottom' or 'center'
75
+      },
76
+      outside: null,               // Use 'x', 'y', or 'xy' to move your jBox outside of the target element
77
+      offset: 0,                   // Offset to final position, you can set different values for x and y with an object, e.g. {x: 20, y: 10}
78
+      attributes: {                // Note that attributes can only be 'left' or 'right' when using numbers for position, e.g. {x: 300, y: 20}
79
+        x: 'left',                 // Horizontal position, use 'left' or 'right'
80
+        y: 'top'                   // Vertical position, use 'top' or 'bottom'
81
+      },
82
+      fixed: false,                // Your jBox will stay on position when scrolling
83
+      adjustPosition: true,        // Adjusts your jBoxes position if there is not enough space, use 'flip', 'move' or true for both. This option overrides the reposition options
84
+      adjustTracker: false,        // By default jBox adjusts its position when it opens or when the window size changes, set to true to also adjust when scrolling
85
+      adjustDistance: 5,           // The minimal distance to the viewport edge while adjusting. Use an object to set different values, e.g. {top: 50, right: 5, bottom: 20, left: 5}
86
+      reposition: true,            // Calculates new position when the window-size changes
87
+      repositionOnOpen: true,      // Calculates new position each time jBox opens (rather than only when it opens the first time)
88
+      repositionOnContent: true,   // Calculates new position when the content changes with .setContent() or .setTitle()
89
+      holdPosition: true,          // Keeps current position if space permits. Applies only to 'Modal' type.
90
+
91
+      // Pointer
92
+      pointer: false,              // Your pointer will always point towards the target element, so the option outside needs to be 'x' or 'y'. By default the pointer is centered, set a position to move it to any side. You can also add an offset, e.g. 'left:30' or 'center:-20'
93
+      pointTo: 'target',           // Setting something else than 'target' will add a pointer even if there is no target element set or found. Use 'top', 'right', 'bottom' or 'left'
94
+
95
+      // Animations
96
+      fade: 180,                   // Fade duration in ms, set to 0 or false to disable
97
+      animation: null,             // Animation when opening or closing, use 'pulse', 'zoomIn', 'zoomOut', 'move', 'slide', 'flip', 'tada' (CSS inspired from Daniel Edens Animate.css: http://daneden.me/animate)
98
+
99
+      // Appearance
100
+      theme: 'Default',            // Set a jBox theme class
101
+      addClass: null,              // Adds classes to the wrapper
102
+      overlay: false,              // Adds an overlay to hide page content when jBox opens (adjust color and opacity with CSS)
103
+      overlayClass: null,          // Add a class name to the overlay
104
+      zIndex: 10000,               // Use a high z-index, or set to 'auto' to bring to front on open
105
+
106
+      // Delays
107
+      delayOpen: 0,                // Delay opening in ms. Note that the delay will be ignored if your jBox didn't finish closing
108
+      delayClose: 0,               // Delay closing in ms. Nnote that there is always a closing delay of at least 10ms to ensure jBox won't be closed when opening right away
109
+
110
+      // Closing
111
+      closeOnEsc: false,           // Close jBox when pressing [esc] key
112
+      closeOnClick: false,         // Close jBox with mouseclick. Use true (click anywhere), 'box' (click on jBox itself), 'overlay' (click on the overlay), 'body' (click anywhere but jBox)
113
+      closeOnMouseleave: false,    // Close jBox when the mouse leaves the jBox area or the area of the attached element
114
+      closeButton: false,          // Adds a close button to your jBox. Use 'title', 'box', 'overlay' or true (true will add the button to the overlay, title or the jBox itself, in that order if any of those elements can be found)
115
+
116
+      // Other options
117
+      appendTo: jQuery('body'),    // The element your jBox will be appended to. Any other element than jQuery('body') is only useful for fixed positions or when position values are numbers
118
+      createOnInit: false,         // Creates jBox and makes it available in DOM when it's being initialized, otherwise it will be created when it opens for the first time
119
+      blockScroll: false,          // Blocks scrolling when jBox is open
120
+      blockScrollAdjust: true,     // Adjust page elements to avoid content jumps when scrolling is blocked. See more here: https://github.com/StephanWagner/unscroll
121
+      draggable: false,            // Make your jBox draggable (use 'true', 'title' or provide an element as handle) (inspired from Chris Coyiers CSS-Tricks http://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/)
122
+      dragOver: true,              // When you have multiple draggable jBoxes, the one you select will always move over the other ones
123
+      autoClose: false,            // Time in ms when jBox will close automatically after it was opened
124
+      delayOnHover: false,         // Delay auto-closing while mouse is hovered
125
+      showCountdown: false,        // Display a nice progress-indicator when autoClose is enabled
126
+
127
+      // Audio                     // You can use the integrated audio function whenever you'd like to play an audio file, e.g. onInit: function () { this.audio('url_to_audio_file_without_file_extension', 75); }
128
+      preloadAudio: true,          // Preloads the audio files set in option audio. You can also preload other audio files, e.g. ['src_to_file.mp3', 'src_to_file.ogg']
129
+      audio: null,                 // The URL to an audio file to play when jBox opens. Set the URL without file extension, jBox will look for an .mp3 and .ogg file. To play audio when jBox closes, use an object, e.g. {open: 'src_to_audio1', close: 'src_to_audio2'}
130
+      volume: 100,                 // The volume in percent. To have different volumes for opening and closeing, use an object, e.g. {open: 75, close: 100}
131
+
132
+      // Events                    // Note that you can use 'this' in all event functions, it refers to your jBox object (e.g. onInit: function () { this.open(); })
133
+      onInit: null,                // Fired when jBox is initialized
134
+      onAttach: null,              // Fired when jBox attached itself to elements, the attached element will be passed as a parameter, e.g. onAttach: function (element) { element.css({color: 'red'}); }
135
+      onPosition: null,            // Fired when jBox is positioned
136
+      onCreated: null,             // Fired when jBox is created and availible in DOM
137
+      onOpen: null,                // Fired when jBox opens
138
+      onClose: null,               // Fired when jBox closes
139
+      onCloseComplete: null,       // Fired when jBox is completely closed (when fading is finished)
140
+      onDragStart: null,           // Fired when dragging starts
141
+      onDragEnd: null              // Fired when dragging finished
142
+    };
143
+
144
+
145
+    // Default plugin options
146
+
147
+    this._pluginOptions = {
148
+
149
+      // Default options for tooltips
150
+      'Tooltip': {
151
+        getContent: 'title',
152
+        trigger: 'mouseenter',
153
+        position: {
154
+          x: 'center',
155
+          y: 'top'
156
+        },
157
+        outside: 'y',
158
+        pointer: true
159
+      },
160
+
161
+      // Default options for mouse tooltips
162
+      'Mouse': {
163
+        responsiveWidth: false,
164
+        responsiveHeight: false,
165
+        adjustPosition: 'flip',
166
+        target: 'mouse',
167
+        trigger: 'mouseenter',
168
+        position: {
169
+          x: 'right',
170
+          y: 'bottom'
171
+        },
172
+        outside: 'xy',
173
+        offset: 5
174
+      },
175
+
176
+      // Default options for modal windows
177
+      'Modal': {
178
+        target: jQuery(window),
179
+        fixed: true,
180
+        blockScroll: true,
181
+        closeOnEsc: true,
182
+        closeOnClick: 'overlay',
183
+        closeButton: true,
184
+        overlay: true,
185
+        animation: 'zoomIn'
186
+      },
187
+    };
188
+
189
+
190
+    // Merge options
191
+
192
+    this.options = jQuery.extend(true, this.options, this._pluginOptions[type] ? this._pluginOptions[type] : jBox._pluginOptions[type], options);
193
+
194
+
195
+    // Set the jBox type
196
+
197
+    jQuery.type(type) == 'string' && (this.type = type);
198
+
199
+
200
+    // Checks if the user is on a touch device, borrowed from https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js
201
+
202
+    this.isTouchDevice = (function () {
203
+      var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
204
+      var mq = function (query) {
205
+        return window.matchMedia(query).matches;
206
+      }
207
+
208
+      if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
209
+        return true;
210
+      }
211
+
212
+      var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
213
+      return mq(query);
214
+    })();
215
+
216
+
217
+    // Add close event for body click when we are on touch device and jBox triggers on mouseenter
218
+
219
+    if (this.isTouchDevice && this.options.trigger === 'mouseenter' && this.options.closeOnClick === false) {
220
+      this.options.closeOnClick = 'body';
221
+    }
222
+
223
+
224
+    // Local function to fire events
225
+
226
+    this._fireEvent = function (event, pass)
227
+    {
228
+      this.options['_' + event] && (this.options['_' + event].bind(this))(pass);
229
+      this.options[event] && (this.options[event].bind(this))(pass);
230
+    };
231
+
232
+
233
+    // Get a unique jBox ID
234
+
235
+    this.options.id === null && (this.options.id = 'jBox' + jBox._getUniqueID());
236
+    this.id = this.options.id;
237
+
238
+
239
+    // Correct impossible options
240
+
241
+    ((this.options.position.x == 'center' && this.options.outside == 'x') || (this.options.position.y == 'center' && this.options.outside == 'y')) && (this.options.outside = null);
242
+    this.options.pointTo == 'target' && (!this.options.outside || this.options.outside == 'xy') && (this.options.pointer = false);
243
+
244
+
245
+    // Correct multiple choice options
246
+
247
+    jQuery.type(this.options.offset) != 'object' ? (this.options.offset = {x: this.options.offset, y: this.options.offset}) : (this.options.offset = jQuery.extend({x: 0, y: 0}, this.options.offset));
248
+    jQuery.type(this.options.adjustDistance) != 'object' ? (this.options.adjustDistance = {top: this.options.adjustDistance, right: this.options.adjustDistance, bottom: this.options.adjustDistance, left: this.options.adjustDistance}) : (this.options.adjustDistance = jQuery.extend({top: 5, left: 5, right: 5, bottom: 5}, this.options.adjustDistance));
249
+
250
+
251
+    // Save default outside position
252
+
253
+    this.outside = this.options.outside && this.options.outside != 'xy' ? this.options.position[this.options.outside] : false;
254
+
255
+
256
+    // Save where the jBox is aligned to
257
+
258
+    this.align = this.outside ? this.outside : (this.options.position.y != 'center' && jQuery.type(this.options.position.y) != 'number' ? this.options.position.x : (this.options.position.x != 'center' && jQuery.type(this.options.position.x) != 'number' ? this.options.position.y : this.options.attributes.x));
259
+
260
+
261
+    // Adjust option zIndex
262
+
263
+    jBox.zIndexMax = Math.max(jBox.zIndexMax || 0, this.options.zIndex === 'auto' ? 10000 : this.options.zIndex);
264
+    if (this.options.zIndex === 'auto') {
265
+      this.adjustZIndexOnOpen = true;
266
+      jBox.zIndexMax += 2;
267
+      this.options.zIndex = jBox.zIndexMax;
268
+      this.trueModal = this.options.overlay;
269
+    }
270
+
271
+    // Internal positioning functions
272
+
273
+    this._getOpp = function (opp) { return {left: 'right', right: 'left', top: 'bottom', bottom: 'top', x: 'y', y: 'x'}[opp]; };
274
+    this._getXY = function (xy) { return {left: 'x', right: 'x', top: 'y', bottom: 'y', center: 'x'}[xy]; };
275
+    this._getTL = function (tl) { return {left: 'left', right: 'left', top: 'top', bottom: 'top', center: 'left', x: 'left', y: 'top'}[tl]; };
276
+
277
+
278
+    // Get a dimension value in integer pixel dependent on appended element
279
+
280
+    this._getInt = function (value, dimension) {
281
+      if (value == 'auto') return 'auto';
282
+      if (value && jQuery.type(value) == 'string' && value.slice(-1) == '%') {
283
+        return jQuery(window)[dimension == 'height' ? 'innerHeight' : 'innerWidth']() * parseInt(value.replace('%', '')) / 100;
284
+      }
285
+      return value;
286
+    };
287
+
288
+
289
+    // Create an svg element
290
+
291
+    this._createSVG = function (type, options)
292
+    {
293
+      var svg = document.createElementNS('http://www.w3.org/2000/svg', type);
294
+      jQuery.each(options, function (index, item) {
295
+        svg.setAttribute(item[0], (item[1] || ''));
296
+      });
297
+      return svg;
298
+    };
299
+
300
+
301
+    // Isolate scrolling in a container
302
+
303
+    this._isolateScroll = function (el)
304
+    {
305
+      // Abort if element not found
306
+      if (!el || !el.length) return;
307
+
308
+      el.on('DOMMouseScroll.jBoxIsolateScroll mousewheel.jBoxIsolateScroll', function (ev) {
309
+        var delta = ev.wheelDelta || (ev.originalEvent && ev.originalEvent.wheelDelta) || -ev.detail;
310
+        var overflowBottom = this.scrollTop + el.outerHeight() - this.scrollHeight >= 0;
311
+        var overflowTop = this.scrollTop <= 0;
312
+        ((delta < 0 && overflowBottom) || (delta > 0 && overflowTop)) && ev.preventDefault();
313
+      });
314
+    };
315
+
316
+
317
+    // Set the title width to content width
318
+
319
+    this._setTitleWidth = function ()
320
+    {
321
+      // Abort if there is no title or width of content is auto
322
+      if (!this.titleContainer || (this.content[0].style.width == 'auto' && !this.content[0].style.maxWidth)) return null;
323
+
324
+      // Expose wrapper to get actual width
325
+      if (this.wrapper.css('display') == 'none') {
326
+        this.wrapper.css('display', 'block');
327
+        var contentWidth = this.content.outerWidth();
328
+        this.wrapper.css('display', 'none');
329
+      } else {
330
+        var contentWidth = this.content.outerWidth();
331
+      }
332
+
333
+      // Set max-width only
334
+      this.titleContainer.css({maxWidth: (Math.max(contentWidth, parseInt(this.content[0].style.maxWidth)) || null)});
335
+    }
336
+
337
+
338
+    // Make jBox draggable
339
+
340
+    this._draggable = function ()
341
+    {
342
+      // Abort if jBox is not draggable
343
+      if (!this.options.draggable) return false;
344
+
345
+      // Get the handle where jBox will be dragged with
346
+      var handle = this.options.draggable == 'title' ? this.titleContainer : (this.options.draggable instanceof jQuery ? this.options.draggable : (jQuery.type(this.options.draggable) == 'string' ? jQuery(this.options.draggable) : this.wrapper));
347
+
348
+      // Abort if no handle or if draggable was set already
349
+      if (!handle || !(handle instanceof jQuery) || !handle.length || handle.data('jBox-draggable')) return false;
350
+
351
+      // Add mouse events
352
+      handle.addClass('jBox-draggable').data('jBox-draggable', true).on('touchstart mousedown', function (ev)
353
+      {
354
+        if (ev.button == 2 || jQuery(ev.target).hasClass('jBox-noDrag') || jQuery(ev.target).parents('.jBox-noDrag').length) return;
355
+
356
+        // Store current mouse position
357
+        this.draggingStartX = ev.pageX;
358
+        this.draggingStartY = ev.pageY;
359
+
360
+        // Adjust z-index when dragging jBox over another draggable jBox
361
+        if (this.options.dragOver && !this.trueModal && parseInt(this.wrapper.css('zIndex'), 10) <= jBox.zIndexMaxDragover) {
362
+          jBox.zIndexMaxDragover += 1;
363
+          this.wrapper.css('zIndex', jBox.zIndexMaxDragover);
364
+        }
365
+
366
+        var drg_h = this.wrapper.outerHeight();
367
+        var drg_w = this.wrapper.outerWidth();
368
+        var pos_y = this.wrapper.offset().top + drg_h - ev.pageY;
369
+        var pos_x = this.wrapper.offset().left + drg_w - ev.pageX;
370
+
371
+        jQuery(document).on('touchmove.jBox-draggable-' + this.id + ' mousemove.jBox-draggable-' + this.id, function (ev) {
372
+          // Fire onDragStart event when jBox moves
373
+          if (!this.dragging && this.draggingStartX != ev.pageX && this.draggingStartY != ev.pageY) {
374
+            this._fireEvent('onDragStart');
375
+            this.dragging = true;
376
+          }
377
+
378
+          // Adjust position
379
+          this.wrapper.offset({
380
+            top: ev.pageY + pos_y - drg_h,
381
+            left: ev.pageX + pos_x - drg_w
382
+          });
383
+        }.bind(this));
384
+        ev.preventDefault();
385
+
386
+      }.bind(this)).on('touchend mouseup', function () {
387
+        // Remove drag event
388
+        jQuery(document).off('touchmove.jBox-draggable-' + this.id + ' mousemove.jBox-draggable-' + this.id);
389
+
390
+        // Fire onDragEnd event
391
+        this.dragging && this._fireEvent('onDragEnd');
392
+
393
+        // Reset dragging reference
394
+        this.dragging = false;
395
+
396
+        if ((this.type == 'Modal' || this.type == 'Confirm') && this.options.holdPosition) {
397
+          // Drag end captures new position
398
+          var jBoxOffset = jQuery('#' + this.id).offset(),
399
+            pos = {
400
+              x: jBoxOffset.left - jQuery(document).scrollLeft(),
401
+              y: jBoxOffset.top - jQuery(document).scrollTop()
402
+            };
403
+          this.position({position: pos, offset: {x: 0, y: 0}});
404
+        }
405
+      }.bind(this));
406
+
407
+      // Get highest z-index
408
+      if (!this.trueModal) {
409
+        jBox.zIndexMaxDragover = !jBox.zIndexMaxDragover ? this.options.zIndex : Math.max(jBox.zIndexMaxDragover, this.options.zIndex);
410
+      }
411
+
412
+      return this;
413
+    };
414
+
415
+    // Create jBox
416
+
417
+    this._create = function ()
418
+    {
419
+      // Abort if jBox was created already
420
+      if (this.wrapper) return;
421
+
422
+      // Create wrapper
423
+      this.wrapper = jQuery('<div/>', {
424
+        id: this.id,
425
+        'class': 'jBox-wrapper' + (this.type ? ' jBox-' + this.type : '') + (this.options.theme ? ' jBox-' + this.options.theme : '') + (this.options.addClass ? ' ' + this.options.addClass : '')
426
+      }).css({
427
+        position: (this.options.fixed ? 'fixed' : 'absolute'),
428
+        display: 'none',
429
+        opacity: 0,
430
+        zIndex: this.options.zIndex
431
+
432
+        // Save the jBox instance in the wrapper, so you can get access to your jBox when you only have the element
433
+      }).data('jBox', this);
434
+
435
+      // Add mouseleave event, only close jBox when the new target is not the source element
436
+      this.options.closeOnMouseleave && this.wrapper.on('mouseleave', function (ev) {
437
+        !this.source || !(ev.relatedTarget == this.source[0] || jQuery.inArray(this.source[0], jQuery(ev.relatedTarget).parents('*')) !== -1) && this.close();
438
+      }.bind(this));
439
+
440
+      // Add closeOnClick: 'box' events
441
+      (this.options.closeOnClick == 'box') && this.wrapper.on('click tap', function () { this.close({ignoreDelay: true}); }.bind(this));
442
+
443
+      // Create container
444
+      this.container = jQuery('<div class="jBox-container"/>').appendTo(this.wrapper);
445
+
446
+      // Create content
447
+      this.content = jQuery('<div class="jBox-content"/>').appendTo(this.container);
448
+
449
+      // Create footer
450
+      this.options.footer && (this.footer = jQuery('<div class="jBox-footer"/>').append(this.options.footer).appendTo(this.container));
451
+
452
+      // Isolate scrolling
453
+      this.options.isolateScroll && this._isolateScroll(this.content);
454
+
455
+      // Create close button
456
+      if (this.options.closeButton) {
457
+        var closeButtonSVG = this._createSVG('svg', [['viewBox', '0 0 24 24']]);
458
+        closeButtonSVG.appendChild(this._createSVG('path', [['d', 'M22.2,4c0,0,0.5,0.6,0,1.1l-6.8,6.8l6.9,6.9c0.5,0.5,0,1.1,0,1.1L20,22.3c0,0-0.6,0.5-1.1,0L12,15.4l-6.9,6.9c-0.5,0.5-1.1,0-1.1,0L1.7,20c0,0-0.5-0.6,0-1.1L8.6,12L1.7,5.1C1.2,4.6,1.7,4,1.7,4L4,1.7c0,0,0.6-0.5,1.1,0L12,8.5l6.8-6.8c0.5-0.5,1.1,0,1.1,0L22.2,4z']]));
459
+        this.closeButton = jQuery('<div class="jBox-closeButton jBox-noDrag"/>').on('click tap', function (ev) { this.close({ignoreDelay: true}); }.bind(this)).append(closeButtonSVG);
460
+
461
+        // Add close button to jBox container
462
+        if (this.options.closeButton == 'box' || (this.options.closeButton === true && !this.options.overlay && !this.options.title && !this.options.getTitle)) {
463
+          this.wrapper.addClass('jBox-closeButton-box');
464
+          this.closeButton.appendTo(this.container);
465
+        }
466
+      }
467
+
468
+      // Append jBox to DOM
469
+      this.wrapper.appendTo(this.options.appendTo);
470
+
471
+      // Fix adjustDistance if there is a close button in the box
472
+      this.wrapper.find('.jBox-closeButton').length &&  jQuery.each(['top', 'right', 'bottom', 'left'], function (index, pos) {
473
+        this.wrapper.find('.jBox-closeButton').css(pos) && this.wrapper.find('.jBox-closeButton').css(pos) != 'auto' && (this.options.adjustDistance[pos] = Math.max(this.options.adjustDistance[pos], this.options.adjustDistance[pos] + (((parseInt(this.wrapper.find('.jBox-closeButton').css(pos)) || 0) + (parseInt(this.container.css('border-' + pos + '-width')) || 0)) * -1)));
474
+      }.bind(this));
475
+
476
+      // Create pointer
477
+      if (this.options.pointer) {
478
+
479
+        // Get pointer vars and save globally
480
+        this.pointer = {
481
+          position: (this.options.pointTo != 'target') ? this.options.pointTo : this._getOpp(this.outside),
482
+          xy: (this.options.pointTo != 'target') ? this._getXY(this.options.pointTo) : this._getXY(this.outside),
483
+          align: 'center',
484
+          offset: 0
485
+        };
486
+
487
+        this.pointer.element = jQuery('<div class="jBox-pointer jBox-pointer-' + this.pointer.position + '"/>').appendTo(this.wrapper);
488
+        this.pointer.dimensions = {
489
+          x: this.pointer.element.outerWidth(),
490
+          y: this.pointer.element.outerHeight()
491
+        };
492
+
493
+        if (jQuery.type(this.options.pointer) == 'string') {
494
+          var split = this.options.pointer.split(':');
495
+          split[0] && (this.pointer.align = split[0]);
496
+          split[1] && (this.pointer.offset = parseInt(split[1]));
497
+        }
498
+        this.pointer.alignAttribute = (this.pointer.xy == 'x' ? (this.pointer.align == 'bottom' ? 'bottom' : 'top') : (this.pointer.align == 'right' ? 'right' : 'left'));
499
+
500
+        // Set wrapper CSS
501
+        this.wrapper.css('padding-' + this.pointer.position, this.pointer.dimensions[this.pointer.xy]);
502
+
503
+        // Set pointer CSS
504
+        this.pointer.element.css(this.pointer.alignAttribute, (this.pointer.align == 'center' ? '50%' : 0)).css('margin-' + this.pointer.alignAttribute, this.pointer.offset);
505
+        this.pointer.margin = {};
506
+        this.pointer.margin['margin-' + this.pointer.alignAttribute] = this.pointer.offset;
507
+
508
+        // Add a transform to fix centered position
509
+        (this.pointer.align == 'center') && this.pointer.element.css('transform', 'translate(' + (this.pointer.xy == 'y' ? (this.pointer.dimensions.x * -0.5 + 'px') : 0) + ', ' + (this.pointer.xy == 'x' ? (this.pointer.dimensions.y * -0.5 + 'px') : 0) + ')');
510
+
511
+        this.pointer.element.css((this.pointer.xy == 'x' ? 'width' : 'height'), parseInt(this.pointer.dimensions[this.pointer.xy]) + parseInt(this.container.css('border-' + this.pointer.alignAttribute + '-width')));
512
+
513
+        // Add class to wrapper for CSS access
514
+        this.wrapper.addClass('jBox-pointerPosition-' + this.pointer.position);
515
+      }
516
+
517
+      // Set title and content
518
+      this.setContent(this.options.content, true);
519
+      this.setTitle(this.options.title, true);
520
+
521
+      this.options.draggable && this._draggable();
522
+
523
+      // Fire onCreated event
524
+      this._fireEvent('onCreated');
525
+    };
526
+
527
+
528
+    // Create jBox onInit
529
+
530
+    this.options.createOnInit && this._create();
531
+
532
+
533
+    // Attach jBox
534
+
535
+    this.options.attach && this.attach();
536
+
537
+
538
+    // Attach document and window events
539
+
540
+    this._attachEvents = function ()
541
+    {
542
+      // Cancel countdown on mouseenter if delayOnHover
543
+      this.options.delayOnHover && jQuery('#' + this.id).on('mouseenter', function (ev) { this.isHovered = true; }.bind(this));
544
+
545
+      // Resume countdown on mouseleave if delayOnHover
546
+      this.options.delayOnHover && jQuery('#' + this.id).on('mouseleave', function (ev) { this.isHovered = false; }.bind(this));
547
+
548
+      // Positioning events
549
+      if ((this.options.adjustPosition || this.options.reposition) && !this.fixed && this.outside) {
550
+
551
+        // Trigger position events when scrolling
552
+        this.options.adjustTracker && jQuery(window).on('scroll.jBox-' + this.id, function (ev) { this.position(); }.bind(this));
553
+
554
+        // Trigger position events when resizing
555
+        (this.options.adjustPosition || this.options.reposition) && jQuery(window).on('resize.jBox-' + this.id, function (ev) { this.position(); }.bind(this));
556
+      }
557
+
558
+      // Mousemove events
559
+      this.options.target == 'mouse' && jQuery('body').on('mousemove.jBox-' + this.id, function (ev) { this.position({mouseTarget: {top: ev.pageY, left: ev.pageX}}); }.bind(this));
560
+    };
561
+
562
+
563
+    // Detach document and window events
564
+
565
+    this._detachEvents = function ()
566
+    {
567
+      // Closing event: closeOnEsc
568
+      this.options.closeOnEsc && jQuery(document).off('keyup.jBox-' + this.id);
569
+
570
+      // Closing event: closeOnClick
571
+      (this.options.closeOnClick === true || this.options.closeOnClick == 'body') && jQuery(document).off('click.jBox-' + this.id + ' tap.jBox-' + this.id);
572
+
573
+      // Positioning events
574
+      this.options.adjustTracker && jQuery(window).off('scroll.jBox-' + this.id);
575
+      (this.options.adjustPosition || this.options.reposition) && jQuery(window).off('resize.jBox-' + this.id);
576
+
577
+      // Mousemove events
578
+      this.options.target == 'mouse' && jQuery('body').off('mousemove.jBox-' + this.id);
579
+    };
580
+
581
+
582
+    // Show overlay
583
+
584
+    this._showOverlay = function ()
585
+    {
586
+      // Create the overlay if wasn't created already
587
+      if (!this.overlay) {
588
+
589
+        // Create element and append to the element where jBox is appended to
590
+        this.overlay = jQuery('<div id="' + this.id + '-overlay"/>').addClass('jBox-overlay' + (this.type ? ' jBox-overlay-' + this.type : '')).css({
591
+          display: 'none',
592
+          opacity: 0,
593
+          zIndex: this.options.zIndex - 1
594
+        }).appendTo(this.options.appendTo);
595
+
596
+        // Add a class name to the overlay
597
+        this.options.overlayClass && this.overlay.addClass(this.options.overlayClass);
598
+
599
+        // Add close button to overlay
600
+        (this.options.closeButton == 'overlay' || this.options.closeButton === true) && this.overlay.append(this.closeButton);
601
+
602
+        // Add closeOnClick: 'overlay' events
603
+        this.options.closeOnClick == 'overlay' && this.overlay.on('click tap', function () { this.close({ignoreDelay: true}); }.bind(this));
604
+
605
+        // Adjust option adjustDistance if there is a close button in the overlay
606
+        jQuery('#' + this.id + '-overlay .jBox-closeButton').length && (this.options.adjustDistance.top = Math.max(jQuery('#' + this.id + '-overlay .jBox-closeButton').outerHeight(), this.options.adjustDistance.top));
607
+      }
608
+
609
+      // Adjust zIndex
610
+      if (this.adjustZIndexOnOpen === true) {
611
+        this.overlay.css('zIndex', parseInt(this.wrapper.css('zIndex'), 10) - 1);
612
+      }
613
+
614
+      // Abort if overlay is already visible
615
+      if (this.overlay.css('display') == 'block') return;
616
+
617
+      // Show overlay
618
+      this.options.fade ? (this.overlay.stop() && this.overlay.animate({opacity: 1}, {
619
+        queue: false,
620
+        duration: this.options.fade,
621
+        start: function () { this.overlay.css({display: 'block'}); }.bind(this)
622
+      })) : this.overlay.css({display: 'block', opacity: 1});
623
+    };
624
+
625
+
626
+    // Hide overlay
627
+
628
+    this._hideOverlay = function ()
629
+    {
630
+      // Abort if the overlay wasn't created yet
631
+      if (!this.overlay) return;
632
+
633
+      // Hide overlay if no other jBox needs it
634
+      this.options.fade ? (this.overlay.stop() && this.overlay.animate({opacity: 0}, {
635
+        queue: false,
636
+        duration: this.options.fade,
637
+        complete: function () { this.overlay.css({display: 'none'}); }.bind(this)
638
+      })) : this.overlay.css({display: 'none', opacity: 0});
639
+    };
640
+
641
+
642
+    // Get the correct jBox dimensions by moving jBox out of viewport
643
+
644
+    this._exposeDimensions = function ()
645
+    {
646
+      // Move wrapper out of viewport
647
+      this.wrapper.css({
648
+        top: -10000,
649
+        left: -10000,
650
+        right: 'auto',
651
+        bottom: 'auto'
652
+      });
653
+
654
+      // Get jBox dimensions
655
+      var jBoxDimensions = {
656
+        x: this.wrapper.outerWidth(),
657
+        y: this.wrapper.outerHeight()
658
+      };
659
+
660
+      // Reset position to viewport
661
+      this.wrapper.css({
662
+        top: 'auto',
663
+        left: 'auto'
664
+      });
665
+
666
+      return jBoxDimensions;
667
+    };
668
+
669
+
670
+    // Generate CSS for animations and append to header
671
+
672
+    this._generateAnimationCSS = function ()
673
+    {
674
+      // Get open and close animations if none provided
675
+      (jQuery.type(this.options.animation) != 'object') && (this.options.animation = {
676
+        pulse: {open: 'pulse', close: 'zoomOut'},
677
+        zoomIn: {open: 'zoomIn', close: 'zoomIn'},
678
+        zoomOut: {open: 'zoomOut', close: 'zoomOut'},
679
+        move: {open: 'move', close: 'move'},
680
+        slide: {open: 'slide', close: 'slide'},
681
+        flip: {open: 'flip', close: 'flip'},
682
+        tada: {open: 'tada', close: 'zoomOut'}
683
+      }[this.options.animation]);
684
+
685
+      // Abort if animation not found
686
+      if (!this.options.animation) return null;
687
+
688
+      // Get direction var
689
+      this.options.animation.open && (this.options.animation.open = this.options.animation.open.split(':'));
690
+      this.options.animation.close && (this.options.animation.close = this.options.animation.close.split(':'));
691
+      this.options.animation.openDirection = this.options.animation.open[1] ? this.options.animation.open[1] : null;
692
+      this.options.animation.closeDirection = this.options.animation.close[1] ? this.options.animation.close[1] : null;
693
+      this.options.animation.open && (this.options.animation.open = this.options.animation.open[0]);
694
+      this.options.animation.close && (this.options.animation.close = this.options.animation.close[0]);
695
+
696
+      // Add 'Open' and 'Close' to animation names
697
+      this.options.animation.open && (this.options.animation.open += 'Open');
698
+      this.options.animation.close && (this.options.animation.close += 'Close');
699
+
700
+      // All animations
701
+      var animations = {
702
+        pulse: {
703
+          duration: 350,
704
+          css: [['0%', 'scale(1)'], ['50%', 'scale(1.1)'], ['100%', 'scale(1)']]
705
+        },
706
+        zoomInOpen: {
707
+          duration: (this.options.fade || 180),
708
+          css: [['0%', 'scale(0.9)'], ['100%', 'scale(1)']]
709
+        },
710
+        zoomInClose: {
711
+          duration: (this.options.fade || 180),
712
+          css: [['0%', 'scale(1)'], ['100%', 'scale(0.9)']]
713
+        },
714
+        zoomOutOpen: {
715
+          duration: (this.options.fade || 180),
716
+          css: [['0%', 'scale(1.1)'], ['100%', 'scale(1)']]
717
+        },
718
+        zoomOutClose: {
719
+          duration: (this.options.fade || 180),
720
+          css: [['0%', 'scale(1)'], ['100%', 'scale(1.1)']]
721
+        },
722
+        moveOpen: {
723
+          duration: (this.options.fade || 180),
724
+          positions: {top: {'0%': -12}, right: {'0%': 12}, bottom: {'0%': 12}, left: {'0%': -12}},
725
+          css: [['0%', 'translate%XY(%Vpx)'], ['100%', 'translate%XY(0px)']]
726
+        },
727
+        moveClose: {
728
+          duration: (this.options.fade || 180),
729
+          timing: 'ease-in',
730
+          positions: {top: {'100%': -12}, right: {'100%': 12}, bottom: {'100%': 12}, left: {'100%': -12}},
731
+          css: [['0%', 'translate%XY(0px)'], ['100%', 'translate%XY(%Vpx)']]
732
+        },
733
+        slideOpen: {
734
+          duration: 400,
735
+          positions: {top: {'0%': -400}, right: {'0%': 400}, bottom: {'0%': 400}, left: {'0%': -400}},
736
+          css: [['0%', 'translate%XY(%Vpx)'], ['100%', 'translate%XY(0px)']]
737
+        },
738
+        slideClose: {
739
+          duration: 400,
740
+          timing: 'ease-in',
741
+          positions: {top: {'100%': -400}, right: {'100%': 400}, bottom: {'100%': 400}, left: {'100%': -400}},
742
+          css: [['0%', 'translate%XY(0px)'], ['100%', 'translate%XY(%Vpx)']]
743
+        },
744
+        flipOpen: {
745
+          duration: 600,
746
+          css: [['0%', 'perspective(400px) rotateX(90deg)'], ['40%', 'perspective(400px) rotateX(-15deg)'], ['70%', 'perspective(400px) rotateX(15deg)'], ['100%', 'perspective(400px) rotateX(0deg)']]
747
+        },
748
+        flipClose: {
749
+          duration: (this.options.fade || 300),
750
+          css: [['0%', 'perspective(400px) rotateX(0deg)'], ['100%', 'perspective(400px) rotateX(90deg)']]
751
+        },
752
+        tada: {
753
+          duration: 800,
754
+          css: [['0%', 'scale(1)'], ['10%, 20%', 'scale(0.9) rotate(-3deg)'], ['30%, 50%, 70%, 90%', 'scale(1.1) rotate(3deg)'], ['40%, 60%, 80%', 'scale(1.1) rotate(-3deg)'], ['100%', 'scale(1) rotate(0)']]
755
+        }
756
+      };
757
+
758
+      // Set Open and Close names for standalone animations
759
+      jQuery.each(['pulse', 'tada'], function (index, item) { animations[item + 'Open'] = animations[item + 'Close'] = animations[item]; });
760
+
761
+      // Function to generate the CSS for the keyframes
762
+      var generateKeyframeCSS = function (ev, position)
763
+      {
764
+        // Generate keyframes CSS
765
+        var keyframe_css = '@keyframes jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + (position ? '-' + position : '') + ' {';
766
+        jQuery.each(animations[this.options.animation[ev]].css, function (index, item) {
767
+          var translate = position ? item[1].replace('%XY', this._getXY(position).toUpperCase()) : item[1];
768
+          animations[this.options.animation[ev]].positions && (translate = translate.replace('%V', animations[this.options.animation[ev]].positions[position][item[0]]));
769
+          keyframe_css += item[0] + ' {transform:' + translate + ';}';
770
+        }.bind(this));
771
+        keyframe_css += '}';
772
+
773
+        // Generate class CSS
774
+        keyframe_css += '.jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + (position ? '-' + position : '') + ' {';
775
+        keyframe_css += 'animation-duration: ' + animations[this.options.animation[ev]].duration + 'ms;';
776
+        keyframe_css += 'animation-name: jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + (position ? '-' + position : '') + ';';
777
+        keyframe_css += animations[this.options.animation[ev]].timing ? ('animation-timing-function: ' + animations[this.options.animation[ev]].timing + ';') : '';
778
+        keyframe_css += '}';
779
+
780
+        return keyframe_css;
781
+      }.bind(this);
782
+
783
+      // Generate css for each event and positions
784
+      this._animationCSS = '';
785
+      jQuery.each(['open', 'close'], function (index, ev)
786
+      {
787
+        // No CSS needed for closing with no fade
788
+        if (!this.options.animation[ev] || !animations[this.options.animation[ev]] || (ev == 'close' && !this.options.fade)) return '';
789
+
790
+        // Generate CSS
791
+        animations[this.options.animation[ev]].positions ?
792
+          jQuery.each(['top', 'right', 'bottom', 'left'], function (index2, position) { this._animationCSS += generateKeyframeCSS(ev, position); }.bind(this)) :
793
+          this._animationCSS += generateKeyframeCSS(ev);
794
+      }.bind(this));
795
+
796
+    };
797
+
798
+
799
+    // Add css for animations
800
+
801
+    this.options.animation && this._generateAnimationCSS();
802
+
803
+
804
+    // Block body clicks for 10ms to prevent extra event triggering
805
+
806
+    this._blockBodyClick = function ()
807
+    {
808
+      this.blockBodyClick = true;
809
+      setTimeout(function () { this.blockBodyClick = false; }.bind(this), 10);
810
+    };
811
+
812
+
813
+    // Animations
814
+
815
+    this._animate = function (ev)
816
+    {
817
+      // The event which triggers the animation
818
+      !ev && (ev = this.isOpen ? 'open' : 'close');
819
+
820
+      // Don't animate when closing with no fade duration
821
+      if (!this.options.fade && ev == 'close') return null;
822
+
823
+      // Get the current position, use opposite if jBox is flipped
824
+      var animationDirection = (this.options.animation[ev + 'Direction'] || ((this.align != 'center') ? this.align : this.options.attributes.x));
825
+      this.flipped && this._getXY(animationDirection) == (this._getXY(this.align)) && (animationDirection = this._getOpp(animationDirection));
826
+
827
+      // Add event and position classes
828
+      var classnames = 'jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + ' jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + '-' + animationDirection;
829
+      this.wrapper.addClass(classnames);
830
+
831
+      // Get duration of animation
832
+      var animationDuration = parseFloat(this.wrapper.css('animation-duration')) * 1000;
833
+      ev == 'close' && (animationDuration = Math.min(animationDuration, this.options.fade));
834
+
835
+      // Remove animation classes when animation is finished
836
+      setTimeout(function () { this.wrapper.removeClass(classnames); }.bind(this), animationDuration);
837
+    };
838
+
839
+
840
+    // Abort an animation
841
+
842
+    this._abortAnimation = function ()
843
+    {
844
+      // Remove all animation classes
845
+      var classes = this.wrapper.attr('class').split(' ').filter(function (c) {
846
+        return c.lastIndexOf('jBox-' + this.id + '-animation', 0) !== 0;
847
+      }.bind(this));
848
+      this.wrapper.attr('class', classes.join(' '));
849
+    };
850
+
851
+
852
+    // Adjust dimensions when browser is resized
853
+
854
+    if (this.options.responsiveWidth || this.options.responsiveHeight)
855
+    {
856
+      // Responsive positioning overrides options adjustPosition and reposition
857
+      // TODO: Only add this resize event when the other one from adjustPosition and reposition was not set
858
+      jQuery(window).on('resize.responsivejBox-' + this.id, function (ev) { if (this.isOpen) { this.position(); } }.bind(this));
859
+    }
860
+
861
+
862
+    // Fix audio options
863
+
864
+    jQuery.type(this.options.preloadAudio) === 'string' && (this.options.preloadAudio = [this.options.preloadAudio]);
865
+    jQuery.type(this.options.audio) === 'string' && (this.options.audio = {open: this.options.audio});
866
+    jQuery.type(this.options.volume) === 'number' && (this.options.volume = {open: this.options.volume, close: this.options.volume});
867
+
868
+    if (this.options.preloadAudio === true && this.options.audio) {
869
+      this.options.preloadAudio = [];
870
+      jQuery.each(this.options.audio, function (index, url) {
871
+        this.options.preloadAudio.push(url + '.mp3');
872
+        this.options.preloadAudio.push(url + '.ogg');
873
+      }.bind(this));
874
+    }
875
+
876
+
877
+    // Preload audio files
878
+
879
+    this.options.preloadAudio.length && jQuery.each(this.options.preloadAudio, function (index, url) {
880
+      var audio = new Audio();
881
+      audio.src = url;
882
+      audio.preload = 'auto';
883
+    });
884
+
885
+
886
+    // Fire onInit event
887
+
888
+    this._fireEvent('onInit');
889
+
890
+
891
+    return this;
892
+  };
893
+
894
+
895
+  // Attach jBox to elements
896
+
897
+  jBox.prototype.attach = function (elements, trigger)
898
+  {
899
+    // Get elements from options if none passed
900
+    !elements && (elements = this.options.attach);
901
+
902
+    // Convert selectors to jQuery objects
903
+    jQuery.type(elements) == 'string' && (elements = jQuery(elements));
904
+
905
+    // Get trigger event from options if not passed
906
+    !trigger && (trigger = this.options.trigger);
907
+
908
+    // Loop through elements and attach jBox
909
+    elements && elements.length && jQuery.each(elements, function (index, el) {
910
+      el = jQuery(el);
911
+
912
+      // Only attach if the element wasn't attached to this jBox already
913
+      if (!el.data('jBox-attached-' + this.id)) {
914
+
915
+        // Remove title attribute and store content on element
916
+        (this.options.getContent == 'title' && el.attr('title') != undefined) && el.data('jBox-getContent', el.attr('title')).removeAttr('title');
917
+
918
+        // Add Element to collection
919
+        this.attachedElements || (this.attachedElements = []);
920
+        this.attachedElements.push(el[0]);
921
+
922
+        // Add click or mouseenter event, click events can prevent default as well
923
+        el.on(trigger + '.jBox-attach-' + this.id, function (ev)
924
+        {
925
+          // Clear timer
926
+          this.timer && clearTimeout(this.timer);
927
+
928
+          // Block opening when jbox is open and the source element is triggering
929
+          if (trigger == 'mouseenter' && this.isOpen && this.source[0] == el[0]) return;
930
+
931
+          // Only close jBox if you click the current target element, otherwise open at new target
932
+          if (this.isOpen && this.source && this.source[0] != el[0]) var forceOpen = true;
933
+
934
+          // Set new source element
935
+          this.source = el;
936
+
937
+          // Set new target
938
+          !this.options.target && (this.target = el);
939
+
940
+          // Prevent default action on click
941
+          trigger == 'click' && this.options.preventDefault && ev.preventDefault();
942
+
943
+          // Toggle or open jBox
944
+          this[trigger == 'click' && !forceOpen ? 'toggle' : 'open']();
945
+
946
+        }.bind(this));
947
+
948
+        // Add close event for trigger event mouseenter
949
+        (this.options.trigger == 'mouseenter') && el.on('mouseleave', function (ev)
950
+        {
951
+          // Abort if jBox wasn't created yet
952
+          if (!this.wrapper) return null;
953
+
954
+          // If we have set closeOnMouseleave, do not close jBox when leaving attached element and mouse is over jBox
955
+          if (!this.options.closeOnMouseleave || !(ev.relatedTarget == this.wrapper[0] || jQuery(ev.relatedTarget).parents('#' + this.id).length)) this.close();
956
+        }.bind(this));
957
+
958
+        // Store
959
+        el.data('jBox-attached-' + this.id, trigger);
960
+
961
+        // Fire onAttach event
962
+        this._fireEvent('onAttach', el);
963
+      }
964
+
965
+    }.bind(this));
966
+
967
+    return this;
968
+  };
969
+
970
+
971
+  // Detach jBox from elements
972
+
973
+  jBox.prototype.detach = function (elements)
974
+  {
975
+    // Get elements from stores elements if none passed
976
+    !elements && (elements = this.attachedElements || []);
977
+
978
+    elements && elements.length && jQuery.each(elements, function (index, el) {
979
+      el = jQuery(el);
980
+
981
+      // Remove events
982
+      if (el.data('jBox-attached-' + this.id)) {
983
+        el.off(el.data('jBox-attached-' + this.id) + '.jBox-attach-' + this.id);
984
+        el.data('jBox-attached-' + this.id, null);
985
+      }
986
+      // Remove element from collection
987
+      this.attachedElements = jQuery.grep(this.attachedElements, function (value) {
988
+        return value != el[0];
989
+      });
990
+    }.bind(this));
991
+
992
+    return this;
993
+  };
994
+
995
+
996
+  // Set title
997
+
998
+  jBox.prototype.setTitle = function (title, ignore_positioning)
999
+  {
1000
+    // Abort if title to set
1001
+    if (title == null || title == undefined) return this;
1002
+
1003
+    // Create jBox if it wasn't created already
1004
+    !this.wrapper && this._create();
1005
+
1006
+    // Get the width and height of wrapper, only if they change we need to reposition
1007
+    var wrapperHeight = this.wrapper.outerHeight();
1008
+    var wrapperWidth = this.wrapper.outerWidth();
1009
+
1010
+    // Create title elements if they weren't created already
1011
+    if (!this.title) {
1012
+      this.titleContainer = jQuery('<div class="jBox-title"/>');
1013
+      this.title = jQuery('<div/>').appendTo(this.titleContainer);
1014
+      if (this.options.closeButton == 'title' || (this.options.closeButton === true && !this.options.overlay)) {
1015
+        this.wrapper.addClass('jBox-closeButton-title');
1016
+        this.closeButton.appendTo(this.titleContainer);
1017
+      }
1018
+      this.titleContainer.insertBefore(this.content);
1019
+      this._setTitleWidth();
1020
+    }
1021
+
1022
+    // Add or remove wrapper class
1023
+    this.wrapper[title ? 'addClass' : 'removeClass']('jBox-hasTitle');
1024
+
1025
+    // Set title html
1026
+    this.title.html(title);
1027
+
1028
+    // Adjust width of title
1029
+    wrapperWidth != this.wrapper.outerWidth() && this._setTitleWidth();
1030
+
1031
+    // Make jBox draggable
1032
+    this.options.draggable && this._draggable();
1033
+
1034
+    // Reposition if dimensions changed
1035
+    !ignore_positioning && this.options.repositionOnContent && (wrapperHeight != this.wrapper.outerHeight() || wrapperWidth != this.wrapper.outerWidth()) && this.position();
1036
+
1037
+    return this;
1038
+  };
1039
+
1040
+
1041
+  // Set content
1042
+
1043
+  jBox.prototype.setContent = function (content, ignore_positioning)
1044
+  {
1045
+    // Abort if no content to set
1046
+    if (content == null || content == undefined) return this;
1047
+
1048
+    // Create jBox if it wasn't created already
1049
+    !this.wrapper && this._create();
1050
+
1051
+    // Get the width and height of wrapper, only if they change we need to reposition
1052
+    var wrapperHeight = this.wrapper.outerHeight();
1053
+    var wrapperWidth = this.wrapper.outerWidth();
1054
+
1055
+    // Move all appended containers to body
1056
+    this.content.children('[data-jbox-content-appended]').appendTo('body').css({display: 'none'});
1057
+
1058
+    // Set the new content
1059
+    switch (jQuery.type(content)) {
1060
+      case 'string':
1061
+        this.content.html(content);
1062
+        break;
1063
+      case 'object':
1064
+        if (content && (content instanceof jQuery || content.constructor.prototype.jquery)) {
1065
+          this.content.html('');
1066
+          content.attr('data-jbox-content-appended', 1).appendTo(this.content).css({display: 'block'});
1067
+        } else {
1068
+          this.content.html(JSON.stringify(content));
1069
+        }
1070
+        break;
1071
+     }
1072
+
1073
+    // Adjust title width
1074
+    wrapperWidth != this.wrapper.outerWidth() && this._setTitleWidth();
1075
+
1076
+    // Make jBox draggable
1077
+    this.options.draggable && this._draggable();
1078
+
1079
+    // Reposition if dimensions changed
1080
+    !ignore_positioning && this.options.repositionOnContent && (wrapperHeight != this.wrapper.outerHeight() || wrapperWidth != this.wrapper.outerWidth()) && this.position();
1081
+
1082
+    return this;
1083
+  };
1084
+
1085
+
1086
+  // Set jBox dimensions
1087
+
1088
+  jBox.prototype.setDimensions = function (type, value, pos)
1089
+  {
1090
+    // Create jBox if it wasn't created already
1091
+    !this.wrapper && this._create();
1092
+
1093
+    // Default value is 'auto'
1094
+    value == undefined && (value = 'auto');
1095
+
1096
+    // Set CSS of content and title
1097
+    this.content.css(type, this._getInt(value));
1098
+
1099
+    // Adjust title width
1100
+    type == 'width' && this._setTitleWidth();
1101
+
1102
+    // Update options
1103
+    this.options[type] = value;
1104
+
1105
+    // Reposition by default
1106
+    (pos == undefined || pos) && this.position();
1107
+  };
1108
+
1109
+
1110
+  // Set jBox width or height
1111
+
1112
+  jBox.prototype.setWidth = function (value, pos) { this.setDimensions('width', value, pos); };
1113
+  jBox.prototype.setHeight = function (value, pos) { this.setDimensions('height', value, pos); };
1114
+
1115
+
1116
+  // Position jBox
1117
+
1118
+  jBox.prototype.position = function (options)
1119
+  {
1120
+    // Options are required
1121
+    !options && (options = {});
1122
+
1123
+    // Combine passed options with jBox options
1124
+    options = jQuery.extend(true, this.options, options);
1125
+
1126
+    // Get the target
1127
+    this.target = options.target || this.target || jQuery(window);
1128
+
1129
+    // Make sure target is a jQuery element
1130
+    !(this.target instanceof jQuery || this.target == 'mouse') && (this.target = jQuery(this.target));
1131
+
1132
+    // Abort if target is missing
1133
+    if (!this.target.length) return this;
1134
+
1135
+    // Reset content css to get original dimensions
1136
+    this.content.css({
1137
+      width: this._getInt(options.width, 'width'),
1138
+      height: this._getInt(options.height, 'height'),
1139
+      minWidth: this._getInt(options.minWidth, 'width'),
1140
+      minHeight: this._getInt(options.minHeight, 'height'),
1141
+      maxWidth: this._getInt(options.maxWidth, 'width'),
1142
+      maxHeight: this._getInt(options.maxHeight, 'height'),
1143
+    });
1144
+
1145
+    // Reset width of title
1146
+    this._setTitleWidth();
1147
+
1148
+    // Get jBox dimensions
1149
+    var jBoxDimensions = this._exposeDimensions();
1150
+
1151
+    // Check if target has fixed position, store in elements data
1152
+    this.target != 'mouse' && !this.target.data('jBox-' + this.id + '-fixed') && this.target.data('jBox-' + this.id + '-fixed', (this.target[0] != jQuery(window)[0] && (this.target.css('position') == 'fixed' || this.target.parents().filter(function () { return jQuery(this).css('position') == 'fixed'; }).length > 0)) ? 'fixed' : 'static');
1153
+
1154
+    // Get the window dimensions
1155
+    var windowDimensions = {
1156
+      x: jQuery(window).outerWidth(),
1157
+      y: jQuery(window).outerHeight(),
1158
+      top: (options.fixed && this.target.data('jBox-' + this.id + '-fixed') ? 0 : jQuery(window).scrollTop()),
1159
+      left: (options.fixed && this.target.data('jBox-' + this.id + '-fixed') ? 0 : jQuery(window).scrollLeft())
1160
+    };
1161
+    windowDimensions.bottom = windowDimensions.top + windowDimensions.y;
1162
+    windowDimensions.right = windowDimensions.left + windowDimensions.x;
1163
+
1164
+    // Get target offset
1165
+    try { var targetOffset = this.target.offset(); } catch (e) { var targetOffset = {top: 0, left: 0}; };
1166
+
1167
+    // When the target is fixed and jBox is fixed, remove scroll offset
1168
+    if (this.target != 'mouse' && this.target.data('jBox-' + this.id + '-fixed') == 'fixed' && options.fixed) {
1169
+      targetOffset.top = targetOffset.top - jQuery(window).scrollTop();
1170
+      targetOffset.left = targetOffset.left - jQuery(window).scrollLeft();
1171
+    }
1172
+
1173
+    // Get target dimensions
1174
+    var targetDimensions = {
1175
+      x: this.target == 'mouse' ? 12 : this.target.outerWidth(),
1176
+      y: this.target == 'mouse' ? 20 : this.target.outerHeight(),
1177
+      top: this.target == 'mouse' && options.mouseTarget ? options.mouseTarget.top : (targetOffset ? targetOffset.top : 0),
1178
+      left: this.target == 'mouse' && options.mouseTarget ? options.mouseTarget.left : (targetOffset ? targetOffset.left : 0)
1179
+    };
1180
+
1181
+    // Check if jBox is outside
1182
+    var outside = options.outside && !(options.position.x == 'center' && options.position.y == 'center');
1183
+
1184
+    // Get the available space on all sides
1185
+    var availableSpace = {
1186
+      x: windowDimensions.x - options.adjustDistance.left - options.adjustDistance.right, // TODO: substract position.x when they are numbers
1187
+      y: windowDimensions.y - options.adjustDistance.top - options.adjustDistance.bottom, // TODO: substract position.x when they are numbers
1188
+      left: !outside ? 0 : (targetDimensions.left - jQuery(window).scrollLeft() - options.adjustDistance.left),
1189
+      right: !outside ? 0 : (windowDimensions.x - targetDimensions.left + jQuery(window).scrollLeft() - targetDimensions.x - options.adjustDistance.right),
1190
+      top: !outside ? 0 : (targetDimensions.top - jQuery(window).scrollTop() - this.options.adjustDistance.top),
1191
+      bottom: !outside ? 0 : (windowDimensions.y - targetDimensions.top + jQuery(window).scrollTop() - targetDimensions.y - options.adjustDistance.bottom),
1192
+    };
1193
+
1194
+    // Get the default outside position, check if box will be flipped
1195
+    var jBoxOutsidePosition = {
1196
+      x: (options.outside == 'x' || options.outside == 'xy') && jQuery.type(options.position.x) != 'number' ? options.position.x : null,
1197
+      y: (options.outside == 'y' || options.outside == 'xy') && jQuery.type(options.position.y) != 'number' ? options.position.y : null
1198
+    };
1199
+    var flip = {x: false, y: false};
1200
+    (jBoxOutsidePosition.x && jBoxDimensions.x > availableSpace[jBoxOutsidePosition.x] && availableSpace[this._getOpp(jBoxOutsidePosition.x)] > availableSpace[jBoxOutsidePosition.x]) && (jBoxOutsidePosition.x = this._getOpp(jBoxOutsidePosition.x)) && (flip.x = true);
1201
+    (jBoxOutsidePosition.y && jBoxDimensions.y > availableSpace[jBoxOutsidePosition.y] && availableSpace[this._getOpp(jBoxOutsidePosition.y)] > availableSpace[jBoxOutsidePosition.y]) && (jBoxOutsidePosition.y = this._getOpp(jBoxOutsidePosition.y)) && (flip.y = true);
1202
+
1203
+    // Adjust responsive dimensions
1204
+    if (options.responsiveWidth || options.responsiveHeight) {
1205
+
1206
+      // Adjust width and height according to default outside position
1207
+      var adjustResponsiveWidth = function ()
1208
+      {
1209
+        if (options.responsiveWidth && jBoxDimensions.x > availableSpace[jBoxOutsidePosition.x || 'x']) {
1210
+          var contentWidth = availableSpace[jBoxOutsidePosition.x || 'x'] - (this.pointer && outside && options.outside == 'x' ? this.pointer.dimensions.x : 0) - parseInt(this.container.css('border-left-width')) - parseInt(this.container.css('border-right-width'));
1211
+          this.content.css({
1212
+            width: contentWidth > this.options.responsiveMinWidth ? contentWidth : null,
1213
+            minWidth: contentWidth < parseInt(this.content.css('minWidth')) ? 0 : null
1214
+          });
1215
+          this._setTitleWidth();
1216
+        }
1217
+        jBoxDimensions = this._exposeDimensions();
1218
+
1219
+      }.bind(this);
1220
+      options.responsiveWidth && adjustResponsiveWidth();
1221
+
1222
+      // After adjusting width, check if jBox will be flipped for y
1223
+      options.responsiveWidth && !flip.y && (jBoxOutsidePosition.y && jBoxDimensions.y > availableSpace[jBoxOutsidePosition.y] && availableSpace[this._getOpp(jBoxOutsidePosition.y)] > availableSpace[jBoxOutsidePosition.y]) && (jBoxOutsidePosition.y = this._getOpp(jBoxOutsidePosition.y)) && (flip.y = true);
1224
+
1225
+      // Adjust width and height according to default outside position
1226
+      var adjustResponsiveHeight = function ()
1227
+      {
1228
+        if (options.responsiveHeight && jBoxDimensions.y > availableSpace[jBoxOutsidePosition.y || 'y']) {
1229
+
1230
+          // Expose wrapper to get correct title height
1231
+          var exposeTitleFooterHeight = function () {
1232
+            if (!this.titleContainer && !this.footer) return 0;
1233
+            if (this.wrapper.css('display') == 'none') {
1234
+              this.wrapper.css('display', 'block');
1235
+              var height = (this.titleContainer ? this.titleContainer.outerHeight() : 0) + (this.footer ? this.footer.outerHeight() : 0);
1236
+              this.wrapper.css('display', 'none');
1237
+            } else {
1238
+              var height = (this.titleContainer ? this.titleContainer.outerHeight() : 0) + (this.footer ? this.footer.outerHeight() : 0);
1239
+            }
1240
+            return height || 0;
1241
+          }.bind(this);
1242
+
1243
+          var contentHeight = availableSpace[jBoxOutsidePosition.y || 'y'] - (this.pointer && outside && options.outside == 'y' ? this.pointer.dimensions.y : 0) - exposeTitleFooterHeight() - parseInt(this.container.css('border-top-width')) - parseInt(this.container.css('border-bottom-width'));
1244
+          this.content.css({height: contentHeight > this.options.responsiveMinHeight ? contentHeight : null});
1245
+          this._setTitleWidth();
1246
+        }
1247
+        jBoxDimensions = this._exposeDimensions();
1248
+
1249
+      }.bind(this);
1250
+      options.responsiveHeight && adjustResponsiveHeight();
1251
+
1252
+      // After adjusting height, check if jBox will be flipped for x
1253
+      options.responsiveHeight && !flip.x && (jBoxOutsidePosition.x && jBoxDimensions.x > availableSpace[jBoxOutsidePosition.x] && availableSpace[this._getOpp(jBoxOutsidePosition.x)] > availableSpace[jBoxOutsidePosition.x]) && (jBoxOutsidePosition.x = this._getOpp(jBoxOutsidePosition.x)) && (flip.x = true);
1254
+
1255
+      // Adjust width and height if jBox will be flipped
1256
+      if (options.adjustPosition && options.adjustPosition != 'move') {
1257
+        flip.x && adjustResponsiveWidth();
1258
+        flip.y && adjustResponsiveHeight();
1259
+      }
1260
+    }
1261
+
1262
+    // Store new positioning vars in local var
1263
+    var pos = {};
1264
+
1265
+    // Calculate positions
1266
+    var setPosition = function (p)
1267
+    {
1268
+      // Set number positions
1269
+      if (jQuery.type(options.position[p]) == 'number') {
1270
+        pos[options.attributes[p]] = options.position[p];
1271
+        return;
1272
+      }
1273
+
1274
+      // We have a target, so use 'left' or 'top' as attributes
1275
+      var a = options.attributes[p] = (p == 'x' ? 'left' : 'top');
1276
+
1277
+      // Start at target position
1278
+      pos[a] = targetDimensions[a];
1279
+
1280
+      // Set centered position
1281
+      if (options.position[p] == 'center') {
1282
+        pos[a] += Math.ceil((targetDimensions[p] - jBoxDimensions[p]) / 2);
1283
+
1284
+        // If the target is the window, adjust centered position depending on adjustDistance
1285
+        (this.target != 'mouse' && this.target[0] && this.target[0] == jQuery(window)[0]) && (pos[a] += (options.adjustDistance[a] - options.adjustDistance[this._getOpp(a)]) * 0.5);
1286
+        return;
1287
+      }
1288
+
1289
+      // Move inside
1290
+      (a != options.position[p]) && (pos[a] += targetDimensions[p] - jBoxDimensions[p]);
1291
+
1292
+      // Move outside
1293
+      (options.outside == p || options.outside == 'xy') && (pos[a] += jBoxDimensions[p] * (a != options.position[p] ? 1 : -1));
1294
+
1295
+    }.bind(this);
1296
+
1297
+    // Set position including offset
1298
+    setPosition('x');
1299
+    setPosition('y');
1300
+
1301
+    // Adjust position depending on pointer align
1302
+    if (this.pointer && options.pointTo == 'target' && jQuery.type(options.position.x) != 'number' && jQuery.type(options.position.y) != 'number') {
1303
+
1304
+      var adjustWrapper = 0;
1305
+
1306
+      // Where is the pointer aligned? Add or substract accordingly
1307
+      switch (this.pointer.align) {
1308
+        case 'center':
1309
+        if (options.position[this._getOpp(options.outside)] != 'center') {
1310
+          adjustWrapper += (jBoxDimensions[this._getOpp(options.outside)] / 2);
1311
+        }
1312
+        break;
1313
+        default:
1314
+        switch (options.position[this._getOpp(options.outside)]) {
1315
+          case 'center':
1316
+            adjustWrapper += ((jBoxDimensions[this._getOpp(options.outside)] / 2) - (this.pointer.dimensions[this._getOpp(options.outside)] / 2)) * (this.pointer.align == this._getTL(this.pointer.align) ? 1 : -1);
1317
+          break;
1318
+          default:
1319
+            adjustWrapper += (this.pointer.align != options.position[this._getOpp(options.outside)]) ?
1320
+
1321
+            // If pointer align is different to position align
1322
+            (this.dimensions[this._getOpp(options.outside)] * (jQuery.inArray(this.pointer.align, ['top', 'left']) !== -1 ? 1 : -1)) + ((this.pointer.dimensions[this._getOpp(options.outside)] / 2) * (jQuery.inArray(this.pointer.align, ['top', 'left']) !== -1 ? -1 : 1)) :
1323
+
1324
+            // If pointer align is same as position align
1325
+            (this.pointer.dimensions[this._getOpp(options.outside)] / 2) * (jQuery.inArray(this.pointer.align, ['top', 'left']) !== -1 ? 1 : -1);
1326
+          break;
1327
+        }
1328
+        break;
1329
+      }
1330
+
1331
+      adjustWrapper *= (options.position[this._getOpp(options.outside)] == this.pointer.alignAttribute ? -1 : 1);
1332
+      adjustWrapper += this.pointer.offset * (this.pointer.align == this._getOpp(this._getTL(this.pointer.align)) ? 1 : -1);
1333
+
1334
+      pos[this._getTL(this._getOpp(this.pointer.xy))] += adjustWrapper;
1335
+    }
1336
+
1337
+    // Add final offset
1338
+    pos[options.attributes.x] += options.offset.x;
1339
+    pos[options.attributes.y] += options.offset.y;
1340
+
1341
+    // Set CSS
1342
+    this.wrapper.css(pos);
1343
+
1344
+    // Adjust position
1345
+    if (options.adjustPosition) {
1346
+
1347
+      // Reset cached pointer position
1348
+      if (this.positionAdjusted) {
1349
+        this.pointer && this.wrapper.css('padding', 0).css('padding-' + this._getOpp(this.outside), this.pointer.dimensions[this._getXY(this.outside)]).removeClass('jBox-pointerPosition-' + this._getOpp(this.pointer.position)).addClass('jBox-pointerPosition-' + this.pointer.position);
1350
+        this.pointer && this.pointer.element.attr('class', 'jBox-pointer jBox-pointer-' + this._getOpp(this.outside)).css(this.pointer.margin);
1351
+        this.positionAdjusted = false;
1352
+        this.flipped = false;
1353
+      }
1354
+
1355
+      // Find out where the jBox is out of view area
1356
+      var outYT = (windowDimensions.top > pos.top - (options.adjustDistance.top || 0)),
1357
+        outXR = (windowDimensions.right < pos.left + jBoxDimensions.x + (options.adjustDistance.right || 0)),
1358
+        outYB = (windowDimensions.bottom < pos.top + jBoxDimensions.y + (options.adjustDistance.bottom || 0)),
1359
+        outXL = (windowDimensions.left > pos.left - (options.adjustDistance.left || 0)),
1360
+        outX = outXL ? 'left' : (outXR ? 'right' : null),
1361
+        outY = outYT ? 'top' : (outYB ? 'bottom' : null),
1362
+        out = outX || outY;
1363
+
1364
+      // Only continue if jBox is out of view area
1365
+      if (out) {
1366
+
1367
+        if ((this.type == 'Modal' || this.type == 'Confirm')
1368
+          && jQuery.type(this.options.position.x) == 'number'
1369
+          && jQuery.type(this.options.position.y) == 'number'
1370
+        ) {
1371
+          var diffX = 0, diffY = 0;
1372
+          if (this.options.holdPosition) {
1373
+
1374
+            // Adjust left or right
1375
+            if (outXL) {
1376
+              diffX = windowDimensions.left - (pos.left - (options.adjustDistance.left || 0));
1377
+            } else if (outXR) {
1378
+              diffX = windowDimensions.right - (pos.left + jBoxDimensions.x + (options.adjustDistance.right || 0));
1379
+            }
1380
+
1381
+            // Adjust top or bottom
1382
+            if (outYT) {
1383
+              diffY = windowDimensions.top - (pos.top - (options.adjustDistance.top || 0));
1384
+            } else if (outYB) {
1385
+              diffY = windowDimensions.bottom - (pos.top + jBoxDimensions.y + (options.adjustDistance.bottom || 0));
1386
+            }
1387
+
1388
+            this.options.position.x = Math.max(windowDimensions.top, this.options.position.x + diffX);
1389
+            this.options.position.y = Math.max(windowDimensions.left, this.options.position.y + diffY);
1390
+
1391
+            setPosition('x');
1392
+            setPosition('y');
1393
+            this.wrapper.css(pos);
1394
+          }
1395
+          // Fire onPosition event
1396
+          this._fireEvent('onPosition');
1397
+
1398
+          return this;
1399
+        }
1400
+
1401
+        // Function to flip position
1402
+        if (options.adjustPosition === true || options.adjustPosition === 'flip') {
1403
+          var flipJBox = function (xy) {
1404
+            this.wrapper.css(this._getTL(xy), pos[this._getTL(xy)] + ((jBoxDimensions[this._getXY(xy)] + (options.offset[this._getXY(xy)] * (xy == 'top' || xy == 'left' ? -2 : 2)) + targetDimensions[this._getXY(xy)]) * (xy == 'top' || xy == 'left' ? 1 : -1)));
1405
+            this.pointer && this.wrapper.removeClass('jBox-pointerPosition-' + this.pointer.position).addClass('jBox-pointerPosition-' + this._getOpp(this.pointer.position)).css('padding', 0).css('padding-' + xy, this.pointer.dimensions[this._getXY(xy)]);
1406
+            this.pointer && this.pointer.element.attr('class', 'jBox-pointer jBox-pointer-' + xy);
1407
+            this.positionAdjusted = true;
1408
+            this.flipped = true;
1409
+          }.bind(this);
1410
+
1411
+          // Flip jBox
1412
+          flip.x && flipJBox(this.options.position.x);
1413
+          flip.y && flipJBox(this.options.position.y);
1414
+        }
1415
+
1416
+        // Move jBox (only possible with pointer)
1417
+        var outMove = (this._getXY(this.outside) == 'x') ? outY : outX;
1418
+
1419
+        if (this.pointer && options.pointTo == 'target' && options.adjustPosition != 'flip' && this._getXY(outMove) == this._getOpp(this._getXY(this.outside))) {
1420
+
1421
+          // Get the maximum space we have availible to adjust
1422
+          if (this.pointer.align == 'center') {
1423
+            var spaceAvail = (jBoxDimensions[this._getXY(outMove)] / 2) - (this.pointer.dimensions[this._getOpp(this.pointer.xy)] / 2) - (parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) * (outMove != this._getTL(outMove) ? -1 : 1));
1424
+          } else {
1425
+            var spaceAvail = (outMove == this.pointer.alignAttribute) ?
1426
+              parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) :
1427
+              jBoxDimensions[this._getXY(outMove)] - parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) - this.pointer.dimensions[this._getXY(outMove)];
1428
+          }
1429
+
1430
+          // Get the overlapping space
1431
+          var spaceDiff = (outMove == this._getTL(outMove)) ?
1432
+            windowDimensions[this._getTL(outMove)] - pos[this._getTL(outMove)] + options.adjustDistance[outMove] :
1433
+            (windowDimensions[this._getOpp(this._getTL(outMove))] - pos[this._getTL(outMove)] - options.adjustDistance[outMove] - jBoxDimensions[this._getXY(outMove)]) * -1;
1434
+
1435
+          // Add overlapping space on left or top window edge
1436
+          if (outMove == this._getOpp(this._getTL(outMove)) && pos[this._getTL(outMove)] - spaceDiff < windowDimensions[this._getTL(outMove)] + options.adjustDistance[this._getTL(outMove)]) {
1437
+            spaceDiff -= windowDimensions[this._getTL(outMove)] + options.adjustDistance[this._getTL(outMove)] - (pos[this._getTL(outMove)] - spaceDiff);
1438
+          }
1439
+
1440
+          // Only adjust the maximum availible
1441
+          spaceDiff = Math.min(spaceDiff, spaceAvail);
1442
+
1443
+          // Move jBox
1444
+          if (spaceDiff <= spaceAvail && spaceDiff > 0) {
1445
+            this.pointer.element.css('margin-' + this.pointer.alignAttribute, parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) - (spaceDiff * (outMove != this.pointer.alignAttribute ? -1 : 1)));
1446
+            this.wrapper.css(this._getTL(outMove), pos[this._getTL(outMove)] + (spaceDiff * (outMove != this._getTL(outMove) ? -1 : 1)));
1447
+            this.positionAdjusted = true;
1448
+          }
1449
+        }
1450
+      }
1451
+    }
1452
+
1453
+    // Fire onPosition event
1454
+    this._fireEvent('onPosition');
1455
+
1456
+    return this;
1457
+  };
1458
+
1459
+
1460
+  // Block scrolling
1461
+  // Borrowed from https://github.com/StephanWagner/unscroll
1462
+
1463
+  jBox.prototype.unscroll = function (elements) {
1464
+
1465
+    // Store reusable vars
1466
+    this.set = function (id, value) {
1467
+      if (!window.unscrollStore) {
1468
+        window.unscrollStore = {};
1469
+      }
1470
+      window.unscrollStore[id] = value;
1471
+    };
1472
+
1473
+    // Get reusable vars
1474
+    this.get = function (id) {
1475
+      return window.unscrollStore ? window.unscrollStore[id] : null;
1476
+    };
1477
+
1478
+    // Get the width of the scroll bar in pixel
1479
+    this.getScrollbarWidth = function () {
1480
+      if (this.get('scrollbarWidth')) {
1481
+        return this.get('scrollbarWidth') + 'px';
1482
+      }
1483
+      var scrollElement = document.createElement('div');
1484
+      scrollElement.style.width = '100px';
1485
+      scrollElement.style.height = '100px';
1486
+      scrollElement.style.overflow = 'scroll';
1487
+      scrollElement.style.position = 'absolute';
1488
+      scrollElement.style.top = '-10000';
1489
+
1490
+      document.body.appendChild(scrollElement);
1491
+      var scrollbarWidth = scrollElement.offsetWidth - scrollElement.clientWidth;
1492
+      document.body.removeChild(scrollElement);
1493
+
1494
+      this.set('scrollbarWidth', scrollbarWidth);
1495
+      return scrollbarWidth + 'px';
1496
+    }
1497
+
1498
+    // Add unscroll class to head
1499
+    function addUnscrollClassName() {
1500
+      if (document.getElementById('unscroll-class-name')) {
1501
+        return;
1502
+      }
1503
+      var css = '.unscrollable { overflow: hidden !important; }',
1504
+        head = document.head || document.getElementsByTagName('head')[0],
1505
+        style = document.createElement('style');
1506
+      style.type = 'text/css';
1507
+      style.setAttribute('id', 'unscroll-class-name');
1508
+      style.appendChild(document.createTextNode(css));
1509
+      head.appendChild(style);
1510
+    }
1511
+
1512
+    // Get the elements to adjust, force body element
1513
+    this.getElementsToAdjust = function (elements) {
1514
+      !elements && (elements = []);
1515
+
1516
+      if (typeof elements === 'string') {
1517
+        elements = [
1518
+          [elements, 'padding-right']
1519
+        ];
1520
+      }
1521
+
1522
+      elements.forEach(function (element, index) {
1523
+        if (typeof element === 'string') {
1524
+          elements[index] = [element, 'padding-right'];
1525
+        }
1526
+      });
1527
+
1528
+      var bodyFound = false;
1529
+      for (var i = 0; i < elements.length; i++) {
1530
+        if (elements[i][0].indexOf('body') !== -1) {
1531
+          bodyFound = true;
1532
+        }
1533
+      };
1534
+
1535
+      if (bodyFound === false) {
1536
+        elements.push(['body', 'padding-right']);
1537
+      }
1538
+
1539
+      return elements;
1540
+    }
1541
+
1542
+    this.pageHasScrollbar = function () {
1543
+      return this.getScrollbarWidth() && document.body.offsetHeight > window.innerHeight;
1544
+    }
1545
+
1546
+    // Clean up elements
1547
+    if (this.pageHasScrollbar()) {
1548
+      elements = this.getElementsToAdjust(elements);
1549
+
1550
+      // Loop through elements and adjust accordingly
1551
+      for (var i = 0; i < elements.length; i++) {
1552
+        var elementsDOM = document.querySelectorAll(elements[i][0]);
1553
+        for (var j = 0; j < elementsDOM.length; j++) {
1554
+          if (elementsDOM[j].getAttribute('data-unscroll')) {
1555
+            return;
1556
+          }
1557
+          var attribute = elements[i][1];
1558
+          var computedStyles = window.getComputedStyle(elementsDOM[j]);
1559
+          var computedStyle = computedStyles.getPropertyValue(attribute);
1560
+          elementsDOM[j].setAttribute('data-unscroll', attribute);
1561
+          if (!computedStyle) {
1562
+            computedStyle = '0px';
1563
+          }
1564
+          var operator = attribute == 'padding-right' || attribute == 'right' ? '+' : '-';
1565
+          elementsDOM[j].style[attribute] = 'calc(' + computedStyle + ' ' + operator + ' ' + this.getScrollbarWidth() + ')';
1566
+        }
1567
+      }
1568
+    }
1569
+
1570
+    // Make the page unscrollable
1571
+    addUnscrollClassName();
1572
+    document.body.classList.add('unscrollable');
1573
+  }
1574
+
1575
+  jBox.prototype.unscroll.reset = function () {
1576
+    var elements = document.querySelectorAll('[data-unscroll]');
1577
+
1578
+    for (var i = 0; i < elements.length; i++) {
1579
+      var attribute = elements[i].getAttribute('data-unscroll');
1580
+      elements[i].style[attribute] = null;
1581
+      elements[i].removeAttribute('data-unscroll');
1582
+    }
1583
+    document.body.classList.remove('unscrollable');
1584
+  }
1585
+
1586
+
1587
+  // Open jBox
1588
+
1589
+  jBox.prototype.open = function (options)
1590
+  {
1591
+    // Create blank options if none passed
1592
+    !options && (options = {});
1593
+
1594
+    // Abort if jBox was destroyed
1595
+    if (this.isDestroyed) return this;
1596
+
1597
+    // Construct jBox if not already constructed
1598
+    !this.wrapper && this._create();
1599
+
1600
+    // Add css to header if not added already
1601
+    !this._styles && (this._styles = jQuery('<style/>').append(this._animationCSS).appendTo(jQuery('head')));
1602
+
1603
+    // Abort any opening or closing timer
1604
+    this.timer && clearTimeout(this.timer);
1605
+
1606
+    // Block body click for 10ms, so jBox can open on attached elements while closeOnClick = 'body'
1607
+    this._blockBodyClick();
1608
+
1609
+    // Block opening
1610
+    if (this.isDisabled) return this;
1611
+
1612
+    // Closing event: closeOnEsc
1613
+    this.options.closeOnEsc && jQuery(document).on('keyup.jBox-' + this.id, function (ev) { if (ev.keyCode == 27) { this.close({ignoreDelay: true}); }}.bind(this));
1614
+
1615
+    // Closing event: closeOnClick
1616
+    if (this.options.closeOnClick === true || this.options.closeOnClick === 'body') {
1617
+      jQuery('body').on('click.jBox-' + this.id + ' tap.jBox-' + this.id, function (ev) {
1618
+        if (this.blockBodyClick || (this.options.closeOnClick == 'body' && (ev.target == this.wrapper[0] || this.wrapper.has(ev.target).length))) return;
1619
+        this.close({ignoreDelay: true});
1620
+      }.bind(this));
1621
+
1622
+      // Fix for iOS event bubbling issue
1623
+      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
1624
+      this.isTouchDevice && jQuery('body > *').on('click.jBox-' + this.id + ' tap.jBox-' + this.id, function () {
1625
+        return true;
1626
+      });
1627
+    }
1628
+
1629
+    // Opening function
1630
+    var open = function () {
1631
+
1632
+      // Adjust zIndex
1633
+      if (this.adjustZIndexOnOpen === true) {
1634
+        jBox.zIndexMax = Math.max(
1635
+          parseInt(this.wrapper.css('zIndex'), 10),
1636
+          this.options.zIndex,
1637
+          jBox.zIndexMax || 0,
1638
+          jBox.zIndexMaxDragover || 0
1639
+        ) + 2;
1640
+        this.wrapper.css('zIndex', jBox.zIndexMax);
1641
+        this.options.zIndex = jBox.zIndexMax;
1642
+      }
1643
+
1644
+      // Set title from source element
1645
+      this.source && this.options.getTitle && (this.source.attr(this.options.getTitle) && this.setTitle(this.source.attr(this.options.getTitle), true));
1646
+
1647
+      // Set content from source element
1648
+      this.source && this.options.getContent && (this.source.data('jBox-getContent') ? this.setContent(this.source.data('jBox-getContent'), true) : (this.source.attr(this.options.getContent) ? this.setContent(this.source.attr(this.options.getContent), true) : (this.options.getContent == 'html' ? this.setContent(this.source.html(), true) : null)));
1649
+
1650
+      // Fire onOpen event
1651
+      this._fireEvent('onOpen');
1652
+
1653
+      // Get content from ajax
1654
+      if ((this.options.ajax && (this.options.ajax.url || (this.source && this.source.attr(this.options.ajax.getURL))) && (!this.ajaxLoaded || this.options.ajax.reload)) || (options.ajax && (options.ajax.url || options.ajax.data))) {
1655
+        // Send the content from stored data if there is any, otherwise load new data
1656
+        (this.options.ajax.reload != 'strict' && this.source && this.source.data('jBox-ajax-data') && !(options.ajax && (options.ajax.url || options.ajax.data))) ? this.setContent(this.source.data('jBox-ajax-data')) : this.ajax((options.ajax || null), true);
1657
+      }
1658
+
1659
+      // Set position
1660
+      (!this.positionedOnOpen || this.options.repositionOnOpen) && this.position(options) && (this.positionedOnOpen = true);
1661
+
1662
+      // Abort closing
1663
+      this.isClosing && this._abortAnimation();
1664
+
1665
+      // Open functions to call when jBox is closed
1666
+      if (!this.isOpen) {
1667
+
1668
+        // jBox is open now
1669
+        this.isOpen = true;
1670
+
1671
+        // Automatically close jBox after some time
1672
+        this.options.autoClose && (this.options.delayClose = this.options.autoClose) && this.close();
1673
+
1674
+        // Attach events
1675
+        this._attachEvents();
1676
+
1677
+        // Block scrolling
1678
+        if (this.options.blockScroll) {
1679
+          if (this.options.blockScrollAdjust) {
1680
+            if (jBox.blockScrollScopes) {
1681
+              jBox.blockScrollScopes++;
1682
+            } else {
1683
+              jBox.blockScrollScopes = 1;
1684
+              this.unscroll(Array.isArray(this.options.blockScrollAdjust) || typeof this.options.blockScrollAdjust === 'string' ? this.options.blockScrollAdjust : null);
1685
+            }
1686
+          } else {
1687
+            jQuery('body').addClass('jBox-blockScroll-' + this.id);
1688
+          }
1689
+        }
1690
+
1691
+        // Show overlay
1692
+        if (this.options.overlay) {
1693
+          this._showOverlay();
1694
+
1695
+          // TODO Optimize: We have to position here again, because if the overlay has a close button, the upper adjustDistance will be wrong
1696
+          this.position();
1697
+        }
1698
+
1699
+        // Only animate if jBox is completely closed
1700
+        this.options.animation && !this.isClosing && this._animate('open');
1701
+
1702
+        // Play audio file
1703
+        this.options.audio && this.options.audio.open && this.audio(this.options.audio.open, this.options.volume.open);
1704
+
1705
+        // Fading animation or show immediately
1706
+        if (this.options.fade) {
1707
+          this.wrapper.stop().animate({opacity: 1}, {
1708
+            queue: false,
1709
+            duration: this.options.fade,
1710
+            start: function () {
1711
+              this.isOpening = true;
1712
+              this.wrapper.css({display: 'block'});
1713
+            }.bind(this),
1714
+            always: function () {
1715
+              this.isOpening = false;
1716
+
1717
+              // Delay positioning for ajax to prevent positioning during animation
1718
+              setTimeout(function () { this.positionOnFadeComplete && this.position() && (this.positionOnFadeComplete = false); }.bind(this), 10);
1719
+            }.bind(this)
1720
+          });
1721
+        } else {
1722
+          this.wrapper.css({display: 'block', opacity: 1});
1723
+          this.positionOnFadeComplete && this.position() && (this.positionOnFadeComplete = false);
1724
+        }
1725
+      }
1726
+    }.bind(this);
1727
+
1728
+    // Open jBox
1729
+    this.options.delayOpen && !this.isOpen && !this.isClosing && !options.ignoreDelay ? (this.timer = setTimeout(open, this.options.delayOpen)) : open();
1730
+
1731
+    return this;
1732
+  };
1733
+
1734
+
1735
+  // Close jBox
1736
+
1737
+  jBox.prototype.close = function (options)
1738
+  {
1739
+    // Create blank options if none passed
1740
+    options || (options = {});
1741
+
1742
+    // Remove close events
1743
+    jQuery('body').off('click.jBox-' + this.id + ' tap.jBox-' + this.id);
1744
+    this.isTouchDevice && jQuery('body > *').off('click.jBox-' + this.id + ' tap.jBox-' + this.id);
1745
+
1746
+    // Abort if jBox was destroyed or is currently closing
1747
+    if (this.isDestroyed || this.isClosing) return this;
1748
+
1749
+    // Abort opening
1750
+    this.timer && clearTimeout(this.timer);
1751
+
1752
+    // Block body click for 10ms, so jBox can open on attached elements while closeOnClick = 'body' is true
1753
+    this._blockBodyClick();
1754
+
1755
+    // Block closing
1756
+    if (this.isDisabled) return this;
1757
+
1758
+    // Close function
1759
+    var close = function () {
1760
+
1761
+      // Fire onClose event
1762
+      this._fireEvent('onClose');
1763
+
1764
+      // Cancel the ajax call
1765
+      if (this.options.cancelAjaxOnClose) {
1766
+        this.cancelAjax();
1767
+      }
1768
+
1769
+      // Only close if jBox is open
1770
+      if (this.isOpen) {
1771
+
1772
+        // jBox is not open anymore
1773
+        this.isOpen = false;
1774
+
1775
+        // Detach events
1776
+        this._detachEvents();
1777
+
1778
+        // Unblock scrolling
1779
+        if (this.options.blockScroll) {
1780
+          if (this.options.blockScrollAdjust) {
1781
+            jBox.blockScrollScopes = jBox.blockScrollScopes ? --jBox.blockScrollScopes : 0;
1782
+            !jBox.blockScrollScopes && this.unscroll.reset();
1783
+          } else {
1784
+            jQuery('body').removeClass('jBox-blockScroll-' + this.id);
1785
+          }
1786
+        }
1787
+
1788
+        // Hide overlay
1789
+        this.options.overlay && this._hideOverlay();
1790
+
1791
+        // Only animate if jBox is compleately closed
1792
+        this.options.animation && !this.isOpening && this._animate('close');
1793
+
1794
+        // Play audio file
1795
+        this.options.audio && this.options.audio.close && this.audio(this.options.audio.close, this.options.volume.close);
1796
+
1797
+        // Get fade duration
1798
+        var fadeDuration = this.isTouchDevice && this.options.target == 'mouse' ? 0 : this.options.fade;
1799
+
1800
+        // Fading animation or show immediately
1801
+        if (fadeDuration) {
1802
+          this.wrapper.stop().animate({opacity: 0}, {
1803
+            queue: false,
1804
+            duration: fadeDuration,
1805
+            start: function () {
1806
+              this.isClosing = true;
1807
+            }.bind(this),
1808
+            complete: function () {
1809
+              this.wrapper.css({display: 'none'});
1810
+              this._fireEvent('onCloseComplete');
1811
+            }.bind(this),
1812
+            always: function () {
1813
+              this.isClosing = false;
1814
+            }.bind(this)
1815
+          });
1816
+        } else {
1817
+          this.wrapper.css({display: 'none', opacity: 0});
1818
+          this._fireEvent('onCloseComplete');
1819
+        }
1820
+      }
1821
+    }.bind(this);
1822
+
1823
+    // Close jBox
1824
+    if (options.ignoreDelay || (this.isTouchDevice && this.options.target == 'mouse')) {
1825
+      close();
1826
+    } else if ((this.options.delayOnHover || this.options.showCountdown) && this.options.delayClose > 10) {
1827
+      var self = this;
1828
+      var remaining = this.options.delayClose;
1829
+      var prevFrame = Date.now();
1830
+      if (this.options.showCountdown && !this.inner) {
1831
+        var outer = jQuery('<div class="jBox-countdown" />');
1832
+        this.inner = jQuery('<div class="jBox-countdown-inner" />');
1833
+        outer.prepend(this.inner);
1834
+        jQuery('#' + this.id).append(outer);
1835
+      }
1836
+      this.countdown = function(){
1837
+        var dateNow = Date.now();
1838
+        if (!self.isHovered) {
1839
+          remaining -= dateNow - prevFrame;
1840
+        }
1841
+        prevFrame = dateNow;
1842
+        if (remaining > 0) {
1843
+          if (self.options.showCountdown) {
1844
+            self.inner.css('width', (remaining * 100 / self.options.delayClose) + '%');
1845
+          }
1846
+          window.requestAnimationFrame(self.countdown);
1847
+        } else {
1848
+          close();
1849
+        }
1850
+      };
1851
+      window.requestAnimationFrame(this.countdown);
1852
+    } else {
1853
+      this.timer = setTimeout(close, Math.max(this.options.delayClose, 10));
1854
+    }
1855
+
1856
+    return this;
1857
+  };
1858
+
1859
+
1860
+  // Open or close jBox
1861
+
1862
+  jBox.prototype.toggle = function (options)
1863
+  {
1864
+    this[this.isOpen ? 'close' : 'open'](options);
1865
+    return this;
1866
+  };
1867
+
1868
+
1869
+  // Block opening and closing
1870
+
1871
+  jBox.prototype.disable = function ()
1872
+  {
1873
+    this.isDisabled = true;
1874
+    return this;
1875
+  };
1876
+
1877
+
1878
+  // Unblock opening and closing
1879
+
1880
+  jBox.prototype.enable = function ()
1881
+  {
1882
+    this.isDisabled = false;
1883
+    return this;
1884
+  };
1885
+
1886
+
1887
+  // Hide jBox
1888
+
1889
+  jBox.prototype.hide = function ()
1890
+  {
1891
+    this.disable();
1892
+    if (this.wrapper) {
1893
+      this.cacheWrapperDisplay = this.wrapper.css('display');
1894
+      this.wrapper.css({display: 'none'});
1895
+    }
1896
+    if (this.overlay) {
1897
+      this.cacheOverlayDisplay = this.overlay.css('display');
1898
+      this.overlay.css({display: 'none'});
1899
+    }
1900
+    return this;
1901
+  };
1902
+
1903
+
1904
+  // Show jBox
1905
+
1906
+  jBox.prototype.show = function ()
1907
+  {
1908
+    this.enable();
1909
+    if (this.wrapper && this.cacheWrapperDisplay) {
1910
+      this.wrapper.css({display: this.cacheWrapperDisplay});
1911
+      this.cacheWrapperDisplay = null;
1912
+    }
1913
+    if (this.overlay && this.cacheOverlayDisplay) {
1914
+      this.overlay.css({display: this.cacheOverlayDisplay});
1915
+      this.cacheOverlayDisplay = null;
1916
+    }
1917
+    return this;
1918
+  };
1919
+
1920
+
1921
+  // Get content from ajax
1922
+
1923
+  jBox.prototype.ajax = function (options, opening)
1924
+  {
1925
+    options || (options = {});
1926
+
1927
+    // Add data or url from source element if none set in options
1928
+    jQuery.each([['getData', 'data'], ['getURL', 'url']], function (index, item) {
1929
+      (this.options.ajax[item[0]] && !options[item[1]] && this.source && this.source.attr(this.options.ajax[item[0]]) != undefined) && (options[item[1]] = this.source.attr(this.options.ajax[item[0]]) || '');
1930
+    }.bind(this));
1931
+
1932
+    // Clone the system options
1933
+    var sysOptions = jQuery.extend(true, {}, this.options.ajax);
1934
+
1935
+    // Abort running ajax call
1936
+    this.cancelAjax();
1937
+
1938
+    // Extract events
1939
+    var beforeSend = options.beforeSend || sysOptions.beforeSend || function () {};
1940
+    var complete = options.complete || sysOptions.complete || function () {};
1941
+    var success = options.success || sysOptions.success || function () {};
1942
+    var error = options.error || sysOptions.error || function () {};
1943
+
1944
+    // Merge options
1945
+    var userOptions = jQuery.extend(true, sysOptions, options);
1946
+
1947
+    // Set new beforeSend event
1948
+    userOptions.beforeSend = function (xhr)
1949
+    {
1950
+      // jBox is loading
1951
+      userOptions.loadingClass && this.wrapper.addClass(userOptions.loadingClass === true ? 'jBox-loading' : userOptions.loadingClass);
1952
+
1953
+      // Add loading spinner
1954
+      userOptions.spinner && (this.spinnerDelay = setTimeout(function ()
1955
+      {
1956
+        // Add class for loading spinner
1957
+        this.wrapper.addClass('jBox-loading-spinner');
1958
+
1959
+        // Reposition jBox
1960
+        // TODO: Only reposition if dimensions change
1961
+        userOptions.spinnerReposition && (opening ? (this.positionOnFadeComplete = true) : this.position());
1962
+
1963
+        // Add spinner to container
1964
+        this.spinner = jQuery(userOptions.spinner !== true ? userOptions.spinner : '<div class="jBox-spinner"></div>').appendTo(this.container);
1965
+
1966
+        // Fix spinners position if there is a title
1967
+        this.titleContainer && this.spinner.css('position') == 'absolute' && this.spinner.css({transform: 'translateY(' + (this.titleContainer.outerHeight() * 0.5) + 'px)'});
1968
+
1969
+      }.bind(this), (this.content.html() == '' ? 0 : (userOptions.spinnerDelay || 0))));
1970
+
1971
+      // Fire users beforeSend event
1972
+      (beforeSend.bind(this))(xhr);
1973
+
1974
+    }.bind(this);
1975
+
1976
+    // Set up new complete event
1977
+    userOptions.complete = function (response)
1978
+    {
1979
+      // Abort spinner timeout
1980
+      this.spinnerDelay && clearTimeout(this.spinnerDelay);
1981
+
1982
+      // jBox finished loading
1983
+      this.wrapper.removeClass('jBox-loading jBox-loading-spinner jBox-loading-spinner-delay');
1984
+
1985
+      // Remove spinner
1986
+      this.spinner && this.spinner.length && this.spinner.remove() && userOptions.spinnerReposition && (opening ? (this.positionOnFadeComplete = true) : this.position());
1987
+
1988
+      // Store that ajax loading finished
1989
+      this.ajaxLoaded = true;
1990
+
1991
+      // Fire users complete event
1992
+      (complete.bind(this))(response);
1993
+
1994
+    }.bind(this);
1995
+
1996
+    // Set up new success event
1997
+    userOptions.success = function (response)
1998
+    {
1999
+      // Set content
2000
+      userOptions.setContent && this.setContent(response, true) && (opening ? (this.positionOnFadeComplete = true) : this.position());
2001
+
2002
+      // Store content in source element
2003
+      userOptions.setContent && this.source && this.source.data('jBox-ajax-data', response);
2004
+
2005
+      // Fire users success event
2006
+      (success.bind(this))(response);
2007
+
2008
+    }.bind(this);
2009
+
2010
+    // Add error event
2011
+    userOptions.error = function (response) { (error.bind(this))(response); }.bind(this);
2012
+
2013
+    // Send new ajax request
2014
+    this.ajaxRequest = jQuery.ajax(userOptions);
2015
+
2016
+    return this;
2017
+  };
2018
+
2019
+
2020
+  // Abort an ajax call
2021
+
2022
+  jBox.prototype.cancelAjax = function () {
2023
+    if (this.ajaxRequest) {
2024
+      this.ajaxRequest.abort();
2025
+      this.ajaxLoaded = false;
2026
+    }
2027
+  };
2028
+
2029
+
2030
+  // Play an audio file
2031
+
2032
+  jBox.prototype.audio = function (url, volume)
2033
+  {
2034
+    // URL is required
2035
+    if (!url) return this;
2036
+
2037
+    // Create intern audio object if it wasn't created already
2038
+    !jBox._audio && (jBox._audio = {});
2039
+
2040
+    // Create an audio element specific to this audio file if it doesn't exist already
2041
+    if (!jBox._audio[url]) {
2042
+      var audio = jQuery('<audio/>');
2043
+      jQuery('<source/>', {src: url + '.mp3'}).appendTo(audio);
2044
+      jQuery('<source/>', {src: url + '.ogg'}).appendTo(audio);
2045
+      jBox._audio[url] = audio[0];
2046
+    }
2047
+
2048
+    // Set volume
2049
+    jBox._audio[url].volume = Math.min(((volume != undefined ? volume : 100) / 100), 1);
2050
+
2051
+    // Try to pause current audio
2052
+    try {
2053
+      jBox._audio[url].pause();
2054
+      jBox._audio[url].currentTime = 0;
2055
+    } catch (e) {}
2056
+
2057
+    // Play audio
2058
+    jBox._audio[url].play();
2059
+
2060
+    return this;
2061
+  };
2062
+
2063
+
2064
+  // Apply custom animations to jBox
2065
+
2066
+  jBox._animationSpeeds = {
2067
+    'tada': 1000,
2068
+    'tadaSmall': 1000,
2069
+    'flash': 500,
2070
+    'shake': 400,
2071
+    'pulseUp': 250,
2072
+    'pulseDown': 250,
2073
+    'popIn': 250,
2074
+    'popOut': 250,
2075
+    'fadeIn': 200,
2076
+    'fadeOut': 200,
2077
+    'slideUp': 400,
2078
+    'slideRight': 400,
2079
+    'slideLeft': 400,
2080
+    'slideDown': 400
2081
+  };
2082
+
2083
+  jBox.prototype.animate = function (animation, options)
2084
+  {
2085
+    // Options are required
2086
+    !options && (options = {});
2087
+
2088
+    // Timout needs to be an object
2089
+    !this.animationTimeout && (this.animationTimeout = {});
2090
+
2091
+    // Use jBox wrapper by default
2092
+    !options.element && (options.element = this.wrapper);
2093
+
2094
+    // Give the element an unique id
2095
+    !options.element.data('jBox-animating-id') && options.element.data('jBox-animating-id', jBox._getUniqueElementID());
2096
+
2097
+    // Abort if element is animating
2098
+    if (options.element.data('jBox-animating')) {
2099
+      options.element.removeClass(options.element.data('jBox-animating')).data('jBox-animating', null);
2100
+      this.animationTimeout[options.element.data('jBox-animating-id')] && clearTimeout(this.animationTimeout[options.element.data('jBox-animating-id')]);
2101
+    }
2102
+
2103
+    // Animate the element
2104
+    options.element.addClass('jBox-animated-' + animation).data('jBox-animating', 'jBox-animated-' + animation);
2105
+    this.animationTimeout[options.element.data('jBox-animating-id')] = setTimeout((function() { options.element.removeClass(options.element.data('jBox-animating')).data('jBox-animating', null); options.complete && options.complete(); }), jBox._animationSpeeds[animation]);
2106
+  };
2107
+
2108
+  // https://gist.github.com/AlexEmashev/ee8302b5036b01362f63dab35948401f
2109
+  jBox.prototype.swipeDetector = function (swipeTarget, options) {
2110
+    // States: 0 - no swipe, 1 - swipe started, 2 - swipe released
2111
+    var swipeState = 0;
2112
+    // Coordinates when swipe started
2113
+    var startX = 0;
2114
+    var startY = 0;
2115
+    // Distance of swipe
2116
+    var pixelOffsetX = 0;
2117
+    var pixelOffsetY = 0;
2118
+
2119
+    var defaultSettings = {
2120
+      // Amount of pixels, when swipe don't count.
2121
+      swipeThreshold: 70,
2122
+      // Flag that indicates that plugin should react only on touch events.
2123
+      // Not on mouse events too.
2124
+      useOnlyTouch: false
2125
+    };
2126
+
2127
+    // Initializer
2128
+    (function init() {
2129
+      options = jQuery.extend(defaultSettings, options);
2130
+      // Support touch and mouse as well.
2131
+      swipeTarget.on("mousedown touchstart", swipeStart);
2132
+      $("html").on("mouseup touchend", swipeEnd);
2133
+      $("html").on("mousemove touchmove", swiping);
2134
+    })();
2135
+
2136
+    function swipeStart(event) {
2137
+      if (options.useOnlyTouch && !event.originalEvent.touches) {
2138
+        return;
2139
+      }
2140
+
2141
+      if (event.originalEvent.touches) {
2142
+        event = event.originalEvent.touches[0];
2143
+      }
2144
+
2145
+      if (swipeState === 0) {
2146
+        swipeState = 1;
2147
+        startX = event.clientX;
2148
+        startY = event.clientY;
2149
+      }
2150
+    }
2151
+
2152
+    function swipeEnd(event) {
2153
+      if (swipeState === 2) {
2154
+        swipeState = 0;
2155
+
2156
+        if (
2157
+          Math.abs(pixelOffsetX) > Math.abs(pixelOffsetY) &&
2158
+          Math.abs(pixelOffsetX) > options.swipeThreshold
2159
+        ) {
2160
+          // Horizontal Swipe
2161
+          if (pixelOffsetX < 0) {
2162
+            swipeTarget.trigger($.Event("swipeLeft.sd"));
2163
+          } else {
2164
+            swipeTarget.trigger($.Event("swipeRight.sd"));
2165
+          }
2166
+        } else if (Math.abs(pixelOffsetY) > options.swipeThreshold) {
2167
+          // Vertical swipe
2168
+          if (pixelOffsetY < 0) {
2169
+            swipeTarget.trigger($.Event("swipeUp.sd"));
2170
+          } else {
2171
+            swipeTarget.trigger($.Event("swipeDown.sd"));
2172
+          }
2173
+        }
2174
+      }
2175
+    }
2176
+
2177
+    function swiping(event) {
2178
+      // If swipe don't occuring, do nothing.
2179
+      if (swipeState !== 1) return;
2180
+
2181
+      if (event.originalEvent.touches) {
2182
+        event = event.originalEvent.touches[0];
2183
+      }
2184
+
2185
+      var swipeOffsetX = event.clientX - startX;
2186
+      var swipeOffsetY = event.clientY - startY;
2187
+
2188
+      if (
2189
+        Math.abs(swipeOffsetX) > options.swipeThreshold ||
2190
+        Math.abs(swipeOffsetY) > options.swipeThreshold
2191
+      ) {
2192
+        swipeState = 2;
2193
+        pixelOffsetX = swipeOffsetX;
2194
+        pixelOffsetY = swipeOffsetY;
2195
+      }
2196
+    }
2197
+
2198
+    return swipeTarget; // Return element available for chaining.
2199
+  }
2200
+
2201
+
2202
+  // Destroy jBox and remove it from DOM
2203
+
2204
+  jBox.prototype.destroy = function ()
2205
+  {
2206
+    // Detach from attached elements
2207
+    this.detach();
2208
+
2209
+    // If jBox is open, close without delay
2210
+    this.isOpen && this.close({ignoreDelay: true});
2211
+
2212
+    // Remove wrapper
2213
+    this.wrapper && this.wrapper.remove();
2214
+
2215
+    // Remove overlay
2216
+    this.overlay && this.overlay.remove();
2217
+
2218
+    // Remove styles
2219
+    this._styles && this._styles.remove();
2220
+
2221
+    // Tell the jBox instance it is destroyed
2222
+    this.isDestroyed = true;
2223
+
2224
+    return this;
2225
+  };
2226
+
2227
+
2228
+  // Get a unique ID for jBoxes
2229
+
2230
+  jBox._getUniqueID = (function ()
2231
+  {
2232
+    var i = 1;
2233
+    return function () { return i++; };
2234
+  }());
2235
+
2236
+
2237
+  // Get a unique ID for animating elements
2238
+
2239
+  jBox._getUniqueElementID = (function ()
2240
+  {
2241
+    var i = 1;
2242
+    return function () { return i++; };
2243
+  }());
2244
+
2245
+
2246
+  // Function to create jBox plugins
2247
+
2248
+  jBox._pluginOptions = {};
2249
+  jBox.plugin = function (type, options)
2250
+  {
2251
+    jBox._pluginOptions[type] = options;
2252
+  };
2253
+
2254
+
2255
+  // Make jBox usable with jQuery selectors
2256
+
2257
+  jQuery.fn.jBox = function (type, options) {
2258
+    // Variables type and object are required
2259
+    !type && (type = {});
2260
+    !options && (options = {});
2261
+
2262
+    // Return a new instance of jBox with the selector as attached element
2263
+    return new jBox(type, jQuery.extend(options, {
2264
+      attach: this
2265
+    }));
2266
+  };
2267
+
2268
+  return jBox;
2269
+
2270
+};
2271
+
2272
+/**
2273
+ * jBox Confirm plugin: Add a confirm dialog to links, buttons, etc.
2274
+ *
2275
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
2276
+ *
2277
+ * License: MIT (https://opensource.org/licenses/MIT)
2278
+ *
2279
+ * Requires: jBox (https://cdn.jsdelivr.net/gh/StephanWagner/jBox@latest/dist/jBox.min.js)
2280
+ */
2281
+
2282
+function jBoxConfirmWrapper(jBox, jQuery) {
2283
+
2284
+  new jBox.plugin('Confirm', {
2285
+
2286
+
2287
+    // Options (https://stephanwagner.me/jBox/options#options-confirm)
2288
+
2289
+    confirmButton: 'Submit',  // Text for the submit button
2290
+    cancelButton: 'Cancel',   // Text for the cancel button
2291
+    confirm: null,            // Function to execute when clicking the submit button. By default jBox will use the onclick or href attribute in that order if found
2292
+    cancel: null,             // Function to execute when clicking the cancel button
2293
+    closeOnConfirm: true,     // Close jBox when the user clicks the confirm button
2294
+    target: window,
2295
+    fixed: true,
2296
+    attach: '[data-confirm]',
2297
+    getContent: 'data-confirm',
2298
+    content: 'Do you really want to do this?',
2299
+    minWidth: 360,
2300
+    maxWidth: 500,
2301
+    blockScroll: true,
2302
+    closeOnEsc: true,
2303
+    closeOnClick: false,
2304
+    closeButton: false,
2305
+    overlay: true,
2306
+    animation: 'zoomIn',
2307
+    preventDefault: true,
2308
+
2309
+
2310
+    // Triggered when jBox is attached to the element
2311
+
2312
+    _onAttach: function (el)
2313
+    {
2314
+      // Extract the href or the onclick event if no submit event is passed
2315
+      if (!this.options.confirm) {
2316
+        var submit = el.attr('onclick') ? el.attr('onclick') : (
2317
+          el.attr('href') ? (
2318
+            el.attr('target') ? 'window.open("' + el.attr('href') + '", "' + el.attr('target') + '");'  : 'window.location.href = "' + el.attr('href') + '";'
2319
+          ) : '');
2320
+        el.prop('onclick', null).data('jBox-Confirm-submit', submit);
2321
+      }
2322
+    },
2323
+
2324
+
2325
+    // Triggered when jBox was created
2326
+
2327
+    _onCreated: function ()
2328
+    {
2329
+      // Add modal class to mimic jBox modal
2330
+      this.wrapper.addClass('jBox-Modal');
2331
+
2332
+      // Add a footer to the jBox container
2333
+      this.footer = jQuery('<div class="jBox-Confirm-footer"/>');
2334
+
2335
+      jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-cancel"/>')
2336
+        .html(this.options.cancelButton)
2337
+        .on('click tap', function () {
2338
+          this.options.cancel && this.options.cancel(this.source);
2339
+          this.close();
2340
+        }.bind(this))
2341
+        .appendTo(this.footer);
2342
+
2343
+      this.submitButton = jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-submit"/>')
2344
+        .html(this.options.confirmButton)
2345
+        .appendTo(this.footer);
2346
+
2347
+      this.footer.appendTo(this.container);
2348
+    },
2349
+
2350
+
2351
+    // Triggered when jBox is opened
2352
+
2353
+    _onOpen: function ()
2354
+    {
2355
+      // Set the new action for the submit button
2356
+      this.submitButton
2357
+        .off('click.jBox-Confirm' + this.id + ' tap.jBox-Confirm' + this.id)
2358
+        .on('click.jBox-Confirm' + this.id + ' tap.jBox-Confirm' + this.id, function () {
2359
+          this.options.confirm ? this.options.confirm(this.source) : eval(this.source.data('jBox-Confirm-submit'));
2360
+          this.options.closeOnConfirm && this.close();
2361
+        }.bind(this));
2362
+    }
2363
+
2364
+  });
2365
+
2366
+};
2367
+
2368
+/**
2369
+ * jBox Image plugin: Adds a lightbox to your images
2370
+ *
2371
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
2372
+ *
2373
+ * License: MIT (https://opensource.org/licenses/MIT)
2374
+ *
2375
+ * Requires: jBox (https://cdn.jsdelivr.net/gh/StephanWagner/jBox@latest/dist/jBox.min.js)
2376
+ */
2377
+
2378
+function jBoxImageWrapper(jBox, jQuery) {
2379
+
2380
+  new jBox.plugin('Image', {
2381
+
2382
+
2383
+    // Options (https://stephanwagner.me/jBox/options#options-image)
2384
+
2385
+    src: 'href',                 // The attribute where jBox gets the image source from, e.g. href="/path_to_image/image.jpg"
2386
+    gallery: 'data-jbox-image',  // The attribute to set the galleries, e.g. data-jbox-image="gallery1"
2387
+    imageLabel: 'title',         // The attribute where jBox gets the image label from, e.g. title="My label"
2388
+    imageFade: 360,              // The fade duration for images in ms
2389
+    imageSize: 'contain',        // How to display the images. Use CSS background-position values, e.g. 'cover', 'contain', 'auto', 'initial', '50% 50%'
2390
+    imageCounter: false,         // Set to true to add an image counter, e.g. 4/20
2391
+    imageCounterSeparator: '/',  // HTML to separate the current image number from all image numbers, e.g. '/' or ' of '
2392
+    downloadButton: false,       // Adds a download button
2393
+    downloadButtonText: null,    // Text for the download button
2394
+    downloadButtonUrl: null,     // The attribute at the source element where to find the image to download, e.g. data-download="/path_to_image/image.jpg". If none provided, the currently active image will be downloaded
2395
+    mobileImageAttr: null,       // The attribute to look for an mobile version of the image
2396
+    mobileImageBreakpoint: null, // The upper breakpoint to load the mobile image
2397
+    preloadFirstImage: false,    // Preload the first image when page is loaded
2398
+    target: window,
2399
+    attach: '[data-jbox-image]',
2400
+    fixed: true,
2401
+    blockScroll: true,
2402
+    closeOnEsc: true,
2403
+    closeOnClick: 'button',
2404
+    closeButton: true,
2405
+    overlay: true,
2406
+    animation: 'zoomIn',
2407
+    preventDefault: true,
2408
+    width: '100%',
2409
+    height: '100%',
2410
+    adjustDistance: {
2411
+      top: 40,
2412
+      right: 0,
2413
+      bottom: 40,
2414
+      left: 0
2415
+    },
2416
+
2417
+
2418
+    // Triggered when jBox is initialized
2419
+
2420
+    _onInit: function ()
2421
+    {
2422
+      // Initial images and z-index
2423
+      this.images = this.currentImage = {};
2424
+      this.imageZIndex = 1;
2425
+
2426
+      this.initImage = function (item) {
2427
+        item = jQuery(item);
2428
+
2429
+        // Abort if the item was added to a gallery already
2430
+        if (item.data('jBox-image-gallery')) {
2431
+          return;
2432
+        }
2433
+
2434
+        // Get the image src
2435
+        var src = item.attr(this.options.src);
2436
+
2437
+        // Update responsive image src
2438
+        if (this.options.mobileImageAttr && this.options.mobileImageBreakpoint && item.attr(this.options.mobileImageAttr)) {
2439
+          if (jQuery(window).width() <= this.options.mobileImageBreakpoint) {
2440
+            src = item.attr(this.options.mobileImageAttr);
2441
+          }
2442
+        }
2443
+
2444
+        // Add item to a gallery
2445
+        var gallery = item.attr(this.options.gallery) || 'default';
2446
+        !this.images[gallery] && (this.images[gallery] = []);
2447
+        this.images[gallery].push({
2448
+          src: src,
2449
+          label: (item.attr(this.options.imageLabel) || ''),
2450
+          downloadUrl: this.options.downloadButtonUrl && item.attr(this.options.downloadButtonUrl) ? item.attr(this.options.downloadButtonUrl) : null
2451
+        });
2452
+
2453
+        // Remove the title attribute so it won't show the browsers tooltip
2454
+        this.options.imageLabel == 'title' && item.removeAttr('title');
2455
+
2456
+        // Store data in source element for easy access
2457
+        item.data('jBox-image-gallery', gallery);
2458
+        item.data('jBox-image-id', (this.images[gallery].length - 1));
2459
+      }.bind(this);
2460
+
2461
+      // Loop through images, sort and save in global variable
2462
+      this.attachedElements && this.attachedElements.length && jQuery.each(this.attachedElements, function (index, item) {
2463
+        this.initImage(item);
2464
+      }.bind(this));
2465
+
2466
+      // Helper to inject the image into content area
2467
+      var appendImage = function (gallery, id, show, instant) {
2468
+        // Abort if image was appended already
2469
+        if (jQuery('#jBox-image-' + gallery + '-' + id).length) {
2470
+          return;
2471
+        }
2472
+
2473
+        // Create image container
2474
+        var image = jQuery('<div/>', {
2475
+          id: 'jBox-image-' + gallery + '-' + id,
2476
+          'class': 'jBox-image-container' + (show ? ' jBox-image-' + gallery + '-current' : '')
2477
+        }).css({
2478
+          backgroundSize: this.options.imageSize,
2479
+          opacity: (instant ? 1 : 0),
2480
+          zIndex: (show ? this.imageZIndex++ : 0)
2481
+        }).appendTo(this.content);
2482
+
2483
+        // Add swipe events
2484
+        this.swipeDetector(image)
2485
+          .on("swipeLeft.sd swipeRight.sd", function (event) {
2486
+            if (event.type === "swipeLeft") {
2487
+              this.showImage('next');
2488
+            } else if (event.type === "swipeRight") {
2489
+              this.showImage('prev');
2490
+            }
2491
+          }.bind(this));
2492
+
2493
+        // Create labels
2494
+        jQuery('<div/>', {
2495
+          id: 'jBox-image-label-' + gallery + '-' + id,
2496
+          'class': 'jBox-image-label' + (show ? ' active' : '')
2497
+        })
2498
+        .html(this.images[gallery][id].label)
2499
+        .on('click tap', function () {
2500
+          jQuery(this).toggleClass('expanded');
2501
+        })
2502
+        .appendTo(this.imageLabelContainer);
2503
+
2504
+        // Show image
2505
+        show && image.animate({opacity: 1}, instant ? 0 : this.options.imageFade);
2506
+
2507
+        return image;
2508
+      }.bind(this);
2509
+
2510
+      // Function to download an image
2511
+      this.downloadImage = function (imageUrl) {
2512
+        var link = document.createElement('a');
2513
+        link.href = imageUrl;
2514
+        link.setAttribute('download', imageUrl.substring(imageUrl.lastIndexOf('/')+1));
2515
+        document.body.appendChild(link);
2516
+        link.click();
2517
+      };
2518
+
2519
+      // Helper to show new image label
2520
+      var showLabel = function (gallery, id) {
2521
+        jQuery('.jBox-image-label.active').removeClass('active expanded');
2522
+        jQuery('#jBox-image-label-' + gallery + '-' + id).addClass('active');
2523
+      };
2524
+
2525
+      // Helper to load image
2526
+      var loadImage = function (gallery, id, show, instant) {
2527
+        var imageContainer = appendImage(gallery, id, show, instant);
2528
+        imageContainer.addClass('jBox-image-loading');
2529
+
2530
+        jQuery('<img src="' + this.images[gallery][id].src + '" />').each(function () {
2531
+          var tmpImg = new Image();
2532
+          tmpImg.onload = function () {
2533
+            imageContainer.removeClass('jBox-image-loading');
2534
+            imageContainer.css({backgroundImage: 'url("' + this.images[gallery][id].src + '")'});
2535
+          }.bind(this);
2536
+
2537
+          tmpImg.onerror = function () {
2538
+            imageContainer.removeClass('jBox-image-loading');
2539
+            imageContainer.addClass('jBox-image-not-found');
2540
+          }.bind(this);
2541
+
2542
+          tmpImg.src = this.images[gallery][id].src;
2543
+        }.bind(this));
2544
+      }.bind(this);
2545
+
2546
+      // Show images when they are loaded or load them if not
2547
+      this.showImage = function (img) {
2548
+        // Get the gallery and the image id from the next or the previous image
2549
+        if (img != 'open') {
2550
+          var gallery = this.currentImage.gallery;
2551
+          var id = this.currentImage.id + (1 * (img == 'prev') ? -1 : 1);
2552
+          id = id > (this.images[gallery].length - 1) ? 0 : (id < 0 ? (this.images[gallery].length - 1) : id);
2553
+
2554
+        // Or get image data from source element
2555
+        } else {
2556
+          // Get gallery and image id from source element
2557
+          if (this.source) {
2558
+            var gallery = this.source.data('jBox-image-gallery');
2559
+            var id = this.source.data('jBox-image-id');
2560
+
2561
+          // Get gallery and image id attached elements
2562
+          } else if (this.attachedElements && this.attachedElements.length) {
2563
+            var gallery = jQuery(this.attachedElements[0]).data('jBox-image-gallery');
2564
+            var id = jQuery(this.attachedElements[0]).data('jBox-image-id');
2565
+          } else {
2566
+            return;
2567
+          }
2568
+
2569
+          // Remove or show the next and prev buttons
2570
+          jQuery('.jBox-image-pointer-prev, .jBox-image-pointer-next').css({display: (this.images[gallery].length > 1 ? 'block' : 'none')});
2571
+        }
2572
+
2573
+        // If there is a current image already shown, hide it
2574
+        if (jQuery('.jBox-image-' + gallery + '-current').length) {
2575
+          jQuery('.jBox-image-' + gallery + '-current').removeClass('jBox-image-' + gallery + '-current').animate({opacity: 0}, (img == 'open') ? 0 : this.options.imageFade);
2576
+        }
2577
+
2578
+        // Set new current image
2579
+        this.currentImage = {gallery: gallery, id: id};
2580
+
2581
+        // Show image if it already exists
2582
+        if (jQuery('#jBox-image-' + gallery + '-' + id).length) {
2583
+          jQuery('#jBox-image-' + gallery + '-' + id).addClass('jBox-image-' + gallery + '-current').css({zIndex: this.imageZIndex++, opacity: 0}).animate({opacity: 1}, (img == 'open') ? 0 : this.options.imageFade);
2584
+
2585
+        // Load image
2586
+        } else {
2587
+          loadImage(gallery, id, true, (img === 'open'));
2588
+        }
2589
+
2590
+        // Show label
2591
+        showLabel(gallery, id);
2592
+
2593
+        // Update the image counter numbers
2594
+        if (this.imageCounter) {
2595
+          if (this.images[gallery].length > 1) {
2596
+            this.wrapper.addClass('jBox-image-has-counter');
2597
+            this.imageCounter.find('.jBox-image-counter-all').html(this.images[gallery].length);
2598
+            this.imageCounter.find('.jBox-image-counter-current').html(id + 1);
2599
+          } else {
2600
+            this.wrapper.removeClass('jBox-image-has-counter');
2601
+          }
2602
+        }
2603
+
2604
+        // Preload next image
2605
+        if (this.images[gallery].length - 1) {
2606
+	        var next_id = id + 1;
2607
+	        next_id = next_id > (this.images[gallery].length - 1) ? 0 : (next_id < 0 ? (this.images[gallery].length - 1) : next_id);
2608
+
2609
+	        if (!jQuery('#jBox-image-' + gallery + '-' + next_id).length) {
2610
+            loadImage(gallery, next_id, false, false);
2611
+          }
2612
+	      }
2613
+      };
2614
+
2615
+      // Preload image
2616
+      if (this.options.preloadFirstImage) {
2617
+        jQuery(window).on('load', function() {
2618
+          this.showImage('open');
2619
+        }.bind(this));
2620
+      }
2621
+    },
2622
+
2623
+
2624
+    // Triggered when jBox attaches a new element
2625
+
2626
+    _onAttach: function (item) {
2627
+      this.initImage && this.initImage(item);
2628
+    },
2629
+
2630
+
2631
+    // Triggered when jBox was created
2632
+
2633
+    _onCreated: function ()
2634
+    {
2635
+      // Create image label and navigation buttons
2636
+      this.imageLabelWrapper = jQuery('<div class="jBox-image-label-wrapper"/>').appendTo(this.wrapper);
2637
+
2638
+      this.imagePrevButton = jQuery('<div class="jBox-image-pointer-prev"/>')
2639
+        .on('click tap', function () {
2640
+          this.showImage('prev');
2641
+        }.bind(this));
2642
+
2643
+      this.imageNextButton = jQuery('<div class="jBox-image-pointer-next"/>')
2644
+        .on('click tap', function () {
2645
+          this.showImage('next');
2646
+        }.bind(this));
2647
+
2648
+      this.imageLabelContainer = jQuery('<div class="jBox-image-label-container"/>');
2649
+
2650
+      this.imageLabelWrapper
2651
+        .append(this.imagePrevButton)
2652
+        .append(this.imageLabelContainer)
2653
+        .append(this.imageNextButton);
2654
+
2655
+      // Append the download button
2656
+      if (this.options.downloadButton) {
2657
+        this.downloadButton = jQuery('<div/>', {'class': 'jBox-image-download-button-wrapper'})
2658
+          .appendTo(this.wrapper)
2659
+          .append(
2660
+            this.options.downloadButtonText ? jQuery('<div/>', {'class': 'jBox-image-download-button-text'}).html(this.options.downloadButtonText) : null
2661
+          )
2662
+          .append(
2663
+            jQuery('<div/>', {'class': 'jBox-image-download-button-icon'})
2664
+          ).on('click tap', function () {
2665
+            if (this.images[this.currentImage.gallery][this.currentImage.id].downloadUrl) {
2666
+              var currentImageUrl = this.images[this.currentImage.gallery][this.currentImage.id].downloadUrl;
2667
+            } else {
2668
+              var currentImage = this.wrapper.find('.jBox-image-' + this.currentImage.gallery + '-current');
2669
+              var currentImageStyle = currentImage[0].style.backgroundImage;
2670
+              var currentImageUrl = currentImageStyle.slice(4, -1).replace(/["']/g, '');
2671
+            }
2672
+            this.downloadImage(currentImageUrl);
2673
+          }.bind(this));
2674
+      }
2675
+
2676
+      // Creating the image counter containers
2677
+      if (this.options.imageCounter) {
2678
+        this.imageCounter = jQuery('<div/>', {'class': 'jBox-image-counter-container'}).insertAfter(this.imageLabelContainer);
2679
+        this.imageCounter.append(jQuery('<span/>', {'class': 'jBox-image-counter-current'})).append(jQuery('<span/>').html(this.options.imageCounterSeparator)).append(jQuery('<span/>', {'class': 'jBox-image-counter-all'}));
2680
+      }
2681
+    },
2682
+
2683
+
2684
+    // Triggered when jBox opens
2685
+
2686
+    _onOpen: function ()
2687
+    {
2688
+      // Add key events
2689
+      jQuery(document).on('keyup.jBox-Image-' + this.id, function (ev) {
2690
+        (ev.keyCode == 37) && this.showImage('prev');
2691
+        (ev.keyCode == 39) && this.showImage('next');
2692
+      }.bind(this));
2693
+
2694
+      // Load the image from the attached element
2695
+      this.showImage('open');
2696
+    },
2697
+
2698
+
2699
+    // Triggered when jBox closes
2700
+
2701
+    _onClose: function ()
2702
+    {
2703
+      // Remove key events
2704
+      jQuery(document).off('keyup.jBox-Image-' + this.id);
2705
+    },
2706
+
2707
+
2708
+    // Triggered when jBox finished closing
2709
+
2710
+    _onCloseComplete: function ()
2711
+    {
2712
+      // Hide all image containers
2713
+      this.wrapper.find('.jBox-image-container').css('opacity', 0);
2714
+    }
2715
+
2716
+  });
2717
+
2718
+};
2719
+
2720
+/**
2721
+ * jBox Notice plugin: Opens a popup notice
2722
+ *
2723
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
2724
+ *
2725
+ * License: MIT (https://opensource.org/licenses/MIT)
2726
+ *
2727
+ * Requires: jBox (https://cdn.jsdelivr.net/gh/StephanWagner/jBox@latest/dist/jBox.min.js)
2728
+ */
2729
+
2730
+function jBoxNoticeWrapper(jBox, jQuery) {
2731
+
2732
+  new jBox.plugin('Notice', {
2733
+
2734
+
2735
+    // Options (https://stephanwagner.me/jBox/options#options-notice)
2736
+
2737
+    color: null,      // Add a color to your notices, use 'gray' (default), 'black', 'red', 'green', 'blue' or 'yellow'
2738
+    stack: true,      // Set to false to disable notice-stacking
2739
+    stackSpacing: 10, // Spacing between notices when they stack
2740
+    autoClose: 6000,  // Time in ms after which the notice will disappear
2741
+    attributes: {     // Defines where the notice will pop up
2742
+      x: 'right',     // 'left' or 'right'
2743
+      y: 'top'        // 'top' or 'bottom'
2744
+    },
2745
+    position: {       // Defines the distance to the viewport boundary
2746
+      x: 15,
2747
+      y: 15
2748
+    },
2749
+    responsivePositions: {  // Responsive positions
2750
+      500: {                // The key defines the maximum width of the viewport, the values will replace the default position options
2751
+        x: 5,               // Start with the lowest viewport
2752
+        y: 5
2753
+      },
2754
+      768: {
2755
+        x: 10,
2756
+        y: 10
2757
+      }
2758
+    },
2759
+    target: window,
2760
+    fixed: true,
2761
+    animation: 'zoomIn',
2762
+    closeOnClick: 'box',
2763
+    zIndex: 12000,
2764
+
2765
+
2766
+    // Triggered when notice is initialized
2767
+
2768
+    _onInit: function ()
2769
+    {
2770
+      // Cache position values
2771
+      this.defaultNoticePosition = jQuery.extend({}, this.options.position);
2772
+
2773
+      // Type Notice has its own adjust position function
2774
+      this._adjustNoticePositon = function () {
2775
+        var win = jQuery(window);
2776
+        var windowDimensions = {
2777
+          x: win.width(),
2778
+          y: win.height()
2779
+        };
2780
+
2781
+        // Reset default position
2782
+        this.options.position = jQuery.extend({}, this.defaultNoticePosition);
2783
+
2784
+        // Adjust depending on viewport
2785
+        jQuery.each(this.options.responsivePositions, function (viewport, position) {
2786
+          if (windowDimensions.x <= viewport) {
2787
+            this.options.position = position;
2788
+            return false;
2789
+          }
2790
+        }.bind(this));
2791
+
2792
+        // Set new padding options
2793
+        this.options.adjustDistance = {
2794
+          top: this.options.position.y,
2795
+          right: this.options.position.x,
2796
+          bottom: this.options.position.y,
2797
+          left: this.options.position.x
2798
+        };
2799
+      };
2800
+
2801
+      // If jBox grabs an element as content, crab a clone instead
2802
+      this.options.content instanceof jQuery && (this.options.content = this.options.content.clone().attr('id', ''));
2803
+
2804
+      // Adjust paddings when window resizes
2805
+      jQuery(window).on('resize.responsivejBoxNotice-' + this.id, function (ev) { if (this.isOpen) { this._adjustNoticePositon(); } }.bind(this));
2806
+
2807
+      this.open();
2808
+    },
2809
+
2810
+
2811
+    // Triggered when notice was created
2812
+
2813
+    _onCreated: function ()
2814
+    {
2815
+      // Add color class
2816
+      this.wrapper.addClass('jBox-Notice-color jBox-Notice-' + (this.options.color || 'gray'));
2817
+
2818
+      // Store position in jBox wrapper
2819
+      this.wrapper.data('jBox-Notice-position', this.options.attributes.x + '-' + this.options.attributes.y);
2820
+    },
2821
+
2822
+
2823
+    // Triggered when notice opens
2824
+
2825
+    _onOpen: function ()
2826
+    {
2827
+      // Bail if we're stacking
2828
+      if (this.options.stack) {
2829
+          return;
2830
+      }
2831
+
2832
+      // Adjust position when opening
2833
+      this._adjustNoticePositon();
2834
+
2835
+      // Loop through notices at same window corner destroy them
2836
+      jQuery.each(jQuery('.jBox-Notice'), function (index, el)
2837
+      {
2838
+        el = jQuery(el);
2839
+
2840
+        // Abort if the element is this notice or when it's not at the same position
2841
+        if (el.attr('id') == this.id || el.data('jBox-Notice-position') != this.options.attributes.x + '-' + this.options.attributes.y) {
2842
+          return;
2843
+        }
2844
+
2845
+        // Remove notice when we don't wont to stack them
2846
+        if (!this.options.stack) {
2847
+          el.data('jBox').close({ignoreDelay: true});
2848
+          return;
2849
+        }
2850
+      }.bind(this));
2851
+    },
2852
+
2853
+    // Triggered when resizing window etc.
2854
+
2855
+    _onPosition: function ()
2856
+    {
2857
+        var stacks = {};
2858
+        jQuery.each(jQuery('.jBox-Notice'), function (index, el)
2859
+        {
2860
+          el = jQuery(el);
2861
+          var pos = el.data('jBox-Notice-position');
2862
+          if (!stacks[pos]) {
2863
+              stacks[pos] = [];
2864
+          }
2865
+          stacks[pos].push(el);
2866
+        });
2867
+        for (var pos in stacks) {
2868
+            var position = pos.split('-');
2869
+            var direction = position[1];
2870
+            stacks[pos].reverse();
2871
+            var margin = 0;
2872
+            for (var i in stacks[pos]) {
2873
+                var el = jQuery(stacks[pos][i]);
2874
+                el.css('margin-' + direction, margin);
2875
+                margin += el.outerHeight() + this.options.stackSpacing;
2876
+            }
2877
+        }
2878
+    },
2879
+
2880
+    // Remove notice from DOM and reposition other notices when closing finishes
2881
+
2882
+    _onCloseComplete: function ()
2883
+    {
2884
+        this.destroy();
2885
+        this.options._onPosition.bind(this).call();
2886
+    }
2887
+
2888
+  });
2889
+
2890
+};
2891
+
2892
+(function (root, factory) {
2893
+  if (typeof define === 'function' && define.amd) {
2894
+    define(['jquery'], function (jQuery) {
2895
+      return (root.jBox = factory(jQuery));
2896
+    });
2897
+  } else if (typeof module === 'object' && module.exports) {
2898
+    module.exports = (root.jBox = factory(require('jquery')));
2899
+  } else {
2900
+    root.jBox = factory(root.jQuery);
2901
+  }
2902
+}(this, function (jQuery) {
2903
+  var jBox = jBoxWrapper(jQuery);
2904
+  try { typeof jBoxConfirmWrapper !== 'undefined' && jBoxConfirmWrapper && jBoxConfirmWrapper(jBox, jQuery); } catch(e) { console.error(e); }
2905
+  try { typeof jBoxImageWrapper !== 'undefined' && jBoxImageWrapper && jBoxImageWrapper(jBox, jQuery); } catch(e) { console.error(e); }
2906
+  try { typeof jBoxNoticeWrapper !== 'undefined' && jBoxNoticeWrapper && jBoxNoticeWrapper(jBox, jQuery); } catch(e) { console.error(e); }
2907
+  return jBox;
2908
+}));
2909
+
2910
+//# sourceMappingURL=jBox.all.js.map
0 2911
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-wrapper{text-align:left;box-sizing:border-box}.jBox-container,.jBox-content,.jBox-title{position:relative;word-break:break-word;box-sizing:border-box}.jBox-container{background:#fff}.jBox-content{padding:8px 12px;overflow-x:hidden;overflow-y:auto;transition:opacity .2s}.jBox-footer{box-sizing:border-box}.jBox-Mouse .jBox-container,.jBox-Tooltip .jBox-container{border-radius:4px;box-shadow:0 0 3px rgba(0,0,0,.25)}.jBox-Mouse .jBox-title,.jBox-Tooltip .jBox-title{padding:8px 10px 0;font-weight:700}.jBox-Mouse.jBox-hasTitle .jBox-content,.jBox-Tooltip.jBox-hasTitle .jBox-content{padding-top:5px}.jBox-Mouse{pointer-events:none}.jBox-pointer{position:absolute;overflow:hidden;box-sizing:border-box}.jBox-pointer:after{content:'';width:20px;height:20px;position:absolute;background:#fff;transform:rotate(45deg);box-sizing:border-box}.jBox-pointer-top{top:0}.jBox-pointer-top:after{left:5px;top:6px;box-shadow:-1px -1px 2px rgba(0,0,0,.15)}.jBox-pointer-right{right:0}.jBox-pointer-right:after{top:5px;right:6px;box-shadow:1px -1px 2px rgba(0,0,0,.15)}.jBox-pointer-left{left:0}.jBox-pointer-left:after{top:5px;left:6px;box-shadow:-1px 1px 2px rgba(0,0,0,.15)}.jBox-pointer-bottom{bottom:0}.jBox-pointer-bottom:after{left:5px;bottom:6px;box-shadow:1px 1px 2px rgba(0,0,0,.15)}.jBox-pointer-bottom,.jBox-pointer-top{width:30px;height:12px}.jBox-pointer-left,.jBox-pointer-right{width:12px;height:30px}.jBox-Modal .jBox-container{border-radius:4px}.jBox-Modal .jBox-container,.jBox-Modal.jBox-closeButton-box:before{box-shadow:0 3px 15px rgba(0,0,0,.4),0 0 5px rgba(0,0,0,.4)}.jBox-Modal .jBox-content{padding:15px 20px}.jBox-Modal .jBox-title{border-radius:4px 4px 0 0;padding:15px 20px;background:#fafafa;border-bottom:1px solid #eee}.jBox-Modal.jBox-closeButton-title .jBox-title{padding-right:65px}.jBox-Modal .jBox-footer{border-radius:0 0 4px 4px}.jBox-closeButton{z-index:1;cursor:pointer;position:absolute;box-sizing:border-box}.jBox-closeButton svg{position:absolute;top:50%;right:50%}.jBox-closeButton path{fill:#aaa;transition:fill .2s}.jBox-closeButton:hover path{fill:#888}.jBox-overlay .jBox-closeButton{top:0;right:0;width:40px;height:40px}.jBox-overlay .jBox-closeButton svg{width:20px;height:20px;margin-top:-10px;margin-right:-10px}.jBox-overlay .jBox-closeButton path{fill:#ddd}.jBox-overlay .jBox-closeButton:hover path{fill:#fff}.jBox-closeButton-title .jBox-closeButton{top:0;right:0;bottom:0;width:50px}.jBox-closeButton-title svg{width:12px;height:12px;margin-top:-6px;margin-right:-6px}.jBox-closeButton-box{box-sizing:border-box}.jBox-closeButton-box .jBox-closeButton{top:-8px;right:-10px;width:24px;height:24px;background:#fff;border-radius:50%}.jBox-closeButton-box .jBox-closeButton svg{width:10px;height:10px;margin-top:-5px;margin-right:-5px}.jBox-closeButton-box:before{content:'';position:absolute;top:-8px;right:-10px;width:24px;height:24px;border-radius:50%;box-shadow:0 0 5px rgba(0,0,0,.3)}.jBox-closeButton-box.jBox-pointerPosition-top:before{top:5px}.jBox-closeButton-box.jBox-pointerPosition-right:before{right:2px}.jBox-Modal.jBox-hasTitle.jBox-closeButton-box .jBox-closeButton{background:#fafafa}.jBox-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.82)}.jBox-footer{background:#fafafa;border-top:1px solid #eee;padding:8px 10px;border-radius:0 0 3px 3px}body[class*=" jBox-blockScroll-"],body[class^=jBox-blockScroll-]{overflow:hidden}.jBox-draggable{cursor:move}@keyframes jBoxLoading{to{transform:rotate(360deg)}}.jBox-loading .jBox-content{opacity:.2}.jBox-loading-spinner .jBox-content{min-height:38px!important;min-width:38px!important;opacity:0}.jBox-spinner{box-sizing:border-box;position:absolute;top:50%;left:50%;width:24px;height:24px;margin-top:-12px;margin-left:-12px}.jBox-spinner:before{display:block;box-sizing:border-box;content:'';width:24px;height:24px;border-radius:50%;border:2px solid rgba(0,0,0,.2);border-top-color:rgba(0,0,0,.8);animation:jBoxLoading .6s linear infinite}.jBox-countdown{border-radius:4px 4px 0 0;z-index:0;background:#000;opacity:.2;position:absolute;top:0;left:0;right:0;height:3px;overflow:hidden}.jBox-countdown-inner{top:0;right:0;width:100%;height:3px;position:absolute;background:#fff}[class*=" jBox-animated-"],[class^=jBox-animated-]{animation-fill-mode:both}@keyframes jBox-tada{0%{transform:scale(1)}10%,20%{transform:scale(.8) rotate(-4deg)}30%,50%,70%,90%{transform:scale(1.2) rotate(4deg)}40%,60%,80%{transform:scale(1.2) rotate(-4deg)}100%{transform:scale(1) rotate(0)}}.jBox-animated-tada{animation:jBox-tada 1s}@keyframes jBox-tadaSmall{0%{transform:scale(1)}10%,20%{transform:scale(.9) rotate(-2deg)}30%,50%,70%,90%{transform:scale(1.1) rotate(2deg)}40%,60%,80%{transform:scale(1.1) rotate(-2deg)}100%{transform:scale(1) rotate(0)}}.jBox-animated-tadaSmall{animation:jBox-tadaSmall 1s}@keyframes jBox-flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}.jBox-animated-flash{animation:jBox-flash .5s}@keyframes jBox-shake{0%,100%{transform:translateX(0)}20%,60%{transform:translateX(-6px)}40%,80%{transform:translateX(6px)}}.jBox-animated-shake{animation:jBox-shake .4s}@keyframes jBox-pulseUp{0%{transform:scale(1)}50%{transform:scale(1.15)}100%{transform:scale(1)}}.jBox-animated-pulseUp{animation:jBox-pulseUp .25s}@keyframes jBox-pulseDown{0%{transform:scale(1)}50%{transform:scale(.85)}100%{transform:scale(1)}}.jBox-animated-pulseDown{animation:jBox-pulseDown .25s}@keyframes jBox-popIn{0%{transform:scale(0)}50%{transform:scale(1.1)}100%{transform:scale(1)}}.jBox-animated-popIn{animation:jBox-popIn .25s}@keyframes jBox-popOut{0%{transform:scale(1)}50%{transform:scale(1.1)}100%{transform:scale(0)}}.jBox-animated-popOut{animation:jBox-popOut .25s}@keyframes jBox-fadeIn{0%{opacity:0}100%{opacity:1}}.jBox-animated-fadeIn{animation:jBox-fadeIn .2s}@keyframes jBox-fadeOut{0%{opacity:1}100%{opacity:0}}.jBox-animated-fadeOut{animation:jBox-fadeOut .2s}@keyframes jBox-slideUp{0%{transform:translateY(0)}100%{transform:translateY(-300px);opacity:0}}.jBox-animated-slideUp{animation:jBox-slideUp .4s}@keyframes jBox-slideRight{0%{transform:translateX(0)}100%{transform:translateX(300px);opacity:0}}.jBox-animated-slideRight{animation:jBox-slideRight .4s}@keyframes jBox-slideDown{0%{transform:translateY(0)}100%{transform:translateY(300px);opacity:0}}.jBox-animated-slideDown{animation:jBox-slideDown .4s}@keyframes jBox-slideLeft{0%{transform:translateX(0)}100%{transform:translateX(-300px);opacity:0}}.jBox-animated-slideLeft{animation:jBox-slideLeft .4s}.jBox-Confirm .jBox-content{text-align:center;padding:46px 35px}@media (max-width:500px){.jBox-Confirm .jBox-content{padding:32px 20px}}.jBox-Confirm-footer{height:46px}.jBox-Confirm-button{display:block;float:left;cursor:pointer;text-align:center;width:50%;line-height:46px;height:46px;overflow:hidden;padding:0 10px;transition:color .2s,background-color .2s;box-sizing:border-box}.jBox-Confirm-button-cancel{border-bottom-left-radius:4px;background:#ddd;color:#666}.jBox-Confirm-button-cancel:active,.jBox-Confirm-button-cancel:hover{background:#ccc}.jBox-Confirm-button-cancel:active{box-shadow:inset 0 1px 3px rgba(0,0,0,.2)}.jBox-Confirm-button-submit{border-bottom-right-radius:4px;background:#7d0;color:#fff}.jBox-Confirm-button-submit:active,.jBox-Confirm-button-submit:hover{background:#6c0}.jBox-Confirm-button-submit:active{box-shadow:inset 0 1px 3px rgba(0,0,0,.2)}.jBox-Image .jBox-container{background-color:transparent}.jBox-Image .jBox-content{padding:0;width:100%;height:100%}.jBox-image-container{background:center center no-repeat;position:absolute;width:100%;height:100%;opacity:0}.jBox-image-label-wrapper{position:absolute;top:100%;left:0;right:0;height:40px;z-index:100;display:flex}.jBox-image-label-container{position:relative;flex:1}.jBox-image-label{box-sizing:border-box;position:absolute;left:0;bottom:0;width:100%;text-align:center;color:#fff;padding:8px 12px;font-size:15px;line-height:24px;transition:opacity .36s;opacity:0;z-index:0;pointer-events:none}.jBox-image-label.expanded{background:#000}.jBox-image-label:not(.expanded){text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.jBox-image-label.active{opacity:1;pointer-events:all}@media (max-width:600px){.jBox-image-label{font-size:13px}}.jBox-image-pointer-next,.jBox-image-pointer-prev{flex-shrink:0;width:40px;height:40px;cursor:pointer;opacity:.8;transition:opacity .2s;background:no-repeat center center url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ijc0LjcgMjI0IDE4LjcgMzIiPg0KPHBhdGggZmlsbD0iI2ZmZmZmZiIgZD0iTTkzLDIyNy40TDgwLjQsMjQwTDkzLDI1Mi42YzAuNCwwLjQsMC40LDEuMSwwLDEuNWwtMS42LDEuNmMtMC40LDAuNC0xLDAuNS0xLjUsMEw3NSwyNDAuN2MtMC40LTAuNC0wLjUtMSwwLTEuNWwxNC45LTE0LjljMC40LTAuNCwxLTAuNCwxLjUsMGwxLjYsMS42QzkzLjUsMjI2LjQsOTMuNCwyMjcsOTMsMjI3LjR6Ii8+DQo8L3N2Zz4=);background-size:11px auto;user-select:none;z-index:1}.jBox-image-pointer-next:hover,.jBox-image-pointer-prev:hover{opacity:1}.jBox-image-pointer-next{transform:scaleX(-1)}.jBox-image-counter-container{flex-shrink:0;white-space:nowrap;height:40px;line-height:40px;font-size:13px;color:#fff;text-align:right;display:none}.jBox-image-has-counter .jBox-image-counter-container{display:block}.jBox-overlay.jBox-overlay-Image{background:#000}.jBox-image-not-found{background:#000}.jBox-image-not-found:before{content:'';box-sizing:border-box;display:block;width:80px;height:80px;margin-top:-40px;margin-left:-40px;position:absolute;top:50%;left:50%;border:5px solid #222;border-radius:50%}.jBox-image-not-found:after{content:'';display:block;box-sizing:content-box;z-index:auto;width:6px;height:74px;margin-top:-37px;margin-left:-3px;position:absolute;top:50%;left:50%;background:#222;transform:rotateZ(45deg);transform-origin:50% 50% 0}.jBox-image-download-button-wrapper{position:absolute;top:-40px;right:35px;height:40px;display:flex;cursor:pointer;opacity:.8;transition:opacity .2s}.jBox-image-download-button-wrapper:hover{opacity:1}.jBox-image-download-button-icon{width:40px;height:40px;background:center center no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNjQwIj48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNNDE2IDI1NnYtMTkyaC0xOTJ2MTkyaC0xNjBsMjU2IDI1NiAyNTYtMjU2aC0xNjB6TTAgNTc2aDY0MHY2NGgtNjQwdi02NHoiPjwvcGF0aD48L3N2Zz4=);background-size:60%}.jBox-image-download-button-text{white-space:nowrap;line-height:40px;padding:0 10px 0 0;color:#fff;font-size:14px}@keyframes jBoxImageLoading{to{transform:rotate(360deg)}}.jBox-image-loading:before{content:'';position:absolute;top:50%;left:50%;width:32px;height:32px;margin-top:-16px;margin-left:-16px;border:4px solid #333;border-bottom-color:#666;animation:jBoxImageLoading 1.2s linear infinite;border-radius:50%}.jBox-Notice{transition:margin .2s}.jBox-Notice .jBox-container{border-radius:4px;box-shadow:inset 1px 1px 0 0 rgba(255,255,255,.25),inset -1px -1px 0 0 rgba(0,0,0,.1)}.jBox-Notice .jBox-content{border-radius:4px;padding:12px 20px}@media (max-width:768px){.jBox-Notice .jBox-content{padding:10px 15px}}@media (max-width:500px){.jBox-Notice .jBox-content{padding:8px 10px}}.jBox-Notice.jBox-hasTitle .jBox-content{padding-top:5px}@media (max-width:500px){.jBox-Notice.jBox-hasTitle .jBox-content{padding-top:0}}.jBox-Notice.jBox-hasTitle .jBox-title{padding:12px 20px 0;font-weight:700}@media (max-width:768px){.jBox-Notice.jBox-hasTitle .jBox-title{padding:10px 15px 0}}@media (max-width:500px){.jBox-Notice.jBox-hasTitle .jBox-title{padding:8px 10px 0}}.jBox-Notice.jBox-closeButton-title .jBox-title{padding-right:55px}.jBox-Notice.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton{width:40px}.jBox-Notice.jBox-Notice-black .jBox-container{color:#fff;background:#000}.jBox-Notice.jBox-Notice-black.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-black.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#fff}.jBox-Notice.jBox-Notice-gray .jBox-container{color:#222;background:#f6f6f6}.jBox-Notice.jBox-Notice-gray.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-gray.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#222}.jBox-Notice.jBox-Notice-red .jBox-container{color:#fff;background:#d00}.jBox-Notice.jBox-Notice-red.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-red.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#fff}.jBox-Notice.jBox-Notice-green .jBox-container{color:#fff;background:#5d0}.jBox-Notice.jBox-Notice-green.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-green.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#fff}.jBox-Notice.jBox-Notice-blue .jBox-container{color:#fff;background:#49d}.jBox-Notice.jBox-Notice-blue.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-blue.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#fff}.jBox-Notice.jBox-Notice-yellow .jBox-container{color:#000;background:#fd0}.jBox-Notice.jBox-Notice-yellow.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-yellow.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#fff}.jBox-NoticeFancy .jBox-content,.jBox-NoticeFancy .jBox-title{padding-left:25px}.jBox-NoticeFancy.jBox-Notice-color .jBox-container{color:#fff;background:#000}.jBox-NoticeFancy.jBox-Notice-color .jBox-container:after{content:'';position:absolute;top:0;left:0;bottom:0;width:8px;border-radius:4px 0 0 4px;background-image:linear-gradient(45deg,rgba(255,255,255,.4) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.4) 75%,transparent 75%,transparent);background-size:14px 14px}.jBox-NoticeFancy.jBox-Notice-black .jBox-container:after,.jBox-NoticeFancy.jBox-Notice-gray .jBox-container:after{background-color:#888}.jBox-NoticeFancy.jBox-Notice-red .jBox-container:after{background-color:#e00}.jBox-NoticeFancy.jBox-Notice-green .jBox-container:after{background-color:#6c0}.jBox-NoticeFancy.jBox-Notice-blue .jBox-container:after{background-color:#49d}.jBox-NoticeFancy.jBox-Notice-yellow .jBox-container:after{background-color:#fb0}.jBox-NoticeFancy .jBox-countdown{left:8px;border-radius:0 4px 0 0}.jBox-TooltipBorder .jBox-container,.jBox-TooltipBorder .jBox-pointer:after{border:2px solid #49d}.jBox-TooltipBorder .jBox-pointer:after{width:22px;height:22px}.jBox-TooltipBorder .jBox-pointer-bottom,.jBox-TooltipBorder .jBox-pointer-top{width:34px;height:13px}.jBox-TooltipBorder .jBox-pointer-bottom:after,.jBox-TooltipBorder .jBox-pointer-top:after{left:6px}.jBox-TooltipBorder .jBox-pointer-left,.jBox-TooltipBorder .jBox-pointer-right{width:13px;height:34px}.jBox-TooltipBorder .jBox-pointer-left:after,.jBox-TooltipBorder .jBox-pointer-right:after{top:6px}.jBox-TooltipBorder.jBox-closeButton-box:before{width:28px;height:28px;background:#49d}.jBox-TooltipBorderThick .jBox-container{box-shadow:none;border-radius:8px;border:4px solid #ccc}.jBox-TooltipBorderThick .jBox-pointer:after{box-shadow:none;border:4px solid #ccc;width:24px;height:24px}.jBox-TooltipBorderThick .jBox-pointer-bottom,.jBox-TooltipBorderThick .jBox-pointer-top{width:38px;height:13px}.jBox-TooltipBorderThick .jBox-pointer-left,.jBox-TooltipBorderThick .jBox-pointer-right{width:13px;height:38px}.jBox-TooltipBorderThick.jBox-closeButton-box:before{width:32px;height:32px;background:#ccc}.jBox-TooltipDark .jBox-container{border-radius:4px;background:#000;color:#fff;box-shadow:0 0 6px rgba(0,0,0,.4)}.jBox-TooltipDark .jBox-pointer:after{background:#000}.jBox-TooltipDark .jBox-closeButton{background:#000}.jBox-TooltipDark.jBox-closeButton-box:before{box-shadow:0 0 6px rgba(0,0,0,.4)}.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton path{fill:#ddd}.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:hover path{fill:#fff}.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:active path{fill:#bbb}.jBox-TooltipError{pointer-events:none}.jBox-TooltipError .jBox-container{border-radius:2px;background:#d00;color:#fff;font-weight:700;font-size:13px}.jBox-TooltipError .jBox-content{padding:0 10px;line-height:28px}.jBox-TooltipError .jBox-pointer:after{background:#d00;width:20px;height:20px}.jBox-TooltipError .jBox-pointer-bottom,.jBox-TooltipError .jBox-pointer-top{width:22px;height:8px}.jBox-TooltipError .jBox-pointer-left,.jBox-TooltipError .jBox-pointer-right{width:8px;height:22px}.jBox-TooltipError .jBox-pointer-top:after{left:1px;top:6px}.jBox-TooltipError .jBox-pointer-right:after{top:1px;right:6px}.jBox-TooltipError .jBox-pointer-bottom:after{left:1px;bottom:6px}.jBox-TooltipError .jBox-pointer-left:after{top:1px;left:6px}.jBox-TooltipSmall{pointer-events:none}.jBox-TooltipSmall .jBox-container{border-radius:2px}.jBox-TooltipSmall .jBox-content{padding:0 10px;line-height:28px}.jBox-TooltipSmall .jBox-pointer:after{width:20px;height:20px}.jBox-TooltipSmall .jBox-pointer-bottom,.jBox-TooltipSmall .jBox-pointer-top{width:22px;height:8px}.jBox-TooltipSmall .jBox-pointer-left,.jBox-TooltipSmall .jBox-pointer-right{width:8px;height:22px}.jBox-TooltipSmall .jBox-pointer-top:after{left:1px;top:6px}.jBox-TooltipSmall .jBox-pointer-right:after{top:1px;right:6px}.jBox-TooltipSmall .jBox-pointer-bottom:after{left:1px;bottom:6px}.jBox-TooltipSmall .jBox-pointer-left:after{top:1px;left:6px}.jBox-TooltipSmallGray{pointer-events:none}.jBox-TooltipSmallGray .jBox-container{font-size:13px;line-height:24px;border-radius:12px;background-image:linear-gradient(to bottom,#fafafa,#f2f2f2)}.jBox-TooltipSmallGray .jBox-content{padding:0 10px}.jBox-TooltipSmallGray .jBox-pointer:after{width:20px;height:20px}.jBox-TooltipSmallGray .jBox-pointer-bottom,.jBox-TooltipSmallGray .jBox-pointer-top{width:22px;height:8px}.jBox-TooltipSmallGray .jBox-pointer-left,.jBox-TooltipSmallGray .jBox-pointer-right{width:8px;height:22px}.jBox-TooltipSmallGray .jBox-pointer-top:after{background:#fafafa;left:1px;top:6px}.jBox-TooltipSmallGray .jBox-pointer-right:after{top:1px;right:6px}.jBox-TooltipSmallGray .jBox-pointer-bottom:after{background:#f2f2f2;left:1px;bottom:6px}.jBox-TooltipSmallGray .jBox-pointer-left:after{top:1px;left:6px}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+function jBoxWrapper(b){function n(t,i){return this.options={id:null,width:"auto",height:"auto",minWidth:null,minHeight:null,maxWidth:null,maxHeight:null,responsiveWidth:!0,responsiveHeight:!0,responsiveMinWidth:100,responsiveMinHeight:100,attach:null,trigger:"click",preventDefault:!1,content:null,getContent:null,title:null,getTitle:null,footer:null,isolateScroll:!0,ajax:{url:null,data:"",reload:!1,getURL:"data-url",getData:"data-ajax",setContent:!0,loadingClass:!0,spinner:!0,spinnerDelay:300,spinnerReposition:!0},cancelAjaxOnClose:!0,target:null,position:{x:"center",y:"center"},outside:null,offset:0,attributes:{x:"left",y:"top"},fixed:!1,adjustPosition:!0,adjustTracker:!1,adjustDistance:5,reposition:!0,repositionOnOpen:!0,repositionOnContent:!0,holdPosition:!0,pointer:!1,pointTo:"target",fade:180,animation:null,theme:"Default",addClass:null,overlay:!1,overlayClass:null,zIndex:1e4,delayOpen:0,delayClose:0,closeOnEsc:!1,closeOnClick:!1,closeOnMouseleave:!1,closeButton:!1,appendTo:b("body"),createOnInit:!1,blockScroll:!1,blockScrollAdjust:!0,draggable:!1,dragOver:!0,autoClose:!1,delayOnHover:!1,showCountdown:!1,preloadAudio:!0,audio:null,volume:100,onInit:null,onAttach:null,onPosition:null,onCreated:null,onOpen:null,onClose:null,onCloseComplete:null,onDragStart:null,onDragEnd:null},this._pluginOptions={Tooltip:{getContent:"title",trigger:"mouseenter",position:{x:"center",y:"top"},outside:"y",pointer:!0},Mouse:{responsiveWidth:!1,responsiveHeight:!1,adjustPosition:"flip",target:"mouse",trigger:"mouseenter",position:{x:"right",y:"bottom"},outside:"xy",offset:5},Modal:{target:b(window),fixed:!0,blockScroll:!0,closeOnEsc:!0,closeOnClick:"overlay",closeButton:!0,overlay:!0,animation:"zoomIn"}},this.options=b.extend(!0,this.options,this._pluginOptions[t]||n._pluginOptions[t],i),"string"==b.type(t)&&(this.type=t),this.isTouchDevice=function(){var t=" -webkit- -moz- -o- -ms- ".split(" ");if("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)return!0;var i,t=["(",t.join("touch-enabled),("),"heartz",")"].join("");return i=t,window.matchMedia(i).matches}(),this.isTouchDevice&&"mouseenter"===this.options.trigger&&!1===this.options.closeOnClick&&(this.options.closeOnClick="body"),this._fireEvent=function(t,i){this.options["_"+t]&&this.options["_"+t].bind(this)(i),this.options[t]&&this.options[t].bind(this)(i)},null===this.options.id&&(this.options.id="jBox"+n._getUniqueID()),this.id=this.options.id,("center"==this.options.position.x&&"x"==this.options.outside||"center"==this.options.position.y&&"y"==this.options.outside)&&(this.options.outside=null),"target"!=this.options.pointTo||this.options.outside&&"xy"!=this.options.outside||(this.options.pointer=!1),"object"!=b.type(this.options.offset)?this.options.offset={x:this.options.offset,y:this.options.offset}:this.options.offset=b.extend({x:0,y:0},this.options.offset),"object"!=b.type(this.options.adjustDistance)?this.options.adjustDistance={top:this.options.adjustDistance,right:this.options.adjustDistance,bottom:this.options.adjustDistance,left:this.options.adjustDistance}:this.options.adjustDistance=b.extend({top:5,left:5,right:5,bottom:5},this.options.adjustDistance),this.outside=!(!this.options.outside||"xy"==this.options.outside)&&this.options.position[this.options.outside],this.align=this.outside||("center"!=this.options.position.y&&"number"!=b.type(this.options.position.y)?this.options.position.x:"center"!=this.options.position.x&&"number"!=b.type(this.options.position.x)?this.options.position.y:this.options.attributes.x),n.zIndexMax=Math.max(n.zIndexMax||0,"auto"===this.options.zIndex?1e4:this.options.zIndex),"auto"===this.options.zIndex&&(this.adjustZIndexOnOpen=!0,n.zIndexMax+=2,this.options.zIndex=n.zIndexMax,this.trueModal=this.options.overlay),this._getOpp=function(t){return{left:"right",right:"left",top:"bottom",bottom:"top",x:"y",y:"x"}[t]},this._getXY=function(t){return{left:"x",right:"x",top:"y",bottom:"y",center:"x"}[t]},this._getTL=function(t){return{left:"left",right:"left",top:"top",bottom:"top",center:"left",x:"left",y:"top"}[t]},this._getInt=function(t,i){return"auto"==t?"auto":t&&"string"==b.type(t)&&"%"==t.slice(-1)?b(window)["height"==i?"innerHeight":"innerWidth"]()*parseInt(t.replace("%",""))/100:t},this._createSVG=function(t,i){var o=document.createElementNS("http://www.w3.org/2000/svg",t);return b.each(i,function(t,i){o.setAttribute(i[0],i[1]||"")}),o},this._isolateScroll=function(e){e&&e.length&&e.on("DOMMouseScroll.jBoxIsolateScroll mousewheel.jBoxIsolateScroll",function(t){var i=t.wheelDelta||t.originalEvent&&t.originalEvent.wheelDelta||-t.detail,o=0<=this.scrollTop+e.outerHeight()-this.scrollHeight,s=this.scrollTop<=0;(i<0&&o||0<i&&s)&&t.preventDefault()})},this._setTitleWidth=function(){if(!this.titleContainer||"auto"==this.content[0].style.width&&!this.content[0].style.maxWidth)return null;var t;"none"==this.wrapper.css("display")?(this.wrapper.css("display","block"),t=this.content.outerWidth(),this.wrapper.css("display","none")):t=this.content.outerWidth(),this.titleContainer.css({maxWidth:Math.max(t,parseInt(this.content[0].style.maxWidth))||null})},this._draggable=function(){if(!this.options.draggable)return!1;var t="title"==this.options.draggable?this.titleContainer:this.options.draggable instanceof b?this.options.draggable:"string"==b.type(this.options.draggable)?b(this.options.draggable):this.wrapper;return!(!(t&&t instanceof b&&t.length)||t.data("jBox-draggable"))&&(t.addClass("jBox-draggable").data("jBox-draggable",!0).on("touchstart mousedown",function(t){var i,o,s,e;2==t.button||b(t.target).hasClass("jBox-noDrag")||b(t.target).parents(".jBox-noDrag").length||(this.draggingStartX=t.pageX,this.draggingStartY=t.pageY,this.options.dragOver&&!this.trueModal&&parseInt(this.wrapper.css("zIndex"),10)<=n.zIndexMaxDragover&&(n.zIndexMaxDragover+=1,this.wrapper.css("zIndex",n.zIndexMaxDragover)),i=this.wrapper.outerHeight(),o=this.wrapper.outerWidth(),s=this.wrapper.offset().top+i-t.pageY,e=this.wrapper.offset().left+o-t.pageX,b(document).on("touchmove.jBox-draggable-"+this.id+" mousemove.jBox-draggable-"+this.id,function(t){this.dragging||this.draggingStartX==t.pageX||this.draggingStartY==t.pageY||(this._fireEvent("onDragStart"),this.dragging=!0),this.wrapper.offset({top:t.pageY+s-i,left:t.pageX+e-o})}.bind(this)),t.preventDefault())}.bind(this)).on("touchend mouseup",function(){var t;b(document).off("touchmove.jBox-draggable-"+this.id+" mousemove.jBox-draggable-"+this.id),this.dragging&&this._fireEvent("onDragEnd"),this.dragging=!1,"Modal"!=this.type&&"Confirm"!=this.type||!this.options.holdPosition||(t={x:(t=b("#"+this.id).offset()).left-b(document).scrollLeft(),y:t.top-b(document).scrollTop()},this.position({position:t,offset:{x:0,y:0}}))}.bind(this)),this.trueModal||(n.zIndexMaxDragover=n.zIndexMaxDragover?Math.max(n.zIndexMaxDragover,this.options.zIndex):this.options.zIndex),this)},this._create=function(){var t;this.wrapper||(this.wrapper=b("<div/>",{id:this.id,class:"jBox-wrapper"+(this.type?" jBox-"+this.type:"")+(this.options.theme?" jBox-"+this.options.theme:"")+(this.options.addClass?" "+this.options.addClass:"")}).css({position:this.options.fixed?"fixed":"absolute",display:"none",opacity:0,zIndex:this.options.zIndex}).data("jBox",this),this.options.closeOnMouseleave&&this.wrapper.on("mouseleave",function(t){!this.source||t.relatedTarget!=this.source[0]&&-1===b.inArray(this.source[0],b(t.relatedTarget).parents("*"))&&this.close()}.bind(this)),"box"==this.options.closeOnClick&&this.wrapper.on("click tap",function(){this.close({ignoreDelay:!0})}.bind(this)),this.container=b('<div class="jBox-container"/>').appendTo(this.wrapper),this.content=b('<div class="jBox-content"/>').appendTo(this.container),this.options.footer&&(this.footer=b('<div class="jBox-footer"/>').append(this.options.footer).appendTo(this.container)),this.options.isolateScroll&&this._isolateScroll(this.content),this.options.closeButton&&((t=this._createSVG("svg",[["viewBox","0 0 24 24"]])).appendChild(this._createSVG("path",[["d","M22.2,4c0,0,0.5,0.6,0,1.1l-6.8,6.8l6.9,6.9c0.5,0.5,0,1.1,0,1.1L20,22.3c0,0-0.6,0.5-1.1,0L12,15.4l-6.9,6.9c-0.5,0.5-1.1,0-1.1,0L1.7,20c0,0-0.5-0.6,0-1.1L8.6,12L1.7,5.1C1.2,4.6,1.7,4,1.7,4L4,1.7c0,0,0.6-0.5,1.1,0L12,8.5l6.8-6.8c0.5-0.5,1.1,0,1.1,0L22.2,4z"]])),this.closeButton=b('<div class="jBox-closeButton jBox-noDrag"/>').on("click tap",function(t){this.close({ignoreDelay:!0})}.bind(this)).append(t),"box"!=this.options.closeButton&&(!0!==this.options.closeButton||this.options.overlay||this.options.title||this.options.getTitle)||(this.wrapper.addClass("jBox-closeButton-box"),this.closeButton.appendTo(this.container))),this.wrapper.appendTo(this.options.appendTo),this.wrapper.find(".jBox-closeButton").length&&b.each(["top","right","bottom","left"],function(t,i){this.wrapper.find(".jBox-closeButton").css(i)&&"auto"!=this.wrapper.find(".jBox-closeButton").css(i)&&(this.options.adjustDistance[i]=Math.max(this.options.adjustDistance[i],this.options.adjustDistance[i]+-1*((parseInt(this.wrapper.find(".jBox-closeButton").css(i))||0)+(parseInt(this.container.css("border-"+i+"-width"))||0))))}.bind(this)),this.options.pointer&&(this.pointer={position:"target"!=this.options.pointTo?this.options.pointTo:this._getOpp(this.outside),xy:"target"!=this.options.pointTo?this._getXY(this.options.pointTo):this._getXY(this.outside),align:"center",offset:0},this.pointer.element=b('<div class="jBox-pointer jBox-pointer-'+this.pointer.position+'"/>').appendTo(this.wrapper),this.pointer.dimensions={x:this.pointer.element.outerWidth(),y:this.pointer.element.outerHeight()},"string"==b.type(this.options.pointer)&&((t=this.options.pointer.split(":"))[0]&&(this.pointer.align=t[0]),t[1]&&(this.pointer.offset=parseInt(t[1]))),this.pointer.alignAttribute="x"==this.pointer.xy?"bottom"==this.pointer.align?"bottom":"top":"right"==this.pointer.align?"right":"left",this.wrapper.css("padding-"+this.pointer.position,this.pointer.dimensions[this.pointer.xy]),this.pointer.element.css(this.pointer.alignAttribute,"center"==this.pointer.align?"50%":0).css("margin-"+this.pointer.alignAttribute,this.pointer.offset),this.pointer.margin={},this.pointer.margin["margin-"+this.pointer.alignAttribute]=this.pointer.offset,"center"==this.pointer.align&&this.pointer.element.css("transform","translate("+("y"==this.pointer.xy?-.5*this.pointer.dimensions.x+"px":0)+", "+("x"==this.pointer.xy?-.5*this.pointer.dimensions.y+"px":0)+")"),this.pointer.element.css("x"==this.pointer.xy?"width":"height",parseInt(this.pointer.dimensions[this.pointer.xy])+parseInt(this.container.css("border-"+this.pointer.alignAttribute+"-width"))),this.wrapper.addClass("jBox-pointerPosition-"+this.pointer.position)),this.setContent(this.options.content,!0),this.setTitle(this.options.title,!0),this.options.draggable&&this._draggable(),this._fireEvent("onCreated"))},this.options.createOnInit&&this._create(),this.options.attach&&this.attach(),this._attachEvents=function(){this.options.delayOnHover&&b("#"+this.id).on("mouseenter",function(t){this.isHovered=!0}.bind(this)),this.options.delayOnHover&&b("#"+this.id).on("mouseleave",function(t){this.isHovered=!1}.bind(this)),(this.options.adjustPosition||this.options.reposition)&&!this.fixed&&this.outside&&(this.options.adjustTracker&&b(window).on("scroll.jBox-"+this.id,function(t){this.position()}.bind(this)),(this.options.adjustPosition||this.options.reposition)&&b(window).on("resize.jBox-"+this.id,function(t){this.position()}.bind(this))),"mouse"==this.options.target&&b("body").on("mousemove.jBox-"+this.id,function(t){this.position({mouseTarget:{top:t.pageY,left:t.pageX}})}.bind(this))},this._detachEvents=function(){this.options.closeOnEsc&&b(document).off("keyup.jBox-"+this.id),!0!==this.options.closeOnClick&&"body"!=this.options.closeOnClick||b(document).off("click.jBox-"+this.id+" tap.jBox-"+this.id),this.options.adjustTracker&&b(window).off("scroll.jBox-"+this.id),(this.options.adjustPosition||this.options.reposition)&&b(window).off("resize.jBox-"+this.id),"mouse"==this.options.target&&b("body").off("mousemove.jBox-"+this.id)},this._showOverlay=function(){this.overlay||(this.overlay=b('<div id="'+this.id+'-overlay"/>').addClass("jBox-overlay"+(this.type?" jBox-overlay-"+this.type:"")).css({display:"none",opacity:0,zIndex:this.options.zIndex-1}).appendTo(this.options.appendTo),this.options.overlayClass&&this.overlay.addClass(this.options.overlayClass),"overlay"!=this.options.closeButton&&!0!==this.options.closeButton||this.overlay.append(this.closeButton),"overlay"==this.options.closeOnClick&&this.overlay.on("click tap",function(){this.close({ignoreDelay:!0})}.bind(this)),b("#"+this.id+"-overlay .jBox-closeButton").length&&(this.options.adjustDistance.top=Math.max(b("#"+this.id+"-overlay .jBox-closeButton").outerHeight(),this.options.adjustDistance.top))),!0===this.adjustZIndexOnOpen&&this.overlay.css("zIndex",parseInt(this.wrapper.css("zIndex"),10)-1),"block"!=this.overlay.css("display")&&(this.options.fade?this.overlay.stop()&&this.overlay.animate({opacity:1},{queue:!1,duration:this.options.fade,start:function(){this.overlay.css({display:"block"})}.bind(this)}):this.overlay.css({display:"block",opacity:1}))},this._hideOverlay=function(){this.overlay&&(this.options.fade?this.overlay.stop()&&this.overlay.animate({opacity:0},{queue:!1,duration:this.options.fade,complete:function(){this.overlay.css({display:"none"})}.bind(this)}):this.overlay.css({display:"none",opacity:0}))},this._exposeDimensions=function(){this.wrapper.css({top:-1e4,left:-1e4,right:"auto",bottom:"auto"});var t={x:this.wrapper.outerWidth(),y:this.wrapper.outerHeight()};return this.wrapper.css({top:"auto",left:"auto"}),t},this._generateAnimationCSS=function(){if("object"!=b.type(this.options.animation)&&(this.options.animation={pulse:{open:"pulse",close:"zoomOut"},zoomIn:{open:"zoomIn",close:"zoomIn"},zoomOut:{open:"zoomOut",close:"zoomOut"},move:{open:"move",close:"move"},slide:{open:"slide",close:"slide"},flip:{open:"flip",close:"flip"},tada:{open:"tada",close:"zoomOut"}}[this.options.animation]),!this.options.animation)return null;this.options.animation.open&&(this.options.animation.open=this.options.animation.open.split(":")),this.options.animation.close&&(this.options.animation.close=this.options.animation.close.split(":")),this.options.animation.openDirection=this.options.animation.open[1]||null,this.options.animation.closeDirection=this.options.animation.close[1]||null,this.options.animation.open&&(this.options.animation.open=this.options.animation.open[0]),this.options.animation.close&&(this.options.animation.close=this.options.animation.close[0]),this.options.animation.open&&(this.options.animation.open+="Open"),this.options.animation.close&&(this.options.animation.close+="Close");var a={pulse:{duration:350,css:[["0%","scale(1)"],["50%","scale(1.1)"],["100%","scale(1)"]]},zoomInOpen:{duration:this.options.fade||180,css:[["0%","scale(0.9)"],["100%","scale(1)"]]},zoomInClose:{duration:this.options.fade||180,css:[["0%","scale(1)"],["100%","scale(0.9)"]]},zoomOutOpen:{duration:this.options.fade||180,css:[["0%","scale(1.1)"],["100%","scale(1)"]]},zoomOutClose:{duration:this.options.fade||180,css:[["0%","scale(1)"],["100%","scale(1.1)"]]},moveOpen:{duration:this.options.fade||180,positions:{top:{"0%":-12},right:{"0%":12},bottom:{"0%":12},left:{"0%":-12}},css:[["0%","translate%XY(%Vpx)"],["100%","translate%XY(0px)"]]},moveClose:{duration:this.options.fade||180,timing:"ease-in",positions:{top:{"100%":-12},right:{"100%":12},bottom:{"100%":12},left:{"100%":-12}},css:[["0%","translate%XY(0px)"],["100%","translate%XY(%Vpx)"]]},slideOpen:{duration:400,positions:{top:{"0%":-400},right:{"0%":400},bottom:{"0%":400},left:{"0%":-400}},css:[["0%","translate%XY(%Vpx)"],["100%","translate%XY(0px)"]]},slideClose:{duration:400,timing:"ease-in",positions:{top:{"100%":-400},right:{"100%":400},bottom:{"100%":400},left:{"100%":-400}},css:[["0%","translate%XY(0px)"],["100%","translate%XY(%Vpx)"]]},flipOpen:{duration:600,css:[["0%","perspective(400px) rotateX(90deg)"],["40%","perspective(400px) rotateX(-15deg)"],["70%","perspective(400px) rotateX(15deg)"],["100%","perspective(400px) rotateX(0deg)"]]},flipClose:{duration:this.options.fade||300,css:[["0%","perspective(400px) rotateX(0deg)"],["100%","perspective(400px) rotateX(90deg)"]]},tada:{duration:800,css:[["0%","scale(1)"],["10%, 20%","scale(0.9) rotate(-3deg)"],["30%, 50%, 70%, 90%","scale(1.1) rotate(3deg)"],["40%, 60%, 80%","scale(1.1) rotate(-3deg)"],["100%","scale(1) rotate(0)"]]}};b.each(["pulse","tada"],function(t,i){a[i+"Open"]=a[i+"Close"]=a[i]});var s=function(s,e){var n="@keyframes jBox-"+this.id+"-animation-"+this.options.animation[s]+"-"+s+(e?"-"+e:"")+" {";return b.each(a[this.options.animation[s]].css,function(t,i){var o=e?i[1].replace("%XY",this._getXY(e).toUpperCase()):i[1];a[this.options.animation[s]].positions&&(o=o.replace("%V",a[this.options.animation[s]].positions[e][i[0]])),n+=i[0]+" {transform:"+o+";}"}.bind(this)),n+="}",n+=".jBox-"+this.id+"-animation-"+this.options.animation[s]+"-"+s+(e?"-"+e:"")+" {",n+="animation-duration: "+a[this.options.animation[s]].duration+"ms;",n+="animation-name: jBox-"+this.id+"-animation-"+this.options.animation[s]+"-"+s+(e?"-"+e:"")+";",n+=a[this.options.animation[s]].timing?"animation-timing-function: "+a[this.options.animation[s]].timing+";":"",n+="}"}.bind(this);this._animationCSS="",b.each(["open","close"],function(t,o){if(!this.options.animation[o]||!a[this.options.animation[o]]||"close"==o&&!this.options.fade)return"";a[this.options.animation[o]].positions?b.each(["top","right","bottom","left"],function(t,i){this._animationCSS+=s(o,i)}.bind(this)):this._animationCSS+=s(o)}.bind(this))},this.options.animation&&this._generateAnimationCSS(),this._blockBodyClick=function(){this.blockBodyClick=!0,setTimeout(function(){this.blockBodyClick=!1}.bind(this),10)},this._animate=function(t){if(t=t||(this.isOpen?"open":"close"),!this.options.fade&&"close"==t)return null;var i=this.options.animation[t+"Direction"]||("center"!=this.align?this.align:this.options.attributes.x);this.flipped&&this._getXY(i)==this._getXY(this.align)&&(i=this._getOpp(i));var o="jBox-"+this.id+"-animation-"+this.options.animation[t]+"-"+t+" jBox-"+this.id+"-animation-"+this.options.animation[t]+"-"+t+"-"+i;this.wrapper.addClass(o);i=1e3*parseFloat(this.wrapper.css("animation-duration"));"close"==t&&(i=Math.min(i,this.options.fade)),setTimeout(function(){this.wrapper.removeClass(o)}.bind(this),i)},this._abortAnimation=function(){var t=this.wrapper.attr("class").split(" ").filter(function(t){return 0!==t.lastIndexOf("jBox-"+this.id+"-animation",0)}.bind(this));this.wrapper.attr("class",t.join(" "))},(this.options.responsiveWidth||this.options.responsiveHeight)&&b(window).on("resize.responsivejBox-"+this.id,function(t){this.isOpen&&this.position()}.bind(this)),"string"===b.type(this.options.preloadAudio)&&(this.options.preloadAudio=[this.options.preloadAudio]),"string"===b.type(this.options.audio)&&(this.options.audio={open:this.options.audio}),"number"===b.type(this.options.volume)&&(this.options.volume={open:this.options.volume,close:this.options.volume}),!0===this.options.preloadAudio&&this.options.audio&&(this.options.preloadAudio=[],b.each(this.options.audio,function(t,i){this.options.preloadAudio.push(i+".mp3"),this.options.preloadAudio.push(i+".ogg")}.bind(this))),this.options.preloadAudio.length&&b.each(this.options.preloadAudio,function(t,i){var o=new Audio;o.src=i,o.preload="auto"}),this._fireEvent("onInit"),this}var t,i;return n.prototype.attach=function(t,s){return t=t||this.options.attach,"string"==b.type(t)&&(t=b(t)),s=s||this.options.trigger,t&&t.length&&b.each(t,function(t,o){(o=b(o)).data("jBox-attached-"+this.id)||("title"==this.options.getContent&&null!=o.attr("title")&&o.data("jBox-getContent",o.attr("title")).removeAttr("title"),this.attachedElements||(this.attachedElements=[]),this.attachedElements.push(o[0]),o.on(s+".jBox-attach-"+this.id,function(t){var i;this.timer&&clearTimeout(this.timer),"mouseenter"==s&&this.isOpen&&this.source[0]==o[0]||(this.isOpen&&this.source&&this.source[0]!=o[0]&&(i=!0),this.source=o,this.options.target||(this.target=o),"click"==s&&this.options.preventDefault&&t.preventDefault(),this["click"!=s||i?"open":"toggle"]())}.bind(this)),"mouseenter"==this.options.trigger&&o.on("mouseleave",function(t){if(!this.wrapper)return null;this.options.closeOnMouseleave&&(t.relatedTarget==this.wrapper[0]||b(t.relatedTarget).parents("#"+this.id).length)||this.close()}.bind(this)),o.data("jBox-attached-"+this.id,s),this._fireEvent("onAttach",o))}.bind(this)),this},n.prototype.detach=function(t){return(t=t||(this.attachedElements||[]))&&t.length&&b.each(t,function(t,i){(i=b(i)).data("jBox-attached-"+this.id)&&(i.off(i.data("jBox-attached-"+this.id)+".jBox-attach-"+this.id),i.data("jBox-attached-"+this.id,null)),this.attachedElements=b.grep(this.attachedElements,function(t){return t!=i[0]})}.bind(this)),this},n.prototype.setTitle=function(t,i){if(null==t||null==t)return this;this.wrapper||this._create();var o=this.wrapper.outerHeight(),s=this.wrapper.outerWidth();return this.title||(this.titleContainer=b('<div class="jBox-title"/>'),this.title=b("<div/>").appendTo(this.titleContainer),"title"!=this.options.closeButton&&(!0!==this.options.closeButton||this.options.overlay)||(this.wrapper.addClass("jBox-closeButton-title"),this.closeButton.appendTo(this.titleContainer)),this.titleContainer.insertBefore(this.content),this._setTitleWidth()),this.wrapper[t?"addClass":"removeClass"]("jBox-hasTitle"),this.title.html(t),s!=this.wrapper.outerWidth()&&this._setTitleWidth(),this.options.draggable&&this._draggable(),i||!this.options.repositionOnContent||o==this.wrapper.outerHeight()&&s==this.wrapper.outerWidth()||this.position(),this},n.prototype.setContent=function(t,i){if(null==t||null==t)return this;this.wrapper||this._create();var o=this.wrapper.outerHeight(),s=this.wrapper.outerWidth();switch(this.content.children("[data-jbox-content-appended]").appendTo("body").css({display:"none"}),b.type(t)){case"string":this.content.html(t);break;case"object":t&&(t instanceof b||t.constructor.prototype.jquery)?(this.content.html(""),t.attr("data-jbox-content-appended",1).appendTo(this.content).css({display:"block"})):this.content.html(JSON.stringify(t))}return s!=this.wrapper.outerWidth()&&this._setTitleWidth(),this.options.draggable&&this._draggable(),i||!this.options.repositionOnContent||o==this.wrapper.outerHeight()&&s==this.wrapper.outerWidth()||this.position(),this},n.prototype.setDimensions=function(t,i,o){this.wrapper||this._create(),null==i&&(i="auto"),this.content.css(t,this._getInt(i)),"width"==t&&this._setTitleWidth(),this.options[t]=i,null!=o&&!o||this.position()},n.prototype.setWidth=function(t,i){this.setDimensions("width",t,i)},n.prototype.setHeight=function(t,i){this.setDimensions("height",t,i)},n.prototype.position=function(o){if(o=o||{},o=b.extend(!0,this.options,o),this.target=o.target||this.target||b(window),this.target instanceof b||"mouse"==this.target||(this.target=b(this.target)),!this.target.length)return this;this.content.css({width:this._getInt(o.width,"width"),height:this._getInt(o.height,"height"),minWidth:this._getInt(o.minWidth,"width"),minHeight:this._getInt(o.minHeight,"height"),maxWidth:this._getInt(o.maxWidth,"width"),maxHeight:this._getInt(o.maxHeight,"height")}),this._setTitleWidth();var s=this._exposeDimensions();"mouse"==this.target||this.target.data("jBox-"+this.id+"-fixed")||this.target.data("jBox-"+this.id+"-fixed",this.target[0]!=b(window)[0]&&("fixed"==this.target.css("position")||0<this.target.parents().filter(function(){return"fixed"==b(this).css("position")}).length)?"fixed":"static");var t={x:b(window).outerWidth(),y:b(window).outerHeight(),top:o.fixed&&this.target.data("jBox-"+this.id+"-fixed")?0:b(window).scrollTop(),left:o.fixed&&this.target.data("jBox-"+this.id+"-fixed")?0:b(window).scrollLeft()};t.bottom=t.top+t.y,t.right=t.left+t.x;try{var i=this.target.offset()}catch(t){i={top:0,left:0}}"mouse"!=this.target&&"fixed"==this.target.data("jBox-"+this.id+"-fixed")&&o.fixed&&(i.top=i.top-b(window).scrollTop(),i.left=i.left-b(window).scrollLeft());var e={x:"mouse"==this.target?12:this.target.outerWidth(),y:"mouse"==this.target?20:this.target.outerHeight(),top:"mouse"==this.target&&o.mouseTarget?o.mouseTarget.top:i?i.top:0,left:"mouse"==this.target&&o.mouseTarget?o.mouseTarget.left:i?i.left:0},n=o.outside&&!("center"==o.position.x&&"center"==o.position.y),a={x:t.x-o.adjustDistance.left-o.adjustDistance.right,y:t.y-o.adjustDistance.top-o.adjustDistance.bottom,left:n?e.left-b(window).scrollLeft()-o.adjustDistance.left:0,right:n?t.x-e.left+b(window).scrollLeft()-e.x-o.adjustDistance.right:0,top:n?e.top-b(window).scrollTop()-this.options.adjustDistance.top:0,bottom:n?t.y-e.top+b(window).scrollTop()-e.y-o.adjustDistance.bottom:0},h={x:"x"!=o.outside&&"xy"!=o.outside||"number"==b.type(o.position.x)?null:o.position.x,y:"y"!=o.outside&&"xy"!=o.outside||"number"==b.type(o.position.y)?null:o.position.y},r={x:!1,y:!1};h.x&&s.x>a[h.x]&&a[this._getOpp(h.x)]>a[h.x]&&(h.x=this._getOpp(h.x))&&(r.x=!0),h.y&&s.y>a[h.y]&&a[this._getOpp(h.y)]>a[h.y]&&(h.y=this._getOpp(h.y))&&(r.y=!0),(o.responsiveWidth||o.responsiveHeight)&&(f=function(){var t;o.responsiveWidth&&s.x>a[h.x||"x"]&&(t=a[h.x||"x"]-(this.pointer&&n&&"x"==o.outside?this.pointer.dimensions.x:0)-parseInt(this.container.css("border-left-width"))-parseInt(this.container.css("border-right-width")),this.content.css({width:t>this.options.responsiveMinWidth?t:null,minWidth:t<parseInt(this.content.css("minWidth"))?0:null}),this._setTitleWidth()),s=this._exposeDimensions()}.bind(this),o.responsiveWidth&&f(),o.responsiveWidth&&!r.y&&h.y&&s.y>a[h.y]&&a[this._getOpp(h.y)]>a[h.y]&&(h.y=this._getOpp(h.y))&&(r.y=!0),x=function(){var t;o.responsiveHeight&&s.y>a[h.y||"y"]&&(t=function(){return this.titleContainer||this.footer?("none"==this.wrapper.css("display")?(this.wrapper.css("display","block"),t=(this.titleContainer?this.titleContainer.outerHeight():0)+(this.footer?this.footer.outerHeight():0),this.wrapper.css("display","none")):t=(this.titleContainer?this.titleContainer.outerHeight():0)+(this.footer?this.footer.outerHeight():0),t||0):0;var t}.bind(this),t=a[h.y||"y"]-(this.pointer&&n&&"y"==o.outside?this.pointer.dimensions.y:0)-t()-parseInt(this.container.css("border-top-width"))-parseInt(this.container.css("border-bottom-width")),this.content.css({height:t>this.options.responsiveMinHeight?t:null}),this._setTitleWidth()),s=this._exposeDimensions()}.bind(this),o.responsiveHeight&&x(),o.responsiveHeight&&!r.x&&h.x&&s.x>a[h.x]&&a[this._getOpp(h.x)]>a[h.x]&&(h.x=this._getOpp(h.x))&&(r.x=!0),o.adjustPosition&&"move"!=o.adjustPosition&&(r.x&&f(),r.y&&x()));var p={},l=function(t){if("number"!=b.type(o.position[t])){var i=o.attributes[t]="x"==t?"left":"top";if(p[i]=e[i],"center"==o.position[t])return p[i]+=Math.ceil((e[t]-s[t])/2),void("mouse"!=this.target&&this.target[0]&&this.target[0]==b(window)[0]&&(p[i]+=.5*(o.adjustDistance[i]-o.adjustDistance[this._getOpp(i)])));i!=o.position[t]&&(p[i]+=e[t]-s[t]),o.outside!=t&&"xy"!=o.outside||(p[i]+=s[t]*(i!=o.position[t]?1:-1))}else p[o.attributes[t]]=o.position[t]}.bind(this);if(l("x"),l("y"),this.pointer&&"target"==o.pointTo&&"number"!=b.type(o.position.x)&&"number"!=b.type(o.position.y)&&(y=0,"center"===this.pointer.align?"center"!=o.position[this._getOpp(o.outside)]&&(y+=s[this._getOpp(o.outside)]/2):"center"===o.position[this._getOpp(o.outside)]?y+=(s[this._getOpp(o.outside)]/2-this.pointer.dimensions[this._getOpp(o.outside)]/2)*(this.pointer.align==this._getTL(this.pointer.align)?1:-1):y+=this.pointer.align!=o.position[this._getOpp(o.outside)]?this.dimensions[this._getOpp(o.outside)]*(-1!==b.inArray(this.pointer.align,["top","left"])?1:-1)+this.pointer.dimensions[this._getOpp(o.outside)]/2*(-1!==b.inArray(this.pointer.align,["top","left"])?-1:1):this.pointer.dimensions[this._getOpp(o.outside)]/2*(-1!==b.inArray(this.pointer.align,["top","left"])?1:-1),y*=o.position[this._getOpp(o.outside)]==this.pointer.alignAttribute?-1:1,y+=this.pointer.offset*(this.pointer.align==this._getOpp(this._getTL(this.pointer.align))?1:-1),p[this._getTL(this._getOpp(this.pointer.xy))]+=y),p[o.attributes.x]+=o.offset.x,p[o.attributes.y]+=o.offset.y,this.wrapper.css(p),o.adjustPosition){this.positionAdjusted&&(this.pointer&&this.wrapper.css("padding",0).css("padding-"+this._getOpp(this.outside),this.pointer.dimensions[this._getXY(this.outside)]).removeClass("jBox-pointerPosition-"+this._getOpp(this.pointer.position)).addClass("jBox-pointerPosition-"+this.pointer.position),this.pointer&&this.pointer.element.attr("class","jBox-pointer jBox-pointer-"+this._getOpp(this.outside)).css(this.pointer.margin),this.positionAdjusted=!1,this.flipped=!1);var d=t.top>p.top-(o.adjustDistance.top||0),c=t.right<p.left+s.x+(o.adjustDistance.right||0),u=t.bottom<p.top+s.y+(o.adjustDistance.bottom||0),g=t.left>p.left-(o.adjustDistance.left||0),m=g?"left":c?"right":null,f=d?"top":u?"bottom":null;if(m||f){if(("Modal"==this.type||"Confirm"==this.type)&&"number"==b.type(this.options.position.x)&&"number"==b.type(this.options.position.y)){var x=0,y=0;return this.options.holdPosition&&(g?x=t.left-(p.left-(o.adjustDistance.left||0)):c&&(x=t.right-(p.left+s.x+(o.adjustDistance.right||0))),d?y=t.top-(p.top-(o.adjustDistance.top||0)):u&&(y=t.bottom-(p.top+s.y+(o.adjustDistance.bottom||0))),this.options.position.x=Math.max(t.top,this.options.position.x+x),this.options.position.y=Math.max(t.left,this.options.position.y+y),l("x"),l("y"),this.wrapper.css(p)),this._fireEvent("onPosition"),this}!0!==o.adjustPosition&&"flip"!==o.adjustPosition||(j=function(t){this.wrapper.css(this._getTL(t),p[this._getTL(t)]+(s[this._getXY(t)]+o.offset[this._getXY(t)]*("top"==t||"left"==t?-2:2)+e[this._getXY(t)])*("top"==t||"left"==t?1:-1)),this.pointer&&this.wrapper.removeClass("jBox-pointerPosition-"+this.pointer.position).addClass("jBox-pointerPosition-"+this._getOpp(this.pointer.position)).css("padding",0).css("padding-"+t,this.pointer.dimensions[this._getXY(t)]),this.pointer&&this.pointer.element.attr("class","jBox-pointer jBox-pointer-"+t),this.positionAdjusted=!0,this.flipped=!0}.bind(this),r.x&&j(this.options.position.x),r.y&&j(this.options.position.y));var j="x"==this._getXY(this.outside)?f:m;this.pointer&&"target"==o.pointTo&&"flip"!=o.adjustPosition&&this._getXY(j)==this._getOpp(this._getXY(this.outside))&&(f="center"==this.pointer.align?s[this._getXY(j)]/2-this.pointer.dimensions[this._getOpp(this.pointer.xy)]/2-parseInt(this.pointer.element.css("margin-"+this.pointer.alignAttribute))*(j!=this._getTL(j)?-1:1):j==this.pointer.alignAttribute?parseInt(this.pointer.element.css("margin-"+this.pointer.alignAttribute)):s[this._getXY(j)]-parseInt(this.pointer.element.css("margin-"+this.pointer.alignAttribute))-this.pointer.dimensions[this._getXY(j)],m=j==this._getTL(j)?t[this._getTL(j)]-p[this._getTL(j)]+o.adjustDistance[j]:-1*(t[this._getOpp(this._getTL(j))]-p[this._getTL(j)]-o.adjustDistance[j]-s[this._getXY(j)]),j==this._getOpp(this._getTL(j))&&p[this._getTL(j)]-m<t[this._getTL(j)]+o.adjustDistance[this._getTL(j)]&&(m-=t[this._getTL(j)]+o.adjustDistance[this._getTL(j)]-(p[this._getTL(j)]-m)),(m=Math.min(m,f))<=f&&0<m&&(this.pointer.element.css("margin-"+this.pointer.alignAttribute,parseInt(this.pointer.element.css("margin-"+this.pointer.alignAttribute))-m*(j!=this.pointer.alignAttribute?-1:1)),this.wrapper.css(this._getTL(j),p[this._getTL(j)]+m*(j!=this._getTL(j)?-1:1)),this.positionAdjusted=!0))}}return this._fireEvent("onPosition"),this},(n.prototype.unscroll=function(t){if(this.set=function(t,i){window.unscrollStore||(window.unscrollStore={}),window.unscrollStore[t]=i},this.get=function(t){return window.unscrollStore?window.unscrollStore[t]:null},this.getScrollbarWidth=function(){if(this.get("scrollbarWidth"))return this.get("scrollbarWidth")+"px";var t=document.createElement("div");t.style.width="100px",t.style.height="100px",t.style.overflow="scroll",t.style.position="absolute",t.style.top="-10000",document.body.appendChild(t);var i=t.offsetWidth-t.clientWidth;return document.body.removeChild(t),this.set("scrollbarWidth",i),i+"px"},this.getElementsToAdjust=function(o){(o="string"==typeof(o=o||[])?[[o,"padding-right"]]:o).forEach(function(t,i){"string"==typeof t&&(o[i]=[t,"padding-right"])});for(var t=!1,i=0;i<o.length;i++)-1!==o[i][0].indexOf("body")&&(t=!0);return!1===t&&o.push(["body","padding-right"]),o},this.pageHasScrollbar=function(){return this.getScrollbarWidth()&&document.body.offsetHeight>window.innerHeight},this.pageHasScrollbar()){t=this.getElementsToAdjust(t);for(var i=0;i<t.length;i++)for(var o=document.querySelectorAll(t[i][0]),s=0;s<o.length;s++){if(o[s].getAttribute("data-unscroll"))return;var e=t[i][1],n=window.getComputedStyle(o[s]).getPropertyValue(e);o[s].setAttribute("data-unscroll",e),n=n||"0px";var a="padding-right"==e||"right"==e?"+":"-";o[s].style[e]="calc("+n+" "+a+" "+this.getScrollbarWidth()+")"}}var h,r;document.getElementById("unscroll-class-name")||(h=document.head||document.getElementsByTagName("head")[0],(r=document.createElement("style")).type="text/css",r.setAttribute("id","unscroll-class-name"),r.appendChild(document.createTextNode(".unscrollable { overflow: hidden !important; }")),h.appendChild(r)),document.body.classList.add("unscrollable")}).reset=function(){for(var t=document.querySelectorAll("[data-unscroll]"),i=0;i<t.length;i++){var o=t[i].getAttribute("data-unscroll");t[i].style[o]=null,t[i].removeAttribute("data-unscroll")}document.body.classList.remove("unscrollable")},n.prototype.open=function(t){if(t=t||{},this.isDestroyed)return this;if(this.wrapper||this._create(),this._styles||(this._styles=b("<style/>").append(this._animationCSS).appendTo(b("head"))),this.timer&&clearTimeout(this.timer),this._blockBodyClick(),this.isDisabled)return this;this.options.closeOnEsc&&b(document).on("keyup.jBox-"+this.id,function(t){27==t.keyCode&&this.close({ignoreDelay:!0})}.bind(this)),!0!==this.options.closeOnClick&&"body"!==this.options.closeOnClick||(b("body").on("click.jBox-"+this.id+" tap.jBox-"+this.id,function(t){this.blockBodyClick||"body"==this.options.closeOnClick&&(t.target==this.wrapper[0]||this.wrapper.has(t.target).length)||this.close({ignoreDelay:!0})}.bind(this)),this.isTouchDevice&&b("body > *").on("click.jBox-"+this.id+" tap.jBox-"+this.id,function(){return!0}));var i=function(){!0===this.adjustZIndexOnOpen&&(n.zIndexMax=Math.max(parseInt(this.wrapper.css("zIndex"),10),this.options.zIndex,n.zIndexMax||0,n.zIndexMaxDragover||0)+2,this.wrapper.css("zIndex",n.zIndexMax),this.options.zIndex=n.zIndexMax),this.source&&this.options.getTitle&&this.source.attr(this.options.getTitle)&&this.setTitle(this.source.attr(this.options.getTitle),!0),this.source&&this.options.getContent&&(this.source.data("jBox-getContent")?this.setContent(this.source.data("jBox-getContent"),!0):this.source.attr(this.options.getContent)?this.setContent(this.source.attr(this.options.getContent),!0):"html"==this.options.getContent&&this.setContent(this.source.html(),!0)),this._fireEvent("onOpen"),(this.options.ajax&&(this.options.ajax.url||this.source&&this.source.attr(this.options.ajax.getURL))&&(!this.ajaxLoaded||this.options.ajax.reload)||t.ajax&&(t.ajax.url||t.ajax.data))&&("strict"==this.options.ajax.reload||!this.source||!this.source.data("jBox-ajax-data")||t.ajax&&(t.ajax.url||t.ajax.data)?this.ajax(t.ajax||null,!0):this.setContent(this.source.data("jBox-ajax-data"))),this.positionedOnOpen&&!this.options.repositionOnOpen||!this.position(t)||(this.positionedOnOpen=!0),this.isClosing&&this._abortAnimation(),this.isOpen||(this.isOpen=!0,this.options.autoClose&&(this.options.delayClose=this.options.autoClose)&&this.close(),this._attachEvents(),this.options.blockScroll&&(this.options.blockScrollAdjust?n.blockScrollScopes?n.blockScrollScopes++:(n.blockScrollScopes=1,this.unscroll(Array.isArray(this.options.blockScrollAdjust)||"string"==typeof this.options.blockScrollAdjust?this.options.blockScrollAdjust:null)):b("body").addClass("jBox-blockScroll-"+this.id)),this.options.overlay&&(this._showOverlay(),this.position()),this.options.animation&&!this.isClosing&&this._animate("open"),this.options.audio&&this.options.audio.open&&this.audio(this.options.audio.open,this.options.volume.open),this.options.fade?this.wrapper.stop().animate({opacity:1},{queue:!1,duration:this.options.fade,start:function(){this.isOpening=!0,this.wrapper.css({display:"block"})}.bind(this),always:function(){this.isOpening=!1,setTimeout(function(){this.positionOnFadeComplete&&this.position()&&(this.positionOnFadeComplete=!1)}.bind(this),10)}.bind(this)}):(this.wrapper.css({display:"block",opacity:1}),this.positionOnFadeComplete&&this.position()&&(this.positionOnFadeComplete=!1)))}.bind(this);return!this.options.delayOpen||this.isOpen||this.isClosing||t.ignoreDelay?i():this.timer=setTimeout(i,this.options.delayOpen),this},n.prototype.close=function(t){if(t=t||{},b("body").off("click.jBox-"+this.id+" tap.jBox-"+this.id),this.isTouchDevice&&b("body > *").off("click.jBox-"+this.id+" tap.jBox-"+this.id),this.isDestroyed||this.isClosing)return this;if(this.timer&&clearTimeout(this.timer),this._blockBodyClick(),this.isDisabled)return this;var i,o,s,e=function(){var t;this._fireEvent("onClose"),this.options.cancelAjaxOnClose&&this.cancelAjax(),this.isOpen&&(this.isOpen=!1,this._detachEvents(),this.options.blockScroll&&(this.options.blockScrollAdjust?(n.blockScrollScopes=n.blockScrollScopes?--n.blockScrollScopes:0)||this.unscroll.reset():b("body").removeClass("jBox-blockScroll-"+this.id)),this.options.overlay&&this._hideOverlay(),this.options.animation&&!this.isOpening&&this._animate("close"),this.options.audio&&this.options.audio.close&&this.audio(this.options.audio.close,this.options.volume.close),(t=this.isTouchDevice&&"mouse"==this.options.target?0:this.options.fade)?this.wrapper.stop().animate({opacity:0},{queue:!1,duration:t,start:function(){this.isClosing=!0}.bind(this),complete:function(){this.wrapper.css({display:"none"}),this._fireEvent("onCloseComplete")}.bind(this),always:function(){this.isClosing=!1}.bind(this)}):(this.wrapper.css({display:"none",opacity:0}),this._fireEvent("onCloseComplete")))}.bind(this);return t.ignoreDelay||this.isTouchDevice&&"mouse"==this.options.target?e():(this.options.delayOnHover||this.options.showCountdown)&&10<this.options.delayClose?(o=(i=this).options.delayClose,s=Date.now(),this.options.showCountdown&&!this.inner&&(t=b('<div class="jBox-countdown" />'),this.inner=b('<div class="jBox-countdown-inner" />'),t.prepend(this.inner),b("#"+this.id).append(t)),this.countdown=function(){var t=Date.now();i.isHovered||(o-=t-s),s=t,0<o?(i.options.showCountdown&&i.inner.css("width",100*o/i.options.delayClose+"%"),window.requestAnimationFrame(i.countdown)):e()},window.requestAnimationFrame(this.countdown)):this.timer=setTimeout(e,Math.max(this.options.delayClose,10)),this},n.prototype.toggle=function(t){return this[this.isOpen?"close":"open"](t),this},n.prototype.disable=function(){return this.isDisabled=!0,this},n.prototype.enable=function(){return this.isDisabled=!1,this},n.prototype.hide=function(){return this.disable(),this.wrapper&&(this.cacheWrapperDisplay=this.wrapper.css("display"),this.wrapper.css({display:"none"})),this.overlay&&(this.cacheOverlayDisplay=this.overlay.css("display"),this.overlay.css({display:"none"})),this},n.prototype.show=function(){return this.enable(),this.wrapper&&this.cacheWrapperDisplay&&(this.wrapper.css({display:this.cacheWrapperDisplay}),this.cacheWrapperDisplay=null),this.overlay&&this.cacheOverlayDisplay&&(this.overlay.css({display:this.cacheOverlayDisplay}),this.cacheOverlayDisplay=null),this},n.prototype.ajax=function(o,i){o=o||{},b.each([["getData","data"],["getURL","url"]],function(t,i){this.options.ajax[i[0]]&&!o[i[1]]&&this.source&&null!=this.source.attr(this.options.ajax[i[0]])&&(o[i[1]]=this.source.attr(this.options.ajax[i[0]])||"")}.bind(this));var t=b.extend(!0,{},this.options.ajax);this.cancelAjax();var s=o.beforeSend||t.beforeSend||function(){},e=o.complete||t.complete||function(){},n=o.success||t.success||function(){},a=o.error||t.error||function(){},h=b.extend(!0,t,o);return h.beforeSend=function(t){h.loadingClass&&this.wrapper.addClass(!0===h.loadingClass?"jBox-loading":h.loadingClass),h.spinner&&(this.spinnerDelay=setTimeout(function(){this.wrapper.addClass("jBox-loading-spinner"),h.spinnerReposition&&(i?this.positionOnFadeComplete=!0:this.position()),this.spinner=b(!0!==h.spinner?h.spinner:'<div class="jBox-spinner"></div>').appendTo(this.container),this.titleContainer&&"absolute"==this.spinner.css("position")&&this.spinner.css({transform:"translateY("+.5*this.titleContainer.outerHeight()+"px)"})}.bind(this),""!=this.content.html()&&h.spinnerDelay||0)),s.bind(this)(t)}.bind(this),h.complete=function(t){this.spinnerDelay&&clearTimeout(this.spinnerDelay),this.wrapper.removeClass("jBox-loading jBox-loading-spinner jBox-loading-spinner-delay"),this.spinner&&this.spinner.length&&this.spinner.remove()&&h.spinnerReposition&&(i?this.positionOnFadeComplete=!0:this.position()),this.ajaxLoaded=!0,e.bind(this)(t)}.bind(this),h.success=function(t){h.setContent&&this.setContent(t,!0)&&(i?this.positionOnFadeComplete=!0:this.position()),h.setContent&&this.source&&this.source.data("jBox-ajax-data",t),n.bind(this)(t)}.bind(this),h.error=function(t){a.bind(this)(t)}.bind(this),this.ajaxRequest=b.ajax(h),this},n.prototype.cancelAjax=function(){this.ajaxRequest&&(this.ajaxRequest.abort(),this.ajaxLoaded=!1)},n.prototype.audio=function(t,i){if(!t)return this;var o;(n._audio=!n._audio?{}:n._audio)[t]||(o=b("<audio/>"),b("<source/>",{src:t+".mp3"}).appendTo(o),b("<source/>",{src:t+".ogg"}).appendTo(o),n._audio[t]=o[0]),n._audio[t].volume=Math.min((null!=i?i:100)/100,1);try{n._audio[t].pause(),n._audio[t].currentTime=0}catch(t){}return n._audio[t].play(),this},n._animationSpeeds={tada:1e3,tadaSmall:1e3,flash:500,shake:400,pulseUp:250,pulseDown:250,popIn:250,popOut:250,fadeIn:200,fadeOut:200,slideUp:400,slideRight:400,slideLeft:400,slideDown:400},n.prototype.animate=function(t,i){i=i||{},this.animationTimeout||(this.animationTimeout={}),i.element||(i.element=this.wrapper),i.element.data("jBox-animating-id")||i.element.data("jBox-animating-id",n._getUniqueElementID()),i.element.data("jBox-animating")&&(i.element.removeClass(i.element.data("jBox-animating")).data("jBox-animating",null),this.animationTimeout[i.element.data("jBox-animating-id")]&&clearTimeout(this.animationTimeout[i.element.data("jBox-animating-id")])),i.element.addClass("jBox-animated-"+t).data("jBox-animating","jBox-animated-"+t),this.animationTimeout[i.element.data("jBox-animating-id")]=setTimeout(function(){i.element.removeClass(i.element.data("jBox-animating")).data("jBox-animating",null),i.complete&&i.complete()},n._animationSpeeds[t])},n.prototype.swipeDetector=function(i,o){var s=0,e=0,n=0,a=0,h=0,t={swipeThreshold:70,useOnlyTouch:!1};function r(t){o.useOnlyTouch&&!t.originalEvent.touches||(t.originalEvent.touches&&(t=t.originalEvent.touches[0]),0===s&&(s=1,e=t.clientX,n=t.clientY))}function p(t){2===s&&(s=0,Math.abs(a)>Math.abs(h)&&Math.abs(a)>o.swipeThreshold?a<0?i.trigger($.Event("swipeLeft.sd")):i.trigger($.Event("swipeRight.sd")):Math.abs(h)>o.swipeThreshold&&(h<0?i.trigger($.Event("swipeUp.sd")):i.trigger($.Event("swipeDown.sd"))))}function l(t){var i;1===s&&(i=(t=t.originalEvent.touches?t.originalEvent.touches[0]:t).clientX-e,t=t.clientY-n,(Math.abs(i)>o.swipeThreshold||Math.abs(t)>o.swipeThreshold)&&(s=2,a=i,h=t))}return o=b.extend(t,o),i.on("mousedown touchstart",r),$("html").on("mouseup touchend",p),$("html").on("mousemove touchmove",l),i},n.prototype.destroy=function(){return this.detach(),this.isOpen&&this.close({ignoreDelay:!0}),this.wrapper&&this.wrapper.remove(),this.overlay&&this.overlay.remove(),this._styles&&this._styles.remove(),this.isDestroyed=!0,this},n._getUniqueID=(t=1,function(){return t++}),n._getUniqueElementID=(i=1,function(){return i++}),n._pluginOptions={},n.plugin=function(t,i){n._pluginOptions[t]=i},b.fn.jBox=function(t,i){return i=i||{},new n(t=t||{},b.extend(i,{attach:this}))},n}function jBoxConfirmWrapper(jBox,jQuery){new jBox.plugin("Confirm",{confirmButton:"Submit",cancelButton:"Cancel",confirm:null,cancel:null,closeOnConfirm:!0,target:window,fixed:!0,attach:"[data-confirm]",getContent:"data-confirm",content:"Do you really want to do this?",minWidth:360,maxWidth:500,blockScroll:!0,closeOnEsc:!0,closeOnClick:!1,closeButton:!1,overlay:!0,animation:"zoomIn",preventDefault:!0,_onAttach:function(t){var i;this.options.confirm||(i=t.attr("onclick")?t.attr("onclick"):t.attr("href")?t.attr("target")?'window.open("'+t.attr("href")+'", "'+t.attr("target")+'");':'window.location.href = "'+t.attr("href")+'";':"",t.prop("onclick",null).data("jBox-Confirm-submit",i))},_onCreated:function(){this.wrapper.addClass("jBox-Modal"),this.footer=jQuery('<div class="jBox-Confirm-footer"/>'),jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-cancel"/>').html(this.options.cancelButton).on("click tap",function(){this.options.cancel&&this.options.cancel(this.source),this.close()}.bind(this)).appendTo(this.footer),this.submitButton=jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-submit"/>').html(this.options.confirmButton).appendTo(this.footer),this.footer.appendTo(this.container)},_onOpen:function(){this.submitButton.off("click.jBox-Confirm"+this.id+" tap.jBox-Confirm"+this.id).on("click.jBox-Confirm"+this.id+" tap.jBox-Confirm"+this.id,function(){this.options.confirm?this.options.confirm(this.source):eval(this.source.data("jBox-Confirm-submit")),this.options.closeOnConfirm&&this.close()}.bind(this))}})}function jBoxImageWrapper(t,a){new t.plugin("Image",{src:"href",gallery:"data-jbox-image",imageLabel:"title",imageFade:360,imageSize:"contain",imageCounter:!1,imageCounterSeparator:"/",downloadButton:!1,downloadButtonText:null,downloadButtonUrl:null,mobileImageAttr:null,mobileImageBreakpoint:null,preloadFirstImage:!1,target:window,attach:"[data-jbox-image]",fixed:!0,blockScroll:!0,closeOnEsc:!0,closeOnClick:"button",closeButton:!0,overlay:!0,animation:"zoomIn",preventDefault:!0,width:"100%",height:"100%",adjustDistance:{top:40,right:0,bottom:40,left:0},_onInit:function(){this.images=this.currentImage={},this.imageZIndex=1,this.initImage=function(t){var i,o;(t=a(t)).data("jBox-image-gallery")||(i=t.attr(this.options.src),this.options.mobileImageAttr&&this.options.mobileImageBreakpoint&&t.attr(this.options.mobileImageAttr)&&a(window).width()<=this.options.mobileImageBreakpoint&&(i=t.attr(this.options.mobileImageAttr)),o=t.attr(this.options.gallery)||"default",this.images[o]||(this.images[o]=[]),this.images[o].push({src:i,label:t.attr(this.options.imageLabel)||"",downloadUrl:this.options.downloadButtonUrl&&t.attr(this.options.downloadButtonUrl)?t.attr(this.options.downloadButtonUrl):null}),"title"==this.options.imageLabel&&t.removeAttr("title"),t.data("jBox-image-gallery",o),t.data("jBox-image-id",this.images[o].length-1))}.bind(this),this.attachedElements&&this.attachedElements.length&&a.each(this.attachedElements,function(t,i){this.initImage(i)}.bind(this));var n=function(t,i,o,s){if(!a("#jBox-image-"+t+"-"+i).length){var e=a("<div/>",{id:"jBox-image-"+t+"-"+i,class:"jBox-image-container"+(o?" jBox-image-"+t+"-current":"")}).css({backgroundSize:this.options.imageSize,opacity:s?1:0,zIndex:o?this.imageZIndex++:0}).appendTo(this.content);return this.swipeDetector(e).on("swipeLeft.sd swipeRight.sd",function(t){"swipeLeft"===t.type?this.showImage("next"):"swipeRight"===t.type&&this.showImage("prev")}.bind(this)),a("<div/>",{id:"jBox-image-label-"+t+"-"+i,class:"jBox-image-label"+(o?" active":"")}).html(this.images[t][i].label).on("click tap",function(){a(this).toggleClass("expanded")}).appendTo(this.imageLabelContainer),o&&e.animate({opacity:1},s?0:this.options.imageFade),e}}.bind(this);this.downloadImage=function(t){var i=document.createElement("a");i.href=t,i.setAttribute("download",t.substring(t.lastIndexOf("/")+1)),document.body.appendChild(i),i.click()};var e=function(i,o,t,s){var e=n(i,o,t,s);e.addClass("jBox-image-loading"),a('<img src="'+this.images[i][o].src+'" />').each(function(){var t=new Image;t.onload=function(){e.removeClass("jBox-image-loading"),e.css({backgroundImage:'url("'+this.images[i][o].src+'")'})}.bind(this),t.onerror=function(){e.removeClass("jBox-image-loading"),e.addClass("jBox-image-not-found")}.bind(this),t.src=this.images[i][o].src}.bind(this))}.bind(this);this.showImage=function(t){if("open"!=t){var i=this.currentImage.gallery;o=(o=this.currentImage.id+(+("prev"==t)?-1:1))>this.images[i].length-1?0:o<0?this.images[i].length-1:o}else{if(this.source)var i=this.source.data("jBox-image-gallery"),o=this.source.data("jBox-image-id");else{if(!this.attachedElements||!this.attachedElements.length)return;i=a(this.attachedElements[0]).data("jBox-image-gallery"),o=a(this.attachedElements[0]).data("jBox-image-id")}a(".jBox-image-pointer-prev, .jBox-image-pointer-next").css({display:1<this.images[i].length?"block":"none"})}var s;a(".jBox-image-"+i+"-current").length&&a(".jBox-image-"+i+"-current").removeClass("jBox-image-"+i+"-current").animate({opacity:0},"open"==t?0:this.options.imageFade),this.currentImage={gallery:i,id:o},a("#jBox-image-"+i+"-"+o).length?a("#jBox-image-"+i+"-"+o).addClass("jBox-image-"+i+"-current").css({zIndex:this.imageZIndex++,opacity:0}).animate({opacity:1},"open"==t?0:this.options.imageFade):e(i,o,!0,"open"===t),s=i,t=o,a(".jBox-image-label.active").removeClass("active expanded"),a("#jBox-image-label-"+s+"-"+t).addClass("active"),this.imageCounter&&(1<this.images[i].length?(this.wrapper.addClass("jBox-image-has-counter"),this.imageCounter.find(".jBox-image-counter-all").html(this.images[i].length),this.imageCounter.find(".jBox-image-counter-current").html(o+1)):this.wrapper.removeClass("jBox-image-has-counter")),this.images[i].length-1&&(o=(o=o+1)>this.images[i].length-1?0:o<0?this.images[i].length-1:o,a("#jBox-image-"+i+"-"+o).length||e(i,o,!1,!1))},this.options.preloadFirstImage&&a(window).on("load",function(){this.showImage("open")}.bind(this))},_onAttach:function(t){this.initImage&&this.initImage(t)},_onCreated:function(){this.imageLabelWrapper=a('<div class="jBox-image-label-wrapper"/>').appendTo(this.wrapper),this.imagePrevButton=a('<div class="jBox-image-pointer-prev"/>').on("click tap",function(){this.showImage("prev")}.bind(this)),this.imageNextButton=a('<div class="jBox-image-pointer-next"/>').on("click tap",function(){this.showImage("next")}.bind(this)),this.imageLabelContainer=a('<div class="jBox-image-label-container"/>'),this.imageLabelWrapper.append(this.imagePrevButton).append(this.imageLabelContainer).append(this.imageNextButton),this.options.downloadButton&&(this.downloadButton=a("<div/>",{class:"jBox-image-download-button-wrapper"}).appendTo(this.wrapper).append(this.options.downloadButtonText?a("<div/>",{class:"jBox-image-download-button-text"}).html(this.options.downloadButtonText):null).append(a("<div/>",{class:"jBox-image-download-button-icon"})).on("click tap",function(){var t;t=this.images[this.currentImage.gallery][this.currentImage.id].downloadUrl||this.wrapper.find(".jBox-image-"+this.currentImage.gallery+"-current")[0].style.backgroundImage.slice(4,-1).replace(/["']/g,""),this.downloadImage(t)}.bind(this))),this.options.imageCounter&&(this.imageCounter=a("<div/>",{class:"jBox-image-counter-container"}).insertAfter(this.imageLabelContainer),this.imageCounter.append(a("<span/>",{class:"jBox-image-counter-current"})).append(a("<span/>").html(this.options.imageCounterSeparator)).append(a("<span/>",{class:"jBox-image-counter-all"})))},_onOpen:function(){a(document).on("keyup.jBox-Image-"+this.id,function(t){37==t.keyCode&&this.showImage("prev"),39==t.keyCode&&this.showImage("next")}.bind(this)),this.showImage("open")},_onClose:function(){a(document).off("keyup.jBox-Image-"+this.id)},_onCloseComplete:function(){this.wrapper.find(".jBox-image-container").css("opacity",0)}})}function jBoxNoticeWrapper(t,a){new t.plugin("Notice",{color:null,stack:!0,stackSpacing:10,autoClose:6e3,attributes:{x:"right",y:"top"},position:{x:15,y:15},responsivePositions:{500:{x:5,y:5},768:{x:10,y:10}},target:window,fixed:!0,animation:"zoomIn",closeOnClick:"box",zIndex:12e3,_onInit:function(){this.defaultNoticePosition=a.extend({},this.options.position),this._adjustNoticePositon=function(){var t=a(window),o=t.width();t.height();this.options.position=a.extend({},this.defaultNoticePosition),a.each(this.options.responsivePositions,function(t,i){if(o<=t)return this.options.position=i,!1}.bind(this)),this.options.adjustDistance={top:this.options.position.y,right:this.options.position.x,bottom:this.options.position.y,left:this.options.position.x}},this.options.content instanceof a&&(this.options.content=this.options.content.clone().attr("id","")),a(window).on("resize.responsivejBoxNotice-"+this.id,function(t){this.isOpen&&this._adjustNoticePositon()}.bind(this)),this.open()},_onCreated:function(){this.wrapper.addClass("jBox-Notice-color jBox-Notice-"+(this.options.color||"gray")),this.wrapper.data("jBox-Notice-position",this.options.attributes.x+"-"+this.options.attributes.y)},_onOpen:function(){this.options.stack||(this._adjustNoticePositon(),a.each(a(".jBox-Notice"),function(t,i){(i=a(i)).attr("id")!=this.id&&i.data("jBox-Notice-position")==this.options.attributes.x+"-"+this.options.attributes.y&&(this.options.stack||i.data("jBox").close({ignoreDelay:!0}))}.bind(this)))},_onPosition:function(){var t,s={};for(t in a.each(a(".jBox-Notice"),function(t,i){var o=(i=a(i)).data("jBox-Notice-position");s[o]||(s[o]=[]),s[o].push(i)}),s){var i=t.split("-")[1];s[t].reverse();var o,e=0;for(o in s[t]){var n=a(s[t][o]);n.css("margin-"+i,e),e+=n.outerHeight()+this.options.stackSpacing}}},_onCloseComplete:function(){this.destroy(),this.options._onPosition.bind(this).call()}})}!function(i,o){"function"==typeof define&&define.amd?define(["jquery"],function(t){return i.jBox=o(t)}):"object"==typeof module&&module.exports?module.exports=i.jBox=o(require("jquery")):i.jBox=o(i.jQuery)}(this,function(t){var i=jBoxWrapper(t);try{void 0!==jBoxConfirmWrapper&&jBoxConfirmWrapper&&jBoxConfirmWrapper(i,t)}catch(t){console.error(t)}try{void 0!==jBoxImageWrapper&&jBoxImageWrapper&&jBoxImageWrapper(i,t)}catch(t){console.error(t)}try{void 0!==jBoxNoticeWrapper&&jBoxNoticeWrapper&&jBoxNoticeWrapper(i,t)}catch(t){console.error(t)}return i});
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,572 @@
1
+.jBox-wrapper {
2
+  text-align: left;
3
+  box-sizing: border-box;
4
+}
5
+
6
+.jBox-title,
7
+.jBox-content,
8
+.jBox-container {
9
+  position: relative;
10
+  word-break: break-word;
11
+  box-sizing: border-box;
12
+}
13
+
14
+.jBox-container {
15
+  background: #fff;
16
+}
17
+
18
+.jBox-content {
19
+  padding: 8px 12px;
20
+  overflow-x: hidden;
21
+  overflow-y: auto;
22
+  transition: opacity .2s;
23
+}
24
+
25
+.jBox-footer {
26
+  box-sizing: border-box;
27
+}
28
+
29
+.jBox-Tooltip .jBox-container,
30
+.jBox-Mouse .jBox-container {
31
+  border-radius: 4px;
32
+  box-shadow: 0 0 3px rgba(0, 0, 0, 0.25);
33
+}
34
+
35
+.jBox-Tooltip .jBox-title,
36
+.jBox-Mouse .jBox-title {
37
+  padding: 8px 10px 0;
38
+  font-weight: bold;
39
+}
40
+
41
+.jBox-Tooltip.jBox-hasTitle .jBox-content,
42
+.jBox-Mouse.jBox-hasTitle .jBox-content {
43
+  padding-top: 5px;
44
+}
45
+
46
+.jBox-Mouse {
47
+  pointer-events: none;
48
+}
49
+
50
+.jBox-pointer {
51
+  position: absolute;
52
+  overflow: hidden;
53
+  box-sizing: border-box;
54
+}
55
+
56
+.jBox-pointer:after {
57
+  content: '';
58
+  width: 20px;
59
+  height: 20px;
60
+  position: absolute;
61
+  background: #fff;
62
+  transform: rotate(45deg);
63
+  box-sizing: border-box;
64
+}
65
+
66
+.jBox-pointer-top {
67
+  top: 0;
68
+}
69
+
70
+.jBox-pointer-top:after {
71
+  left: 5px;
72
+  top: 6px;
73
+  box-shadow: -1px -1px 2px rgba(0, 0, 0, 0.15);
74
+}
75
+
76
+.jBox-pointer-right {
77
+  right: 0;
78
+}
79
+
80
+.jBox-pointer-right:after {
81
+  top: 5px;
82
+  right: 6px;
83
+  box-shadow: 1px -1px 2px rgba(0, 0, 0, 0.15);
84
+}
85
+
86
+.jBox-pointer-left {
87
+  left: 0;
88
+}
89
+
90
+.jBox-pointer-left:after {
91
+  top: 5px;
92
+  left: 6px;
93
+  box-shadow: -1px 1px 2px rgba(0, 0, 0, 0.15);
94
+}
95
+
96
+.jBox-pointer-bottom {
97
+  bottom: 0;
98
+}
99
+
100
+.jBox-pointer-bottom:after {
101
+  left: 5px;
102
+  bottom: 6px;
103
+  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.15);
104
+}
105
+
106
+.jBox-pointer-top, .jBox-pointer-bottom {
107
+  width: 30px;
108
+  height: 12px;
109
+}
110
+
111
+.jBox-pointer-left, .jBox-pointer-right {
112
+  width: 12px;
113
+  height: 30px;
114
+}
115
+
116
+.jBox-Modal .jBox-container {
117
+  border-radius: 4px;
118
+}
119
+
120
+.jBox-Modal .jBox-container, .jBox-Modal.jBox-closeButton-box:before {
121
+  box-shadow: 0 3px 15px rgba(0, 0, 0, 0.4), 0 0 5px rgba(0, 0, 0, 0.4);
122
+}
123
+
124
+.jBox-Modal .jBox-content {
125
+  padding: 15px 20px;
126
+}
127
+
128
+.jBox-Modal .jBox-title {
129
+  border-radius: 4px 4px 0 0;
130
+  padding: 15px 20px;
131
+  background: #fafafa;
132
+  border-bottom: 1px solid #eee;
133
+}
134
+
135
+.jBox-Modal.jBox-closeButton-title .jBox-title {
136
+  padding-right: 65px;
137
+}
138
+
139
+.jBox-Modal .jBox-footer {
140
+  border-radius: 0 0 4px 4px;
141
+}
142
+
143
+.jBox-closeButton {
144
+  z-index: 1;
145
+  cursor: pointer;
146
+  position: absolute;
147
+  box-sizing: border-box;
148
+}
149
+
150
+.jBox-closeButton svg {
151
+  position: absolute;
152
+  top: 50%;
153
+  right: 50%;
154
+}
155
+
156
+.jBox-closeButton path {
157
+  fill: #aaa;
158
+  transition: fill .2s;
159
+}
160
+
161
+.jBox-closeButton:hover path {
162
+  fill: #888;
163
+}
164
+
165
+.jBox-overlay .jBox-closeButton {
166
+  top: 0;
167
+  right: 0;
168
+  width: 40px;
169
+  height: 40px;
170
+}
171
+
172
+.jBox-overlay .jBox-closeButton svg {
173
+  width: 20px;
174
+  height: 20px;
175
+  margin-top: -10px;
176
+  margin-right: -10px;
177
+}
178
+
179
+.jBox-overlay .jBox-closeButton path {
180
+  fill: #ddd;
181
+}
182
+
183
+.jBox-overlay .jBox-closeButton:hover path {
184
+  fill: #fff;
185
+}
186
+
187
+.jBox-closeButton-title .jBox-closeButton {
188
+  top: 0;
189
+  right: 0;
190
+  bottom: 0;
191
+  width: 50px;
192
+}
193
+
194
+.jBox-closeButton-title svg {
195
+  width: 12px;
196
+  height: 12px;
197
+  margin-top: -6px;
198
+  margin-right: -6px;
199
+}
200
+
201
+.jBox-closeButton-box {
202
+  box-sizing: border-box;
203
+}
204
+
205
+.jBox-closeButton-box .jBox-closeButton {
206
+  top: -8px;
207
+  right: -10px;
208
+  width: 24px;
209
+  height: 24px;
210
+  background: #fff;
211
+  border-radius: 50%;
212
+}
213
+
214
+.jBox-closeButton-box .jBox-closeButton svg {
215
+  width: 10px;
216
+  height: 10px;
217
+  margin-top: -5px;
218
+  margin-right: -5px;
219
+}
220
+
221
+.jBox-closeButton-box:before {
222
+  content: '';
223
+  position: absolute;
224
+  top: -8px;
225
+  right: -10px;
226
+  width: 24px;
227
+  height: 24px;
228
+  border-radius: 50%;
229
+  box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
230
+}
231
+
232
+.jBox-closeButton-box.jBox-pointerPosition-top:before {
233
+  top: 5px;
234
+}
235
+
236
+.jBox-closeButton-box.jBox-pointerPosition-right:before {
237
+  right: 2px;
238
+}
239
+
240
+.jBox-Modal.jBox-hasTitle.jBox-closeButton-box .jBox-closeButton {
241
+  background: #fafafa;
242
+}
243
+
244
+.jBox-overlay {
245
+  position: fixed;
246
+  top: 0;
247
+  left: 0;
248
+  width: 100%;
249
+  height: 100%;
250
+  background-color: rgba(0, 0, 0, 0.82);
251
+}
252
+
253
+.jBox-footer {
254
+  background: #fafafa;
255
+  border-top: 1px solid #eee;
256
+  padding: 8px 10px;
257
+  border-radius: 0 0 3px 3px;
258
+}
259
+
260
+body[class^="jBox-blockScroll-"],
261
+body[class*=" jBox-blockScroll-"] {
262
+  overflow: hidden;
263
+}
264
+
265
+.jBox-draggable {
266
+  cursor: move;
267
+}
268
+
269
+@keyframes jBoxLoading {
270
+  to {
271
+    transform: rotate(360deg);
272
+  }
273
+}
274
+
275
+.jBox-loading .jBox-content {
276
+  opacity: .2;
277
+}
278
+
279
+.jBox-loading-spinner .jBox-content {
280
+  min-height: 38px !important;
281
+  min-width: 38px !important;
282
+  opacity: 0;
283
+}
284
+
285
+.jBox-spinner {
286
+  box-sizing: border-box;
287
+  position: absolute;
288
+  top: 50%;
289
+  left: 50%;
290
+  width: 24px;
291
+  height: 24px;
292
+  margin-top: -12px;
293
+  margin-left: -12px;
294
+}
295
+
296
+.jBox-spinner:before {
297
+  display: block;
298
+  box-sizing: border-box;
299
+  content: '';
300
+  width: 24px;
301
+  height: 24px;
302
+  border-radius: 50%;
303
+  border: 2px solid rgba(0, 0, 0, 0.2);
304
+  border-top-color: rgba(0, 0, 0, 0.8);
305
+  animation: jBoxLoading .6s linear infinite;
306
+}
307
+
308
+.jBox-countdown {
309
+  border-radius: 4px 4px 0 0;
310
+  z-index: 0;
311
+  background: #000;
312
+  opacity: .2;
313
+  position: absolute;
314
+  top: 0;
315
+  left: 0;
316
+  right: 0;
317
+  height: 3px;
318
+  overflow: hidden;
319
+}
320
+
321
+.jBox-countdown-inner {
322
+  top: 0;
323
+  right: 0;
324
+  width: 100%;
325
+  height: 3px;
326
+  position: absolute;
327
+  background: #fff;
328
+}
329
+
330
+[class^="jBox-animated-"],
331
+[class*=" jBox-animated-"] {
332
+  animation-fill-mode: both;
333
+}
334
+
335
+@keyframes jBox-tada {
336
+  0% {
337
+    transform: scale(1);
338
+  }
339
+  10%,
340
+  20% {
341
+    transform: scale(0.8) rotate(-4deg);
342
+  }
343
+  30%,
344
+  50%,
345
+  70%,
346
+  90% {
347
+    transform: scale(1.2) rotate(4deg);
348
+  }
349
+  40%,
350
+  60%,
351
+  80% {
352
+    transform: scale(1.2) rotate(-4deg);
353
+  }
354
+  100% {
355
+    transform: scale(1) rotate(0);
356
+  }
357
+}
358
+
359
+.jBox-animated-tada {
360
+  animation: jBox-tada 1s;
361
+}
362
+
363
+@keyframes jBox-tadaSmall {
364
+  0% {
365
+    transform: scale(1);
366
+  }
367
+  10%,
368
+  20% {
369
+    transform: scale(0.9) rotate(-2deg);
370
+  }
371
+  30%,
372
+  50%,
373
+  70%,
374
+  90% {
375
+    transform: scale(1.1) rotate(2deg);
376
+  }
377
+  40%,
378
+  60%,
379
+  80% {
380
+    transform: scale(1.1) rotate(-2deg);
381
+  }
382
+  100% {
383
+    transform: scale(1) rotate(0);
384
+  }
385
+}
386
+
387
+.jBox-animated-tadaSmall {
388
+  animation: jBox-tadaSmall 1s;
389
+}
390
+
391
+@keyframes jBox-flash {
392
+  0%,
393
+  50%,
394
+  100% {
395
+    opacity: 1;
396
+  }
397
+  25%,
398
+  75% {
399
+    opacity: 0;
400
+  }
401
+}
402
+
403
+.jBox-animated-flash {
404
+  animation: jBox-flash .5s;
405
+}
406
+
407
+@keyframes jBox-shake {
408
+  0%,
409
+  100% {
410
+    transform: translateX(0);
411
+  }
412
+  20%,
413
+  60% {
414
+    transform: translateX(-6px);
415
+  }
416
+  40%,
417
+  80% {
418
+    transform: translateX(6px);
419
+  }
420
+}
421
+
422
+.jBox-animated-shake {
423
+  animation: jBox-shake .4s;
424
+}
425
+
426
+@keyframes jBox-pulseUp {
427
+  0% {
428
+    transform: scale(1);
429
+  }
430
+  50% {
431
+    transform: scale(1.15);
432
+  }
433
+  100% {
434
+    transform: scale(1);
435
+  }
436
+}
437
+
438
+.jBox-animated-pulseUp {
439
+  animation: jBox-pulseUp .25s;
440
+}
441
+
442
+@keyframes jBox-pulseDown {
443
+  0% {
444
+    transform: scale(1);
445
+  }
446
+  50% {
447
+    transform: scale(0.85);
448
+  }
449
+  100% {
450
+    transform: scale(1);
451
+  }
452
+}
453
+
454
+.jBox-animated-pulseDown {
455
+  animation: jBox-pulseDown .25s;
456
+}
457
+
458
+@keyframes jBox-popIn {
459
+  0% {
460
+    transform: scale(0);
461
+  }
462
+  50% {
463
+    transform: scale(1.1);
464
+  }
465
+  100% {
466
+    transform: scale(1);
467
+  }
468
+}
469
+
470
+.jBox-animated-popIn {
471
+  animation: jBox-popIn .25s;
472
+}
473
+
474
+@keyframes jBox-popOut {
475
+  0% {
476
+    transform: scale(1);
477
+  }
478
+  50% {
479
+    transform: scale(1.1);
480
+  }
481
+  100% {
482
+    transform: scale(0);
483
+  }
484
+}
485
+
486
+.jBox-animated-popOut {
487
+  animation: jBox-popOut .25s;
488
+}
489
+
490
+@keyframes jBox-fadeIn {
491
+  0% {
492
+    opacity: 0;
493
+  }
494
+  100% {
495
+    opacity: 1;
496
+  }
497
+}
498
+
499
+.jBox-animated-fadeIn {
500
+  animation: jBox-fadeIn .2s;
501
+}
502
+
503
+@keyframes jBox-fadeOut {
504
+  0% {
505
+    opacity: 1;
506
+  }
507
+  100% {
508
+    opacity: 0;
509
+  }
510
+}
511
+
512
+.jBox-animated-fadeOut {
513
+  animation: jBox-fadeOut .2s;
514
+}
515
+
516
+@keyframes jBox-slideUp {
517
+  0% {
518
+    transform: translateY(0);
519
+  }
520
+  100% {
521
+    transform: translateY(-300px);
522
+    opacity: 0;
523
+  }
524
+}
525
+
526
+.jBox-animated-slideUp {
527
+  animation: jBox-slideUp .4s;
528
+}
529
+
530
+@keyframes jBox-slideRight {
531
+  0% {
532
+    transform: translateX(0);
533
+  }
534
+  100% {
535
+    transform: translateX(300px);
536
+    opacity: 0;
537
+  }
538
+}
539
+
540
+.jBox-animated-slideRight {
541
+  animation: jBox-slideRight .4s;
542
+}
543
+
544
+@keyframes jBox-slideDown {
545
+  0% {
546
+    transform: translateY(0);
547
+  }
548
+  100% {
549
+    transform: translateY(300px);
550
+    opacity: 0;
551
+  }
552
+}
553
+
554
+.jBox-animated-slideDown {
555
+  animation: jBox-slideDown .4s;
556
+}
557
+
558
+@keyframes jBox-slideLeft {
559
+  0% {
560
+    transform: translateX(0);
561
+  }
562
+  100% {
563
+    transform: translateX(-300px);
564
+    opacity: 0;
565
+  }
566
+}
567
+
568
+.jBox-animated-slideLeft {
569
+  animation: jBox-slideLeft .4s;
570
+}
571
+
572
+/*# sourceMappingURL=jBox.css.map */
0 573
new file mode 100644
... ...
@@ -0,0 +1,2290 @@
1
+/**
2
+ * jBox is a jQuery plugin that makes it easy to create customizable tooltips, modal windows, image galleries and more.
3
+ *
4
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
5
+ *
6
+ * License: MIT (https://opensource.org/licenses/MIT)
7
+ *
8
+ * Requires: jQuery 3.5.0 (https://code.jquery.com/jquery-3.5.0.min.js)
9
+ *
10
+ * Documentation: https://stephanwagner.me/jBox/documentation
11
+ *
12
+ * Demos: https://stephanwagner.me/jBox/demos
13
+ */
14
+
15
+function jBoxWrapper(jQuery) {
16
+
17
+
18
+  var jBox = function jBox(type, options) {
19
+
20
+
21
+    // Options (https://stephanwagner.me/jBox/options)
22
+
23
+    this.options = {
24
+
25
+      // jBox ID
26
+      id: null,                    // Choose a unique id, otherwise jBox will set one for you (jBox1, jBox2, ...)
27
+
28
+      // Dimensions
29
+      width: 'auto',               // The width of the content area, e.g. 'auto', 200, '80%'
30
+      height: 'auto',              // The height of the content area
31
+      minWidth: null,              // Minimal width
32
+      minHeight: null,             // Minimal height
33
+      maxWidth: null,              // Maximal width
34
+      maxHeight: null,             // Maximal height
35
+
36
+      // Responsive dimensions
37
+      responsiveWidth: true,       // Adjusts the width to fit the viewport
38
+      responsiveHeight: true,      // Adjusts the height to fit the viewport
39
+      responsiveMinWidth: 100,     // Don't adjust width below this value (in pixel)
40
+      responsiveMinHeight: 100,    // Don't adjust height below this value (in pixel)
41
+
42
+      // Attach
43
+      attach: null,                // A jQuery selector to elements that will open and close your jBox, e.g. '.tooltip'
44
+      trigger: 'click',            // The event to open or close your jBox, use 'click', 'touchclick' or 'mouseenter'
45
+      preventDefault: false,       // Prevent the default event when opening jBox, e.g. don't follow the href in a link
46
+
47
+      // Content
48
+      content: null,               // You can use HTML or a jQuery element, e.g. jQuery('#jBox-content'). The elements will be appended to the content element and then made visible, so hide them with style="display: none" beforehand
49
+      getContent: null,            // Get the content from an attribute when jBox opens, e.g. getContent: 'data-content'. Use 'html' to get the attached elements HTML as content
50
+      title: null,                 // Adds a title to your jBox
51
+      getTitle: null,              // Get the title from an attribute when jBox opens, e.g. getTitle: 'data-title'
52
+      footer: null,                // Adds a footer to your jBox
53
+      isolateScroll: true,         // Isolates scrolling to the content container
54
+
55
+      // AJAX
56
+      ajax: {                      // Setting an URL will make an AJAX request when jBox opens. Optional you can add any jQuery AJAX option (http://api.jquery.com/jquery.ajax/)
57
+        url: null,                 // The URL to send the AJAX request to
58
+        data: '',                  // Data to send with your AJAX request, e.g. {id: 82, limit: 10}
59
+        reload: false,             // Resend the AJAX request when jBox opens. Use true to send the AJAX request only once for every attached element or 'strict' to resend every time jBox opens
60
+        getURL: 'data-url',        // The attribute in the source element where the AJAX request will look for the URL, e.g. data-url="https://reqres.in/api/users"
61
+        getData: 'data-ajax',      // The attribute in the source element where the AJAX request will look for the data, e.g. data-ajax="id=82&limit=10"
62
+        setContent: true,          // Automatically set the response as new content when the AJAX request is finished
63
+        loadingClass: true,        // Add a class to the wrapper when jBox is loading, set to class name or true to use the default class name 'jBox-loading'
64
+        spinner: true,             // Hides the current content and adds a spinner while loading. You can pass HTML content to add your own spinner, e.g. spinner: '<div class="mySpinner"></div>'
65
+        spinnerDelay: 300,         // Milliseconds to wait until spinner appears
66
+        spinnerReposition: true    // Repositions jBox when the spinner is added or removed
67
+      },
68
+      cancelAjaxOnClose: true,     // Cancels the ajax call when jBox closes and it hasn't finished loading yet
69
+
70
+      // Position
71
+      target: null,                // The jQuery selector to the target element where jBox will be opened. If no element is found, jBox will use the attached element as target
72
+      position: {
73
+        x: 'center',               // Horizontal position, use a number, 'left', 'right' or 'center'
74
+        y: 'center'                // Vertical position, use a number, 'top', 'bottom' or 'center'
75
+      },
76
+      outside: null,               // Use 'x', 'y', or 'xy' to move your jBox outside of the target element
77
+      offset: 0,                   // Offset to final position, you can set different values for x and y with an object, e.g. {x: 20, y: 10}
78
+      attributes: {                // Note that attributes can only be 'left' or 'right' when using numbers for position, e.g. {x: 300, y: 20}
79
+        x: 'left',                 // Horizontal position, use 'left' or 'right'
80
+        y: 'top'                   // Vertical position, use 'top' or 'bottom'
81
+      },
82
+      fixed: false,                // Your jBox will stay on position when scrolling
83
+      adjustPosition: true,        // Adjusts your jBoxes position if there is not enough space, use 'flip', 'move' or true for both. This option overrides the reposition options
84
+      adjustTracker: false,        // By default jBox adjusts its position when it opens or when the window size changes, set to true to also adjust when scrolling
85
+      adjustDistance: 5,           // The minimal distance to the viewport edge while adjusting. Use an object to set different values, e.g. {top: 50, right: 5, bottom: 20, left: 5}
86
+      reposition: true,            // Calculates new position when the window-size changes
87
+      repositionOnOpen: true,      // Calculates new position each time jBox opens (rather than only when it opens the first time)
88
+      repositionOnContent: true,   // Calculates new position when the content changes with .setContent() or .setTitle()
89
+      holdPosition: true,          // Keeps current position if space permits. Applies only to 'Modal' type.
90
+
91
+      // Pointer
92
+      pointer: false,              // Your pointer will always point towards the target element, so the option outside needs to be 'x' or 'y'. By default the pointer is centered, set a position to move it to any side. You can also add an offset, e.g. 'left:30' or 'center:-20'
93
+      pointTo: 'target',           // Setting something else than 'target' will add a pointer even if there is no target element set or found. Use 'top', 'right', 'bottom' or 'left'
94
+
95
+      // Animations
96
+      fade: 180,                   // Fade duration in ms, set to 0 or false to disable
97
+      animation: null,             // Animation when opening or closing, use 'pulse', 'zoomIn', 'zoomOut', 'move', 'slide', 'flip', 'tada' (CSS inspired from Daniel Edens Animate.css: http://daneden.me/animate)
98
+
99
+      // Appearance
100
+      theme: 'Default',            // Set a jBox theme class
101
+      addClass: null,              // Adds classes to the wrapper
102
+      overlay: false,              // Adds an overlay to hide page content when jBox opens (adjust color and opacity with CSS)
103
+      overlayClass: null,          // Add a class name to the overlay
104
+      zIndex: 10000,               // Use a high z-index, or set to 'auto' to bring to front on open
105
+
106
+      // Delays
107
+      delayOpen: 0,                // Delay opening in ms. Note that the delay will be ignored if your jBox didn't finish closing
108
+      delayClose: 0,               // Delay closing in ms. Nnote that there is always a closing delay of at least 10ms to ensure jBox won't be closed when opening right away
109
+
110
+      // Closing
111
+      closeOnEsc: false,           // Close jBox when pressing [esc] key
112
+      closeOnClick: false,         // Close jBox with mouseclick. Use true (click anywhere), 'box' (click on jBox itself), 'overlay' (click on the overlay), 'body' (click anywhere but jBox)
113
+      closeOnMouseleave: false,    // Close jBox when the mouse leaves the jBox area or the area of the attached element
114
+      closeButton: false,          // Adds a close button to your jBox. Use 'title', 'box', 'overlay' or true (true will add the button to the overlay, title or the jBox itself, in that order if any of those elements can be found)
115
+
116
+      // Other options
117
+      appendTo: jQuery('body'),    // The element your jBox will be appended to. Any other element than jQuery('body') is only useful for fixed positions or when position values are numbers
118
+      createOnInit: false,         // Creates jBox and makes it available in DOM when it's being initialized, otherwise it will be created when it opens for the first time
119
+      blockScroll: false,          // Blocks scrolling when jBox is open
120
+      blockScrollAdjust: true,     // Adjust page elements to avoid content jumps when scrolling is blocked. See more here: https://github.com/StephanWagner/unscroll
121
+      draggable: false,            // Make your jBox draggable (use 'true', 'title' or provide an element as handle) (inspired from Chris Coyiers CSS-Tricks http://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/)
122
+      dragOver: true,              // When you have multiple draggable jBoxes, the one you select will always move over the other ones
123
+      autoClose: false,            // Time in ms when jBox will close automatically after it was opened
124
+      delayOnHover: false,         // Delay auto-closing while mouse is hovered
125
+      showCountdown: false,        // Display a nice progress-indicator when autoClose is enabled
126
+
127
+      // Audio                     // You can use the integrated audio function whenever you'd like to play an audio file, e.g. onInit: function () { this.audio('url_to_audio_file_without_file_extension', 75); }
128
+      preloadAudio: true,          // Preloads the audio files set in option audio. You can also preload other audio files, e.g. ['src_to_file.mp3', 'src_to_file.ogg']
129
+      audio: null,                 // The URL to an audio file to play when jBox opens. Set the URL without file extension, jBox will look for an .mp3 and .ogg file. To play audio when jBox closes, use an object, e.g. {open: 'src_to_audio1', close: 'src_to_audio2'}
130
+      volume: 100,                 // The volume in percent. To have different volumes for opening and closeing, use an object, e.g. {open: 75, close: 100}
131
+
132
+      // Events                    // Note that you can use 'this' in all event functions, it refers to your jBox object (e.g. onInit: function () { this.open(); })
133
+      onInit: null,                // Fired when jBox is initialized
134
+      onAttach: null,              // Fired when jBox attached itself to elements, the attached element will be passed as a parameter, e.g. onAttach: function (element) { element.css({color: 'red'}); }
135
+      onPosition: null,            // Fired when jBox is positioned
136
+      onCreated: null,             // Fired when jBox is created and availible in DOM
137
+      onOpen: null,                // Fired when jBox opens
138
+      onClose: null,               // Fired when jBox closes
139
+      onCloseComplete: null,       // Fired when jBox is completely closed (when fading is finished)
140
+      onDragStart: null,           // Fired when dragging starts
141
+      onDragEnd: null              // Fired when dragging finished
142
+    };
143
+
144
+
145
+    // Default plugin options
146
+
147
+    this._pluginOptions = {
148
+
149
+      // Default options for tooltips
150
+      'Tooltip': {
151
+        getContent: 'title',
152
+        trigger: 'mouseenter',
153
+        position: {
154
+          x: 'center',
155
+          y: 'top'
156
+        },
157
+        outside: 'y',
158
+        pointer: true
159
+      },
160
+
161
+      // Default options for mouse tooltips
162
+      'Mouse': {
163
+        responsiveWidth: false,
164
+        responsiveHeight: false,
165
+        adjustPosition: 'flip',
166
+        target: 'mouse',
167
+        trigger: 'mouseenter',
168
+        position: {
169
+          x: 'right',
170
+          y: 'bottom'
171
+        },
172
+        outside: 'xy',
173
+        offset: 5
174
+      },
175
+
176
+      // Default options for modal windows
177
+      'Modal': {
178
+        target: jQuery(window),
179
+        fixed: true,
180
+        blockScroll: true,
181
+        closeOnEsc: true,
182
+        closeOnClick: 'overlay',
183
+        closeButton: true,
184
+        overlay: true,
185
+        animation: 'zoomIn'
186
+      },
187
+    };
188
+
189
+
190
+    // Merge options
191
+
192
+    this.options = jQuery.extend(true, this.options, this._pluginOptions[type] ? this._pluginOptions[type] : jBox._pluginOptions[type], options);
193
+
194
+
195
+    // Set the jBox type
196
+
197
+    jQuery.type(type) == 'string' && (this.type = type);
198
+
199
+
200
+    // Checks if the user is on a touch device, borrowed from https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js
201
+
202
+    this.isTouchDevice = (function () {
203
+      var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
204
+      var mq = function (query) {
205
+        return window.matchMedia(query).matches;
206
+      }
207
+
208
+      if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
209
+        return true;
210
+      }
211
+
212
+      var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
213
+      return mq(query);
214
+    })();
215
+
216
+
217
+    // Add close event for body click when we are on touch device and jBox triggers on mouseenter
218
+
219
+    if (this.isTouchDevice && this.options.trigger === 'mouseenter' && this.options.closeOnClick === false) {
220
+      this.options.closeOnClick = 'body';
221
+    }
222
+
223
+
224
+    // Local function to fire events
225
+
226
+    this._fireEvent = function (event, pass)
227
+    {
228
+      this.options['_' + event] && (this.options['_' + event].bind(this))(pass);
229
+      this.options[event] && (this.options[event].bind(this))(pass);
230
+    };
231
+
232
+
233
+    // Get a unique jBox ID
234
+
235
+    this.options.id === null && (this.options.id = 'jBox' + jBox._getUniqueID());
236
+    this.id = this.options.id;
237
+
238
+
239
+    // Correct impossible options
240
+
241
+    ((this.options.position.x == 'center' && this.options.outside == 'x') || (this.options.position.y == 'center' && this.options.outside == 'y')) && (this.options.outside = null);
242
+    this.options.pointTo == 'target' && (!this.options.outside || this.options.outside == 'xy') && (this.options.pointer = false);
243
+
244
+
245
+    // Correct multiple choice options
246
+
247
+    jQuery.type(this.options.offset) != 'object' ? (this.options.offset = {x: this.options.offset, y: this.options.offset}) : (this.options.offset = jQuery.extend({x: 0, y: 0}, this.options.offset));
248
+    jQuery.type(this.options.adjustDistance) != 'object' ? (this.options.adjustDistance = {top: this.options.adjustDistance, right: this.options.adjustDistance, bottom: this.options.adjustDistance, left: this.options.adjustDistance}) : (this.options.adjustDistance = jQuery.extend({top: 5, left: 5, right: 5, bottom: 5}, this.options.adjustDistance));
249
+
250
+
251
+    // Save default outside position
252
+
253
+    this.outside = this.options.outside && this.options.outside != 'xy' ? this.options.position[this.options.outside] : false;
254
+
255
+
256
+    // Save where the jBox is aligned to
257
+
258
+    this.align = this.outside ? this.outside : (this.options.position.y != 'center' && jQuery.type(this.options.position.y) != 'number' ? this.options.position.x : (this.options.position.x != 'center' && jQuery.type(this.options.position.x) != 'number' ? this.options.position.y : this.options.attributes.x));
259
+
260
+
261
+    // Adjust option zIndex
262
+
263
+    jBox.zIndexMax = Math.max(jBox.zIndexMax || 0, this.options.zIndex === 'auto' ? 10000 : this.options.zIndex);
264
+    if (this.options.zIndex === 'auto') {
265
+      this.adjustZIndexOnOpen = true;
266
+      jBox.zIndexMax += 2;
267
+      this.options.zIndex = jBox.zIndexMax;
268
+      this.trueModal = this.options.overlay;
269
+    }
270
+
271
+    // Internal positioning functions
272
+
273
+    this._getOpp = function (opp) { return {left: 'right', right: 'left', top: 'bottom', bottom: 'top', x: 'y', y: 'x'}[opp]; };
274
+    this._getXY = function (xy) { return {left: 'x', right: 'x', top: 'y', bottom: 'y', center: 'x'}[xy]; };
275
+    this._getTL = function (tl) { return {left: 'left', right: 'left', top: 'top', bottom: 'top', center: 'left', x: 'left', y: 'top'}[tl]; };
276
+
277
+
278
+    // Get a dimension value in integer pixel dependent on appended element
279
+
280
+    this._getInt = function (value, dimension) {
281
+      if (value == 'auto') return 'auto';
282
+      if (value && jQuery.type(value) == 'string' && value.slice(-1) == '%') {
283
+        return jQuery(window)[dimension == 'height' ? 'innerHeight' : 'innerWidth']() * parseInt(value.replace('%', '')) / 100;
284
+      }
285
+      return value;
286
+    };
287
+
288
+
289
+    // Create an svg element
290
+
291
+    this._createSVG = function (type, options)
292
+    {
293
+      var svg = document.createElementNS('http://www.w3.org/2000/svg', type);
294
+      jQuery.each(options, function (index, item) {
295
+        svg.setAttribute(item[0], (item[1] || ''));
296
+      });
297
+      return svg;
298
+    };
299
+
300
+
301
+    // Isolate scrolling in a container
302
+
303
+    this._isolateScroll = function (el)
304
+    {
305
+      // Abort if element not found
306
+      if (!el || !el.length) return;
307
+
308
+      el.on('DOMMouseScroll.jBoxIsolateScroll mousewheel.jBoxIsolateScroll', function (ev) {
309
+        var delta = ev.wheelDelta || (ev.originalEvent && ev.originalEvent.wheelDelta) || -ev.detail;
310
+        var overflowBottom = this.scrollTop + el.outerHeight() - this.scrollHeight >= 0;
311
+        var overflowTop = this.scrollTop <= 0;
312
+        ((delta < 0 && overflowBottom) || (delta > 0 && overflowTop)) && ev.preventDefault();
313
+      });
314
+    };
315
+
316
+
317
+    // Set the title width to content width
318
+
319
+    this._setTitleWidth = function ()
320
+    {
321
+      // Abort if there is no title or width of content is auto
322
+      if (!this.titleContainer || (this.content[0].style.width == 'auto' && !this.content[0].style.maxWidth)) return null;
323
+
324
+      // Expose wrapper to get actual width
325
+      if (this.wrapper.css('display') == 'none') {
326
+        this.wrapper.css('display', 'block');
327
+        var contentWidth = this.content.outerWidth();
328
+        this.wrapper.css('display', 'none');
329
+      } else {
330
+        var contentWidth = this.content.outerWidth();
331
+      }
332
+
333
+      // Set max-width only
334
+      this.titleContainer.css({maxWidth: (Math.max(contentWidth, parseInt(this.content[0].style.maxWidth)) || null)});
335
+    }
336
+
337
+
338
+    // Make jBox draggable
339
+
340
+    this._draggable = function ()
341
+    {
342
+      // Abort if jBox is not draggable
343
+      if (!this.options.draggable) return false;
344
+
345
+      // Get the handle where jBox will be dragged with
346
+      var handle = this.options.draggable == 'title' ? this.titleContainer : (this.options.draggable instanceof jQuery ? this.options.draggable : (jQuery.type(this.options.draggable) == 'string' ? jQuery(this.options.draggable) : this.wrapper));
347
+
348
+      // Abort if no handle or if draggable was set already
349
+      if (!handle || !(handle instanceof jQuery) || !handle.length || handle.data('jBox-draggable')) return false;
350
+
351
+      // Add mouse events
352
+      handle.addClass('jBox-draggable').data('jBox-draggable', true).on('touchstart mousedown', function (ev)
353
+      {
354
+        if (ev.button == 2 || jQuery(ev.target).hasClass('jBox-noDrag') || jQuery(ev.target).parents('.jBox-noDrag').length) return;
355
+
356
+        // Store current mouse position
357
+        this.draggingStartX = ev.pageX;
358
+        this.draggingStartY = ev.pageY;
359
+
360
+        // Adjust z-index when dragging jBox over another draggable jBox
361
+        if (this.options.dragOver && !this.trueModal && parseInt(this.wrapper.css('zIndex'), 10) <= jBox.zIndexMaxDragover) {
362
+          jBox.zIndexMaxDragover += 1;
363
+          this.wrapper.css('zIndex', jBox.zIndexMaxDragover);
364
+        }
365
+
366
+        var drg_h = this.wrapper.outerHeight();
367
+        var drg_w = this.wrapper.outerWidth();
368
+        var pos_y = this.wrapper.offset().top + drg_h - ev.pageY;
369
+        var pos_x = this.wrapper.offset().left + drg_w - ev.pageX;
370
+
371
+        jQuery(document).on('touchmove.jBox-draggable-' + this.id + ' mousemove.jBox-draggable-' + this.id, function (ev) {
372
+          // Fire onDragStart event when jBox moves
373
+          if (!this.dragging && this.draggingStartX != ev.pageX && this.draggingStartY != ev.pageY) {
374
+            this._fireEvent('onDragStart');
375
+            this.dragging = true;
376
+          }
377
+
378
+          // Adjust position
379
+          this.wrapper.offset({
380
+            top: ev.pageY + pos_y - drg_h,
381
+            left: ev.pageX + pos_x - drg_w
382
+          });
383
+        }.bind(this));
384
+        ev.preventDefault();
385
+
386
+      }.bind(this)).on('touchend mouseup', function () {
387
+        // Remove drag event
388
+        jQuery(document).off('touchmove.jBox-draggable-' + this.id + ' mousemove.jBox-draggable-' + this.id);
389
+
390
+        // Fire onDragEnd event
391
+        this.dragging && this._fireEvent('onDragEnd');
392
+
393
+        // Reset dragging reference
394
+        this.dragging = false;
395
+
396
+        if ((this.type == 'Modal' || this.type == 'Confirm') && this.options.holdPosition) {
397
+          // Drag end captures new position
398
+          var jBoxOffset = jQuery('#' + this.id).offset(),
399
+            pos = {
400
+              x: jBoxOffset.left - jQuery(document).scrollLeft(),
401
+              y: jBoxOffset.top - jQuery(document).scrollTop()
402
+            };
403
+          this.position({position: pos, offset: {x: 0, y: 0}});
404
+        }
405
+      }.bind(this));
406
+
407
+      // Get highest z-index
408
+      if (!this.trueModal) {
409
+        jBox.zIndexMaxDragover = !jBox.zIndexMaxDragover ? this.options.zIndex : Math.max(jBox.zIndexMaxDragover, this.options.zIndex);
410
+      }
411
+
412
+      return this;
413
+    };
414
+
415
+    // Create jBox
416
+
417
+    this._create = function ()
418
+    {
419
+      // Abort if jBox was created already
420
+      if (this.wrapper) return;
421
+
422
+      // Create wrapper
423
+      this.wrapper = jQuery('<div/>', {
424
+        id: this.id,
425
+        'class': 'jBox-wrapper' + (this.type ? ' jBox-' + this.type : '') + (this.options.theme ? ' jBox-' + this.options.theme : '') + (this.options.addClass ? ' ' + this.options.addClass : '')
426
+      }).css({
427
+        position: (this.options.fixed ? 'fixed' : 'absolute'),
428
+        display: 'none',
429
+        opacity: 0,
430
+        zIndex: this.options.zIndex
431
+
432
+        // Save the jBox instance in the wrapper, so you can get access to your jBox when you only have the element
433
+      }).data('jBox', this);
434
+
435
+      // Add mouseleave event, only close jBox when the new target is not the source element
436
+      this.options.closeOnMouseleave && this.wrapper.on('mouseleave', function (ev) {
437
+        !this.source || !(ev.relatedTarget == this.source[0] || jQuery.inArray(this.source[0], jQuery(ev.relatedTarget).parents('*')) !== -1) && this.close();
438
+      }.bind(this));
439
+
440
+      // Add closeOnClick: 'box' events
441
+      (this.options.closeOnClick == 'box') && this.wrapper.on('click tap', function () { this.close({ignoreDelay: true}); }.bind(this));
442
+
443
+      // Create container
444
+      this.container = jQuery('<div class="jBox-container"/>').appendTo(this.wrapper);
445
+
446
+      // Create content
447
+      this.content = jQuery('<div class="jBox-content"/>').appendTo(this.container);
448
+
449
+      // Create footer
450
+      this.options.footer && (this.footer = jQuery('<div class="jBox-footer"/>').append(this.options.footer).appendTo(this.container));
451
+
452
+      // Isolate scrolling
453
+      this.options.isolateScroll && this._isolateScroll(this.content);
454
+
455
+      // Create close button
456
+      if (this.options.closeButton) {
457
+        var closeButtonSVG = this._createSVG('svg', [['viewBox', '0 0 24 24']]);
458
+        closeButtonSVG.appendChild(this._createSVG('path', [['d', 'M22.2,4c0,0,0.5,0.6,0,1.1l-6.8,6.8l6.9,6.9c0.5,0.5,0,1.1,0,1.1L20,22.3c0,0-0.6,0.5-1.1,0L12,15.4l-6.9,6.9c-0.5,0.5-1.1,0-1.1,0L1.7,20c0,0-0.5-0.6,0-1.1L8.6,12L1.7,5.1C1.2,4.6,1.7,4,1.7,4L4,1.7c0,0,0.6-0.5,1.1,0L12,8.5l6.8-6.8c0.5-0.5,1.1,0,1.1,0L22.2,4z']]));
459
+        this.closeButton = jQuery('<div class="jBox-closeButton jBox-noDrag"/>').on('click tap', function (ev) { this.close({ignoreDelay: true}); }.bind(this)).append(closeButtonSVG);
460
+
461
+        // Add close button to jBox container
462
+        if (this.options.closeButton == 'box' || (this.options.closeButton === true && !this.options.overlay && !this.options.title && !this.options.getTitle)) {
463
+          this.wrapper.addClass('jBox-closeButton-box');
464
+          this.closeButton.appendTo(this.container);
465
+        }
466
+      }
467
+
468
+      // Append jBox to DOM
469
+      this.wrapper.appendTo(this.options.appendTo);
470
+
471
+      // Fix adjustDistance if there is a close button in the box
472
+      this.wrapper.find('.jBox-closeButton').length &&  jQuery.each(['top', 'right', 'bottom', 'left'], function (index, pos) {
473
+        this.wrapper.find('.jBox-closeButton').css(pos) && this.wrapper.find('.jBox-closeButton').css(pos) != 'auto' && (this.options.adjustDistance[pos] = Math.max(this.options.adjustDistance[pos], this.options.adjustDistance[pos] + (((parseInt(this.wrapper.find('.jBox-closeButton').css(pos)) || 0) + (parseInt(this.container.css('border-' + pos + '-width')) || 0)) * -1)));
474
+      }.bind(this));
475
+
476
+      // Create pointer
477
+      if (this.options.pointer) {
478
+
479
+        // Get pointer vars and save globally
480
+        this.pointer = {
481
+          position: (this.options.pointTo != 'target') ? this.options.pointTo : this._getOpp(this.outside),
482
+          xy: (this.options.pointTo != 'target') ? this._getXY(this.options.pointTo) : this._getXY(this.outside),
483
+          align: 'center',
484
+          offset: 0
485
+        };
486
+
487
+        this.pointer.element = jQuery('<div class="jBox-pointer jBox-pointer-' + this.pointer.position + '"/>').appendTo(this.wrapper);
488
+        this.pointer.dimensions = {
489
+          x: this.pointer.element.outerWidth(),
490
+          y: this.pointer.element.outerHeight()
491
+        };
492
+
493
+        if (jQuery.type(this.options.pointer) == 'string') {
494
+          var split = this.options.pointer.split(':');
495
+          split[0] && (this.pointer.align = split[0]);
496
+          split[1] && (this.pointer.offset = parseInt(split[1]));
497
+        }
498
+        this.pointer.alignAttribute = (this.pointer.xy == 'x' ? (this.pointer.align == 'bottom' ? 'bottom' : 'top') : (this.pointer.align == 'right' ? 'right' : 'left'));
499
+
500
+        // Set wrapper CSS
501
+        this.wrapper.css('padding-' + this.pointer.position, this.pointer.dimensions[this.pointer.xy]);
502
+
503
+        // Set pointer CSS
504
+        this.pointer.element.css(this.pointer.alignAttribute, (this.pointer.align == 'center' ? '50%' : 0)).css('margin-' + this.pointer.alignAttribute, this.pointer.offset);
505
+        this.pointer.margin = {};
506
+        this.pointer.margin['margin-' + this.pointer.alignAttribute] = this.pointer.offset;
507
+
508
+        // Add a transform to fix centered position
509
+        (this.pointer.align == 'center') && this.pointer.element.css('transform', 'translate(' + (this.pointer.xy == 'y' ? (this.pointer.dimensions.x * -0.5 + 'px') : 0) + ', ' + (this.pointer.xy == 'x' ? (this.pointer.dimensions.y * -0.5 + 'px') : 0) + ')');
510
+
511
+        this.pointer.element.css((this.pointer.xy == 'x' ? 'width' : 'height'), parseInt(this.pointer.dimensions[this.pointer.xy]) + parseInt(this.container.css('border-' + this.pointer.alignAttribute + '-width')));
512
+
513
+        // Add class to wrapper for CSS access
514
+        this.wrapper.addClass('jBox-pointerPosition-' + this.pointer.position);
515
+      }
516
+
517
+      // Set title and content
518
+      this.setContent(this.options.content, true);
519
+      this.setTitle(this.options.title, true);
520
+
521
+      this.options.draggable && this._draggable();
522
+
523
+      // Fire onCreated event
524
+      this._fireEvent('onCreated');
525
+    };
526
+
527
+
528
+    // Create jBox onInit
529
+
530
+    this.options.createOnInit && this._create();
531
+
532
+
533
+    // Attach jBox
534
+
535
+    this.options.attach && this.attach();
536
+
537
+
538
+    // Attach document and window events
539
+
540
+    this._attachEvents = function ()
541
+    {
542
+      // Cancel countdown on mouseenter if delayOnHover
543
+      this.options.delayOnHover && jQuery('#' + this.id).on('mouseenter', function (ev) { this.isHovered = true; }.bind(this));
544
+
545
+      // Resume countdown on mouseleave if delayOnHover
546
+      this.options.delayOnHover && jQuery('#' + this.id).on('mouseleave', function (ev) { this.isHovered = false; }.bind(this));
547
+
548
+      // Positioning events
549
+      if ((this.options.adjustPosition || this.options.reposition) && !this.fixed && this.outside) {
550
+
551
+        // Trigger position events when scrolling
552
+        this.options.adjustTracker && jQuery(window).on('scroll.jBox-' + this.id, function (ev) { this.position(); }.bind(this));
553
+
554
+        // Trigger position events when resizing
555
+        (this.options.adjustPosition || this.options.reposition) && jQuery(window).on('resize.jBox-' + this.id, function (ev) { this.position(); }.bind(this));
556
+      }
557
+
558
+      // Mousemove events
559
+      this.options.target == 'mouse' && jQuery('body').on('mousemove.jBox-' + this.id, function (ev) { this.position({mouseTarget: {top: ev.pageY, left: ev.pageX}}); }.bind(this));
560
+    };
561
+
562
+
563
+    // Detach document and window events
564
+
565
+    this._detachEvents = function ()
566
+    {
567
+      // Closing event: closeOnEsc
568
+      this.options.closeOnEsc && jQuery(document).off('keyup.jBox-' + this.id);
569
+
570
+      // Closing event: closeOnClick
571
+      (this.options.closeOnClick === true || this.options.closeOnClick == 'body') && jQuery(document).off('click.jBox-' + this.id + ' tap.jBox-' + this.id);
572
+
573
+      // Positioning events
574
+      this.options.adjustTracker && jQuery(window).off('scroll.jBox-' + this.id);
575
+      (this.options.adjustPosition || this.options.reposition) && jQuery(window).off('resize.jBox-' + this.id);
576
+
577
+      // Mousemove events
578
+      this.options.target == 'mouse' && jQuery('body').off('mousemove.jBox-' + this.id);
579
+    };
580
+
581
+
582
+    // Show overlay
583
+
584
+    this._showOverlay = function ()
585
+    {
586
+      // Create the overlay if wasn't created already
587
+      if (!this.overlay) {
588
+
589
+        // Create element and append to the element where jBox is appended to
590
+        this.overlay = jQuery('<div id="' + this.id + '-overlay"/>').addClass('jBox-overlay' + (this.type ? ' jBox-overlay-' + this.type : '')).css({
591
+          display: 'none',
592
+          opacity: 0,
593
+          zIndex: this.options.zIndex - 1
594
+        }).appendTo(this.options.appendTo);
595
+
596
+        // Add a class name to the overlay
597
+        this.options.overlayClass && this.overlay.addClass(this.options.overlayClass);
598
+
599
+        // Add close button to overlay
600
+        (this.options.closeButton == 'overlay' || this.options.closeButton === true) && this.overlay.append(this.closeButton);
601
+
602
+        // Add closeOnClick: 'overlay' events
603
+        this.options.closeOnClick == 'overlay' && this.overlay.on('click tap', function () { this.close({ignoreDelay: true}); }.bind(this));
604
+
605
+        // Adjust option adjustDistance if there is a close button in the overlay
606
+        jQuery('#' + this.id + '-overlay .jBox-closeButton').length && (this.options.adjustDistance.top = Math.max(jQuery('#' + this.id + '-overlay .jBox-closeButton').outerHeight(), this.options.adjustDistance.top));
607
+      }
608
+
609
+      // Adjust zIndex
610
+      if (this.adjustZIndexOnOpen === true) {
611
+        this.overlay.css('zIndex', parseInt(this.wrapper.css('zIndex'), 10) - 1);
612
+      }
613
+
614
+      // Abort if overlay is already visible
615
+      if (this.overlay.css('display') == 'block') return;
616
+
617
+      // Show overlay
618
+      this.options.fade ? (this.overlay.stop() && this.overlay.animate({opacity: 1}, {
619
+        queue: false,
620
+        duration: this.options.fade,
621
+        start: function () { this.overlay.css({display: 'block'}); }.bind(this)
622
+      })) : this.overlay.css({display: 'block', opacity: 1});
623
+    };
624
+
625
+
626
+    // Hide overlay
627
+
628
+    this._hideOverlay = function ()
629
+    {
630
+      // Abort if the overlay wasn't created yet
631
+      if (!this.overlay) return;
632
+
633
+      // Hide overlay if no other jBox needs it
634
+      this.options.fade ? (this.overlay.stop() && this.overlay.animate({opacity: 0}, {
635
+        queue: false,
636
+        duration: this.options.fade,
637
+        complete: function () { this.overlay.css({display: 'none'}); }.bind(this)
638
+      })) : this.overlay.css({display: 'none', opacity: 0});
639
+    };
640
+
641
+
642
+    // Get the correct jBox dimensions by moving jBox out of viewport
643
+
644
+    this._exposeDimensions = function ()
645
+    {
646
+      // Move wrapper out of viewport
647
+      this.wrapper.css({
648
+        top: -10000,
649
+        left: -10000,
650
+        right: 'auto',
651
+        bottom: 'auto'
652
+      });
653
+
654
+      // Get jBox dimensions
655
+      var jBoxDimensions = {
656
+        x: this.wrapper.outerWidth(),
657
+        y: this.wrapper.outerHeight()
658
+      };
659
+
660
+      // Reset position to viewport
661
+      this.wrapper.css({
662
+        top: 'auto',
663
+        left: 'auto'
664
+      });
665
+
666
+      return jBoxDimensions;
667
+    };
668
+
669
+
670
+    // Generate CSS for animations and append to header
671
+
672
+    this._generateAnimationCSS = function ()
673
+    {
674
+      // Get open and close animations if none provided
675
+      (jQuery.type(this.options.animation) != 'object') && (this.options.animation = {
676
+        pulse: {open: 'pulse', close: 'zoomOut'},
677
+        zoomIn: {open: 'zoomIn', close: 'zoomIn'},
678
+        zoomOut: {open: 'zoomOut', close: 'zoomOut'},
679
+        move: {open: 'move', close: 'move'},
680
+        slide: {open: 'slide', close: 'slide'},
681
+        flip: {open: 'flip', close: 'flip'},
682
+        tada: {open: 'tada', close: 'zoomOut'}
683
+      }[this.options.animation]);
684
+
685
+      // Abort if animation not found
686
+      if (!this.options.animation) return null;
687
+
688
+      // Get direction var
689
+      this.options.animation.open && (this.options.animation.open = this.options.animation.open.split(':'));
690
+      this.options.animation.close && (this.options.animation.close = this.options.animation.close.split(':'));
691
+      this.options.animation.openDirection = this.options.animation.open[1] ? this.options.animation.open[1] : null;
692
+      this.options.animation.closeDirection = this.options.animation.close[1] ? this.options.animation.close[1] : null;
693
+      this.options.animation.open && (this.options.animation.open = this.options.animation.open[0]);
694
+      this.options.animation.close && (this.options.animation.close = this.options.animation.close[0]);
695
+
696
+      // Add 'Open' and 'Close' to animation names
697
+      this.options.animation.open && (this.options.animation.open += 'Open');
698
+      this.options.animation.close && (this.options.animation.close += 'Close');
699
+
700
+      // All animations
701
+      var animations = {
702
+        pulse: {
703
+          duration: 350,
704
+          css: [['0%', 'scale(1)'], ['50%', 'scale(1.1)'], ['100%', 'scale(1)']]
705
+        },
706
+        zoomInOpen: {
707
+          duration: (this.options.fade || 180),
708
+          css: [['0%', 'scale(0.9)'], ['100%', 'scale(1)']]
709
+        },
710
+        zoomInClose: {
711
+          duration: (this.options.fade || 180),
712
+          css: [['0%', 'scale(1)'], ['100%', 'scale(0.9)']]
713
+        },
714
+        zoomOutOpen: {
715
+          duration: (this.options.fade || 180),
716
+          css: [['0%', 'scale(1.1)'], ['100%', 'scale(1)']]
717
+        },
718
+        zoomOutClose: {
719
+          duration: (this.options.fade || 180),
720
+          css: [['0%', 'scale(1)'], ['100%', 'scale(1.1)']]
721
+        },
722
+        moveOpen: {
723
+          duration: (this.options.fade || 180),
724
+          positions: {top: {'0%': -12}, right: {'0%': 12}, bottom: {'0%': 12}, left: {'0%': -12}},
725
+          css: [['0%', 'translate%XY(%Vpx)'], ['100%', 'translate%XY(0px)']]
726
+        },
727
+        moveClose: {
728
+          duration: (this.options.fade || 180),
729
+          timing: 'ease-in',
730
+          positions: {top: {'100%': -12}, right: {'100%': 12}, bottom: {'100%': 12}, left: {'100%': -12}},
731
+          css: [['0%', 'translate%XY(0px)'], ['100%', 'translate%XY(%Vpx)']]
732
+        },
733
+        slideOpen: {
734
+          duration: 400,
735
+          positions: {top: {'0%': -400}, right: {'0%': 400}, bottom: {'0%': 400}, left: {'0%': -400}},
736
+          css: [['0%', 'translate%XY(%Vpx)'], ['100%', 'translate%XY(0px)']]
737
+        },
738
+        slideClose: {
739
+          duration: 400,
740
+          timing: 'ease-in',
741
+          positions: {top: {'100%': -400}, right: {'100%': 400}, bottom: {'100%': 400}, left: {'100%': -400}},
742
+          css: [['0%', 'translate%XY(0px)'], ['100%', 'translate%XY(%Vpx)']]
743
+        },
744
+        flipOpen: {
745
+          duration: 600,
746
+          css: [['0%', 'perspective(400px) rotateX(90deg)'], ['40%', 'perspective(400px) rotateX(-15deg)'], ['70%', 'perspective(400px) rotateX(15deg)'], ['100%', 'perspective(400px) rotateX(0deg)']]
747
+        },
748
+        flipClose: {
749
+          duration: (this.options.fade || 300),
750
+          css: [['0%', 'perspective(400px) rotateX(0deg)'], ['100%', 'perspective(400px) rotateX(90deg)']]
751
+        },
752
+        tada: {
753
+          duration: 800,
754
+          css: [['0%', 'scale(1)'], ['10%, 20%', 'scale(0.9) rotate(-3deg)'], ['30%, 50%, 70%, 90%', 'scale(1.1) rotate(3deg)'], ['40%, 60%, 80%', 'scale(1.1) rotate(-3deg)'], ['100%', 'scale(1) rotate(0)']]
755
+        }
756
+      };
757
+
758
+      // Set Open and Close names for standalone animations
759
+      jQuery.each(['pulse', 'tada'], function (index, item) { animations[item + 'Open'] = animations[item + 'Close'] = animations[item]; });
760
+
761
+      // Function to generate the CSS for the keyframes
762
+      var generateKeyframeCSS = function (ev, position)
763
+      {
764
+        // Generate keyframes CSS
765
+        var keyframe_css = '@keyframes jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + (position ? '-' + position : '') + ' {';
766
+        jQuery.each(animations[this.options.animation[ev]].css, function (index, item) {
767
+          var translate = position ? item[1].replace('%XY', this._getXY(position).toUpperCase()) : item[1];
768
+          animations[this.options.animation[ev]].positions && (translate = translate.replace('%V', animations[this.options.animation[ev]].positions[position][item[0]]));
769
+          keyframe_css += item[0] + ' {transform:' + translate + ';}';
770
+        }.bind(this));
771
+        keyframe_css += '}';
772
+
773
+        // Generate class CSS
774
+        keyframe_css += '.jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + (position ? '-' + position : '') + ' {';
775
+        keyframe_css += 'animation-duration: ' + animations[this.options.animation[ev]].duration + 'ms;';
776
+        keyframe_css += 'animation-name: jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + (position ? '-' + position : '') + ';';
777
+        keyframe_css += animations[this.options.animation[ev]].timing ? ('animation-timing-function: ' + animations[this.options.animation[ev]].timing + ';') : '';
778
+        keyframe_css += '}';
779
+
780
+        return keyframe_css;
781
+      }.bind(this);
782
+
783
+      // Generate css for each event and positions
784
+      this._animationCSS = '';
785
+      jQuery.each(['open', 'close'], function (index, ev)
786
+      {
787
+        // No CSS needed for closing with no fade
788
+        if (!this.options.animation[ev] || !animations[this.options.animation[ev]] || (ev == 'close' && !this.options.fade)) return '';
789
+
790
+        // Generate CSS
791
+        animations[this.options.animation[ev]].positions ?
792
+          jQuery.each(['top', 'right', 'bottom', 'left'], function (index2, position) { this._animationCSS += generateKeyframeCSS(ev, position); }.bind(this)) :
793
+          this._animationCSS += generateKeyframeCSS(ev);
794
+      }.bind(this));
795
+
796
+    };
797
+
798
+
799
+    // Add css for animations
800
+
801
+    this.options.animation && this._generateAnimationCSS();
802
+
803
+
804
+    // Block body clicks for 10ms to prevent extra event triggering
805
+
806
+    this._blockBodyClick = function ()
807
+    {
808
+      this.blockBodyClick = true;
809
+      setTimeout(function () { this.blockBodyClick = false; }.bind(this), 10);
810
+    };
811
+
812
+
813
+    // Animations
814
+
815
+    this._animate = function (ev)
816
+    {
817
+      // The event which triggers the animation
818
+      !ev && (ev = this.isOpen ? 'open' : 'close');
819
+
820
+      // Don't animate when closing with no fade duration
821
+      if (!this.options.fade && ev == 'close') return null;
822
+
823
+      // Get the current position, use opposite if jBox is flipped
824
+      var animationDirection = (this.options.animation[ev + 'Direction'] || ((this.align != 'center') ? this.align : this.options.attributes.x));
825
+      this.flipped && this._getXY(animationDirection) == (this._getXY(this.align)) && (animationDirection = this._getOpp(animationDirection));
826
+
827
+      // Add event and position classes
828
+      var classnames = 'jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + ' jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + '-' + animationDirection;
829
+      this.wrapper.addClass(classnames);
830
+
831
+      // Get duration of animation
832
+      var animationDuration = parseFloat(this.wrapper.css('animation-duration')) * 1000;
833
+      ev == 'close' && (animationDuration = Math.min(animationDuration, this.options.fade));
834
+
835
+      // Remove animation classes when animation is finished
836
+      setTimeout(function () { this.wrapper.removeClass(classnames); }.bind(this), animationDuration);
837
+    };
838
+
839
+
840
+    // Abort an animation
841
+
842
+    this._abortAnimation = function ()
843
+    {
844
+      // Remove all animation classes
845
+      var classes = this.wrapper.attr('class').split(' ').filter(function (c) {
846
+        return c.lastIndexOf('jBox-' + this.id + '-animation', 0) !== 0;
847
+      }.bind(this));
848
+      this.wrapper.attr('class', classes.join(' '));
849
+    };
850
+
851
+
852
+    // Adjust dimensions when browser is resized
853
+
854
+    if (this.options.responsiveWidth || this.options.responsiveHeight)
855
+    {
856
+      // Responsive positioning overrides options adjustPosition and reposition
857
+      // TODO: Only add this resize event when the other one from adjustPosition and reposition was not set
858
+      jQuery(window).on('resize.responsivejBox-' + this.id, function (ev) { if (this.isOpen) { this.position(); } }.bind(this));
859
+    }
860
+
861
+
862
+    // Fix audio options
863
+
864
+    jQuery.type(this.options.preloadAudio) === 'string' && (this.options.preloadAudio = [this.options.preloadAudio]);
865
+    jQuery.type(this.options.audio) === 'string' && (this.options.audio = {open: this.options.audio});
866
+    jQuery.type(this.options.volume) === 'number' && (this.options.volume = {open: this.options.volume, close: this.options.volume});
867
+
868
+    if (this.options.preloadAudio === true && this.options.audio) {
869
+      this.options.preloadAudio = [];
870
+      jQuery.each(this.options.audio, function (index, url) {
871
+        this.options.preloadAudio.push(url + '.mp3');
872
+        this.options.preloadAudio.push(url + '.ogg');
873
+      }.bind(this));
874
+    }
875
+
876
+
877
+    // Preload audio files
878
+
879
+    this.options.preloadAudio.length && jQuery.each(this.options.preloadAudio, function (index, url) {
880
+      var audio = new Audio();
881
+      audio.src = url;
882
+      audio.preload = 'auto';
883
+    });
884
+
885
+
886
+    // Fire onInit event
887
+
888
+    this._fireEvent('onInit');
889
+
890
+
891
+    return this;
892
+  };
893
+
894
+
895
+  // Attach jBox to elements
896
+
897
+  jBox.prototype.attach = function (elements, trigger)
898
+  {
899
+    // Get elements from options if none passed
900
+    !elements && (elements = this.options.attach);
901
+
902
+    // Convert selectors to jQuery objects
903
+    jQuery.type(elements) == 'string' && (elements = jQuery(elements));
904
+
905
+    // Get trigger event from options if not passed
906
+    !trigger && (trigger = this.options.trigger);
907
+
908
+    // Loop through elements and attach jBox
909
+    elements && elements.length && jQuery.each(elements, function (index, el) {
910
+      el = jQuery(el);
911
+
912
+      // Only attach if the element wasn't attached to this jBox already
913
+      if (!el.data('jBox-attached-' + this.id)) {
914
+
915
+        // Remove title attribute and store content on element
916
+        (this.options.getContent == 'title' && el.attr('title') != undefined) && el.data('jBox-getContent', el.attr('title')).removeAttr('title');
917
+
918
+        // Add Element to collection
919
+        this.attachedElements || (this.attachedElements = []);
920
+        this.attachedElements.push(el[0]);
921
+
922
+        // Add click or mouseenter event, click events can prevent default as well
923
+        el.on(trigger + '.jBox-attach-' + this.id, function (ev)
924
+        {
925
+          // Clear timer
926
+          this.timer && clearTimeout(this.timer);
927
+
928
+          // Block opening when jbox is open and the source element is triggering
929
+          if (trigger == 'mouseenter' && this.isOpen && this.source[0] == el[0]) return;
930
+
931
+          // Only close jBox if you click the current target element, otherwise open at new target
932
+          if (this.isOpen && this.source && this.source[0] != el[0]) var forceOpen = true;
933
+
934
+          // Set new source element
935
+          this.source = el;
936
+
937
+          // Set new target
938
+          !this.options.target && (this.target = el);
939
+
940
+          // Prevent default action on click
941
+          trigger == 'click' && this.options.preventDefault && ev.preventDefault();
942
+
943
+          // Toggle or open jBox
944
+          this[trigger == 'click' && !forceOpen ? 'toggle' : 'open']();
945
+
946
+        }.bind(this));
947
+
948
+        // Add close event for trigger event mouseenter
949
+        (this.options.trigger == 'mouseenter') && el.on('mouseleave', function (ev)
950
+        {
951
+          // Abort if jBox wasn't created yet
952
+          if (!this.wrapper) return null;
953
+
954
+          // If we have set closeOnMouseleave, do not close jBox when leaving attached element and mouse is over jBox
955
+          if (!this.options.closeOnMouseleave || !(ev.relatedTarget == this.wrapper[0] || jQuery(ev.relatedTarget).parents('#' + this.id).length)) this.close();
956
+        }.bind(this));
957
+
958
+        // Store
959
+        el.data('jBox-attached-' + this.id, trigger);
960
+
961
+        // Fire onAttach event
962
+        this._fireEvent('onAttach', el);
963
+      }
964
+
965
+    }.bind(this));
966
+
967
+    return this;
968
+  };
969
+
970
+
971
+  // Detach jBox from elements
972
+
973
+  jBox.prototype.detach = function (elements)
974
+  {
975
+    // Get elements from stores elements if none passed
976
+    !elements && (elements = this.attachedElements || []);
977
+
978
+    elements && elements.length && jQuery.each(elements, function (index, el) {
979
+      el = jQuery(el);
980
+
981
+      // Remove events
982
+      if (el.data('jBox-attached-' + this.id)) {
983
+        el.off(el.data('jBox-attached-' + this.id) + '.jBox-attach-' + this.id);
984
+        el.data('jBox-attached-' + this.id, null);
985
+      }
986
+      // Remove element from collection
987
+      this.attachedElements = jQuery.grep(this.attachedElements, function (value) {
988
+        return value != el[0];
989
+      });
990
+    }.bind(this));
991
+
992
+    return this;
993
+  };
994
+
995
+
996
+  // Set title
997
+
998
+  jBox.prototype.setTitle = function (title, ignore_positioning)
999
+  {
1000
+    // Abort if title to set
1001
+    if (title == null || title == undefined) return this;
1002
+
1003
+    // Create jBox if it wasn't created already
1004
+    !this.wrapper && this._create();
1005
+
1006
+    // Get the width and height of wrapper, only if they change we need to reposition
1007
+    var wrapperHeight = this.wrapper.outerHeight();
1008
+    var wrapperWidth = this.wrapper.outerWidth();
1009
+
1010
+    // Create title elements if they weren't created already
1011
+    if (!this.title) {
1012
+      this.titleContainer = jQuery('<div class="jBox-title"/>');
1013
+      this.title = jQuery('<div/>').appendTo(this.titleContainer);
1014
+      if (this.options.closeButton == 'title' || (this.options.closeButton === true && !this.options.overlay)) {
1015
+        this.wrapper.addClass('jBox-closeButton-title');
1016
+        this.closeButton.appendTo(this.titleContainer);
1017
+      }
1018
+      this.titleContainer.insertBefore(this.content);
1019
+      this._setTitleWidth();
1020
+    }
1021
+
1022
+    // Add or remove wrapper class
1023
+    this.wrapper[title ? 'addClass' : 'removeClass']('jBox-hasTitle');
1024
+
1025
+    // Set title html
1026
+    this.title.html(title);
1027
+
1028
+    // Adjust width of title
1029
+    wrapperWidth != this.wrapper.outerWidth() && this._setTitleWidth();
1030
+
1031
+    // Make jBox draggable
1032
+    this.options.draggable && this._draggable();
1033
+
1034
+    // Reposition if dimensions changed
1035
+    !ignore_positioning && this.options.repositionOnContent && (wrapperHeight != this.wrapper.outerHeight() || wrapperWidth != this.wrapper.outerWidth()) && this.position();
1036
+
1037
+    return this;
1038
+  };
1039
+
1040
+
1041
+  // Set content
1042
+
1043
+  jBox.prototype.setContent = function (content, ignore_positioning)
1044
+  {
1045
+    // Abort if no content to set
1046
+    if (content == null || content == undefined) return this;
1047
+
1048
+    // Create jBox if it wasn't created already
1049
+    !this.wrapper && this._create();
1050
+
1051
+    // Get the width and height of wrapper, only if they change we need to reposition
1052
+    var wrapperHeight = this.wrapper.outerHeight();
1053
+    var wrapperWidth = this.wrapper.outerWidth();
1054
+
1055
+    // Move all appended containers to body
1056
+    this.content.children('[data-jbox-content-appended]').appendTo('body').css({display: 'none'});
1057
+
1058
+    // Set the new content
1059
+    switch (jQuery.type(content)) {
1060
+      case 'string':
1061
+        this.content.html(content);
1062
+        break;
1063
+      case 'object':
1064
+        if (content && (content instanceof jQuery || content.constructor.prototype.jquery)) {
1065
+          this.content.html('');
1066
+          content.attr('data-jbox-content-appended', 1).appendTo(this.content).css({display: 'block'});
1067
+        } else {
1068
+          this.content.html(JSON.stringify(content));
1069
+        }
1070
+        break;
1071
+     }
1072
+
1073
+    // Adjust title width
1074
+    wrapperWidth != this.wrapper.outerWidth() && this._setTitleWidth();
1075
+
1076
+    // Make jBox draggable
1077
+    this.options.draggable && this._draggable();
1078
+
1079
+    // Reposition if dimensions changed
1080
+    !ignore_positioning && this.options.repositionOnContent && (wrapperHeight != this.wrapper.outerHeight() || wrapperWidth != this.wrapper.outerWidth()) && this.position();
1081
+
1082
+    return this;
1083
+  };
1084
+
1085
+
1086
+  // Set jBox dimensions
1087
+
1088
+  jBox.prototype.setDimensions = function (type, value, pos)
1089
+  {
1090
+    // Create jBox if it wasn't created already
1091
+    !this.wrapper && this._create();
1092
+
1093
+    // Default value is 'auto'
1094
+    value == undefined && (value = 'auto');
1095
+
1096
+    // Set CSS of content and title
1097
+    this.content.css(type, this._getInt(value));
1098
+
1099
+    // Adjust title width
1100
+    type == 'width' && this._setTitleWidth();
1101
+
1102
+    // Update options
1103
+    this.options[type] = value;
1104
+
1105
+    // Reposition by default
1106
+    (pos == undefined || pos) && this.position();
1107
+  };
1108
+
1109
+
1110
+  // Set jBox width or height
1111
+
1112
+  jBox.prototype.setWidth = function (value, pos) { this.setDimensions('width', value, pos); };
1113
+  jBox.prototype.setHeight = function (value, pos) { this.setDimensions('height', value, pos); };
1114
+
1115
+
1116
+  // Position jBox
1117
+
1118
+  jBox.prototype.position = function (options)
1119
+  {
1120
+    // Options are required
1121
+    !options && (options = {});
1122
+
1123
+    // Combine passed options with jBox options
1124
+    options = jQuery.extend(true, this.options, options);
1125
+
1126
+    // Get the target
1127
+    this.target = options.target || this.target || jQuery(window);
1128
+
1129
+    // Make sure target is a jQuery element
1130
+    !(this.target instanceof jQuery || this.target == 'mouse') && (this.target = jQuery(this.target));
1131
+
1132
+    // Abort if target is missing
1133
+    if (!this.target.length) return this;
1134
+
1135
+    // Reset content css to get original dimensions
1136
+    this.content.css({
1137
+      width: this._getInt(options.width, 'width'),
1138
+      height: this._getInt(options.height, 'height'),
1139
+      minWidth: this._getInt(options.minWidth, 'width'),
1140
+      minHeight: this._getInt(options.minHeight, 'height'),
1141
+      maxWidth: this._getInt(options.maxWidth, 'width'),
1142
+      maxHeight: this._getInt(options.maxHeight, 'height'),
1143
+    });
1144
+
1145
+    // Reset width of title
1146
+    this._setTitleWidth();
1147
+
1148
+    // Get jBox dimensions
1149
+    var jBoxDimensions = this._exposeDimensions();
1150
+
1151
+    // Check if target has fixed position, store in elements data
1152
+    this.target != 'mouse' && !this.target.data('jBox-' + this.id + '-fixed') && this.target.data('jBox-' + this.id + '-fixed', (this.target[0] != jQuery(window)[0] && (this.target.css('position') == 'fixed' || this.target.parents().filter(function () { return jQuery(this).css('position') == 'fixed'; }).length > 0)) ? 'fixed' : 'static');
1153
+
1154
+    // Get the window dimensions
1155
+    var windowDimensions = {
1156
+      x: jQuery(window).outerWidth(),
1157
+      y: jQuery(window).outerHeight(),
1158
+      top: (options.fixed && this.target.data('jBox-' + this.id + '-fixed') ? 0 : jQuery(window).scrollTop()),
1159
+      left: (options.fixed && this.target.data('jBox-' + this.id + '-fixed') ? 0 : jQuery(window).scrollLeft())
1160
+    };
1161
+    windowDimensions.bottom = windowDimensions.top + windowDimensions.y;
1162
+    windowDimensions.right = windowDimensions.left + windowDimensions.x;
1163
+
1164
+    // Get target offset
1165
+    try { var targetOffset = this.target.offset(); } catch (e) { var targetOffset = {top: 0, left: 0}; };
1166
+
1167
+    // When the target is fixed and jBox is fixed, remove scroll offset
1168
+    if (this.target != 'mouse' && this.target.data('jBox-' + this.id + '-fixed') == 'fixed' && options.fixed) {
1169
+      targetOffset.top = targetOffset.top - jQuery(window).scrollTop();
1170
+      targetOffset.left = targetOffset.left - jQuery(window).scrollLeft();
1171
+    }
1172
+
1173
+    // Get target dimensions
1174
+    var targetDimensions = {
1175
+      x: this.target == 'mouse' ? 12 : this.target.outerWidth(),
1176
+      y: this.target == 'mouse' ? 20 : this.target.outerHeight(),
1177
+      top: this.target == 'mouse' && options.mouseTarget ? options.mouseTarget.top : (targetOffset ? targetOffset.top : 0),
1178
+      left: this.target == 'mouse' && options.mouseTarget ? options.mouseTarget.left : (targetOffset ? targetOffset.left : 0)
1179
+    };
1180
+
1181
+    // Check if jBox is outside
1182
+    var outside = options.outside && !(options.position.x == 'center' && options.position.y == 'center');
1183
+
1184
+    // Get the available space on all sides
1185
+    var availableSpace = {
1186
+      x: windowDimensions.x - options.adjustDistance.left - options.adjustDistance.right, // TODO: substract position.x when they are numbers
1187
+      y: windowDimensions.y - options.adjustDistance.top - options.adjustDistance.bottom, // TODO: substract position.x when they are numbers
1188
+      left: !outside ? 0 : (targetDimensions.left - jQuery(window).scrollLeft() - options.adjustDistance.left),
1189
+      right: !outside ? 0 : (windowDimensions.x - targetDimensions.left + jQuery(window).scrollLeft() - targetDimensions.x - options.adjustDistance.right),
1190
+      top: !outside ? 0 : (targetDimensions.top - jQuery(window).scrollTop() - this.options.adjustDistance.top),
1191
+      bottom: !outside ? 0 : (windowDimensions.y - targetDimensions.top + jQuery(window).scrollTop() - targetDimensions.y - options.adjustDistance.bottom),
1192
+    };
1193
+
1194
+    // Get the default outside position, check if box will be flipped
1195
+    var jBoxOutsidePosition = {
1196
+      x: (options.outside == 'x' || options.outside == 'xy') && jQuery.type(options.position.x) != 'number' ? options.position.x : null,
1197
+      y: (options.outside == 'y' || options.outside == 'xy') && jQuery.type(options.position.y) != 'number' ? options.position.y : null
1198
+    };
1199
+    var flip = {x: false, y: false};
1200
+    (jBoxOutsidePosition.x && jBoxDimensions.x > availableSpace[jBoxOutsidePosition.x] && availableSpace[this._getOpp(jBoxOutsidePosition.x)] > availableSpace[jBoxOutsidePosition.x]) && (jBoxOutsidePosition.x = this._getOpp(jBoxOutsidePosition.x)) && (flip.x = true);
1201
+    (jBoxOutsidePosition.y && jBoxDimensions.y > availableSpace[jBoxOutsidePosition.y] && availableSpace[this._getOpp(jBoxOutsidePosition.y)] > availableSpace[jBoxOutsidePosition.y]) && (jBoxOutsidePosition.y = this._getOpp(jBoxOutsidePosition.y)) && (flip.y = true);
1202
+
1203
+    // Adjust responsive dimensions
1204
+    if (options.responsiveWidth || options.responsiveHeight) {
1205
+
1206
+      // Adjust width and height according to default outside position
1207
+      var adjustResponsiveWidth = function ()
1208
+      {
1209
+        if (options.responsiveWidth && jBoxDimensions.x > availableSpace[jBoxOutsidePosition.x || 'x']) {
1210
+          var contentWidth = availableSpace[jBoxOutsidePosition.x || 'x'] - (this.pointer && outside && options.outside == 'x' ? this.pointer.dimensions.x : 0) - parseInt(this.container.css('border-left-width')) - parseInt(this.container.css('border-right-width'));
1211
+          this.content.css({
1212
+            width: contentWidth > this.options.responsiveMinWidth ? contentWidth : null,
1213
+            minWidth: contentWidth < parseInt(this.content.css('minWidth')) ? 0 : null
1214
+          });
1215
+          this._setTitleWidth();
1216
+        }
1217
+        jBoxDimensions = this._exposeDimensions();
1218
+
1219
+      }.bind(this);
1220
+      options.responsiveWidth && adjustResponsiveWidth();
1221
+
1222
+      // After adjusting width, check if jBox will be flipped for y
1223
+      options.responsiveWidth && !flip.y && (jBoxOutsidePosition.y && jBoxDimensions.y > availableSpace[jBoxOutsidePosition.y] && availableSpace[this._getOpp(jBoxOutsidePosition.y)] > availableSpace[jBoxOutsidePosition.y]) && (jBoxOutsidePosition.y = this._getOpp(jBoxOutsidePosition.y)) && (flip.y = true);
1224
+
1225
+      // Adjust width and height according to default outside position
1226
+      var adjustResponsiveHeight = function ()
1227
+      {
1228
+        if (options.responsiveHeight && jBoxDimensions.y > availableSpace[jBoxOutsidePosition.y || 'y']) {
1229
+
1230
+          // Expose wrapper to get correct title height
1231
+          var exposeTitleFooterHeight = function () {
1232
+            if (!this.titleContainer && !this.footer) return 0;
1233
+            if (this.wrapper.css('display') == 'none') {
1234
+              this.wrapper.css('display', 'block');
1235
+              var height = (this.titleContainer ? this.titleContainer.outerHeight() : 0) + (this.footer ? this.footer.outerHeight() : 0);
1236
+              this.wrapper.css('display', 'none');
1237
+            } else {
1238
+              var height = (this.titleContainer ? this.titleContainer.outerHeight() : 0) + (this.footer ? this.footer.outerHeight() : 0);
1239
+            }
1240
+            return height || 0;
1241
+          }.bind(this);
1242
+
1243
+          var contentHeight = availableSpace[jBoxOutsidePosition.y || 'y'] - (this.pointer && outside && options.outside == 'y' ? this.pointer.dimensions.y : 0) - exposeTitleFooterHeight() - parseInt(this.container.css('border-top-width')) - parseInt(this.container.css('border-bottom-width'));
1244
+          this.content.css({height: contentHeight > this.options.responsiveMinHeight ? contentHeight : null});
1245
+          this._setTitleWidth();
1246
+        }
1247
+        jBoxDimensions = this._exposeDimensions();
1248
+
1249
+      }.bind(this);
1250
+      options.responsiveHeight && adjustResponsiveHeight();
1251
+
1252
+      // After adjusting height, check if jBox will be flipped for x
1253
+      options.responsiveHeight && !flip.x && (jBoxOutsidePosition.x && jBoxDimensions.x > availableSpace[jBoxOutsidePosition.x] && availableSpace[this._getOpp(jBoxOutsidePosition.x)] > availableSpace[jBoxOutsidePosition.x]) && (jBoxOutsidePosition.x = this._getOpp(jBoxOutsidePosition.x)) && (flip.x = true);
1254
+
1255
+      // Adjust width and height if jBox will be flipped
1256
+      if (options.adjustPosition && options.adjustPosition != 'move') {
1257
+        flip.x && adjustResponsiveWidth();
1258
+        flip.y && adjustResponsiveHeight();
1259
+      }
1260
+    }
1261
+
1262
+    // Store new positioning vars in local var
1263
+    var pos = {};
1264
+
1265
+    // Calculate positions
1266
+    var setPosition = function (p)
1267
+    {
1268
+      // Set number positions
1269
+      if (jQuery.type(options.position[p]) == 'number') {
1270
+        pos[options.attributes[p]] = options.position[p];
1271
+        return;
1272
+      }
1273
+
1274
+      // We have a target, so use 'left' or 'top' as attributes
1275
+      var a = options.attributes[p] = (p == 'x' ? 'left' : 'top');
1276
+
1277
+      // Start at target position
1278
+      pos[a] = targetDimensions[a];
1279
+
1280
+      // Set centered position
1281
+      if (options.position[p] == 'center') {
1282
+        pos[a] += Math.ceil((targetDimensions[p] - jBoxDimensions[p]) / 2);
1283
+
1284
+        // If the target is the window, adjust centered position depending on adjustDistance
1285
+        (this.target != 'mouse' && this.target[0] && this.target[0] == jQuery(window)[0]) && (pos[a] += (options.adjustDistance[a] - options.adjustDistance[this._getOpp(a)]) * 0.5);
1286
+        return;
1287
+      }
1288
+
1289
+      // Move inside
1290
+      (a != options.position[p]) && (pos[a] += targetDimensions[p] - jBoxDimensions[p]);
1291
+
1292
+      // Move outside
1293
+      (options.outside == p || options.outside == 'xy') && (pos[a] += jBoxDimensions[p] * (a != options.position[p] ? 1 : -1));
1294
+
1295
+    }.bind(this);
1296
+
1297
+    // Set position including offset
1298
+    setPosition('x');
1299
+    setPosition('y');
1300
+
1301
+    // Adjust position depending on pointer align
1302
+    if (this.pointer && options.pointTo == 'target' && jQuery.type(options.position.x) != 'number' && jQuery.type(options.position.y) != 'number') {
1303
+
1304
+      var adjustWrapper = 0;
1305
+
1306
+      // Where is the pointer aligned? Add or substract accordingly
1307
+      switch (this.pointer.align) {
1308
+        case 'center':
1309
+        if (options.position[this._getOpp(options.outside)] != 'center') {
1310
+          adjustWrapper += (jBoxDimensions[this._getOpp(options.outside)] / 2);
1311
+        }
1312
+        break;
1313
+        default:
1314
+        switch (options.position[this._getOpp(options.outside)]) {
1315
+          case 'center':
1316
+            adjustWrapper += ((jBoxDimensions[this._getOpp(options.outside)] / 2) - (this.pointer.dimensions[this._getOpp(options.outside)] / 2)) * (this.pointer.align == this._getTL(this.pointer.align) ? 1 : -1);
1317
+          break;
1318
+          default:
1319
+            adjustWrapper += (this.pointer.align != options.position[this._getOpp(options.outside)]) ?
1320
+
1321
+            // If pointer align is different to position align
1322
+            (this.dimensions[this._getOpp(options.outside)] * (jQuery.inArray(this.pointer.align, ['top', 'left']) !== -1 ? 1 : -1)) + ((this.pointer.dimensions[this._getOpp(options.outside)] / 2) * (jQuery.inArray(this.pointer.align, ['top', 'left']) !== -1 ? -1 : 1)) :
1323
+
1324
+            // If pointer align is same as position align
1325
+            (this.pointer.dimensions[this._getOpp(options.outside)] / 2) * (jQuery.inArray(this.pointer.align, ['top', 'left']) !== -1 ? 1 : -1);
1326
+          break;
1327
+        }
1328
+        break;
1329
+      }
1330
+
1331
+      adjustWrapper *= (options.position[this._getOpp(options.outside)] == this.pointer.alignAttribute ? -1 : 1);
1332
+      adjustWrapper += this.pointer.offset * (this.pointer.align == this._getOpp(this._getTL(this.pointer.align)) ? 1 : -1);
1333
+
1334
+      pos[this._getTL(this._getOpp(this.pointer.xy))] += adjustWrapper;
1335
+    }
1336
+
1337
+    // Add final offset
1338
+    pos[options.attributes.x] += options.offset.x;
1339
+    pos[options.attributes.y] += options.offset.y;
1340
+
1341
+    // Set CSS
1342
+    this.wrapper.css(pos);
1343
+
1344
+    // Adjust position
1345
+    if (options.adjustPosition) {
1346
+
1347
+      // Reset cached pointer position
1348
+      if (this.positionAdjusted) {
1349
+        this.pointer && this.wrapper.css('padding', 0).css('padding-' + this._getOpp(this.outside), this.pointer.dimensions[this._getXY(this.outside)]).removeClass('jBox-pointerPosition-' + this._getOpp(this.pointer.position)).addClass('jBox-pointerPosition-' + this.pointer.position);
1350
+        this.pointer && this.pointer.element.attr('class', 'jBox-pointer jBox-pointer-' + this._getOpp(this.outside)).css(this.pointer.margin);
1351
+        this.positionAdjusted = false;
1352
+        this.flipped = false;
1353
+      }
1354
+
1355
+      // Find out where the jBox is out of view area
1356
+      var outYT = (windowDimensions.top > pos.top - (options.adjustDistance.top || 0)),
1357
+        outXR = (windowDimensions.right < pos.left + jBoxDimensions.x + (options.adjustDistance.right || 0)),
1358
+        outYB = (windowDimensions.bottom < pos.top + jBoxDimensions.y + (options.adjustDistance.bottom || 0)),
1359
+        outXL = (windowDimensions.left > pos.left - (options.adjustDistance.left || 0)),
1360
+        outX = outXL ? 'left' : (outXR ? 'right' : null),
1361
+        outY = outYT ? 'top' : (outYB ? 'bottom' : null),
1362
+        out = outX || outY;
1363
+
1364
+      // Only continue if jBox is out of view area
1365
+      if (out) {
1366
+
1367
+        if ((this.type == 'Modal' || this.type == 'Confirm')
1368
+          && jQuery.type(this.options.position.x) == 'number'
1369
+          && jQuery.type(this.options.position.y) == 'number'
1370
+        ) {
1371
+          var diffX = 0, diffY = 0;
1372
+          if (this.options.holdPosition) {
1373
+
1374
+            // Adjust left or right
1375
+            if (outXL) {
1376
+              diffX = windowDimensions.left - (pos.left - (options.adjustDistance.left || 0));
1377
+            } else if (outXR) {
1378
+              diffX = windowDimensions.right - (pos.left + jBoxDimensions.x + (options.adjustDistance.right || 0));
1379
+            }
1380
+
1381
+            // Adjust top or bottom
1382
+            if (outYT) {
1383
+              diffY = windowDimensions.top - (pos.top - (options.adjustDistance.top || 0));
1384
+            } else if (outYB) {
1385
+              diffY = windowDimensions.bottom - (pos.top + jBoxDimensions.y + (options.adjustDistance.bottom || 0));
1386
+            }
1387
+
1388
+            this.options.position.x = Math.max(windowDimensions.top, this.options.position.x + diffX);
1389
+            this.options.position.y = Math.max(windowDimensions.left, this.options.position.y + diffY);
1390
+
1391
+            setPosition('x');
1392
+            setPosition('y');
1393
+            this.wrapper.css(pos);
1394
+          }
1395
+          // Fire onPosition event
1396
+          this._fireEvent('onPosition');
1397
+
1398
+          return this;
1399
+        }
1400
+
1401
+        // Function to flip position
1402
+        if (options.adjustPosition === true || options.adjustPosition === 'flip') {
1403
+          var flipJBox = function (xy) {
1404
+            this.wrapper.css(this._getTL(xy), pos[this._getTL(xy)] + ((jBoxDimensions[this._getXY(xy)] + (options.offset[this._getXY(xy)] * (xy == 'top' || xy == 'left' ? -2 : 2)) + targetDimensions[this._getXY(xy)]) * (xy == 'top' || xy == 'left' ? 1 : -1)));
1405
+            this.pointer && this.wrapper.removeClass('jBox-pointerPosition-' + this.pointer.position).addClass('jBox-pointerPosition-' + this._getOpp(this.pointer.position)).css('padding', 0).css('padding-' + xy, this.pointer.dimensions[this._getXY(xy)]);
1406
+            this.pointer && this.pointer.element.attr('class', 'jBox-pointer jBox-pointer-' + xy);
1407
+            this.positionAdjusted = true;
1408
+            this.flipped = true;
1409
+          }.bind(this);
1410
+
1411
+          // Flip jBox
1412
+          flip.x && flipJBox(this.options.position.x);
1413
+          flip.y && flipJBox(this.options.position.y);
1414
+        }
1415
+
1416
+        // Move jBox (only possible with pointer)
1417
+        var outMove = (this._getXY(this.outside) == 'x') ? outY : outX;
1418
+
1419
+        if (this.pointer && options.pointTo == 'target' && options.adjustPosition != 'flip' && this._getXY(outMove) == this._getOpp(this._getXY(this.outside))) {
1420
+
1421
+          // Get the maximum space we have availible to adjust
1422
+          if (this.pointer.align == 'center') {
1423
+            var spaceAvail = (jBoxDimensions[this._getXY(outMove)] / 2) - (this.pointer.dimensions[this._getOpp(this.pointer.xy)] / 2) - (parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) * (outMove != this._getTL(outMove) ? -1 : 1));
1424
+          } else {
1425
+            var spaceAvail = (outMove == this.pointer.alignAttribute) ?
1426
+              parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) :
1427
+              jBoxDimensions[this._getXY(outMove)] - parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) - this.pointer.dimensions[this._getXY(outMove)];
1428
+          }
1429
+
1430
+          // Get the overlapping space
1431
+          var spaceDiff = (outMove == this._getTL(outMove)) ?
1432
+            windowDimensions[this._getTL(outMove)] - pos[this._getTL(outMove)] + options.adjustDistance[outMove] :
1433
+            (windowDimensions[this._getOpp(this._getTL(outMove))] - pos[this._getTL(outMove)] - options.adjustDistance[outMove] - jBoxDimensions[this._getXY(outMove)]) * -1;
1434
+
1435
+          // Add overlapping space on left or top window edge
1436
+          if (outMove == this._getOpp(this._getTL(outMove)) && pos[this._getTL(outMove)] - spaceDiff < windowDimensions[this._getTL(outMove)] + options.adjustDistance[this._getTL(outMove)]) {
1437
+            spaceDiff -= windowDimensions[this._getTL(outMove)] + options.adjustDistance[this._getTL(outMove)] - (pos[this._getTL(outMove)] - spaceDiff);
1438
+          }
1439
+
1440
+          // Only adjust the maximum availible
1441
+          spaceDiff = Math.min(spaceDiff, spaceAvail);
1442
+
1443
+          // Move jBox
1444
+          if (spaceDiff <= spaceAvail && spaceDiff > 0) {
1445
+            this.pointer.element.css('margin-' + this.pointer.alignAttribute, parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) - (spaceDiff * (outMove != this.pointer.alignAttribute ? -1 : 1)));
1446
+            this.wrapper.css(this._getTL(outMove), pos[this._getTL(outMove)] + (spaceDiff * (outMove != this._getTL(outMove) ? -1 : 1)));
1447
+            this.positionAdjusted = true;
1448
+          }
1449
+        }
1450
+      }
1451
+    }
1452
+
1453
+    // Fire onPosition event
1454
+    this._fireEvent('onPosition');
1455
+
1456
+    return this;
1457
+  };
1458
+
1459
+
1460
+  // Block scrolling
1461
+  // Borrowed from https://github.com/StephanWagner/unscroll
1462
+
1463
+  jBox.prototype.unscroll = function (elements) {
1464
+
1465
+    // Store reusable vars
1466
+    this.set = function (id, value) {
1467
+      if (!window.unscrollStore) {
1468
+        window.unscrollStore = {};
1469
+      }
1470
+      window.unscrollStore[id] = value;
1471
+    };
1472
+
1473
+    // Get reusable vars
1474
+    this.get = function (id) {
1475
+      return window.unscrollStore ? window.unscrollStore[id] : null;
1476
+    };
1477
+
1478
+    // Get the width of the scroll bar in pixel
1479
+    this.getScrollbarWidth = function () {
1480
+      if (this.get('scrollbarWidth')) {
1481
+        return this.get('scrollbarWidth') + 'px';
1482
+      }
1483
+      var scrollElement = document.createElement('div');
1484
+      scrollElement.style.width = '100px';
1485
+      scrollElement.style.height = '100px';
1486
+      scrollElement.style.overflow = 'scroll';
1487
+      scrollElement.style.position = 'absolute';
1488
+      scrollElement.style.top = '-10000';
1489
+
1490
+      document.body.appendChild(scrollElement);
1491
+      var scrollbarWidth = scrollElement.offsetWidth - scrollElement.clientWidth;
1492
+      document.body.removeChild(scrollElement);
1493
+
1494
+      this.set('scrollbarWidth', scrollbarWidth);
1495
+      return scrollbarWidth + 'px';
1496
+    }
1497
+
1498
+    // Add unscroll class to head
1499
+    function addUnscrollClassName() {
1500
+      if (document.getElementById('unscroll-class-name')) {
1501
+        return;
1502
+      }
1503
+      var css = '.unscrollable { overflow: hidden !important; }',
1504
+        head = document.head || document.getElementsByTagName('head')[0],
1505
+        style = document.createElement('style');
1506
+      style.type = 'text/css';
1507
+      style.setAttribute('id', 'unscroll-class-name');
1508
+      style.appendChild(document.createTextNode(css));
1509
+      head.appendChild(style);
1510
+    }
1511
+
1512
+    // Get the elements to adjust, force body element
1513
+    this.getElementsToAdjust = function (elements) {
1514
+      !elements && (elements = []);
1515
+
1516
+      if (typeof elements === 'string') {
1517
+        elements = [
1518
+          [elements, 'padding-right']
1519
+        ];
1520
+      }
1521
+
1522
+      elements.forEach(function (element, index) {
1523
+        if (typeof element === 'string') {
1524
+          elements[index] = [element, 'padding-right'];
1525
+        }
1526
+      });
1527
+
1528
+      var bodyFound = false;
1529
+      for (var i = 0; i < elements.length; i++) {
1530
+        if (elements[i][0].indexOf('body') !== -1) {
1531
+          bodyFound = true;
1532
+        }
1533
+      };
1534
+
1535
+      if (bodyFound === false) {
1536
+        elements.push(['body', 'padding-right']);
1537
+      }
1538
+
1539
+      return elements;
1540
+    }
1541
+
1542
+    this.pageHasScrollbar = function () {
1543
+      return this.getScrollbarWidth() && document.body.offsetHeight > window.innerHeight;
1544
+    }
1545
+
1546
+    // Clean up elements
1547
+    if (this.pageHasScrollbar()) {
1548
+      elements = this.getElementsToAdjust(elements);
1549
+
1550
+      // Loop through elements and adjust accordingly
1551
+      for (var i = 0; i < elements.length; i++) {
1552
+        var elementsDOM = document.querySelectorAll(elements[i][0]);
1553
+        for (var j = 0; j < elementsDOM.length; j++) {
1554
+          if (elementsDOM[j].getAttribute('data-unscroll')) {
1555
+            return;
1556
+          }
1557
+          var attribute = elements[i][1];
1558
+          var computedStyles = window.getComputedStyle(elementsDOM[j]);
1559
+          var computedStyle = computedStyles.getPropertyValue(attribute);
1560
+          elementsDOM[j].setAttribute('data-unscroll', attribute);
1561
+          if (!computedStyle) {
1562
+            computedStyle = '0px';
1563
+          }
1564
+          var operator = attribute == 'padding-right' || attribute == 'right' ? '+' : '-';
1565
+          elementsDOM[j].style[attribute] = 'calc(' + computedStyle + ' ' + operator + ' ' + this.getScrollbarWidth() + ')';
1566
+        }
1567
+      }
1568
+    }
1569
+
1570
+    // Make the page unscrollable
1571
+    addUnscrollClassName();
1572
+    document.body.classList.add('unscrollable');
1573
+  }
1574
+
1575
+  jBox.prototype.unscroll.reset = function () {
1576
+    var elements = document.querySelectorAll('[data-unscroll]');
1577
+
1578
+    for (var i = 0; i < elements.length; i++) {
1579
+      var attribute = elements[i].getAttribute('data-unscroll');
1580
+      elements[i].style[attribute] = null;
1581
+      elements[i].removeAttribute('data-unscroll');
1582
+    }
1583
+    document.body.classList.remove('unscrollable');
1584
+  }
1585
+
1586
+
1587
+  // Open jBox
1588
+
1589
+  jBox.prototype.open = function (options)
1590
+  {
1591
+    // Create blank options if none passed
1592
+    !options && (options = {});
1593
+
1594
+    // Abort if jBox was destroyed
1595
+    if (this.isDestroyed) return this;
1596
+
1597
+    // Construct jBox if not already constructed
1598
+    !this.wrapper && this._create();
1599
+
1600
+    // Add css to header if not added already
1601
+    !this._styles && (this._styles = jQuery('<style/>').append(this._animationCSS).appendTo(jQuery('head')));
1602
+
1603
+    // Abort any opening or closing timer
1604
+    this.timer && clearTimeout(this.timer);
1605
+
1606
+    // Block body click for 10ms, so jBox can open on attached elements while closeOnClick = 'body'
1607
+    this._blockBodyClick();
1608
+
1609
+    // Block opening
1610
+    if (this.isDisabled) return this;
1611
+
1612
+    // Closing event: closeOnEsc
1613
+    this.options.closeOnEsc && jQuery(document).on('keyup.jBox-' + this.id, function (ev) { if (ev.keyCode == 27) { this.close({ignoreDelay: true}); }}.bind(this));
1614
+
1615
+    // Closing event: closeOnClick
1616
+    if (this.options.closeOnClick === true || this.options.closeOnClick === 'body') {
1617
+      jQuery('body').on('click.jBox-' + this.id + ' tap.jBox-' + this.id, function (ev) {
1618
+        if (this.blockBodyClick || (this.options.closeOnClick == 'body' && (ev.target == this.wrapper[0] || this.wrapper.has(ev.target).length))) return;
1619
+        this.close({ignoreDelay: true});
1620
+      }.bind(this));
1621
+
1622
+      // Fix for iOS event bubbling issue
1623
+      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
1624
+      this.isTouchDevice && jQuery('body > *').on('click.jBox-' + this.id + ' tap.jBox-' + this.id, function () {
1625
+        return true;
1626
+      });
1627
+    }
1628
+
1629
+    // Opening function
1630
+    var open = function () {
1631
+
1632
+      // Adjust zIndex
1633
+      if (this.adjustZIndexOnOpen === true) {
1634
+        jBox.zIndexMax = Math.max(
1635
+          parseInt(this.wrapper.css('zIndex'), 10),
1636
+          this.options.zIndex,
1637
+          jBox.zIndexMax || 0,
1638
+          jBox.zIndexMaxDragover || 0
1639
+        ) + 2;
1640
+        this.wrapper.css('zIndex', jBox.zIndexMax);
1641
+        this.options.zIndex = jBox.zIndexMax;
1642
+      }
1643
+
1644
+      // Set title from source element
1645
+      this.source && this.options.getTitle && (this.source.attr(this.options.getTitle) && this.setTitle(this.source.attr(this.options.getTitle), true));
1646
+
1647
+      // Set content from source element
1648
+      this.source && this.options.getContent && (this.source.data('jBox-getContent') ? this.setContent(this.source.data('jBox-getContent'), true) : (this.source.attr(this.options.getContent) ? this.setContent(this.source.attr(this.options.getContent), true) : (this.options.getContent == 'html' ? this.setContent(this.source.html(), true) : null)));
1649
+
1650
+      // Fire onOpen event
1651
+      this._fireEvent('onOpen');
1652
+
1653
+      // Get content from ajax
1654
+      if ((this.options.ajax && (this.options.ajax.url || (this.source && this.source.attr(this.options.ajax.getURL))) && (!this.ajaxLoaded || this.options.ajax.reload)) || (options.ajax && (options.ajax.url || options.ajax.data))) {
1655
+        // Send the content from stored data if there is any, otherwise load new data
1656
+        (this.options.ajax.reload != 'strict' && this.source && this.source.data('jBox-ajax-data') && !(options.ajax && (options.ajax.url || options.ajax.data))) ? this.setContent(this.source.data('jBox-ajax-data')) : this.ajax((options.ajax || null), true);
1657
+      }
1658
+
1659
+      // Set position
1660
+      (!this.positionedOnOpen || this.options.repositionOnOpen) && this.position(options) && (this.positionedOnOpen = true);
1661
+
1662
+      // Abort closing
1663
+      this.isClosing && this._abortAnimation();
1664
+
1665
+      // Open functions to call when jBox is closed
1666
+      if (!this.isOpen) {
1667
+
1668
+        // jBox is open now
1669
+        this.isOpen = true;
1670
+
1671
+        // Automatically close jBox after some time
1672
+        this.options.autoClose && (this.options.delayClose = this.options.autoClose) && this.close();
1673
+
1674
+        // Attach events
1675
+        this._attachEvents();
1676
+
1677
+        // Block scrolling
1678
+        if (this.options.blockScroll) {
1679
+          if (this.options.blockScrollAdjust) {
1680
+            if (jBox.blockScrollScopes) {
1681
+              jBox.blockScrollScopes++;
1682
+            } else {
1683
+              jBox.blockScrollScopes = 1;
1684
+              this.unscroll(Array.isArray(this.options.blockScrollAdjust) || typeof this.options.blockScrollAdjust === 'string' ? this.options.blockScrollAdjust : null);
1685
+            }
1686
+          } else {
1687
+            jQuery('body').addClass('jBox-blockScroll-' + this.id);
1688
+          }
1689
+        }
1690
+
1691
+        // Show overlay
1692
+        if (this.options.overlay) {
1693
+          this._showOverlay();
1694
+
1695
+          // TODO Optimize: We have to position here again, because if the overlay has a close button, the upper adjustDistance will be wrong
1696
+          this.position();
1697
+        }
1698
+
1699
+        // Only animate if jBox is completely closed
1700
+        this.options.animation && !this.isClosing && this._animate('open');
1701
+
1702
+        // Play audio file
1703
+        this.options.audio && this.options.audio.open && this.audio(this.options.audio.open, this.options.volume.open);
1704
+
1705
+        // Fading animation or show immediately
1706
+        if (this.options.fade) {
1707
+          this.wrapper.stop().animate({opacity: 1}, {
1708
+            queue: false,
1709
+            duration: this.options.fade,
1710
+            start: function () {
1711
+              this.isOpening = true;
1712
+              this.wrapper.css({display: 'block'});
1713
+            }.bind(this),
1714
+            always: function () {
1715
+              this.isOpening = false;
1716
+
1717
+              // Delay positioning for ajax to prevent positioning during animation
1718
+              setTimeout(function () { this.positionOnFadeComplete && this.position() && (this.positionOnFadeComplete = false); }.bind(this), 10);
1719
+            }.bind(this)
1720
+          });
1721
+        } else {
1722
+          this.wrapper.css({display: 'block', opacity: 1});
1723
+          this.positionOnFadeComplete && this.position() && (this.positionOnFadeComplete = false);
1724
+        }
1725
+      }
1726
+    }.bind(this);
1727
+
1728
+    // Open jBox
1729
+    this.options.delayOpen && !this.isOpen && !this.isClosing && !options.ignoreDelay ? (this.timer = setTimeout(open, this.options.delayOpen)) : open();
1730
+
1731
+    return this;
1732
+  };
1733
+
1734
+
1735
+  // Close jBox
1736
+
1737
+  jBox.prototype.close = function (options)
1738
+  {
1739
+    // Create blank options if none passed
1740
+    options || (options = {});
1741
+
1742
+    // Remove close events
1743
+    jQuery('body').off('click.jBox-' + this.id + ' tap.jBox-' + this.id);
1744
+    this.isTouchDevice && jQuery('body > *').off('click.jBox-' + this.id + ' tap.jBox-' + this.id);
1745
+
1746
+    // Abort if jBox was destroyed or is currently closing
1747
+    if (this.isDestroyed || this.isClosing) return this;
1748
+
1749
+    // Abort opening
1750
+    this.timer && clearTimeout(this.timer);
1751
+
1752
+    // Block body click for 10ms, so jBox can open on attached elements while closeOnClick = 'body' is true
1753
+    this._blockBodyClick();
1754
+
1755
+    // Block closing
1756
+    if (this.isDisabled) return this;
1757
+
1758
+    // Close function
1759
+    var close = function () {
1760
+
1761
+      // Fire onClose event
1762
+      this._fireEvent('onClose');
1763
+
1764
+      // Cancel the ajax call
1765
+      if (this.options.cancelAjaxOnClose) {
1766
+        this.cancelAjax();
1767
+      }
1768
+
1769
+      // Only close if jBox is open
1770
+      if (this.isOpen) {
1771
+
1772
+        // jBox is not open anymore
1773
+        this.isOpen = false;
1774
+
1775
+        // Detach events
1776
+        this._detachEvents();
1777
+
1778
+        // Unblock scrolling
1779
+        if (this.options.blockScroll) {
1780
+          if (this.options.blockScrollAdjust) {
1781
+            jBox.blockScrollScopes = jBox.blockScrollScopes ? --jBox.blockScrollScopes : 0;
1782
+            !jBox.blockScrollScopes && this.unscroll.reset();
1783
+          } else {
1784
+            jQuery('body').removeClass('jBox-blockScroll-' + this.id);
1785
+          }
1786
+        }
1787
+
1788
+        // Hide overlay
1789
+        this.options.overlay && this._hideOverlay();
1790
+
1791
+        // Only animate if jBox is compleately closed
1792
+        this.options.animation && !this.isOpening && this._animate('close');
1793
+
1794
+        // Play audio file
1795
+        this.options.audio && this.options.audio.close && this.audio(this.options.audio.close, this.options.volume.close);
1796
+
1797
+        // Get fade duration
1798
+        var fadeDuration = this.isTouchDevice && this.options.target == 'mouse' ? 0 : this.options.fade;
1799
+
1800
+        // Fading animation or show immediately
1801
+        if (fadeDuration) {
1802
+          this.wrapper.stop().animate({opacity: 0}, {
1803
+            queue: false,
1804
+            duration: fadeDuration,
1805
+            start: function () {
1806
+              this.isClosing = true;
1807
+            }.bind(this),
1808
+            complete: function () {
1809
+              this.wrapper.css({display: 'none'});
1810
+              this._fireEvent('onCloseComplete');
1811
+            }.bind(this),
1812
+            always: function () {
1813
+              this.isClosing = false;
1814
+            }.bind(this)
1815
+          });
1816
+        } else {
1817
+          this.wrapper.css({display: 'none', opacity: 0});
1818
+          this._fireEvent('onCloseComplete');
1819
+        }
1820
+      }
1821
+    }.bind(this);
1822
+
1823
+    // Close jBox
1824
+    if (options.ignoreDelay || (this.isTouchDevice && this.options.target == 'mouse')) {
1825
+      close();
1826
+    } else if ((this.options.delayOnHover || this.options.showCountdown) && this.options.delayClose > 10) {
1827
+      var self = this;
1828
+      var remaining = this.options.delayClose;
1829
+      var prevFrame = Date.now();
1830
+      if (this.options.showCountdown && !this.inner) {
1831
+        var outer = jQuery('<div class="jBox-countdown" />');
1832
+        this.inner = jQuery('<div class="jBox-countdown-inner" />');
1833
+        outer.prepend(this.inner);
1834
+        jQuery('#' + this.id).append(outer);
1835
+      }
1836
+      this.countdown = function(){
1837
+        var dateNow = Date.now();
1838
+        if (!self.isHovered) {
1839
+          remaining -= dateNow - prevFrame;
1840
+        }
1841
+        prevFrame = dateNow;
1842
+        if (remaining > 0) {
1843
+          if (self.options.showCountdown) {
1844
+            self.inner.css('width', (remaining * 100 / self.options.delayClose) + '%');
1845
+          }
1846
+          window.requestAnimationFrame(self.countdown);
1847
+        } else {
1848
+          close();
1849
+        }
1850
+      };
1851
+      window.requestAnimationFrame(this.countdown);
1852
+    } else {
1853
+      this.timer = setTimeout(close, Math.max(this.options.delayClose, 10));
1854
+    }
1855
+
1856
+    return this;
1857
+  };
1858
+
1859
+
1860
+  // Open or close jBox
1861
+
1862
+  jBox.prototype.toggle = function (options)
1863
+  {
1864
+    this[this.isOpen ? 'close' : 'open'](options);
1865
+    return this;
1866
+  };
1867
+
1868
+
1869
+  // Block opening and closing
1870
+
1871
+  jBox.prototype.disable = function ()
1872
+  {
1873
+    this.isDisabled = true;
1874
+    return this;
1875
+  };
1876
+
1877
+
1878
+  // Unblock opening and closing
1879
+
1880
+  jBox.prototype.enable = function ()
1881
+  {
1882
+    this.isDisabled = false;
1883
+    return this;
1884
+  };
1885
+
1886
+
1887
+  // Hide jBox
1888
+
1889
+  jBox.prototype.hide = function ()
1890
+  {
1891
+    this.disable();
1892
+    if (this.wrapper) {
1893
+      this.cacheWrapperDisplay = this.wrapper.css('display');
1894
+      this.wrapper.css({display: 'none'});
1895
+    }
1896
+    if (this.overlay) {
1897
+      this.cacheOverlayDisplay = this.overlay.css('display');
1898
+      this.overlay.css({display: 'none'});
1899
+    }
1900
+    return this;
1901
+  };
1902
+
1903
+
1904
+  // Show jBox
1905
+
1906
+  jBox.prototype.show = function ()
1907
+  {
1908
+    this.enable();
1909
+    if (this.wrapper && this.cacheWrapperDisplay) {
1910
+      this.wrapper.css({display: this.cacheWrapperDisplay});
1911
+      this.cacheWrapperDisplay = null;
1912
+    }
1913
+    if (this.overlay && this.cacheOverlayDisplay) {
1914
+      this.overlay.css({display: this.cacheOverlayDisplay});
1915
+      this.cacheOverlayDisplay = null;
1916
+    }
1917
+    return this;
1918
+  };
1919
+
1920
+
1921
+  // Get content from ajax
1922
+
1923
+  jBox.prototype.ajax = function (options, opening)
1924
+  {
1925
+    options || (options = {});
1926
+
1927
+    // Add data or url from source element if none set in options
1928
+    jQuery.each([['getData', 'data'], ['getURL', 'url']], function (index, item) {
1929
+      (this.options.ajax[item[0]] && !options[item[1]] && this.source && this.source.attr(this.options.ajax[item[0]]) != undefined) && (options[item[1]] = this.source.attr(this.options.ajax[item[0]]) || '');
1930
+    }.bind(this));
1931
+
1932
+    // Clone the system options
1933
+    var sysOptions = jQuery.extend(true, {}, this.options.ajax);
1934
+
1935
+    // Abort running ajax call
1936
+    this.cancelAjax();
1937
+
1938
+    // Extract events
1939
+    var beforeSend = options.beforeSend || sysOptions.beforeSend || function () {};
1940
+    var complete = options.complete || sysOptions.complete || function () {};
1941
+    var success = options.success || sysOptions.success || function () {};
1942
+    var error = options.error || sysOptions.error || function () {};
1943
+
1944
+    // Merge options
1945
+    var userOptions = jQuery.extend(true, sysOptions, options);
1946
+
1947
+    // Set new beforeSend event
1948
+    userOptions.beforeSend = function (xhr)
1949
+    {
1950
+      // jBox is loading
1951
+      userOptions.loadingClass && this.wrapper.addClass(userOptions.loadingClass === true ? 'jBox-loading' : userOptions.loadingClass);
1952
+
1953
+      // Add loading spinner
1954
+      userOptions.spinner && (this.spinnerDelay = setTimeout(function ()
1955
+      {
1956
+        // Add class for loading spinner
1957
+        this.wrapper.addClass('jBox-loading-spinner');
1958
+
1959
+        // Reposition jBox
1960
+        // TODO: Only reposition if dimensions change
1961
+        userOptions.spinnerReposition && (opening ? (this.positionOnFadeComplete = true) : this.position());
1962
+
1963
+        // Add spinner to container
1964
+        this.spinner = jQuery(userOptions.spinner !== true ? userOptions.spinner : '<div class="jBox-spinner"></div>').appendTo(this.container);
1965
+
1966
+        // Fix spinners position if there is a title
1967
+        this.titleContainer && this.spinner.css('position') == 'absolute' && this.spinner.css({transform: 'translateY(' + (this.titleContainer.outerHeight() * 0.5) + 'px)'});
1968
+
1969
+      }.bind(this), (this.content.html() == '' ? 0 : (userOptions.spinnerDelay || 0))));
1970
+
1971
+      // Fire users beforeSend event
1972
+      (beforeSend.bind(this))(xhr);
1973
+
1974
+    }.bind(this);
1975
+
1976
+    // Set up new complete event
1977
+    userOptions.complete = function (response)
1978
+    {
1979
+      // Abort spinner timeout
1980
+      this.spinnerDelay && clearTimeout(this.spinnerDelay);
1981
+
1982
+      // jBox finished loading
1983
+      this.wrapper.removeClass('jBox-loading jBox-loading-spinner jBox-loading-spinner-delay');
1984
+
1985
+      // Remove spinner
1986
+      this.spinner && this.spinner.length && this.spinner.remove() && userOptions.spinnerReposition && (opening ? (this.positionOnFadeComplete = true) : this.position());
1987
+
1988
+      // Store that ajax loading finished
1989
+      this.ajaxLoaded = true;
1990
+
1991
+      // Fire users complete event
1992
+      (complete.bind(this))(response);
1993
+
1994
+    }.bind(this);
1995
+
1996
+    // Set up new success event
1997
+    userOptions.success = function (response)
1998
+    {
1999
+      // Set content
2000
+      userOptions.setContent && this.setContent(response, true) && (opening ? (this.positionOnFadeComplete = true) : this.position());
2001
+
2002
+      // Store content in source element
2003
+      userOptions.setContent && this.source && this.source.data('jBox-ajax-data', response);
2004
+
2005
+      // Fire users success event
2006
+      (success.bind(this))(response);
2007
+
2008
+    }.bind(this);
2009
+
2010
+    // Add error event
2011
+    userOptions.error = function (response) { (error.bind(this))(response); }.bind(this);
2012
+
2013
+    // Send new ajax request
2014
+    this.ajaxRequest = jQuery.ajax(userOptions);
2015
+
2016
+    return this;
2017
+  };
2018
+
2019
+
2020
+  // Abort an ajax call
2021
+
2022
+  jBox.prototype.cancelAjax = function () {
2023
+    if (this.ajaxRequest) {
2024
+      this.ajaxRequest.abort();
2025
+      this.ajaxLoaded = false;
2026
+    }
2027
+  };
2028
+
2029
+
2030
+  // Play an audio file
2031
+
2032
+  jBox.prototype.audio = function (url, volume)
2033
+  {
2034
+    // URL is required
2035
+    if (!url) return this;
2036
+
2037
+    // Create intern audio object if it wasn't created already
2038
+    !jBox._audio && (jBox._audio = {});
2039
+
2040
+    // Create an audio element specific to this audio file if it doesn't exist already
2041
+    if (!jBox._audio[url]) {
2042
+      var audio = jQuery('<audio/>');
2043
+      jQuery('<source/>', {src: url + '.mp3'}).appendTo(audio);
2044
+      jQuery('<source/>', {src: url + '.ogg'}).appendTo(audio);
2045
+      jBox._audio[url] = audio[0];
2046
+    }
2047
+
2048
+    // Set volume
2049
+    jBox._audio[url].volume = Math.min(((volume != undefined ? volume : 100) / 100), 1);
2050
+
2051
+    // Try to pause current audio
2052
+    try {
2053
+      jBox._audio[url].pause();
2054
+      jBox._audio[url].currentTime = 0;
2055
+    } catch (e) {}
2056
+
2057
+    // Play audio
2058
+    jBox._audio[url].play();
2059
+
2060
+    return this;
2061
+  };
2062
+
2063
+
2064
+  // Apply custom animations to jBox
2065
+
2066
+  jBox._animationSpeeds = {
2067
+    'tada': 1000,
2068
+    'tadaSmall': 1000,
2069
+    'flash': 500,
2070
+    'shake': 400,
2071
+    'pulseUp': 250,
2072
+    'pulseDown': 250,
2073
+    'popIn': 250,
2074
+    'popOut': 250,
2075
+    'fadeIn': 200,
2076
+    'fadeOut': 200,
2077
+    'slideUp': 400,
2078
+    'slideRight': 400,
2079
+    'slideLeft': 400,
2080
+    'slideDown': 400
2081
+  };
2082
+
2083
+  jBox.prototype.animate = function (animation, options)
2084
+  {
2085
+    // Options are required
2086
+    !options && (options = {});
2087
+
2088
+    // Timout needs to be an object
2089
+    !this.animationTimeout && (this.animationTimeout = {});
2090
+
2091
+    // Use jBox wrapper by default
2092
+    !options.element && (options.element = this.wrapper);
2093
+
2094
+    // Give the element an unique id
2095
+    !options.element.data('jBox-animating-id') && options.element.data('jBox-animating-id', jBox._getUniqueElementID());
2096
+
2097
+    // Abort if element is animating
2098
+    if (options.element.data('jBox-animating')) {
2099
+      options.element.removeClass(options.element.data('jBox-animating')).data('jBox-animating', null);
2100
+      this.animationTimeout[options.element.data('jBox-animating-id')] && clearTimeout(this.animationTimeout[options.element.data('jBox-animating-id')]);
2101
+    }
2102
+
2103
+    // Animate the element
2104
+    options.element.addClass('jBox-animated-' + animation).data('jBox-animating', 'jBox-animated-' + animation);
2105
+    this.animationTimeout[options.element.data('jBox-animating-id')] = setTimeout((function() { options.element.removeClass(options.element.data('jBox-animating')).data('jBox-animating', null); options.complete && options.complete(); }), jBox._animationSpeeds[animation]);
2106
+  };
2107
+
2108
+  // https://gist.github.com/AlexEmashev/ee8302b5036b01362f63dab35948401f
2109
+  jBox.prototype.swipeDetector = function (swipeTarget, options) {
2110
+    // States: 0 - no swipe, 1 - swipe started, 2 - swipe released
2111
+    var swipeState = 0;
2112
+    // Coordinates when swipe started
2113
+    var startX = 0;
2114
+    var startY = 0;
2115
+    // Distance of swipe
2116
+    var pixelOffsetX = 0;
2117
+    var pixelOffsetY = 0;
2118
+
2119
+    var defaultSettings = {
2120
+      // Amount of pixels, when swipe don't count.
2121
+      swipeThreshold: 70,
2122
+      // Flag that indicates that plugin should react only on touch events.
2123
+      // Not on mouse events too.
2124
+      useOnlyTouch: false
2125
+    };
2126
+
2127
+    // Initializer
2128
+    (function init() {
2129
+      options = jQuery.extend(defaultSettings, options);
2130
+      // Support touch and mouse as well.
2131
+      swipeTarget.on("mousedown touchstart", swipeStart);
2132
+      $("html").on("mouseup touchend", swipeEnd);
2133
+      $("html").on("mousemove touchmove", swiping);
2134
+    })();
2135
+
2136
+    function swipeStart(event) {
2137
+      if (options.useOnlyTouch && !event.originalEvent.touches) {
2138
+        return;
2139
+      }
2140
+
2141
+      if (event.originalEvent.touches) {
2142
+        event = event.originalEvent.touches[0];
2143
+      }
2144
+
2145
+      if (swipeState === 0) {
2146
+        swipeState = 1;
2147
+        startX = event.clientX;
2148
+        startY = event.clientY;
2149
+      }
2150
+    }
2151
+
2152
+    function swipeEnd(event) {
2153
+      if (swipeState === 2) {
2154
+        swipeState = 0;
2155
+
2156
+        if (
2157
+          Math.abs(pixelOffsetX) > Math.abs(pixelOffsetY) &&
2158
+          Math.abs(pixelOffsetX) > options.swipeThreshold
2159
+        ) {
2160
+          // Horizontal Swipe
2161
+          if (pixelOffsetX < 0) {
2162
+            swipeTarget.trigger($.Event("swipeLeft.sd"));
2163
+          } else {
2164
+            swipeTarget.trigger($.Event("swipeRight.sd"));
2165
+          }
2166
+        } else if (Math.abs(pixelOffsetY) > options.swipeThreshold) {
2167
+          // Vertical swipe
2168
+          if (pixelOffsetY < 0) {
2169
+            swipeTarget.trigger($.Event("swipeUp.sd"));
2170
+          } else {
2171
+            swipeTarget.trigger($.Event("swipeDown.sd"));
2172
+          }
2173
+        }
2174
+      }
2175
+    }
2176
+
2177
+    function swiping(event) {
2178
+      // If swipe don't occuring, do nothing.
2179
+      if (swipeState !== 1) return;
2180
+
2181
+      if (event.originalEvent.touches) {
2182
+        event = event.originalEvent.touches[0];
2183
+      }
2184
+
2185
+      var swipeOffsetX = event.clientX - startX;
2186
+      var swipeOffsetY = event.clientY - startY;
2187
+
2188
+      if (
2189
+        Math.abs(swipeOffsetX) > options.swipeThreshold ||
2190
+        Math.abs(swipeOffsetY) > options.swipeThreshold
2191
+      ) {
2192
+        swipeState = 2;
2193
+        pixelOffsetX = swipeOffsetX;
2194
+        pixelOffsetY = swipeOffsetY;
2195
+      }
2196
+    }
2197
+
2198
+    return swipeTarget; // Return element available for chaining.
2199
+  }
2200
+
2201
+
2202
+  // Destroy jBox and remove it from DOM
2203
+
2204
+  jBox.prototype.destroy = function ()
2205
+  {
2206
+    // Detach from attached elements
2207
+    this.detach();
2208
+
2209
+    // If jBox is open, close without delay
2210
+    this.isOpen && this.close({ignoreDelay: true});
2211
+
2212
+    // Remove wrapper
2213
+    this.wrapper && this.wrapper.remove();
2214
+
2215
+    // Remove overlay
2216
+    this.overlay && this.overlay.remove();
2217
+
2218
+    // Remove styles
2219
+    this._styles && this._styles.remove();
2220
+
2221
+    // Tell the jBox instance it is destroyed
2222
+    this.isDestroyed = true;
2223
+
2224
+    return this;
2225
+  };
2226
+
2227
+
2228
+  // Get a unique ID for jBoxes
2229
+
2230
+  jBox._getUniqueID = (function ()
2231
+  {
2232
+    var i = 1;
2233
+    return function () { return i++; };
2234
+  }());
2235
+
2236
+
2237
+  // Get a unique ID for animating elements
2238
+
2239
+  jBox._getUniqueElementID = (function ()
2240
+  {
2241
+    var i = 1;
2242
+    return function () { return i++; };
2243
+  }());
2244
+
2245
+
2246
+  // Function to create jBox plugins
2247
+
2248
+  jBox._pluginOptions = {};
2249
+  jBox.plugin = function (type, options)
2250
+  {
2251
+    jBox._pluginOptions[type] = options;
2252
+  };
2253
+
2254
+
2255
+  // Make jBox usable with jQuery selectors
2256
+
2257
+  jQuery.fn.jBox = function (type, options) {
2258
+    // Variables type and object are required
2259
+    !type && (type = {});
2260
+    !options && (options = {});
2261
+
2262
+    // Return a new instance of jBox with the selector as attached element
2263
+    return new jBox(type, jQuery.extend(options, {
2264
+      attach: this
2265
+    }));
2266
+  };
2267
+
2268
+  return jBox;
2269
+
2270
+};
2271
+
2272
+(function (root, factory) {
2273
+  if (typeof define === 'function' && define.amd) {
2274
+    define(['jquery'], function (jQuery) {
2275
+      return (root.jBox = factory(jQuery));
2276
+    });
2277
+  } else if (typeof module === 'object' && module.exports) {
2278
+    module.exports = (root.jBox = factory(require('jquery')));
2279
+  } else {
2280
+    root.jBox = factory(root.jQuery);
2281
+  }
2282
+}(this, function (jQuery) {
2283
+  var jBox = jBoxWrapper(jQuery);
2284
+  try { typeof jBoxConfirmWrapper !== 'undefined' && jBoxConfirmWrapper && jBoxConfirmWrapper(jBox, jQuery); } catch(e) { console.error(e); }
2285
+  try { typeof jBoxImageWrapper !== 'undefined' && jBoxImageWrapper && jBoxImageWrapper(jBox, jQuery); } catch(e) { console.error(e); }
2286
+  try { typeof jBoxNoticeWrapper !== 'undefined' && jBoxNoticeWrapper && jBoxNoticeWrapper(jBox, jQuery); } catch(e) { console.error(e); }
2287
+  return jBox;
2288
+}));
2289
+
2290
+//# sourceMappingURL=jBox.js.map
0 2291
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-wrapper{text-align:left;box-sizing:border-box}.jBox-container,.jBox-content,.jBox-title{position:relative;word-break:break-word;box-sizing:border-box}.jBox-container{background:#fff}.jBox-content{padding:8px 12px;overflow-x:hidden;overflow-y:auto;transition:opacity .2s}.jBox-footer{box-sizing:border-box}.jBox-Mouse .jBox-container,.jBox-Tooltip .jBox-container{border-radius:4px;box-shadow:0 0 3px rgba(0,0,0,.25)}.jBox-Mouse .jBox-title,.jBox-Tooltip .jBox-title{padding:8px 10px 0;font-weight:700}.jBox-Mouse.jBox-hasTitle .jBox-content,.jBox-Tooltip.jBox-hasTitle .jBox-content{padding-top:5px}.jBox-Mouse{pointer-events:none}.jBox-pointer{position:absolute;overflow:hidden;box-sizing:border-box}.jBox-pointer:after{content:'';width:20px;height:20px;position:absolute;background:#fff;transform:rotate(45deg);box-sizing:border-box}.jBox-pointer-top{top:0}.jBox-pointer-top:after{left:5px;top:6px;box-shadow:-1px -1px 2px rgba(0,0,0,.15)}.jBox-pointer-right{right:0}.jBox-pointer-right:after{top:5px;right:6px;box-shadow:1px -1px 2px rgba(0,0,0,.15)}.jBox-pointer-left{left:0}.jBox-pointer-left:after{top:5px;left:6px;box-shadow:-1px 1px 2px rgba(0,0,0,.15)}.jBox-pointer-bottom{bottom:0}.jBox-pointer-bottom:after{left:5px;bottom:6px;box-shadow:1px 1px 2px rgba(0,0,0,.15)}.jBox-pointer-bottom,.jBox-pointer-top{width:30px;height:12px}.jBox-pointer-left,.jBox-pointer-right{width:12px;height:30px}.jBox-Modal .jBox-container{border-radius:4px}.jBox-Modal .jBox-container,.jBox-Modal.jBox-closeButton-box:before{box-shadow:0 3px 15px rgba(0,0,0,.4),0 0 5px rgba(0,0,0,.4)}.jBox-Modal .jBox-content{padding:15px 20px}.jBox-Modal .jBox-title{border-radius:4px 4px 0 0;padding:15px 20px;background:#fafafa;border-bottom:1px solid #eee}.jBox-Modal.jBox-closeButton-title .jBox-title{padding-right:65px}.jBox-Modal .jBox-footer{border-radius:0 0 4px 4px}.jBox-closeButton{z-index:1;cursor:pointer;position:absolute;box-sizing:border-box}.jBox-closeButton svg{position:absolute;top:50%;right:50%}.jBox-closeButton path{fill:#aaa;transition:fill .2s}.jBox-closeButton:hover path{fill:#888}.jBox-overlay .jBox-closeButton{top:0;right:0;width:40px;height:40px}.jBox-overlay .jBox-closeButton svg{width:20px;height:20px;margin-top:-10px;margin-right:-10px}.jBox-overlay .jBox-closeButton path{fill:#ddd}.jBox-overlay .jBox-closeButton:hover path{fill:#fff}.jBox-closeButton-title .jBox-closeButton{top:0;right:0;bottom:0;width:50px}.jBox-closeButton-title svg{width:12px;height:12px;margin-top:-6px;margin-right:-6px}.jBox-closeButton-box{box-sizing:border-box}.jBox-closeButton-box .jBox-closeButton{top:-8px;right:-10px;width:24px;height:24px;background:#fff;border-radius:50%}.jBox-closeButton-box .jBox-closeButton svg{width:10px;height:10px;margin-top:-5px;margin-right:-5px}.jBox-closeButton-box:before{content:'';position:absolute;top:-8px;right:-10px;width:24px;height:24px;border-radius:50%;box-shadow:0 0 5px rgba(0,0,0,.3)}.jBox-closeButton-box.jBox-pointerPosition-top:before{top:5px}.jBox-closeButton-box.jBox-pointerPosition-right:before{right:2px}.jBox-Modal.jBox-hasTitle.jBox-closeButton-box .jBox-closeButton{background:#fafafa}.jBox-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.82)}.jBox-footer{background:#fafafa;border-top:1px solid #eee;padding:8px 10px;border-radius:0 0 3px 3px}body[class*=" jBox-blockScroll-"],body[class^=jBox-blockScroll-]{overflow:hidden}.jBox-draggable{cursor:move}@keyframes jBoxLoading{to{transform:rotate(360deg)}}.jBox-loading .jBox-content{opacity:.2}.jBox-loading-spinner .jBox-content{min-height:38px!important;min-width:38px!important;opacity:0}.jBox-spinner{box-sizing:border-box;position:absolute;top:50%;left:50%;width:24px;height:24px;margin-top:-12px;margin-left:-12px}.jBox-spinner:before{display:block;box-sizing:border-box;content:'';width:24px;height:24px;border-radius:50%;border:2px solid rgba(0,0,0,.2);border-top-color:rgba(0,0,0,.8);animation:jBoxLoading .6s linear infinite}.jBox-countdown{border-radius:4px 4px 0 0;z-index:0;background:#000;opacity:.2;position:absolute;top:0;left:0;right:0;height:3px;overflow:hidden}.jBox-countdown-inner{top:0;right:0;width:100%;height:3px;position:absolute;background:#fff}[class*=" jBox-animated-"],[class^=jBox-animated-]{animation-fill-mode:both}@keyframes jBox-tada{0%{transform:scale(1)}10%,20%{transform:scale(.8) rotate(-4deg)}30%,50%,70%,90%{transform:scale(1.2) rotate(4deg)}40%,60%,80%{transform:scale(1.2) rotate(-4deg)}100%{transform:scale(1) rotate(0)}}.jBox-animated-tada{animation:jBox-tada 1s}@keyframes jBox-tadaSmall{0%{transform:scale(1)}10%,20%{transform:scale(.9) rotate(-2deg)}30%,50%,70%,90%{transform:scale(1.1) rotate(2deg)}40%,60%,80%{transform:scale(1.1) rotate(-2deg)}100%{transform:scale(1) rotate(0)}}.jBox-animated-tadaSmall{animation:jBox-tadaSmall 1s}@keyframes jBox-flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}.jBox-animated-flash{animation:jBox-flash .5s}@keyframes jBox-shake{0%,100%{transform:translateX(0)}20%,60%{transform:translateX(-6px)}40%,80%{transform:translateX(6px)}}.jBox-animated-shake{animation:jBox-shake .4s}@keyframes jBox-pulseUp{0%{transform:scale(1)}50%{transform:scale(1.15)}100%{transform:scale(1)}}.jBox-animated-pulseUp{animation:jBox-pulseUp .25s}@keyframes jBox-pulseDown{0%{transform:scale(1)}50%{transform:scale(.85)}100%{transform:scale(1)}}.jBox-animated-pulseDown{animation:jBox-pulseDown .25s}@keyframes jBox-popIn{0%{transform:scale(0)}50%{transform:scale(1.1)}100%{transform:scale(1)}}.jBox-animated-popIn{animation:jBox-popIn .25s}@keyframes jBox-popOut{0%{transform:scale(1)}50%{transform:scale(1.1)}100%{transform:scale(0)}}.jBox-animated-popOut{animation:jBox-popOut .25s}@keyframes jBox-fadeIn{0%{opacity:0}100%{opacity:1}}.jBox-animated-fadeIn{animation:jBox-fadeIn .2s}@keyframes jBox-fadeOut{0%{opacity:1}100%{opacity:0}}.jBox-animated-fadeOut{animation:jBox-fadeOut .2s}@keyframes jBox-slideUp{0%{transform:translateY(0)}100%{transform:translateY(-300px);opacity:0}}.jBox-animated-slideUp{animation:jBox-slideUp .4s}@keyframes jBox-slideRight{0%{transform:translateX(0)}100%{transform:translateX(300px);opacity:0}}.jBox-animated-slideRight{animation:jBox-slideRight .4s}@keyframes jBox-slideDown{0%{transform:translateY(0)}100%{transform:translateY(300px);opacity:0}}.jBox-animated-slideDown{animation:jBox-slideDown .4s}@keyframes jBox-slideLeft{0%{transform:translateX(0)}100%{transform:translateX(-300px);opacity:0}}.jBox-animated-slideLeft{animation:jBox-slideLeft .4s}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+function jBoxWrapper(b){function n(t,i){return this.options={id:null,width:"auto",height:"auto",minWidth:null,minHeight:null,maxWidth:null,maxHeight:null,responsiveWidth:!0,responsiveHeight:!0,responsiveMinWidth:100,responsiveMinHeight:100,attach:null,trigger:"click",preventDefault:!1,content:null,getContent:null,title:null,getTitle:null,footer:null,isolateScroll:!0,ajax:{url:null,data:"",reload:!1,getURL:"data-url",getData:"data-ajax",setContent:!0,loadingClass:!0,spinner:!0,spinnerDelay:300,spinnerReposition:!0},cancelAjaxOnClose:!0,target:null,position:{x:"center",y:"center"},outside:null,offset:0,attributes:{x:"left",y:"top"},fixed:!1,adjustPosition:!0,adjustTracker:!1,adjustDistance:5,reposition:!0,repositionOnOpen:!0,repositionOnContent:!0,holdPosition:!0,pointer:!1,pointTo:"target",fade:180,animation:null,theme:"Default",addClass:null,overlay:!1,overlayClass:null,zIndex:1e4,delayOpen:0,delayClose:0,closeOnEsc:!1,closeOnClick:!1,closeOnMouseleave:!1,closeButton:!1,appendTo:b("body"),createOnInit:!1,blockScroll:!1,blockScrollAdjust:!0,draggable:!1,dragOver:!0,autoClose:!1,delayOnHover:!1,showCountdown:!1,preloadAudio:!0,audio:null,volume:100,onInit:null,onAttach:null,onPosition:null,onCreated:null,onOpen:null,onClose:null,onCloseComplete:null,onDragStart:null,onDragEnd:null},this._pluginOptions={Tooltip:{getContent:"title",trigger:"mouseenter",position:{x:"center",y:"top"},outside:"y",pointer:!0},Mouse:{responsiveWidth:!1,responsiveHeight:!1,adjustPosition:"flip",target:"mouse",trigger:"mouseenter",position:{x:"right",y:"bottom"},outside:"xy",offset:5},Modal:{target:b(window),fixed:!0,blockScroll:!0,closeOnEsc:!0,closeOnClick:"overlay",closeButton:!0,overlay:!0,animation:"zoomIn"}},this.options=b.extend(!0,this.options,this._pluginOptions[t]||n._pluginOptions[t],i),"string"==b.type(t)&&(this.type=t),this.isTouchDevice=function(){var t=" -webkit- -moz- -o- -ms- ".split(" ");if("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)return!0;var i,t=["(",t.join("touch-enabled),("),"heartz",")"].join("");return i=t,window.matchMedia(i).matches}(),this.isTouchDevice&&"mouseenter"===this.options.trigger&&!1===this.options.closeOnClick&&(this.options.closeOnClick="body"),this._fireEvent=function(t,i){this.options["_"+t]&&this.options["_"+t].bind(this)(i),this.options[t]&&this.options[t].bind(this)(i)},null===this.options.id&&(this.options.id="jBox"+n._getUniqueID()),this.id=this.options.id,("center"==this.options.position.x&&"x"==this.options.outside||"center"==this.options.position.y&&"y"==this.options.outside)&&(this.options.outside=null),"target"!=this.options.pointTo||this.options.outside&&"xy"!=this.options.outside||(this.options.pointer=!1),"object"!=b.type(this.options.offset)?this.options.offset={x:this.options.offset,y:this.options.offset}:this.options.offset=b.extend({x:0,y:0},this.options.offset),"object"!=b.type(this.options.adjustDistance)?this.options.adjustDistance={top:this.options.adjustDistance,right:this.options.adjustDistance,bottom:this.options.adjustDistance,left:this.options.adjustDistance}:this.options.adjustDistance=b.extend({top:5,left:5,right:5,bottom:5},this.options.adjustDistance),this.outside=!(!this.options.outside||"xy"==this.options.outside)&&this.options.position[this.options.outside],this.align=this.outside||("center"!=this.options.position.y&&"number"!=b.type(this.options.position.y)?this.options.position.x:"center"!=this.options.position.x&&"number"!=b.type(this.options.position.x)?this.options.position.y:this.options.attributes.x),n.zIndexMax=Math.max(n.zIndexMax||0,"auto"===this.options.zIndex?1e4:this.options.zIndex),"auto"===this.options.zIndex&&(this.adjustZIndexOnOpen=!0,n.zIndexMax+=2,this.options.zIndex=n.zIndexMax,this.trueModal=this.options.overlay),this._getOpp=function(t){return{left:"right",right:"left",top:"bottom",bottom:"top",x:"y",y:"x"}[t]},this._getXY=function(t){return{left:"x",right:"x",top:"y",bottom:"y",center:"x"}[t]},this._getTL=function(t){return{left:"left",right:"left",top:"top",bottom:"top",center:"left",x:"left",y:"top"}[t]},this._getInt=function(t,i){return"auto"==t?"auto":t&&"string"==b.type(t)&&"%"==t.slice(-1)?b(window)["height"==i?"innerHeight":"innerWidth"]()*parseInt(t.replace("%",""))/100:t},this._createSVG=function(t,i){var s=document.createElementNS("http://www.w3.org/2000/svg",t);return b.each(i,function(t,i){s.setAttribute(i[0],i[1]||"")}),s},this._isolateScroll=function(e){e&&e.length&&e.on("DOMMouseScroll.jBoxIsolateScroll mousewheel.jBoxIsolateScroll",function(t){var i=t.wheelDelta||t.originalEvent&&t.originalEvent.wheelDelta||-t.detail,s=0<=this.scrollTop+e.outerHeight()-this.scrollHeight,o=this.scrollTop<=0;(i<0&&s||0<i&&o)&&t.preventDefault()})},this._setTitleWidth=function(){if(!this.titleContainer||"auto"==this.content[0].style.width&&!this.content[0].style.maxWidth)return null;var t;"none"==this.wrapper.css("display")?(this.wrapper.css("display","block"),t=this.content.outerWidth(),this.wrapper.css("display","none")):t=this.content.outerWidth(),this.titleContainer.css({maxWidth:Math.max(t,parseInt(this.content[0].style.maxWidth))||null})},this._draggable=function(){if(!this.options.draggable)return!1;var t="title"==this.options.draggable?this.titleContainer:this.options.draggable instanceof b?this.options.draggable:"string"==b.type(this.options.draggable)?b(this.options.draggable):this.wrapper;return!(!(t&&t instanceof b&&t.length)||t.data("jBox-draggable"))&&(t.addClass("jBox-draggable").data("jBox-draggable",!0).on("touchstart mousedown",function(t){var i,s,o,e;2==t.button||b(t.target).hasClass("jBox-noDrag")||b(t.target).parents(".jBox-noDrag").length||(this.draggingStartX=t.pageX,this.draggingStartY=t.pageY,this.options.dragOver&&!this.trueModal&&parseInt(this.wrapper.css("zIndex"),10)<=n.zIndexMaxDragover&&(n.zIndexMaxDragover+=1,this.wrapper.css("zIndex",n.zIndexMaxDragover)),i=this.wrapper.outerHeight(),s=this.wrapper.outerWidth(),o=this.wrapper.offset().top+i-t.pageY,e=this.wrapper.offset().left+s-t.pageX,b(document).on("touchmove.jBox-draggable-"+this.id+" mousemove.jBox-draggable-"+this.id,function(t){this.dragging||this.draggingStartX==t.pageX||this.draggingStartY==t.pageY||(this._fireEvent("onDragStart"),this.dragging=!0),this.wrapper.offset({top:t.pageY+o-i,left:t.pageX+e-s})}.bind(this)),t.preventDefault())}.bind(this)).on("touchend mouseup",function(){var t;b(document).off("touchmove.jBox-draggable-"+this.id+" mousemove.jBox-draggable-"+this.id),this.dragging&&this._fireEvent("onDragEnd"),this.dragging=!1,"Modal"!=this.type&&"Confirm"!=this.type||!this.options.holdPosition||(t={x:(t=b("#"+this.id).offset()).left-b(document).scrollLeft(),y:t.top-b(document).scrollTop()},this.position({position:t,offset:{x:0,y:0}}))}.bind(this)),this.trueModal||(n.zIndexMaxDragover=n.zIndexMaxDragover?Math.max(n.zIndexMaxDragover,this.options.zIndex):this.options.zIndex),this)},this._create=function(){var t;this.wrapper||(this.wrapper=b("<div/>",{id:this.id,class:"jBox-wrapper"+(this.type?" jBox-"+this.type:"")+(this.options.theme?" jBox-"+this.options.theme:"")+(this.options.addClass?" "+this.options.addClass:"")}).css({position:this.options.fixed?"fixed":"absolute",display:"none",opacity:0,zIndex:this.options.zIndex}).data("jBox",this),this.options.closeOnMouseleave&&this.wrapper.on("mouseleave",function(t){!this.source||t.relatedTarget!=this.source[0]&&-1===b.inArray(this.source[0],b(t.relatedTarget).parents("*"))&&this.close()}.bind(this)),"box"==this.options.closeOnClick&&this.wrapper.on("click tap",function(){this.close({ignoreDelay:!0})}.bind(this)),this.container=b('<div class="jBox-container"/>').appendTo(this.wrapper),this.content=b('<div class="jBox-content"/>').appendTo(this.container),this.options.footer&&(this.footer=b('<div class="jBox-footer"/>').append(this.options.footer).appendTo(this.container)),this.options.isolateScroll&&this._isolateScroll(this.content),this.options.closeButton&&((t=this._createSVG("svg",[["viewBox","0 0 24 24"]])).appendChild(this._createSVG("path",[["d","M22.2,4c0,0,0.5,0.6,0,1.1l-6.8,6.8l6.9,6.9c0.5,0.5,0,1.1,0,1.1L20,22.3c0,0-0.6,0.5-1.1,0L12,15.4l-6.9,6.9c-0.5,0.5-1.1,0-1.1,0L1.7,20c0,0-0.5-0.6,0-1.1L8.6,12L1.7,5.1C1.2,4.6,1.7,4,1.7,4L4,1.7c0,0,0.6-0.5,1.1,0L12,8.5l6.8-6.8c0.5-0.5,1.1,0,1.1,0L22.2,4z"]])),this.closeButton=b('<div class="jBox-closeButton jBox-noDrag"/>').on("click tap",function(t){this.close({ignoreDelay:!0})}.bind(this)).append(t),"box"!=this.options.closeButton&&(!0!==this.options.closeButton||this.options.overlay||this.options.title||this.options.getTitle)||(this.wrapper.addClass("jBox-closeButton-box"),this.closeButton.appendTo(this.container))),this.wrapper.appendTo(this.options.appendTo),this.wrapper.find(".jBox-closeButton").length&&b.each(["top","right","bottom","left"],function(t,i){this.wrapper.find(".jBox-closeButton").css(i)&&"auto"!=this.wrapper.find(".jBox-closeButton").css(i)&&(this.options.adjustDistance[i]=Math.max(this.options.adjustDistance[i],this.options.adjustDistance[i]+-1*((parseInt(this.wrapper.find(".jBox-closeButton").css(i))||0)+(parseInt(this.container.css("border-"+i+"-width"))||0))))}.bind(this)),this.options.pointer&&(this.pointer={position:"target"!=this.options.pointTo?this.options.pointTo:this._getOpp(this.outside),xy:"target"!=this.options.pointTo?this._getXY(this.options.pointTo):this._getXY(this.outside),align:"center",offset:0},this.pointer.element=b('<div class="jBox-pointer jBox-pointer-'+this.pointer.position+'"/>').appendTo(this.wrapper),this.pointer.dimensions={x:this.pointer.element.outerWidth(),y:this.pointer.element.outerHeight()},"string"==b.type(this.options.pointer)&&((t=this.options.pointer.split(":"))[0]&&(this.pointer.align=t[0]),t[1]&&(this.pointer.offset=parseInt(t[1]))),this.pointer.alignAttribute="x"==this.pointer.xy?"bottom"==this.pointer.align?"bottom":"top":"right"==this.pointer.align?"right":"left",this.wrapper.css("padding-"+this.pointer.position,this.pointer.dimensions[this.pointer.xy]),this.pointer.element.css(this.pointer.alignAttribute,"center"==this.pointer.align?"50%":0).css("margin-"+this.pointer.alignAttribute,this.pointer.offset),this.pointer.margin={},this.pointer.margin["margin-"+this.pointer.alignAttribute]=this.pointer.offset,"center"==this.pointer.align&&this.pointer.element.css("transform","translate("+("y"==this.pointer.xy?-.5*this.pointer.dimensions.x+"px":0)+", "+("x"==this.pointer.xy?-.5*this.pointer.dimensions.y+"px":0)+")"),this.pointer.element.css("x"==this.pointer.xy?"width":"height",parseInt(this.pointer.dimensions[this.pointer.xy])+parseInt(this.container.css("border-"+this.pointer.alignAttribute+"-width"))),this.wrapper.addClass("jBox-pointerPosition-"+this.pointer.position)),this.setContent(this.options.content,!0),this.setTitle(this.options.title,!0),this.options.draggable&&this._draggable(),this._fireEvent("onCreated"))},this.options.createOnInit&&this._create(),this.options.attach&&this.attach(),this._attachEvents=function(){this.options.delayOnHover&&b("#"+this.id).on("mouseenter",function(t){this.isHovered=!0}.bind(this)),this.options.delayOnHover&&b("#"+this.id).on("mouseleave",function(t){this.isHovered=!1}.bind(this)),(this.options.adjustPosition||this.options.reposition)&&!this.fixed&&this.outside&&(this.options.adjustTracker&&b(window).on("scroll.jBox-"+this.id,function(t){this.position()}.bind(this)),(this.options.adjustPosition||this.options.reposition)&&b(window).on("resize.jBox-"+this.id,function(t){this.position()}.bind(this))),"mouse"==this.options.target&&b("body").on("mousemove.jBox-"+this.id,function(t){this.position({mouseTarget:{top:t.pageY,left:t.pageX}})}.bind(this))},this._detachEvents=function(){this.options.closeOnEsc&&b(document).off("keyup.jBox-"+this.id),!0!==this.options.closeOnClick&&"body"!=this.options.closeOnClick||b(document).off("click.jBox-"+this.id+" tap.jBox-"+this.id),this.options.adjustTracker&&b(window).off("scroll.jBox-"+this.id),(this.options.adjustPosition||this.options.reposition)&&b(window).off("resize.jBox-"+this.id),"mouse"==this.options.target&&b("body").off("mousemove.jBox-"+this.id)},this._showOverlay=function(){this.overlay||(this.overlay=b('<div id="'+this.id+'-overlay"/>').addClass("jBox-overlay"+(this.type?" jBox-overlay-"+this.type:"")).css({display:"none",opacity:0,zIndex:this.options.zIndex-1}).appendTo(this.options.appendTo),this.options.overlayClass&&this.overlay.addClass(this.options.overlayClass),"overlay"!=this.options.closeButton&&!0!==this.options.closeButton||this.overlay.append(this.closeButton),"overlay"==this.options.closeOnClick&&this.overlay.on("click tap",function(){this.close({ignoreDelay:!0})}.bind(this)),b("#"+this.id+"-overlay .jBox-closeButton").length&&(this.options.adjustDistance.top=Math.max(b("#"+this.id+"-overlay .jBox-closeButton").outerHeight(),this.options.adjustDistance.top))),!0===this.adjustZIndexOnOpen&&this.overlay.css("zIndex",parseInt(this.wrapper.css("zIndex"),10)-1),"block"!=this.overlay.css("display")&&(this.options.fade?this.overlay.stop()&&this.overlay.animate({opacity:1},{queue:!1,duration:this.options.fade,start:function(){this.overlay.css({display:"block"})}.bind(this)}):this.overlay.css({display:"block",opacity:1}))},this._hideOverlay=function(){this.overlay&&(this.options.fade?this.overlay.stop()&&this.overlay.animate({opacity:0},{queue:!1,duration:this.options.fade,complete:function(){this.overlay.css({display:"none"})}.bind(this)}):this.overlay.css({display:"none",opacity:0}))},this._exposeDimensions=function(){this.wrapper.css({top:-1e4,left:-1e4,right:"auto",bottom:"auto"});var t={x:this.wrapper.outerWidth(),y:this.wrapper.outerHeight()};return this.wrapper.css({top:"auto",left:"auto"}),t},this._generateAnimationCSS=function(){if("object"!=b.type(this.options.animation)&&(this.options.animation={pulse:{open:"pulse",close:"zoomOut"},zoomIn:{open:"zoomIn",close:"zoomIn"},zoomOut:{open:"zoomOut",close:"zoomOut"},move:{open:"move",close:"move"},slide:{open:"slide",close:"slide"},flip:{open:"flip",close:"flip"},tada:{open:"tada",close:"zoomOut"}}[this.options.animation]),!this.options.animation)return null;this.options.animation.open&&(this.options.animation.open=this.options.animation.open.split(":")),this.options.animation.close&&(this.options.animation.close=this.options.animation.close.split(":")),this.options.animation.openDirection=this.options.animation.open[1]||null,this.options.animation.closeDirection=this.options.animation.close[1]||null,this.options.animation.open&&(this.options.animation.open=this.options.animation.open[0]),this.options.animation.close&&(this.options.animation.close=this.options.animation.close[0]),this.options.animation.open&&(this.options.animation.open+="Open"),this.options.animation.close&&(this.options.animation.close+="Close");var a={pulse:{duration:350,css:[["0%","scale(1)"],["50%","scale(1.1)"],["100%","scale(1)"]]},zoomInOpen:{duration:this.options.fade||180,css:[["0%","scale(0.9)"],["100%","scale(1)"]]},zoomInClose:{duration:this.options.fade||180,css:[["0%","scale(1)"],["100%","scale(0.9)"]]},zoomOutOpen:{duration:this.options.fade||180,css:[["0%","scale(1.1)"],["100%","scale(1)"]]},zoomOutClose:{duration:this.options.fade||180,css:[["0%","scale(1)"],["100%","scale(1.1)"]]},moveOpen:{duration:this.options.fade||180,positions:{top:{"0%":-12},right:{"0%":12},bottom:{"0%":12},left:{"0%":-12}},css:[["0%","translate%XY(%Vpx)"],["100%","translate%XY(0px)"]]},moveClose:{duration:this.options.fade||180,timing:"ease-in",positions:{top:{"100%":-12},right:{"100%":12},bottom:{"100%":12},left:{"100%":-12}},css:[["0%","translate%XY(0px)"],["100%","translate%XY(%Vpx)"]]},slideOpen:{duration:400,positions:{top:{"0%":-400},right:{"0%":400},bottom:{"0%":400},left:{"0%":-400}},css:[["0%","translate%XY(%Vpx)"],["100%","translate%XY(0px)"]]},slideClose:{duration:400,timing:"ease-in",positions:{top:{"100%":-400},right:{"100%":400},bottom:{"100%":400},left:{"100%":-400}},css:[["0%","translate%XY(0px)"],["100%","translate%XY(%Vpx)"]]},flipOpen:{duration:600,css:[["0%","perspective(400px) rotateX(90deg)"],["40%","perspective(400px) rotateX(-15deg)"],["70%","perspective(400px) rotateX(15deg)"],["100%","perspective(400px) rotateX(0deg)"]]},flipClose:{duration:this.options.fade||300,css:[["0%","perspective(400px) rotateX(0deg)"],["100%","perspective(400px) rotateX(90deg)"]]},tada:{duration:800,css:[["0%","scale(1)"],["10%, 20%","scale(0.9) rotate(-3deg)"],["30%, 50%, 70%, 90%","scale(1.1) rotate(3deg)"],["40%, 60%, 80%","scale(1.1) rotate(-3deg)"],["100%","scale(1) rotate(0)"]]}};b.each(["pulse","tada"],function(t,i){a[i+"Open"]=a[i+"Close"]=a[i]});var o=function(o,e){var n="@keyframes jBox-"+this.id+"-animation-"+this.options.animation[o]+"-"+o+(e?"-"+e:"")+" {";return b.each(a[this.options.animation[o]].css,function(t,i){var s=e?i[1].replace("%XY",this._getXY(e).toUpperCase()):i[1];a[this.options.animation[o]].positions&&(s=s.replace("%V",a[this.options.animation[o]].positions[e][i[0]])),n+=i[0]+" {transform:"+s+";}"}.bind(this)),n+="}",n+=".jBox-"+this.id+"-animation-"+this.options.animation[o]+"-"+o+(e?"-"+e:"")+" {",n+="animation-duration: "+a[this.options.animation[o]].duration+"ms;",n+="animation-name: jBox-"+this.id+"-animation-"+this.options.animation[o]+"-"+o+(e?"-"+e:"")+";",n+=a[this.options.animation[o]].timing?"animation-timing-function: "+a[this.options.animation[o]].timing+";":"",n+="}"}.bind(this);this._animationCSS="",b.each(["open","close"],function(t,s){if(!this.options.animation[s]||!a[this.options.animation[s]]||"close"==s&&!this.options.fade)return"";a[this.options.animation[s]].positions?b.each(["top","right","bottom","left"],function(t,i){this._animationCSS+=o(s,i)}.bind(this)):this._animationCSS+=o(s)}.bind(this))},this.options.animation&&this._generateAnimationCSS(),this._blockBodyClick=function(){this.blockBodyClick=!0,setTimeout(function(){this.blockBodyClick=!1}.bind(this),10)},this._animate=function(t){if(t=t||(this.isOpen?"open":"close"),!this.options.fade&&"close"==t)return null;var i=this.options.animation[t+"Direction"]||("center"!=this.align?this.align:this.options.attributes.x);this.flipped&&this._getXY(i)==this._getXY(this.align)&&(i=this._getOpp(i));var s="jBox-"+this.id+"-animation-"+this.options.animation[t]+"-"+t+" jBox-"+this.id+"-animation-"+this.options.animation[t]+"-"+t+"-"+i;this.wrapper.addClass(s);i=1e3*parseFloat(this.wrapper.css("animation-duration"));"close"==t&&(i=Math.min(i,this.options.fade)),setTimeout(function(){this.wrapper.removeClass(s)}.bind(this),i)},this._abortAnimation=function(){var t=this.wrapper.attr("class").split(" ").filter(function(t){return 0!==t.lastIndexOf("jBox-"+this.id+"-animation",0)}.bind(this));this.wrapper.attr("class",t.join(" "))},(this.options.responsiveWidth||this.options.responsiveHeight)&&b(window).on("resize.responsivejBox-"+this.id,function(t){this.isOpen&&this.position()}.bind(this)),"string"===b.type(this.options.preloadAudio)&&(this.options.preloadAudio=[this.options.preloadAudio]),"string"===b.type(this.options.audio)&&(this.options.audio={open:this.options.audio}),"number"===b.type(this.options.volume)&&(this.options.volume={open:this.options.volume,close:this.options.volume}),!0===this.options.preloadAudio&&this.options.audio&&(this.options.preloadAudio=[],b.each(this.options.audio,function(t,i){this.options.preloadAudio.push(i+".mp3"),this.options.preloadAudio.push(i+".ogg")}.bind(this))),this.options.preloadAudio.length&&b.each(this.options.preloadAudio,function(t,i){var s=new Audio;s.src=i,s.preload="auto"}),this._fireEvent("onInit"),this}var t,i;return n.prototype.attach=function(t,o){return t=t||this.options.attach,"string"==b.type(t)&&(t=b(t)),o=o||this.options.trigger,t&&t.length&&b.each(t,function(t,s){(s=b(s)).data("jBox-attached-"+this.id)||("title"==this.options.getContent&&null!=s.attr("title")&&s.data("jBox-getContent",s.attr("title")).removeAttr("title"),this.attachedElements||(this.attachedElements=[]),this.attachedElements.push(s[0]),s.on(o+".jBox-attach-"+this.id,function(t){var i;this.timer&&clearTimeout(this.timer),"mouseenter"==o&&this.isOpen&&this.source[0]==s[0]||(this.isOpen&&this.source&&this.source[0]!=s[0]&&(i=!0),this.source=s,this.options.target||(this.target=s),"click"==o&&this.options.preventDefault&&t.preventDefault(),this["click"!=o||i?"open":"toggle"]())}.bind(this)),"mouseenter"==this.options.trigger&&s.on("mouseleave",function(t){if(!this.wrapper)return null;this.options.closeOnMouseleave&&(t.relatedTarget==this.wrapper[0]||b(t.relatedTarget).parents("#"+this.id).length)||this.close()}.bind(this)),s.data("jBox-attached-"+this.id,o),this._fireEvent("onAttach",s))}.bind(this)),this},n.prototype.detach=function(t){return(t=t||(this.attachedElements||[]))&&t.length&&b.each(t,function(t,i){(i=b(i)).data("jBox-attached-"+this.id)&&(i.off(i.data("jBox-attached-"+this.id)+".jBox-attach-"+this.id),i.data("jBox-attached-"+this.id,null)),this.attachedElements=b.grep(this.attachedElements,function(t){return t!=i[0]})}.bind(this)),this},n.prototype.setTitle=function(t,i){if(null==t||null==t)return this;this.wrapper||this._create();var s=this.wrapper.outerHeight(),o=this.wrapper.outerWidth();return this.title||(this.titleContainer=b('<div class="jBox-title"/>'),this.title=b("<div/>").appendTo(this.titleContainer),"title"!=this.options.closeButton&&(!0!==this.options.closeButton||this.options.overlay)||(this.wrapper.addClass("jBox-closeButton-title"),this.closeButton.appendTo(this.titleContainer)),this.titleContainer.insertBefore(this.content),this._setTitleWidth()),this.wrapper[t?"addClass":"removeClass"]("jBox-hasTitle"),this.title.html(t),o!=this.wrapper.outerWidth()&&this._setTitleWidth(),this.options.draggable&&this._draggable(),i||!this.options.repositionOnContent||s==this.wrapper.outerHeight()&&o==this.wrapper.outerWidth()||this.position(),this},n.prototype.setContent=function(t,i){if(null==t||null==t)return this;this.wrapper||this._create();var s=this.wrapper.outerHeight(),o=this.wrapper.outerWidth();switch(this.content.children("[data-jbox-content-appended]").appendTo("body").css({display:"none"}),b.type(t)){case"string":this.content.html(t);break;case"object":t&&(t instanceof b||t.constructor.prototype.jquery)?(this.content.html(""),t.attr("data-jbox-content-appended",1).appendTo(this.content).css({display:"block"})):this.content.html(JSON.stringify(t))}return o!=this.wrapper.outerWidth()&&this._setTitleWidth(),this.options.draggable&&this._draggable(),i||!this.options.repositionOnContent||s==this.wrapper.outerHeight()&&o==this.wrapper.outerWidth()||this.position(),this},n.prototype.setDimensions=function(t,i,s){this.wrapper||this._create(),null==i&&(i="auto"),this.content.css(t,this._getInt(i)),"width"==t&&this._setTitleWidth(),this.options[t]=i,null!=s&&!s||this.position()},n.prototype.setWidth=function(t,i){this.setDimensions("width",t,i)},n.prototype.setHeight=function(t,i){this.setDimensions("height",t,i)},n.prototype.position=function(s){if(s=s||{},s=b.extend(!0,this.options,s),this.target=s.target||this.target||b(window),this.target instanceof b||"mouse"==this.target||(this.target=b(this.target)),!this.target.length)return this;this.content.css({width:this._getInt(s.width,"width"),height:this._getInt(s.height,"height"),minWidth:this._getInt(s.minWidth,"width"),minHeight:this._getInt(s.minHeight,"height"),maxWidth:this._getInt(s.maxWidth,"width"),maxHeight:this._getInt(s.maxHeight,"height")}),this._setTitleWidth();var o=this._exposeDimensions();"mouse"==this.target||this.target.data("jBox-"+this.id+"-fixed")||this.target.data("jBox-"+this.id+"-fixed",this.target[0]!=b(window)[0]&&("fixed"==this.target.css("position")||0<this.target.parents().filter(function(){return"fixed"==b(this).css("position")}).length)?"fixed":"static");var t={x:b(window).outerWidth(),y:b(window).outerHeight(),top:s.fixed&&this.target.data("jBox-"+this.id+"-fixed")?0:b(window).scrollTop(),left:s.fixed&&this.target.data("jBox-"+this.id+"-fixed")?0:b(window).scrollLeft()};t.bottom=t.top+t.y,t.right=t.left+t.x;try{var i=this.target.offset()}catch(t){i={top:0,left:0}}"mouse"!=this.target&&"fixed"==this.target.data("jBox-"+this.id+"-fixed")&&s.fixed&&(i.top=i.top-b(window).scrollTop(),i.left=i.left-b(window).scrollLeft());var e={x:"mouse"==this.target?12:this.target.outerWidth(),y:"mouse"==this.target?20:this.target.outerHeight(),top:"mouse"==this.target&&s.mouseTarget?s.mouseTarget.top:i?i.top:0,left:"mouse"==this.target&&s.mouseTarget?s.mouseTarget.left:i?i.left:0},n=s.outside&&!("center"==s.position.x&&"center"==s.position.y),a={x:t.x-s.adjustDistance.left-s.adjustDistance.right,y:t.y-s.adjustDistance.top-s.adjustDistance.bottom,left:n?e.left-b(window).scrollLeft()-s.adjustDistance.left:0,right:n?t.x-e.left+b(window).scrollLeft()-e.x-s.adjustDistance.right:0,top:n?e.top-b(window).scrollTop()-this.options.adjustDistance.top:0,bottom:n?t.y-e.top+b(window).scrollTop()-e.y-s.adjustDistance.bottom:0},h={x:"x"!=s.outside&&"xy"!=s.outside||"number"==b.type(s.position.x)?null:s.position.x,y:"y"!=s.outside&&"xy"!=s.outside||"number"==b.type(s.position.y)?null:s.position.y},r={x:!1,y:!1};h.x&&o.x>a[h.x]&&a[this._getOpp(h.x)]>a[h.x]&&(h.x=this._getOpp(h.x))&&(r.x=!0),h.y&&o.y>a[h.y]&&a[this._getOpp(h.y)]>a[h.y]&&(h.y=this._getOpp(h.y))&&(r.y=!0),(s.responsiveWidth||s.responsiveHeight)&&(f=function(){var t;s.responsiveWidth&&o.x>a[h.x||"x"]&&(t=a[h.x||"x"]-(this.pointer&&n&&"x"==s.outside?this.pointer.dimensions.x:0)-parseInt(this.container.css("border-left-width"))-parseInt(this.container.css("border-right-width")),this.content.css({width:t>this.options.responsiveMinWidth?t:null,minWidth:t<parseInt(this.content.css("minWidth"))?0:null}),this._setTitleWidth()),o=this._exposeDimensions()}.bind(this),s.responsiveWidth&&f(),s.responsiveWidth&&!r.y&&h.y&&o.y>a[h.y]&&a[this._getOpp(h.y)]>a[h.y]&&(h.y=this._getOpp(h.y))&&(r.y=!0),x=function(){var t;s.responsiveHeight&&o.y>a[h.y||"y"]&&(t=function(){return this.titleContainer||this.footer?("none"==this.wrapper.css("display")?(this.wrapper.css("display","block"),t=(this.titleContainer?this.titleContainer.outerHeight():0)+(this.footer?this.footer.outerHeight():0),this.wrapper.css("display","none")):t=(this.titleContainer?this.titleContainer.outerHeight():0)+(this.footer?this.footer.outerHeight():0),t||0):0;var t}.bind(this),t=a[h.y||"y"]-(this.pointer&&n&&"y"==s.outside?this.pointer.dimensions.y:0)-t()-parseInt(this.container.css("border-top-width"))-parseInt(this.container.css("border-bottom-width")),this.content.css({height:t>this.options.responsiveMinHeight?t:null}),this._setTitleWidth()),o=this._exposeDimensions()}.bind(this),s.responsiveHeight&&x(),s.responsiveHeight&&!r.x&&h.x&&o.x>a[h.x]&&a[this._getOpp(h.x)]>a[h.x]&&(h.x=this._getOpp(h.x))&&(r.x=!0),s.adjustPosition&&"move"!=s.adjustPosition&&(r.x&&f(),r.y&&x()));var p={},l=function(t){if("number"!=b.type(s.position[t])){var i=s.attributes[t]="x"==t?"left":"top";if(p[i]=e[i],"center"==s.position[t])return p[i]+=Math.ceil((e[t]-o[t])/2),void("mouse"!=this.target&&this.target[0]&&this.target[0]==b(window)[0]&&(p[i]+=.5*(s.adjustDistance[i]-s.adjustDistance[this._getOpp(i)])));i!=s.position[t]&&(p[i]+=e[t]-o[t]),s.outside!=t&&"xy"!=s.outside||(p[i]+=o[t]*(i!=s.position[t]?1:-1))}else p[s.attributes[t]]=s.position[t]}.bind(this);if(l("x"),l("y"),this.pointer&&"target"==s.pointTo&&"number"!=b.type(s.position.x)&&"number"!=b.type(s.position.y)&&(y=0,"center"===this.pointer.align?"center"!=s.position[this._getOpp(s.outside)]&&(y+=o[this._getOpp(s.outside)]/2):"center"===s.position[this._getOpp(s.outside)]?y+=(o[this._getOpp(s.outside)]/2-this.pointer.dimensions[this._getOpp(s.outside)]/2)*(this.pointer.align==this._getTL(this.pointer.align)?1:-1):y+=this.pointer.align!=s.position[this._getOpp(s.outside)]?this.dimensions[this._getOpp(s.outside)]*(-1!==b.inArray(this.pointer.align,["top","left"])?1:-1)+this.pointer.dimensions[this._getOpp(s.outside)]/2*(-1!==b.inArray(this.pointer.align,["top","left"])?-1:1):this.pointer.dimensions[this._getOpp(s.outside)]/2*(-1!==b.inArray(this.pointer.align,["top","left"])?1:-1),y*=s.position[this._getOpp(s.outside)]==this.pointer.alignAttribute?-1:1,y+=this.pointer.offset*(this.pointer.align==this._getOpp(this._getTL(this.pointer.align))?1:-1),p[this._getTL(this._getOpp(this.pointer.xy))]+=y),p[s.attributes.x]+=s.offset.x,p[s.attributes.y]+=s.offset.y,this.wrapper.css(p),s.adjustPosition){this.positionAdjusted&&(this.pointer&&this.wrapper.css("padding",0).css("padding-"+this._getOpp(this.outside),this.pointer.dimensions[this._getXY(this.outside)]).removeClass("jBox-pointerPosition-"+this._getOpp(this.pointer.position)).addClass("jBox-pointerPosition-"+this.pointer.position),this.pointer&&this.pointer.element.attr("class","jBox-pointer jBox-pointer-"+this._getOpp(this.outside)).css(this.pointer.margin),this.positionAdjusted=!1,this.flipped=!1);var d=t.top>p.top-(s.adjustDistance.top||0),c=t.right<p.left+o.x+(s.adjustDistance.right||0),u=t.bottom<p.top+o.y+(s.adjustDistance.bottom||0),g=t.left>p.left-(s.adjustDistance.left||0),m=g?"left":c?"right":null,f=d?"top":u?"bottom":null;if(m||f){if(("Modal"==this.type||"Confirm"==this.type)&&"number"==b.type(this.options.position.x)&&"number"==b.type(this.options.position.y)){var x=0,y=0;return this.options.holdPosition&&(g?x=t.left-(p.left-(s.adjustDistance.left||0)):c&&(x=t.right-(p.left+o.x+(s.adjustDistance.right||0))),d?y=t.top-(p.top-(s.adjustDistance.top||0)):u&&(y=t.bottom-(p.top+o.y+(s.adjustDistance.bottom||0))),this.options.position.x=Math.max(t.top,this.options.position.x+x),this.options.position.y=Math.max(t.left,this.options.position.y+y),l("x"),l("y"),this.wrapper.css(p)),this._fireEvent("onPosition"),this}!0!==s.adjustPosition&&"flip"!==s.adjustPosition||(v=function(t){this.wrapper.css(this._getTL(t),p[this._getTL(t)]+(o[this._getXY(t)]+s.offset[this._getXY(t)]*("top"==t||"left"==t?-2:2)+e[this._getXY(t)])*("top"==t||"left"==t?1:-1)),this.pointer&&this.wrapper.removeClass("jBox-pointerPosition-"+this.pointer.position).addClass("jBox-pointerPosition-"+this._getOpp(this.pointer.position)).css("padding",0).css("padding-"+t,this.pointer.dimensions[this._getXY(t)]),this.pointer&&this.pointer.element.attr("class","jBox-pointer jBox-pointer-"+t),this.positionAdjusted=!0,this.flipped=!0}.bind(this),r.x&&v(this.options.position.x),r.y&&v(this.options.position.y));var v="x"==this._getXY(this.outside)?f:m;this.pointer&&"target"==s.pointTo&&"flip"!=s.adjustPosition&&this._getXY(v)==this._getOpp(this._getXY(this.outside))&&(f="center"==this.pointer.align?o[this._getXY(v)]/2-this.pointer.dimensions[this._getOpp(this.pointer.xy)]/2-parseInt(this.pointer.element.css("margin-"+this.pointer.alignAttribute))*(v!=this._getTL(v)?-1:1):v==this.pointer.alignAttribute?parseInt(this.pointer.element.css("margin-"+this.pointer.alignAttribute)):o[this._getXY(v)]-parseInt(this.pointer.element.css("margin-"+this.pointer.alignAttribute))-this.pointer.dimensions[this._getXY(v)],m=v==this._getTL(v)?t[this._getTL(v)]-p[this._getTL(v)]+s.adjustDistance[v]:-1*(t[this._getOpp(this._getTL(v))]-p[this._getTL(v)]-s.adjustDistance[v]-o[this._getXY(v)]),v==this._getOpp(this._getTL(v))&&p[this._getTL(v)]-m<t[this._getTL(v)]+s.adjustDistance[this._getTL(v)]&&(m-=t[this._getTL(v)]+s.adjustDistance[this._getTL(v)]-(p[this._getTL(v)]-m)),(m=Math.min(m,f))<=f&&0<m&&(this.pointer.element.css("margin-"+this.pointer.alignAttribute,parseInt(this.pointer.element.css("margin-"+this.pointer.alignAttribute))-m*(v!=this.pointer.alignAttribute?-1:1)),this.wrapper.css(this._getTL(v),p[this._getTL(v)]+m*(v!=this._getTL(v)?-1:1)),this.positionAdjusted=!0))}}return this._fireEvent("onPosition"),this},(n.prototype.unscroll=function(t){if(this.set=function(t,i){window.unscrollStore||(window.unscrollStore={}),window.unscrollStore[t]=i},this.get=function(t){return window.unscrollStore?window.unscrollStore[t]:null},this.getScrollbarWidth=function(){if(this.get("scrollbarWidth"))return this.get("scrollbarWidth")+"px";var t=document.createElement("div");t.style.width="100px",t.style.height="100px",t.style.overflow="scroll",t.style.position="absolute",t.style.top="-10000",document.body.appendChild(t);var i=t.offsetWidth-t.clientWidth;return document.body.removeChild(t),this.set("scrollbarWidth",i),i+"px"},this.getElementsToAdjust=function(s){(s="string"==typeof(s=s||[])?[[s,"padding-right"]]:s).forEach(function(t,i){"string"==typeof t&&(s[i]=[t,"padding-right"])});for(var t=!1,i=0;i<s.length;i++)-1!==s[i][0].indexOf("body")&&(t=!0);return!1===t&&s.push(["body","padding-right"]),s},this.pageHasScrollbar=function(){return this.getScrollbarWidth()&&document.body.offsetHeight>window.innerHeight},this.pageHasScrollbar()){t=this.getElementsToAdjust(t);for(var i=0;i<t.length;i++)for(var s=document.querySelectorAll(t[i][0]),o=0;o<s.length;o++){if(s[o].getAttribute("data-unscroll"))return;var e=t[i][1],n=window.getComputedStyle(s[o]).getPropertyValue(e);s[o].setAttribute("data-unscroll",e),n=n||"0px";var a="padding-right"==e||"right"==e?"+":"-";s[o].style[e]="calc("+n+" "+a+" "+this.getScrollbarWidth()+")"}}var h,r;document.getElementById("unscroll-class-name")||(h=document.head||document.getElementsByTagName("head")[0],(r=document.createElement("style")).type="text/css",r.setAttribute("id","unscroll-class-name"),r.appendChild(document.createTextNode(".unscrollable { overflow: hidden !important; }")),h.appendChild(r)),document.body.classList.add("unscrollable")}).reset=function(){for(var t=document.querySelectorAll("[data-unscroll]"),i=0;i<t.length;i++){var s=t[i].getAttribute("data-unscroll");t[i].style[s]=null,t[i].removeAttribute("data-unscroll")}document.body.classList.remove("unscrollable")},n.prototype.open=function(t){if(t=t||{},this.isDestroyed)return this;if(this.wrapper||this._create(),this._styles||(this._styles=b("<style/>").append(this._animationCSS).appendTo(b("head"))),this.timer&&clearTimeout(this.timer),this._blockBodyClick(),this.isDisabled)return this;this.options.closeOnEsc&&b(document).on("keyup.jBox-"+this.id,function(t){27==t.keyCode&&this.close({ignoreDelay:!0})}.bind(this)),!0!==this.options.closeOnClick&&"body"!==this.options.closeOnClick||(b("body").on("click.jBox-"+this.id+" tap.jBox-"+this.id,function(t){this.blockBodyClick||"body"==this.options.closeOnClick&&(t.target==this.wrapper[0]||this.wrapper.has(t.target).length)||this.close({ignoreDelay:!0})}.bind(this)),this.isTouchDevice&&b("body > *").on("click.jBox-"+this.id+" tap.jBox-"+this.id,function(){return!0}));var i=function(){!0===this.adjustZIndexOnOpen&&(n.zIndexMax=Math.max(parseInt(this.wrapper.css("zIndex"),10),this.options.zIndex,n.zIndexMax||0,n.zIndexMaxDragover||0)+2,this.wrapper.css("zIndex",n.zIndexMax),this.options.zIndex=n.zIndexMax),this.source&&this.options.getTitle&&this.source.attr(this.options.getTitle)&&this.setTitle(this.source.attr(this.options.getTitle),!0),this.source&&this.options.getContent&&(this.source.data("jBox-getContent")?this.setContent(this.source.data("jBox-getContent"),!0):this.source.attr(this.options.getContent)?this.setContent(this.source.attr(this.options.getContent),!0):"html"==this.options.getContent&&this.setContent(this.source.html(),!0)),this._fireEvent("onOpen"),(this.options.ajax&&(this.options.ajax.url||this.source&&this.source.attr(this.options.ajax.getURL))&&(!this.ajaxLoaded||this.options.ajax.reload)||t.ajax&&(t.ajax.url||t.ajax.data))&&("strict"==this.options.ajax.reload||!this.source||!this.source.data("jBox-ajax-data")||t.ajax&&(t.ajax.url||t.ajax.data)?this.ajax(t.ajax||null,!0):this.setContent(this.source.data("jBox-ajax-data"))),this.positionedOnOpen&&!this.options.repositionOnOpen||!this.position(t)||(this.positionedOnOpen=!0),this.isClosing&&this._abortAnimation(),this.isOpen||(this.isOpen=!0,this.options.autoClose&&(this.options.delayClose=this.options.autoClose)&&this.close(),this._attachEvents(),this.options.blockScroll&&(this.options.blockScrollAdjust?n.blockScrollScopes?n.blockScrollScopes++:(n.blockScrollScopes=1,this.unscroll(Array.isArray(this.options.blockScrollAdjust)||"string"==typeof this.options.blockScrollAdjust?this.options.blockScrollAdjust:null)):b("body").addClass("jBox-blockScroll-"+this.id)),this.options.overlay&&(this._showOverlay(),this.position()),this.options.animation&&!this.isClosing&&this._animate("open"),this.options.audio&&this.options.audio.open&&this.audio(this.options.audio.open,this.options.volume.open),this.options.fade?this.wrapper.stop().animate({opacity:1},{queue:!1,duration:this.options.fade,start:function(){this.isOpening=!0,this.wrapper.css({display:"block"})}.bind(this),always:function(){this.isOpening=!1,setTimeout(function(){this.positionOnFadeComplete&&this.position()&&(this.positionOnFadeComplete=!1)}.bind(this),10)}.bind(this)}):(this.wrapper.css({display:"block",opacity:1}),this.positionOnFadeComplete&&this.position()&&(this.positionOnFadeComplete=!1)))}.bind(this);return!this.options.delayOpen||this.isOpen||this.isClosing||t.ignoreDelay?i():this.timer=setTimeout(i,this.options.delayOpen),this},n.prototype.close=function(t){if(t=t||{},b("body").off("click.jBox-"+this.id+" tap.jBox-"+this.id),this.isTouchDevice&&b("body > *").off("click.jBox-"+this.id+" tap.jBox-"+this.id),this.isDestroyed||this.isClosing)return this;if(this.timer&&clearTimeout(this.timer),this._blockBodyClick(),this.isDisabled)return this;var i,s,o,e=function(){var t;this._fireEvent("onClose"),this.options.cancelAjaxOnClose&&this.cancelAjax(),this.isOpen&&(this.isOpen=!1,this._detachEvents(),this.options.blockScroll&&(this.options.blockScrollAdjust?(n.blockScrollScopes=n.blockScrollScopes?--n.blockScrollScopes:0)||this.unscroll.reset():b("body").removeClass("jBox-blockScroll-"+this.id)),this.options.overlay&&this._hideOverlay(),this.options.animation&&!this.isOpening&&this._animate("close"),this.options.audio&&this.options.audio.close&&this.audio(this.options.audio.close,this.options.volume.close),(t=this.isTouchDevice&&"mouse"==this.options.target?0:this.options.fade)?this.wrapper.stop().animate({opacity:0},{queue:!1,duration:t,start:function(){this.isClosing=!0}.bind(this),complete:function(){this.wrapper.css({display:"none"}),this._fireEvent("onCloseComplete")}.bind(this),always:function(){this.isClosing=!1}.bind(this)}):(this.wrapper.css({display:"none",opacity:0}),this._fireEvent("onCloseComplete")))}.bind(this);return t.ignoreDelay||this.isTouchDevice&&"mouse"==this.options.target?e():(this.options.delayOnHover||this.options.showCountdown)&&10<this.options.delayClose?(s=(i=this).options.delayClose,o=Date.now(),this.options.showCountdown&&!this.inner&&(t=b('<div class="jBox-countdown" />'),this.inner=b('<div class="jBox-countdown-inner" />'),t.prepend(this.inner),b("#"+this.id).append(t)),this.countdown=function(){var t=Date.now();i.isHovered||(s-=t-o),o=t,0<s?(i.options.showCountdown&&i.inner.css("width",100*s/i.options.delayClose+"%"),window.requestAnimationFrame(i.countdown)):e()},window.requestAnimationFrame(this.countdown)):this.timer=setTimeout(e,Math.max(this.options.delayClose,10)),this},n.prototype.toggle=function(t){return this[this.isOpen?"close":"open"](t),this},n.prototype.disable=function(){return this.isDisabled=!0,this},n.prototype.enable=function(){return this.isDisabled=!1,this},n.prototype.hide=function(){return this.disable(),this.wrapper&&(this.cacheWrapperDisplay=this.wrapper.css("display"),this.wrapper.css({display:"none"})),this.overlay&&(this.cacheOverlayDisplay=this.overlay.css("display"),this.overlay.css({display:"none"})),this},n.prototype.show=function(){return this.enable(),this.wrapper&&this.cacheWrapperDisplay&&(this.wrapper.css({display:this.cacheWrapperDisplay}),this.cacheWrapperDisplay=null),this.overlay&&this.cacheOverlayDisplay&&(this.overlay.css({display:this.cacheOverlayDisplay}),this.cacheOverlayDisplay=null),this},n.prototype.ajax=function(s,i){s=s||{},b.each([["getData","data"],["getURL","url"]],function(t,i){this.options.ajax[i[0]]&&!s[i[1]]&&this.source&&null!=this.source.attr(this.options.ajax[i[0]])&&(s[i[1]]=this.source.attr(this.options.ajax[i[0]])||"")}.bind(this));var t=b.extend(!0,{},this.options.ajax);this.cancelAjax();var o=s.beforeSend||t.beforeSend||function(){},e=s.complete||t.complete||function(){},n=s.success||t.success||function(){},a=s.error||t.error||function(){},h=b.extend(!0,t,s);return h.beforeSend=function(t){h.loadingClass&&this.wrapper.addClass(!0===h.loadingClass?"jBox-loading":h.loadingClass),h.spinner&&(this.spinnerDelay=setTimeout(function(){this.wrapper.addClass("jBox-loading-spinner"),h.spinnerReposition&&(i?this.positionOnFadeComplete=!0:this.position()),this.spinner=b(!0!==h.spinner?h.spinner:'<div class="jBox-spinner"></div>').appendTo(this.container),this.titleContainer&&"absolute"==this.spinner.css("position")&&this.spinner.css({transform:"translateY("+.5*this.titleContainer.outerHeight()+"px)"})}.bind(this),""!=this.content.html()&&h.spinnerDelay||0)),o.bind(this)(t)}.bind(this),h.complete=function(t){this.spinnerDelay&&clearTimeout(this.spinnerDelay),this.wrapper.removeClass("jBox-loading jBox-loading-spinner jBox-loading-spinner-delay"),this.spinner&&this.spinner.length&&this.spinner.remove()&&h.spinnerReposition&&(i?this.positionOnFadeComplete=!0:this.position()),this.ajaxLoaded=!0,e.bind(this)(t)}.bind(this),h.success=function(t){h.setContent&&this.setContent(t,!0)&&(i?this.positionOnFadeComplete=!0:this.position()),h.setContent&&this.source&&this.source.data("jBox-ajax-data",t),n.bind(this)(t)}.bind(this),h.error=function(t){a.bind(this)(t)}.bind(this),this.ajaxRequest=b.ajax(h),this},n.prototype.cancelAjax=function(){this.ajaxRequest&&(this.ajaxRequest.abort(),this.ajaxLoaded=!1)},n.prototype.audio=function(t,i){if(!t)return this;var s;(n._audio=!n._audio?{}:n._audio)[t]||(s=b("<audio/>"),b("<source/>",{src:t+".mp3"}).appendTo(s),b("<source/>",{src:t+".ogg"}).appendTo(s),n._audio[t]=s[0]),n._audio[t].volume=Math.min((null!=i?i:100)/100,1);try{n._audio[t].pause(),n._audio[t].currentTime=0}catch(t){}return n._audio[t].play(),this},n._animationSpeeds={tada:1e3,tadaSmall:1e3,flash:500,shake:400,pulseUp:250,pulseDown:250,popIn:250,popOut:250,fadeIn:200,fadeOut:200,slideUp:400,slideRight:400,slideLeft:400,slideDown:400},n.prototype.animate=function(t,i){i=i||{},this.animationTimeout||(this.animationTimeout={}),i.element||(i.element=this.wrapper),i.element.data("jBox-animating-id")||i.element.data("jBox-animating-id",n._getUniqueElementID()),i.element.data("jBox-animating")&&(i.element.removeClass(i.element.data("jBox-animating")).data("jBox-animating",null),this.animationTimeout[i.element.data("jBox-animating-id")]&&clearTimeout(this.animationTimeout[i.element.data("jBox-animating-id")])),i.element.addClass("jBox-animated-"+t).data("jBox-animating","jBox-animated-"+t),this.animationTimeout[i.element.data("jBox-animating-id")]=setTimeout(function(){i.element.removeClass(i.element.data("jBox-animating")).data("jBox-animating",null),i.complete&&i.complete()},n._animationSpeeds[t])},n.prototype.swipeDetector=function(i,s){var o=0,e=0,n=0,a=0,h=0,t={swipeThreshold:70,useOnlyTouch:!1};function r(t){s.useOnlyTouch&&!t.originalEvent.touches||(t.originalEvent.touches&&(t=t.originalEvent.touches[0]),0===o&&(o=1,e=t.clientX,n=t.clientY))}function p(t){2===o&&(o=0,Math.abs(a)>Math.abs(h)&&Math.abs(a)>s.swipeThreshold?a<0?i.trigger($.Event("swipeLeft.sd")):i.trigger($.Event("swipeRight.sd")):Math.abs(h)>s.swipeThreshold&&(h<0?i.trigger($.Event("swipeUp.sd")):i.trigger($.Event("swipeDown.sd"))))}function l(t){var i;1===o&&(i=(t=t.originalEvent.touches?t.originalEvent.touches[0]:t).clientX-e,t=t.clientY-n,(Math.abs(i)>s.swipeThreshold||Math.abs(t)>s.swipeThreshold)&&(o=2,a=i,h=t))}return s=b.extend(t,s),i.on("mousedown touchstart",r),$("html").on("mouseup touchend",p),$("html").on("mousemove touchmove",l),i},n.prototype.destroy=function(){return this.detach(),this.isOpen&&this.close({ignoreDelay:!0}),this.wrapper&&this.wrapper.remove(),this.overlay&&this.overlay.remove(),this._styles&&this._styles.remove(),this.isDestroyed=!0,this},n._getUniqueID=(t=1,function(){return t++}),n._getUniqueElementID=(i=1,function(){return i++}),n._pluginOptions={},n.plugin=function(t,i){n._pluginOptions[t]=i},b.fn.jBox=function(t,i){return i=i||{},new n(t=t||{},b.extend(i,{attach:this}))},n}!function(i,s){"function"==typeof define&&define.amd?define(["jquery"],function(t){return i.jBox=s(t)}):"object"==typeof module&&module.exports?module.exports=i.jBox=s(require("jquery")):i.jBox=s(i.jQuery)}(this,function(t){var i=jBoxWrapper(t);try{"undefined"!=typeof jBoxConfirmWrapper&&jBoxConfirmWrapper&&jBoxConfirmWrapper(i,t)}catch(t){console.error(t)}try{"undefined"!=typeof jBoxImageWrapper&&jBoxImageWrapper&&jBoxImageWrapper(i,t)}catch(t){console.error(t)}try{"undefined"!=typeof jBoxNoticeWrapper&&jBoxNoticeWrapper&&jBoxNoticeWrapper(i,t)}catch(t){console.error(t)}return i});
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,58 @@
1
+.jBox-Confirm .jBox-content {
2
+  text-align: center;
3
+  padding: 46px 35px;
4
+}
5
+
6
+@media (max-width: 500px) {
7
+  .jBox-Confirm .jBox-content {
8
+    padding: 32px 20px;
9
+  }
10
+}
11
+
12
+.jBox-Confirm-footer {
13
+  height: 46px;
14
+}
15
+
16
+.jBox-Confirm-button {
17
+  display: block;
18
+  float: left;
19
+  cursor: pointer;
20
+  text-align: center;
21
+  width: 50%;
22
+  line-height: 46px;
23
+  height: 46px;
24
+  overflow: hidden;
25
+  padding: 0 10px;
26
+  transition: color .2s, background-color .2s;
27
+  box-sizing: border-box;
28
+}
29
+
30
+.jBox-Confirm-button-cancel {
31
+  border-bottom-left-radius: 4px;
32
+  background: #ddd;
33
+  color: #666;
34
+}
35
+
36
+.jBox-Confirm-button-cancel:hover, .jBox-Confirm-button-cancel:active {
37
+  background: #ccc;
38
+}
39
+
40
+.jBox-Confirm-button-cancel:active {
41
+  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
42
+}
43
+
44
+.jBox-Confirm-button-submit {
45
+  border-bottom-right-radius: 4px;
46
+  background: #7d0;
47
+  color: #fff;
48
+}
49
+
50
+.jBox-Confirm-button-submit:hover, .jBox-Confirm-button-submit:active {
51
+  background: #6c0;
52
+}
53
+
54
+.jBox-Confirm-button-submit:active {
55
+  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
56
+}
57
+
58
+/*# sourceMappingURL=jBox.Confirm.css.map */
0 59
new file mode 100644
... ...
@@ -0,0 +1,97 @@
1
+/**
2
+ * jBox Confirm plugin: Add a confirm dialog to links, buttons, etc.
3
+ *
4
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
5
+ *
6
+ * License: MIT (https://opensource.org/licenses/MIT)
7
+ *
8
+ * Requires: jBox (https://cdn.jsdelivr.net/gh/StephanWagner/jBox@latest/dist/jBox.min.js)
9
+ */
10
+
11
+function jBoxConfirmWrapper(jBox, jQuery) {
12
+
13
+  new jBox.plugin('Confirm', {
14
+
15
+
16
+    // Options (https://stephanwagner.me/jBox/options#options-confirm)
17
+
18
+    confirmButton: 'Submit',  // Text for the submit button
19
+    cancelButton: 'Cancel',   // Text for the cancel button
20
+    confirm: null,            // Function to execute when clicking the submit button. By default jBox will use the onclick or href attribute in that order if found
21
+    cancel: null,             // Function to execute when clicking the cancel button
22
+    closeOnConfirm: true,     // Close jBox when the user clicks the confirm button
23
+    target: window,
24
+    fixed: true,
25
+    attach: '[data-confirm]',
26
+    getContent: 'data-confirm',
27
+    content: 'Do you really want to do this?',
28
+    minWidth: 360,
29
+    maxWidth: 500,
30
+    blockScroll: true,
31
+    closeOnEsc: true,
32
+    closeOnClick: false,
33
+    closeButton: false,
34
+    overlay: true,
35
+    animation: 'zoomIn',
36
+    preventDefault: true,
37
+
38
+
39
+    // Triggered when jBox is attached to the element
40
+
41
+    _onAttach: function (el)
42
+    {
43
+      // Extract the href or the onclick event if no submit event is passed
44
+      if (!this.options.confirm) {
45
+        var submit = el.attr('onclick') ? el.attr('onclick') : (
46
+          el.attr('href') ? (
47
+            el.attr('target') ? 'window.open("' + el.attr('href') + '", "' + el.attr('target') + '");'  : 'window.location.href = "' + el.attr('href') + '";'
48
+          ) : '');
49
+        el.prop('onclick', null).data('jBox-Confirm-submit', submit);
50
+      }
51
+    },
52
+
53
+
54
+    // Triggered when jBox was created
55
+
56
+    _onCreated: function ()
57
+    {
58
+      // Add modal class to mimic jBox modal
59
+      this.wrapper.addClass('jBox-Modal');
60
+
61
+      // Add a footer to the jBox container
62
+      this.footer = jQuery('<div class="jBox-Confirm-footer"/>');
63
+
64
+      jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-cancel"/>')
65
+        .html(this.options.cancelButton)
66
+        .on('click tap', function () {
67
+          this.options.cancel && this.options.cancel(this.source);
68
+          this.close();
69
+        }.bind(this))
70
+        .appendTo(this.footer);
71
+
72
+      this.submitButton = jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-submit"/>')
73
+        .html(this.options.confirmButton)
74
+        .appendTo(this.footer);
75
+
76
+      this.footer.appendTo(this.container);
77
+    },
78
+
79
+
80
+    // Triggered when jBox is opened
81
+
82
+    _onOpen: function ()
83
+    {
84
+      // Set the new action for the submit button
85
+      this.submitButton
86
+        .off('click.jBox-Confirm' + this.id + ' tap.jBox-Confirm' + this.id)
87
+        .on('click.jBox-Confirm' + this.id + ' tap.jBox-Confirm' + this.id, function () {
88
+          this.options.confirm ? this.options.confirm(this.source) : eval(this.source.data('jBox-Confirm-submit'));
89
+          this.options.closeOnConfirm && this.close();
90
+        }.bind(this));
91
+    }
92
+
93
+  });
94
+
95
+};
96
+
97
+//# sourceMappingURL=jBox.Confirm.js.map
0 98
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-Confirm .jBox-content{text-align:center;padding:46px 35px}@media (max-width:500px){.jBox-Confirm .jBox-content{padding:32px 20px}}.jBox-Confirm-footer{height:46px}.jBox-Confirm-button{display:block;float:left;cursor:pointer;text-align:center;width:50%;line-height:46px;height:46px;overflow:hidden;padding:0 10px;transition:color .2s,background-color .2s;box-sizing:border-box}.jBox-Confirm-button-cancel{border-bottom-left-radius:4px;background:#ddd;color:#666}.jBox-Confirm-button-cancel:active,.jBox-Confirm-button-cancel:hover{background:#ccc}.jBox-Confirm-button-cancel:active{box-shadow:inset 0 1px 3px rgba(0,0,0,.2)}.jBox-Confirm-button-submit{border-bottom-right-radius:4px;background:#7d0;color:#fff}.jBox-Confirm-button-submit:active,.jBox-Confirm-button-submit:hover{background:#6c0}.jBox-Confirm-button-submit:active{box-shadow:inset 0 1px 3px rgba(0,0,0,.2)}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+function jBoxConfirmWrapper(jBox,jQuery){new jBox.plugin("Confirm",{confirmButton:"Submit",cancelButton:"Cancel",confirm:null,cancel:null,closeOnConfirm:!0,target:window,fixed:!0,attach:"[data-confirm]",getContent:"data-confirm",content:"Do you really want to do this?",minWidth:360,maxWidth:500,blockScroll:!0,closeOnEsc:!0,closeOnClick:!1,closeButton:!1,overlay:!0,animation:"zoomIn",preventDefault:!0,_onAttach:function(o){var t;this.options.confirm||(t=o.attr("onclick")?o.attr("onclick"):o.attr("href")?o.attr("target")?'window.open("'+o.attr("href")+'", "'+o.attr("target")+'");':'window.location.href = "'+o.attr("href")+'";':"",o.prop("onclick",null).data("jBox-Confirm-submit",t))},_onCreated:function(){this.wrapper.addClass("jBox-Modal"),this.footer=jQuery('<div class="jBox-Confirm-footer"/>'),jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-cancel"/>').html(this.options.cancelButton).on("click tap",function(){this.options.cancel&&this.options.cancel(this.source),this.close()}.bind(this)).appendTo(this.footer),this.submitButton=jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-submit"/>').html(this.options.confirmButton).appendTo(this.footer),this.footer.appendTo(this.container)},_onOpen:function(){this.submitButton.off("click.jBox-Confirm"+this.id+" tap.jBox-Confirm"+this.id).on("click.jBox-Confirm"+this.id+" tap.jBox-Confirm"+this.id,function(){this.options.confirm?this.options.confirm(this.source):eval(this.source.data("jBox-Confirm-submit")),this.options.closeOnConfirm&&this.close()}.bind(this))}})}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,201 @@
1
+.jBox-Image .jBox-container {
2
+  background-color: transparent;
3
+}
4
+
5
+.jBox-Image .jBox-content {
6
+  padding: 0;
7
+  width: 100%;
8
+  height: 100%;
9
+}
10
+
11
+.jBox-image-container {
12
+  background: center center no-repeat;
13
+  position: absolute;
14
+  width: 100%;
15
+  height: 100%;
16
+  opacity: 0;
17
+}
18
+
19
+.jBox-image-label-wrapper {
20
+  position: absolute;
21
+  top: 100%;
22
+  left: 0;
23
+  right: 0;
24
+  height: 40px;
25
+  z-index: 100;
26
+  display: flex;
27
+}
28
+
29
+.jBox-image-label-container {
30
+  position: relative;
31
+  flex: 1;
32
+}
33
+
34
+.jBox-image-label {
35
+  box-sizing: border-box;
36
+  position: absolute;
37
+  left: 0;
38
+  bottom: 0;
39
+  width: 100%;
40
+  text-align: center;
41
+  color: #fff;
42
+  padding: 8px 12px;
43
+  font-size: 15px;
44
+  line-height: 24px;
45
+  transition: opacity .36s;
46
+  opacity: 0;
47
+  z-index: 0;
48
+  pointer-events: none;
49
+}
50
+
51
+.jBox-image-label.expanded {
52
+  background: #000;
53
+}
54
+
55
+.jBox-image-label:not(.expanded) {
56
+  text-overflow: ellipsis;
57
+  white-space: nowrap;
58
+  overflow: hidden;
59
+}
60
+
61
+.jBox-image-label.active {
62
+  opacity: 1;
63
+  pointer-events: all;
64
+}
65
+
66
+@media (max-width: 600px) {
67
+  .jBox-image-label {
68
+    font-size: 13px;
69
+  }
70
+}
71
+
72
+.jBox-image-pointer-next,
73
+.jBox-image-pointer-prev {
74
+  flex-shrink: 0;
75
+  width: 40px;
76
+  height: 40px;
77
+  cursor: pointer;
78
+  opacity: .8;
79
+  transition: opacity .2s;
80
+  background: no-repeat center center url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ijc0LjcgMjI0IDE4LjcgMzIiPg0KPHBhdGggZmlsbD0iI2ZmZmZmZiIgZD0iTTkzLDIyNy40TDgwLjQsMjQwTDkzLDI1Mi42YzAuNCwwLjQsMC40LDEuMSwwLDEuNWwtMS42LDEuNmMtMC40LDAuNC0xLDAuNS0xLjUsMEw3NSwyNDAuN2MtMC40LTAuNC0wLjUtMSwwLTEuNWwxNC45LTE0LjljMC40LTAuNCwxLTAuNCwxLjUsMGwxLjYsMS42QzkzLjUsMjI2LjQsOTMuNCwyMjcsOTMsMjI3LjR6Ii8+DQo8L3N2Zz4=);
81
+  background-size: 11px auto;
82
+  user-select: none;
83
+  z-index: 1;
84
+}
85
+
86
+.jBox-image-pointer-next:hover,
87
+.jBox-image-pointer-prev:hover {
88
+  opacity: 1;
89
+}
90
+
91
+.jBox-image-pointer-next {
92
+  transform: scaleX(-1);
93
+}
94
+
95
+.jBox-image-counter-container {
96
+  flex-shrink: 0;
97
+  white-space: nowrap;
98
+  height: 40px;
99
+  line-height: 40px;
100
+  font-size: 13px;
101
+  color: #fff;
102
+  text-align: right;
103
+  display: none;
104
+}
105
+
106
+.jBox-image-has-counter .jBox-image-counter-container {
107
+  display: block;
108
+}
109
+
110
+.jBox-overlay.jBox-overlay-Image {
111
+  background: #000;
112
+}
113
+
114
+.jBox-image-not-found {
115
+  background: #000;
116
+}
117
+
118
+.jBox-image-not-found:before {
119
+  content: '';
120
+  box-sizing: border-box;
121
+  display: block;
122
+  width: 80px;
123
+  height: 80px;
124
+  margin-top: -40px;
125
+  margin-left: -40px;
126
+  position: absolute;
127
+  top: 50%;
128
+  left: 50%;
129
+  border: 5px solid #222;
130
+  border-radius: 50%;
131
+}
132
+
133
+.jBox-image-not-found:after {
134
+  content: '';
135
+  display: block;
136
+  box-sizing: content-box;
137
+  z-index: auto;
138
+  width: 6px;
139
+  height: 74px;
140
+  margin-top: -37px;
141
+  margin-left: -3px;
142
+  position: absolute;
143
+  top: 50%;
144
+  left: 50%;
145
+  background: #222;
146
+  transform: rotateZ(45deg);
147
+  transform-origin: 50% 50% 0;
148
+}
149
+
150
+.jBox-image-download-button-wrapper {
151
+  position: absolute;
152
+  top: -40px;
153
+  right: 35px;
154
+  height: 40px;
155
+  display: flex;
156
+  cursor: pointer;
157
+  opacity: .8;
158
+  transition: opacity .2s;
159
+}
160
+
161
+.jBox-image-download-button-wrapper:hover {
162
+  opacity: 1;
163
+}
164
+
165
+.jBox-image-download-button-icon {
166
+  width: 40px;
167
+  height: 40px;
168
+  background: center center no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNjQwIj48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNNDE2IDI1NnYtMTkyaC0xOTJ2MTkyaC0xNjBsMjU2IDI1NiAyNTYtMjU2aC0xNjB6TTAgNTc2aDY0MHY2NGgtNjQwdi02NHoiPjwvcGF0aD48L3N2Zz4=);
169
+  background-size: 60%;
170
+}
171
+
172
+.jBox-image-download-button-text {
173
+  white-space: nowrap;
174
+  line-height: 40px;
175
+  padding: 0 10px 0 0;
176
+  color: #fff;
177
+  font-size: 14px;
178
+}
179
+
180
+@keyframes jBoxImageLoading {
181
+  to {
182
+    transform: rotate(360deg);
183
+  }
184
+}
185
+
186
+.jBox-image-loading:before {
187
+  content: '';
188
+  position: absolute;
189
+  top: 50%;
190
+  left: 50%;
191
+  width: 32px;
192
+  height: 32px;
193
+  margin-top: -16px;
194
+  margin-left: -16px;
195
+  border: 4px solid #333;
196
+  border-bottom-color: #666;
197
+  animation: jBoxImageLoading 1.2s linear infinite;
198
+  border-radius: 50%;
199
+}
200
+
201
+/*# sourceMappingURL=jBox.Image.css.map */
0 202
new file mode 100644
... ...
@@ -0,0 +1,353 @@
1
+/**
2
+ * jBox Image plugin: Adds a lightbox to your images
3
+ *
4
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
5
+ *
6
+ * License: MIT (https://opensource.org/licenses/MIT)
7
+ *
8
+ * Requires: jBox (https://cdn.jsdelivr.net/gh/StephanWagner/jBox@latest/dist/jBox.min.js)
9
+ */
10
+
11
+function jBoxImageWrapper(jBox, jQuery) {
12
+
13
+  new jBox.plugin('Image', {
14
+
15
+
16
+    // Options (https://stephanwagner.me/jBox/options#options-image)
17
+
18
+    src: 'href',                 // The attribute where jBox gets the image source from, e.g. href="/path_to_image/image.jpg"
19
+    gallery: 'data-jbox-image',  // The attribute to set the galleries, e.g. data-jbox-image="gallery1"
20
+    imageLabel: 'title',         // The attribute where jBox gets the image label from, e.g. title="My label"
21
+    imageFade: 360,              // The fade duration for images in ms
22
+    imageSize: 'contain',        // How to display the images. Use CSS background-position values, e.g. 'cover', 'contain', 'auto', 'initial', '50% 50%'
23
+    imageCounter: false,         // Set to true to add an image counter, e.g. 4/20
24
+    imageCounterSeparator: '/',  // HTML to separate the current image number from all image numbers, e.g. '/' or ' of '
25
+    downloadButton: false,       // Adds a download button
26
+    downloadButtonText: null,    // Text for the download button
27
+    downloadButtonUrl: null,     // The attribute at the source element where to find the image to download, e.g. data-download="/path_to_image/image.jpg". If none provided, the currently active image will be downloaded
28
+    mobileImageAttr: null,       // The attribute to look for an mobile version of the image
29
+    mobileImageBreakpoint: null, // The upper breakpoint to load the mobile image
30
+    preloadFirstImage: false,    // Preload the first image when page is loaded
31
+    target: window,
32
+    attach: '[data-jbox-image]',
33
+    fixed: true,
34
+    blockScroll: true,
35
+    closeOnEsc: true,
36
+    closeOnClick: 'button',
37
+    closeButton: true,
38
+    overlay: true,
39
+    animation: 'zoomIn',
40
+    preventDefault: true,
41
+    width: '100%',
42
+    height: '100%',
43
+    adjustDistance: {
44
+      top: 40,
45
+      right: 0,
46
+      bottom: 40,
47
+      left: 0
48
+    },
49
+
50
+
51
+    // Triggered when jBox is initialized
52
+
53
+    _onInit: function ()
54
+    {
55
+      // Initial images and z-index
56
+      this.images = this.currentImage = {};
57
+      this.imageZIndex = 1;
58
+
59
+      this.initImage = function (item) {
60
+        item = jQuery(item);
61
+
62
+        // Abort if the item was added to a gallery already
63
+        if (item.data('jBox-image-gallery')) {
64
+          return;
65
+        }
66
+
67
+        // Get the image src
68
+        var src = item.attr(this.options.src);
69
+
70
+        // Update responsive image src
71
+        if (this.options.mobileImageAttr && this.options.mobileImageBreakpoint && item.attr(this.options.mobileImageAttr)) {
72
+          if (jQuery(window).width() <= this.options.mobileImageBreakpoint) {
73
+            src = item.attr(this.options.mobileImageAttr);
74
+          }
75
+        }
76
+
77
+        // Add item to a gallery
78
+        var gallery = item.attr(this.options.gallery) || 'default';
79
+        !this.images[gallery] && (this.images[gallery] = []);
80
+        this.images[gallery].push({
81
+          src: src,
82
+          label: (item.attr(this.options.imageLabel) || ''),
83
+          downloadUrl: this.options.downloadButtonUrl && item.attr(this.options.downloadButtonUrl) ? item.attr(this.options.downloadButtonUrl) : null
84
+        });
85
+
86
+        // Remove the title attribute so it won't show the browsers tooltip
87
+        this.options.imageLabel == 'title' && item.removeAttr('title');
88
+
89
+        // Store data in source element for easy access
90
+        item.data('jBox-image-gallery', gallery);
91
+        item.data('jBox-image-id', (this.images[gallery].length - 1));
92
+      }.bind(this);
93
+
94
+      // Loop through images, sort and save in global variable
95
+      this.attachedElements && this.attachedElements.length && jQuery.each(this.attachedElements, function (index, item) {
96
+        this.initImage(item);
97
+      }.bind(this));
98
+
99
+      // Helper to inject the image into content area
100
+      var appendImage = function (gallery, id, show, instant) {
101
+        // Abort if image was appended already
102
+        if (jQuery('#jBox-image-' + gallery + '-' + id).length) {
103
+          return;
104
+        }
105
+
106
+        // Create image container
107
+        var image = jQuery('<div/>', {
108
+          id: 'jBox-image-' + gallery + '-' + id,
109
+          'class': 'jBox-image-container' + (show ? ' jBox-image-' + gallery + '-current' : '')
110
+        }).css({
111
+          backgroundSize: this.options.imageSize,
112
+          opacity: (instant ? 1 : 0),
113
+          zIndex: (show ? this.imageZIndex++ : 0)
114
+        }).appendTo(this.content);
115
+
116
+        // Add swipe events
117
+        this.swipeDetector(image)
118
+          .on("swipeLeft.sd swipeRight.sd", function (event) {
119
+            if (event.type === "swipeLeft") {
120
+              this.showImage('next');
121
+            } else if (event.type === "swipeRight") {
122
+              this.showImage('prev');
123
+            }
124
+          }.bind(this));
125
+
126
+        // Create labels
127
+        jQuery('<div/>', {
128
+          id: 'jBox-image-label-' + gallery + '-' + id,
129
+          'class': 'jBox-image-label' + (show ? ' active' : '')
130
+        })
131
+        .html(this.images[gallery][id].label)
132
+        .on('click tap', function () {
133
+          jQuery(this).toggleClass('expanded');
134
+        })
135
+        .appendTo(this.imageLabelContainer);
136
+
137
+        // Show image
138
+        show && image.animate({opacity: 1}, instant ? 0 : this.options.imageFade);
139
+
140
+        return image;
141
+      }.bind(this);
142
+
143
+      // Function to download an image
144
+      this.downloadImage = function (imageUrl) {
145
+        var link = document.createElement('a');
146
+        link.href = imageUrl;
147
+        link.setAttribute('download', imageUrl.substring(imageUrl.lastIndexOf('/')+1));
148
+        document.body.appendChild(link);
149
+        link.click();
150
+      };
151
+
152
+      // Helper to show new image label
153
+      var showLabel = function (gallery, id) {
154
+        jQuery('.jBox-image-label.active').removeClass('active expanded');
155
+        jQuery('#jBox-image-label-' + gallery + '-' + id).addClass('active');
156
+      };
157
+
158
+      // Helper to load image
159
+      var loadImage = function (gallery, id, show, instant) {
160
+        var imageContainer = appendImage(gallery, id, show, instant);
161
+        imageContainer.addClass('jBox-image-loading');
162
+
163
+        jQuery('<img src="' + this.images[gallery][id].src + '" />').each(function () {
164
+          var tmpImg = new Image();
165
+          tmpImg.onload = function () {
166
+            imageContainer.removeClass('jBox-image-loading');
167
+            imageContainer.css({backgroundImage: 'url("' + this.images[gallery][id].src + '")'});
168
+          }.bind(this);
169
+
170
+          tmpImg.onerror = function () {
171
+            imageContainer.removeClass('jBox-image-loading');
172
+            imageContainer.addClass('jBox-image-not-found');
173
+          }.bind(this);
174
+
175
+          tmpImg.src = this.images[gallery][id].src;
176
+        }.bind(this));
177
+      }.bind(this);
178
+
179
+      // Show images when they are loaded or load them if not
180
+      this.showImage = function (img) {
181
+        // Get the gallery and the image id from the next or the previous image
182
+        if (img != 'open') {
183
+          var gallery = this.currentImage.gallery;
184
+          var id = this.currentImage.id + (1 * (img == 'prev') ? -1 : 1);
185
+          id = id > (this.images[gallery].length - 1) ? 0 : (id < 0 ? (this.images[gallery].length - 1) : id);
186
+
187
+        // Or get image data from source element
188
+        } else {
189
+          // Get gallery and image id from source element
190
+          if (this.source) {
191
+            var gallery = this.source.data('jBox-image-gallery');
192
+            var id = this.source.data('jBox-image-id');
193
+
194
+          // Get gallery and image id attached elements
195
+          } else if (this.attachedElements && this.attachedElements.length) {
196
+            var gallery = jQuery(this.attachedElements[0]).data('jBox-image-gallery');
197
+            var id = jQuery(this.attachedElements[0]).data('jBox-image-id');
198
+          } else {
199
+            return;
200
+          }
201
+
202
+          // Remove or show the next and prev buttons
203
+          jQuery('.jBox-image-pointer-prev, .jBox-image-pointer-next').css({display: (this.images[gallery].length > 1 ? 'block' : 'none')});
204
+        }
205
+
206
+        // If there is a current image already shown, hide it
207
+        if (jQuery('.jBox-image-' + gallery + '-current').length) {
208
+          jQuery('.jBox-image-' + gallery + '-current').removeClass('jBox-image-' + gallery + '-current').animate({opacity: 0}, (img == 'open') ? 0 : this.options.imageFade);
209
+        }
210
+
211
+        // Set new current image
212
+        this.currentImage = {gallery: gallery, id: id};
213
+
214
+        // Show image if it already exists
215
+        if (jQuery('#jBox-image-' + gallery + '-' + id).length) {
216
+          jQuery('#jBox-image-' + gallery + '-' + id).addClass('jBox-image-' + gallery + '-current').css({zIndex: this.imageZIndex++, opacity: 0}).animate({opacity: 1}, (img == 'open') ? 0 : this.options.imageFade);
217
+
218
+        // Load image
219
+        } else {
220
+          loadImage(gallery, id, true, (img === 'open'));
221
+        }
222
+
223
+        // Show label
224
+        showLabel(gallery, id);
225
+
226
+        // Update the image counter numbers
227
+        if (this.imageCounter) {
228
+          if (this.images[gallery].length > 1) {
229
+            this.wrapper.addClass('jBox-image-has-counter');
230
+            this.imageCounter.find('.jBox-image-counter-all').html(this.images[gallery].length);
231
+            this.imageCounter.find('.jBox-image-counter-current').html(id + 1);
232
+          } else {
233
+            this.wrapper.removeClass('jBox-image-has-counter');
234
+          }
235
+        }
236
+
237
+        // Preload next image
238
+        if (this.images[gallery].length - 1) {
239
+	        var next_id = id + 1;
240
+	        next_id = next_id > (this.images[gallery].length - 1) ? 0 : (next_id < 0 ? (this.images[gallery].length - 1) : next_id);
241
+
242
+	        if (!jQuery('#jBox-image-' + gallery + '-' + next_id).length) {
243
+            loadImage(gallery, next_id, false, false);
244
+          }
245
+	      }
246
+      };
247
+
248
+      // Preload image
249
+      if (this.options.preloadFirstImage) {
250
+        jQuery(window).on('load', function() {
251
+          this.showImage('open');
252
+        }.bind(this));
253
+      }
254
+    },
255
+
256
+
257
+    // Triggered when jBox attaches a new element
258
+
259
+    _onAttach: function (item) {
260
+      this.initImage && this.initImage(item);
261
+    },
262
+
263
+
264
+    // Triggered when jBox was created
265
+
266
+    _onCreated: function ()
267
+    {
268
+      // Create image label and navigation buttons
269
+      this.imageLabelWrapper = jQuery('<div class="jBox-image-label-wrapper"/>').appendTo(this.wrapper);
270
+
271
+      this.imagePrevButton = jQuery('<div class="jBox-image-pointer-prev"/>')
272
+        .on('click tap', function () {
273
+          this.showImage('prev');
274
+        }.bind(this));
275
+
276
+      this.imageNextButton = jQuery('<div class="jBox-image-pointer-next"/>')
277
+        .on('click tap', function () {
278
+          this.showImage('next');
279
+        }.bind(this));
280
+
281
+      this.imageLabelContainer = jQuery('<div class="jBox-image-label-container"/>');
282
+
283
+      this.imageLabelWrapper
284
+        .append(this.imagePrevButton)
285
+        .append(this.imageLabelContainer)
286
+        .append(this.imageNextButton);
287
+
288
+      // Append the download button
289
+      if (this.options.downloadButton) {
290
+        this.downloadButton = jQuery('<div/>', {'class': 'jBox-image-download-button-wrapper'})
291
+          .appendTo(this.wrapper)
292
+          .append(
293
+            this.options.downloadButtonText ? jQuery('<div/>', {'class': 'jBox-image-download-button-text'}).html(this.options.downloadButtonText) : null
294
+          )
295
+          .append(
296
+            jQuery('<div/>', {'class': 'jBox-image-download-button-icon'})
297
+          ).on('click tap', function () {
298
+            if (this.images[this.currentImage.gallery][this.currentImage.id].downloadUrl) {
299
+              var currentImageUrl = this.images[this.currentImage.gallery][this.currentImage.id].downloadUrl;
300
+            } else {
301
+              var currentImage = this.wrapper.find('.jBox-image-' + this.currentImage.gallery + '-current');
302
+              var currentImageStyle = currentImage[0].style.backgroundImage;
303
+              var currentImageUrl = currentImageStyle.slice(4, -1).replace(/["']/g, '');
304
+            }
305
+            this.downloadImage(currentImageUrl);
306
+          }.bind(this));
307
+      }
308
+
309
+      // Creating the image counter containers
310
+      if (this.options.imageCounter) {
311
+        this.imageCounter = jQuery('<div/>', {'class': 'jBox-image-counter-container'}).insertAfter(this.imageLabelContainer);
312
+        this.imageCounter.append(jQuery('<span/>', {'class': 'jBox-image-counter-current'})).append(jQuery('<span/>').html(this.options.imageCounterSeparator)).append(jQuery('<span/>', {'class': 'jBox-image-counter-all'}));
313
+      }
314
+    },
315
+
316
+
317
+    // Triggered when jBox opens
318
+
319
+    _onOpen: function ()
320
+    {
321
+      // Add key events
322
+      jQuery(document).on('keyup.jBox-Image-' + this.id, function (ev) {
323
+        (ev.keyCode == 37) && this.showImage('prev');
324
+        (ev.keyCode == 39) && this.showImage('next');
325
+      }.bind(this));
326
+
327
+      // Load the image from the attached element
328
+      this.showImage('open');
329
+    },
330
+
331
+
332
+    // Triggered when jBox closes
333
+
334
+    _onClose: function ()
335
+    {
336
+      // Remove key events
337
+      jQuery(document).off('keyup.jBox-Image-' + this.id);
338
+    },
339
+
340
+
341
+    // Triggered when jBox finished closing
342
+
343
+    _onCloseComplete: function ()
344
+    {
345
+      // Hide all image containers
346
+      this.wrapper.find('.jBox-image-container').css('opacity', 0);
347
+    }
348
+
349
+  });
350
+
351
+};
352
+
353
+//# sourceMappingURL=jBox.Image.js.map
0 354
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-Image .jBox-container{background-color:transparent}.jBox-Image .jBox-content{padding:0;width:100%;height:100%}.jBox-image-container{background:center center no-repeat;position:absolute;width:100%;height:100%;opacity:0}.jBox-image-label-wrapper{position:absolute;top:100%;left:0;right:0;height:40px;z-index:100;display:flex}.jBox-image-label-container{position:relative;flex:1}.jBox-image-label{box-sizing:border-box;position:absolute;left:0;bottom:0;width:100%;text-align:center;color:#fff;padding:8px 12px;font-size:15px;line-height:24px;transition:opacity .36s;opacity:0;z-index:0;pointer-events:none}.jBox-image-label.expanded{background:#000}.jBox-image-label:not(.expanded){text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.jBox-image-label.active{opacity:1;pointer-events:all}@media (max-width:600px){.jBox-image-label{font-size:13px}}.jBox-image-pointer-next,.jBox-image-pointer-prev{flex-shrink:0;width:40px;height:40px;cursor:pointer;opacity:.8;transition:opacity .2s;background:no-repeat center center url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ijc0LjcgMjI0IDE4LjcgMzIiPg0KPHBhdGggZmlsbD0iI2ZmZmZmZiIgZD0iTTkzLDIyNy40TDgwLjQsMjQwTDkzLDI1Mi42YzAuNCwwLjQsMC40LDEuMSwwLDEuNWwtMS42LDEuNmMtMC40LDAuNC0xLDAuNS0xLjUsMEw3NSwyNDAuN2MtMC40LTAuNC0wLjUtMSwwLTEuNWwxNC45LTE0LjljMC40LTAuNCwxLTAuNCwxLjUsMGwxLjYsMS42QzkzLjUsMjI2LjQsOTMuNCwyMjcsOTMsMjI3LjR6Ii8+DQo8L3N2Zz4=);background-size:11px auto;user-select:none;z-index:1}.jBox-image-pointer-next:hover,.jBox-image-pointer-prev:hover{opacity:1}.jBox-image-pointer-next{transform:scaleX(-1)}.jBox-image-counter-container{flex-shrink:0;white-space:nowrap;height:40px;line-height:40px;font-size:13px;color:#fff;text-align:right;display:none}.jBox-image-has-counter .jBox-image-counter-container{display:block}.jBox-overlay.jBox-overlay-Image{background:#000}.jBox-image-not-found{background:#000}.jBox-image-not-found:before{content:'';box-sizing:border-box;display:block;width:80px;height:80px;margin-top:-40px;margin-left:-40px;position:absolute;top:50%;left:50%;border:5px solid #222;border-radius:50%}.jBox-image-not-found:after{content:'';display:block;box-sizing:content-box;z-index:auto;width:6px;height:74px;margin-top:-37px;margin-left:-3px;position:absolute;top:50%;left:50%;background:#222;transform:rotateZ(45deg);transform-origin:50% 50% 0}.jBox-image-download-button-wrapper{position:absolute;top:-40px;right:35px;height:40px;display:flex;cursor:pointer;opacity:.8;transition:opacity .2s}.jBox-image-download-button-wrapper:hover{opacity:1}.jBox-image-download-button-icon{width:40px;height:40px;background:center center no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNjQwIj48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNNDE2IDI1NnYtMTkyaC0xOTJ2MTkyaC0xNjBsMjU2IDI1NiAyNTYtMjU2aC0xNjB6TTAgNTc2aDY0MHY2NGgtNjQwdi02NHoiPjwvcGF0aD48L3N2Zz4=);background-size:60%}.jBox-image-download-button-text{white-space:nowrap;line-height:40px;padding:0 10px 0 0;color:#fff;font-size:14px}@keyframes jBoxImageLoading{to{transform:rotate(360deg)}}.jBox-image-loading:before{content:'';position:absolute;top:50%;left:50%;width:32px;height:32px;margin-top:-16px;margin-left:-16px;border:4px solid #333;border-bottom-color:#666;animation:jBoxImageLoading 1.2s linear infinite;border-radius:50%}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+function jBoxImageWrapper(t,s){new t.plugin("Image",{src:"href",gallery:"data-jbox-image",imageLabel:"title",imageFade:360,imageSize:"contain",imageCounter:!1,imageCounterSeparator:"/",downloadButton:!1,downloadButtonText:null,downloadButtonUrl:null,mobileImageAttr:null,mobileImageBreakpoint:null,preloadFirstImage:!1,target:window,attach:"[data-jbox-image]",fixed:!0,blockScroll:!0,closeOnEsc:!0,closeOnClick:"button",closeButton:!0,overlay:!0,animation:"zoomIn",preventDefault:!0,width:"100%",height:"100%",adjustDistance:{top:40,right:0,bottom:40,left:0},_onInit:function(){this.images=this.currentImage={},this.imageZIndex=1,this.initImage=function(t){var e,i;(t=s(t)).data("jBox-image-gallery")||(e=t.attr(this.options.src),this.options.mobileImageAttr&&this.options.mobileImageBreakpoint&&t.attr(this.options.mobileImageAttr)&&s(window).width()<=this.options.mobileImageBreakpoint&&(e=t.attr(this.options.mobileImageAttr)),i=t.attr(this.options.gallery)||"default",this.images[i]||(this.images[i]=[]),this.images[i].push({src:e,label:t.attr(this.options.imageLabel)||"",downloadUrl:this.options.downloadButtonUrl&&t.attr(this.options.downloadButtonUrl)?t.attr(this.options.downloadButtonUrl):null}),"title"==this.options.imageLabel&&t.removeAttr("title"),t.data("jBox-image-gallery",i),t.data("jBox-image-id",this.images[i].length-1))}.bind(this),this.attachedElements&&this.attachedElements.length&&s.each(this.attachedElements,function(t,e){this.initImage(e)}.bind(this));var n=function(t,e,i,a){if(!s("#jBox-image-"+t+"-"+e).length){var o=s("<div/>",{id:"jBox-image-"+t+"-"+e,class:"jBox-image-container"+(i?" jBox-image-"+t+"-current":"")}).css({backgroundSize:this.options.imageSize,opacity:a?1:0,zIndex:i?this.imageZIndex++:0}).appendTo(this.content);return this.swipeDetector(o).on("swipeLeft.sd swipeRight.sd",function(t){"swipeLeft"===t.type?this.showImage("next"):"swipeRight"===t.type&&this.showImage("prev")}.bind(this)),s("<div/>",{id:"jBox-image-label-"+t+"-"+e,class:"jBox-image-label"+(i?" active":"")}).html(this.images[t][e].label).on("click tap",function(){s(this).toggleClass("expanded")}).appendTo(this.imageLabelContainer),i&&o.animate({opacity:1},a?0:this.options.imageFade),o}}.bind(this);this.downloadImage=function(t){var e=document.createElement("a");e.href=t,e.setAttribute("download",t.substring(t.lastIndexOf("/")+1)),document.body.appendChild(e),e.click()};var o=function(e,i,t,a){var o=n(e,i,t,a);o.addClass("jBox-image-loading"),s('<img src="'+this.images[e][i].src+'" />').each(function(){var t=new Image;t.onload=function(){o.removeClass("jBox-image-loading"),o.css({backgroundImage:'url("'+this.images[e][i].src+'")'})}.bind(this),t.onerror=function(){o.removeClass("jBox-image-loading"),o.addClass("jBox-image-not-found")}.bind(this),t.src=this.images[e][i].src}.bind(this))}.bind(this);this.showImage=function(t){if("open"!=t){var e=this.currentImage.gallery;i=(i=this.currentImage.id+(+("prev"==t)?-1:1))>this.images[e].length-1?0:i<0?this.images[e].length-1:i}else{if(this.source)var e=this.source.data("jBox-image-gallery"),i=this.source.data("jBox-image-id");else{if(!this.attachedElements||!this.attachedElements.length)return;e=s(this.attachedElements[0]).data("jBox-image-gallery"),i=s(this.attachedElements[0]).data("jBox-image-id")}s(".jBox-image-pointer-prev, .jBox-image-pointer-next").css({display:1<this.images[e].length?"block":"none"})}var a;s(".jBox-image-"+e+"-current").length&&s(".jBox-image-"+e+"-current").removeClass("jBox-image-"+e+"-current").animate({opacity:0},"open"==t?0:this.options.imageFade),this.currentImage={gallery:e,id:i},s("#jBox-image-"+e+"-"+i).length?s("#jBox-image-"+e+"-"+i).addClass("jBox-image-"+e+"-current").css({zIndex:this.imageZIndex++,opacity:0}).animate({opacity:1},"open"==t?0:this.options.imageFade):o(e,i,!0,"open"===t),a=e,t=i,s(".jBox-image-label.active").removeClass("active expanded"),s("#jBox-image-label-"+a+"-"+t).addClass("active"),this.imageCounter&&(1<this.images[e].length?(this.wrapper.addClass("jBox-image-has-counter"),this.imageCounter.find(".jBox-image-counter-all").html(this.images[e].length),this.imageCounter.find(".jBox-image-counter-current").html(i+1)):this.wrapper.removeClass("jBox-image-has-counter")),this.images[e].length-1&&(i=(i=i+1)>this.images[e].length-1?0:i<0?this.images[e].length-1:i,s("#jBox-image-"+e+"-"+i).length||o(e,i,!1,!1))},this.options.preloadFirstImage&&s(window).on("load",function(){this.showImage("open")}.bind(this))},_onAttach:function(t){this.initImage&&this.initImage(t)},_onCreated:function(){this.imageLabelWrapper=s('<div class="jBox-image-label-wrapper"/>').appendTo(this.wrapper),this.imagePrevButton=s('<div class="jBox-image-pointer-prev"/>').on("click tap",function(){this.showImage("prev")}.bind(this)),this.imageNextButton=s('<div class="jBox-image-pointer-next"/>').on("click tap",function(){this.showImage("next")}.bind(this)),this.imageLabelContainer=s('<div class="jBox-image-label-container"/>'),this.imageLabelWrapper.append(this.imagePrevButton).append(this.imageLabelContainer).append(this.imageNextButton),this.options.downloadButton&&(this.downloadButton=s("<div/>",{class:"jBox-image-download-button-wrapper"}).appendTo(this.wrapper).append(this.options.downloadButtonText?s("<div/>",{class:"jBox-image-download-button-text"}).html(this.options.downloadButtonText):null).append(s("<div/>",{class:"jBox-image-download-button-icon"})).on("click tap",function(){var t;t=this.images[this.currentImage.gallery][this.currentImage.id].downloadUrl||this.wrapper.find(".jBox-image-"+this.currentImage.gallery+"-current")[0].style.backgroundImage.slice(4,-1).replace(/["']/g,""),this.downloadImage(t)}.bind(this))),this.options.imageCounter&&(this.imageCounter=s("<div/>",{class:"jBox-image-counter-container"}).insertAfter(this.imageLabelContainer),this.imageCounter.append(s("<span/>",{class:"jBox-image-counter-current"})).append(s("<span/>").html(this.options.imageCounterSeparator)).append(s("<span/>",{class:"jBox-image-counter-all"})))},_onOpen:function(){s(document).on("keyup.jBox-Image-"+this.id,function(t){37==t.keyCode&&this.showImage("prev"),39==t.keyCode&&this.showImage("next")}.bind(this)),this.showImage("open")},_onClose:function(){s(document).off("keyup.jBox-Image-"+this.id)},_onCloseComplete:function(){this.wrapper.find(".jBox-image-container").css("opacity",0)}})}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,122 @@
1
+.jBox-Notice {
2
+  transition: margin .2s;
3
+}
4
+
5
+.jBox-Notice .jBox-container {
6
+  border-radius: 4px;
7
+  box-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, 0.25), inset -1px -1px 0 0 rgba(0, 0, 0, 0.1);
8
+}
9
+
10
+.jBox-Notice .jBox-content {
11
+  border-radius: 4px;
12
+  padding: 12px 20px;
13
+}
14
+
15
+@media (max-width: 768px) {
16
+  .jBox-Notice .jBox-content {
17
+    padding: 10px 15px;
18
+  }
19
+}
20
+
21
+@media (max-width: 500px) {
22
+  .jBox-Notice .jBox-content {
23
+    padding: 8px 10px;
24
+  }
25
+}
26
+
27
+.jBox-Notice.jBox-hasTitle .jBox-content {
28
+  padding-top: 5px;
29
+}
30
+
31
+@media (max-width: 500px) {
32
+  .jBox-Notice.jBox-hasTitle .jBox-content {
33
+    padding-top: 0;
34
+  }
35
+}
36
+
37
+.jBox-Notice.jBox-hasTitle .jBox-title {
38
+  padding: 12px 20px 0;
39
+  font-weight: bold;
40
+}
41
+
42
+@media (max-width: 768px) {
43
+  .jBox-Notice.jBox-hasTitle .jBox-title {
44
+    padding: 10px 15px 0;
45
+  }
46
+}
47
+
48
+@media (max-width: 500px) {
49
+  .jBox-Notice.jBox-hasTitle .jBox-title {
50
+    padding: 8px 10px 0;
51
+  }
52
+}
53
+
54
+.jBox-Notice.jBox-closeButton-title .jBox-title {
55
+  padding-right: 55px;
56
+}
57
+
58
+.jBox-Notice.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton {
59
+  width: 40px;
60
+}
61
+
62
+.jBox-Notice.jBox-Notice-black .jBox-container {
63
+  color: #fff;
64
+  background: #000;
65
+}
66
+
67
+.jBox-Notice.jBox-Notice-black.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
68
+.jBox-Notice.jBox-Notice-black.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
69
+  fill: #fff;
70
+}
71
+
72
+.jBox-Notice.jBox-Notice-gray .jBox-container {
73
+  color: #222;
74
+  background: #f6f6f6;
75
+}
76
+
77
+.jBox-Notice.jBox-Notice-gray.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
78
+.jBox-Notice.jBox-Notice-gray.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
79
+  fill: #222;
80
+}
81
+
82
+.jBox-Notice.jBox-Notice-red .jBox-container {
83
+  color: #fff;
84
+  background: #d00;
85
+}
86
+
87
+.jBox-Notice.jBox-Notice-red.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
88
+.jBox-Notice.jBox-Notice-red.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
89
+  fill: #fff;
90
+}
91
+
92
+.jBox-Notice.jBox-Notice-green .jBox-container {
93
+  color: #fff;
94
+  background: #5d0;
95
+}
96
+
97
+.jBox-Notice.jBox-Notice-green.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
98
+.jBox-Notice.jBox-Notice-green.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
99
+  fill: #fff;
100
+}
101
+
102
+.jBox-Notice.jBox-Notice-blue .jBox-container {
103
+  color: #fff;
104
+  background: #49d;
105
+}
106
+
107
+.jBox-Notice.jBox-Notice-blue.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
108
+.jBox-Notice.jBox-Notice-blue.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
109
+  fill: #fff;
110
+}
111
+
112
+.jBox-Notice.jBox-Notice-yellow .jBox-container {
113
+  color: #000;
114
+  background: #fd0;
115
+}
116
+
117
+.jBox-Notice.jBox-Notice-yellow.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,
118
+.jBox-Notice.jBox-Notice-yellow.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path {
119
+  fill: #fff;
120
+}
121
+
122
+/*# sourceMappingURL=jBox.Notice.css.map */
0 123
new file mode 100644
... ...
@@ -0,0 +1,173 @@
1
+/**
2
+ * jBox Notice plugin: Opens a popup notice
3
+ *
4
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
5
+ *
6
+ * License: MIT (https://opensource.org/licenses/MIT)
7
+ *
8
+ * Requires: jBox (https://cdn.jsdelivr.net/gh/StephanWagner/jBox@latest/dist/jBox.min.js)
9
+ */
10
+
11
+function jBoxNoticeWrapper(jBox, jQuery) {
12
+
13
+  new jBox.plugin('Notice', {
14
+
15
+
16
+    // Options (https://stephanwagner.me/jBox/options#options-notice)
17
+
18
+    color: null,      // Add a color to your notices, use 'gray' (default), 'black', 'red', 'green', 'blue' or 'yellow'
19
+    stack: true,      // Set to false to disable notice-stacking
20
+    stackSpacing: 10, // Spacing between notices when they stack
21
+    autoClose: 6000,  // Time in ms after which the notice will disappear
22
+    attributes: {     // Defines where the notice will pop up
23
+      x: 'right',     // 'left' or 'right'
24
+      y: 'top'        // 'top' or 'bottom'
25
+    },
26
+    position: {       // Defines the distance to the viewport boundary
27
+      x: 15,
28
+      y: 15
29
+    },
30
+    responsivePositions: {  // Responsive positions
31
+      500: {                // The key defines the maximum width of the viewport, the values will replace the default position options
32
+        x: 5,               // Start with the lowest viewport
33
+        y: 5
34
+      },
35
+      768: {
36
+        x: 10,
37
+        y: 10
38
+      }
39
+    },
40
+    target: window,
41
+    fixed: true,
42
+    animation: 'zoomIn',
43
+    closeOnClick: 'box',
44
+    zIndex: 12000,
45
+
46
+
47
+    // Triggered when notice is initialized
48
+
49
+    _onInit: function ()
50
+    {
51
+      // Cache position values
52
+      this.defaultNoticePosition = jQuery.extend({}, this.options.position);
53
+
54
+      // Type Notice has its own adjust position function
55
+      this._adjustNoticePositon = function () {
56
+        var win = jQuery(window);
57
+        var windowDimensions = {
58
+          x: win.width(),
59
+          y: win.height()
60
+        };
61
+
62
+        // Reset default position
63
+        this.options.position = jQuery.extend({}, this.defaultNoticePosition);
64
+
65
+        // Adjust depending on viewport
66
+        jQuery.each(this.options.responsivePositions, function (viewport, position) {
67
+          if (windowDimensions.x <= viewport) {
68
+            this.options.position = position;
69
+            return false;
70
+          }
71
+        }.bind(this));
72
+
73
+        // Set new padding options
74
+        this.options.adjustDistance = {
75
+          top: this.options.position.y,
76
+          right: this.options.position.x,
77
+          bottom: this.options.position.y,
78
+          left: this.options.position.x
79
+        };
80
+      };
81
+
82
+      // If jBox grabs an element as content, crab a clone instead
83
+      this.options.content instanceof jQuery && (this.options.content = this.options.content.clone().attr('id', ''));
84
+
85
+      // Adjust paddings when window resizes
86
+      jQuery(window).on('resize.responsivejBoxNotice-' + this.id, function (ev) { if (this.isOpen) { this._adjustNoticePositon(); } }.bind(this));
87
+
88
+      this.open();
89
+    },
90
+
91
+
92
+    // Triggered when notice was created
93
+
94
+    _onCreated: function ()
95
+    {
96
+      // Add color class
97
+      this.wrapper.addClass('jBox-Notice-color jBox-Notice-' + (this.options.color || 'gray'));
98
+
99
+      // Store position in jBox wrapper
100
+      this.wrapper.data('jBox-Notice-position', this.options.attributes.x + '-' + this.options.attributes.y);
101
+    },
102
+
103
+
104
+    // Triggered when notice opens
105
+
106
+    _onOpen: function ()
107
+    {
108
+      // Bail if we're stacking
109
+      if (this.options.stack) {
110
+          return;
111
+      }
112
+
113
+      // Adjust position when opening
114
+      this._adjustNoticePositon();
115
+
116
+      // Loop through notices at same window corner destroy them
117
+      jQuery.each(jQuery('.jBox-Notice'), function (index, el)
118
+      {
119
+        el = jQuery(el);
120
+
121
+        // Abort if the element is this notice or when it's not at the same position
122
+        if (el.attr('id') == this.id || el.data('jBox-Notice-position') != this.options.attributes.x + '-' + this.options.attributes.y) {
123
+          return;
124
+        }
125
+
126
+        // Remove notice when we don't wont to stack them
127
+        if (!this.options.stack) {
128
+          el.data('jBox').close({ignoreDelay: true});
129
+          return;
130
+        }
131
+      }.bind(this));
132
+    },
133
+
134
+    // Triggered when resizing window etc.
135
+
136
+    _onPosition: function ()
137
+    {
138
+        var stacks = {};
139
+        jQuery.each(jQuery('.jBox-Notice'), function (index, el)
140
+        {
141
+          el = jQuery(el);
142
+          var pos = el.data('jBox-Notice-position');
143
+          if (!stacks[pos]) {
144
+              stacks[pos] = [];
145
+          }
146
+          stacks[pos].push(el);
147
+        });
148
+        for (var pos in stacks) {
149
+            var position = pos.split('-');
150
+            var direction = position[1];
151
+            stacks[pos].reverse();
152
+            var margin = 0;
153
+            for (var i in stacks[pos]) {
154
+                var el = jQuery(stacks[pos][i]);
155
+                el.css('margin-' + direction, margin);
156
+                margin += el.outerHeight() + this.options.stackSpacing;
157
+            }
158
+        }
159
+    },
160
+
161
+    // Remove notice from DOM and reposition other notices when closing finishes
162
+
163
+    _onCloseComplete: function ()
164
+    {
165
+        this.destroy();
166
+        this.options._onPosition.bind(this).call();
167
+    }
168
+
169
+  });
170
+
171
+};
172
+
173
+//# sourceMappingURL=jBox.Notice.js.map
0 174
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-Notice{transition:margin .2s}.jBox-Notice .jBox-container{border-radius:4px;box-shadow:inset 1px 1px 0 0 rgba(255,255,255,.25),inset -1px -1px 0 0 rgba(0,0,0,.1)}.jBox-Notice .jBox-content{border-radius:4px;padding:12px 20px}@media (max-width:768px){.jBox-Notice .jBox-content{padding:10px 15px}}@media (max-width:500px){.jBox-Notice .jBox-content{padding:8px 10px}}.jBox-Notice.jBox-hasTitle .jBox-content{padding-top:5px}@media (max-width:500px){.jBox-Notice.jBox-hasTitle .jBox-content{padding-top:0}}.jBox-Notice.jBox-hasTitle .jBox-title{padding:12px 20px 0;font-weight:700}@media (max-width:768px){.jBox-Notice.jBox-hasTitle .jBox-title{padding:10px 15px 0}}@media (max-width:500px){.jBox-Notice.jBox-hasTitle .jBox-title{padding:8px 10px 0}}.jBox-Notice.jBox-closeButton-title .jBox-title{padding-right:55px}.jBox-Notice.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton{width:40px}.jBox-Notice.jBox-Notice-black .jBox-container{color:#fff;background:#000}.jBox-Notice.jBox-Notice-black.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-black.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#fff}.jBox-Notice.jBox-Notice-gray .jBox-container{color:#222;background:#f6f6f6}.jBox-Notice.jBox-Notice-gray.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-gray.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#222}.jBox-Notice.jBox-Notice-red .jBox-container{color:#fff;background:#d00}.jBox-Notice.jBox-Notice-red.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-red.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#fff}.jBox-Notice.jBox-Notice-green .jBox-container{color:#fff;background:#5d0}.jBox-Notice.jBox-Notice-green.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-green.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#fff}.jBox-Notice.jBox-Notice-blue .jBox-container{color:#fff;background:#49d}.jBox-Notice.jBox-Notice-blue.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-blue.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#fff}.jBox-Notice.jBox-Notice-yellow .jBox-container{color:#000;background:#fd0}.jBox-Notice.jBox-Notice-yellow.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton path,.jBox-Notice.jBox-Notice-yellow.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton:hover path{fill:#fff}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+function jBoxNoticeWrapper(t,a){new t.plugin("Notice",{color:null,stack:!0,stackSpacing:10,autoClose:6e3,attributes:{x:"right",y:"top"},position:{x:15,y:15},responsivePositions:{500:{x:5,y:5},768:{x:10,y:10}},target:window,fixed:!0,animation:"zoomIn",closeOnClick:"box",zIndex:12e3,_onInit:function(){this.defaultNoticePosition=a.extend({},this.options.position),this._adjustNoticePositon=function(){var t=a(window),o=t.width();t.height();this.options.position=a.extend({},this.defaultNoticePosition),a.each(this.options.responsivePositions,function(t,i){if(o<=t)return this.options.position=i,!1}.bind(this)),this.options.adjustDistance={top:this.options.position.y,right:this.options.position.x,bottom:this.options.position.y,left:this.options.position.x}},this.options.content instanceof a&&(this.options.content=this.options.content.clone().attr("id","")),a(window).on("resize.responsivejBoxNotice-"+this.id,function(t){this.isOpen&&this._adjustNoticePositon()}.bind(this)),this.open()},_onCreated:function(){this.wrapper.addClass("jBox-Notice-color jBox-Notice-"+(this.options.color||"gray")),this.wrapper.data("jBox-Notice-position",this.options.attributes.x+"-"+this.options.attributes.y)},_onOpen:function(){this.options.stack||(this._adjustNoticePositon(),a.each(a(".jBox-Notice"),function(t,i){(i=a(i)).attr("id")!=this.id&&i.data("jBox-Notice-position")==this.options.attributes.x+"-"+this.options.attributes.y&&(this.options.stack||i.data("jBox").close({ignoreDelay:!0}))}.bind(this)))},_onPosition:function(){var t,s={};for(t in a.each(a(".jBox-Notice"),function(t,i){var o=(i=a(i)).data("jBox-Notice-position");s[o]||(s[o]=[]),s[o].push(i)}),s){var i=t.split("-")[1];s[t].reverse();var o,n=0;for(o in s[t]){var e=a(s[t][o]);e.css("margin-"+i,n),n+=e.outerHeight()+this.options.stackSpacing}}},_onCloseComplete:function(){this.destroy(),this.options._onPosition.bind(this).call()}})}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,490 @@
1
+declare namespace jBox {
2
+  interface jBoxOptions {
3
+    /** Choose a unique id, otherwise jBox will set one for you (jBox1, jBox2, ...) */
4
+    id?: string;
5
+
6
+    /** The width of the content area */
7
+    width?: 'auto' | number;
8
+
9
+    /** The height of the content area */
10
+    height?: 'auto' | number;
11
+
12
+    /** Minimal width of content area */
13
+    minWidth?: number;
14
+
15
+    /** Minimal height of content area */
16
+    minHeight?: number;
17
+
18
+    /** Maximal width of content area */
19
+    maxWidth?: number;
20
+
21
+    /** Maximal height of content area */
22
+    maxHeight?: number;
23
+
24
+    /** Adjusts width to fit the viewport */
25
+    responsiveWidth?: boolean;
26
+
27
+    /** Adjusts height to fit the viewport */
28
+    responsiveHeight?: boolean;
29
+
30
+    /** Don't adjust width below this value (in pixel) */
31
+    responsiveMinWidth?: number;
32
+
33
+    /** Don't adjust height below this value (in pixel) */
34
+    responsiveMinHeight?: number;
35
+
36
+    /** A jQuery selector to elements that will open and close your jBox, e.g. '.tooltip' */
37
+    attach?: JQuery<HTMLElement>;
38
+
39
+    /** Defines with which event the jBox opens or closes when interacting with the attached element */
40
+    trigger?: 'click' | 'mouseenter' | 'touchclick';
41
+
42
+    /** Prevent the default event when opening jBox, e.g. don't follow the href in a link */
43
+    preventDefault?: boolean;
44
+
45
+    /** Sets the content of your jBox. You can use jQuery elements to append elements (set CSS style display to none so the elements won't show up on your page) */
46
+    content?: string | JQuery<HTMLElement>;
47
+
48
+    /** Get the content from an attribute when jBox opens, e.g. 'data-content'. Use 'html' to get the attached elements HTML as content */
49
+    getContent?: string;
50
+
51
+    /** Adds a title to your jBox */
52
+    title?: string;
53
+
54
+    /** Get the title from an attribute when jBox opens, e.g. 'data-title' */
55
+    getTitle?: string;
56
+
57
+    /** Adds a footer to your jBox */
58
+    footer?: string;
59
+
60
+    /** Isolates scrolling to the content container */
61
+    isolateScroll?: boolean;
62
+
63
+    /** When you set an URL, jBox makes an AJAX request when it opens. You can add any jQuery ajax option, e.g. beforeSend, complete, success, etc. */
64
+    ajax?: jBoxAjaxOptions;
65
+
66
+    /** Cancels the ajax call when you close the jBox and it's not finished yet */
67
+    cancelAjaxOnClose?: boolean,
68
+
69
+    /** The jQuery selector to the target element where jBox will be opened. If no element is found, jBox will use the attached element as target */
70
+    target?: JQuery<HTMLElement>;
71
+
72
+    /** Set an object with the horizontal position x and the vertical position y, e.g. {x: 'right', y: 'center'}. You can also set numbers for an absolute position */
73
+    position?: { x: 'right' | 'left' | 'center' | number; y: 'top' | 'bottom' | 'center' | number };
74
+
75
+    /** Moves your jBox outside of the target element */
76
+    outside?: 'x' | 'y' | 'xy';
77
+
78
+    /** Offset to final position. You can set different values for x and y with an object, e.g. {x: 15, y: -10} */
79
+    offset?: number | { x: number; y: number };
80
+
81
+    /** Defines which CSS attributes should be used, e.g. {x: 'right', y: 'bottom'}. Note that right and bottom can only be used when your position values are integer, e.g. {x: 300, y: 20} */
82
+    attributes?: { x: 'right' | 'left' | 'center'; y: 'top' | 'bottom' | 'center' };
83
+
84
+    /** Your jBox will stay on position when scrolling */
85
+    fixed?: boolean;
86
+
87
+    /** Adjusts your jBoxes position if there is not enough space. The value 'flip' positions the jBox on the opposite outside position, the value 'move' works only with a pointer.
88
+     * Set to true to use both. This option overrides the reposition options */
89
+    adjustPosition?: 'flip' | 'move' | boolean;
90
+
91
+    /** By default jBox adjusts its position when it opens or when the window size changes, set to true to also adjust when scrolling */
92
+    adjustTracker?: boolean;
93
+
94
+    /** The minimal distance to the viewport edge while adjusting. Use an object to set different values, e.g. {top: 50, right: 5, bottom: 20, left: 5} */
95
+    adjustDistance?: number | { top?: number; right?: number; bottom?: number; left?: number };
96
+
97
+    /** Calculates new position when the window-size changes */
98
+    reposition?: boolean;
99
+
100
+    /** Calculates new position each time jBox opens (rather than only when it opens the first time) */
101
+    repositionOnOpen?: boolean;
102
+
103
+    /** Calculates new position when the content changes with .setContent() or .setTitle() */
104
+    repositionOnContent?: boolean;
105
+
106
+    /** Keeps current position if space permits. Applies only to 'Modal' type */
107
+    holdPosition?: boolean;
108
+
109
+    /** Your pointer will always point towards the target element, so the option outside needs to be 'x' or 'y'. By default the pointer is centered, set a position to move it to any side. You can also add an offset, e.g. 'left:30' or 'center:-20'  */
110
+    pointer?: boolean | 'left' | 'right' | 'top' | 'bottom' | 'center';
111
+
112
+    /** Setting something else than 'target' will add a pointer even if there is no target element set or found */
113
+    pointTo?: 'target' | 'left' | 'right' | 'top' | 'bottom';
114
+
115
+    /** Fade duration in ms, set 0 or false to disable */
116
+    fade?: number;
117
+
118
+    /** Animation when jBox opens or closes. To use different animations for opening and closing, use an object: {open: 'tada', close: 'flip'}.
119
+     * You can also set the direction of the move and slide animations: {open: 'move:right', close: 'slide:top'} */
120
+    animation?: jBoxAnimations | { open?: jBoxAnimations; close?: jBoxAnimations } | boolean;
121
+
122
+    /** Set a jBox theme class, e.g. 'TooltipDark' */
123
+    theme?: string;
124
+
125
+    /** Adds classes to the wrapper */
126
+    addClass?: string;
127
+
128
+    /** Adds an overlay to hide page content when jBox opens (adjust color and opacity with CSS) */
129
+    overlay?: boolean;
130
+
131
+    /** Add a class name to the overlay */
132
+    overlayClass?: null | string;
133
+
134
+    /** Use a high z-index, or set to 'auto' to move the jBox to the very top when it opens */
135
+    zIndex?: number | 'auto';
136
+
137
+    /** Delay opening in ms. Note that the delay will be ignored if your jBox didn't finish closing */
138
+    delayOpen?: number;
139
+
140
+    /** Delay closing in ms. Nnote that there is always a closing delay of at least 10ms to ensure jBox won't be closed when opening right away */
141
+    delayClose?: number;
142
+
143
+    /** Close jBox when pressing [esc] key */
144
+    closeOnEsc?: boolean;
145
+
146
+    /** Close jBox with a mouseclick: true closes when you click anywhere, 'overlay' when clicking on the overlay, 'box' when clicking on the jBox itself and 'body' when you click anywhere but the jBox */
147
+    closeOnClick?: boolean | 'body' | 'box' | 'overlay';
148
+
149
+    /** Close jBox when the mouse leaves the jBox area or the area of the attached element */
150
+    closeOnMouseleave?: boolean;
151
+
152
+    /** Adds a close button to your jBox. The value true will add the button to the overlay, title or the jBox itself, in that order if any of those elements can be found */
153
+    closeButton?: boolean | 'overlay' | 'title' | 'box';
154
+
155
+    /** The element your jBox will be appended to. Any other element than $('body') is only useful for fixed positions or when position values are numbers */
156
+    appendTo?: JQuery<HTMLElement>;
157
+
158
+    /** Creates jBox and makes it available in DOM when it's being initialized, otherwise it will be created when it opens for the first time */
159
+    createOnInit?: boolean;
160
+
161
+    /** Blocks scrolling when jBox is open */
162
+    blockScroll?: boolean;
163
+
164
+    /** Adjust page elements to avoid content jumps when scrolling is blocked. See more here: https://github.com/StephanWagner/unscroll */
165
+    blockScrollAdjust?: boolean | string | Array<string | Array<string>>;
166
+
167
+    /** Makes your jBox draggable. Use title or provide the selector of any child element of jBox to use as the handle */
168
+    draggable?: boolean | 'title' | JQuery<HTMLElement>;
169
+
170
+    /** When you have multiple draggable jBoxes, the one you select will always move over the other ones */
171
+    dragOver?: boolean;
172
+
173
+    /** Time in ms when jBox will close automatically after it was opened */
174
+    autoClose?: number | boolean;
175
+
176
+    /** Preloads the audio files set in option audio. You can also preload other audio files, e.g. ['src_to_file.mp3', 'src_to_file.ogg'] */
177
+    preloadAudio?: boolean | string[];
178
+
179
+    /** The URL to an audio file to play when jBox opens. Set the URL without file extension, jBox will look for an .mp3 and .ogg file. To play audio when jBox closes, use an object, e.g. {open: 'src_to_audio1', close: 'src_to_audio2'} */
180
+    audio?: string | { open?: string; close?: string };
181
+
182
+    /** The volume of the audio in percent. To have different volumes for opening and closeing, use an object, e.g. {open: 75, close: 100} */
183
+    volume?: number | { open?: number; close?: number };
184
+
185
+    /** Fired when jBox is initialized. Note that you can use this in the event functions, it refers to your jBox object, e.g. onInit: function() { this.open(); } */
186
+    onInit?: () => void;
187
+
188
+    /** Fired when jBox attached itself to elements */
189
+    onAttach?: () => void;
190
+
191
+    /** Fired when jBox is positioned */
192
+    onPosition?: () => void;
193
+
194
+    /** Fired when jBox is created and is availible in DOM */
195
+    onCreated?: () => void;
196
+
197
+    /** Fired when jBox opens */
198
+    onOpen?: () => void;
199
+
200
+    /** Fired when jBox closes */
201
+    onClose?: () => void;
202
+
203
+    /** Fired when jBox is completely closed (when fading finished) */
204
+    onCloseComplete?: () => void;
205
+
206
+    /** Fired when dragging starts */
207
+    onDragStart?: () => void;
208
+
209
+    /** Fired when dragging finished */
210
+    onDragEnd?: () => void;
211
+  }
212
+
213
+  /** Possible values for the 'animation' option */
214
+  type jBoxAnimations =
215
+    | 'zoomIn'
216
+    | 'zoomOut'
217
+    | 'pulse'
218
+    | 'move'
219
+    | 'slide'
220
+    | 'flip'
221
+    | 'tada'
222
+    | 'move:right'
223
+    | 'move:left'
224
+    | 'move:top'
225
+    | 'move:bottom'
226
+    | 'slide:right'
227
+    | 'slide:left'
228
+    | 'slide:top'
229
+    | 'slide:bottom';
230
+
231
+  /** Options for AJAX calls.  */
232
+  interface jBoxAjaxOptions {
233
+    /** The URL to send the AJAX request to */
234
+    url?: string | null;
235
+
236
+    /** Data to send with your AJAX request, e.g. {id: 82, limit: 10} */
237
+    data?: string | {};
238
+
239
+    /** Resend the AJAX request when jBox opens. Use true to send the AJAX request call only once for every element or 'strict' to resend every time jBox opens  */
240
+    reload?: boolean | 'strict';
241
+
242
+    /** The attribute in the source element where the AJAX request will look for the URL, e.g. 'data-url'  */
243
+    getURL?: string;
244
+
245
+    /** The attribute in the source element where the AJAX request will look for the data, e.g. 'data-ajax'  */
246
+    getData?: string;
247
+
248
+    /** Automatically set the response as new content when the AJAX request is finished  */
249
+    setContent?: boolean;
250
+
251
+    /** Add a class to the wrapper when jBox is loading, set to class name or true to use the default class name 'jBox-loading' */
252
+    loadingClass?: boolean | string,
253
+
254
+    /** Hides the current content and adds a spinner while loading. You can pass HTML content to add your own spinner, e.g. spinner: '<div class="mySpinner"></div>'  */
255
+    spinner?: boolean | string;
256
+
257
+    /** Milliseconds to wait until spinner appears  */
258
+    spinnerDelay?: number;
259
+
260
+    /** Repositions jBox when the spinner is added or removed  */
261
+    spinnerReposition?: boolean;
262
+  }
263
+
264
+  /** Additional options for the Confirm plugin */
265
+  interface jBoxConfirmOptions extends jBoxOptions {
266
+    /** Text for the submit button */
267
+    confirmButton?: string;
268
+
269
+    /** Text for the cancel button */
270
+    cancelButton?: string;
271
+
272
+    /** Function to execute when clicking the submit button. By default jBox will use the onclick or href attribute in that order if found */
273
+    confirm?: () => void;
274
+
275
+    /** Function to execute when clicking the cancel button */
276
+    cancel?: () => void;
277
+
278
+    /** Close jBox when the user clicks the confirm button */
279
+    closeOnConfirm: boolean;
280
+  }
281
+
282
+  /** Additional options for the Image plugin */
283
+  interface jBoxImageOptions extends jBoxOptions {
284
+    /** The attribute to get the image source from, e.g. 'href' for a link: <a href="/path/image.jpg"> */
285
+    src?: string;
286
+
287
+    /** The attribute to set the galleries, e.g. 'data-jbox-gallery'. When changing this option, make sure you check the option attach, as jBox Image gets attached to [data-jbox-gallery] by default. */
288
+    gallery?: string;
289
+
290
+    /** The attribute where jBox gets the image label from, e.g. 'title' */
291
+    imageLabel?: string;
292
+
293
+    /** The fade duration for images in ms */
294
+    imageFade?: number;
295
+
296
+    /** How to display the images. Use CSS styles of background-position, e.g. 'cover', '50% auto' */
297
+    imageSize?: 'cover' | 'contain' | 'auto' | string;
298
+
299
+    /** Set to true to add an image counter, e.g. 4/20 */
300
+    imageCounter?: boolean;
301
+
302
+    /** HTML to separate the current image number from all image numbers, e.g. '/' or ' of ' */
303
+    imageCounterSeparator: string;
304
+
305
+    /** Adds a download button */
306
+    downloadButton?: boolean;
307
+
308
+    /** Text for the download button */
309
+    downloadButtonText?: string | null;
310
+
311
+    /** The attribute at the source element where to find the image to download, e.g. data-download="/path_to_image/image.jpg". If none provided, the currently active image will be downloaded */
312
+    downloadButtonUrl?: string | null;
313
+
314
+    /** The attribute to look for an mobile version of the image */
315
+    mobileImageAttr?: string | null;
316
+
317
+    /** The upper breakpoint to load the mobile image */
318
+    mobileImageBreakpoint?: number | null;
319
+
320
+    /** Preload the first image when page is loaded */
321
+    preloadFirstImage?: boolean;
322
+  }
323
+
324
+  /** Additional options for the Notice plugin */
325
+  interface jBoxNoticeOptions extends jBoxOptions {
326
+    /** Add a color to your notices */
327
+    color?: 'black' | 'red' | 'green' | 'blue' | 'yellow';
328
+
329
+    /** Set to false to disable notice-stacking */
330
+    stack?: boolean;
331
+
332
+    /** Spacing between notices when they stack */
333
+    stackSpacing?: number;
334
+
335
+    /** When hovering the notice it won't close */
336
+    delayOnHover?: boolean;
337
+
338
+    /** Adds a progress bar showing the time it will take until the notice closes */
339
+    showCountdown?: boolean;
340
+  }
341
+
342
+
343
+}
344
+
345
+/** Connects the name of the plugin with the type of its options */
346
+declare interface jBoxOptionsMap {
347
+  Tooltip: jBox.jBoxOptions;
348
+  Modal: jBox.jBoxOptions;
349
+  Confirm: jBox.jBoxConfirmOptions;
350
+  Notice: jBox.jBoxNoticeOptions;
351
+  Image: jBox.jBoxImageOptions;
352
+}
353
+
354
+interface IgnoreDelay {
355
+/** Whether to open or close immediately (true) or respect the original delay settings. */
356
+ignoreDelay?: boolean;
357
+}
358
+
359
+/** The core jBox class. Create instances using 'new' e.g. new jBox('Tooltip', { attach: '.tooltip'. }) */
360
+declare class jBox<T extends keyof jBoxOptionsMap> {
361
+  constructor(type: T, options: jBoxOptionsMap[T]);
362
+
363
+  /**
364
+   * Opens the jBox. You can set a new target with the option target, e.g. {target: $('#newTarget')}.
365
+   * If your jBox has an opening delay, you can force it to open immediately with the option ignoreDelay,
366
+   * e.g. {ignoreDelay: true}. To set new AJAX content when opening the jBox, you can pass an AJAX object,
367
+   * e.g. {ajax: {url: 'https://reqres.in/api/users'}}
368
+   */
369
+  open(options?: jBoxOptionsMap[T] & IgnoreDelay): void;
370
+
371
+  /**
372
+   * Closes the jBox. If your jBox has a closing delay, you can force it to close immediately with the option
373
+   * ignoreDelay, e.g. {ignoreDelay: true}
374
+   */
375
+  close(options?: jBoxOptionsMap[T] & IgnoreDelay): void;
376
+
377
+  /**
378
+   * Calls the method open when jBox is closed and close when it is open
379
+   */
380
+  toggle(options?: jBoxOptionsMap[T] & IgnoreDelay): void;
381
+
382
+  /** Sets the CSS width of the content container.
383
+   * Optional you can set a second argument to disable the automatic repositioning of jBox, e.g. .setWidth(200, true)
384
+   */
385
+  setWidth(value: number, disableAutoPosition?: boolean): void;
386
+
387
+  /** Sets the CSS height of the content container.
388
+   * Optional you can set a second argument to disable the automatic repositioning of jBox, e.g. .setWidth(200, true)
389
+   */
390
+  setHeight(value: number, disableAutoPosition?: boolean): void;
391
+
392
+  /**
393
+   * Attaches your jBox to elements. Providing a jQuery selector is optional.
394
+   * If you don't tell this method which elements to use, it will use the selector defined in the options.
395
+   * This method should be called when elements, which should open or close a jBox, are being created in runtime
396
+   */
397
+  attach(element: JQuery<HTMLElement>): void;
398
+
399
+  /**
400
+   * Removes the open and close function from elements.
401
+   */
402
+  detach(element: JQuery<HTMLElement>): void;
403
+  /**
404
+   * Sets the title of your jBox. If there is no title yet, it will be created.
405
+   * jBox will reposition if dimensions change, to disable, pass true as second argument:
406
+   * @example .setTitle('myTitle', true)
407
+   */
408
+  setTitle(title: string, disableAutoPosition?: boolean): void;
409
+
410
+  /**
411
+   * Sets the content of your jBox. You can use jQuery elements to append elements
412
+   * (set CSS style display to none so the elements won't show up on your page).
413
+   * jBox will reposition if dimensions change, to disable, pass true as second argument:
414
+   * @example .setContent('myContent', true)
415
+   */
416
+  setContent(content: string, disableAutoPosition?: boolean): void;
417
+
418
+  /**
419
+   * Reloads the AJAX request. You can pass the options url and data, e.g. {url: '/example.php', data: 'id=82'} or any jQuery ajax Option.
420
+   */
421
+  ajax(options: jBox.jBoxAjaxOptions): void;
422
+
423
+  /**
424
+   * Abort running ajax call
425
+   */
426
+  cancelAjax(): void;
427
+
428
+  /**
429
+   * Plays an audio file. Don't add the file extension, jBox will look for an .mp3 and an .ogg file.
430
+   */
431
+  audio(url: string, volume: number): void;
432
+
433
+  /**
434
+   * Recalculates your jBoxes position. You can set a new target with the option target, e.g. {target: $('#newTarget')}
435
+   */
436
+  position(options: jBoxOptionsMap[T]): void;
437
+
438
+  /**
439
+   * Animates for your jBox or any other element. The animation method is independent from the option animation.
440
+   * By default this method will animate the jBox wrapper, to animate another element set the option element, e.g. {element: $('#animateMe')}.
441
+   * To execute a function when the animation is finished use the option complete, e.g. {complete: function () { $('#animateMe').remove(); }}
442
+   */
443
+  animate(
444
+  animation:
445
+      | 'tada'
446
+      | 'tadaSmall'
447
+      | 'flash'
448
+      | 'shake'
449
+      | 'pulseUp'
450
+      | 'pulseDown'
451
+      | 'popIn'
452
+      | 'popOut'
453
+      | 'fadeIn'
454
+      | 'fadeOut'
455
+      | 'slideUp'
456
+      | 'slideRight'
457
+      | 'slideLeft'
458
+      | 'slideDown',
459
+  options?: { element?: JQuery<HTMLElement>; complete?: () => void }
460
+  ): void;
461
+
462
+  /**
463
+   * Disables your jBox, you won't be able to open or close it until enabled.
464
+   */
465
+  disable(): void;
466
+
467
+  /**
468
+   * Enables your jBox, so you can close and open it again.
469
+   */
470
+  enable(): void;
471
+
472
+  /**
473
+   * Disables and hides the jBox. This doesnt affect the overlay.
474
+   */
475
+  hide(): void;
476
+
477
+  /**
478
+   * Enables and shows your jBox again.
479
+   */
480
+  show(): void;
481
+
482
+  /**
483
+   * Destroys your jBox and removes it from DOM.
484
+   */
485
+  destroy(): void;
486
+}
487
+
488
+export = jBox;
489
+
490
+export as namespace jBox;
0 491
new file mode 100644
... ...
@@ -0,0 +1,2270 @@
1
+/**
2
+ * jBox is a jQuery plugin that makes it easy to create customizable tooltips, modal windows, image galleries and more.
3
+ *
4
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
5
+ *
6
+ * License: MIT (https://opensource.org/licenses/MIT)
7
+ *
8
+ * Requires: jQuery 3.5.0 (https://code.jquery.com/jquery-3.5.0.min.js)
9
+ *
10
+ * Documentation: https://stephanwagner.me/jBox/documentation
11
+ *
12
+ * Demos: https://stephanwagner.me/jBox/demos
13
+ */
14
+
15
+function jBoxWrapper(jQuery) {
16
+
17
+
18
+  var jBox = function jBox(type, options) {
19
+
20
+
21
+    // Options (https://stephanwagner.me/jBox/options)
22
+
23
+    this.options = {
24
+
25
+      // jBox ID
26
+      id: null,                    // Choose a unique id, otherwise jBox will set one for you (jBox1, jBox2, ...)
27
+
28
+      // Dimensions
29
+      width: 'auto',               // The width of the content area, e.g. 'auto', 200, '80%'
30
+      height: 'auto',              // The height of the content area
31
+      minWidth: null,              // Minimal width
32
+      minHeight: null,             // Minimal height
33
+      maxWidth: null,              // Maximal width
34
+      maxHeight: null,             // Maximal height
35
+
36
+      // Responsive dimensions
37
+      responsiveWidth: true,       // Adjusts the width to fit the viewport
38
+      responsiveHeight: true,      // Adjusts the height to fit the viewport
39
+      responsiveMinWidth: 100,     // Don't adjust width below this value (in pixel)
40
+      responsiveMinHeight: 100,    // Don't adjust height below this value (in pixel)
41
+
42
+      // Attach
43
+      attach: null,                // A jQuery selector to elements that will open and close your jBox, e.g. '.tooltip'
44
+      trigger: 'click',            // The event to open or close your jBox, use 'click', 'touchclick' or 'mouseenter'
45
+      preventDefault: false,       // Prevent the default event when opening jBox, e.g. don't follow the href in a link
46
+
47
+      // Content
48
+      content: null,               // You can use HTML or a jQuery element, e.g. jQuery('#jBox-content'). The elements will be appended to the content element and then made visible, so hide them with style="display: none" beforehand
49
+      getContent: null,            // Get the content from an attribute when jBox opens, e.g. getContent: 'data-content'. Use 'html' to get the attached elements HTML as content
50
+      title: null,                 // Adds a title to your jBox
51
+      getTitle: null,              // Get the title from an attribute when jBox opens, e.g. getTitle: 'data-title'
52
+      footer: null,                // Adds a footer to your jBox
53
+      isolateScroll: true,         // Isolates scrolling to the content container
54
+
55
+      // AJAX
56
+      ajax: {                      // Setting an URL will make an AJAX request when jBox opens. Optional you can add any jQuery AJAX option (http://api.jquery.com/jquery.ajax/)
57
+        url: null,                 // The URL to send the AJAX request to
58
+        data: '',                  // Data to send with your AJAX request, e.g. {id: 82, limit: 10}
59
+        reload: false,             // Resend the AJAX request when jBox opens. Use true to send the AJAX request only once for every attached element or 'strict' to resend every time jBox opens
60
+        getURL: 'data-url',        // The attribute in the source element where the AJAX request will look for the URL, e.g. data-url="https://reqres.in/api/users"
61
+        getData: 'data-ajax',      // The attribute in the source element where the AJAX request will look for the data, e.g. data-ajax="id=82&limit=10"
62
+        setContent: true,          // Automatically set the response as new content when the AJAX request is finished
63
+        loadingClass: true,        // Add a class to the wrapper when jBox is loading, set to class name or true to use the default class name 'jBox-loading'
64
+        spinner: true,             // Hides the current content and adds a spinner while loading. You can pass HTML content to add your own spinner, e.g. spinner: '<div class="mySpinner"></div>'
65
+        spinnerDelay: 300,         // Milliseconds to wait until spinner appears
66
+        spinnerReposition: true    // Repositions jBox when the spinner is added or removed
67
+      },
68
+      cancelAjaxOnClose: true,     // Cancels the ajax call when jBox closes and it hasn't finished loading yet
69
+
70
+      // Position
71
+      target: null,                // The jQuery selector to the target element where jBox will be opened. If no element is found, jBox will use the attached element as target
72
+      position: {
73
+        x: 'center',               // Horizontal position, use a number, 'left', 'right' or 'center'
74
+        y: 'center'                // Vertical position, use a number, 'top', 'bottom' or 'center'
75
+      },
76
+      outside: null,               // Use 'x', 'y', or 'xy' to move your jBox outside of the target element
77
+      offset: 0,                   // Offset to final position, you can set different values for x and y with an object, e.g. {x: 20, y: 10}
78
+      attributes: {                // Note that attributes can only be 'left' or 'right' when using numbers for position, e.g. {x: 300, y: 20}
79
+        x: 'left',                 // Horizontal position, use 'left' or 'right'
80
+        y: 'top'                   // Vertical position, use 'top' or 'bottom'
81
+      },
82
+      fixed: false,                // Your jBox will stay on position when scrolling
83
+      adjustPosition: true,        // Adjusts your jBoxes position if there is not enough space, use 'flip', 'move' or true for both. This option overrides the reposition options
84
+      adjustTracker: false,        // By default jBox adjusts its position when it opens or when the window size changes, set to true to also adjust when scrolling
85
+      adjustDistance: 5,           // The minimal distance to the viewport edge while adjusting. Use an object to set different values, e.g. {top: 50, right: 5, bottom: 20, left: 5}
86
+      reposition: true,            // Calculates new position when the window-size changes
87
+      repositionOnOpen: true,      // Calculates new position each time jBox opens (rather than only when it opens the first time)
88
+      repositionOnContent: true,   // Calculates new position when the content changes with .setContent() or .setTitle()
89
+      holdPosition: true,          // Keeps current position if space permits. Applies only to 'Modal' type.
90
+
91
+      // Pointer
92
+      pointer: false,              // Your pointer will always point towards the target element, so the option outside needs to be 'x' or 'y'. By default the pointer is centered, set a position to move it to any side. You can also add an offset, e.g. 'left:30' or 'center:-20'
93
+      pointTo: 'target',           // Setting something else than 'target' will add a pointer even if there is no target element set or found. Use 'top', 'right', 'bottom' or 'left'
94
+
95
+      // Animations
96
+      fade: 180,                   // Fade duration in ms, set to 0 or false to disable
97
+      animation: null,             // Animation when opening or closing, use 'pulse', 'zoomIn', 'zoomOut', 'move', 'slide', 'flip', 'tada' (CSS inspired from Daniel Edens Animate.css: http://daneden.me/animate)
98
+
99
+      // Appearance
100
+      theme: 'Default',            // Set a jBox theme class
101
+      addClass: null,              // Adds classes to the wrapper
102
+      overlay: false,              // Adds an overlay to hide page content when jBox opens (adjust color and opacity with CSS)
103
+      overlayClass: null,          // Add a class name to the overlay
104
+      zIndex: 10000,               // Use a high z-index, or set to 'auto' to bring to front on open
105
+
106
+      // Delays
107
+      delayOpen: 0,                // Delay opening in ms. Note that the delay will be ignored if your jBox didn't finish closing
108
+      delayClose: 0,               // Delay closing in ms. Nnote that there is always a closing delay of at least 10ms to ensure jBox won't be closed when opening right away
109
+
110
+      // Closing
111
+      closeOnEsc: false,           // Close jBox when pressing [esc] key
112
+      closeOnClick: false,         // Close jBox with mouseclick. Use true (click anywhere), 'box' (click on jBox itself), 'overlay' (click on the overlay), 'body' (click anywhere but jBox)
113
+      closeOnMouseleave: false,    // Close jBox when the mouse leaves the jBox area or the area of the attached element
114
+      closeButton: false,          // Adds a close button to your jBox. Use 'title', 'box', 'overlay' or true (true will add the button to the overlay, title or the jBox itself, in that order if any of those elements can be found)
115
+
116
+      // Other options
117
+      appendTo: jQuery('body'),    // The element your jBox will be appended to. Any other element than jQuery('body') is only useful for fixed positions or when position values are numbers
118
+      createOnInit: false,         // Creates jBox and makes it available in DOM when it's being initialized, otherwise it will be created when it opens for the first time
119
+      blockScroll: false,          // Blocks scrolling when jBox is open
120
+      blockScrollAdjust: true,     // Adjust page elements to avoid content jumps when scrolling is blocked. See more here: https://github.com/StephanWagner/unscroll
121
+      draggable: false,            // Make your jBox draggable (use 'true', 'title' or provide an element as handle) (inspired from Chris Coyiers CSS-Tricks http://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/)
122
+      dragOver: true,              // When you have multiple draggable jBoxes, the one you select will always move over the other ones
123
+      autoClose: false,            // Time in ms when jBox will close automatically after it was opened
124
+      delayOnHover: false,         // Delay auto-closing while mouse is hovered
125
+      showCountdown: false,        // Display a nice progress-indicator when autoClose is enabled
126
+
127
+      // Audio                     // You can use the integrated audio function whenever you'd like to play an audio file, e.g. onInit: function () { this.audio('url_to_audio_file_without_file_extension', 75); }
128
+      preloadAudio: true,          // Preloads the audio files set in option audio. You can also preload other audio files, e.g. ['src_to_file.mp3', 'src_to_file.ogg']
129
+      audio: null,                 // The URL to an audio file to play when jBox opens. Set the URL without file extension, jBox will look for an .mp3 and .ogg file. To play audio when jBox closes, use an object, e.g. {open: 'src_to_audio1', close: 'src_to_audio2'}
130
+      volume: 100,                 // The volume in percent. To have different volumes for opening and closeing, use an object, e.g. {open: 75, close: 100}
131
+
132
+      // Events                    // Note that you can use 'this' in all event functions, it refers to your jBox object (e.g. onInit: function () { this.open(); })
133
+      onInit: null,                // Fired when jBox is initialized
134
+      onAttach: null,              // Fired when jBox attached itself to elements, the attached element will be passed as a parameter, e.g. onAttach: function (element) { element.css({color: 'red'}); }
135
+      onPosition: null,            // Fired when jBox is positioned
136
+      onCreated: null,             // Fired when jBox is created and availible in DOM
137
+      onOpen: null,                // Fired when jBox opens
138
+      onClose: null,               // Fired when jBox closes
139
+      onCloseComplete: null,       // Fired when jBox is completely closed (when fading is finished)
140
+      onDragStart: null,           // Fired when dragging starts
141
+      onDragEnd: null              // Fired when dragging finished
142
+    };
143
+
144
+
145
+    // Default plugin options
146
+
147
+    this._pluginOptions = {
148
+
149
+      // Default options for tooltips
150
+      'Tooltip': {
151
+        getContent: 'title',
152
+        trigger: 'mouseenter',
153
+        position: {
154
+          x: 'center',
155
+          y: 'top'
156
+        },
157
+        outside: 'y',
158
+        pointer: true
159
+      },
160
+
161
+      // Default options for mouse tooltips
162
+      'Mouse': {
163
+        responsiveWidth: false,
164
+        responsiveHeight: false,
165
+        adjustPosition: 'flip',
166
+        target: 'mouse',
167
+        trigger: 'mouseenter',
168
+        position: {
169
+          x: 'right',
170
+          y: 'bottom'
171
+        },
172
+        outside: 'xy',
173
+        offset: 5
174
+      },
175
+
176
+      // Default options for modal windows
177
+      'Modal': {
178
+        target: jQuery(window),
179
+        fixed: true,
180
+        blockScroll: true,
181
+        closeOnEsc: true,
182
+        closeOnClick: 'overlay',
183
+        closeButton: true,
184
+        overlay: true,
185
+        animation: 'zoomIn'
186
+      },
187
+    };
188
+
189
+
190
+    // Merge options
191
+
192
+    this.options = jQuery.extend(true, this.options, this._pluginOptions[type] ? this._pluginOptions[type] : jBox._pluginOptions[type], options);
193
+
194
+
195
+    // Set the jBox type
196
+
197
+    jQuery.type(type) == 'string' && (this.type = type);
198
+
199
+
200
+    // Checks if the user is on a touch device, borrowed from https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js
201
+
202
+    this.isTouchDevice = (function () {
203
+      var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
204
+      var mq = function (query) {
205
+        return window.matchMedia(query).matches;
206
+      }
207
+
208
+      if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
209
+        return true;
210
+      }
211
+
212
+      var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
213
+      return mq(query);
214
+    })();
215
+
216
+
217
+    // Add close event for body click when we are on touch device and jBox triggers on mouseenter
218
+
219
+    if (this.isTouchDevice && this.options.trigger === 'mouseenter' && this.options.closeOnClick === false) {
220
+      this.options.closeOnClick = 'body';
221
+    }
222
+
223
+
224
+    // Local function to fire events
225
+
226
+    this._fireEvent = function (event, pass)
227
+    {
228
+      this.options['_' + event] && (this.options['_' + event].bind(this))(pass);
229
+      this.options[event] && (this.options[event].bind(this))(pass);
230
+    };
231
+
232
+
233
+    // Get a unique jBox ID
234
+
235
+    this.options.id === null && (this.options.id = 'jBox' + jBox._getUniqueID());
236
+    this.id = this.options.id;
237
+
238
+
239
+    // Correct impossible options
240
+
241
+    ((this.options.position.x == 'center' && this.options.outside == 'x') || (this.options.position.y == 'center' && this.options.outside == 'y')) && (this.options.outside = null);
242
+    this.options.pointTo == 'target' && (!this.options.outside || this.options.outside == 'xy') && (this.options.pointer = false);
243
+
244
+
245
+    // Correct multiple choice options
246
+
247
+    jQuery.type(this.options.offset) != 'object' ? (this.options.offset = {x: this.options.offset, y: this.options.offset}) : (this.options.offset = jQuery.extend({x: 0, y: 0}, this.options.offset));
248
+    jQuery.type(this.options.adjustDistance) != 'object' ? (this.options.adjustDistance = {top: this.options.adjustDistance, right: this.options.adjustDistance, bottom: this.options.adjustDistance, left: this.options.adjustDistance}) : (this.options.adjustDistance = jQuery.extend({top: 5, left: 5, right: 5, bottom: 5}, this.options.adjustDistance));
249
+
250
+
251
+    // Save default outside position
252
+
253
+    this.outside = this.options.outside && this.options.outside != 'xy' ? this.options.position[this.options.outside] : false;
254
+
255
+
256
+    // Save where the jBox is aligned to
257
+
258
+    this.align = this.outside ? this.outside : (this.options.position.y != 'center' && jQuery.type(this.options.position.y) != 'number' ? this.options.position.x : (this.options.position.x != 'center' && jQuery.type(this.options.position.x) != 'number' ? this.options.position.y : this.options.attributes.x));
259
+
260
+
261
+    // Adjust option zIndex
262
+
263
+    jBox.zIndexMax = Math.max(jBox.zIndexMax || 0, this.options.zIndex === 'auto' ? 10000 : this.options.zIndex);
264
+    if (this.options.zIndex === 'auto') {
265
+      this.adjustZIndexOnOpen = true;
266
+      jBox.zIndexMax += 2;
267
+      this.options.zIndex = jBox.zIndexMax;
268
+      this.trueModal = this.options.overlay;
269
+    }
270
+
271
+    // Internal positioning functions
272
+
273
+    this._getOpp = function (opp) { return {left: 'right', right: 'left', top: 'bottom', bottom: 'top', x: 'y', y: 'x'}[opp]; };
274
+    this._getXY = function (xy) { return {left: 'x', right: 'x', top: 'y', bottom: 'y', center: 'x'}[xy]; };
275
+    this._getTL = function (tl) { return {left: 'left', right: 'left', top: 'top', bottom: 'top', center: 'left', x: 'left', y: 'top'}[tl]; };
276
+
277
+
278
+    // Get a dimension value in integer pixel dependent on appended element
279
+
280
+    this._getInt = function (value, dimension) {
281
+      if (value == 'auto') return 'auto';
282
+      if (value && jQuery.type(value) == 'string' && value.slice(-1) == '%') {
283
+        return jQuery(window)[dimension == 'height' ? 'innerHeight' : 'innerWidth']() * parseInt(value.replace('%', '')) / 100;
284
+      }
285
+      return value;
286
+    };
287
+
288
+
289
+    // Create an svg element
290
+
291
+    this._createSVG = function (type, options)
292
+    {
293
+      var svg = document.createElementNS('http://www.w3.org/2000/svg', type);
294
+      jQuery.each(options, function (index, item) {
295
+        svg.setAttribute(item[0], (item[1] || ''));
296
+      });
297
+      return svg;
298
+    };
299
+
300
+
301
+    // Isolate scrolling in a container
302
+
303
+    this._isolateScroll = function (el)
304
+    {
305
+      // Abort if element not found
306
+      if (!el || !el.length) return;
307
+
308
+      el.on('DOMMouseScroll.jBoxIsolateScroll mousewheel.jBoxIsolateScroll', function (ev) {
309
+        var delta = ev.wheelDelta || (ev.originalEvent && ev.originalEvent.wheelDelta) || -ev.detail;
310
+        var overflowBottom = this.scrollTop + el.outerHeight() - this.scrollHeight >= 0;
311
+        var overflowTop = this.scrollTop <= 0;
312
+        ((delta < 0 && overflowBottom) || (delta > 0 && overflowTop)) && ev.preventDefault();
313
+      });
314
+    };
315
+
316
+
317
+    // Set the title width to content width
318
+
319
+    this._setTitleWidth = function ()
320
+    {
321
+      // Abort if there is no title or width of content is auto
322
+      if (!this.titleContainer || (this.content[0].style.width == 'auto' && !this.content[0].style.maxWidth)) return null;
323
+
324
+      // Expose wrapper to get actual width
325
+      if (this.wrapper.css('display') == 'none') {
326
+        this.wrapper.css('display', 'block');
327
+        var contentWidth = this.content.outerWidth();
328
+        this.wrapper.css('display', 'none');
329
+      } else {
330
+        var contentWidth = this.content.outerWidth();
331
+      }
332
+
333
+      // Set max-width only
334
+      this.titleContainer.css({maxWidth: (Math.max(contentWidth, parseInt(this.content[0].style.maxWidth)) || null)});
335
+    }
336
+
337
+
338
+    // Make jBox draggable
339
+
340
+    this._draggable = function ()
341
+    {
342
+      // Abort if jBox is not draggable
343
+      if (!this.options.draggable) return false;
344
+
345
+      // Get the handle where jBox will be dragged with
346
+      var handle = this.options.draggable == 'title' ? this.titleContainer : (this.options.draggable instanceof jQuery ? this.options.draggable : (jQuery.type(this.options.draggable) == 'string' ? jQuery(this.options.draggable) : this.wrapper));
347
+
348
+      // Abort if no handle or if draggable was set already
349
+      if (!handle || !(handle instanceof jQuery) || !handle.length || handle.data('jBox-draggable')) return false;
350
+
351
+      // Add mouse events
352
+      handle.addClass('jBox-draggable').data('jBox-draggable', true).on('touchstart mousedown', function (ev)
353
+      {
354
+        if (ev.button == 2 || jQuery(ev.target).hasClass('jBox-noDrag') || jQuery(ev.target).parents('.jBox-noDrag').length) return;
355
+
356
+        // Store current mouse position
357
+        this.draggingStartX = ev.pageX;
358
+        this.draggingStartY = ev.pageY;
359
+
360
+        // Adjust z-index when dragging jBox over another draggable jBox
361
+        if (this.options.dragOver && !this.trueModal && parseInt(this.wrapper.css('zIndex'), 10) <= jBox.zIndexMaxDragover) {
362
+          jBox.zIndexMaxDragover += 1;
363
+          this.wrapper.css('zIndex', jBox.zIndexMaxDragover);
364
+        }
365
+
366
+        var drg_h = this.wrapper.outerHeight();
367
+        var drg_w = this.wrapper.outerWidth();
368
+        var pos_y = this.wrapper.offset().top + drg_h - ev.pageY;
369
+        var pos_x = this.wrapper.offset().left + drg_w - ev.pageX;
370
+
371
+        jQuery(document).on('touchmove.jBox-draggable-' + this.id + ' mousemove.jBox-draggable-' + this.id, function (ev) {
372
+          // Fire onDragStart event when jBox moves
373
+          if (!this.dragging && this.draggingStartX != ev.pageX && this.draggingStartY != ev.pageY) {
374
+            this._fireEvent('onDragStart');
375
+            this.dragging = true;
376
+          }
377
+
378
+          // Adjust position
379
+          this.wrapper.offset({
380
+            top: ev.pageY + pos_y - drg_h,
381
+            left: ev.pageX + pos_x - drg_w
382
+          });
383
+        }.bind(this));
384
+        ev.preventDefault();
385
+
386
+      }.bind(this)).on('touchend mouseup', function () {
387
+        // Remove drag event
388
+        jQuery(document).off('touchmove.jBox-draggable-' + this.id + ' mousemove.jBox-draggable-' + this.id);
389
+
390
+        // Fire onDragEnd event
391
+        this.dragging && this._fireEvent('onDragEnd');
392
+
393
+        // Reset dragging reference
394
+        this.dragging = false;
395
+
396
+        if ((this.type == 'Modal' || this.type == 'Confirm') && this.options.holdPosition) {
397
+          // Drag end captures new position
398
+          var jBoxOffset = jQuery('#' + this.id).offset(),
399
+            pos = {
400
+              x: jBoxOffset.left - jQuery(document).scrollLeft(),
401
+              y: jBoxOffset.top - jQuery(document).scrollTop()
402
+            };
403
+          this.position({position: pos, offset: {x: 0, y: 0}});
404
+        }
405
+      }.bind(this));
406
+
407
+      // Get highest z-index
408
+      if (!this.trueModal) {
409
+        jBox.zIndexMaxDragover = !jBox.zIndexMaxDragover ? this.options.zIndex : Math.max(jBox.zIndexMaxDragover, this.options.zIndex);
410
+      }
411
+
412
+      return this;
413
+    };
414
+
415
+    // Create jBox
416
+
417
+    this._create = function ()
418
+    {
419
+      // Abort if jBox was created already
420
+      if (this.wrapper) return;
421
+
422
+      // Create wrapper
423
+      this.wrapper = jQuery('<div/>', {
424
+        id: this.id,
425
+        'class': 'jBox-wrapper' + (this.type ? ' jBox-' + this.type : '') + (this.options.theme ? ' jBox-' + this.options.theme : '') + (this.options.addClass ? ' ' + this.options.addClass : '')
426
+      }).css({
427
+        position: (this.options.fixed ? 'fixed' : 'absolute'),
428
+        display: 'none',
429
+        opacity: 0,
430
+        zIndex: this.options.zIndex
431
+
432
+        // Save the jBox instance in the wrapper, so you can get access to your jBox when you only have the element
433
+      }).data('jBox', this);
434
+
435
+      // Add mouseleave event, only close jBox when the new target is not the source element
436
+      this.options.closeOnMouseleave && this.wrapper.on('mouseleave', function (ev) {
437
+        !this.source || !(ev.relatedTarget == this.source[0] || jQuery.inArray(this.source[0], jQuery(ev.relatedTarget).parents('*')) !== -1) && this.close();
438
+      }.bind(this));
439
+
440
+      // Add closeOnClick: 'box' events
441
+      (this.options.closeOnClick == 'box') && this.wrapper.on('click tap', function () { this.close({ignoreDelay: true}); }.bind(this));
442
+
443
+      // Create container
444
+      this.container = jQuery('<div class="jBox-container"/>').appendTo(this.wrapper);
445
+
446
+      // Create content
447
+      this.content = jQuery('<div class="jBox-content"/>').appendTo(this.container);
448
+
449
+      // Create footer
450
+      this.options.footer && (this.footer = jQuery('<div class="jBox-footer"/>').append(this.options.footer).appendTo(this.container));
451
+
452
+      // Isolate scrolling
453
+      this.options.isolateScroll && this._isolateScroll(this.content);
454
+
455
+      // Create close button
456
+      if (this.options.closeButton) {
457
+        var closeButtonSVG = this._createSVG('svg', [['viewBox', '0 0 24 24']]);
458
+        closeButtonSVG.appendChild(this._createSVG('path', [['d', 'M22.2,4c0,0,0.5,0.6,0,1.1l-6.8,6.8l6.9,6.9c0.5,0.5,0,1.1,0,1.1L20,22.3c0,0-0.6,0.5-1.1,0L12,15.4l-6.9,6.9c-0.5,0.5-1.1,0-1.1,0L1.7,20c0,0-0.5-0.6,0-1.1L8.6,12L1.7,5.1C1.2,4.6,1.7,4,1.7,4L4,1.7c0,0,0.6-0.5,1.1,0L12,8.5l6.8-6.8c0.5-0.5,1.1,0,1.1,0L22.2,4z']]));
459
+        this.closeButton = jQuery('<div class="jBox-closeButton jBox-noDrag"/>').on('click tap', function (ev) { this.close({ignoreDelay: true}); }.bind(this)).append(closeButtonSVG);
460
+
461
+        // Add close button to jBox container
462
+        if (this.options.closeButton == 'box' || (this.options.closeButton === true && !this.options.overlay && !this.options.title && !this.options.getTitle)) {
463
+          this.wrapper.addClass('jBox-closeButton-box');
464
+          this.closeButton.appendTo(this.container);
465
+        }
466
+      }
467
+
468
+      // Append jBox to DOM
469
+      this.wrapper.appendTo(this.options.appendTo);
470
+
471
+      // Fix adjustDistance if there is a close button in the box
472
+      this.wrapper.find('.jBox-closeButton').length &&  jQuery.each(['top', 'right', 'bottom', 'left'], function (index, pos) {
473
+        this.wrapper.find('.jBox-closeButton').css(pos) && this.wrapper.find('.jBox-closeButton').css(pos) != 'auto' && (this.options.adjustDistance[pos] = Math.max(this.options.adjustDistance[pos], this.options.adjustDistance[pos] + (((parseInt(this.wrapper.find('.jBox-closeButton').css(pos)) || 0) + (parseInt(this.container.css('border-' + pos + '-width')) || 0)) * -1)));
474
+      }.bind(this));
475
+
476
+      // Create pointer
477
+      if (this.options.pointer) {
478
+
479
+        // Get pointer vars and save globally
480
+        this.pointer = {
481
+          position: (this.options.pointTo != 'target') ? this.options.pointTo : this._getOpp(this.outside),
482
+          xy: (this.options.pointTo != 'target') ? this._getXY(this.options.pointTo) : this._getXY(this.outside),
483
+          align: 'center',
484
+          offset: 0
485
+        };
486
+
487
+        this.pointer.element = jQuery('<div class="jBox-pointer jBox-pointer-' + this.pointer.position + '"/>').appendTo(this.wrapper);
488
+        this.pointer.dimensions = {
489
+          x: this.pointer.element.outerWidth(),
490
+          y: this.pointer.element.outerHeight()
491
+        };
492
+
493
+        if (jQuery.type(this.options.pointer) == 'string') {
494
+          var split = this.options.pointer.split(':');
495
+          split[0] && (this.pointer.align = split[0]);
496
+          split[1] && (this.pointer.offset = parseInt(split[1]));
497
+        }
498
+        this.pointer.alignAttribute = (this.pointer.xy == 'x' ? (this.pointer.align == 'bottom' ? 'bottom' : 'top') : (this.pointer.align == 'right' ? 'right' : 'left'));
499
+
500
+        // Set wrapper CSS
501
+        this.wrapper.css('padding-' + this.pointer.position, this.pointer.dimensions[this.pointer.xy]);
502
+
503
+        // Set pointer CSS
504
+        this.pointer.element.css(this.pointer.alignAttribute, (this.pointer.align == 'center' ? '50%' : 0)).css('margin-' + this.pointer.alignAttribute, this.pointer.offset);
505
+        this.pointer.margin = {};
506
+        this.pointer.margin['margin-' + this.pointer.alignAttribute] = this.pointer.offset;
507
+
508
+        // Add a transform to fix centered position
509
+        (this.pointer.align == 'center') && this.pointer.element.css('transform', 'translate(' + (this.pointer.xy == 'y' ? (this.pointer.dimensions.x * -0.5 + 'px') : 0) + ', ' + (this.pointer.xy == 'x' ? (this.pointer.dimensions.y * -0.5 + 'px') : 0) + ')');
510
+
511
+        this.pointer.element.css((this.pointer.xy == 'x' ? 'width' : 'height'), parseInt(this.pointer.dimensions[this.pointer.xy]) + parseInt(this.container.css('border-' + this.pointer.alignAttribute + '-width')));
512
+
513
+        // Add class to wrapper for CSS access
514
+        this.wrapper.addClass('jBox-pointerPosition-' + this.pointer.position);
515
+      }
516
+
517
+      // Set title and content
518
+      this.setContent(this.options.content, true);
519
+      this.setTitle(this.options.title, true);
520
+
521
+      this.options.draggable && this._draggable();
522
+
523
+      // Fire onCreated event
524
+      this._fireEvent('onCreated');
525
+    };
526
+
527
+
528
+    // Create jBox onInit
529
+
530
+    this.options.createOnInit && this._create();
531
+
532
+
533
+    // Attach jBox
534
+
535
+    this.options.attach && this.attach();
536
+
537
+
538
+    // Attach document and window events
539
+
540
+    this._attachEvents = function ()
541
+    {
542
+      // Cancel countdown on mouseenter if delayOnHover
543
+      this.options.delayOnHover && jQuery('#' + this.id).on('mouseenter', function (ev) { this.isHovered = true; }.bind(this));
544
+
545
+      // Resume countdown on mouseleave if delayOnHover
546
+      this.options.delayOnHover && jQuery('#' + this.id).on('mouseleave', function (ev) { this.isHovered = false; }.bind(this));
547
+
548
+      // Positioning events
549
+      if ((this.options.adjustPosition || this.options.reposition) && !this.fixed && this.outside) {
550
+
551
+        // Trigger position events when scrolling
552
+        this.options.adjustTracker && jQuery(window).on('scroll.jBox-' + this.id, function (ev) { this.position(); }.bind(this));
553
+
554
+        // Trigger position events when resizing
555
+        (this.options.adjustPosition || this.options.reposition) && jQuery(window).on('resize.jBox-' + this.id, function (ev) { this.position(); }.bind(this));
556
+      }
557
+
558
+      // Mousemove events
559
+      this.options.target == 'mouse' && jQuery('body').on('mousemove.jBox-' + this.id, function (ev) { this.position({mouseTarget: {top: ev.pageY, left: ev.pageX}}); }.bind(this));
560
+    };
561
+
562
+
563
+    // Detach document and window events
564
+
565
+    this._detachEvents = function ()
566
+    {
567
+      // Closing event: closeOnEsc
568
+      this.options.closeOnEsc && jQuery(document).off('keyup.jBox-' + this.id);
569
+
570
+      // Closing event: closeOnClick
571
+      (this.options.closeOnClick === true || this.options.closeOnClick == 'body') && jQuery(document).off('click.jBox-' + this.id + ' tap.jBox-' + this.id);
572
+
573
+      // Positioning events
574
+      this.options.adjustTracker && jQuery(window).off('scroll.jBox-' + this.id);
575
+      (this.options.adjustPosition || this.options.reposition) && jQuery(window).off('resize.jBox-' + this.id);
576
+
577
+      // Mousemove events
578
+      this.options.target == 'mouse' && jQuery('body').off('mousemove.jBox-' + this.id);
579
+    };
580
+
581
+
582
+    // Show overlay
583
+
584
+    this._showOverlay = function ()
585
+    {
586
+      // Create the overlay if wasn't created already
587
+      if (!this.overlay) {
588
+
589
+        // Create element and append to the element where jBox is appended to
590
+        this.overlay = jQuery('<div id="' + this.id + '-overlay"/>').addClass('jBox-overlay' + (this.type ? ' jBox-overlay-' + this.type : '')).css({
591
+          display: 'none',
592
+          opacity: 0,
593
+          zIndex: this.options.zIndex - 1
594
+        }).appendTo(this.options.appendTo);
595
+
596
+        // Add a class name to the overlay
597
+        this.options.overlayClass && this.overlay.addClass(this.options.overlayClass);
598
+
599
+        // Add close button to overlay
600
+        (this.options.closeButton == 'overlay' || this.options.closeButton === true) && this.overlay.append(this.closeButton);
601
+
602
+        // Add closeOnClick: 'overlay' events
603
+        this.options.closeOnClick == 'overlay' && this.overlay.on('click tap', function () { this.close({ignoreDelay: true}); }.bind(this));
604
+
605
+        // Adjust option adjustDistance if there is a close button in the overlay
606
+        jQuery('#' + this.id + '-overlay .jBox-closeButton').length && (this.options.adjustDistance.top = Math.max(jQuery('#' + this.id + '-overlay .jBox-closeButton').outerHeight(), this.options.adjustDistance.top));
607
+      }
608
+
609
+      // Adjust zIndex
610
+      if (this.adjustZIndexOnOpen === true) {
611
+        this.overlay.css('zIndex', parseInt(this.wrapper.css('zIndex'), 10) - 1);
612
+      }
613
+
614
+      // Abort if overlay is already visible
615
+      if (this.overlay.css('display') == 'block') return;
616
+
617
+      // Show overlay
618
+      this.options.fade ? (this.overlay.stop() && this.overlay.animate({opacity: 1}, {
619
+        queue: false,
620
+        duration: this.options.fade,
621
+        start: function () { this.overlay.css({display: 'block'}); }.bind(this)
622
+      })) : this.overlay.css({display: 'block', opacity: 1});
623
+    };
624
+
625
+
626
+    // Hide overlay
627
+
628
+    this._hideOverlay = function ()
629
+    {
630
+      // Abort if the overlay wasn't created yet
631
+      if (!this.overlay) return;
632
+
633
+      // Hide overlay if no other jBox needs it
634
+      this.options.fade ? (this.overlay.stop() && this.overlay.animate({opacity: 0}, {
635
+        queue: false,
636
+        duration: this.options.fade,
637
+        complete: function () { this.overlay.css({display: 'none'}); }.bind(this)
638
+      })) : this.overlay.css({display: 'none', opacity: 0});
639
+    };
640
+
641
+
642
+    // Get the correct jBox dimensions by moving jBox out of viewport
643
+
644
+    this._exposeDimensions = function ()
645
+    {
646
+      // Move wrapper out of viewport
647
+      this.wrapper.css({
648
+        top: -10000,
649
+        left: -10000,
650
+        right: 'auto',
651
+        bottom: 'auto'
652
+      });
653
+
654
+      // Get jBox dimensions
655
+      var jBoxDimensions = {
656
+        x: this.wrapper.outerWidth(),
657
+        y: this.wrapper.outerHeight()
658
+      };
659
+
660
+      // Reset position to viewport
661
+      this.wrapper.css({
662
+        top: 'auto',
663
+        left: 'auto'
664
+      });
665
+
666
+      return jBoxDimensions;
667
+    };
668
+
669
+
670
+    // Generate CSS for animations and append to header
671
+
672
+    this._generateAnimationCSS = function ()
673
+    {
674
+      // Get open and close animations if none provided
675
+      (jQuery.type(this.options.animation) != 'object') && (this.options.animation = {
676
+        pulse: {open: 'pulse', close: 'zoomOut'},
677
+        zoomIn: {open: 'zoomIn', close: 'zoomIn'},
678
+        zoomOut: {open: 'zoomOut', close: 'zoomOut'},
679
+        move: {open: 'move', close: 'move'},
680
+        slide: {open: 'slide', close: 'slide'},
681
+        flip: {open: 'flip', close: 'flip'},
682
+        tada: {open: 'tada', close: 'zoomOut'}
683
+      }[this.options.animation]);
684
+
685
+      // Abort if animation not found
686
+      if (!this.options.animation) return null;
687
+
688
+      // Get direction var
689
+      this.options.animation.open && (this.options.animation.open = this.options.animation.open.split(':'));
690
+      this.options.animation.close && (this.options.animation.close = this.options.animation.close.split(':'));
691
+      this.options.animation.openDirection = this.options.animation.open[1] ? this.options.animation.open[1] : null;
692
+      this.options.animation.closeDirection = this.options.animation.close[1] ? this.options.animation.close[1] : null;
693
+      this.options.animation.open && (this.options.animation.open = this.options.animation.open[0]);
694
+      this.options.animation.close && (this.options.animation.close = this.options.animation.close[0]);
695
+
696
+      // Add 'Open' and 'Close' to animation names
697
+      this.options.animation.open && (this.options.animation.open += 'Open');
698
+      this.options.animation.close && (this.options.animation.close += 'Close');
699
+
700
+      // All animations
701
+      var animations = {
702
+        pulse: {
703
+          duration: 350,
704
+          css: [['0%', 'scale(1)'], ['50%', 'scale(1.1)'], ['100%', 'scale(1)']]
705
+        },
706
+        zoomInOpen: {
707
+          duration: (this.options.fade || 180),
708
+          css: [['0%', 'scale(0.9)'], ['100%', 'scale(1)']]
709
+        },
710
+        zoomInClose: {
711
+          duration: (this.options.fade || 180),
712
+          css: [['0%', 'scale(1)'], ['100%', 'scale(0.9)']]
713
+        },
714
+        zoomOutOpen: {
715
+          duration: (this.options.fade || 180),
716
+          css: [['0%', 'scale(1.1)'], ['100%', 'scale(1)']]
717
+        },
718
+        zoomOutClose: {
719
+          duration: (this.options.fade || 180),
720
+          css: [['0%', 'scale(1)'], ['100%', 'scale(1.1)']]
721
+        },
722
+        moveOpen: {
723
+          duration: (this.options.fade || 180),
724
+          positions: {top: {'0%': -12}, right: {'0%': 12}, bottom: {'0%': 12}, left: {'0%': -12}},
725
+          css: [['0%', 'translate%XY(%Vpx)'], ['100%', 'translate%XY(0px)']]
726
+        },
727
+        moveClose: {
728
+          duration: (this.options.fade || 180),
729
+          timing: 'ease-in',
730
+          positions: {top: {'100%': -12}, right: {'100%': 12}, bottom: {'100%': 12}, left: {'100%': -12}},
731
+          css: [['0%', 'translate%XY(0px)'], ['100%', 'translate%XY(%Vpx)']]
732
+        },
733
+        slideOpen: {
734
+          duration: 400,
735
+          positions: {top: {'0%': -400}, right: {'0%': 400}, bottom: {'0%': 400}, left: {'0%': -400}},
736
+          css: [['0%', 'translate%XY(%Vpx)'], ['100%', 'translate%XY(0px)']]
737
+        },
738
+        slideClose: {
739
+          duration: 400,
740
+          timing: 'ease-in',
741
+          positions: {top: {'100%': -400}, right: {'100%': 400}, bottom: {'100%': 400}, left: {'100%': -400}},
742
+          css: [['0%', 'translate%XY(0px)'], ['100%', 'translate%XY(%Vpx)']]
743
+        },
744
+        flipOpen: {
745
+          duration: 600,
746
+          css: [['0%', 'perspective(400px) rotateX(90deg)'], ['40%', 'perspective(400px) rotateX(-15deg)'], ['70%', 'perspective(400px) rotateX(15deg)'], ['100%', 'perspective(400px) rotateX(0deg)']]
747
+        },
748
+        flipClose: {
749
+          duration: (this.options.fade || 300),
750
+          css: [['0%', 'perspective(400px) rotateX(0deg)'], ['100%', 'perspective(400px) rotateX(90deg)']]
751
+        },
752
+        tada: {
753
+          duration: 800,
754
+          css: [['0%', 'scale(1)'], ['10%, 20%', 'scale(0.9) rotate(-3deg)'], ['30%, 50%, 70%, 90%', 'scale(1.1) rotate(3deg)'], ['40%, 60%, 80%', 'scale(1.1) rotate(-3deg)'], ['100%', 'scale(1) rotate(0)']]
755
+        }
756
+      };
757
+
758
+      // Set Open and Close names for standalone animations
759
+      jQuery.each(['pulse', 'tada'], function (index, item) { animations[item + 'Open'] = animations[item + 'Close'] = animations[item]; });
760
+
761
+      // Function to generate the CSS for the keyframes
762
+      var generateKeyframeCSS = function (ev, position)
763
+      {
764
+        // Generate keyframes CSS
765
+        var keyframe_css = '@keyframes jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + (position ? '-' + position : '') + ' {';
766
+        jQuery.each(animations[this.options.animation[ev]].css, function (index, item) {
767
+          var translate = position ? item[1].replace('%XY', this._getXY(position).toUpperCase()) : item[1];
768
+          animations[this.options.animation[ev]].positions && (translate = translate.replace('%V', animations[this.options.animation[ev]].positions[position][item[0]]));
769
+          keyframe_css += item[0] + ' {transform:' + translate + ';}';
770
+        }.bind(this));
771
+        keyframe_css += '}';
772
+
773
+        // Generate class CSS
774
+        keyframe_css += '.jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + (position ? '-' + position : '') + ' {';
775
+        keyframe_css += 'animation-duration: ' + animations[this.options.animation[ev]].duration + 'ms;';
776
+        keyframe_css += 'animation-name: jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + (position ? '-' + position : '') + ';';
777
+        keyframe_css += animations[this.options.animation[ev]].timing ? ('animation-timing-function: ' + animations[this.options.animation[ev]].timing + ';') : '';
778
+        keyframe_css += '}';
779
+
780
+        return keyframe_css;
781
+      }.bind(this);
782
+
783
+      // Generate css for each event and positions
784
+      this._animationCSS = '';
785
+      jQuery.each(['open', 'close'], function (index, ev)
786
+      {
787
+        // No CSS needed for closing with no fade
788
+        if (!this.options.animation[ev] || !animations[this.options.animation[ev]] || (ev == 'close' && !this.options.fade)) return '';
789
+
790
+        // Generate CSS
791
+        animations[this.options.animation[ev]].positions ?
792
+          jQuery.each(['top', 'right', 'bottom', 'left'], function (index2, position) { this._animationCSS += generateKeyframeCSS(ev, position); }.bind(this)) :
793
+          this._animationCSS += generateKeyframeCSS(ev);
794
+      }.bind(this));
795
+
796
+    };
797
+
798
+
799
+    // Add css for animations
800
+
801
+    this.options.animation && this._generateAnimationCSS();
802
+
803
+
804
+    // Block body clicks for 10ms to prevent extra event triggering
805
+
806
+    this._blockBodyClick = function ()
807
+    {
808
+      this.blockBodyClick = true;
809
+      setTimeout(function () { this.blockBodyClick = false; }.bind(this), 10);
810
+    };
811
+
812
+
813
+    // Animations
814
+
815
+    this._animate = function (ev)
816
+    {
817
+      // The event which triggers the animation
818
+      !ev && (ev = this.isOpen ? 'open' : 'close');
819
+
820
+      // Don't animate when closing with no fade duration
821
+      if (!this.options.fade && ev == 'close') return null;
822
+
823
+      // Get the current position, use opposite if jBox is flipped
824
+      var animationDirection = (this.options.animation[ev + 'Direction'] || ((this.align != 'center') ? this.align : this.options.attributes.x));
825
+      this.flipped && this._getXY(animationDirection) == (this._getXY(this.align)) && (animationDirection = this._getOpp(animationDirection));
826
+
827
+      // Add event and position classes
828
+      var classnames = 'jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + ' jBox-' + this.id + '-animation-' + this.options.animation[ev] + '-' + ev + '-' + animationDirection;
829
+      this.wrapper.addClass(classnames);
830
+
831
+      // Get duration of animation
832
+      var animationDuration = parseFloat(this.wrapper.css('animation-duration')) * 1000;
833
+      ev == 'close' && (animationDuration = Math.min(animationDuration, this.options.fade));
834
+
835
+      // Remove animation classes when animation is finished
836
+      setTimeout(function () { this.wrapper.removeClass(classnames); }.bind(this), animationDuration);
837
+    };
838
+
839
+
840
+    // Abort an animation
841
+
842
+    this._abortAnimation = function ()
843
+    {
844
+      // Remove all animation classes
845
+      var classes = this.wrapper.attr('class').split(' ').filter(function (c) {
846
+        return c.lastIndexOf('jBox-' + this.id + '-animation', 0) !== 0;
847
+      }.bind(this));
848
+      this.wrapper.attr('class', classes.join(' '));
849
+    };
850
+
851
+
852
+    // Adjust dimensions when browser is resized
853
+
854
+    if (this.options.responsiveWidth || this.options.responsiveHeight)
855
+    {
856
+      // Responsive positioning overrides options adjustPosition and reposition
857
+      // TODO: Only add this resize event when the other one from adjustPosition and reposition was not set
858
+      jQuery(window).on('resize.responsivejBox-' + this.id, function (ev) { if (this.isOpen) { this.position(); } }.bind(this));
859
+    }
860
+
861
+
862
+    // Fix audio options
863
+
864
+    jQuery.type(this.options.preloadAudio) === 'string' && (this.options.preloadAudio = [this.options.preloadAudio]);
865
+    jQuery.type(this.options.audio) === 'string' && (this.options.audio = {open: this.options.audio});
866
+    jQuery.type(this.options.volume) === 'number' && (this.options.volume = {open: this.options.volume, close: this.options.volume});
867
+
868
+    if (this.options.preloadAudio === true && this.options.audio) {
869
+      this.options.preloadAudio = [];
870
+      jQuery.each(this.options.audio, function (index, url) {
871
+        this.options.preloadAudio.push(url + '.mp3');
872
+        this.options.preloadAudio.push(url + '.ogg');
873
+      }.bind(this));
874
+    }
875
+
876
+
877
+    // Preload audio files
878
+
879
+    this.options.preloadAudio.length && jQuery.each(this.options.preloadAudio, function (index, url) {
880
+      var audio = new Audio();
881
+      audio.src = url;
882
+      audio.preload = 'auto';
883
+    });
884
+
885
+
886
+    // Fire onInit event
887
+
888
+    this._fireEvent('onInit');
889
+
890
+
891
+    return this;
892
+  };
893
+
894
+
895
+  // Attach jBox to elements
896
+
897
+  jBox.prototype.attach = function (elements, trigger)
898
+  {
899
+    // Get elements from options if none passed
900
+    !elements && (elements = this.options.attach);
901
+
902
+    // Convert selectors to jQuery objects
903
+    jQuery.type(elements) == 'string' && (elements = jQuery(elements));
904
+
905
+    // Get trigger event from options if not passed
906
+    !trigger && (trigger = this.options.trigger);
907
+
908
+    // Loop through elements and attach jBox
909
+    elements && elements.length && jQuery.each(elements, function (index, el) {
910
+      el = jQuery(el);
911
+
912
+      // Only attach if the element wasn't attached to this jBox already
913
+      if (!el.data('jBox-attached-' + this.id)) {
914
+
915
+        // Remove title attribute and store content on element
916
+        (this.options.getContent == 'title' && el.attr('title') != undefined) && el.data('jBox-getContent', el.attr('title')).removeAttr('title');
917
+
918
+        // Add Element to collection
919
+        this.attachedElements || (this.attachedElements = []);
920
+        this.attachedElements.push(el[0]);
921
+
922
+        // Add click or mouseenter event, click events can prevent default as well
923
+        el.on(trigger + '.jBox-attach-' + this.id, function (ev)
924
+        {
925
+          // Clear timer
926
+          this.timer && clearTimeout(this.timer);
927
+
928
+          // Block opening when jbox is open and the source element is triggering
929
+          if (trigger == 'mouseenter' && this.isOpen && this.source[0] == el[0]) return;
930
+
931
+          // Only close jBox if you click the current target element, otherwise open at new target
932
+          if (this.isOpen && this.source && this.source[0] != el[0]) var forceOpen = true;
933
+
934
+          // Set new source element
935
+          this.source = el;
936
+
937
+          // Set new target
938
+          !this.options.target && (this.target = el);
939
+
940
+          // Prevent default action on click
941
+          trigger == 'click' && this.options.preventDefault && ev.preventDefault();
942
+
943
+          // Toggle or open jBox
944
+          this[trigger == 'click' && !forceOpen ? 'toggle' : 'open']();
945
+
946
+        }.bind(this));
947
+
948
+        // Add close event for trigger event mouseenter
949
+        (this.options.trigger == 'mouseenter') && el.on('mouseleave', function (ev)
950
+        {
951
+          // Abort if jBox wasn't created yet
952
+          if (!this.wrapper) return null;
953
+
954
+          // If we have set closeOnMouseleave, do not close jBox when leaving attached element and mouse is over jBox
955
+          if (!this.options.closeOnMouseleave || !(ev.relatedTarget == this.wrapper[0] || jQuery(ev.relatedTarget).parents('#' + this.id).length)) this.close();
956
+        }.bind(this));
957
+
958
+        // Store
959
+        el.data('jBox-attached-' + this.id, trigger);
960
+
961
+        // Fire onAttach event
962
+        this._fireEvent('onAttach', el);
963
+      }
964
+
965
+    }.bind(this));
966
+
967
+    return this;
968
+  };
969
+
970
+
971
+  // Detach jBox from elements
972
+
973
+  jBox.prototype.detach = function (elements)
974
+  {
975
+    // Get elements from stores elements if none passed
976
+    !elements && (elements = this.attachedElements || []);
977
+
978
+    elements && elements.length && jQuery.each(elements, function (index, el) {
979
+      el = jQuery(el);
980
+
981
+      // Remove events
982
+      if (el.data('jBox-attached-' + this.id)) {
983
+        el.off(el.data('jBox-attached-' + this.id) + '.jBox-attach-' + this.id);
984
+        el.data('jBox-attached-' + this.id, null);
985
+      }
986
+      // Remove element from collection
987
+      this.attachedElements = jQuery.grep(this.attachedElements, function (value) {
988
+        return value != el[0];
989
+      });
990
+    }.bind(this));
991
+
992
+    return this;
993
+  };
994
+
995
+
996
+  // Set title
997
+
998
+  jBox.prototype.setTitle = function (title, ignore_positioning)
999
+  {
1000
+    // Abort if title to set
1001
+    if (title == null || title == undefined) return this;
1002
+
1003
+    // Create jBox if it wasn't created already
1004
+    !this.wrapper && this._create();
1005
+
1006
+    // Get the width and height of wrapper, only if they change we need to reposition
1007
+    var wrapperHeight = this.wrapper.outerHeight();
1008
+    var wrapperWidth = this.wrapper.outerWidth();
1009
+
1010
+    // Create title elements if they weren't created already
1011
+    if (!this.title) {
1012
+      this.titleContainer = jQuery('<div class="jBox-title"/>');
1013
+      this.title = jQuery('<div/>').appendTo(this.titleContainer);
1014
+      if (this.options.closeButton == 'title' || (this.options.closeButton === true && !this.options.overlay)) {
1015
+        this.wrapper.addClass('jBox-closeButton-title');
1016
+        this.closeButton.appendTo(this.titleContainer);
1017
+      }
1018
+      this.titleContainer.insertBefore(this.content);
1019
+      this._setTitleWidth();
1020
+    }
1021
+
1022
+    // Add or remove wrapper class
1023
+    this.wrapper[title ? 'addClass' : 'removeClass']('jBox-hasTitle');
1024
+
1025
+    // Set title html
1026
+    this.title.html(title);
1027
+
1028
+    // Adjust width of title
1029
+    wrapperWidth != this.wrapper.outerWidth() && this._setTitleWidth();
1030
+
1031
+    // Make jBox draggable
1032
+    this.options.draggable && this._draggable();
1033
+
1034
+    // Reposition if dimensions changed
1035
+    !ignore_positioning && this.options.repositionOnContent && (wrapperHeight != this.wrapper.outerHeight() || wrapperWidth != this.wrapper.outerWidth()) && this.position();
1036
+
1037
+    return this;
1038
+  };
1039
+
1040
+
1041
+  // Set content
1042
+
1043
+  jBox.prototype.setContent = function (content, ignore_positioning)
1044
+  {
1045
+    // Abort if no content to set
1046
+    if (content == null || content == undefined) return this;
1047
+
1048
+    // Create jBox if it wasn't created already
1049
+    !this.wrapper && this._create();
1050
+
1051
+    // Get the width and height of wrapper, only if they change we need to reposition
1052
+    var wrapperHeight = this.wrapper.outerHeight();
1053
+    var wrapperWidth = this.wrapper.outerWidth();
1054
+
1055
+    // Move all appended containers to body
1056
+    this.content.children('[data-jbox-content-appended]').appendTo('body').css({display: 'none'});
1057
+
1058
+    // Set the new content
1059
+    switch (jQuery.type(content)) {
1060
+      case 'string':
1061
+        this.content.html(content);
1062
+        break;
1063
+      case 'object':
1064
+        if (content && (content instanceof jQuery || content.constructor.prototype.jquery)) {
1065
+          this.content.html('');
1066
+          content.attr('data-jbox-content-appended', 1).appendTo(this.content).css({display: 'block'});
1067
+        } else {
1068
+          this.content.html(JSON.stringify(content));
1069
+        }
1070
+        break;
1071
+     }
1072
+
1073
+    // Adjust title width
1074
+    wrapperWidth != this.wrapper.outerWidth() && this._setTitleWidth();
1075
+
1076
+    // Make jBox draggable
1077
+    this.options.draggable && this._draggable();
1078
+
1079
+    // Reposition if dimensions changed
1080
+    !ignore_positioning && this.options.repositionOnContent && (wrapperHeight != this.wrapper.outerHeight() || wrapperWidth != this.wrapper.outerWidth()) && this.position();
1081
+
1082
+    return this;
1083
+  };
1084
+
1085
+
1086
+  // Set jBox dimensions
1087
+
1088
+  jBox.prototype.setDimensions = function (type, value, pos)
1089
+  {
1090
+    // Create jBox if it wasn't created already
1091
+    !this.wrapper && this._create();
1092
+
1093
+    // Default value is 'auto'
1094
+    value == undefined && (value = 'auto');
1095
+
1096
+    // Set CSS of content and title
1097
+    this.content.css(type, this._getInt(value));
1098
+
1099
+    // Adjust title width
1100
+    type == 'width' && this._setTitleWidth();
1101
+
1102
+    // Update options
1103
+    this.options[type] = value;
1104
+
1105
+    // Reposition by default
1106
+    (pos == undefined || pos) && this.position();
1107
+  };
1108
+
1109
+
1110
+  // Set jBox width or height
1111
+
1112
+  jBox.prototype.setWidth = function (value, pos) { this.setDimensions('width', value, pos); };
1113
+  jBox.prototype.setHeight = function (value, pos) { this.setDimensions('height', value, pos); };
1114
+
1115
+
1116
+  // Position jBox
1117
+
1118
+  jBox.prototype.position = function (options)
1119
+  {
1120
+    // Options are required
1121
+    !options && (options = {});
1122
+
1123
+    // Combine passed options with jBox options
1124
+    options = jQuery.extend(true, this.options, options);
1125
+
1126
+    // Get the target
1127
+    this.target = options.target || this.target || jQuery(window);
1128
+
1129
+    // Make sure target is a jQuery element
1130
+    !(this.target instanceof jQuery || this.target == 'mouse') && (this.target = jQuery(this.target));
1131
+
1132
+    // Abort if target is missing
1133
+    if (!this.target.length) return this;
1134
+
1135
+    // Reset content css to get original dimensions
1136
+    this.content.css({
1137
+      width: this._getInt(options.width, 'width'),
1138
+      height: this._getInt(options.height, 'height'),
1139
+      minWidth: this._getInt(options.minWidth, 'width'),
1140
+      minHeight: this._getInt(options.minHeight, 'height'),
1141
+      maxWidth: this._getInt(options.maxWidth, 'width'),
1142
+      maxHeight: this._getInt(options.maxHeight, 'height'),
1143
+    });
1144
+
1145
+    // Reset width of title
1146
+    this._setTitleWidth();
1147
+
1148
+    // Get jBox dimensions
1149
+    var jBoxDimensions = this._exposeDimensions();
1150
+
1151
+    // Check if target has fixed position, store in elements data
1152
+    this.target != 'mouse' && !this.target.data('jBox-' + this.id + '-fixed') && this.target.data('jBox-' + this.id + '-fixed', (this.target[0] != jQuery(window)[0] && (this.target.css('position') == 'fixed' || this.target.parents().filter(function () { return jQuery(this).css('position') == 'fixed'; }).length > 0)) ? 'fixed' : 'static');
1153
+
1154
+    // Get the window dimensions
1155
+    var windowDimensions = {
1156
+      x: jQuery(window).outerWidth(),
1157
+      y: jQuery(window).outerHeight(),
1158
+      top: (options.fixed && this.target.data('jBox-' + this.id + '-fixed') ? 0 : jQuery(window).scrollTop()),
1159
+      left: (options.fixed && this.target.data('jBox-' + this.id + '-fixed') ? 0 : jQuery(window).scrollLeft())
1160
+    };
1161
+    windowDimensions.bottom = windowDimensions.top + windowDimensions.y;
1162
+    windowDimensions.right = windowDimensions.left + windowDimensions.x;
1163
+
1164
+    // Get target offset
1165
+    try { var targetOffset = this.target.offset(); } catch (e) { var targetOffset = {top: 0, left: 0}; };
1166
+
1167
+    // When the target is fixed and jBox is fixed, remove scroll offset
1168
+    if (this.target != 'mouse' && this.target.data('jBox-' + this.id + '-fixed') == 'fixed' && options.fixed) {
1169
+      targetOffset.top = targetOffset.top - jQuery(window).scrollTop();
1170
+      targetOffset.left = targetOffset.left - jQuery(window).scrollLeft();
1171
+    }
1172
+
1173
+    // Get target dimensions
1174
+    var targetDimensions = {
1175
+      x: this.target == 'mouse' ? 12 : this.target.outerWidth(),
1176
+      y: this.target == 'mouse' ? 20 : this.target.outerHeight(),
1177
+      top: this.target == 'mouse' && options.mouseTarget ? options.mouseTarget.top : (targetOffset ? targetOffset.top : 0),
1178
+      left: this.target == 'mouse' && options.mouseTarget ? options.mouseTarget.left : (targetOffset ? targetOffset.left : 0)
1179
+    };
1180
+
1181
+    // Check if jBox is outside
1182
+    var outside = options.outside && !(options.position.x == 'center' && options.position.y == 'center');
1183
+
1184
+    // Get the available space on all sides
1185
+    var availableSpace = {
1186
+      x: windowDimensions.x - options.adjustDistance.left - options.adjustDistance.right, // TODO: substract position.x when they are numbers
1187
+      y: windowDimensions.y - options.adjustDistance.top - options.adjustDistance.bottom, // TODO: substract position.x when they are numbers
1188
+      left: !outside ? 0 : (targetDimensions.left - jQuery(window).scrollLeft() - options.adjustDistance.left),
1189
+      right: !outside ? 0 : (windowDimensions.x - targetDimensions.left + jQuery(window).scrollLeft() - targetDimensions.x - options.adjustDistance.right),
1190
+      top: !outside ? 0 : (targetDimensions.top - jQuery(window).scrollTop() - this.options.adjustDistance.top),
1191
+      bottom: !outside ? 0 : (windowDimensions.y - targetDimensions.top + jQuery(window).scrollTop() - targetDimensions.y - options.adjustDistance.bottom),
1192
+    };
1193
+
1194
+    // Get the default outside position, check if box will be flipped
1195
+    var jBoxOutsidePosition = {
1196
+      x: (options.outside == 'x' || options.outside == 'xy') && jQuery.type(options.position.x) != 'number' ? options.position.x : null,
1197
+      y: (options.outside == 'y' || options.outside == 'xy') && jQuery.type(options.position.y) != 'number' ? options.position.y : null
1198
+    };
1199
+    var flip = {x: false, y: false};
1200
+    (jBoxOutsidePosition.x && jBoxDimensions.x > availableSpace[jBoxOutsidePosition.x] && availableSpace[this._getOpp(jBoxOutsidePosition.x)] > availableSpace[jBoxOutsidePosition.x]) && (jBoxOutsidePosition.x = this._getOpp(jBoxOutsidePosition.x)) && (flip.x = true);
1201
+    (jBoxOutsidePosition.y && jBoxDimensions.y > availableSpace[jBoxOutsidePosition.y] && availableSpace[this._getOpp(jBoxOutsidePosition.y)] > availableSpace[jBoxOutsidePosition.y]) && (jBoxOutsidePosition.y = this._getOpp(jBoxOutsidePosition.y)) && (flip.y = true);
1202
+
1203
+    // Adjust responsive dimensions
1204
+    if (options.responsiveWidth || options.responsiveHeight) {
1205
+
1206
+      // Adjust width and height according to default outside position
1207
+      var adjustResponsiveWidth = function ()
1208
+      {
1209
+        if (options.responsiveWidth && jBoxDimensions.x > availableSpace[jBoxOutsidePosition.x || 'x']) {
1210
+          var contentWidth = availableSpace[jBoxOutsidePosition.x || 'x'] - (this.pointer && outside && options.outside == 'x' ? this.pointer.dimensions.x : 0) - parseInt(this.container.css('border-left-width')) - parseInt(this.container.css('border-right-width'));
1211
+          this.content.css({
1212
+            width: contentWidth > this.options.responsiveMinWidth ? contentWidth : null,
1213
+            minWidth: contentWidth < parseInt(this.content.css('minWidth')) ? 0 : null
1214
+          });
1215
+          this._setTitleWidth();
1216
+        }
1217
+        jBoxDimensions = this._exposeDimensions();
1218
+
1219
+      }.bind(this);
1220
+      options.responsiveWidth && adjustResponsiveWidth();
1221
+
1222
+      // After adjusting width, check if jBox will be flipped for y
1223
+      options.responsiveWidth && !flip.y && (jBoxOutsidePosition.y && jBoxDimensions.y > availableSpace[jBoxOutsidePosition.y] && availableSpace[this._getOpp(jBoxOutsidePosition.y)] > availableSpace[jBoxOutsidePosition.y]) && (jBoxOutsidePosition.y = this._getOpp(jBoxOutsidePosition.y)) && (flip.y = true);
1224
+
1225
+      // Adjust width and height according to default outside position
1226
+      var adjustResponsiveHeight = function ()
1227
+      {
1228
+        if (options.responsiveHeight && jBoxDimensions.y > availableSpace[jBoxOutsidePosition.y || 'y']) {
1229
+
1230
+          // Expose wrapper to get correct title height
1231
+          var exposeTitleFooterHeight = function () {
1232
+            if (!this.titleContainer && !this.footer) return 0;
1233
+            if (this.wrapper.css('display') == 'none') {
1234
+              this.wrapper.css('display', 'block');
1235
+              var height = (this.titleContainer ? this.titleContainer.outerHeight() : 0) + (this.footer ? this.footer.outerHeight() : 0);
1236
+              this.wrapper.css('display', 'none');
1237
+            } else {
1238
+              var height = (this.titleContainer ? this.titleContainer.outerHeight() : 0) + (this.footer ? this.footer.outerHeight() : 0);
1239
+            }
1240
+            return height || 0;
1241
+          }.bind(this);
1242
+
1243
+          var contentHeight = availableSpace[jBoxOutsidePosition.y || 'y'] - (this.pointer && outside && options.outside == 'y' ? this.pointer.dimensions.y : 0) - exposeTitleFooterHeight() - parseInt(this.container.css('border-top-width')) - parseInt(this.container.css('border-bottom-width'));
1244
+          this.content.css({height: contentHeight > this.options.responsiveMinHeight ? contentHeight : null});
1245
+          this._setTitleWidth();
1246
+        }
1247
+        jBoxDimensions = this._exposeDimensions();
1248
+
1249
+      }.bind(this);
1250
+      options.responsiveHeight && adjustResponsiveHeight();
1251
+
1252
+      // After adjusting height, check if jBox will be flipped for x
1253
+      options.responsiveHeight && !flip.x && (jBoxOutsidePosition.x && jBoxDimensions.x > availableSpace[jBoxOutsidePosition.x] && availableSpace[this._getOpp(jBoxOutsidePosition.x)] > availableSpace[jBoxOutsidePosition.x]) && (jBoxOutsidePosition.x = this._getOpp(jBoxOutsidePosition.x)) && (flip.x = true);
1254
+
1255
+      // Adjust width and height if jBox will be flipped
1256
+      if (options.adjustPosition && options.adjustPosition != 'move') {
1257
+        flip.x && adjustResponsiveWidth();
1258
+        flip.y && adjustResponsiveHeight();
1259
+      }
1260
+    }
1261
+
1262
+    // Store new positioning vars in local var
1263
+    var pos = {};
1264
+
1265
+    // Calculate positions
1266
+    var setPosition = function (p)
1267
+    {
1268
+      // Set number positions
1269
+      if (jQuery.type(options.position[p]) == 'number') {
1270
+        pos[options.attributes[p]] = options.position[p];
1271
+        return;
1272
+      }
1273
+
1274
+      // We have a target, so use 'left' or 'top' as attributes
1275
+      var a = options.attributes[p] = (p == 'x' ? 'left' : 'top');
1276
+
1277
+      // Start at target position
1278
+      pos[a] = targetDimensions[a];
1279
+
1280
+      // Set centered position
1281
+      if (options.position[p] == 'center') {
1282
+        pos[a] += Math.ceil((targetDimensions[p] - jBoxDimensions[p]) / 2);
1283
+
1284
+        // If the target is the window, adjust centered position depending on adjustDistance
1285
+        (this.target != 'mouse' && this.target[0] && this.target[0] == jQuery(window)[0]) && (pos[a] += (options.adjustDistance[a] - options.adjustDistance[this._getOpp(a)]) * 0.5);
1286
+        return;
1287
+      }
1288
+
1289
+      // Move inside
1290
+      (a != options.position[p]) && (pos[a] += targetDimensions[p] - jBoxDimensions[p]);
1291
+
1292
+      // Move outside
1293
+      (options.outside == p || options.outside == 'xy') && (pos[a] += jBoxDimensions[p] * (a != options.position[p] ? 1 : -1));
1294
+
1295
+    }.bind(this);
1296
+
1297
+    // Set position including offset
1298
+    setPosition('x');
1299
+    setPosition('y');
1300
+
1301
+    // Adjust position depending on pointer align
1302
+    if (this.pointer && options.pointTo == 'target' && jQuery.type(options.position.x) != 'number' && jQuery.type(options.position.y) != 'number') {
1303
+
1304
+      var adjustWrapper = 0;
1305
+
1306
+      // Where is the pointer aligned? Add or substract accordingly
1307
+      switch (this.pointer.align) {
1308
+        case 'center':
1309
+        if (options.position[this._getOpp(options.outside)] != 'center') {
1310
+          adjustWrapper += (jBoxDimensions[this._getOpp(options.outside)] / 2);
1311
+        }
1312
+        break;
1313
+        default:
1314
+        switch (options.position[this._getOpp(options.outside)]) {
1315
+          case 'center':
1316
+            adjustWrapper += ((jBoxDimensions[this._getOpp(options.outside)] / 2) - (this.pointer.dimensions[this._getOpp(options.outside)] / 2)) * (this.pointer.align == this._getTL(this.pointer.align) ? 1 : -1);
1317
+          break;
1318
+          default:
1319
+            adjustWrapper += (this.pointer.align != options.position[this._getOpp(options.outside)]) ?
1320
+
1321
+            // If pointer align is different to position align
1322
+            (this.dimensions[this._getOpp(options.outside)] * (jQuery.inArray(this.pointer.align, ['top', 'left']) !== -1 ? 1 : -1)) + ((this.pointer.dimensions[this._getOpp(options.outside)] / 2) * (jQuery.inArray(this.pointer.align, ['top', 'left']) !== -1 ? -1 : 1)) :
1323
+
1324
+            // If pointer align is same as position align
1325
+            (this.pointer.dimensions[this._getOpp(options.outside)] / 2) * (jQuery.inArray(this.pointer.align, ['top', 'left']) !== -1 ? 1 : -1);
1326
+          break;
1327
+        }
1328
+        break;
1329
+      }
1330
+
1331
+      adjustWrapper *= (options.position[this._getOpp(options.outside)] == this.pointer.alignAttribute ? -1 : 1);
1332
+      adjustWrapper += this.pointer.offset * (this.pointer.align == this._getOpp(this._getTL(this.pointer.align)) ? 1 : -1);
1333
+
1334
+      pos[this._getTL(this._getOpp(this.pointer.xy))] += adjustWrapper;
1335
+    }
1336
+
1337
+    // Add final offset
1338
+    pos[options.attributes.x] += options.offset.x;
1339
+    pos[options.attributes.y] += options.offset.y;
1340
+
1341
+    // Set CSS
1342
+    this.wrapper.css(pos);
1343
+
1344
+    // Adjust position
1345
+    if (options.adjustPosition) {
1346
+
1347
+      // Reset cached pointer position
1348
+      if (this.positionAdjusted) {
1349
+        this.pointer && this.wrapper.css('padding', 0).css('padding-' + this._getOpp(this.outside), this.pointer.dimensions[this._getXY(this.outside)]).removeClass('jBox-pointerPosition-' + this._getOpp(this.pointer.position)).addClass('jBox-pointerPosition-' + this.pointer.position);
1350
+        this.pointer && this.pointer.element.attr('class', 'jBox-pointer jBox-pointer-' + this._getOpp(this.outside)).css(this.pointer.margin);
1351
+        this.positionAdjusted = false;
1352
+        this.flipped = false;
1353
+      }
1354
+
1355
+      // Find out where the jBox is out of view area
1356
+      var outYT = (windowDimensions.top > pos.top - (options.adjustDistance.top || 0)),
1357
+        outXR = (windowDimensions.right < pos.left + jBoxDimensions.x + (options.adjustDistance.right || 0)),
1358
+        outYB = (windowDimensions.bottom < pos.top + jBoxDimensions.y + (options.adjustDistance.bottom || 0)),
1359
+        outXL = (windowDimensions.left > pos.left - (options.adjustDistance.left || 0)),
1360
+        outX = outXL ? 'left' : (outXR ? 'right' : null),
1361
+        outY = outYT ? 'top' : (outYB ? 'bottom' : null),
1362
+        out = outX || outY;
1363
+
1364
+      // Only continue if jBox is out of view area
1365
+      if (out) {
1366
+
1367
+        if ((this.type == 'Modal' || this.type == 'Confirm')
1368
+          && jQuery.type(this.options.position.x) == 'number'
1369
+          && jQuery.type(this.options.position.y) == 'number'
1370
+        ) {
1371
+          var diffX = 0, diffY = 0;
1372
+          if (this.options.holdPosition) {
1373
+
1374
+            // Adjust left or right
1375
+            if (outXL) {
1376
+              diffX = windowDimensions.left - (pos.left - (options.adjustDistance.left || 0));
1377
+            } else if (outXR) {
1378
+              diffX = windowDimensions.right - (pos.left + jBoxDimensions.x + (options.adjustDistance.right || 0));
1379
+            }
1380
+
1381
+            // Adjust top or bottom
1382
+            if (outYT) {
1383
+              diffY = windowDimensions.top - (pos.top - (options.adjustDistance.top || 0));
1384
+            } else if (outYB) {
1385
+              diffY = windowDimensions.bottom - (pos.top + jBoxDimensions.y + (options.adjustDistance.bottom || 0));
1386
+            }
1387
+
1388
+            this.options.position.x = Math.max(windowDimensions.top, this.options.position.x + diffX);
1389
+            this.options.position.y = Math.max(windowDimensions.left, this.options.position.y + diffY);
1390
+
1391
+            setPosition('x');
1392
+            setPosition('y');
1393
+            this.wrapper.css(pos);
1394
+          }
1395
+          // Fire onPosition event
1396
+          this._fireEvent('onPosition');
1397
+
1398
+          return this;
1399
+        }
1400
+
1401
+        // Function to flip position
1402
+        if (options.adjustPosition === true || options.adjustPosition === 'flip') {
1403
+          var flipJBox = function (xy) {
1404
+            this.wrapper.css(this._getTL(xy), pos[this._getTL(xy)] + ((jBoxDimensions[this._getXY(xy)] + (options.offset[this._getXY(xy)] * (xy == 'top' || xy == 'left' ? -2 : 2)) + targetDimensions[this._getXY(xy)]) * (xy == 'top' || xy == 'left' ? 1 : -1)));
1405
+            this.pointer && this.wrapper.removeClass('jBox-pointerPosition-' + this.pointer.position).addClass('jBox-pointerPosition-' + this._getOpp(this.pointer.position)).css('padding', 0).css('padding-' + xy, this.pointer.dimensions[this._getXY(xy)]);
1406
+            this.pointer && this.pointer.element.attr('class', 'jBox-pointer jBox-pointer-' + xy);
1407
+            this.positionAdjusted = true;
1408
+            this.flipped = true;
1409
+          }.bind(this);
1410
+
1411
+          // Flip jBox
1412
+          flip.x && flipJBox(this.options.position.x);
1413
+          flip.y && flipJBox(this.options.position.y);
1414
+        }
1415
+
1416
+        // Move jBox (only possible with pointer)
1417
+        var outMove = (this._getXY(this.outside) == 'x') ? outY : outX;
1418
+
1419
+        if (this.pointer && options.pointTo == 'target' && options.adjustPosition != 'flip' && this._getXY(outMove) == this._getOpp(this._getXY(this.outside))) {
1420
+
1421
+          // Get the maximum space we have availible to adjust
1422
+          if (this.pointer.align == 'center') {
1423
+            var spaceAvail = (jBoxDimensions[this._getXY(outMove)] / 2) - (this.pointer.dimensions[this._getOpp(this.pointer.xy)] / 2) - (parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) * (outMove != this._getTL(outMove) ? -1 : 1));
1424
+          } else {
1425
+            var spaceAvail = (outMove == this.pointer.alignAttribute) ?
1426
+              parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) :
1427
+              jBoxDimensions[this._getXY(outMove)] - parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) - this.pointer.dimensions[this._getXY(outMove)];
1428
+          }
1429
+
1430
+          // Get the overlapping space
1431
+          var spaceDiff = (outMove == this._getTL(outMove)) ?
1432
+            windowDimensions[this._getTL(outMove)] - pos[this._getTL(outMove)] + options.adjustDistance[outMove] :
1433
+            (windowDimensions[this._getOpp(this._getTL(outMove))] - pos[this._getTL(outMove)] - options.adjustDistance[outMove] - jBoxDimensions[this._getXY(outMove)]) * -1;
1434
+
1435
+          // Add overlapping space on left or top window edge
1436
+          if (outMove == this._getOpp(this._getTL(outMove)) && pos[this._getTL(outMove)] - spaceDiff < windowDimensions[this._getTL(outMove)] + options.adjustDistance[this._getTL(outMove)]) {
1437
+            spaceDiff -= windowDimensions[this._getTL(outMove)] + options.adjustDistance[this._getTL(outMove)] - (pos[this._getTL(outMove)] - spaceDiff);
1438
+          }
1439
+
1440
+          // Only adjust the maximum availible
1441
+          spaceDiff = Math.min(spaceDiff, spaceAvail);
1442
+
1443
+          // Move jBox
1444
+          if (spaceDiff <= spaceAvail && spaceDiff > 0) {
1445
+            this.pointer.element.css('margin-' + this.pointer.alignAttribute, parseInt(this.pointer.element.css('margin-' + this.pointer.alignAttribute)) - (spaceDiff * (outMove != this.pointer.alignAttribute ? -1 : 1)));
1446
+            this.wrapper.css(this._getTL(outMove), pos[this._getTL(outMove)] + (spaceDiff * (outMove != this._getTL(outMove) ? -1 : 1)));
1447
+            this.positionAdjusted = true;
1448
+          }
1449
+        }
1450
+      }
1451
+    }
1452
+
1453
+    // Fire onPosition event
1454
+    this._fireEvent('onPosition');
1455
+
1456
+    return this;
1457
+  };
1458
+
1459
+
1460
+  // Block scrolling
1461
+  // Borrowed from https://github.com/StephanWagner/unscroll
1462
+
1463
+  jBox.prototype.unscroll = function (elements) {
1464
+
1465
+    // Store reusable vars
1466
+    this.set = function (id, value) {
1467
+      if (!window.unscrollStore) {
1468
+        window.unscrollStore = {};
1469
+      }
1470
+      window.unscrollStore[id] = value;
1471
+    };
1472
+
1473
+    // Get reusable vars
1474
+    this.get = function (id) {
1475
+      return window.unscrollStore ? window.unscrollStore[id] : null;
1476
+    };
1477
+
1478
+    // Get the width of the scroll bar in pixel
1479
+    this.getScrollbarWidth = function () {
1480
+      if (this.get('scrollbarWidth')) {
1481
+        return this.get('scrollbarWidth') + 'px';
1482
+      }
1483
+      var scrollElement = document.createElement('div');
1484
+      scrollElement.style.width = '100px';
1485
+      scrollElement.style.height = '100px';
1486
+      scrollElement.style.overflow = 'scroll';
1487
+      scrollElement.style.position = 'absolute';
1488
+      scrollElement.style.top = '-10000';
1489
+
1490
+      document.body.appendChild(scrollElement);
1491
+      var scrollbarWidth = scrollElement.offsetWidth - scrollElement.clientWidth;
1492
+      document.body.removeChild(scrollElement);
1493
+
1494
+      this.set('scrollbarWidth', scrollbarWidth);
1495
+      return scrollbarWidth + 'px';
1496
+    }
1497
+
1498
+    // Add unscroll class to head
1499
+    function addUnscrollClassName() {
1500
+      if (document.getElementById('unscroll-class-name')) {
1501
+        return;
1502
+      }
1503
+      var css = '.unscrollable { overflow: hidden !important; }',
1504
+        head = document.head || document.getElementsByTagName('head')[0],
1505
+        style = document.createElement('style');
1506
+      style.type = 'text/css';
1507
+      style.setAttribute('id', 'unscroll-class-name');
1508
+      style.appendChild(document.createTextNode(css));
1509
+      head.appendChild(style);
1510
+    }
1511
+
1512
+    // Get the elements to adjust, force body element
1513
+    this.getElementsToAdjust = function (elements) {
1514
+      !elements && (elements = []);
1515
+
1516
+      if (typeof elements === 'string') {
1517
+        elements = [
1518
+          [elements, 'padding-right']
1519
+        ];
1520
+      }
1521
+
1522
+      elements.forEach(function (element, index) {
1523
+        if (typeof element === 'string') {
1524
+          elements[index] = [element, 'padding-right'];
1525
+        }
1526
+      });
1527
+
1528
+      var bodyFound = false;
1529
+      for (var i = 0; i < elements.length; i++) {
1530
+        if (elements[i][0].indexOf('body') !== -1) {
1531
+          bodyFound = true;
1532
+        }
1533
+      };
1534
+
1535
+      if (bodyFound === false) {
1536
+        elements.push(['body', 'padding-right']);
1537
+      }
1538
+
1539
+      return elements;
1540
+    }
1541
+
1542
+    this.pageHasScrollbar = function () {
1543
+      return this.getScrollbarWidth() && document.body.offsetHeight > window.innerHeight;
1544
+    }
1545
+
1546
+    // Clean up elements
1547
+    if (this.pageHasScrollbar()) {
1548
+      elements = this.getElementsToAdjust(elements);
1549
+
1550
+      // Loop through elements and adjust accordingly
1551
+      for (var i = 0; i < elements.length; i++) {
1552
+        var elementsDOM = document.querySelectorAll(elements[i][0]);
1553
+        for (var j = 0; j < elementsDOM.length; j++) {
1554
+          if (elementsDOM[j].getAttribute('data-unscroll')) {
1555
+            return;
1556
+          }
1557
+          var attribute = elements[i][1];
1558
+          var computedStyles = window.getComputedStyle(elementsDOM[j]);
1559
+          var computedStyle = computedStyles.getPropertyValue(attribute);
1560
+          elementsDOM[j].setAttribute('data-unscroll', attribute);
1561
+          if (!computedStyle) {
1562
+            computedStyle = '0px';
1563
+          }
1564
+          var operator = attribute == 'padding-right' || attribute == 'right' ? '+' : '-';
1565
+          elementsDOM[j].style[attribute] = 'calc(' + computedStyle + ' ' + operator + ' ' + this.getScrollbarWidth() + ')';
1566
+        }
1567
+      }
1568
+    }
1569
+
1570
+    // Make the page unscrollable
1571
+    addUnscrollClassName();
1572
+    document.body.classList.add('unscrollable');
1573
+  }
1574
+
1575
+  jBox.prototype.unscroll.reset = function () {
1576
+    var elements = document.querySelectorAll('[data-unscroll]');
1577
+
1578
+    for (var i = 0; i < elements.length; i++) {
1579
+      var attribute = elements[i].getAttribute('data-unscroll');
1580
+      elements[i].style[attribute] = null;
1581
+      elements[i].removeAttribute('data-unscroll');
1582
+    }
1583
+    document.body.classList.remove('unscrollable');
1584
+  }
1585
+
1586
+
1587
+  // Open jBox
1588
+
1589
+  jBox.prototype.open = function (options)
1590
+  {
1591
+    // Create blank options if none passed
1592
+    !options && (options = {});
1593
+
1594
+    // Abort if jBox was destroyed
1595
+    if (this.isDestroyed) return this;
1596
+
1597
+    // Construct jBox if not already constructed
1598
+    !this.wrapper && this._create();
1599
+
1600
+    // Add css to header if not added already
1601
+    !this._styles && (this._styles = jQuery('<style/>').append(this._animationCSS).appendTo(jQuery('head')));
1602
+
1603
+    // Abort any opening or closing timer
1604
+    this.timer && clearTimeout(this.timer);
1605
+
1606
+    // Block body click for 10ms, so jBox can open on attached elements while closeOnClick = 'body'
1607
+    this._blockBodyClick();
1608
+
1609
+    // Block opening
1610
+    if (this.isDisabled) return this;
1611
+
1612
+    // Closing event: closeOnEsc
1613
+    this.options.closeOnEsc && jQuery(document).on('keyup.jBox-' + this.id, function (ev) { if (ev.keyCode == 27) { this.close({ignoreDelay: true}); }}.bind(this));
1614
+
1615
+    // Closing event: closeOnClick
1616
+    if (this.options.closeOnClick === true || this.options.closeOnClick === 'body') {
1617
+      jQuery('body').on('click.jBox-' + this.id + ' tap.jBox-' + this.id, function (ev) {
1618
+        if (this.blockBodyClick || (this.options.closeOnClick == 'body' && (ev.target == this.wrapper[0] || this.wrapper.has(ev.target).length))) return;
1619
+        this.close({ignoreDelay: true});
1620
+      }.bind(this));
1621
+
1622
+      // Fix for iOS event bubbling issue
1623
+      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
1624
+      this.isTouchDevice && jQuery('body > *').on('click.jBox-' + this.id + ' tap.jBox-' + this.id, function () {
1625
+        return true;
1626
+      });
1627
+    }
1628
+
1629
+    // Opening function
1630
+    var open = function () {
1631
+
1632
+      // Adjust zIndex
1633
+      if (this.adjustZIndexOnOpen === true) {
1634
+        jBox.zIndexMax = Math.max(
1635
+          parseInt(this.wrapper.css('zIndex'), 10),
1636
+          this.options.zIndex,
1637
+          jBox.zIndexMax || 0,
1638
+          jBox.zIndexMaxDragover || 0
1639
+        ) + 2;
1640
+        this.wrapper.css('zIndex', jBox.zIndexMax);
1641
+        this.options.zIndex = jBox.zIndexMax;
1642
+      }
1643
+
1644
+      // Set title from source element
1645
+      this.source && this.options.getTitle && (this.source.attr(this.options.getTitle) && this.setTitle(this.source.attr(this.options.getTitle), true));
1646
+
1647
+      // Set content from source element
1648
+      this.source && this.options.getContent && (this.source.data('jBox-getContent') ? this.setContent(this.source.data('jBox-getContent'), true) : (this.source.attr(this.options.getContent) ? this.setContent(this.source.attr(this.options.getContent), true) : (this.options.getContent == 'html' ? this.setContent(this.source.html(), true) : null)));
1649
+
1650
+      // Fire onOpen event
1651
+      this._fireEvent('onOpen');
1652
+
1653
+      // Get content from ajax
1654
+      if ((this.options.ajax && (this.options.ajax.url || (this.source && this.source.attr(this.options.ajax.getURL))) && (!this.ajaxLoaded || this.options.ajax.reload)) || (options.ajax && (options.ajax.url || options.ajax.data))) {
1655
+        // Send the content from stored data if there is any, otherwise load new data
1656
+        (this.options.ajax.reload != 'strict' && this.source && this.source.data('jBox-ajax-data') && !(options.ajax && (options.ajax.url || options.ajax.data))) ? this.setContent(this.source.data('jBox-ajax-data')) : this.ajax((options.ajax || null), true);
1657
+      }
1658
+
1659
+      // Set position
1660
+      (!this.positionedOnOpen || this.options.repositionOnOpen) && this.position(options) && (this.positionedOnOpen = true);
1661
+
1662
+      // Abort closing
1663
+      this.isClosing && this._abortAnimation();
1664
+
1665
+      // Open functions to call when jBox is closed
1666
+      if (!this.isOpen) {
1667
+
1668
+        // jBox is open now
1669
+        this.isOpen = true;
1670
+
1671
+        // Automatically close jBox after some time
1672
+        this.options.autoClose && (this.options.delayClose = this.options.autoClose) && this.close();
1673
+
1674
+        // Attach events
1675
+        this._attachEvents();
1676
+
1677
+        // Block scrolling
1678
+        if (this.options.blockScroll) {
1679
+          if (this.options.blockScrollAdjust) {
1680
+            if (jBox.blockScrollScopes) {
1681
+              jBox.blockScrollScopes++;
1682
+            } else {
1683
+              jBox.blockScrollScopes = 1;
1684
+              this.unscroll(Array.isArray(this.options.blockScrollAdjust) || typeof this.options.blockScrollAdjust === 'string' ? this.options.blockScrollAdjust : null);
1685
+            }
1686
+          } else {
1687
+            jQuery('body').addClass('jBox-blockScroll-' + this.id);
1688
+          }
1689
+        }
1690
+
1691
+        // Show overlay
1692
+        if (this.options.overlay) {
1693
+          this._showOverlay();
1694
+
1695
+          // TODO Optimize: We have to position here again, because if the overlay has a close button, the upper adjustDistance will be wrong
1696
+          this.position();
1697
+        }
1698
+
1699
+        // Only animate if jBox is completely closed
1700
+        this.options.animation && !this.isClosing && this._animate('open');
1701
+
1702
+        // Play audio file
1703
+        this.options.audio && this.options.audio.open && this.audio(this.options.audio.open, this.options.volume.open);
1704
+
1705
+        // Fading animation or show immediately
1706
+        if (this.options.fade) {
1707
+          this.wrapper.stop().animate({opacity: 1}, {
1708
+            queue: false,
1709
+            duration: this.options.fade,
1710
+            start: function () {
1711
+              this.isOpening = true;
1712
+              this.wrapper.css({display: 'block'});
1713
+            }.bind(this),
1714
+            always: function () {
1715
+              this.isOpening = false;
1716
+
1717
+              // Delay positioning for ajax to prevent positioning during animation
1718
+              setTimeout(function () { this.positionOnFadeComplete && this.position() && (this.positionOnFadeComplete = false); }.bind(this), 10);
1719
+            }.bind(this)
1720
+          });
1721
+        } else {
1722
+          this.wrapper.css({display: 'block', opacity: 1});
1723
+          this.positionOnFadeComplete && this.position() && (this.positionOnFadeComplete = false);
1724
+        }
1725
+      }
1726
+    }.bind(this);
1727
+
1728
+    // Open jBox
1729
+    this.options.delayOpen && !this.isOpen && !this.isClosing && !options.ignoreDelay ? (this.timer = setTimeout(open, this.options.delayOpen)) : open();
1730
+
1731
+    return this;
1732
+  };
1733
+
1734
+
1735
+  // Close jBox
1736
+
1737
+  jBox.prototype.close = function (options)
1738
+  {
1739
+    // Create blank options if none passed
1740
+    options || (options = {});
1741
+
1742
+    // Remove close events
1743
+    jQuery('body').off('click.jBox-' + this.id + ' tap.jBox-' + this.id);
1744
+    this.isTouchDevice && jQuery('body > *').off('click.jBox-' + this.id + ' tap.jBox-' + this.id);
1745
+
1746
+    // Abort if jBox was destroyed or is currently closing
1747
+    if (this.isDestroyed || this.isClosing) return this;
1748
+
1749
+    // Abort opening
1750
+    this.timer && clearTimeout(this.timer);
1751
+
1752
+    // Block body click for 10ms, so jBox can open on attached elements while closeOnClick = 'body' is true
1753
+    this._blockBodyClick();
1754
+
1755
+    // Block closing
1756
+    if (this.isDisabled) return this;
1757
+
1758
+    // Close function
1759
+    var close = function () {
1760
+
1761
+      // Fire onClose event
1762
+      this._fireEvent('onClose');
1763
+
1764
+      // Cancel the ajax call
1765
+      if (this.options.cancelAjaxOnClose) {
1766
+        this.cancelAjax();
1767
+      }
1768
+
1769
+      // Only close if jBox is open
1770
+      if (this.isOpen) {
1771
+
1772
+        // jBox is not open anymore
1773
+        this.isOpen = false;
1774
+
1775
+        // Detach events
1776
+        this._detachEvents();
1777
+
1778
+        // Unblock scrolling
1779
+        if (this.options.blockScroll) {
1780
+          if (this.options.blockScrollAdjust) {
1781
+            jBox.blockScrollScopes = jBox.blockScrollScopes ? --jBox.blockScrollScopes : 0;
1782
+            !jBox.blockScrollScopes && this.unscroll.reset();
1783
+          } else {
1784
+            jQuery('body').removeClass('jBox-blockScroll-' + this.id);
1785
+          }
1786
+        }
1787
+
1788
+        // Hide overlay
1789
+        this.options.overlay && this._hideOverlay();
1790
+
1791
+        // Only animate if jBox is compleately closed
1792
+        this.options.animation && !this.isOpening && this._animate('close');
1793
+
1794
+        // Play audio file
1795
+        this.options.audio && this.options.audio.close && this.audio(this.options.audio.close, this.options.volume.close);
1796
+
1797
+        // Get fade duration
1798
+        var fadeDuration = this.isTouchDevice && this.options.target == 'mouse' ? 0 : this.options.fade;
1799
+
1800
+        // Fading animation or show immediately
1801
+        if (fadeDuration) {
1802
+          this.wrapper.stop().animate({opacity: 0}, {
1803
+            queue: false,
1804
+            duration: fadeDuration,
1805
+            start: function () {
1806
+              this.isClosing = true;
1807
+            }.bind(this),
1808
+            complete: function () {
1809
+              this.wrapper.css({display: 'none'});
1810
+              this._fireEvent('onCloseComplete');
1811
+            }.bind(this),
1812
+            always: function () {
1813
+              this.isClosing = false;
1814
+            }.bind(this)
1815
+          });
1816
+        } else {
1817
+          this.wrapper.css({display: 'none', opacity: 0});
1818
+          this._fireEvent('onCloseComplete');
1819
+        }
1820
+      }
1821
+    }.bind(this);
1822
+
1823
+    // Close jBox
1824
+    if (options.ignoreDelay || (this.isTouchDevice && this.options.target == 'mouse')) {
1825
+      close();
1826
+    } else if ((this.options.delayOnHover || this.options.showCountdown) && this.options.delayClose > 10) {
1827
+      var self = this;
1828
+      var remaining = this.options.delayClose;
1829
+      var prevFrame = Date.now();
1830
+      if (this.options.showCountdown && !this.inner) {
1831
+        var outer = jQuery('<div class="jBox-countdown" />');
1832
+        this.inner = jQuery('<div class="jBox-countdown-inner" />');
1833
+        outer.prepend(this.inner);
1834
+        jQuery('#' + this.id).append(outer);
1835
+      }
1836
+      this.countdown = function(){
1837
+        var dateNow = Date.now();
1838
+        if (!self.isHovered) {
1839
+          remaining -= dateNow - prevFrame;
1840
+        }
1841
+        prevFrame = dateNow;
1842
+        if (remaining > 0) {
1843
+          if (self.options.showCountdown) {
1844
+            self.inner.css('width', (remaining * 100 / self.options.delayClose) + '%');
1845
+          }
1846
+          window.requestAnimationFrame(self.countdown);
1847
+        } else {
1848
+          close();
1849
+        }
1850
+      };
1851
+      window.requestAnimationFrame(this.countdown);
1852
+    } else {
1853
+      this.timer = setTimeout(close, Math.max(this.options.delayClose, 10));
1854
+    }
1855
+
1856
+    return this;
1857
+  };
1858
+
1859
+
1860
+  // Open or close jBox
1861
+
1862
+  jBox.prototype.toggle = function (options)
1863
+  {
1864
+    this[this.isOpen ? 'close' : 'open'](options);
1865
+    return this;
1866
+  };
1867
+
1868
+
1869
+  // Block opening and closing
1870
+
1871
+  jBox.prototype.disable = function ()
1872
+  {
1873
+    this.isDisabled = true;
1874
+    return this;
1875
+  };
1876
+
1877
+
1878
+  // Unblock opening and closing
1879
+
1880
+  jBox.prototype.enable = function ()
1881
+  {
1882
+    this.isDisabled = false;
1883
+    return this;
1884
+  };
1885
+
1886
+
1887
+  // Hide jBox
1888
+
1889
+  jBox.prototype.hide = function ()
1890
+  {
1891
+    this.disable();
1892
+    if (this.wrapper) {
1893
+      this.cacheWrapperDisplay = this.wrapper.css('display');
1894
+      this.wrapper.css({display: 'none'});
1895
+    }
1896
+    if (this.overlay) {
1897
+      this.cacheOverlayDisplay = this.overlay.css('display');
1898
+      this.overlay.css({display: 'none'});
1899
+    }
1900
+    return this;
1901
+  };
1902
+
1903
+
1904
+  // Show jBox
1905
+
1906
+  jBox.prototype.show = function ()
1907
+  {
1908
+    this.enable();
1909
+    if (this.wrapper && this.cacheWrapperDisplay) {
1910
+      this.wrapper.css({display: this.cacheWrapperDisplay});
1911
+      this.cacheWrapperDisplay = null;
1912
+    }
1913
+    if (this.overlay && this.cacheOverlayDisplay) {
1914
+      this.overlay.css({display: this.cacheOverlayDisplay});
1915
+      this.cacheOverlayDisplay = null;
1916
+    }
1917
+    return this;
1918
+  };
1919
+
1920
+
1921
+  // Get content from ajax
1922
+
1923
+  jBox.prototype.ajax = function (options, opening)
1924
+  {
1925
+    options || (options = {});
1926
+
1927
+    // Add data or url from source element if none set in options
1928
+    jQuery.each([['getData', 'data'], ['getURL', 'url']], function (index, item) {
1929
+      (this.options.ajax[item[0]] && !options[item[1]] && this.source && this.source.attr(this.options.ajax[item[0]]) != undefined) && (options[item[1]] = this.source.attr(this.options.ajax[item[0]]) || '');
1930
+    }.bind(this));
1931
+
1932
+    // Clone the system options
1933
+    var sysOptions = jQuery.extend(true, {}, this.options.ajax);
1934
+
1935
+    // Abort running ajax call
1936
+    this.cancelAjax();
1937
+
1938
+    // Extract events
1939
+    var beforeSend = options.beforeSend || sysOptions.beforeSend || function () {};
1940
+    var complete = options.complete || sysOptions.complete || function () {};
1941
+    var success = options.success || sysOptions.success || function () {};
1942
+    var error = options.error || sysOptions.error || function () {};
1943
+
1944
+    // Merge options
1945
+    var userOptions = jQuery.extend(true, sysOptions, options);
1946
+
1947
+    // Set new beforeSend event
1948
+    userOptions.beforeSend = function (xhr)
1949
+    {
1950
+      // jBox is loading
1951
+      userOptions.loadingClass && this.wrapper.addClass(userOptions.loadingClass === true ? 'jBox-loading' : userOptions.loadingClass);
1952
+
1953
+      // Add loading spinner
1954
+      userOptions.spinner && (this.spinnerDelay = setTimeout(function ()
1955
+      {
1956
+        // Add class for loading spinner
1957
+        this.wrapper.addClass('jBox-loading-spinner');
1958
+
1959
+        // Reposition jBox
1960
+        // TODO: Only reposition if dimensions change
1961
+        userOptions.spinnerReposition && (opening ? (this.positionOnFadeComplete = true) : this.position());
1962
+
1963
+        // Add spinner to container
1964
+        this.spinner = jQuery(userOptions.spinner !== true ? userOptions.spinner : '<div class="jBox-spinner"></div>').appendTo(this.container);
1965
+
1966
+        // Fix spinners position if there is a title
1967
+        this.titleContainer && this.spinner.css('position') == 'absolute' && this.spinner.css({transform: 'translateY(' + (this.titleContainer.outerHeight() * 0.5) + 'px)'});
1968
+
1969
+      }.bind(this), (this.content.html() == '' ? 0 : (userOptions.spinnerDelay || 0))));
1970
+
1971
+      // Fire users beforeSend event
1972
+      (beforeSend.bind(this))(xhr);
1973
+
1974
+    }.bind(this);
1975
+
1976
+    // Set up new complete event
1977
+    userOptions.complete = function (response)
1978
+    {
1979
+      // Abort spinner timeout
1980
+      this.spinnerDelay && clearTimeout(this.spinnerDelay);
1981
+
1982
+      // jBox finished loading
1983
+      this.wrapper.removeClass('jBox-loading jBox-loading-spinner jBox-loading-spinner-delay');
1984
+
1985
+      // Remove spinner
1986
+      this.spinner && this.spinner.length && this.spinner.remove() && userOptions.spinnerReposition && (opening ? (this.positionOnFadeComplete = true) : this.position());
1987
+
1988
+      // Store that ajax loading finished
1989
+      this.ajaxLoaded = true;
1990
+
1991
+      // Fire users complete event
1992
+      (complete.bind(this))(response);
1993
+
1994
+    }.bind(this);
1995
+
1996
+    // Set up new success event
1997
+    userOptions.success = function (response)
1998
+    {
1999
+      // Set content
2000
+      userOptions.setContent && this.setContent(response, true) && (opening ? (this.positionOnFadeComplete = true) : this.position());
2001
+
2002
+      // Store content in source element
2003
+      userOptions.setContent && this.source && this.source.data('jBox-ajax-data', response);
2004
+
2005
+      // Fire users success event
2006
+      (success.bind(this))(response);
2007
+
2008
+    }.bind(this);
2009
+
2010
+    // Add error event
2011
+    userOptions.error = function (response) { (error.bind(this))(response); }.bind(this);
2012
+
2013
+    // Send new ajax request
2014
+    this.ajaxRequest = jQuery.ajax(userOptions);
2015
+
2016
+    return this;
2017
+  };
2018
+
2019
+
2020
+  // Abort an ajax call
2021
+
2022
+  jBox.prototype.cancelAjax = function () {
2023
+    if (this.ajaxRequest) {
2024
+      this.ajaxRequest.abort();
2025
+      this.ajaxLoaded = false;
2026
+    }
2027
+  };
2028
+
2029
+
2030
+  // Play an audio file
2031
+
2032
+  jBox.prototype.audio = function (url, volume)
2033
+  {
2034
+    // URL is required
2035
+    if (!url) return this;
2036
+
2037
+    // Create intern audio object if it wasn't created already
2038
+    !jBox._audio && (jBox._audio = {});
2039
+
2040
+    // Create an audio element specific to this audio file if it doesn't exist already
2041
+    if (!jBox._audio[url]) {
2042
+      var audio = jQuery('<audio/>');
2043
+      jQuery('<source/>', {src: url + '.mp3'}).appendTo(audio);
2044
+      jQuery('<source/>', {src: url + '.ogg'}).appendTo(audio);
2045
+      jBox._audio[url] = audio[0];
2046
+    }
2047
+
2048
+    // Set volume
2049
+    jBox._audio[url].volume = Math.min(((volume != undefined ? volume : 100) / 100), 1);
2050
+
2051
+    // Try to pause current audio
2052
+    try {
2053
+      jBox._audio[url].pause();
2054
+      jBox._audio[url].currentTime = 0;
2055
+    } catch (e) {}
2056
+
2057
+    // Play audio
2058
+    jBox._audio[url].play();
2059
+
2060
+    return this;
2061
+  };
2062
+
2063
+
2064
+  // Apply custom animations to jBox
2065
+
2066
+  jBox._animationSpeeds = {
2067
+    'tada': 1000,
2068
+    'tadaSmall': 1000,
2069
+    'flash': 500,
2070
+    'shake': 400,
2071
+    'pulseUp': 250,
2072
+    'pulseDown': 250,
2073
+    'popIn': 250,
2074
+    'popOut': 250,
2075
+    'fadeIn': 200,
2076
+    'fadeOut': 200,
2077
+    'slideUp': 400,
2078
+    'slideRight': 400,
2079
+    'slideLeft': 400,
2080
+    'slideDown': 400
2081
+  };
2082
+
2083
+  jBox.prototype.animate = function (animation, options)
2084
+  {
2085
+    // Options are required
2086
+    !options && (options = {});
2087
+
2088
+    // Timout needs to be an object
2089
+    !this.animationTimeout && (this.animationTimeout = {});
2090
+
2091
+    // Use jBox wrapper by default
2092
+    !options.element && (options.element = this.wrapper);
2093
+
2094
+    // Give the element an unique id
2095
+    !options.element.data('jBox-animating-id') && options.element.data('jBox-animating-id', jBox._getUniqueElementID());
2096
+
2097
+    // Abort if element is animating
2098
+    if (options.element.data('jBox-animating')) {
2099
+      options.element.removeClass(options.element.data('jBox-animating')).data('jBox-animating', null);
2100
+      this.animationTimeout[options.element.data('jBox-animating-id')] && clearTimeout(this.animationTimeout[options.element.data('jBox-animating-id')]);
2101
+    }
2102
+
2103
+    // Animate the element
2104
+    options.element.addClass('jBox-animated-' + animation).data('jBox-animating', 'jBox-animated-' + animation);
2105
+    this.animationTimeout[options.element.data('jBox-animating-id')] = setTimeout((function() { options.element.removeClass(options.element.data('jBox-animating')).data('jBox-animating', null); options.complete && options.complete(); }), jBox._animationSpeeds[animation]);
2106
+  };
2107
+
2108
+  // https://gist.github.com/AlexEmashev/ee8302b5036b01362f63dab35948401f
2109
+  jBox.prototype.swipeDetector = function (swipeTarget, options) {
2110
+    // States: 0 - no swipe, 1 - swipe started, 2 - swipe released
2111
+    var swipeState = 0;
2112
+    // Coordinates when swipe started
2113
+    var startX = 0;
2114
+    var startY = 0;
2115
+    // Distance of swipe
2116
+    var pixelOffsetX = 0;
2117
+    var pixelOffsetY = 0;
2118
+
2119
+    var defaultSettings = {
2120
+      // Amount of pixels, when swipe don't count.
2121
+      swipeThreshold: 70,
2122
+      // Flag that indicates that plugin should react only on touch events.
2123
+      // Not on mouse events too.
2124
+      useOnlyTouch: false
2125
+    };
2126
+
2127
+    // Initializer
2128
+    (function init() {
2129
+      options = jQuery.extend(defaultSettings, options);
2130
+      // Support touch and mouse as well.
2131
+      swipeTarget.on("mousedown touchstart", swipeStart);
2132
+      $("html").on("mouseup touchend", swipeEnd);
2133
+      $("html").on("mousemove touchmove", swiping);
2134
+    })();
2135
+
2136
+    function swipeStart(event) {
2137
+      if (options.useOnlyTouch && !event.originalEvent.touches) {
2138
+        return;
2139
+      }
2140
+
2141
+      if (event.originalEvent.touches) {
2142
+        event = event.originalEvent.touches[0];
2143
+      }
2144
+
2145
+      if (swipeState === 0) {
2146
+        swipeState = 1;
2147
+        startX = event.clientX;
2148
+        startY = event.clientY;
2149
+      }
2150
+    }
2151
+
2152
+    function swipeEnd(event) {
2153
+      if (swipeState === 2) {
2154
+        swipeState = 0;
2155
+
2156
+        if (
2157
+          Math.abs(pixelOffsetX) > Math.abs(pixelOffsetY) &&
2158
+          Math.abs(pixelOffsetX) > options.swipeThreshold
2159
+        ) {
2160
+          // Horizontal Swipe
2161
+          if (pixelOffsetX < 0) {
2162
+            swipeTarget.trigger($.Event("swipeLeft.sd"));
2163
+          } else {
2164
+            swipeTarget.trigger($.Event("swipeRight.sd"));
2165
+          }
2166
+        } else if (Math.abs(pixelOffsetY) > options.swipeThreshold) {
2167
+          // Vertical swipe
2168
+          if (pixelOffsetY < 0) {
2169
+            swipeTarget.trigger($.Event("swipeUp.sd"));
2170
+          } else {
2171
+            swipeTarget.trigger($.Event("swipeDown.sd"));
2172
+          }
2173
+        }
2174
+      }
2175
+    }
2176
+
2177
+    function swiping(event) {
2178
+      // If swipe don't occuring, do nothing.
2179
+      if (swipeState !== 1) return;
2180
+
2181
+      if (event.originalEvent.touches) {
2182
+        event = event.originalEvent.touches[0];
2183
+      }
2184
+
2185
+      var swipeOffsetX = event.clientX - startX;
2186
+      var swipeOffsetY = event.clientY - startY;
2187
+
2188
+      if (
2189
+        Math.abs(swipeOffsetX) > options.swipeThreshold ||
2190
+        Math.abs(swipeOffsetY) > options.swipeThreshold
2191
+      ) {
2192
+        swipeState = 2;
2193
+        pixelOffsetX = swipeOffsetX;
2194
+        pixelOffsetY = swipeOffsetY;
2195
+      }
2196
+    }
2197
+
2198
+    return swipeTarget; // Return element available for chaining.
2199
+  }
2200
+
2201
+
2202
+  // Destroy jBox and remove it from DOM
2203
+
2204
+  jBox.prototype.destroy = function ()
2205
+  {
2206
+    // Detach from attached elements
2207
+    this.detach();
2208
+
2209
+    // If jBox is open, close without delay
2210
+    this.isOpen && this.close({ignoreDelay: true});
2211
+
2212
+    // Remove wrapper
2213
+    this.wrapper && this.wrapper.remove();
2214
+
2215
+    // Remove overlay
2216
+    this.overlay && this.overlay.remove();
2217
+
2218
+    // Remove styles
2219
+    this._styles && this._styles.remove();
2220
+
2221
+    // Tell the jBox instance it is destroyed
2222
+    this.isDestroyed = true;
2223
+
2224
+    return this;
2225
+  };
2226
+
2227
+
2228
+  // Get a unique ID for jBoxes
2229
+
2230
+  jBox._getUniqueID = (function ()
2231
+  {
2232
+    var i = 1;
2233
+    return function () { return i++; };
2234
+  }());
2235
+
2236
+
2237
+  // Get a unique ID for animating elements
2238
+
2239
+  jBox._getUniqueElementID = (function ()
2240
+  {
2241
+    var i = 1;
2242
+    return function () { return i++; };
2243
+  }());
2244
+
2245
+
2246
+  // Function to create jBox plugins
2247
+
2248
+  jBox._pluginOptions = {};
2249
+  jBox.plugin = function (type, options)
2250
+  {
2251
+    jBox._pluginOptions[type] = options;
2252
+  };
2253
+
2254
+
2255
+  // Make jBox usable with jQuery selectors
2256
+
2257
+  jQuery.fn.jBox = function (type, options) {
2258
+    // Variables type and object are required
2259
+    !type && (type = {});
2260
+    !options && (options = {});
2261
+
2262
+    // Return a new instance of jBox with the selector as attached element
2263
+    return new jBox(type, jQuery.extend(options, {
2264
+      attach: this
2265
+    }));
2266
+  };
2267
+
2268
+  return jBox;
2269
+
2270
+};
0 2271
new file mode 100644
... ...
@@ -0,0 +1,95 @@
1
+/**
2
+ * jBox Confirm plugin: Add a confirm dialog to links, buttons, etc.
3
+ *
4
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
5
+ *
6
+ * License: MIT (https://opensource.org/licenses/MIT)
7
+ *
8
+ * Requires: jBox (https://cdn.jsdelivr.net/gh/StephanWagner/jBox@latest/dist/jBox.min.js)
9
+ */
10
+
11
+function jBoxConfirmWrapper(jBox, jQuery) {
12
+
13
+  new jBox.plugin('Confirm', {
14
+
15
+
16
+    // Options (https://stephanwagner.me/jBox/options#options-confirm)
17
+
18
+    confirmButton: 'Submit',  // Text for the submit button
19
+    cancelButton: 'Cancel',   // Text for the cancel button
20
+    confirm: null,            // Function to execute when clicking the submit button. By default jBox will use the onclick or href attribute in that order if found
21
+    cancel: null,             // Function to execute when clicking the cancel button
22
+    closeOnConfirm: true,     // Close jBox when the user clicks the confirm button
23
+    target: window,
24
+    fixed: true,
25
+    attach: '[data-confirm]',
26
+    getContent: 'data-confirm',
27
+    content: 'Do you really want to do this?',
28
+    minWidth: 360,
29
+    maxWidth: 500,
30
+    blockScroll: true,
31
+    closeOnEsc: true,
32
+    closeOnClick: false,
33
+    closeButton: false,
34
+    overlay: true,
35
+    animation: 'zoomIn',
36
+    preventDefault: true,
37
+
38
+
39
+    // Triggered when jBox is attached to the element
40
+
41
+    _onAttach: function (el)
42
+    {
43
+      // Extract the href or the onclick event if no submit event is passed
44
+      if (!this.options.confirm) {
45
+        var submit = el.attr('onclick') ? el.attr('onclick') : (
46
+          el.attr('href') ? (
47
+            el.attr('target') ? 'window.open("' + el.attr('href') + '", "' + el.attr('target') + '");'  : 'window.location.href = "' + el.attr('href') + '";'
48
+          ) : '');
49
+        el.prop('onclick', null).data('jBox-Confirm-submit', submit);
50
+      }
51
+    },
52
+
53
+
54
+    // Triggered when jBox was created
55
+
56
+    _onCreated: function ()
57
+    {
58
+      // Add modal class to mimic jBox modal
59
+      this.wrapper.addClass('jBox-Modal');
60
+
61
+      // Add a footer to the jBox container
62
+      this.footer = jQuery('<div class="jBox-Confirm-footer"/>');
63
+
64
+      jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-cancel"/>')
65
+        .html(this.options.cancelButton)
66
+        .on('click tap', function () {
67
+          this.options.cancel && this.options.cancel(this.source);
68
+          this.close();
69
+        }.bind(this))
70
+        .appendTo(this.footer);
71
+
72
+      this.submitButton = jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-submit"/>')
73
+        .html(this.options.confirmButton)
74
+        .appendTo(this.footer);
75
+
76
+      this.footer.appendTo(this.container);
77
+    },
78
+
79
+
80
+    // Triggered when jBox is opened
81
+
82
+    _onOpen: function ()
83
+    {
84
+      // Set the new action for the submit button
85
+      this.submitButton
86
+        .off('click.jBox-Confirm' + this.id + ' tap.jBox-Confirm' + this.id)
87
+        .on('click.jBox-Confirm' + this.id + ' tap.jBox-Confirm' + this.id, function () {
88
+          this.options.confirm ? this.options.confirm(this.source) : eval(this.source.data('jBox-Confirm-submit'));
89
+          this.options.closeOnConfirm && this.close();
90
+        }.bind(this));
91
+    }
92
+
93
+  });
94
+
95
+};
0 96
new file mode 100644
... ...
@@ -0,0 +1,351 @@
1
+/**
2
+ * jBox Image plugin: Adds a lightbox to your images
3
+ *
4
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
5
+ *
6
+ * License: MIT (https://opensource.org/licenses/MIT)
7
+ *
8
+ * Requires: jBox (https://cdn.jsdelivr.net/gh/StephanWagner/jBox@latest/dist/jBox.min.js)
9
+ */
10
+
11
+function jBoxImageWrapper(jBox, jQuery) {
12
+
13
+  new jBox.plugin('Image', {
14
+
15
+
16
+    // Options (https://stephanwagner.me/jBox/options#options-image)
17
+
18
+    src: 'href',                 // The attribute where jBox gets the image source from, e.g. href="/path_to_image/image.jpg"
19
+    gallery: 'data-jbox-image',  // The attribute to set the galleries, e.g. data-jbox-image="gallery1"
20
+    imageLabel: 'title',         // The attribute where jBox gets the image label from, e.g. title="My label"
21
+    imageFade: 360,              // The fade duration for images in ms
22
+    imageSize: 'contain',        // How to display the images. Use CSS background-position values, e.g. 'cover', 'contain', 'auto', 'initial', '50% 50%'
23
+    imageCounter: false,         // Set to true to add an image counter, e.g. 4/20
24
+    imageCounterSeparator: '/',  // HTML to separate the current image number from all image numbers, e.g. '/' or ' of '
25
+    downloadButton: false,       // Adds a download button
26
+    downloadButtonText: null,    // Text for the download button
27
+    downloadButtonUrl: null,     // The attribute at the source element where to find the image to download, e.g. data-download="/path_to_image/image.jpg". If none provided, the currently active image will be downloaded
28
+    mobileImageAttr: null,       // The attribute to look for an mobile version of the image
29
+    mobileImageBreakpoint: null, // The upper breakpoint to load the mobile image
30
+    preloadFirstImage: false,    // Preload the first image when page is loaded
31
+    target: window,
32
+    attach: '[data-jbox-image]',
33
+    fixed: true,
34
+    blockScroll: true,
35
+    closeOnEsc: true,
36
+    closeOnClick: 'button',
37
+    closeButton: true,
38
+    overlay: true,
39
+    animation: 'zoomIn',
40
+    preventDefault: true,
41
+    width: '100%',
42
+    height: '100%',
43
+    adjustDistance: {
44
+      top: 40,
45
+      right: 0,
46
+      bottom: 40,
47
+      left: 0
48
+    },
49
+
50
+
51
+    // Triggered when jBox is initialized
52
+
53
+    _onInit: function ()
54
+    {
55
+      // Initial images and z-index
56
+      this.images = this.currentImage = {};
57
+      this.imageZIndex = 1;
58
+
59
+      this.initImage = function (item) {
60
+        item = jQuery(item);
61
+
62
+        // Abort if the item was added to a gallery already
63
+        if (item.data('jBox-image-gallery')) {
64
+          return;
65
+        }
66
+
67
+        // Get the image src
68
+        var src = item.attr(this.options.src);
69
+
70
+        // Update responsive image src
71
+        if (this.options.mobileImageAttr && this.options.mobileImageBreakpoint && item.attr(this.options.mobileImageAttr)) {
72
+          if (jQuery(window).width() <= this.options.mobileImageBreakpoint) {
73
+            src = item.attr(this.options.mobileImageAttr);
74
+          }
75
+        }
76
+
77
+        // Add item to a gallery
78
+        var gallery = item.attr(this.options.gallery) || 'default';
79
+        !this.images[gallery] && (this.images[gallery] = []);
80
+        this.images[gallery].push({
81
+          src: src,
82
+          label: (item.attr(this.options.imageLabel) || ''),
83
+          downloadUrl: this.options.downloadButtonUrl && item.attr(this.options.downloadButtonUrl) ? item.attr(this.options.downloadButtonUrl) : null
84
+        });
85
+
86
+        // Remove the title attribute so it won't show the browsers tooltip
87
+        this.options.imageLabel == 'title' && item.removeAttr('title');
88
+
89
+        // Store data in source element for easy access
90
+        item.data('jBox-image-gallery', gallery);
91
+        item.data('jBox-image-id', (this.images[gallery].length - 1));
92
+      }.bind(this);
93
+
94
+      // Loop through images, sort and save in global variable
95
+      this.attachedElements && this.attachedElements.length && jQuery.each(this.attachedElements, function (index, item) {
96
+        this.initImage(item);
97
+      }.bind(this));
98
+
99
+      // Helper to inject the image into content area
100
+      var appendImage = function (gallery, id, show, instant) {
101
+        // Abort if image was appended already
102
+        if (jQuery('#jBox-image-' + gallery + '-' + id).length) {
103
+          return;
104
+        }
105
+
106
+        // Create image container
107
+        var image = jQuery('<div/>', {
108
+          id: 'jBox-image-' + gallery + '-' + id,
109
+          'class': 'jBox-image-container' + (show ? ' jBox-image-' + gallery + '-current' : '')
110
+        }).css({
111
+          backgroundSize: this.options.imageSize,
112
+          opacity: (instant ? 1 : 0),
113
+          zIndex: (show ? this.imageZIndex++ : 0)
114
+        }).appendTo(this.content);
115
+
116
+        // Add swipe events
117
+        this.swipeDetector(image)
118
+          .on("swipeLeft.sd swipeRight.sd", function (event) {
119
+            if (event.type === "swipeLeft") {
120
+              this.showImage('next');
121
+            } else if (event.type === "swipeRight") {
122
+              this.showImage('prev');
123
+            }
124
+          }.bind(this));
125
+
126
+        // Create labels
127
+        jQuery('<div/>', {
128
+          id: 'jBox-image-label-' + gallery + '-' + id,
129
+          'class': 'jBox-image-label' + (show ? ' active' : '')
130
+        })
131
+        .html(this.images[gallery][id].label)
132
+        .on('click tap', function () {
133
+          jQuery(this).toggleClass('expanded');
134
+        })
135
+        .appendTo(this.imageLabelContainer);
136
+
137
+        // Show image
138
+        show && image.animate({opacity: 1}, instant ? 0 : this.options.imageFade);
139
+
140
+        return image;
141
+      }.bind(this);
142
+
143
+      // Function to download an image
144
+      this.downloadImage = function (imageUrl) {
145
+        var link = document.createElement('a');
146
+        link.href = imageUrl;
147
+        link.setAttribute('download', imageUrl.substring(imageUrl.lastIndexOf('/')+1));
148
+        document.body.appendChild(link);
149
+        link.click();
150
+      };
151
+
152
+      // Helper to show new image label
153
+      var showLabel = function (gallery, id) {
154
+        jQuery('.jBox-image-label.active').removeClass('active expanded');
155
+        jQuery('#jBox-image-label-' + gallery + '-' + id).addClass('active');
156
+      };
157
+
158
+      // Helper to load image
159
+      var loadImage = function (gallery, id, show, instant) {
160
+        var imageContainer = appendImage(gallery, id, show, instant);
161
+        imageContainer.addClass('jBox-image-loading');
162
+
163
+        jQuery('<img src="' + this.images[gallery][id].src + '" />').each(function () {
164
+          var tmpImg = new Image();
165
+          tmpImg.onload = function () {
166
+            imageContainer.removeClass('jBox-image-loading');
167
+            imageContainer.css({backgroundImage: 'url("' + this.images[gallery][id].src + '")'});
168
+          }.bind(this);
169
+
170
+          tmpImg.onerror = function () {
171
+            imageContainer.removeClass('jBox-image-loading');
172
+            imageContainer.addClass('jBox-image-not-found');
173
+          }.bind(this);
174
+
175
+          tmpImg.src = this.images[gallery][id].src;
176
+        }.bind(this));
177
+      }.bind(this);
178
+
179
+      // Show images when they are loaded or load them if not
180
+      this.showImage = function (img) {
181
+        // Get the gallery and the image id from the next or the previous image
182
+        if (img != 'open') {
183
+          var gallery = this.currentImage.gallery;
184
+          var id = this.currentImage.id + (1 * (img == 'prev') ? -1 : 1);
185
+          id = id > (this.images[gallery].length - 1) ? 0 : (id < 0 ? (this.images[gallery].length - 1) : id);
186
+
187
+        // Or get image data from source element
188
+        } else {
189
+          // Get gallery and image id from source element
190
+          if (this.source) {
191
+            var gallery = this.source.data('jBox-image-gallery');
192
+            var id = this.source.data('jBox-image-id');
193
+
194
+          // Get gallery and image id attached elements
195
+          } else if (this.attachedElements && this.attachedElements.length) {
196
+            var gallery = jQuery(this.attachedElements[0]).data('jBox-image-gallery');
197
+            var id = jQuery(this.attachedElements[0]).data('jBox-image-id');
198
+          } else {
199
+            return;
200
+          }
201
+
202
+          // Remove or show the next and prev buttons
203
+          jQuery('.jBox-image-pointer-prev, .jBox-image-pointer-next').css({display: (this.images[gallery].length > 1 ? 'block' : 'none')});
204
+        }
205
+
206
+        // If there is a current image already shown, hide it
207
+        if (jQuery('.jBox-image-' + gallery + '-current').length) {
208
+          jQuery('.jBox-image-' + gallery + '-current').removeClass('jBox-image-' + gallery + '-current').animate({opacity: 0}, (img == 'open') ? 0 : this.options.imageFade);
209
+        }
210
+
211
+        // Set new current image
212
+        this.currentImage = {gallery: gallery, id: id};
213
+
214
+        // Show image if it already exists
215
+        if (jQuery('#jBox-image-' + gallery + '-' + id).length) {
216
+          jQuery('#jBox-image-' + gallery + '-' + id).addClass('jBox-image-' + gallery + '-current').css({zIndex: this.imageZIndex++, opacity: 0}).animate({opacity: 1}, (img == 'open') ? 0 : this.options.imageFade);
217
+
218
+        // Load image
219
+        } else {
220
+          loadImage(gallery, id, true, (img === 'open'));
221
+        }
222
+
223
+        // Show label
224
+        showLabel(gallery, id);
225
+
226
+        // Update the image counter numbers
227
+        if (this.imageCounter) {
228
+          if (this.images[gallery].length > 1) {
229
+            this.wrapper.addClass('jBox-image-has-counter');
230
+            this.imageCounter.find('.jBox-image-counter-all').html(this.images[gallery].length);
231
+            this.imageCounter.find('.jBox-image-counter-current').html(id + 1);
232
+          } else {
233
+            this.wrapper.removeClass('jBox-image-has-counter');
234
+          }
235
+        }
236
+
237
+        // Preload next image
238
+        if (this.images[gallery].length - 1) {
239
+	        var next_id = id + 1;
240
+	        next_id = next_id > (this.images[gallery].length - 1) ? 0 : (next_id < 0 ? (this.images[gallery].length - 1) : next_id);
241
+
242
+	        if (!jQuery('#jBox-image-' + gallery + '-' + next_id).length) {
243
+            loadImage(gallery, next_id, false, false);
244
+          }
245
+	      }
246
+      };
247
+
248
+      // Preload image
249
+      if (this.options.preloadFirstImage) {
250
+        jQuery(window).on('load', function() {
251
+          this.showImage('open');
252
+        }.bind(this));
253
+      }
254
+    },
255
+
256
+
257
+    // Triggered when jBox attaches a new element
258
+
259
+    _onAttach: function (item) {
260
+      this.initImage && this.initImage(item);
261
+    },
262
+
263
+
264
+    // Triggered when jBox was created
265
+
266
+    _onCreated: function ()
267
+    {
268
+      // Create image label and navigation buttons
269
+      this.imageLabelWrapper = jQuery('<div class="jBox-image-label-wrapper"/>').appendTo(this.wrapper);
270
+
271
+      this.imagePrevButton = jQuery('<div class="jBox-image-pointer-prev"/>')
272
+        .on('click tap', function () {
273
+          this.showImage('prev');
274
+        }.bind(this));
275
+
276
+      this.imageNextButton = jQuery('<div class="jBox-image-pointer-next"/>')
277
+        .on('click tap', function () {
278
+          this.showImage('next');
279
+        }.bind(this));
280
+
281
+      this.imageLabelContainer = jQuery('<div class="jBox-image-label-container"/>');
282
+
283
+      this.imageLabelWrapper
284
+        .append(this.imagePrevButton)
285
+        .append(this.imageLabelContainer)
286
+        .append(this.imageNextButton);
287
+
288
+      // Append the download button
289
+      if (this.options.downloadButton) {
290
+        this.downloadButton = jQuery('<div/>', {'class': 'jBox-image-download-button-wrapper'})
291
+          .appendTo(this.wrapper)
292
+          .append(
293
+            this.options.downloadButtonText ? jQuery('<div/>', {'class': 'jBox-image-download-button-text'}).html(this.options.downloadButtonText) : null
294
+          )
295
+          .append(
296
+            jQuery('<div/>', {'class': 'jBox-image-download-button-icon'})
297
+          ).on('click tap', function () {
298
+            if (this.images[this.currentImage.gallery][this.currentImage.id].downloadUrl) {
299
+              var currentImageUrl = this.images[this.currentImage.gallery][this.currentImage.id].downloadUrl;
300
+            } else {
301
+              var currentImage = this.wrapper.find('.jBox-image-' + this.currentImage.gallery + '-current');
302
+              var currentImageStyle = currentImage[0].style.backgroundImage;
303
+              var currentImageUrl = currentImageStyle.slice(4, -1).replace(/["']/g, '');
304
+            }
305
+            this.downloadImage(currentImageUrl);
306
+          }.bind(this));
307
+      }
308
+
309
+      // Creating the image counter containers
310
+      if (this.options.imageCounter) {
311
+        this.imageCounter = jQuery('<div/>', {'class': 'jBox-image-counter-container'}).insertAfter(this.imageLabelContainer);
312
+        this.imageCounter.append(jQuery('<span/>', {'class': 'jBox-image-counter-current'})).append(jQuery('<span/>').html(this.options.imageCounterSeparator)).append(jQuery('<span/>', {'class': 'jBox-image-counter-all'}));
313
+      }
314
+    },
315
+
316
+
317
+    // Triggered when jBox opens
318
+
319
+    _onOpen: function ()
320
+    {
321
+      // Add key events
322
+      jQuery(document).on('keyup.jBox-Image-' + this.id, function (ev) {
323
+        (ev.keyCode == 37) && this.showImage('prev');
324
+        (ev.keyCode == 39) && this.showImage('next');
325
+      }.bind(this));
326
+
327
+      // Load the image from the attached element
328
+      this.showImage('open');
329
+    },
330
+
331
+
332
+    // Triggered when jBox closes
333
+
334
+    _onClose: function ()
335
+    {
336
+      // Remove key events
337
+      jQuery(document).off('keyup.jBox-Image-' + this.id);
338
+    },
339
+
340
+
341
+    // Triggered when jBox finished closing
342
+
343
+    _onCloseComplete: function ()
344
+    {
345
+      // Hide all image containers
346
+      this.wrapper.find('.jBox-image-container').css('opacity', 0);
347
+    }
348
+
349
+  });
350
+
351
+};
0 352
new file mode 100644
... ...
@@ -0,0 +1,171 @@
1
+/**
2
+ * jBox Notice plugin: Opens a popup notice
3
+ *
4
+ * Author: Stephan Wagner <stephanwagner.me@gmail.com> (https://stephanwagner.me)
5
+ *
6
+ * License: MIT (https://opensource.org/licenses/MIT)
7
+ *
8
+ * Requires: jBox (https://cdn.jsdelivr.net/gh/StephanWagner/jBox@latest/dist/jBox.min.js)
9
+ */
10
+
11
+function jBoxNoticeWrapper(jBox, jQuery) {
12
+
13
+  new jBox.plugin('Notice', {
14
+
15
+
16
+    // Options (https://stephanwagner.me/jBox/options#options-notice)
17
+
18
+    color: null,      // Add a color to your notices, use 'gray' (default), 'black', 'red', 'green', 'blue' or 'yellow'
19
+    stack: true,      // Set to false to disable notice-stacking
20
+    stackSpacing: 10, // Spacing between notices when they stack
21
+    autoClose: 6000,  // Time in ms after which the notice will disappear
22
+    attributes: {     // Defines where the notice will pop up
23
+      x: 'right',     // 'left' or 'right'
24
+      y: 'top'        // 'top' or 'bottom'
25
+    },
26
+    position: {       // Defines the distance to the viewport boundary
27
+      x: 15,
28
+      y: 15
29
+    },
30
+    responsivePositions: {  // Responsive positions
31
+      500: {                // The key defines the maximum width of the viewport, the values will replace the default position options
32
+        x: 5,               // Start with the lowest viewport
33
+        y: 5
34
+      },
35
+      768: {
36
+        x: 10,
37
+        y: 10
38
+      }
39
+    },
40
+    target: window,
41
+    fixed: true,
42
+    animation: 'zoomIn',
43
+    closeOnClick: 'box',
44
+    zIndex: 12000,
45
+
46
+
47
+    // Triggered when notice is initialized
48
+
49
+    _onInit: function ()
50
+    {
51
+      // Cache position values
52
+      this.defaultNoticePosition = jQuery.extend({}, this.options.position);
53
+
54
+      // Type Notice has its own adjust position function
55
+      this._adjustNoticePositon = function () {
56
+        var win = jQuery(window);
57
+        var windowDimensions = {
58
+          x: win.width(),
59
+          y: win.height()
60
+        };
61
+
62
+        // Reset default position
63
+        this.options.position = jQuery.extend({}, this.defaultNoticePosition);
64
+
65
+        // Adjust depending on viewport
66
+        jQuery.each(this.options.responsivePositions, function (viewport, position) {
67
+          if (windowDimensions.x <= viewport) {
68
+            this.options.position = position;
69
+            return false;
70
+          }
71
+        }.bind(this));
72
+
73
+        // Set new padding options
74
+        this.options.adjustDistance = {
75
+          top: this.options.position.y,
76
+          right: this.options.position.x,
77
+          bottom: this.options.position.y,
78
+          left: this.options.position.x
79
+        };
80
+      };
81
+
82
+      // If jBox grabs an element as content, crab a clone instead
83
+      this.options.content instanceof jQuery && (this.options.content = this.options.content.clone().attr('id', ''));
84
+
85
+      // Adjust paddings when window resizes
86
+      jQuery(window).on('resize.responsivejBoxNotice-' + this.id, function (ev) { if (this.isOpen) { this._adjustNoticePositon(); } }.bind(this));
87
+
88
+      this.open();
89
+    },
90
+
91
+
92
+    // Triggered when notice was created
93
+
94
+    _onCreated: function ()
95
+    {
96
+      // Add color class
97
+      this.wrapper.addClass('jBox-Notice-color jBox-Notice-' + (this.options.color || 'gray'));
98
+
99
+      // Store position in jBox wrapper
100
+      this.wrapper.data('jBox-Notice-position', this.options.attributes.x + '-' + this.options.attributes.y);
101
+    },
102
+
103
+
104
+    // Triggered when notice opens
105
+
106
+    _onOpen: function ()
107
+    {
108
+      // Bail if we're stacking
109
+      if (this.options.stack) {
110
+          return;
111
+      }
112
+
113
+      // Adjust position when opening
114
+      this._adjustNoticePositon();
115
+
116
+      // Loop through notices at same window corner destroy them
117
+      jQuery.each(jQuery('.jBox-Notice'), function (index, el)
118
+      {
119
+        el = jQuery(el);
120
+
121
+        // Abort if the element is this notice or when it's not at the same position
122
+        if (el.attr('id') == this.id || el.data('jBox-Notice-position') != this.options.attributes.x + '-' + this.options.attributes.y) {
123
+          return;
124
+        }
125
+
126
+        // Remove notice when we don't wont to stack them
127
+        if (!this.options.stack) {
128
+          el.data('jBox').close({ignoreDelay: true});
129
+          return;
130
+        }
131
+      }.bind(this));
132
+    },
133
+
134
+    // Triggered when resizing window etc.
135
+
136
+    _onPosition: function ()
137
+    {
138
+        var stacks = {};
139
+        jQuery.each(jQuery('.jBox-Notice'), function (index, el)
140
+        {
141
+          el = jQuery(el);
142
+          var pos = el.data('jBox-Notice-position');
143
+          if (!stacks[pos]) {
144
+              stacks[pos] = [];
145
+          }
146
+          stacks[pos].push(el);
147
+        });
148
+        for (var pos in stacks) {
149
+            var position = pos.split('-');
150
+            var direction = position[1];
151
+            stacks[pos].reverse();
152
+            var margin = 0;
153
+            for (var i in stacks[pos]) {
154
+                var el = jQuery(stacks[pos][i]);
155
+                el.css('margin-' + direction, margin);
156
+                margin += el.outerHeight() + this.options.stackSpacing;
157
+            }
158
+        }
159
+    },
160
+
161
+    // Remove notice from DOM and reposition other notices when closing finishes
162
+
163
+    _onCloseComplete: function ()
164
+    {
165
+        this.destroy();
166
+        this.options._onPosition.bind(this).call();
167
+    }
168
+
169
+  });
170
+
171
+};
0 172
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+(function (root, factory) {
2
+  if (typeof define === 'function' && define.amd) {
3
+    define(['jquery'], function (jQuery) {
4
+      return (root.jBox = factory(jQuery));
5
+    });
6
+  } else if (typeof module === 'object' && module.exports) {
7
+    module.exports = (root.jBox = factory(require('jquery')));
8
+  } else {
9
+    root.jBox = factory(root.jQuery);
10
+  }
11
+}(this, function (jQuery) {
12
+  var jBox = jBoxWrapper(jQuery);
13
+  try { typeof jBoxConfirmWrapper !== 'undefined' && jBoxConfirmWrapper && jBoxConfirmWrapper(jBox, jQuery); } catch(e) { console.error(e); }
14
+  try { typeof jBoxImageWrapper !== 'undefined' && jBoxImageWrapper && jBoxImageWrapper(jBox, jQuery); } catch(e) { console.error(e); }
15
+  try { typeof jBoxNoticeWrapper !== 'undefined' && jBoxNoticeWrapper && jBoxNoticeWrapper(jBox, jQuery); } catch(e) { console.error(e); }
16
+  return jBox;
17
+}));
0 18
new file mode 100644
... ...
@@ -0,0 +1,670 @@
1
+// Global
2
+
3
+.jBox-wrapper {
4
+  text-align: left;
5
+  box-sizing: border-box;
6
+}
7
+
8
+.jBox-title,
9
+.jBox-content,
10
+.jBox-container {
11
+  position: relative;
12
+  word-break: break-word;
13
+  box-sizing: border-box;
14
+}
15
+
16
+.jBox-container {
17
+  background: #fff;
18
+}
19
+
20
+.jBox-content {
21
+  padding: 8px 12px;
22
+  overflow-x: hidden;
23
+  overflow-y: auto;
24
+  transition: opacity .2s;
25
+}
26
+
27
+.jBox-footer {
28
+  box-sizing: border-box;
29
+}
30
+
31
+// jBox Tooltip
32
+
33
+.jBox-Tooltip,
34
+.jBox-Mouse {
35
+  .jBox-container {
36
+    border-radius: 4px;
37
+    box-shadow: 0 0 3px rgba(0, 0, 0, .25);
38
+  }
39
+
40
+  .jBox-title {
41
+    padding: 8px 10px 0;
42
+    font-weight: bold;
43
+  }
44
+
45
+  &.jBox-hasTitle .jBox-content {
46
+    padding-top: 5px;
47
+  }
48
+}
49
+
50
+.jBox-Mouse {
51
+  pointer-events: none;
52
+}
53
+
54
+// Pointer
55
+
56
+.jBox-pointer {
57
+  position: absolute;
58
+  overflow: hidden;
59
+  box-sizing: border-box;
60
+
61
+  &:after {
62
+    content: '';
63
+    width: 20px;
64
+    height: 20px;
65
+    position: absolute;
66
+    background: #fff;
67
+    transform: rotate(45deg);
68
+    box-sizing: border-box;
69
+  }
70
+
71
+  &-top {
72
+    top: 0;
73
+
74
+    &:after {
75
+      left: 5px;
76
+      top: 6px;
77
+      box-shadow: -1px -1px 2px rgba(0, 0, 0, .15);
78
+    }
79
+  }
80
+
81
+  &-right {
82
+    right: 0;
83
+
84
+    &:after {
85
+      top: 5px;
86
+      right: 6px;
87
+      box-shadow: 1px -1px 2px rgba(0, 0, 0, .15);
88
+    }
89
+  }
90
+
91
+  &-left {
92
+    left: 0;
93
+
94
+    &:after {
95
+      top: 5px;
96
+      left: 6px;
97
+      box-shadow: -1px 1px 2px rgba(0, 0, 0, .15);
98
+    }
99
+  }
100
+
101
+  &-bottom {
102
+    bottom: 0;
103
+
104
+    &:after {
105
+      left: 5px;
106
+      bottom: 6px;
107
+      box-shadow: 1px 1px 2px rgba(0, 0, 0, .15);
108
+    }
109
+  }
110
+
111
+  &-top,
112
+  &-bottom {
113
+    width: 30px;
114
+    height: 12px;
115
+  }
116
+
117
+  &-left,
118
+  &-right {
119
+    width: 12px;
120
+    height: 30px;
121
+  }
122
+}
123
+
124
+// jBox Modal
125
+
126
+.jBox-Modal {
127
+  .jBox-container {
128
+    border-radius: 4px;
129
+  }
130
+
131
+  .jBox-container,
132
+  &.jBox-closeButton-box:before {
133
+    box-shadow: 0 3px 15px rgba(0, 0, 0, .4), 0 0 5px rgba(0, 0, 0, .4);
134
+  }
135
+
136
+  .jBox-content {
137
+    padding: 15px 20px;
138
+  }
139
+
140
+  .jBox-title {
141
+    border-radius: 4px 4px 0 0;
142
+    padding: 15px 20px;
143
+    background: #fafafa;
144
+    border-bottom: 1px solid #eee;
145
+  }
146
+
147
+  &.jBox-closeButton-title {
148
+    .jBox-title {
149
+      padding-right: 65px;
150
+    }
151
+  }
152
+
153
+  .jBox-footer {
154
+    border-radius: 0 0 4px 4px;
155
+  }
156
+}
157
+
158
+// Close button
159
+
160
+.jBox-closeButton {
161
+  z-index: 1;
162
+  cursor: pointer;
163
+  position: absolute;
164
+  box-sizing: border-box;
165
+
166
+  svg {
167
+    position: absolute;
168
+    top: 50%;
169
+    right: 50%;
170
+  }
171
+
172
+  path {
173
+    fill: #aaa;
174
+    transition: fill .2s;
175
+  }
176
+
177
+  &:hover {
178
+    path {
179
+      fill: #888;
180
+    }
181
+  }
182
+}
183
+
184
+// Close button in overlay
185
+
186
+.jBox-overlay {
187
+  .jBox-closeButton {
188
+    top: 0;
189
+    right: 0;
190
+    width: 40px;
191
+    height: 40px;
192
+
193
+    svg {
194
+      width: 20px;
195
+      height: 20px;
196
+      margin-top: -10px;
197
+      margin-right: -10px;
198
+    }
199
+
200
+    path {
201
+      fill: #ddd;
202
+    }
203
+
204
+    &:hover path {
205
+      fill: #fff;
206
+    }
207
+  }
208
+
209
+}
210
+
211
+// Close button in title
212
+
213
+.jBox-closeButton-title {
214
+  .jBox-closeButton {
215
+    top: 0;
216
+    right: 0;
217
+    bottom: 0;
218
+    width: 50px;
219
+  }
220
+
221
+  svg {
222
+    width: 12px;
223
+    height: 12px;
224
+    margin-top: -6px;
225
+    margin-right: -6px;
226
+  }
227
+}
228
+
229
+// Close button in box
230
+
231
+.jBox-closeButton-box {
232
+  box-sizing: border-box;
233
+
234
+  .jBox-closeButton {
235
+    top: -8px;
236
+    right: -10px;
237
+    width: 24px;
238
+    height: 24px;
239
+    background: #fff;
240
+    border-radius: 50%;
241
+
242
+    svg {
243
+      width: 10px;
244
+      height: 10px;
245
+      margin-top: -5px;
246
+      margin-right: -5px;
247
+    }
248
+  }
249
+
250
+  &:before {
251
+    content: '';
252
+    position: absolute;
253
+    top: -8px;
254
+    right: -10px;
255
+    width: 24px;
256
+    height: 24px;
257
+    border-radius: 50%;
258
+    box-shadow: 0 0 5px rgba(0, 0, 0, .3);
259
+  }
260
+
261
+  &.jBox-pointerPosition-top:before {
262
+    top: 5px;
263
+  }
264
+
265
+  &.jBox-pointerPosition-right:before {
266
+    right: 2px;
267
+  }
268
+}
269
+
270
+
271
+.jBox-Modal.jBox-hasTitle.jBox-closeButton-box .jBox-closeButton {
272
+  background: #fafafa;
273
+}
274
+
275
+// Overlay
276
+
277
+.jBox-overlay {
278
+  position: fixed;
279
+  top: 0;
280
+  left: 0;
281
+  width: 100%;
282
+  height: 100%;
283
+  background-color: rgba(0, 0, 0, .82);
284
+}
285
+
286
+// Footer
287
+
288
+.jBox-footer {
289
+  background: #fafafa;
290
+  border-top: 1px solid #eee;
291
+  padding: 8px 10px;
292
+  border-radius: 0 0 3px 3px;
293
+}
294
+
295
+// Block scrolling
296
+
297
+body[class^="jBox-blockScroll-"],
298
+body[class*=" jBox-blockScroll-"] {
299
+  overflow: hidden;
300
+}
301
+
302
+// Draggable
303
+
304
+.jBox-draggable {
305
+  cursor: move;
306
+}
307
+
308
+// Spinner
309
+
310
+@keyframes jBoxLoading {
311
+  to {
312
+    transform: rotate(360deg);
313
+  }
314
+}
315
+
316
+.jBox-loading .jBox-content {
317
+  opacity: .2;
318
+}
319
+
320
+.jBox-loading-spinner .jBox-content {
321
+  min-height: 38px !important;
322
+  min-width: 38px !important;
323
+  opacity: 0;
324
+}
325
+
326
+.jBox-spinner {
327
+  box-sizing: border-box;
328
+  position: absolute;
329
+  top: 50%;
330
+  left: 50%;
331
+  width: 24px;
332
+  height: 24px;
333
+  margin-top: -12px;
334
+  margin-left: -12px;
335
+
336
+  &:before {
337
+    display: block;
338
+    box-sizing: border-box;
339
+    content: '';
340
+    width: 24px;
341
+    height: 24px;
342
+    border-radius: 50%;
343
+    border: 2px solid rgba(0, 0, 0, .2);
344
+    border-top-color: rgba(0, 0, 0, .8);
345
+    animation: jBoxLoading .6s linear infinite;
346
+  }
347
+}
348
+
349
+// Countdown
350
+
351
+.jBox-countdown {
352
+  border-radius: 4px 4px 0 0;
353
+  z-index: 0;
354
+  background: #000;
355
+  opacity: .2;
356
+  position: absolute;
357
+  top: 0;
358
+  left: 0;
359
+  right: 0;
360
+  height: 3px;
361
+  overflow: hidden;
362
+
363
+  &-inner {
364
+    top: 0;
365
+    right: 0;
366
+    width: 100%;
367
+    height: 3px;
368
+    position: absolute;
369
+    background: #fff;
370
+  }
371
+}
372
+
373
+// Animations
374
+
375
+[class^="jBox-animated-"],
376
+[class*=" jBox-animated-"] {
377
+  animation-fill-mode: both;
378
+}
379
+
380
+// Animation tada
381
+
382
+@keyframes jBox-tada {
383
+  0% {
384
+    transform: scale(1);
385
+  }
386
+
387
+  10%,
388
+  20% {
389
+    transform: scale(0.8) rotate(-4deg);
390
+  }
391
+
392
+  30%,
393
+  50%,
394
+  70%,
395
+  90% {
396
+    transform: scale(1.2) rotate(4deg);
397
+  }
398
+
399
+  40%,
400
+  60%,
401
+  80% {
402
+    transform: scale(1.2) rotate(-4deg);
403
+  }
404
+
405
+  100% {
406
+    transform: scale(1) rotate(0);
407
+  }
408
+}
409
+
410
+.jBox-animated-tada {
411
+  animation: jBox-tada 1s;
412
+}
413
+
414
+// Animation tadaSmall
415
+
416
+@keyframes jBox-tadaSmall {
417
+  0% {
418
+    transform: scale(1);
419
+  }
420
+
421
+  10%,
422
+  20% {
423
+    transform: scale(0.9) rotate(-2deg);
424
+  }
425
+
426
+  30%,
427
+  50%,
428
+  70%,
429
+  90% {
430
+    transform: scale(1.1) rotate(2deg);
431
+  }
432
+
433
+  40%,
434
+  60%,
435
+  80% {
436
+    transform: scale(1.1) rotate(-2deg);
437
+  }
438
+
439
+  100% {
440
+    transform: scale(1) rotate(0);
441
+  }
442
+}
443
+
444
+.jBox-animated-tadaSmall {
445
+  animation: jBox-tadaSmall 1s;
446
+}
447
+
448
+// Animation flash
449
+
450
+@keyframes jBox-flash {
451
+
452
+  0%,
453
+  50%,
454
+  100% {
455
+    opacity: 1;
456
+  }
457
+
458
+  25%,
459
+  75% {
460
+    opacity: 0;
461
+  }
462
+}
463
+
464
+.jBox-animated-flash {
465
+  animation: jBox-flash .5s;
466
+}
467
+
468
+// Animation shake
469
+
470
+@keyframes jBox-shake {
471
+
472
+  0%,
473
+  100% {
474
+    transform: translateX(0);
475
+  }
476
+
477
+  20%,
478
+  60% {
479
+    transform: translateX(-6px);
480
+  }
481
+
482
+  40%,
483
+  80% {
484
+    transform: translateX(6px);
485
+  }
486
+}
487
+
488
+.jBox-animated-shake {
489
+  animation: jBox-shake .4s;
490
+}
491
+
492
+// Animation pulseUp
493
+
494
+@keyframes jBox-pulseUp {
495
+  0% {
496
+    transform: scale(1);
497
+  }
498
+
499
+  50% {
500
+    transform: scale(1.15);
501
+  }
502
+
503
+  100% {
504
+    transform: scale(1);
505
+  }
506
+}
507
+
508
+.jBox-animated-pulseUp {
509
+  animation: jBox-pulseUp .25s;
510
+}
511
+
512
+// Animation pulseDown
513
+
514
+@keyframes jBox-pulseDown {
515
+  0% {
516
+    transform: scale(1);
517
+  }
518
+
519
+  50% {
520
+    transform: scale(0.85);
521
+  }
522
+
523
+  100% {
524
+    transform: scale(1);
525
+  }
526
+}
527
+
528
+.jBox-animated-pulseDown {
529
+  animation: jBox-pulseDown .25s;
530
+}
531
+
532
+// Animation popIn
533
+
534
+@keyframes jBox-popIn {
535
+  0% {
536
+    transform: scale(0);
537
+  }
538
+
539
+  50% {
540
+    transform: scale(1.1);
541
+  }
542
+
543
+  100% {
544
+    transform: scale(1);
545
+  }
546
+}
547
+
548
+.jBox-animated-popIn {
549
+  animation: jBox-popIn .25s;
550
+}
551
+
552
+// Animation popOut
553
+
554
+@keyframes jBox-popOut {
555
+  0% {
556
+    transform: scale(1);
557
+  }
558
+
559
+  50% {
560
+    transform: scale(1.1);
561
+  }
562
+
563
+  100% {
564
+    transform: scale(0);
565
+  }
566
+}
567
+
568
+.jBox-animated-popOut {
569
+  animation: jBox-popOut .25s;
570
+}
571
+
572
+// Animation fadeIn
573
+
574
+@keyframes jBox-fadeIn {
575
+  0% {
576
+    opacity: 0;
577
+  }
578
+
579
+  100% {
580
+    opacity: 1;
581
+  }
582
+}
583
+
584
+.jBox-animated-fadeIn {
585
+  animation: jBox-fadeIn .2s;
586
+}
587
+
588
+// Animation fadeOut
589
+
590
+@keyframes jBox-fadeOut {
591
+  0% {
592
+    opacity: 1;
593
+  }
594
+
595
+  100% {
596
+    opacity: 0;
597
+  }
598
+}
599
+
600
+.jBox-animated-fadeOut {
601
+  animation: jBox-fadeOut .2s;
602
+}
603
+
604
+// Animation slideUp
605
+
606
+@keyframes jBox-slideUp {
607
+  0% {
608
+    transform: translateY(0);
609
+  }
610
+
611
+  100% {
612
+    transform: translateY(-300px);
613
+    opacity: 0;
614
+  }
615
+}
616
+
617
+.jBox-animated-slideUp {
618
+  animation: jBox-slideUp .4s;
619
+}
620
+
621
+// Animation slideRight
622
+
623
+@keyframes jBox-slideRight {
624
+  0% {
625
+    transform: translateX(0);
626
+  }
627
+
628
+  100% {
629
+    transform: translateX(300px);
630
+    opacity: 0;
631
+  }
632
+}
633
+
634
+.jBox-animated-slideRight {
635
+  animation: jBox-slideRight .4s;
636
+}
637
+
638
+// Animation slideDown
639
+
640
+@keyframes jBox-slideDown {
641
+  0% {
642
+    transform: translateY(0);
643
+  }
644
+
645
+  100% {
646
+    transform: translateY(300px);
647
+    opacity: 0;
648
+  }
649
+}
650
+
651
+.jBox-animated-slideDown {
652
+  animation: jBox-slideDown .4s;
653
+}
654
+
655
+// Animation slideLeft
656
+
657
+@keyframes jBox-slideLeft {
658
+  0% {
659
+    transform: translateX(0);
660
+  }
661
+
662
+  100% {
663
+    transform: translateX(-300px);
664
+    opacity: 0;
665
+  }
666
+}
667
+
668
+.jBox-animated-slideLeft {
669
+  animation: jBox-slideLeft .4s;
670
+}
0 671
new file mode 100644
... ...
@@ -0,0 +1,60 @@
1
+// jBox plugin: Confirm
2
+
3
+.jBox-Confirm {
4
+  .jBox-content {
5
+    text-align: center;
6
+    padding: 46px 35px;
7
+
8
+    @media (max-width: 500px) {
9
+      padding: 32px 20px;
10
+    }
11
+  }
12
+}
13
+
14
+.jBox-Confirm-footer {
15
+  height: 46px;
16
+}
17
+
18
+.jBox-Confirm-button {
19
+  display: block;
20
+  float: left;
21
+  cursor: pointer;
22
+  text-align: center;
23
+  width: 50%;
24
+  line-height: 46px;
25
+  height: 46px;
26
+  overflow: hidden;
27
+  padding: 0 10px;
28
+  transition: color .2s, background-color .2s;
29
+  box-sizing: border-box;
30
+
31
+  &-cancel {
32
+    border-bottom-left-radius: 4px;
33
+    background: #ddd;
34
+    color: #666;
35
+
36
+    &:hover,
37
+    &:active {
38
+      background: #ccc;
39
+    }
40
+
41
+    &:active {
42
+      box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);
43
+    }
44
+  }
45
+
46
+  &-submit {
47
+    border-bottom-right-radius: 4px;
48
+    background: #7d0;
49
+    color: #fff;
50
+
51
+    &:hover,
52
+    &:active {
53
+      background: #6c0;
54
+    }
55
+
56
+    &:active {
57
+      box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);
58
+    }
59
+  }
60
+}
0 61
new file mode 100644
... ...
@@ -0,0 +1,204 @@
1
+// jBox plugin: Image
2
+
3
+.jBox-Image {
4
+  .jBox-container {
5
+    background-color: transparent;
6
+  }
7
+
8
+  .jBox-content {
9
+    padding: 0;
10
+    width: 100%;
11
+    height: 100%;
12
+  }
13
+}
14
+
15
+.jBox-image-container {
16
+  background: center center no-repeat;
17
+  position: absolute;
18
+  width: 100%;
19
+  height: 100%;
20
+  opacity: 0;
21
+}
22
+
23
+.jBox-image-label-wrapper {
24
+  position: absolute;
25
+  top: 100%;
26
+  left: 0;
27
+  right: 0;
28
+  height: 40px;
29
+  z-index: 100;
30
+  display: flex;
31
+}
32
+
33
+.jBox-image-label-container {
34
+  position: relative;
35
+  flex: 1;
36
+}
37
+
38
+.jBox-image-label {
39
+  box-sizing: border-box;
40
+  position: absolute;
41
+  left: 0;
42
+  bottom: 0;
43
+  width: 100%;
44
+  text-align: center;
45
+  color: #fff;
46
+  padding: 8px 12px;
47
+  font-size: 15px;
48
+  line-height: 24px;
49
+  transition: opacity .36s;
50
+  opacity: 0;
51
+  z-index: 0;
52
+  pointer-events: none;
53
+
54
+  &.expanded {
55
+    background: #000;
56
+  }
57
+
58
+  &:not(.expanded) {
59
+    text-overflow: ellipsis;
60
+    white-space: nowrap;
61
+    overflow: hidden;
62
+  }
63
+
64
+  &.active {
65
+    opacity: 1;
66
+    pointer-events: all;
67
+  }
68
+
69
+  @media (max-width: 600px) {
70
+    font-size: 13px;
71
+  }
72
+}
73
+
74
+.jBox-image-pointer-next,
75
+.jBox-image-pointer-prev {
76
+  flex-shrink: 0;
77
+  width: 40px;
78
+  height: 40px;
79
+  cursor: pointer;
80
+  opacity: .8;
81
+  transition: opacity .2s;
82
+  background: no-repeat center center url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ijc0LjcgMjI0IDE4LjcgMzIiPg0KPHBhdGggZmlsbD0iI2ZmZmZmZiIgZD0iTTkzLDIyNy40TDgwLjQsMjQwTDkzLDI1Mi42YzAuNCwwLjQsMC40LDEuMSwwLDEuNWwtMS42LDEuNmMtMC40LDAuNC0xLDAuNS0xLjUsMEw3NSwyNDAuN2MtMC40LTAuNC0wLjUtMSwwLTEuNWwxNC45LTE0LjljMC40LTAuNCwxLTAuNCwxLjUsMGwxLjYsMS42QzkzLjUsMjI2LjQsOTMuNCwyMjcsOTMsMjI3LjR6Ii8+DQo8L3N2Zz4=);
83
+  background-size: 11px auto;
84
+  user-select: none;
85
+  z-index: 1;
86
+
87
+  &:hover {
88
+    opacity: 1;
89
+  }
90
+}
91
+
92
+.jBox-image-pointer-next {
93
+  transform: scaleX(-1);
94
+}
95
+
96
+.jBox-image-counter-container {
97
+  flex-shrink: 0;
98
+  white-space: nowrap;
99
+  height: 40px;
100
+  line-height: 40px;
101
+  font-size: 13px;
102
+  color: #fff;
103
+  text-align: right;
104
+  display: none;
105
+}
106
+
107
+.jBox-image-has-counter .jBox-image-counter-container {
108
+  display: block;
109
+}
110
+
111
+.jBox-overlay.jBox-overlay-Image {
112
+  background: #000;
113
+}
114
+
115
+.jBox-image-not-found {
116
+  background: #000;
117
+
118
+  &:before {
119
+    content: '';
120
+    box-sizing: border-box;
121
+    display: block;
122
+    width: 80px;
123
+    height: 80px;
124
+    margin-top: -40px;
125
+    margin-left: -40px;
126
+    position: absolute;
127
+    top: 50%;
128
+    left: 50%;
129
+    border: 5px solid #222;
130
+    border-radius: 50%;
131
+  }
132
+
133
+  &:after {
134
+    content: '';
135
+    display: block;
136
+    box-sizing: content-box;
137
+    z-index: auto;
138
+    width: 6px;
139
+    height: 74px;
140
+    margin-top: -37px;
141
+    margin-left: -3px;
142
+    position: absolute;
143
+    top: 50%;
144
+    left: 50%;
145
+    background: #222;
146
+    transform: rotateZ(45deg);
147
+    transform-origin: 50% 50% 0;
148
+  }
149
+}
150
+
151
+// Download button
152
+
153
+.jBox-image-download-button-wrapper {
154
+  position: absolute;
155
+  top: -40px;
156
+  right: 35px;
157
+  height: 40px;
158
+  display: flex;
159
+  cursor: pointer;
160
+  opacity: .8;
161
+  transition: opacity .2s;
162
+
163
+  &:hover {
164
+    opacity: 1;
165
+  }
166
+}
167
+
168
+.jBox-image-download-button-icon {
169
+  width: 40px;
170
+  height: 40px;
171
+  background: center center no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNjQwIj48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNNDE2IDI1NnYtMTkyaC0xOTJ2MTkyaC0xNjBsMjU2IDI1NiAyNTYtMjU2aC0xNjB6TTAgNTc2aDY0MHY2NGgtNjQwdi02NHoiPjwvcGF0aD48L3N2Zz4=);
172
+  background-size: 60%;
173
+}
174
+
175
+.jBox-image-download-button-text {
176
+  white-space: nowrap;
177
+  line-height: 40px;
178
+  padding: 0 10px 0 0;
179
+  color: #fff;
180
+  font-size: 14px;
181
+}
182
+
183
+// Image spinner
184
+
185
+@keyframes jBoxImageLoading {
186
+  to {
187
+    transform: rotate(360deg);
188
+  }
189
+}
190
+
191
+.jBox-image-loading:before {
192
+  content: '';
193
+  position: absolute;
194
+  top: 50%;
195
+  left: 50%;
196
+  width: 32px;
197
+  height: 32px;
198
+  margin-top: -16px;
199
+  margin-left: -16px;
200
+  border: 4px solid #333;
201
+  border-bottom-color: #666;
202
+  animation: jBoxImageLoading 1.2s linear infinite;
203
+  border-radius: 50%;
204
+}
0 205
new file mode 100644
... ...
@@ -0,0 +1,148 @@
1
+// jBox plugin: Notice
2
+
3
+.jBox-Notice {
4
+  transition: margin .2s;
5
+
6
+  .jBox-container {
7
+    border-radius: 4px;
8
+    box-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, .25), inset -1px -1px 0 0 rgba(0, 0, 0, .1);
9
+  }
10
+
11
+  .jBox-content {
12
+    border-radius: 4px;
13
+    padding: 12px 20px;
14
+
15
+    @media (max-width: 768px) {
16
+      padding: 10px 15px;
17
+    }
18
+
19
+    @media (max-width: 500px) {
20
+      padding: 8px 10px;
21
+    }
22
+  }
23
+
24
+  &.jBox-hasTitle {
25
+    .jBox-content {
26
+      padding-top: 5px;
27
+
28
+      @media (max-width: 500px) {
29
+        padding-top: 0;
30
+      }
31
+    }
32
+
33
+    .jBox-title {
34
+      padding: 12px 20px 0;
35
+      font-weight: bold;
36
+
37
+      @media (max-width: 768px) {
38
+        padding: 10px 15px 0;
39
+      }
40
+
41
+      @media (max-width: 500px) {
42
+        padding: 8px 10px 0;
43
+      }
44
+    }
45
+  }
46
+
47
+  &.jBox-closeButton-title {
48
+    .jBox-title {
49
+      padding-right: 55px;
50
+    }
51
+
52
+    &.jBox-hasTitle {
53
+      .jBox-closeButton {
54
+        width: 40px;
55
+      }
56
+    }
57
+  }
58
+
59
+  &.jBox-Notice-black {
60
+    .jBox-container {
61
+      color: #fff;
62
+      background: #000;
63
+    }
64
+
65
+    &.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton {
66
+
67
+      path,
68
+      &:hover path {
69
+        fill: #fff;
70
+      }
71
+    }
72
+  }
73
+
74
+  &.jBox-Notice-gray {
75
+    .jBox-container {
76
+      color: #222;
77
+      background: #f6f6f6;
78
+    }
79
+
80
+    &.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton {
81
+
82
+      path,
83
+      &:hover path {
84
+        fill: #222;
85
+      }
86
+    }
87
+  }
88
+
89
+  &.jBox-Notice-red {
90
+    .jBox-container {
91
+      color: #fff;
92
+      background: #d00;
93
+    }
94
+
95
+    &.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton {
96
+
97
+      path,
98
+      &:hover path {
99
+        fill: #fff;
100
+      }
101
+    }
102
+  }
103
+
104
+  &.jBox-Notice-green {
105
+    .jBox-container {
106
+      color: #fff;
107
+      background: #5d0;
108
+    }
109
+
110
+    &.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton {
111
+
112
+      path,
113
+      &:hover path {
114
+        fill: #fff;
115
+      }
116
+    }
117
+  }
118
+
119
+  &.jBox-Notice-blue {
120
+    .jBox-container {
121
+      color: #fff;
122
+      background: #49d;
123
+    }
124
+
125
+    &.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton {
126
+
127
+      path,
128
+      &:hover path {
129
+        fill: #fff;
130
+      }
131
+    }
132
+  }
133
+
134
+  &.jBox-Notice-yellow {
135
+    .jBox-container {
136
+      color: #000;
137
+      background: #fd0;
138
+    }
139
+
140
+    &.jBox-closeButton-title.jBox-hasTitle .jBox-closeButton {
141
+
142
+      path,
143
+      &:hover path {
144
+        fill: #fff;
145
+      }
146
+    }
147
+  }
148
+}
0 149
new file mode 100644
... ...
@@ -0,0 +1,52 @@
1
+// jBox theme: NoticeFancy
2
+
3
+.jBox-NoticeFancy {
4
+
5
+  .jBox-content,
6
+  .jBox-title {
7
+    padding-left: 25px;
8
+  }
9
+
10
+  &.jBox-Notice-color .jBox-container {
11
+    color: #fff;
12
+    background: #000;
13
+
14
+    &:after {
15
+      content: '';
16
+      position: absolute;
17
+      top: 0;
18
+      left: 0;
19
+      bottom: 0;
20
+      width: 8px;
21
+      border-radius: 4px 0 0 4px;
22
+      background-image: linear-gradient(45deg, rgba(255, 255, 255, .4) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .4) 50%, rgba(255, 255, 255, .4) 75%, transparent 75%, transparent);
23
+      background-size: 14px 14px;
24
+    }
25
+  }
26
+
27
+  &.jBox-Notice-black .jBox-container:after,
28
+  &.jBox-Notice-gray .jBox-container:after {
29
+    background-color: #888;
30
+  }
31
+
32
+  &.jBox-Notice-red .jBox-container:after {
33
+    background-color: #e00;
34
+  }
35
+
36
+  &.jBox-Notice-green .jBox-container:after {
37
+    background-color: #6c0;
38
+  }
39
+
40
+  &.jBox-Notice-blue .jBox-container:after {
41
+    background-color: #49d;
42
+  }
43
+
44
+  &.jBox-Notice-yellow .jBox-container:after {
45
+    background-color: #fb0;
46
+  }
47
+
48
+  .jBox-countdown {
49
+    left: 8px;
50
+    border-radius: 0 4px 0 0;
51
+  }
52
+}
0 53
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+// jBox theme: TooltipBorder
2
+
3
+.jBox-TooltipBorder {
4
+  .jBox-container,
5
+  .jBox-pointer:after {
6
+    border: 2px solid #49d;
7
+  }
8
+
9
+  .jBox-pointer:after {
10
+    width: 22px;
11
+    height: 22px;
12
+  }
13
+
14
+  .jBox-pointer-top,
15
+  .jBox-pointer-bottom {
16
+    width: 34px;
17
+    height: 13px;
18
+
19
+    &:after {
20
+      left: 6px;
21
+    }
22
+  }
23
+
24
+  .jBox-pointer-left,
25
+  .jBox-pointer-right {
26
+    width: 13px;
27
+    height: 34px;
28
+
29
+    &:after {
30
+      top: 6px;
31
+    }
32
+  }
33
+
34
+  &.jBox-closeButton-box:before {
35
+    width: 28px;
36
+    height: 28px;
37
+    background: #49d;
38
+  }
39
+}
0 40
new file mode 100644
... ...
@@ -0,0 +1,34 @@
1
+// jBox theme: TooltipBorderThick
2
+
3
+.jBox-TooltipBorderThick {
4
+  .jBox-container {
5
+    box-shadow: none;
6
+    border-radius: 8px;
7
+    border: 4px solid #ccc;
8
+  }
9
+
10
+  .jBox-pointer:after {
11
+    box-shadow: none;
12
+    border: 4px solid #ccc;
13
+    width: 24px;
14
+    height: 24px;
15
+  }
16
+
17
+  .jBox-pointer-top,
18
+  .jBox-pointer-bottom {
19
+    width: 38px;
20
+    height: 13px;
21
+  }
22
+
23
+  .jBox-pointer-left,
24
+  .jBox-pointer-right {
25
+    width: 13px;
26
+    height: 38px;
27
+  }
28
+
29
+  &.jBox-closeButton-box:before {
30
+    width: 32px;
31
+    height: 32px;
32
+    background: #ccc;
33
+  }
34
+}
0 35
new file mode 100644
... ...
@@ -0,0 +1,38 @@
1
+// jBox theme: TooltipDark
2
+
3
+.jBox-TooltipDark {
4
+  .jBox-container {
5
+    border-radius: 4px;
6
+    background: #000;
7
+    color: #fff;
8
+    box-shadow: 0 0 6px rgba(0, 0, 0, .4);
9
+  }
10
+
11
+  .jBox-pointer:after {
12
+    background: #000;
13
+  }
14
+
15
+  .jBox-closeButton {
16
+    background: #000;
17
+  }
18
+
19
+  &.jBox-closeButton-box {
20
+    &:before {
21
+      box-shadow: 0 0 6px rgba(0, 0, 0, .4);
22
+    }
23
+
24
+    .jBox-closeButton {
25
+      path {
26
+        fill: #ddd;
27
+      }
28
+
29
+      &:hover path {
30
+        fill: #fff;
31
+      }
32
+
33
+      &:active path {
34
+        fill: #bbb;
35
+      }
36
+    }
37
+  }
38
+}
0 39
new file mode 100644
... ...
@@ -0,0 +1,58 @@
1
+// jBox theme: TooltipError
2
+
3
+.jBox-TooltipError {
4
+  pointer-events: none;
5
+
6
+  .jBox-container {
7
+    border-radius: 2px;
8
+    background: #d00;
9
+    color: #fff;
10
+    font-weight: bold;
11
+    font-size: 13px;
12
+  }
13
+
14
+  .jBox-content {
15
+    padding: 0 10px;
16
+    line-height: 28px;
17
+  }
18
+
19
+  .jBox-pointer {
20
+    &:after {
21
+      background: #d00;
22
+      width: 20px;
23
+      height: 20px;
24
+    }
25
+
26
+    &-top,
27
+    &-bottom {
28
+      width: 22px;
29
+      height: 8px;
30
+    }
31
+
32
+    &-right,
33
+    &-left {
34
+      width: 8px;
35
+      height: 22px;
36
+    }
37
+
38
+    &-top:after {
39
+      left: 1px;
40
+      top: 6px;
41
+    }
42
+
43
+    &-right:after {
44
+      top: 1px;
45
+      right: 6px;
46
+    }
47
+
48
+    &-bottom:after {
49
+      left: 1px;
50
+      bottom: 6px;
51
+    }
52
+
53
+    &-left:after {
54
+      top: 1px;
55
+      left: 6px;
56
+    }
57
+  }
58
+}
0 59
new file mode 100644
... ...
@@ -0,0 +1,53 @@
1
+// Box theme: TooltipSmall
2
+
3
+.jBox-TooltipSmall {
4
+  pointer-events: none;
5
+
6
+  .jBox-container {
7
+    border-radius: 2px;
8
+  }
9
+
10
+  .jBox-content {
11
+    padding: 0 10px;
12
+    line-height: 28px;
13
+  }
14
+
15
+  .jBox-pointer {
16
+    &:after {
17
+      width: 20px;
18
+      height: 20px;
19
+    }
20
+
21
+    &-top,
22
+    &-bottom {
23
+      width: 22px;
24
+      height: 8px;
25
+    }
26
+
27
+    &-right,
28
+    &-left {
29
+      width: 8px;
30
+      height: 22px;
31
+    }
32
+
33
+    &-top:after {
34
+      left: 1px;
35
+      top: 6px;
36
+    }
37
+
38
+    &-right:after {
39
+      top: 1px;
40
+      right: 6px;
41
+    }
42
+
43
+    &-bottom:after {
44
+      left: 1px;
45
+      bottom: 6px;
46
+    }
47
+
48
+    &-left:after {
49
+      top: 1px;
50
+      left: 6px;
51
+    }
52
+  }
53
+}
0 54
new file mode 100644
... ...
@@ -0,0 +1,57 @@
1
+// jBox theme: TooltipSmallGray
2
+
3
+.jBox-TooltipSmallGray {
4
+  pointer-events: none;
5
+
6
+  .jBox-container {
7
+    font-size: 13px;
8
+    line-height: 24px;
9
+    border-radius: 12px;
10
+    background-image: linear-gradient(to bottom, #fafafa, #f2f2f2);
11
+  }
12
+
13
+  .jBox-content {
14
+    padding: 0 10px;
15
+  }
16
+
17
+  .jBox-pointer {
18
+    &:after {
19
+      width: 20px;
20
+      height: 20px;
21
+    }
22
+
23
+    &-top,
24
+    &-bottom {
25
+      width: 22px;
26
+      height: 8px;
27
+    }
28
+
29
+    &-left,
30
+    &-right {
31
+      width: 8px;
32
+      height: 22px;
33
+    }
34
+
35
+    &-top:after {
36
+      background: #fafafa;
37
+      left: 1px;
38
+      top: 6px;
39
+    }
40
+
41
+    &-right:after {
42
+      top: 1px;
43
+      right: 6px;
44
+    }
45
+
46
+    &-bottom:after {
47
+      background: #f2f2f2;
48
+      left: 1px;
49
+      bottom: 6px;
50
+    }
51
+
52
+    &-left:after {
53
+      top: 1px;
54
+      left: 6px;
55
+    }
56
+  }
57
+}
0 58
new file mode 100644
... ...
@@ -0,0 +1,49 @@
1
+.jBox-NoticeFancy .jBox-content,
2
+.jBox-NoticeFancy .jBox-title {
3
+  padding-left: 25px;
4
+}
5
+
6
+.jBox-NoticeFancy.jBox-Notice-color .jBox-container {
7
+  color: #fff;
8
+  background: #000;
9
+}
10
+
11
+.jBox-NoticeFancy.jBox-Notice-color .jBox-container:after {
12
+  content: '';
13
+  position: absolute;
14
+  top: 0;
15
+  left: 0;
16
+  bottom: 0;
17
+  width: 8px;
18
+  border-radius: 4px 0 0 4px;
19
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.4) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.4) 75%, transparent 75%, transparent);
20
+  background-size: 14px 14px;
21
+}
22
+
23
+.jBox-NoticeFancy.jBox-Notice-black .jBox-container:after,
24
+.jBox-NoticeFancy.jBox-Notice-gray .jBox-container:after {
25
+  background-color: #888;
26
+}
27
+
28
+.jBox-NoticeFancy.jBox-Notice-red .jBox-container:after {
29
+  background-color: #e00;
30
+}
31
+
32
+.jBox-NoticeFancy.jBox-Notice-green .jBox-container:after {
33
+  background-color: #6c0;
34
+}
35
+
36
+.jBox-NoticeFancy.jBox-Notice-blue .jBox-container:after {
37
+  background-color: #49d;
38
+}
39
+
40
+.jBox-NoticeFancy.jBox-Notice-yellow .jBox-container:after {
41
+  background-color: #fb0;
42
+}
43
+
44
+.jBox-NoticeFancy .jBox-countdown {
45
+  left: 8px;
46
+  border-radius: 0 4px 0 0;
47
+}
48
+
49
+/*# sourceMappingURL=jBox.NoticeFancy.css.map */
0 50
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-NoticeFancy .jBox-content,.jBox-NoticeFancy .jBox-title{padding-left:25px}.jBox-NoticeFancy.jBox-Notice-color .jBox-container{color:#fff;background:#000}.jBox-NoticeFancy.jBox-Notice-color .jBox-container:after{content:'';position:absolute;top:0;left:0;bottom:0;width:8px;border-radius:4px 0 0 4px;background-image:linear-gradient(45deg,rgba(255,255,255,.4) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.4) 75%,transparent 75%,transparent);background-size:14px 14px}.jBox-NoticeFancy.jBox-Notice-black .jBox-container:after,.jBox-NoticeFancy.jBox-Notice-gray .jBox-container:after{background-color:#888}.jBox-NoticeFancy.jBox-Notice-red .jBox-container:after{background-color:#e00}.jBox-NoticeFancy.jBox-Notice-green .jBox-container:after{background-color:#6c0}.jBox-NoticeFancy.jBox-Notice-blue .jBox-container:after{background-color:#49d}.jBox-NoticeFancy.jBox-Notice-yellow .jBox-container:after{background-color:#fb0}.jBox-NoticeFancy .jBox-countdown{left:8px;border-radius:0 4px 0 0}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+.jBox-TooltipBorder .jBox-container,
2
+.jBox-TooltipBorder .jBox-pointer:after {
3
+  border: 2px solid #49d;
4
+}
5
+
6
+.jBox-TooltipBorder .jBox-pointer:after {
7
+  width: 22px;
8
+  height: 22px;
9
+}
10
+
11
+.jBox-TooltipBorder .jBox-pointer-top,
12
+.jBox-TooltipBorder .jBox-pointer-bottom {
13
+  width: 34px;
14
+  height: 13px;
15
+}
16
+
17
+.jBox-TooltipBorder .jBox-pointer-top:after,
18
+.jBox-TooltipBorder .jBox-pointer-bottom:after {
19
+  left: 6px;
20
+}
21
+
22
+.jBox-TooltipBorder .jBox-pointer-left,
23
+.jBox-TooltipBorder .jBox-pointer-right {
24
+  width: 13px;
25
+  height: 34px;
26
+}
27
+
28
+.jBox-TooltipBorder .jBox-pointer-left:after,
29
+.jBox-TooltipBorder .jBox-pointer-right:after {
30
+  top: 6px;
31
+}
32
+
33
+.jBox-TooltipBorder.jBox-closeButton-box:before {
34
+  width: 28px;
35
+  height: 28px;
36
+  background: #49d;
37
+}
38
+
39
+/*# sourceMappingURL=jBox.TooltipBorder.css.map */
0 40
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-TooltipBorder .jBox-container,.jBox-TooltipBorder .jBox-pointer:after{border:2px solid #49d}.jBox-TooltipBorder .jBox-pointer:after{width:22px;height:22px}.jBox-TooltipBorder .jBox-pointer-bottom,.jBox-TooltipBorder .jBox-pointer-top{width:34px;height:13px}.jBox-TooltipBorder .jBox-pointer-bottom:after,.jBox-TooltipBorder .jBox-pointer-top:after{left:6px}.jBox-TooltipBorder .jBox-pointer-left,.jBox-TooltipBorder .jBox-pointer-right{width:13px;height:34px}.jBox-TooltipBorder .jBox-pointer-left:after,.jBox-TooltipBorder .jBox-pointer-right:after{top:6px}.jBox-TooltipBorder.jBox-closeButton-box:before{width:28px;height:28px;background:#49d}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,32 @@
1
+.jBox-TooltipBorderThick .jBox-container {
2
+  box-shadow: none;
3
+  border-radius: 8px;
4
+  border: 4px solid #ccc;
5
+}
6
+
7
+.jBox-TooltipBorderThick .jBox-pointer:after {
8
+  box-shadow: none;
9
+  border: 4px solid #ccc;
10
+  width: 24px;
11
+  height: 24px;
12
+}
13
+
14
+.jBox-TooltipBorderThick .jBox-pointer-top,
15
+.jBox-TooltipBorderThick .jBox-pointer-bottom {
16
+  width: 38px;
17
+  height: 13px;
18
+}
19
+
20
+.jBox-TooltipBorderThick .jBox-pointer-left,
21
+.jBox-TooltipBorderThick .jBox-pointer-right {
22
+  width: 13px;
23
+  height: 38px;
24
+}
25
+
26
+.jBox-TooltipBorderThick.jBox-closeButton-box:before {
27
+  width: 32px;
28
+  height: 32px;
29
+  background: #ccc;
30
+}
31
+
32
+/*# sourceMappingURL=jBox.TooltipBorderThick.css.map */
0 33
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-TooltipBorderThick .jBox-container{box-shadow:none;border-radius:8px;border:4px solid #ccc}.jBox-TooltipBorderThick .jBox-pointer:after{box-shadow:none;border:4px solid #ccc;width:24px;height:24px}.jBox-TooltipBorderThick .jBox-pointer-bottom,.jBox-TooltipBorderThick .jBox-pointer-top{width:38px;height:13px}.jBox-TooltipBorderThick .jBox-pointer-left,.jBox-TooltipBorderThick .jBox-pointer-right{width:13px;height:38px}.jBox-TooltipBorderThick.jBox-closeButton-box:before{width:32px;height:32px;background:#ccc}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,32 @@
1
+.jBox-TooltipDark .jBox-container {
2
+  border-radius: 4px;
3
+  background: #000;
4
+  color: #fff;
5
+  box-shadow: 0 0 6px rgba(0, 0, 0, 0.4);
6
+}
7
+
8
+.jBox-TooltipDark .jBox-pointer:after {
9
+  background: #000;
10
+}
11
+
12
+.jBox-TooltipDark .jBox-closeButton {
13
+  background: #000;
14
+}
15
+
16
+.jBox-TooltipDark.jBox-closeButton-box:before {
17
+  box-shadow: 0 0 6px rgba(0, 0, 0, 0.4);
18
+}
19
+
20
+.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton path {
21
+  fill: #ddd;
22
+}
23
+
24
+.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:hover path {
25
+  fill: #fff;
26
+}
27
+
28
+.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:active path {
29
+  fill: #bbb;
30
+}
31
+
32
+/*# sourceMappingURL=jBox.TooltipDark.css.map */
0 33
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-TooltipDark .jBox-container{border-radius:4px;background:#000;color:#fff;box-shadow:0 0 6px rgba(0,0,0,.4)}.jBox-TooltipDark .jBox-pointer:after{background:#000}.jBox-TooltipDark .jBox-closeButton{background:#000}.jBox-TooltipDark.jBox-closeButton-box:before{box-shadow:0 0 6px rgba(0,0,0,.4)}.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton path{fill:#ddd}.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:hover path{fill:#fff}.jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:active path{fill:#bbb}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,54 @@
1
+.jBox-TooltipError {
2
+  pointer-events: none;
3
+}
4
+
5
+.jBox-TooltipError .jBox-container {
6
+  border-radius: 2px;
7
+  background: #d00;
8
+  color: #fff;
9
+  font-weight: bold;
10
+  font-size: 13px;
11
+}
12
+
13
+.jBox-TooltipError .jBox-content {
14
+  padding: 0 10px;
15
+  line-height: 28px;
16
+}
17
+
18
+.jBox-TooltipError .jBox-pointer:after {
19
+  background: #d00;
20
+  width: 20px;
21
+  height: 20px;
22
+}
23
+
24
+.jBox-TooltipError .jBox-pointer-top, .jBox-TooltipError .jBox-pointer-bottom {
25
+  width: 22px;
26
+  height: 8px;
27
+}
28
+
29
+.jBox-TooltipError .jBox-pointer-right, .jBox-TooltipError .jBox-pointer-left {
30
+  width: 8px;
31
+  height: 22px;
32
+}
33
+
34
+.jBox-TooltipError .jBox-pointer-top:after {
35
+  left: 1px;
36
+  top: 6px;
37
+}
38
+
39
+.jBox-TooltipError .jBox-pointer-right:after {
40
+  top: 1px;
41
+  right: 6px;
42
+}
43
+
44
+.jBox-TooltipError .jBox-pointer-bottom:after {
45
+  left: 1px;
46
+  bottom: 6px;
47
+}
48
+
49
+.jBox-TooltipError .jBox-pointer-left:after {
50
+  top: 1px;
51
+  left: 6px;
52
+}
53
+
54
+/*# sourceMappingURL=jBox.TooltipError.css.map */
0 55
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-TooltipError{pointer-events:none}.jBox-TooltipError .jBox-container{border-radius:2px;background:#d00;color:#fff;font-weight:700;font-size:13px}.jBox-TooltipError .jBox-content{padding:0 10px;line-height:28px}.jBox-TooltipError .jBox-pointer:after{background:#d00;width:20px;height:20px}.jBox-TooltipError .jBox-pointer-bottom,.jBox-TooltipError .jBox-pointer-top{width:22px;height:8px}.jBox-TooltipError .jBox-pointer-left,.jBox-TooltipError .jBox-pointer-right{width:8px;height:22px}.jBox-TooltipError .jBox-pointer-top:after{left:1px;top:6px}.jBox-TooltipError .jBox-pointer-right:after{top:1px;right:6px}.jBox-TooltipError .jBox-pointer-bottom:after{left:1px;bottom:6px}.jBox-TooltipError .jBox-pointer-left:after{top:1px;left:6px}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,49 @@
1
+.jBox-TooltipSmall {
2
+  pointer-events: none;
3
+}
4
+
5
+.jBox-TooltipSmall .jBox-container {
6
+  border-radius: 2px;
7
+}
8
+
9
+.jBox-TooltipSmall .jBox-content {
10
+  padding: 0 10px;
11
+  line-height: 28px;
12
+}
13
+
14
+.jBox-TooltipSmall .jBox-pointer:after {
15
+  width: 20px;
16
+  height: 20px;
17
+}
18
+
19
+.jBox-TooltipSmall .jBox-pointer-top, .jBox-TooltipSmall .jBox-pointer-bottom {
20
+  width: 22px;
21
+  height: 8px;
22
+}
23
+
24
+.jBox-TooltipSmall .jBox-pointer-right, .jBox-TooltipSmall .jBox-pointer-left {
25
+  width: 8px;
26
+  height: 22px;
27
+}
28
+
29
+.jBox-TooltipSmall .jBox-pointer-top:after {
30
+  left: 1px;
31
+  top: 6px;
32
+}
33
+
34
+.jBox-TooltipSmall .jBox-pointer-right:after {
35
+  top: 1px;
36
+  right: 6px;
37
+}
38
+
39
+.jBox-TooltipSmall .jBox-pointer-bottom:after {
40
+  left: 1px;
41
+  bottom: 6px;
42
+}
43
+
44
+.jBox-TooltipSmall .jBox-pointer-left:after {
45
+  top: 1px;
46
+  left: 6px;
47
+}
48
+
49
+/*# sourceMappingURL=jBox.TooltipSmall.css.map */
0 50
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-TooltipSmall{pointer-events:none}.jBox-TooltipSmall .jBox-container{border-radius:2px}.jBox-TooltipSmall .jBox-content{padding:0 10px;line-height:28px}.jBox-TooltipSmall .jBox-pointer:after{width:20px;height:20px}.jBox-TooltipSmall .jBox-pointer-bottom,.jBox-TooltipSmall .jBox-pointer-top{width:22px;height:8px}.jBox-TooltipSmall .jBox-pointer-left,.jBox-TooltipSmall .jBox-pointer-right{width:8px;height:22px}.jBox-TooltipSmall .jBox-pointer-top:after{left:1px;top:6px}.jBox-TooltipSmall .jBox-pointer-right:after{top:1px;right:6px}.jBox-TooltipSmall .jBox-pointer-bottom:after{left:1px;bottom:6px}.jBox-TooltipSmall .jBox-pointer-left:after{top:1px;left:6px}
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,53 @@
1
+.jBox-TooltipSmallGray {
2
+  pointer-events: none;
3
+}
4
+
5
+.jBox-TooltipSmallGray .jBox-container {
6
+  font-size: 13px;
7
+  line-height: 24px;
8
+  border-radius: 12px;
9
+  background-image: linear-gradient(to bottom, #fafafa, #f2f2f2);
10
+}
11
+
12
+.jBox-TooltipSmallGray .jBox-content {
13
+  padding: 0 10px;
14
+}
15
+
16
+.jBox-TooltipSmallGray .jBox-pointer:after {
17
+  width: 20px;
18
+  height: 20px;
19
+}
20
+
21
+.jBox-TooltipSmallGray .jBox-pointer-top, .jBox-TooltipSmallGray .jBox-pointer-bottom {
22
+  width: 22px;
23
+  height: 8px;
24
+}
25
+
26
+.jBox-TooltipSmallGray .jBox-pointer-left, .jBox-TooltipSmallGray .jBox-pointer-right {
27
+  width: 8px;
28
+  height: 22px;
29
+}
30
+
31
+.jBox-TooltipSmallGray .jBox-pointer-top:after {
32
+  background: #fafafa;
33
+  left: 1px;
34
+  top: 6px;
35
+}
36
+
37
+.jBox-TooltipSmallGray .jBox-pointer-right:after {
38
+  top: 1px;
39
+  right: 6px;
40
+}
41
+
42
+.jBox-TooltipSmallGray .jBox-pointer-bottom:after {
43
+  background: #f2f2f2;
44
+  left: 1px;
45
+  bottom: 6px;
46
+}
47
+
48
+.jBox-TooltipSmallGray .jBox-pointer-left:after {
49
+  top: 1px;
50
+  left: 6px;
51
+}
52
+
53
+/*# sourceMappingURL=jBox.TooltipSmallGray.css.map */
0 54
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+.jBox-TooltipSmallGray{pointer-events:none}.jBox-TooltipSmallGray .jBox-container{font-size:13px;line-height:24px;border-radius:12px;background-image:linear-gradient(to bottom,#fafafa,#f2f2f2)}.jBox-TooltipSmallGray .jBox-content{padding:0 10px}.jBox-TooltipSmallGray .jBox-pointer:after{width:20px;height:20px}.jBox-TooltipSmallGray .jBox-pointer-bottom,.jBox-TooltipSmallGray .jBox-pointer-top{width:22px;height:8px}.jBox-TooltipSmallGray .jBox-pointer-left,.jBox-TooltipSmallGray .jBox-pointer-right{width:8px;height:22px}.jBox-TooltipSmallGray .jBox-pointer-top:after{background:#fafafa;left:1px;top:6px}.jBox-TooltipSmallGray .jBox-pointer-right:after{top:1px;right:6px}.jBox-TooltipSmallGray .jBox-pointer-bottom:after{background:#f2f2f2;left:1px;bottom:6px}.jBox-TooltipSmallGray .jBox-pointer-left:after{top:1px;left:6px}
0 2
\ No newline at end of file
... ...
@@ -1,13 +1,13 @@
1 1
 <?php
2 2
 
3 3
 // Add the colorbox style sheet
4
-$GLOBALS['TL_CSS'][] = 'files/themes/vonrotenberg_2020/assets/js/lib/jBox/1.0.7/jBox.min.css|static';
5
-$GLOBALS['TL_CSS'][] = 'files/themes/vonrotenberg_2020/assets/js/lib/jBox/1.0.7/plugins/jBox.Image.css|static';
6
-$GLOBALS['TL_CSS'][] = 'files/themes/vonrotenberg_2020/assets/css/jBox.TooltipDurbacher.css|static';
4
+$GLOBALS['TL_CSS'][] = 'files/themes/aldegott_2022/assets/js/lib/jBox/1.2.3/jBox.min.css|static';
5
+$GLOBALS['TL_CSS'][] = 'files/themes/aldegott_2022/assets/js/lib/jBox/1.2.3/plugins/jBox.Image.css|static';
6
+$GLOBALS['TL_CSS'][] = 'files/themes/aldegott_2022/assets/css/jBox.TooltipDurbacher.css|static';
7 7
 
8 8
 ?>
9 9
 
10
-<script src="files/themes/vonrotenberg_2020/assets/js/lib/jBox/1.0.7/jBox.all.min.js"></script>
10
+<script src="files/themes/aldegott_2022/assets/js/lib/jBox/1.2.3/jBox.all.min.js"></script>
11 11
 <script>
12 12
   jQuery(function($) {
13 13
     $('a[data-jbox-iframe]').map(function() {
... ...
@@ -38,6 +38,26 @@ $GLOBALS['TL_CSS'][] = 'files/themes/vonrotenberg_2020/assets/css/jBox.TooltipDu
38 38
       });
39 39
     });
40 40
 
41
+    $('a[data-jbox-basic-modal]').map(function() {
42
+      new jBox('Modal', {
43
+        attach: $(this),
44
+        preventDefault: true,
45
+        // content: $($(this).data('jbox-basic-modal')),
46
+        closeButton: 'box',
47
+        // width: 700,
48
+        // height: 650,
49
+        theme: 'iframe',
50
+        addClass: 'jBox-noPadding',
51
+        // addClass: 'jBox-noPadding'
52
+        onOpen: function () {
53
+          this.setContent($($(this.source[0]).data('jbox-basic-modal'))[0].innerHTML);
54
+        },
55
+        onCloseComplete: function() {
56
+          this.setContent('');
57
+        }
58
+      });
59
+    });
60
+
41 61
     $lbImages = $('[data-lightbox]').filter(function(index) {
42 62
       if (!$(this).parents().eq(3).hasClass('slick-cloned'))
43 63
       {
44 64
deleted file mode 100644
45 65
Binary files a/var/backups/backup__20221216092532.sql.gz and /dev/null differ
46 66
deleted file mode 100644
47 67
Binary files a/var/backups/backup__20221216185236.sql.gz and /dev/null differ
48 68
new file mode 100644
49 69
Binary files /dev/null and b/var/backups/backup__20221219141627.sql.gz differ