semantic-ui-sass 0.19.3.1 → 1.7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +5 -6
  4. data/app/assets/fonts/semantic-ui/icons.eot +0 -0
  5. data/app/assets/fonts/semantic-ui/icons.otf +0 -0
  6. data/app/assets/fonts/semantic-ui/icons.svg +472 -367
  7. data/app/assets/fonts/semantic-ui/icons.ttf +0 -0
  8. data/app/assets/fonts/semantic-ui/icons.woff +0 -0
  9. data/app/assets/images/semantic-ui/flags.png +0 -0
  10. data/app/assets/javascripts/semantic-ui.js +9 -5
  11. data/app/assets/javascripts/semantic-ui/accordion.js +169 -102
  12. data/app/assets/javascripts/semantic-ui/api.js +840 -0
  13. data/app/assets/javascripts/semantic-ui/checkbox.js +203 -46
  14. data/app/assets/javascripts/semantic-ui/{behavior/colorize.js → colorize.js} +4 -2
  15. data/app/assets/javascripts/semantic-ui/dimmer.js +110 -76
  16. data/app/assets/javascripts/semantic-ui/dropdown.js +897 -285
  17. data/app/assets/javascripts/semantic-ui/{behavior/form.js → form.js} +127 -42
  18. data/app/assets/javascripts/semantic-ui/modal.js +294 -219
  19. data/app/assets/javascripts/semantic-ui/nag.js +120 -186
  20. data/app/assets/javascripts/semantic-ui/popup.js +491 -223
  21. data/app/assets/javascripts/semantic-ui/progress.js +779 -0
  22. data/app/assets/javascripts/semantic-ui/rating.js +66 -22
  23. data/app/assets/javascripts/semantic-ui/search.js +219 -99
  24. data/app/assets/javascripts/semantic-ui/shape.js +72 -29
  25. data/app/assets/javascripts/semantic-ui/sidebar.js +678 -142
  26. data/app/assets/javascripts/semantic-ui/site.js +487 -0
  27. data/app/assets/javascripts/semantic-ui/{behavior/state.js → state.js} +116 -151
  28. data/app/assets/javascripts/semantic-ui/sticky.js +771 -0
  29. data/app/assets/javascripts/semantic-ui/tab.js +680 -603
  30. data/app/assets/javascripts/semantic-ui/transition.js +269 -158
  31. data/app/assets/javascripts/semantic-ui/video.js +113 -32
  32. data/app/assets/javascripts/semantic-ui/visibility.js +970 -0
  33. data/app/assets/javascripts/semantic-ui/visit.js +513 -0
  34. data/app/assets/stylesheets/semantic-ui.scss +2 -0
  35. data/app/assets/stylesheets/semantic-ui/collections/_breadcrumb.scss +58 -14
  36. data/app/assets/stylesheets/semantic-ui/collections/_form.scss +464 -372
  37. data/app/assets/stylesheets/semantic-ui/collections/_grid.scss +1385 -533
  38. data/app/assets/stylesheets/semantic-ui/collections/_menu.scss +482 -655
  39. data/app/assets/stylesheets/semantic-ui/collections/_message.scss +238 -139
  40. data/app/assets/stylesheets/semantic-ui/collections/_table.scss +631 -280
  41. data/app/assets/stylesheets/semantic-ui/elements/_all.scss +3 -2
  42. data/app/assets/stylesheets/semantic-ui/elements/_button.scss +1614 -657
  43. data/app/assets/stylesheets/semantic-ui/elements/_divider.scss +143 -80
  44. data/app/assets/stylesheets/semantic-ui/elements/_flag.scss +1018 -0
  45. data/app/assets/stylesheets/semantic-ui/elements/_header.scss +302 -145
  46. data/app/assets/stylesheets/semantic-ui/elements/_icon.scss +1653 -1365
  47. data/app/assets/stylesheets/semantic-ui/elements/_image.scss +160 -59
  48. data/app/assets/stylesheets/semantic-ui/elements/_input.scss +247 -118
  49. data/app/assets/stylesheets/semantic-ui/elements/_label.scss +501 -470
  50. data/app/assets/stylesheets/semantic-ui/elements/_list.scss +888 -0
  51. data/app/assets/stylesheets/semantic-ui/elements/_loader.scss +189 -98
  52. data/app/assets/stylesheets/semantic-ui/elements/_rail.scss +125 -0
  53. data/app/assets/stylesheets/semantic-ui/elements/_reveal.scss +147 -212
  54. data/app/assets/stylesheets/semantic-ui/elements/_segment.scss +328 -190
  55. data/app/assets/stylesheets/semantic-ui/elements/_step.scss +261 -185
  56. data/app/assets/stylesheets/semantic-ui/globals/_all.scss +2 -0
  57. data/app/assets/stylesheets/semantic-ui/globals/_reset.scss +430 -0
  58. data/app/assets/stylesheets/semantic-ui/globals/_site.scss +128 -0
  59. data/app/assets/stylesheets/semantic-ui/modules/_accordion.scss +190 -106
  60. data/app/assets/stylesheets/semantic-ui/modules/_all.scss +2 -1
  61. data/app/assets/stylesheets/semantic-ui/modules/_checkbox.scss +303 -201
  62. data/app/assets/stylesheets/semantic-ui/modules/_dimmer.scss +72 -63
  63. data/app/assets/stylesheets/semantic-ui/modules/_dropdown.scss +711 -331
  64. data/app/assets/stylesheets/semantic-ui/modules/_modal.scss +262 -140
  65. data/app/assets/stylesheets/semantic-ui/modules/_nag.scss +82 -71
  66. data/app/assets/stylesheets/semantic-ui/modules/_popup.scss +163 -119
  67. data/app/assets/stylesheets/semantic-ui/modules/_progress.scss +435 -0
  68. data/app/assets/stylesheets/semantic-ui/modules/_rating.scss +163 -68
  69. data/app/assets/stylesheets/semantic-ui/modules/_search.scss +223 -150
  70. data/app/assets/stylesheets/semantic-ui/modules/_shape.scss +39 -40
  71. data/app/assets/stylesheets/semantic-ui/modules/_sidebar.scss +413 -147
  72. data/app/assets/stylesheets/semantic-ui/modules/_sticky.scss +80 -0
  73. data/app/assets/stylesheets/semantic-ui/modules/_tab.scss +49 -20
  74. data/app/assets/stylesheets/semantic-ui/modules/_transition.scss +542 -568
  75. data/app/assets/stylesheets/semantic-ui/modules/_video.scss +69 -37
  76. data/app/assets/stylesheets/semantic-ui/views/_ad.scss +265 -0
  77. data/app/assets/stylesheets/semantic-ui/views/_all.scss +1 -1
  78. data/app/assets/stylesheets/semantic-ui/views/_card.scss +758 -0
  79. data/app/assets/stylesheets/semantic-ui/views/_comment.scss +133 -92
  80. data/app/assets/stylesheets/semantic-ui/views/_feed.scss +200 -87
  81. data/app/assets/stylesheets/semantic-ui/views/_item.scss +298 -523
  82. data/app/assets/stylesheets/semantic-ui/views/_statistic.scss +390 -12
  83. data/lib/semantic/ui/sass/version.rb +2 -2
  84. data/tasks/converter.rb +99 -216
  85. metadata +22 -27
  86. data/app/assets/fonts/semantic-ui/basic.icons.eot +0 -0
  87. data/app/assets/fonts/semantic-ui/basic.icons.svg +0 -450
  88. data/app/assets/fonts/semantic-ui/basic.icons.ttf +0 -0
  89. data/app/assets/fonts/semantic-ui/basic.icons.woff +0 -0
  90. data/app/assets/images/semantic-ui/loader-large-inverted.gif +0 -0
  91. data/app/assets/images/semantic-ui/loader-large.gif +0 -0
  92. data/app/assets/images/semantic-ui/loader-medium-inverted.gif +0 -0
  93. data/app/assets/images/semantic-ui/loader-medium.gif +0 -0
  94. data/app/assets/images/semantic-ui/loader-mini-inverted.gif +0 -0
  95. data/app/assets/images/semantic-ui/loader-mini.gif +0 -0
  96. data/app/assets/images/semantic-ui/loader-small-inverted.gif +0 -0
  97. data/app/assets/images/semantic-ui/loader-small.gif +0 -0
  98. data/app/assets/javascripts/semantic-ui/behavior/api.js +0 -634
  99. data/app/assets/javascripts/semantic-ui/chatroom.js +0 -772
  100. data/app/assets/stylesheets/semantic-ui/depends/_basic.icon.scss +0 -4
  101. data/app/assets/stylesheets/semantic-ui/depends/_icon.scss +0 -4
  102. data/app/assets/stylesheets/semantic-ui/depends/_loader.scss +0 -8
  103. data/app/assets/stylesheets/semantic-ui/elements/_basic.icon.scss +0 -1124
  104. data/app/assets/stylesheets/semantic-ui/elements/_progress.scss +0 -280
  105. data/app/assets/stylesheets/semantic-ui/modules/_chatroom.scss +0 -299
  106. data/app/assets/stylesheets/semantic-ui/modules/_reveal.scss +0 -322
  107. data/app/assets/stylesheets/semantic-ui/views/_list.scss +0 -700
