semantic-ui-sass 1.12.3.0 → 2.0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/app/assets/javascripts/semantic-ui.js +1 -0
  4. data/app/assets/javascripts/semantic-ui/accordion.js +67 -53
  5. data/app/assets/javascripts/semantic-ui/api.js +395 -189
  6. data/app/assets/javascripts/semantic-ui/checkbox.js +322 -114
  7. data/app/assets/javascripts/semantic-ui/colorize.js +4 -2
  8. data/app/assets/javascripts/semantic-ui/dimmer.js +74 -50
  9. data/app/assets/javascripts/semantic-ui/dropdown.js +2046 -584
  10. data/app/assets/javascripts/semantic-ui/embed.js +662 -0
  11. data/app/assets/javascripts/semantic-ui/form.js +345 -163
  12. data/app/assets/javascripts/semantic-ui/modal.js +119 -90
  13. data/app/assets/javascripts/semantic-ui/nag.js +8 -9
  14. data/app/assets/javascripts/semantic-ui/popup.js +390 -228
  15. data/app/assets/javascripts/semantic-ui/progress.js +112 -103
  16. data/app/assets/javascripts/semantic-ui/rating.js +79 -55
  17. data/app/assets/javascripts/semantic-ui/search.js +305 -123
  18. data/app/assets/javascripts/semantic-ui/shape.js +94 -48
  19. data/app/assets/javascripts/semantic-ui/sidebar.js +84 -151
  20. data/app/assets/javascripts/semantic-ui/site.js +5 -5
  21. data/app/assets/javascripts/semantic-ui/state.js +4 -4
  22. data/app/assets/javascripts/semantic-ui/sticky.js +108 -35
  23. data/app/assets/javascripts/semantic-ui/tab.js +220 -125
  24. data/app/assets/javascripts/semantic-ui/transition.js +205 -171
  25. data/app/assets/javascripts/semantic-ui/visibility.js +220 -100
  26. data/app/assets/javascripts/semantic-ui/visit.js +6 -4
  27. data/app/assets/stylesheets/semantic-ui/collections/_breadcrumb.scss +17 -16
  28. data/app/assets/stylesheets/semantic-ui/collections/_form.scss +223 -121
  29. data/app/assets/stylesheets/semantic-ui/collections/_grid.scss +462 -448
  30. data/app/assets/stylesheets/semantic-ui/collections/_menu.scss +949 -665
  31. data/app/assets/stylesheets/semantic-ui/collections/_message.scss +134 -92
  32. data/app/assets/stylesheets/semantic-ui/collections/_table.scss +270 -208
  33. data/app/assets/stylesheets/semantic-ui/elements/_all.scss +1 -0
  34. data/app/assets/stylesheets/semantic-ui/elements/_button.scss +1357 -521
  35. data/app/assets/stylesheets/semantic-ui/elements/_container.scss +125 -0
  36. data/app/assets/stylesheets/semantic-ui/elements/_divider.scss +51 -31
  37. data/app/assets/stylesheets/semantic-ui/elements/_flag.scss +3 -3
  38. data/app/assets/stylesheets/semantic-ui/elements/_header.scss +270 -144
  39. data/app/assets/stylesheets/semantic-ui/elements/_icon.scss +241 -110
  40. data/app/assets/stylesheets/semantic-ui/elements/_image.scss +30 -16
  41. data/app/assets/stylesheets/semantic-ui/elements/_input.scss +88 -53
  42. data/app/assets/stylesheets/semantic-ui/elements/_label.scss +432 -281
  43. data/app/assets/stylesheets/semantic-ui/elements/_list.scss +172 -128
  44. data/app/assets/stylesheets/semantic-ui/elements/_loader.scss +16 -14
  45. data/app/assets/stylesheets/semantic-ui/elements/_rail.scss +15 -7
  46. data/app/assets/stylesheets/semantic-ui/elements/_reveal.scss +32 -13
  47. data/app/assets/stylesheets/semantic-ui/elements/_segment.scss +329 -212
  48. data/app/assets/stylesheets/semantic-ui/elements/_step.scss +291 -99
  49. data/app/assets/stylesheets/semantic-ui/globals/_reset.scss +2 -2
  50. data/app/assets/stylesheets/semantic-ui/globals/_site.scss +19 -18
  51. data/app/assets/stylesheets/semantic-ui/modules/_accordion.scss +17 -18
  52. data/app/assets/stylesheets/semantic-ui/modules/_all.scss +1 -0
  53. data/app/assets/stylesheets/semantic-ui/modules/_checkbox.scss +265 -161
  54. data/app/assets/stylesheets/semantic-ui/modules/_dimmer.scss +29 -15
  55. data/app/assets/stylesheets/semantic-ui/modules/_dropdown.scss +441 -156
  56. data/app/assets/stylesheets/semantic-ui/modules/_embed.scss +168 -0
  57. data/app/assets/stylesheets/semantic-ui/modules/_modal.scss +163 -85
  58. data/app/assets/stylesheets/semantic-ui/modules/_nag.scss +8 -8
  59. data/app/assets/stylesheets/semantic-ui/modules/_popup.scss +88 -23
  60. data/app/assets/stylesheets/semantic-ui/modules/_progress.scss +185 -129
  61. data/app/assets/stylesheets/semantic-ui/modules/_rating.scss +75 -60
  62. data/app/assets/stylesheets/semantic-ui/modules/_search.scss +99 -52
  63. data/app/assets/stylesheets/semantic-ui/modules/_shape.scss +11 -11
  64. data/app/assets/stylesheets/semantic-ui/modules/_sidebar.scss +16 -12
  65. data/app/assets/stylesheets/semantic-ui/modules/_sticky.scss +4 -4
  66. data/app/assets/stylesheets/semantic-ui/modules/_tab.scss +3 -3
  67. data/app/assets/stylesheets/semantic-ui/modules/_transition.scss +31 -39
  68. data/app/assets/stylesheets/semantic-ui/views/_ad.scss +3 -3
  69. data/app/assets/stylesheets/semantic-ui/views/_all.scss +1 -0
  70. data/app/assets/stylesheets/semantic-ui/views/_card.scss +204 -162
  71. data/app/assets/stylesheets/semantic-ui/views/_comment.scss +6 -6
  72. data/app/assets/stylesheets/semantic-ui/views/_feed.scss +51 -26
  73. data/app/assets/stylesheets/semantic-ui/views/_item.scss +62 -36
  74. data/app/assets/stylesheets/semantic-ui/views/_statistic.scss +265 -90
  75. data/lib/semantic/ui/sass/version.rb +2 -2
  76. data/semantic-ui-sass.gemspec +2 -2
  77. metadata +9 -6