@@ -3,7 +3,7 @@
3
3
  * http://github.com/jlukic/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2014 Contributors
6
+ * Copyright 2014 Contributor
7
7
  * Released under the MIT license
8
8
  * http://opensource.org/licenses/MIT
9
9
  *
@@ -11,19 +11,22 @@
11
11
 
12
12
  ;(function ($, window, document, undefined) {
13
13
 
14
+ "use strict";
15
+
14
16
  $.fn.popup = function(parameters) {
15
17
  var
16
- $allModules = $(this),
17
- $document = $(document),
18
+ $allModules = $(this),
19
+ $document = $(document),
18
20
 
19
- moduleSelector = $allModules.selector || '',
21
+ moduleSelector = $allModules.selector || '',
20
22
 
21
- time = new Date().getTime(),
22
- performance = [],
23
+ hasTouch = ('ontouchstart' in document.documentElement),
24
+ time = new Date().getTime(),
25
+ performance = [],
23
26
 
24
- query = arguments[0],
25
- methodInvoked = (typeof query == 'string'),
26
- queryArguments = [].slice.call(arguments, 1),
27
+ query = arguments[0],
28
+ methodInvoked = (typeof query == 'string'),
29
+ queryArguments = [].slice.call(arguments, 1),
27
30
 
28
31
  returnedValue
29
32
  ;
@@ -34,34 +37,31 @@ $.fn.popup = function(parameters) {
34
37
  ? $.extend(true, {}, $.fn.popup.settings, parameters)
35
38
  : $.extend({}, $.fn.popup.settings),
36
39
 
37
- selector = settings.selector,
38
- className = settings.className,
39
- error = settings.error,
40
- metadata = settings.metadata,
41
- namespace = settings.namespace,
40
+ selector = settings.selector,
41
+ className = settings.className,
42
+ error = settings.error,
43
+ metadata = settings.metadata,
44
+ namespace = settings.namespace,
42
45
 
43
- eventNamespace = '.' + settings.namespace,
44
- moduleNamespace = 'module-' + namespace,
46
+ eventNamespace = '.' + settings.namespace,
47
+ moduleNamespace = 'module-' + namespace,
45
48
 
46
- $module = $(this),
47
- $context = $(settings.context),
48
- $target = (settings.target)
49
+ $module = $(this),
50
+ $context = $(settings.context),
51
+ $target = (settings.target)
49
52
  ? $(settings.target)
50
53
  : $module,
51
54
 
52
- $window = $(window),
53
-
54
- $offsetParent = (settings.inline)
55
- ? $target.offsetParent()
56
- : $window,
57
- $popup = (settings.inline)
58
- ? $target.next(settings.selector.popup)
59
- : $window.children(settings.selector.popup).last(),
55
+ $window = $(window),
56
+ $body = $('body'),
57
+ $popup,
58
+ $offsetParent,
60
59
 
61
- searchDepth = 0,
60
+ searchDepth = 0,
61
+ triedPositions = false,
62
62
 
63
- element = this,
64
- instance = $module.data(moduleNamespace),
63
+ element = this,
64
+ instance = $module.data(moduleNamespace),
65
65
  module
66
66
  ;
67
67
 
@@ -70,12 +70,13 @@ $.fn.popup = function(parameters) {
70
70
  // binds events
71
71
  initialize: function() {
72
72
  module.debug('Initializing module', $module);
73
+ module.refresh();
73
74
  if(settings.on == 'click') {
74
75
  $module
75
- .on('click', module.toggle)
76
+ .on('click' + eventNamespace, module.toggle)
76
77
  ;
77
78
  }
78
- else {
79
+ else if( module.get.startEvent() ) {
79
80
  $module
80
81
  .on(module.get.startEvent() + eventNamespace, module.event.start)
81
82
  .on(module.get.endEvent() + eventNamespace, module.event.end)
@@ -87,6 +88,12 @@ $.fn.popup = function(parameters) {
87
88
  $window
88
89
  .on('resize' + eventNamespace, module.event.resize)
89
90
  ;
91
+ if( !module.exists() ) {
92
+ module.create();
93
+ }
94
+ else if(settings.hoverable) {
95
+ module.bind.popup();
96
+ }
90
97
  module.instantiate();
91
98
  },
92
99
 
@@ -99,23 +106,50 @@ $.fn.popup = function(parameters) {
99
106
  },
100
107
 
101
108
  refresh: function() {
102
- if(settings.inline) {
103
- $popup = $target.next(selector.popup);
104
- $offsetParent = $target.offsetParent();
109
+ if(settings.popup) {
110
+ $popup = $(settings.popup);
105
111
  }
106
112
  else {
107
- $popup = $window.children(selector.popup).last();
113
+ if(settings.inline) {
114
+ $popup = $target.next(settings.selector.popup);
115
+ }
116
+ }
117
+ if(settings.popup) {
118
+ $popup.addClass(className.loading);
119
+ if($popup.offsetParent()[0] !== $module.offsetParent()[0]) {
120
+ module.debug('Moving popup to the same offset parent as activating element');
121
+ $offsetParent = $module.offsetParent();
122
+ $popup
123
+ .detach()
124
+ .appendTo($offsetParent)
125
+ ;
126
+ }
127
+ $popup.removeClass(className.loading);
128
+ }
129
+ else {
130
+ $offsetParent = (settings.inline)
131
+ ? $target.offsetParent()
132
+ : $body
133
+ ;
134
+ }
135
+ if( $offsetParent.is('html') ) {
136
+ module.debug('Page is popups offset parent');
137
+ $offsetParent = $body;
108
138
  }
109
139
  },
110
140
 
141
+ reposition: function() {
142
+ module.refresh();
143
+ module.set.position();
144
+ },
145
+
111
146
  destroy: function() {
112
147
  module.debug('Destroying previous module');
113
- $window
114
- .off(eventNamespace)
115
- ;
116
- $popup
117
- .remove()
118
- ;
148
+ if($popup && !settings.preserve) {
149
+ module.removePopup();
150
+ }
151
+ clearTimeout(module.hideTimer);
152
+ clearTimeout(module.showTimer);
119
153
  $module
120
154
  .off(eventNamespace)
121
155
  .removeData(moduleNamespace)
@@ -124,17 +158,30 @@ $.fn.popup = function(parameters) {
124
158
 
125
159
  event: {
126
160
  start: function(event) {
127
- module.timer = setTimeout(function() {
128
- if( module.is.hidden() ) {
161
+ var
162
+ delay = ($.isPlainObject(settings.delay))
163
+ ? settings.delay.show
164
+ : settings.delay
165
+ ;
166
+ clearTimeout(module.hideTimer);
167
+ module.showTimer = setTimeout(function() {
168
+ if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
129
169
  module.show();
130
170
  }
131
- }, settings.delay);
171
+ }, delay);
132
172
  },
133
173
  end: function() {
134
- clearTimeout(module.timer);
135
- if( module.is.visible() ) {
136
- module.hide();
137
- }
174
+ var
175
+ delay = ($.isPlainObject(settings.delay))
176
+ ? settings.delay.hide
177
+ : settings.delay
178
+ ;
179
+ clearTimeout(module.showTimer);
180
+ module.hideTimer = setTimeout(function() {
181
+ if(module.is.visible() ) {
182
+ module.hide();
183
+ }
184
+ }, delay);
138
185
  },
139
186
  resize: function() {
140
187
  if( module.is.visible() ) {
@@ -145,7 +192,6 @@ $.fn.popup = function(parameters) {
145
192
 
146
193
  // generates popup html from metadata
147
194
  create: function() {
148
- module.debug('Creating pop-up html');
149
195
  var
150
196
  html = $module.data(metadata.html) || settings.html,
151
197
  variation = $module.data(metadata.variation) || settings.variation,
@@ -153,8 +199,9 @@ $.fn.popup = function(parameters) {
153
199
  content = $module.data(metadata.content) || $module.attr('title') || settings.content
154
200
  ;
155
201
  if(html || content || title) {
202
+ module.debug('Creating pop-up html');
156
203
  if(!html) {
157
- html = settings.template({
204
+ html = settings.templates.popup({
158
205
  title : title,
159
206
  content : content
160
207
  });
@@ -164,24 +211,38 @@ $.fn.popup = function(parameters) {
164
211
  .addClass(variation)
165
212
  .html(html)
166
213
  ;
214
+ if(variation) {
215
+ $popup
216
+ .addClass(variation)
217
+ ;
218
+ }
167
219
  if(settings.inline) {
168
220
  module.verbose('Inserting popup element inline', $popup);
169
221
  $popup
170
- .data(moduleNamespace, instance)
171
222
  .insertAfter($module)
172
223
  ;
173
224
  }
174
225
  else {
175
226
  module.verbose('Appending popup element to body', $popup);
176
227
  $popup
177
- .data(moduleNamespace, instance)
178
228
  .appendTo( $context )
179
229
  ;
180
230
  }
181
- $.proxy(settings.onCreate, $popup)();
231
+ if(settings.hoverable) {
232
+ module.bind.popup();
233
+ }
234
+ $.proxy(settings.onCreate, $popup)(element);
235
+ }
236
+ else if($target.next(settings.selector.popup).size() !== 0) {
237
+ module.verbose('Pre-existing popup found, reverting to inline');
238
+ settings.inline = true;
239
+ module.refresh();
240
+ if(settings.hoverable) {
241
+ module.bind.popup();
242
+ }
182
243
  }
183
244
  else {
184
- module.error(error.content);
245
+ module.debug('No content specified skipping display', element);
185
246
  }
186
247
  },
187
248
 
@@ -201,28 +262,27 @@ $.fn.popup = function(parameters) {
201
262
  },
202
263
 
203
264
  show: function(callback) {
204
- callback = callback || function(){};
265
+ callback = $.isFunction(callback) ? callback : function(){};
205
266
  module.debug('Showing pop-up', settings.transition);
206
- if(!settings.preserve) {
267
+ if(!settings.preserve && !settings.popup) {
207
268
  module.refresh();
208
269
  }
209
270
  if( !module.exists() ) {
210
271
  module.create();
211
272
  }
212
- module.save.conditions();
213
- module.set.position();
214
- module.animate.show(callback);
273
+ if( $popup && module.set.position() ) {
274
+ module.save.conditions();
275
+ module.animate.show(callback);
276
+ }
215
277
  },
216
278
 
217
279
 
218
280
  hide: function(callback) {
219
- callback = callback || function(){};
220
- $module
221
- .removeClass(className.visible)
222
- ;
223
- module.restore.conditions();
281
+ callback = $.isFunction(callback) ? callback : function(){};
282
+ module.remove.visible();
224
283
  module.unbind.close();
225
284
  if( module.is.visible() ) {
285
+ module.restore.conditions();
226
286
  module.animate.hide(callback);
227
287
  }
228
288
  },
@@ -246,20 +306,26 @@ $.fn.popup = function(parameters) {
246
306
  },
247
307
 
248
308
  exists: function() {
249
- if(settings.inline) {
250
- return ( $popup.size() !== 0 );
309
+ if(!$popup) {
310
+ return false;
311
+ }
312
+ if(settings.inline || settings.popup) {
313
+ return ( module.has.popup() );
251
314
  }
252
315
  else {
253
- return ( $popup.parent($context).size() );
316
+ return ( $popup.closest($context).size() > 1 )
317
+ ? true
318
+ : false
319
+ ;
254
320
  }
255
321
  },
256
322
 
257
- remove: function() {
258
- module.debug('Removing popup');
259
- $popup
260
- .remove()
261
- ;
262
- $.proxy(settings.onRemove, $popup)();
323
+ removePopup: function() {
324
+ module.debug('Removing popup', $popup);
325
+ if( module.has.popup() ) {
326
+ $popup.remove();
327
+ }
328
+ $.proxy(settings.onRemove, $popup)(element);
263
329
  },
264
330
 
265
331
  save: {
@@ -275,6 +341,7 @@ $.fn.popup = function(parameters) {
275
341
  },
276
342
  restore: {
277
343
  conditions: function() {
344
+ element.blur();
278
345
  if(module.cache && module.cache.title) {
279
346
  $module.attr('title', module.cache.title);
280
347
  module.verbose('Restoring original attributes', module.cache.title);
@@ -284,19 +351,26 @@ $.fn.popup = function(parameters) {
284
351
  },
285
352
  animate: {
286
353
  show: function(callback) {
287
- callback = callback || function(){};
288
- $module
289
- .addClass(className.visible)
290
- ;
354
+ callback = $.isFunction(callback) ? callback : function(){};
291
355
  if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
356
+ module.set.visible();
292
357
  $popup
293
- .transition(settings.transition + ' in', settings.duration, function() {
294
- module.bind.close();
295
- $.proxy(callback, element)();
358
+ .transition({
359
+ animation : settings.transition + ' in',
360
+ queue : false,
361
+ debug : settings.debug,
362
+ verbose : settings.verbose,
363
+ duration : settings.duration,
364
+ onComplete : function() {
365
+ module.bind.close();
366
+ $.proxy(callback, $popup)(element);
367
+ $.proxy(settings.onVisible, $popup)(element);
368
+ }
296
369
  })
297
370
  ;
298
371
  }
299
372
  else {
373
+ module.set.visible();
300
374
  $popup
301
375
  .stop()
302
376
  .fadeIn(settings.duration, settings.easing, function() {
@@ -305,16 +379,24 @@ $.fn.popup = function(parameters) {
305
379
  })
306
380
  ;
307
381
  }
308
- $.proxy(settings.onShow, element)();
382
+ $.proxy(settings.onShow, $popup)(element);
309
383
  },
310
384
  hide: function(callback) {
311
- callback = callback || function(){};
385
+ callback = $.isFunction(callback) ? callback : function(){};
312
386
  module.debug('Hiding pop-up');
313
387
  if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
314
388
  $popup
315
- .transition(settings.transition + ' out', settings.duration, function() {
316
- module.reset();
317
- callback();
389
+ .transition({
390
+ animation : settings.transition + ' out',
391
+ queue : false,
392
+ duration : settings.duration,
393
+ debug : settings.debug,
394
+ verbose : settings.verbose,
395
+ onComplete : function() {
396
+ module.reset();
397
+ $.proxy(callback, $popup)(element);
398
+ $.proxy(settings.onHidden, $popup)(element);
399
+ }
318
400
  })
319
401
  ;
320
402
  }
@@ -327,7 +409,7 @@ $.fn.popup = function(parameters) {
327
409
  })
328
410
  ;
329
411
  }
330
- $.proxy(settings.onHide, element)();
412
+ $.proxy(settings.onHide, $popup)(element);
331
413
  }
332
414
  },
333
415
 
@@ -339,6 +421,7 @@ $.fn.popup = function(parameters) {
339
421
  else if(settings.on == 'focus') {
340
422
  return 'focus';
341
423
  }
424
+ return false;
342
425
  },
343
426
  endEvent: function() {
344
427
  if(settings.on == 'hover') {
@@ -347,9 +430,11 @@ $.fn.popup = function(parameters) {
347
430
  else if(settings.on == 'focus') {
348
431
  return 'blur';
349
432
  }
433
+ return false;
350
434
  },
351
- offstagePosition: function() {
435
+ offstagePosition: function(position) {
352
436
  var
437
+ position = position || false,
353
438
  boundary = {
354
439
  top : $(window).scrollTop(),
355
440
  bottom : $(window).scrollTop() + $(window).height(),
@@ -357,22 +442,22 @@ $.fn.popup = function(parameters) {
357
442
  right : $(window).width()
358
443
  },
359
444
  popup = {
360
- width : $popup.width(),
361
- height : $popup.outerHeight(),
362
- position : $popup.offset()
445
+ width : $popup.width(),
446
+ height : $popup.height(),
447
+ offset : $popup.offset()
363
448
  },
364
449
  offstage = {},
365
450
  offstagePositions = []
366
451
  ;
367
- if(popup.position) {
452
+ if(popup.offset && position) {
453
+ module.verbose('Checking if outside viewable area', popup.offset);
368
454
  offstage = {
369
- top : (popup.position.top < boundary.top),
370
- bottom : (popup.position.top + popup.height > boundary.bottom),
371
- right : (popup.position.left + popup.width > boundary.right),
372
- left : (popup.position.left < boundary.left)
455
+ top : (popup.offset.top < boundary.top),
456
+ bottom : (popup.offset.top + popup.height > boundary.bottom),
457
+ right : (popup.offset.left + popup.width > boundary.right),
458
+ left : (popup.offset.left < boundary.left)
373
459
  };
374
460
  }
375
- module.verbose('Checking if outside viewable area', popup.position);
376
461
  // return only boundaries that have been surpassed
377
462
  $.each(offstage, function(direction, isOffstage) {
378
463
  if(isOffstage) {
@@ -384,55 +469,104 @@ $.fn.popup = function(parameters) {
384
469
  : false
385
470
  ;
386
471
  },
472
+ positions: function() {
473
+ return {
474
+ 'top left' : false,
475
+ 'top center' : false,
476
+ 'top right' : false,
477
+ 'bottom left' : false,
478
+ 'bottom center' : false,
479
+ 'bottom right' : false,
480
+ 'left center' : false,
481
+ 'right center' : false
482
+ };
483
+ },
387
484
  nextPosition: function(position) {
388
- switch(position) {
389
- case 'top left':
390
- position = 'bottom left';
391
- break;
392
- case 'bottom left':
393
- position = 'top right';
394
- break;
395
- case 'top right':
396
- position = 'bottom right';
397
- break;
398
- case 'bottom right':
399
- position = 'top center';
400
- break;
401
- case 'top center':
402
- position = 'bottom center';
403
- break;
404
- case 'bottom center':
405
- position = 'right center';
406
- break;
407
- case 'right center':
408
- position = 'left center';
409
- break;
410
- case 'left center':
411
- position = 'top center';
412
- break;
485
+ var
486
+ positions = position.split(' '),
487
+ verticalPosition = positions[0],
488
+ horizontalPosition = positions[1],
489
+ opposite = {
490
+ top : 'bottom',
491
+ bottom : 'top',
492
+ left : 'right',
493
+ right : 'left'
494
+ },
495
+ adjacent = {
496
+ left : 'center',
497
+ center : 'right',
498
+ right : 'left'
499
+ },
500
+ backup = {
501
+ 'top left' : 'top center',
502
+ 'top center' : 'top right',
503
+ 'top right' : 'right center',
504
+ 'right center' : 'bottom right',
505
+ 'bottom right' : 'bottom center',
506
+ 'bottom center' : 'bottom left',
507
+ 'bottom left' : 'left center',
508
+ 'left center' : 'top left'
509
+ },
510
+ adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'),
511
+ oppositeTried = false,
512
+ adjacentTried = false,
513
+ nextPosition = false
514
+ ;
515
+ if(!triedPositions) {
516
+ module.verbose('All available positions available');
517
+ triedPositions = module.get.positions();
518
+ }
519
+
520
+ module.debug('Recording last position tried', position);
521
+ triedPositions[position] = true;
522
+
523
+ if(settings.prefer === 'opposite') {
524
+ nextPosition = [opposite[verticalPosition], horizontalPosition];
525
+ nextPosition = nextPosition.join(' ');
526
+ oppositeTried = (triedPositions[nextPosition] === true);
527
+ module.debug('Trying opposite strategy', nextPosition);
413
528
  }
414
- return position;
529
+ if((settings.prefer === 'adjacent') && adjacentsAvailable ) {
530
+ nextPosition = [verticalPosition, adjacent[horizontalPosition]];
531
+ nextPosition = nextPosition.join(' ');
532
+ adjacentTried = (triedPositions[nextPosition] === true);
533
+ module.debug('Trying adjacent strategy', nextPosition);
534
+ }
535
+ if(adjacentTried || oppositeTried) {
536
+ module.debug('Using backup position', nextPosition);
537
+ nextPosition = backup[position];
538
+ }
539
+ return nextPosition;
415
540
  }
416
541
  },
417
542
 
418
543
  set: {
419
544
  position: function(position, arrowOffset) {
420
545
  var
421
- windowWidth = $(window).width(),
422
- windowHeight = $(window).height(),
546
+ windowWidth = $(window).width(),
547
+ windowHeight = $(window).height(),
548
+
549
+ targetWidth = $target.outerWidth(),
550
+ targetHeight = $target.outerHeight(),
423
551
 
424
- width = $target.outerWidth(),
425
- height = $target.outerHeight(),
552
+ popupWidth = $popup.outerWidth(),
553
+ popupHeight = $popup.outerHeight(),
426
554
 
427
- popupWidth = $popup.width(),
428
- popupHeight = $popup.outerHeight(),
555
+ parentWidth = $offsetParent.outerWidth(),
556
+ parentHeight = $offsetParent.outerHeight(),
429
557
 
430
- parentWidth = $offsetParent.outerWidth(),
431
- parentHeight = $offsetParent.outerHeight(),
558
+ distanceAway = settings.distanceAway,
432
559
 
433
- distanceAway = settings.distanceAway,
560
+ targetElement = $target[0],
434
561
 
435
- offset = (settings.inline)
562
+ marginTop = (settings.inline)
563
+ ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
564
+ : 0,
565
+ marginLeft = (settings.inline)
566
+ ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10)
567
+ : 0,
568
+
569
+ target = (settings.inline || settings.popup)
436
570
  ? $target.position()
437
571
  : $target.offset(),
438
572
 
@@ -441,84 +575,100 @@ $.fn.popup = function(parameters) {
441
575
  ;
442
576
  position = position || $module.data(metadata.position) || settings.position;
443
577
  arrowOffset = arrowOffset || $module.data(metadata.offset) || settings.offset;
444
- // adjust for margin when inline
578
+
579
+ if(searchDepth == settings.maxSearchDepth && settings.lastResort) {
580
+ module.debug('Using last resort position to display', settings.lastResort);
581
+ position = settings.lastResort;
582
+ }
583
+
445
584
  if(settings.inline) {
585
+ module.debug('Adding targets margin to calculation');
446
586
  if(position == 'left center' || position == 'right center') {
447
- arrowOffset += parseInt( window.getComputedStyle(element).getPropertyValue('margin-top'), 10);
448
- distanceAway += -parseInt( window.getComputedStyle(element).getPropertyValue('margin-left'), 10);
587
+ arrowOffset += marginTop;
588
+ distanceAway += -marginLeft;
589
+ }
590
+ else if (position == 'top left' || position == 'top center' || position == 'top right') {
591
+ arrowOffset += marginLeft;
592
+ distanceAway -= marginTop;
449
593
  }
450
594
  else {
451
- arrowOffset += parseInt( window.getComputedStyle(element).getPropertyValue('margin-left'), 10);
452
- distanceAway += parseInt( window.getComputedStyle(element).getPropertyValue('margin-top'), 10);
595
+ arrowOffset += marginLeft;
596
+ distanceAway += marginTop;
453
597
  }
454
598
  }
455
- module.debug('Calculating offset for position', position);
599
+ module.debug('Calculating popup positioning', position);
456
600
  switch(position) {
457
601
  case 'top left':
458
602
  positioning = {
459
- bottom : parentHeight - offset.top + distanceAway,
460
- right : parentWidth - offset.left - arrowOffset,
461
603
  top : 'auto',
462
- left : 'auto'
604
+ bottom : parentHeight - target.top + distanceAway,
605
+ left : target.left + arrowOffset,
606
+ right : 'auto'
463
607
  };
464
608
  break;
465
609
  case 'top center':
466
610
  positioning = {
467
- bottom : parentHeight - offset.top + distanceAway,
468
- left : offset.left + (width / 2) - (popupWidth / 2) + arrowOffset,
611
+ bottom : parentHeight - target.top + distanceAway,
612
+ left : target.left + (targetWidth / 2) - (popupWidth / 2) + arrowOffset,
469
613
  top : 'auto',
470
614
  right : 'auto'
471
615
  };
472
616
  break;
473
617
  case 'top right':
474
618
  positioning = {
619
+ bottom : parentHeight - target.top + distanceAway,
620
+ right : parentWidth - target.left - targetWidth - arrowOffset,
475
621
  top : 'auto',
476
- bottom : parentHeight - offset.top + distanceAway,
477
- left : offset.left + width + arrowOffset,
478
- right : 'auto'
622
+ left : 'auto'
479
623
  };
480
624
  break;
481
625
  case 'left center':
482
626
  positioning = {
483
- top : offset.top + (height / 2) - (popupHeight / 2) + arrowOffset,
484
- right : parentWidth - offset.left + distanceAway,
627
+ top : target.top + (targetHeight / 2) - (popupHeight / 2) + arrowOffset,
628
+ right : parentWidth - target.left + distanceAway,
485
629
  left : 'auto',
486
630
  bottom : 'auto'
487
631
  };
488
632
  break;
489
633
  case 'right center':
490
634
  positioning = {
491
- top : offset.top + (height / 2) - (popupHeight / 2) + arrowOffset,
492
- left : offset.left + width + distanceAway,
635
+ top : target.top + (targetHeight / 2) - (popupHeight / 2) + arrowOffset,
636
+ left : target.left + targetWidth + distanceAway,
493
637
  bottom : 'auto',
494
638
  right : 'auto'
495
639
  };
496
640
  break;
497
641
  case 'bottom left':
498
642
  positioning = {
499
- top : offset.top + height + distanceAway,
500
- right : parentWidth - offset.left - arrowOffset,
501
- left : 'auto',
502
- bottom : 'auto'
643
+ top : target.top + targetHeight + distanceAway,
644
+ left : target.left + arrowOffset,
645
+ bottom : 'auto',
646
+ right : 'auto'
503
647
  };
504
648
  break;
505
649
  case 'bottom center':
506
650
  positioning = {
507
- top : offset.top + height + distanceAway,
508
- left : offset.left + (width / 2) - (popupWidth / 2) + arrowOffset,
651
+ top : target.top + targetHeight + distanceAway,
652
+ left : target.left + (targetWidth / 2) - (popupWidth / 2) + arrowOffset,
509
653
  bottom : 'auto',
510
654
  right : 'auto'
511
655
  };
512
656
  break;
513
657
  case 'bottom right':
514
658
  positioning = {
515
- top : offset.top + height + distanceAway,
516
- left : offset.left + width + arrowOffset,
517
- bottom : 'auto',
518
- right : 'auto'
659
+ top : target.top + targetHeight + distanceAway,
660
+ right : parentWidth - target.left - targetWidth - arrowOffset,
661
+ left : 'auto',
662
+ bottom : 'auto'
519
663
  };
520
664
  break;
521
665
  }
666
+ if(positioning === undefined) {
667
+ module.error(error.invalidPosition, position);
668
+ }
669
+
670
+ module.debug('Calculated popup positioning values', positioning);
671
+
522
672
  // tentatively place on stage
523
673
  $popup
524
674
  .css(positioning)
@@ -527,43 +677,89 @@ $.fn.popup = function(parameters) {
527
677
  .addClass(className.loading)
528
678
  ;
529
679
  // check if is offstage
530
- offstagePosition = module.get.offstagePosition();
680
+ offstagePosition = module.get.offstagePosition(position);
531
681
 
532
682
  // recursively find new positioning
533
683
  if(offstagePosition) {
534
- module.debug('Element is outside boundaries', offstagePosition);
684
+ module.debug('Popup cant fit into viewport', offstagePosition);
535
685
  if(searchDepth < settings.maxSearchDepth) {
536
- position = module.get.nextPosition(position);
537
686
  searchDepth++;
687
+ position = module.get.nextPosition(position);
538
688
  module.debug('Trying new position', position);
539
- return module.set.position(position);
689
+ return ($popup)
690
+ ? module.set.position(position)
691
+ : false
692
+ ;
540
693
  }
541
- else {
542
- module.error(error.recursion);
543
- searchDepth = 0;
694
+ else if(!settings.lastResort) {
695
+ module.debug('Popup could not find a position in view', $popup);
696
+ module.error(error.cannotPlace);
697
+ module.remove.attempts();
698
+ module.remove.loading();
544
699
  module.reset();
545
- $popup.removeClass(className.loading);
546
700
  return false;
547
701
  }
548
702
  }
549
- else {
550
- module.debug('Position is on stage', position);
551
- searchDepth = 0;
552
- $popup.removeClass(className.loading);
553
- return true;
703
+
704
+ module.debug('Position is on stage', position);
705
+ module.remove.attempts();
706
+ module.set.fluidWidth();
707
+ module.remove.loading();
708
+ return true;
709
+ },
710
+
711
+ fluidWidth: function() {
712
+ if( settings.setFluidWidth && $popup.hasClass(className.fluid) ) {
713
+ $popup.css('width', $offsetParent.width());
554
714
  }
715
+ },
716
+
717
+ visible: function() {
718
+ $module.addClass(className.visible);
555
719
  }
720
+ },
556
721
 
722
+ remove: {
723
+ loading: function() {
724
+ $popup.removeClass(className.loading);
725
+ },
726
+ visible: function() {
727
+ $module.removeClass(className.visible);
728
+ },
729
+ attempts: function() {
730
+ module.verbose('Resetting all searched positions');
731
+ searchDepth = 0;
732
+ triedPositions = false;
733
+ }
557
734
  },
558
735
 
559
736
  bind: {
737
+ popup: function() {
738
+ module.verbose('Allowing hover events on popup to prevent closing');
739
+ if( $popup && module.has.popup() ) {
740
+ $popup
741
+ .on('mouseenter' + eventNamespace, module.event.start)
742
+ .on('mouseleave' + eventNamespace, module.event.end)
743
+ ;
744
+ }
745
+ },
560
746
  close:function() {
747
+ if(settings.hideOnScroll === true || settings.hideOnScroll == 'auto' && settings.on != 'click') {
748
+ $document
749
+ .one('touchmove' + eventNamespace, module.hideGracefully)
750
+ .one('scroll' + eventNamespace, module.hideGracefully)
751
+ ;
752
+ $context
753
+ .one('touchmove' + eventNamespace, module.hideGracefully)
754
+ .one('scroll' + eventNamespace, module.hideGracefully)
755
+ ;
756
+ }
561
757
  if(settings.on == 'click' && settings.closable) {
562
758
  module.verbose('Binding popup close event to document');
563
759
  $document
564
760
  .on('click' + eventNamespace, function(event) {
565
761
  module.verbose('Pop-up clickaway intent detected');
566
- $.proxy(module.hideGracefully, this)(event);
762
+ $.proxy(module.hideGracefully, element)(event);
567
763
  })
568
764
  ;
569
765
  }
@@ -572,6 +768,14 @@ $.fn.popup = function(parameters) {
572
768
 
573
769
  unbind: {
574
770
  close: function() {
771
+ if(settings.hideOnScroll === true || settings.hideOnScroll == 'auto' && settings.on != 'click') {
772
+ $document
773
+ .off('scroll' + eventNamespace, module.hide)
774
+ ;
775
+ $context
776
+ .off('scroll' + eventNamespace, module.hide)
777
+ ;
778
+ }
575
779
  if(settings.on == 'click' && settings.closable) {
576
780
  module.verbose('Removing close event from document');
577
781
  $document
@@ -581,12 +785,24 @@ $.fn.popup = function(parameters) {
581
785
  }
582
786
  },
583
787
 
788
+ has: {
789
+ popup: function() {
790
+ return ($popup.size() > 0);
791
+ }
792
+ },
793
+
584
794
  is: {
795
+ active: function() {
796
+ return $module.hasClass(className.active);
797
+ },
585
798
  animating: function() {
586
- return ( $popup.is(':animated') || $popup.hasClass(className.animating) );
799
+ return ( $popup && $popup.is(':animated') || $popup.hasClass(className.animating) );
587
800
  },
588
801
  visible: function() {
589
- return $popup.is(':visible');
802
+ return $popup && $popup.is(':visible');
803
+ },
804
+ dropdown: function() {
805
+ return $module.hasClass(className.dropdown);
590
806
  },
591
807
  hidden: function() {
592
808
  return !module.is.visible();
@@ -594,12 +810,16 @@ $.fn.popup = function(parameters) {
594
810
  },
595
811
 
596
812
  reset: function() {
597
- $popup
598
- .attr('style', '')
599
- .removeAttr('style')
600
- ;
601
- if(!settings.preserve) {
602
- module.remove();
813
+ module.remove.visible();
814
+ if(settings.preserve || settings.popup) {
815
+ if($.fn.transition !== undefined) {
816
+ $popup
817
+ .transition('remove transition')
818
+ ;
819
+ }
820
+ }
821
+ else {
822
+ module.removePopup();
603
823
  }
604
824
  },
605
825
 
@@ -664,9 +884,9 @@ $.fn.popup = function(parameters) {
664
884
  executionTime = currentTime - previousTime;
665
885
  time = currentTime;
666
886
  performance.push({
667
- 'Element' : element,
668
887
  'Name' : message[0],
669
888
  'Arguments' : [].slice.call(message, 1) || '',
889
+ 'Element' : element,
670
890
  'Execution Time' : executionTime
671
891
  });
672
892
  }
@@ -780,44 +1000,61 @@ $.fn.popup = function(parameters) {
780
1000
 
781
1001
  $.fn.popup.settings = {
782
1002
 
783
- name : 'Popup',
784
- debug : false,
785
- verbose : true,
786
- performance : true,
787
- namespace : 'popup',
1003
+ name : 'Popup',
788
1004
 
789
- onCreate : function(){},
790
- onRemove : function(){},
791
- onShow : function(){},
792
- onHide : function(){},
1005
+ debug : false,
1006
+ verbose : true,
1007
+ performance : true,
1008
+ namespace : 'popup',
793
1009
 
794
- variation : '',
795
- content : false,
796
- html : false,
797
- title : false,
1010
+ onCreate : function(){},
1011
+ onRemove : function(){},
798
1012
 
799
- on : 'hover',
800
- target : false,
801
- closable : true,
1013
+ onShow : function(){},
1014
+ onVisible : function(){},
1015
+ onHide : function(){},
1016
+ onHidden : function(){},
1017
+
1018
+ variation : '',
1019
+ content : false,
1020
+ html : false,
1021
+ title : false,
1022
+
1023
+ on : 'hover',
1024
+ closable : true,
1025
+ hideOnScroll : 'auto',
1026
+
1027
+ context : 'body',
1028
+
1029
+ position : 'top left',
1030
+ prefer : 'opposite',
1031
+ lastResort : false,
1032
+
1033
+ delay : {
1034
+ show : 30,
1035
+ hide : 0
1036
+ },
802
1037
 
803
- context : 'body',
804
- position : 'top center',
805
- delay : 150,
1038
+ setFluidWidth : true,
1039
+
1040
+ target : false,
1041
+ popup : false,
806
1042
  inline : false,
807
- preserve : false,
1043
+ preserve : true,
1044
+ hoverable : false,
808
1045
 
809
- duration : 250,
810
- easing : 'easeOutQuad',
1046
+ duration : 200,
1047
+ easing : 'easeOutQuint',
811
1048
  transition : 'scale',
812
1049
 
813
1050
  distanceAway : 0,
814
1051
  offset : 0,
815
- maxSearchDepth : 10,
1052
+ maxSearchDepth : 20,
816
1053
 
817
1054
  error: {
818
- content : 'Your popup has no content specified',
819
- method : 'The method you called is not defined.',
820
- recursion : 'Popup attempted to reposition element to fit, but could not find an adequate position.'
1055
+ invalidPosition : 'The position you specified is not a valid position',
1056
+ cannotPlace : 'No visible position could be found for the popup',
1057
+ method : 'The method you called is not defined.'
821
1058
  },
822
1059
 
823
1060
  metadata: {
@@ -830,28 +1067,59 @@ $.fn.popup.settings = {
830
1067
  },
831
1068
 
832
1069
  className : {
833
- animating : 'animating',
834
- loading : 'loading',
835
- popup : 'ui popup',
836
- position : 'top left center bottom right',
837
- visible : 'visible'
1070
+ active : 'active',
1071
+ animating : 'animating',
1072
+ dropdown : 'dropdown',
1073
+ fluid : 'fluid',
1074
+ loading : 'loading',
1075
+ popup : 'ui popup',
1076
+ position : 'top left center bottom right',
1077
+ visible : 'visible'
838
1078
  },
839
1079
 
840
1080
  selector : {
841
1081
  popup : '.ui.popup'
842
1082
  },
843
1083
 
844
- template: function(text) {
845
- var html = '';
846
- if(typeof text !== undefined) {
847
- if(typeof text.title !== undefined && text.title) {
848
- html += '<div class="header">' + text.title + '</div>';
1084
+ templates: {
1085
+ escape: function(string) {
1086
+ var
1087
+ badChars = /[&<>"'`]/g,
1088
+ shouldEscape = /[&<>"'`]/,
1089
+ escape = {
1090
+ "&": "&amp;",
1091
+ "<": "&lt;",
1092
+ ">": "&gt;",
1093
+ '"': "&quot;",
1094
+ "'": "&#x27;",
1095
+ "`": "&#x60;"
1096
+ },
1097
+ escapedChar = function(chr) {
1098
+ return escape[chr];
1099
+ }
1100
+ ;
1101
+ if(shouldEscape.test(string)) {
1102
+ return string.replace(badChars, escapedChar);
849
1103
  }
850
- if(typeof text.content !== undefined && text.content) {
851
- html += '<div class="content">' + text.content + '</div>';
1104
+ return string;
1105
+ },
1106
+ popup: function(text) {
1107
+ var
1108
+ html = '',
1109
+ escape = $.fn.popup.settings.templates.escape
1110
+ ;
1111
+ if(typeof text !== undefined) {
1112
+ if(typeof text.title !== undefined && text.title) {
1113
+ text.title = escape(text.title);
1114
+ html += '<div class="header">' + text.title + '</div>';
1115
+ }
1116
+ if(typeof text.content !== undefined && text.content) {
1117
+ text.content = escape(text.content);
1118
+ html += '<div class="content">' + text.content + '</div>';
1119
+ }
852
1120
  }
1121
+ return html;
853
1122
  }
854
- return html;
855
1123
  }
856
1124
 
857
1125
  };