@@ -1,9 +1,9 @@
1
1
  /*!
2
- * # Semantic UI 1.12.3 - Modal
2
+ * # Semantic UI - Modal
3
3
  * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2014 Contributors
6
+ * Copyright 2015 Contributors
7
7
  * Released under the MIT license
8
8
  * http://opensource.org/licenses/MIT
9
9
  *
@@ -80,9 +80,10 @@ $.fn.modal = function(parameters) {
80
80
  module.create.dimmer();
81
81
  module.refreshModals();
82
82
 
83
- module.verbose('Attaching close events', $close);
84
83
  module.bind.events();
85
- module.observeChanges();
84
+ if(settings.observeChanges) {
85
+ module.observeChanges();
86
+ }
86
87
  module.instantiate();
87
88
  },
88
89
 
@@ -107,6 +108,12 @@ $.fn.modal = function(parameters) {
107
108
  },
108
109
  dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
109
110
  ;
111
+ if(settings.inverted) {
112
+ dimmerSettings.variation = (dimmerSettings.variation !== undefined)
113
+ ? dimmerSettings.variation + ' inverted'
114
+ : 'inverted'
115
+ ;
116
+ }
110
117
  if($.fn.dimmer === undefined) {
111
118
  module.error(error.dimmer);
112
119
  return;
@@ -117,6 +124,12 @@ $.fn.modal = function(parameters) {
117
124
  module.verbose('Modal is detachable, moving content into dimmer');
118
125
  $dimmable.dimmer('add content', $module);
119
126
  }
127
+ else {
128
+ module.set.undetached();
129
+ }
130
+ if(settings.blurring) {
131
+ $dimmable.addClass(className.blurring);
132
+ }
120
133
  $dimmer = $dimmable.dimmer('get dimmer');
121
134
  },
122
135
  id: function() {
@@ -186,8 +199,15 @@ $.fn.modal = function(parameters) {
186
199
 
187
200
  bind: {
188
201
  events: function() {
189
- $close.on('click' + eventNamespace, module.event.close);
190
- $window.on('resize' + elementNamespace, module.event.resize);
202
+ module.verbose('Attaching events');
203
+ $module
204
+ .on('click' + eventNamespace, selector.close, module.event.close)
205
+ .on('click' + eventNamespace, selector.approve, module.event.approve)
206
+ .on('click' + eventNamespace, selector.deny, module.event.deny)
207
+ ;
208
+ $window
209
+ .on('resize' + elementNamespace, module.event.resize)
210
+ ;
191
211
  }
192
212
  },
193
213
 
@@ -198,30 +218,30 @@ $.fn.modal = function(parameters) {
198
218
  },
199
219
 
200
220
  event: {
201
- close: function() {
202
- module.verbose('Closing element pressed');
203
- if( $(this).is(selector.approve) ) {
204
- if(settings.onApprove.call(element) !== false) {
205
- module.hide();
206
- }
207
- else {
208
- module.verbose('Approve callback returned false cancelling hide');
209
- }
210
- }
211
- else if( $(this).is(selector.deny) ) {
212
- if(settings.onDeny.call(element) !== false) {
213
- module.hide();
214
- }
215
- else {
216
- module.verbose('Deny callback returned false cancelling hide');
217
- }
221
+ approve: function() {
222
+ if(settings.onApprove.call(element, $(this)) === false) {
223
+ module.verbose('Approve callback returned false cancelling hide');
224
+ return;
218
225
  }
219
- else {
220
- module.hide();
226
+ module.hide();
227
+ },
228
+ deny: function() {
229
+ if(settings.onDeny.call(element, $(this)) === false) {
230
+ module.verbose('Deny callback returned false cancelling hide');
231
+ return;
221
232
  }
233
+ module.hide();
234
+ },
235
+ close: function() {
236
+ module.hide();
222
237
  },
223
238
  click: function(event) {
224
- if( $(event.target).closest($module).length === 0 ) {
239
+ var
240
+ $target = $(event.target),
241
+ isInModal = ($target.closest(selector.modal).length > 0),
242
+ isInDOM = $.contains(document.documentElement, event.target)
243
+ ;
244
+ if(!isInModal && isInDOM) {
225
245
  module.debug('Dimmer clicked, hiding all modals');
226
246
  if( module.is.active() ) {
227
247
  module.remove.clickaway();
@@ -302,8 +322,7 @@ $.fn.modal = function(parameters) {
302
322
  module.set.type();
303
323
  module.set.clickaway();
304
324
 
305
- if( !settings.allowMultiple && $otherModals.filter('.' + className.active).length > 0) {
306
- module.debug('Other modals visible, queueing show animation');
325
+ if( !settings.allowMultiple && module.others.active() ) {
307
326
  module.hideOthers(module.showModal);
308
327
  }
309
328
  else {
@@ -329,16 +348,7 @@ $.fn.modal = function(parameters) {
329
348
  ;
330
349
  }
331
350
  else {
332
- module.debug('Showing modal with javascript');
333
- $module
334
- .fadeIn(settings.duration, settings.easing, function() {
335
- settings.onVisible.apply(element);
336
- module.add.keyboardShortcuts();
337
- module.save.focus();
338
- module.set.active();
339
- callback();
340
- })
341
- ;
351
+ module.error(error.noTransition);
342
352
  }
343
353
  }
344
354
  }
@@ -366,7 +376,7 @@ $.fn.modal = function(parameters) {
366
376
  duration : settings.duration,
367
377
  useFailSafe : true,
368
378
  onStart : function() {
369
- if(!module.othersActive() && !keepDimmed) {
379
+ if(!module.others.active() && !keepDimmed) {
370
380
  module.hideDimmer();
371
381
  }
372
382
  module.remove.keyboardShortcuts();
@@ -380,18 +390,7 @@ $.fn.modal = function(parameters) {
380
390
  ;
381
391
  }
382
392
  else {
383
- module.remove.active();
384
- if( !module.othersActive() ) {
385
- module.hideDimmer();
386
- }
387
- module.remove.keyboardShortcuts();
388
- $module
389
- .fadeOut(settings.duration, settings.easing, function() {
390
- settings.onHidden.call(element);
391
- module.restore.focus();
392
- callback();
393
- })
394
- ;
393
+ module.error(error.noTransition);
395
394
  }
396
395
  }
397
396
  },
@@ -409,10 +408,8 @@ $.fn.modal = function(parameters) {
409
408
  hideDimmer: function() {
410
409
  if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
411
410
  $dimmable.dimmer('hide', function() {
412
- if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
413
- module.remove.clickaway();
414
- module.remove.screenHeight();
415
- }
411
+ module.remove.clickaway();
412
+ module.remove.screenHeight();
416
413
  });
417
414
  }
418
415
  else {
@@ -423,7 +420,7 @@ $.fn.modal = function(parameters) {
423
420
 
424
421
  hideAll: function(callback) {
425
422
  var
426
- $visibleModals = $allModals.filter(':visible')
423
+ $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
427
424
  ;
428
425
  callback = $.isFunction(callback)
429
426
  ? callback
@@ -440,7 +437,7 @@ $.fn.modal = function(parameters) {
440
437
 
441
438
  hideOthers: function(callback) {
442
439
  var
443
- $visibleModals = $otherModals.filter(':visible')
440
+ $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
444
441
  ;
445
442
  callback = $.isFunction(callback)
446
443
  ? callback
@@ -454,10 +451,16 @@ $.fn.modal = function(parameters) {
454
451
  }
455
452
  },
456
453
 
457
- othersActive: function() {
458
- return ($otherModals.filter('.' + className.active).length > 0);
454
+ others: {
455
+ active: function() {
456
+ return ($otherModals.filter('.' + className.active).length > 0);
457
+ },
458
+ animating: function() {
459
+ return ($otherModals.filter('.' + className.animating).length > 0);
460
+ }
459
461
  },
460
462
 
463
+
461
464
  add: {
462
465
  keyboardShortcuts: function() {
463
466
  module.verbose('Adding keyboard shortcuts');
@@ -492,14 +495,18 @@ $.fn.modal = function(parameters) {
492
495
  ;
493
496
  }
494
497
  },
495
- screenHeight: function() {
496
- if(module.cache.height > module.cache.pageHeight) {
497
- module.debug('Removing page height');
498
- $body
499
- .css('height', '')
500
- ;
498
+ bodyStyle: function() {
499
+ if($body.attr('style') === '') {
500
+ module.verbose('Removing style attribute');
501
+ $body.removeAttr('style');
501
502
  }
502
503
  },
504
+ screenHeight: function() {
505
+ module.debug('Removing page height');
506
+ $body
507
+ .css('height', '')
508
+ ;
509
+ },
503
510
  keyboardShortcuts: function() {
504
511
  module.verbose('Removing keyboard shortcuts');
505
512
  $document
@@ -557,13 +564,15 @@ $.fn.modal = function(parameters) {
557
564
  autofocus: function() {
558
565
  if(settings.autofocus) {
559
566
  var
560
- $inputs = $module.find(':input:visible'),
567
+ $inputs = $module.filter(':input').filter(':visible'),
561
568
  $autofocus = $inputs.filter('[autofocus]'),
562
569
  $input = ($autofocus.length > 0)
563
- ? $autofocus
564
- : $inputs
570
+ ? $autofocus.first()
571
+ : $inputs.first()
565
572
  ;
566
- $input.first().focus();
573
+ if($input.length > 0) {
574
+ $input.focus();
575
+ }
567
576
  }
568
577
  },
569
578
  clickaway: function() {
@@ -580,7 +589,7 @@ $.fn.modal = function(parameters) {
580
589
  else {
581
590
  module.debug('Modal is taller than page content, resizing page height');
582
591
  $body
583
- .css('height', module.cache.height + (settings.padding / 2) )
592
+ .css('height', module.cache.height + (settings.padding * 2) )
584
593
  ;
585
594
  }
586
595
  },
@@ -594,7 +603,7 @@ $.fn.modal = function(parameters) {
594
603
  type: function() {
595
604
  if(module.can.fit()) {
596
605
  module.verbose('Modal fits on screen');
597
- if(!module.othersActive) {
606
+ if(!module.others.active() && !module.others.animating()) {
598
607
  module.remove.scrolling();
599
608
  }
600
609
  }
@@ -621,6 +630,9 @@ $.fn.modal = function(parameters) {
621
630
  })
622
631
  ;
623
632
  }
633
+ },
634
+ undetached: function() {
635
+ $dimmable.addClass(className.undetached);
624
636
  }
625
637
  },
626
638
 
@@ -693,7 +705,7 @@ $.fn.modal = function(parameters) {
693
705
  });
694
706
  }
695
707
  clearTimeout(module.performance.timer);
696
- module.performance.timer = setTimeout(module.performance.display, 100);
708
+ module.performance.timer = setTimeout(module.performance.display, 500);
697
709
  },
698
710
  display: function() {
699
711
  var
@@ -806,40 +818,55 @@ $.fn.modal.settings = {
806
818
  namespace : 'modal',
807
819
 
808
820
  debug : false,
809
- verbose : true,
821
+ verbose : false,
810
822
  performance : true,
811
823
 
824
+ observeChanges : false,
825
+
812
826
  allowMultiple : false,
813
827
  detachable : true,
814
828
  closable : true,
815
829
  autofocus : true,
816
830
 
831
+ inverted : false,
832
+ blurring : false,
833
+
817
834
  dimmerSettings : {
818
835
  closable : false,
819
836
  useCSS : true
820
837
  },
821
838
 
822
- context : 'body',
823
839
 
824
- queue : false,
825
- duration : 500,
826
- easing : 'easeOutExpo',
827
- offset : 0,
828
- transition : 'scale',
840
+ context : 'body',
841
+
842
+ queue : false,
843
+ duration : 500,
844
+ offset : 0,
845
+ transition : 'scale',
846
+
847
+ // padding with edge of page
848
+ padding : 50,
849
+
850
+ // called before show animation
851
+ onShow : function(){},
852
+
853
+ // called after show animation
854
+ onVisible : function(){},
829
855
 
830
- padding : 50,
856
+ // called before hide animation
857
+ onHide : function(){},
831
858
 
832
- onShow : function(){},
833
- onHide : function(){},
859
+ // called after hide animation
860
+ onHidden : function(){},
834
861
 
835
- onVisible : function(){},
836
- onHidden : function(){},
862
+ // called after approve selector match
863
+ onApprove : function(){ return true; },
837
864
 
838
- onApprove : function(){ return true; },
839
- onDeny : function(){ return true; },
865
+ // called after deny selector match
866
+ onDeny : function(){ return true; },
840
867
 
841
868
  selector : {
842
- close : '.close, .actions .button',
869
+ close : '.close',
843
870
  approve : '.actions .positive, .actions .approve, .actions .ok',
844
871
  deny : '.actions .negative, .actions .deny, .actions .cancel',
845
872
  modal : '.ui.modal'
@@ -850,9 +877,11 @@ $.fn.modal.settings = {
850
877
  notFound : 'The element you specified could not be found'
851
878
  },
852
879
  className : {
853
- active : 'active',
854
- animating : 'animating',
855
- scrolling : 'scrolling'
880
+ active : 'active',
881
+ animating : 'animating',
882
+ blurring : 'blurring',
883
+ scrolling : 'scrolling',
884
+ undetached : 'undetached'
856
885
  }
857
886
  };
858
887
 
@@ -1,9 +1,9 @@
1
1
  /*!
2
- * # Semantic UI 1.12.3 - Nag
2
+ * # Semantic UI - Nag
3
3
  * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2014 Contributors
6
+ * Copyright 2015 Contributors
7
7
  * Released under the MIT license
8
8
  * http://opensource.org/licenses/MIT
9
9
  *
@@ -76,11 +76,9 @@ $.fn.nag = function(parameters) {
76
76
  module.verbose('Initializing element');
77
77
 
78
78
  $module
79
+ .on('click' + eventNamespace, selector.close, module.dismiss)
79
80
  .data(moduleNamespace, module)
80
81
  ;
81
- $close
82
- .on('click' + eventNamespace, module.dismiss)
83
- ;
84
82
 
85
83
  if(settings.detachable && $module.parent()[0] !== $context[0]) {
86
84
  $module
@@ -310,7 +308,7 @@ $.fn.nag = function(parameters) {
310
308
  });
311
309
  }
312
310
  clearTimeout(module.performance.timer);
313
- module.performance.timer = setTimeout(module.performance.display, 100);
311
+ module.performance.timer = setTimeout(module.performance.display, 500);
314
312
  },
315
313
  display: function() {
316
314
  var
@@ -423,7 +421,7 @@ $.fn.nag.settings = {
423
421
  name : 'Nag',
424
422
 
425
423
  debug : false,
426
- verbose : true,
424
+ verbose : false,
427
425
  performance : true,
428
426
 
429
427
  namespace : 'Nag',
@@ -454,8 +452,9 @@ $.fn.nag.settings = {
454
452
  value : 'dismiss',
455
453
 
456
454
  error: {
457
- noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
458
- method : 'The method you called is not defined.'
455
+ noCookieStorage : '$.cookie is not included. A storage solution is required.',
456
+ noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
457
+ method : 'The method you called is not defined.'
459
458
  },
460
459
 
461
460
  className : {
@@ -1,9 +1,9 @@
1
1
  /*!
2
- * # Semantic UI 1.12.3 - Popup
2
+ * # Semantic UI - Popup
3
3
  * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2014 Contributors
6
+ * Copyright 2015 Contributors
7
7
  * Released under the MIT license
8
8
  * http://opensource.org/licenses/MIT
9
9
  *
@@ -17,6 +17,8 @@ $.fn.popup = function(parameters) {
17
17
  var
18
18
  $allModules = $(this),
19
19
  $document = $(document),
20
+ $window = $(window),
21
+ $body = $('body'),
20
22
 
21
23
  moduleSelector = $allModules.selector || '',
22
24
 
@@ -52,13 +54,12 @@ $.fn.popup = function(parameters) {
52
54
  ? $(settings.target)
53
55
  : $module,
54
56
 
55
- $window = $(window),
56
- $body = $('body'),
57
57
  $popup,
58
58
  $offsetParent,
59
59
 
60
60
  searchDepth = 0,
61
61
  triedPositions = false,
62
+ openedWithTouch = false,
62
63
 
63
64
  element = this,
64
65
  instance = $module.data(moduleNamespace),
@@ -96,6 +97,7 @@ $.fn.popup = function(parameters) {
96
97
  else {
97
98
  if(settings.inline) {
98
99
  $popup = $target.next(selector.popup).eq(0);
100
+ settings.popup = $popup;
99
101
  }
100
102
  }
101
103
  if(settings.popup) {
@@ -118,7 +120,7 @@ $.fn.popup = function(parameters) {
118
120
  : $body
119
121
  ;
120
122
  }
121
- if( $offsetParent.is('html') ) {
123
+ if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) {
122
124
  module.debug('Setting page as offset parent');
123
125
  $offsetParent = $body;
124
126
  }
@@ -154,11 +156,7 @@ $.fn.popup = function(parameters) {
154
156
  : settings.delay
155
157
  ;
156
158
  clearTimeout(module.hideTimer);
157
- module.showTimer = setTimeout(function() {
158
- if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
159
- module.show();
160
- }
161
- }, delay);
159
+ module.showTimer = setTimeout(module.show, delay);
162
160
  },
163
161
  end: function() {
164
162
  var
@@ -167,27 +165,38 @@ $.fn.popup = function(parameters) {
167
165
  : settings.delay
168
166
  ;
169
167
  clearTimeout(module.showTimer);
170
- module.hideTimer = setTimeout(function() {
171
- if(module.is.visible() ) {
172
- module.hide();
173
- }
174
- }, delay);
168
+ module.hideTimer = setTimeout(module.hide, delay);
169
+ },
170
+ touchstart: function(event) {
171
+ openedWithTouch = true;
172
+ module.event.start();
175
173
  },
176
174
  resize: function() {
177
175
  if( module.is.visible() ) {
178
176
  module.set.position();
179
177
  }
178
+ },
179
+ hideGracefully: function(event) {
180
+ // don't close on clicks inside popup
181
+ if(event && $(event.target).closest(selector.popup).length === 0) {
182
+ module.debug('Click occurred outside popup hiding popup');
183
+ module.hide();
184
+ }
185
+ else {
186
+ module.debug('Click was inside popup, keeping popup open');
187
+ }
180
188
  }
181
189
  },
182
190
 
183
191
  // generates popup html from metadata
184
192
  create: function() {
185
193
  var
186
- html = $module.data(metadata.html) || settings.html,
187
- variation = $module.data(metadata.variation) || settings.variation,
188
- title = $module.data(metadata.title) || settings.title,
189
- content = $module.data(metadata.content) || $module.attr('title') || settings.content
194
+ html = module.get.html(),
195
+ variation = module.get.variation(),
196
+ title = module.get.title(),
197
+ content = module.get.content()
190
198
  ;
199
+
191
200
  if(html || content || title) {
192
201
  module.debug('Creating pop-up html');
193
202
  if(!html) {
@@ -228,14 +237,14 @@ $.fn.popup = function(parameters) {
228
237
  else if($target.next(selector.popup).length !== 0) {
229
238
  module.verbose('Pre-existing popup found');
230
239
  settings.inline = true;
231
- settings.popup = $target.next(selector.popup).data(metadata.activator, $module);
240
+ settings.popups = $target.next(selector.popup).data(metadata.activator, $module);
232
241
  module.refresh();
233
242
  if(settings.hoverable) {
234
243
  module.bind.popup();
235
244
  }
236
245
  }
237
246
  else if(settings.popup) {
238
- settings.popup.data(metadata.activator, $module);
247
+ $(settings.popup).data(metadata.activator, $module);
239
248
  module.verbose('Used popup specified in settings');
240
249
  module.refresh();
241
250
  if(settings.hoverable) {
@@ -268,29 +277,40 @@ $.fn.popup = function(parameters) {
268
277
  },
269
278
 
270
279
  show: function(callback) {
271
- callback = $.isFunction(callback) ? callback : function(){};
280
+ callback = callback || function(){};
272
281
  module.debug('Showing pop-up', settings.transition);
273
- if( !module.exists() ) {
274
- module.create();
275
- }
276
- else if(!settings.preserve && !settings.popup) {
277
- module.refresh();
278
- }
279
- if( $popup && module.set.position() ) {
280
- module.save.conditions();
281
- if(settings.exclusive) {
282
- module.hideAll();
282
+
283
+ if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
284
+ if( !module.exists() ) {
285
+ module.create();
286
+ }
287
+ if(settings.onShow.call($popup, element) === false) {
288
+ module.debug('onShow callback returned false, cancelling popup animation');
289
+ return;
290
+ }
291
+ else if(!settings.preserve && !settings.popup) {
292
+ module.refresh();
293
+ }
294
+ if( $popup && module.set.position() ) {
295
+ module.save.conditions();
296
+ if(settings.exclusive) {
297
+ module.hideAll();
298
+ }
299
+ module.animate.show(callback);
283
300
  }
284
- module.animate.show(callback);
285
301
  }
286
302
  },
287
303
 
288
304
 
289
305
  hide: function(callback) {
290
- callback = $.isFunction(callback) ? callback : function(){};
291
- module.remove.visible();
292
- module.unbind.close();
293
- if( module.is.visible() ) {
306
+ callback = callback || function(){};
307
+ if( module.is.visible() || module.is.animating() ) {
308
+ if(settings.onHide.call($popup, element) === false) {
309
+ module.debug('onHide callback returned false, cancelling popup animation');
310
+ return;
311
+ }
312
+ module.remove.visible();
313
+ module.unbind.close();
294
314
  module.restore.conditions();
295
315
  module.animate.hide(callback);
296
316
  }
@@ -307,18 +327,6 @@ $.fn.popup = function(parameters) {
307
327
  })
308
328
  ;
309
329
  },
310
-
311
- hideGracefully: function(event) {
312
- // don't close on clicks inside popup
313
- if(event && $(event.target).closest(selector.popup).length === 0) {
314
- module.debug('Click occurred outside popup hiding popup');
315
- module.hide();
316
- }
317
- else {
318
- module.debug('Click was inside popup, keeping popup open');
319
- }
320
- },
321
-
322
330
  exists: function() {
323
331
  if(!$popup) {
324
332
  return false;
@@ -384,21 +392,16 @@ $.fn.popup = function(parameters) {
384
392
  ;
385
393
  }
386
394
  else {
387
- module.set.visible();
388
- $popup
389
- .stop()
390
- .fadeIn(settings.duration, settings.easing, function() {
391
- module.bind.close();
392
- callback.call($popup, element);
393
- settings.onVisible.call($popup, element);
394
- })
395
- ;
395
+ module.error(error.noTransition);
396
396
  }
397
- settings.onShow.call($popup, element);
398
397
  },
399
398
  hide: function(callback) {
400
399
  callback = $.isFunction(callback) ? callback : function(){};
401
400
  module.debug('Hiding pop-up');
401
+ if(settings.onShow.call($popup, element) === false) {
402
+ module.debug('onShow callback returned false, cancelling popup animation');
403
+ return;
404
+ }
402
405
  if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
403
406
  $popup
404
407
  .transition({
@@ -416,29 +419,106 @@ $.fn.popup = function(parameters) {
416
419
  ;
417
420
  }
418
421
  else {
419
- $popup
420
- .stop()
421
- .fadeOut(settings.duration, settings.easing, function() {
422
- module.reset();
423
- callback.call($popup, element);
424
- settings.onHidden.call($popup, element);
425
- })
426
- ;
422
+ module.error(error.noTransition);
427
423
  }
428
- settings.onHide.call($popup, element);
429
424
  }
430
425
  },
431
426
 
432
427
  get: {
428
+ html: function() {
429
+ $module.removeData(metadata.html);
430
+ return $module.data(metadata.html) || settings.html;
431
+ },
432
+ title: function() {
433
+ $module.removeData(metadata.title);
434
+ return $module.data(metadata.title) || settings.title;
435
+ },
436
+ content: function() {
437
+ $module.removeData(metadata.content);
438
+ return $module.data(metadata.content) || $module.attr('title') || settings.content;
439
+ },
440
+ variation: function() {
441
+ $module.removeData(metadata.variation);
442
+ return $module.data(metadata.variation) || settings.variation;
443
+ },
444
+ popupOffset: function() {
445
+ return $popup.offset();
446
+ },
447
+ calculations: function() {
448
+ var
449
+ targetElement = $target[0],
450
+ targetPosition = (settings.inline || settings.popup)
451
+ ? $target.position()
452
+ : $target.offset(),
453
+ calculations = {},
454
+ screen
455
+ ;
456
+ calculations = {
457
+ // element which is launching popup
458
+ target : {
459
+ element : $target[0],
460
+ width : $target.outerWidth(),
461
+ height : $target.outerHeight(),
462
+ top : targetPosition.top,
463
+ left : targetPosition.left,
464
+ margin : {}
465
+ },
466
+ // popup itself
467
+ popup : {
468
+ width : $popup.outerWidth(),
469
+ height : $popup.outerHeight()
470
+ },
471
+ // offset container (or 3d context)
472
+ parent : {
473
+ width : $offsetParent.outerWidth(),
474
+ height : $offsetParent.outerHeight()
475
+ },
476
+ // screen boundaries
477
+ screen : {
478
+ scroll: {
479
+ top : $window.scrollTop(),
480
+ left : $window.scrollLeft()
481
+ },
482
+ width : $window.width(),
483
+ height : $window.height()
484
+ }
485
+ };
486
+
487
+ // add in container calcs if fluid
488
+ if( settings.setFluidWidth && module.is.fluid() ) {
489
+ calculations.container = {
490
+ width: $popup.parent().outerWidth()
491
+ };
492
+ calculations.popup.width = calculations.container.width;
493
+ }
494
+
495
+ // add in margins if inline
496
+ calculations.target.margin.top = (settings.inline)
497
+ ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
498
+ : 0
499
+ ;
500
+ calculations.target.margin.left = (settings.inline)
501
+ ? module.is.rtl()
502
+ ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10)
503
+ : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left') , 10)
504
+ : 0
505
+ ;
506
+ // calculate screen boundaries
507
+ screen = calculations.screen;
508
+ calculations.boundary = {
509
+ top : screen.scroll.top,
510
+ bottom : screen.scroll.top + screen.height,
511
+ left : screen.scroll.left,
512
+ right : screen.scroll.left + screen.width
513
+ };
514
+ return calculations;
515
+ },
433
516
  id: function() {
434
517
  return id;
435
518
  },
436
519
  startEvent: function() {
437
520
  if(settings.on == 'hover') {
438
- return (hasTouch)
439
- ? 'touchstart mouseenter'
440
- : 'mouseenter'
441
- ;
521
+ return 'mouseenter';
442
522
  }
443
523
  else if(settings.on == 'focus') {
444
524
  return 'focus';
@@ -446,10 +526,7 @@ $.fn.popup = function(parameters) {
446
526
  return false;
447
527
  },
448
528
  scrollEvent: function() {
449
- return (hasTouch)
450
- ? 'touchmove scroll'
451
- : 'scroll'
452
- ;
529
+ return 'scroll';
453
530
  },
454
531
  endEvent: function() {
455
532
  if(settings.on == 'hover') {
@@ -460,6 +537,30 @@ $.fn.popup = function(parameters) {
460
537
  }
461
538
  return false;
462
539
  },
540
+ distanceFromBoundary: function(offset, calculations) {
541
+ var
542
+ distanceFromBoundary = {},
543
+ popup,
544
+ boundary
545
+ ;
546
+ offset = offset || module.get.offset();
547
+ calculations = calculations || module.get.calculations();
548
+
549
+ // shorthand
550
+ popup = calculations.popup;
551
+ boundary = calculations.boundary;
552
+
553
+ if(offset) {
554
+ distanceFromBoundary = {
555
+ top : (offset.top - boundary.top),
556
+ left : (offset.left - boundary.left),
557
+ right : (boundary.right - (offset.left + popup.width) ),
558
+ bottom : (boundary.bottom - (offset.top + popup.height) )
559
+ };
560
+ module.verbose('Distance from boundaries determined', offset, distanceFromBoundary);
561
+ }
562
+ return distanceFromBoundary;
563
+ },
463
564
  offsetParent: function($target) {
464
565
  var
465
566
  element = ($target !== undefined)
@@ -487,43 +588,6 @@ $.fn.popup = function(parameters) {
487
588
  : $()
488
589
  ;
489
590
  },
490
- offstagePosition: function(position) {
491
- var
492
- boundary = {
493
- top : $(window).scrollTop(),
494
- bottom : $(window).scrollTop() + $(window).height(),
495
- left : 0,
496
- right : $(window).width()
497
- },
498
- popup = {
499
- width : $popup.width(),
500
- height : $popup.height(),
501
- offset : $popup.offset()
502
- },
503
- offstage = {},
504
- offstagePositions = []
505
- ;
506
- position = position || false;
507
- if(popup.offset && position) {
508
- module.verbose('Checking if outside viewable area', popup.offset);
509
- offstage = {
510
- top : (popup.offset.top < boundary.top),
511
- bottom : (popup.offset.top + popup.height > boundary.bottom),
512
- right : (popup.offset.left + popup.width > boundary.right),
513
- left : (popup.offset.left < boundary.left)
514
- };
515
- }
516
- // return only boundaries that have been surpassed
517
- $.each(offstage, function(direction, isOffstage) {
518
- if(isOffstage) {
519
- offstagePositions.push(direction);
520
- }
521
- });
522
- return (offstagePositions.length > 0)
523
- ? offstagePositions.join(' ')
524
- : false
525
- ;
526
- },
527
591
  positions: function() {
528
592
  return {
529
593
  'top left' : false,
@@ -596,135 +660,134 @@ $.fn.popup = function(parameters) {
596
660
  },
597
661
 
598
662
  set: {
599
- position: function(position, arrowOffset) {
600
- var
601
- windowWidth = $(window).width(),
602
- windowHeight = $(window).height(),
603
-
604
- targetWidth = $target.outerWidth(),
605
- targetHeight = $target.outerHeight(),
663
+ position: function(position, calculations) {
606
664
 
607
- popupWidth = $popup.outerWidth(),
608
- popupHeight = $popup.outerHeight(),
609
-
610
- parentWidth = $offsetParent.outerWidth(),
611
- parentHeight = $offsetParent.outerHeight(),
612
-
613
- distanceAway = settings.distanceAway,
614
-
615
- targetElement = $target[0],
665
+ // exit conditions
666
+ if($target.length === 0 || $popup.length === 0) {
667
+ module.error(error.notFound);
668
+ return;
669
+ }
670
+ var
671
+ offset,
672
+ distanceAway,
673
+ target,
674
+ popup,
675
+ parent,
676
+ positioning,
677
+ popupOffset,
678
+ distanceFromBoundary
679
+ ;
616
680
 
617
- marginTop = (settings.inline)
618
- ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
619
- : 0,
620
- marginLeft = (settings.inline)
621
- ? parseInt( window.getComputedStyle(targetElement).getPropertyValue(module.is.rtl() ? 'margin-right' : 'margin-left'), 10)
622
- : 0,
681
+ calculations = calculations || module.get.calculations();
682
+ position = position || $module.data(metadata.position) || settings.position;
623
683
 
624
- target = (settings.inline || settings.popup)
625
- ? $target.position()
626
- : $target.offset(),
684
+ offset = $module.data(metadata.offset) || settings.offset;
685
+ distanceAway = settings.distanceAway;
627
686
 
628
- computedPosition,
629
- positioning,
630
- offstagePosition
631
- ;
632
- position = position || $module.data(metadata.position) || settings.position;
633
- arrowOffset = arrowOffset || $module.data(metadata.offset) || settings.offset;
687
+ // shorthand
688
+ target = calculations.target;
689
+ popup = calculations.popup;
690
+ parent = calculations.parent;
634
691
 
635
- if(searchDepth == settings.maxSearchDepth && settings.lastResort) {
636
- module.debug('Using last resort position to display', settings.lastResort);
637
- position = settings.lastResort;
692
+ if(target.width === 0 && target.height === 0) {
693
+ module.debug('Popup target is hidden, no action taken');
694
+ return false;
638
695
  }
639
696
 
640
697
  if(settings.inline) {
641
- module.debug('Adding targets margin to calculation');
698
+ module.debug('Adding margin to calculation', target.margin);
642
699
  if(position == 'left center' || position == 'right center') {
643
- arrowOffset += marginTop;
644
- distanceAway += -marginLeft;
700
+ offset += target.margin.top;
701
+ distanceAway += -target.margin.left;
645
702
  }
646
703
  else if (position == 'top left' || position == 'top center' || position == 'top right') {
647
- arrowOffset += marginLeft;
648
- distanceAway -= marginTop;
704
+ offset += target.margin.left;
705
+ distanceAway -= target.margin.top;
649
706
  }
650
707
  else {
651
- arrowOffset += marginLeft;
652
- distanceAway += marginTop;
708
+ offset += target.margin.left;
709
+ distanceAway += target.margin.top;
653
710
  }
654
711
  }
655
- module.debug('Calculating popup positioning', position);
656
712
 
657
- computedPosition = position;
713
+ module.debug('Determining popup position from calculations', position, calculations);
714
+
658
715
  if (module.is.rtl()) {
659
- computedPosition = computedPosition.replace(/left|right/g, function (match) {
716
+ position = position.replace(/left|right/g, function (match) {
660
717
  return (match == 'left')
661
718
  ? 'right'
662
719
  : 'left'
663
720
  ;
664
721
  });
665
- module.debug('RTL: Popup positioning updated', computedPosition);
722
+ module.debug('RTL: Popup position updated', position);
723
+ }
724
+
725
+ // if last attempt use specified last resort position
726
+ if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') {
727
+ position = settings.lastResort;
666
728
  }
667
- switch (computedPosition) {
729
+
730
+ switch (position) {
668
731
  case 'top left':
669
732
  positioning = {
670
733
  top : 'auto',
671
- bottom : parentHeight - target.top + distanceAway,
672
- left : target.left + arrowOffset,
734
+ bottom : parent.height - target.top + distanceAway,
735
+ left : target.left + offset,
673
736
  right : 'auto'
674
737
  };
675
738
  break;
676
739
  case 'top center':
677
740
  positioning = {
678
- bottom : parentHeight - target.top + distanceAway,
679
- left : target.left + (targetWidth / 2) - (popupWidth / 2) + arrowOffset,
741
+ bottom : parent.height - target.top + distanceAway,
742
+ left : target.left + (target.width / 2) - (popup.width / 2) + offset,
680
743
  top : 'auto',
681
744
  right : 'auto'
682
745
  };
683
746
  break;
684
747
  case 'top right':
685
748
  positioning = {
686
- bottom : parentHeight - target.top + distanceAway,
687
- right : parentWidth - target.left - targetWidth - arrowOffset,
749
+ bottom : parent.height - target.top + distanceAway,
750
+ right : parent.width - target.left - target.width - offset,
688
751
  top : 'auto',
689
752
  left : 'auto'
690
753
  };
691
754
  break;
692
755
  case 'left center':
693
756
  positioning = {
694
- top : target.top + (targetHeight / 2) - (popupHeight / 2) + arrowOffset,
695
- right : parentWidth - target.left + distanceAway,
757
+ top : target.top + (target.height / 2) - (popup.height / 2) + offset,
758
+ right : parent.width - target.left + distanceAway,
696
759
  left : 'auto',
697
760
  bottom : 'auto'
698
761
  };
699
762
  break;
700
763
  case 'right center':
701
764
  positioning = {
702
- top : target.top + (targetHeight / 2) - (popupHeight / 2) + arrowOffset,
703
- left : target.left + targetWidth + distanceAway,
765
+ top : target.top + (target.height / 2) - (popup.height / 2) + offset,
766
+ left : target.left + target.width + distanceAway,
704
767
  bottom : 'auto',
705
768
  right : 'auto'
706
769
  };
707
770
  break;
708
771
  case 'bottom left':
709
772
  positioning = {
710
- top : target.top + targetHeight + distanceAway,
711
- left : target.left + arrowOffset,
773
+ top : target.top + target.height + distanceAway,
774
+ left : target.left + offset,
712
775
  bottom : 'auto',
713
776
  right : 'auto'
714
777
  };
715
778
  break;
716
779
  case 'bottom center':
717
780
  positioning = {
718
- top : target.top + targetHeight + distanceAway,
719
- left : target.left + (targetWidth / 2) - (popupWidth / 2) + arrowOffset,
781
+ top : target.top + target.height + distanceAway,
782
+ left : target.left + (target.width / 2) - (popup.width / 2) + offset,
720
783
  bottom : 'auto',
721
784
  right : 'auto'
722
785
  };
723
786
  break;
724
787
  case 'bottom right':
725
788
  positioning = {
726
- top : target.top + targetHeight + distanceAway,
727
- right : parentWidth - target.left - targetWidth - arrowOffset,
789
+ top : target.top + target.height + distanceAway,
790
+ right : parent.width - target.left - target.width - offset,
728
791
  left : 'auto',
729
792
  bottom : 'auto'
730
793
  };
@@ -743,42 +806,50 @@ $.fn.popup = function(parameters) {
743
806
  .addClass(position)
744
807
  .addClass(className.loading)
745
808
  ;
746
- // check if is offstage
747
- offstagePosition = module.get.offstagePosition(position);
748
809
 
749
- // recursively find new positioning
750
- if(offstagePosition) {
751
- module.debug('Popup cant fit into viewport', offstagePosition);
810
+ popupOffset = module.get.popupOffset();
811
+
812
+ // see if any boundaries are surpassed with this tentative position
813
+ distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations);
814
+
815
+ if( module.is.offstage(distanceFromBoundary, position) ) {
816
+ module.debug('Position is outside viewport', position);
752
817
  if(searchDepth < settings.maxSearchDepth) {
753
818
  searchDepth++;
754
819
  position = module.get.nextPosition(position);
755
820
  module.debug('Trying new position', position);
756
821
  return ($popup)
757
- ? module.set.position(position)
822
+ ? module.set.position(position, calculations)
758
823
  : false
759
824
  ;
760
825
  }
761
- else if(!settings.lastResort) {
762
- module.debug('Popup could not find a position in view', $popup);
763
- // module.error(error.cannotPlace, element);
764
- module.remove.attempts();
765
- module.remove.loading();
766
- module.reset();
767
- return false;
826
+ else {
827
+ if(settings.lastResort) {
828
+ module.debug('No position found, showing with last position');
829
+ }
830
+ else {
831
+ module.debug('Popup could not find a position to display', $popup);
832
+ module.error(error.cannotPlace, element);
833
+ module.remove.attempts();
834
+ module.remove.loading();
835
+ module.reset();
836
+ return false;
837
+ }
768
838
  }
769
839
  }
770
-
771
840
  module.debug('Position is on stage', position);
772
841
  module.remove.attempts();
773
- module.set.fluidWidth();
774
842
  module.remove.loading();
843
+ if( settings.setFluidWidth && module.is.fluid() ) {
844
+ module.set.fluidWidth(calculations);
845
+ }
775
846
  return true;
776
847
  },
777
848
 
778
- fluidWidth: function() {
779
- if( settings.setFluidWidth && $popup.hasClass(className.fluid) ) {
780
- $popup.css('width', $offsetParent.width());
781
- }
849
+ fluidWidth: function(calculations) {
850
+ calculations = calculations || module.get.calculations();
851
+ module.debug('Automatically setting element width to parent width', calculations.parent.width);
852
+ $popup.css('width', calculations.container.width);
782
853
  },
783
854
 
784
855
  visible: function() {
@@ -808,6 +879,11 @@ $.fn.popup = function(parameters) {
808
879
  .on('click' + eventNamespace, module.toggle)
809
880
  ;
810
881
  }
882
+ if(settings.on == 'hover' && hasTouch) {
883
+ $module
884
+ .on('touchstart' + eventNamespace, module.event.touchstart)
885
+ ;
886
+ }
811
887
  else if( module.get.startEvent() ) {
812
888
  $module
813
889
  .on(module.get.startEvent() + eventNamespace, module.event.start)
@@ -828,21 +904,30 @@ $.fn.popup = function(parameters) {
828
904
  ;
829
905
  }
830
906
  },
831
- close:function() {
832
- if(settings.hideOnScroll === true || settings.hideOnScroll == 'auto' && settings.on != 'click') {
907
+ close: function() {
908
+ if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
833
909
  $document
834
- .one(module.get.scrollEvent() + elementNamespace, module.hideGracefully)
910
+ .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
835
911
  ;
836
912
  $context
837
- .one(module.get.scrollEvent() + elementNamespace, module.hideGracefully)
913
+ .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
914
+ ;
915
+ }
916
+ if(settings.on == 'hover' && openedWithTouch) {
917
+ module.verbose('Binding popup close event to document');
918
+ $document
919
+ .on('touchstart' + elementNamespace, function(event) {
920
+ module.verbose('Touched away from popup');
921
+ module.event.hideGracefully.call(element, event);
922
+ })
838
923
  ;
839
924
  }
840
925
  if(settings.on == 'click' && settings.closable) {
841
926
  module.verbose('Binding popup close event to document');
842
927
  $document
843
928
  .on('click' + elementNamespace, function(event) {
844
- module.verbose('Pop-up clickaway intent detected');
845
- module.hideGracefully.call(element, event);
929
+ module.verbose('Clicked away from popup');
930
+ module.event.hideGracefully.call(element, event);
846
931
  })
847
932
  ;
848
933
  }
@@ -851,7 +936,7 @@ $.fn.popup = function(parameters) {
851
936
 
852
937
  unbind: {
853
938
  close: function() {
854
- if(settings.hideOnScroll === true || settings.hideOnScroll == 'auto' && settings.on != 'click') {
939
+ if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
855
940
  $document
856
941
  .off('scroll' + elementNamespace, module.hide)
857
942
  ;
@@ -859,6 +944,12 @@ $.fn.popup = function(parameters) {
859
944
  .off('scroll' + elementNamespace, module.hide)
860
945
  ;
861
946
  }
947
+ if(settings.on == 'hover' && openedWithTouch) {
948
+ $document
949
+ .off('touchstart' + elementNamespace)
950
+ ;
951
+ openedWithTouch = false;
952
+ }
862
953
  if(settings.on == 'click' && settings.closable) {
863
954
  module.verbose('Removing close event from document');
864
955
  $document
@@ -875,14 +966,35 @@ $.fn.popup = function(parameters) {
875
966
  },
876
967
 
877
968
  is: {
969
+ offstage: function(distanceFromBoundary, position) {
970
+ var
971
+ offstage = []
972
+ ;
973
+ // return boundaries that have been surpassed
974
+ $.each(distanceFromBoundary, function(direction, distance) {
975
+ if(distance < -settings.jitter) {
976
+ module.debug('Position exceeds allowable distance from edge', direction, distance, position);
977
+ offstage.push(direction);
978
+ }
979
+ });
980
+ if(offstage.length > 0) {
981
+ return true;
982
+ }
983
+ else {
984
+ return false;
985
+ }
986
+ },
878
987
  active: function() {
879
988
  return $module.hasClass(className.active);
880
989
  },
881
990
  animating: function() {
882
- return ( $popup && $popup.is(':animated') || $popup.hasClass(className.animating) );
991
+ return ( $popup && $popup.hasClass(className.animating) );
992
+ },
993
+ fluid: function() {
994
+ return ( $popup && $popup.hasClass(className.fluid));
883
995
  },
884
996
  visible: function() {
885
- return $popup && $popup.is(':visible');
997
+ return $popup && $popup.hasClass(className.visible);
886
998
  },
887
999
  dropdown: function() {
888
1000
  return $module.hasClass(className.dropdown);
@@ -977,7 +1089,7 @@ $.fn.popup = function(parameters) {
977
1089
  });
978
1090
  }
979
1091
  clearTimeout(module.performance.timer);
980
- module.performance.timer = setTimeout(module.performance.display, 100);
1092
+ module.performance.timer = setTimeout(module.performance.display, 500);
981
1093
  },
982
1094
  display: function() {
983
1095
  var
@@ -1088,61 +1200,118 @@ $.fn.popup.settings = {
1088
1200
 
1089
1201
  name : 'Popup',
1090
1202
 
1203
+ // module settings
1091
1204
  debug : false,
1092
- verbose : true,
1205
+ verbose : false,
1093
1206
  performance : true,
1094
1207
  namespace : 'popup',
1095
1208
 
1209
+ // callback only when element added to dom
1096
1210
  onCreate : function(){},
1211
+
1212
+ // callback before element removed from dom
1097
1213
  onRemove : function(){},
1098
1214
 
1215
+ // callback before show animation
1099
1216
  onShow : function(){},
1217
+
1218
+ // callback after show animation
1100
1219
  onVisible : function(){},
1220
+
1221
+ // callback before hide animation
1101
1222
  onHide : function(){},
1223
+
1224
+ // callback after hide animation
1102
1225
  onHidden : function(){},
1103
1226
 
1227
+ // when to show popup
1228
+ on : 'hover',
1229
+
1230
+ // whether to add touchstart events when using hover
1231
+ addTouchEvents : true,
1232
+
1233
+ // default position relative to element
1234
+ position : 'top left',
1235
+
1236
+ // name of variation to use
1104
1237
  variation : '',
1238
+
1239
+ // whether popup should be moved to context
1240
+ movePopup : true,
1241
+
1242
+ // element which popup should be relative to
1243
+ target : false,
1244
+
1245
+ // jq selector or element that should be used as popup
1246
+ popup : false,
1247
+
1248
+ // popup should remain inline next to activator
1249
+ inline : false,
1250
+
1251
+ // popup should be removed from page on hide
1252
+ preserve : false,
1253
+
1254
+ // popup should not close when being hovered on
1255
+ hoverable : false,
1256
+
1257
+ // explicitly set content
1105
1258
  content : false,
1259
+
1260
+ // explicitly set html
1106
1261
  html : false,
1262
+
1263
+ // explicitly set title
1107
1264
  title : false,
1108
1265
 
1109
- on : 'hover',
1266
+ // whether automatically close on clickaway when on click
1110
1267
  closable : true,
1268
+
1269
+ // automatically hide on scroll
1111
1270
  hideOnScroll : 'auto',
1112
- exclusive : true,
1113
1271
 
1272
+ // hide other popups on show
1273
+ exclusive : false,
1274
+
1275
+ // context to attach popups
1114
1276
  context : 'body',
1115
1277
 
1116
- position : 'top left',
1278
+ // position to prefer when calculating new position
1117
1279
  prefer : 'opposite',
1280
+
1281
+ // specify position to appear even if it doesn't fit
1118
1282
  lastResort : false,
1119
1283
 
1284
+ // delay used to prevent accidental refiring of animations due to user error
1120
1285
  delay : {
1121
- show : 30,
1122
- hide : 0
1286
+ show : 50,
1287
+ hide : 70
1123
1288
  },
1124
1289
 
1290
+ // whether fluid variation should assign width explicitly
1125
1291
  setFluidWidth : true,
1126
- movePopup : true,
1127
-
1128
- target : false,
1129
- popup : false,
1130
- inline : false,
1131
- preserve : false,
1132
- hoverable : false,
1133
1292
 
1293
+ // transition settings
1134
1294
  duration : 200,
1135
- easing : 'easeOutQuint',
1136
1295
  transition : 'scale',
1137
1296
 
1297
+ // distance away from activating element in px
1138
1298
  distanceAway : 0,
1299
+
1300
+ // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding)
1301
+ jitter : 2,
1302
+
1303
+ // offset on aligning axis from calculated position
1139
1304
  offset : 0,
1140
- maxSearchDepth : 20,
1305
+
1306
+ // maximum times to look for a position before failing (9 positions total)
1307
+ maxSearchDepth : 15,
1141
1308
 
1142
1309
  error: {
1143
1310
  invalidPosition : 'The position you specified is not a valid position',
1144
- cannotPlace : 'No visible position could be found for the popup',
1145
- method : 'The method you called is not defined.'
1311
+ cannotPlace : 'Popup does not fit within the boundaries of the viewport',
1312
+ method : 'The method you called is not defined.',
1313
+ noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
1314
+ notFound : 'The target or popup you specified does not exist on the page'
1146
1315
  },
1147
1316
 
1148
1317
  metadata: {
@@ -1213,12 +1382,5 @@ $.fn.popup.settings = {
1213
1382
 
1214
1383
  };
1215
1384
 
1216
- // Adds easing
1217
- $.extend( $.easing, {
1218
- easeOutQuad: function (x, t, b, c, d) {
1219
- return -c *(t/=d)*(t-2) + b;
1220
- }
1221
- });
1222
-
1223
1385
 
1224
1386
  })( jQuery, window , document );