surveyor 0.22.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +1 -0
  3. data/CHANGELOG.md +83 -0
  4. data/Gemfile.rails_version +7 -1
  5. data/README.md +114 -16
  6. data/Rakefile +15 -9
  7. data/app/inputs/quiet_input.rb +5 -0
  8. data/app/inputs/surveyor_check_boxes_input.rb +35 -0
  9. data/app/inputs/surveyor_radio_input.rb +18 -0
  10. data/app/views/partials/_answer.html.haml +4 -4
  11. data/app/views/partials/_question.html.haml +7 -7
  12. data/app/views/partials/_question_group.html.haml +9 -8
  13. data/app/views/surveyor/export.json.rabl +28 -25
  14. data/app/views/surveyor/new.html.haml +8 -5
  15. data/app/views/surveyor/show.json.rabl +3 -2
  16. data/ci-exec.sh +13 -7
  17. data/cucumber.yml +3 -3
  18. data/doc/REPRESENTATIONS.md +34 -0
  19. data/doc/api_id_schema.json +7 -0
  20. data/doc/response_set_schema.json +54 -0
  21. data/doc/surveyor question combinations.png +0 -0
  22. data/doc/surveyor_timestamp_schema.json +9 -0
  23. data/features/ajax_submissions.feature +140 -0
  24. data/features/export_to_json.feature +182 -34
  25. data/features/no_duplicates.feature +110 -0
  26. data/features/show_survey.feature +1 -1
  27. data/features/step_definitions/parser_steps.rb +25 -2
  28. data/features/step_definitions/surveyor_steps.rb +145 -20
  29. data/features/step_definitions/ui_steps.rb +3 -0
  30. data/features/support/database_cleaner.rb +16 -0
  31. data/features/support/env.rb +21 -17
  32. data/features/support/simultaneous_ajax.rb +101 -0
  33. data/features/support/single_quit_selenium_driver.rb +23 -0
  34. data/features/support/slow_updates.rb +18 -0
  35. data/features/surveyor.feature +174 -44
  36. data/features/surveyor_dependencies.feature +80 -39
  37. data/features/surveyor_parser.feature +114 -20
  38. data/features/z_redcap_parser.feature +0 -1
  39. data/lib/{generators/surveyor/templates/public → assets}/images/surveyor/next.gif +0 -0
  40. data/lib/{generators/surveyor/templates/public → assets}/images/surveyor/prev.gif +0 -0
  41. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  42. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  43. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_65_ffffff_1x400.png +0 -0
  44. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  45. data/lib/assets/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  46. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  47. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-icons_ef8c08_256x240.png +0 -0
  48. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-icons_ffffff_256x240.png +0 -0
  49. data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery-ui-timepicker-addon.js +23 -23
  50. data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery-ui.js +125 -125
  51. data/lib/assets/javascripts/surveyor/jquery.selectToUISlider.js +240 -0
  52. data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery.surveyor.js +52 -57
  53. data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery.tools.min.js +7 -7
  54. data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/dateinput.css +13 -13
  55. data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/jquery-ui-timepicker-addon.css +0 -0
  56. data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/jquery-ui.custom.css +17 -17
  57. data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/reset.css +1 -1
  58. data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/results.css +0 -0
  59. data/lib/assets/stylesheets/surveyor/ui.slider.extras.css +110 -0
  60. data/lib/{generators/surveyor/templates/public/stylesheets/sass → assets/stylesheets}/surveyor.sass +15 -7
  61. data/lib/generators/surveyor/custom_generator.rb +3 -2
  62. data/lib/generators/surveyor/install_generator.rb +59 -17
  63. data/lib/generators/surveyor/templates/app/assets/javascripts/surveyor_all.js +5 -0
  64. data/lib/generators/surveyor/templates/app/assets/stylesheets/surveyor_all.css +9 -0
  65. data/lib/generators/surveyor/templates/app/controllers/surveyor_controller.rb +2 -1
  66. data/lib/generators/surveyor/templates/app/views/layouts/surveyor_custom.html.erb +1 -0
  67. data/lib/generators/surveyor/templates/config/locales/surveyor_es.yml +1 -0
  68. data/lib/generators/surveyor/templates/config/locales/surveyor_he.yml +1 -0
  69. data/lib/generators/surveyor/templates/db/migrate/add_api_id_to_question_groups.rb +1 -0
  70. data/lib/generators/surveyor/templates/db/migrate/add_api_ids.rb +1 -0
  71. data/lib/generators/surveyor/templates/db/migrate/add_api_ids_to_response_sets_and_responses.rb +1 -0
  72. data/lib/generators/surveyor/templates/db/migrate/add_correct_answer_id_to_questions.rb +1 -0
  73. data/lib/generators/surveyor/templates/db/migrate/add_default_value_to_answers.rb +1 -0
  74. data/lib/generators/surveyor/templates/db/migrate/add_display_order_to_surveys.rb +1 -0
  75. data/lib/generators/surveyor/templates/db/migrate/add_display_type_to_answers.rb +1 -0
  76. data/lib/generators/surveyor/templates/db/migrate/add_index_to_response_sets.rb +1 -0
  77. data/lib/generators/surveyor/templates/db/migrate/add_index_to_surveys.rb +1 -0
  78. data/lib/generators/surveyor/templates/db/migrate/add_section_id_to_responses.rb +1 -0
  79. data/lib/generators/surveyor/templates/db/migrate/add_unique_index_on_access_code_and_version_in_surveys.rb +10 -0
  80. data/lib/generators/surveyor/templates/db/migrate/add_unique_indicies.rb +3 -2
  81. data/lib/generators/surveyor/templates/db/migrate/add_version_to_surveys.rb +10 -0
  82. data/lib/generators/surveyor/templates/db/migrate/api_ids_must_be_unique.rb +23 -0
  83. data/lib/generators/surveyor/templates/db/migrate/create_answers.rb +6 -5
  84. data/lib/generators/surveyor/templates/db/migrate/create_dependencies.rb +2 -1
  85. data/lib/generators/surveyor/templates/db/migrate/create_dependency_conditions.rb +2 -1
  86. data/lib/generators/surveyor/templates/db/migrate/create_question_groups.rb +5 -4
  87. data/lib/generators/surveyor/templates/db/migrate/create_questions.rb +4 -3
  88. data/lib/generators/surveyor/templates/db/migrate/create_response_sets.rb +1 -0
  89. data/lib/generators/surveyor/templates/db/migrate/create_responses.rb +10 -9
  90. data/lib/generators/surveyor/templates/db/migrate/create_survey_sections.rb +5 -4
  91. data/lib/generators/surveyor/templates/db/migrate/create_surveys.rb +4 -3
  92. data/lib/generators/surveyor/templates/db/migrate/create_validation_conditions.rb +5 -4
  93. data/lib/generators/surveyor/templates/db/migrate/create_validations.rb +3 -2
  94. data/lib/generators/surveyor/templates/db/migrate/drop_unique_index_on_access_code_in_surveys.rb +10 -0
  95. data/lib/generators/surveyor/templates/db/migrate/update_blank_api_ids_on_question_group.rb +22 -0
  96. data/lib/generators/surveyor/templates/db/migrate/update_blank_versions_on_surveys.rb +13 -0
  97. data/lib/generators/surveyor/templates/surveys/date_survey.rb +1 -0
  98. data/lib/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +54 -24
  99. data/lib/generators/surveyor/templates/surveys/quiz.rb +1 -0
  100. data/lib/generators/surveyor/templates/{public/stylesheets/sass → vendor/assets/stylesheets}/custom.sass +1 -1
  101. data/lib/surveyor/common.rb +16 -31
  102. data/lib/surveyor/engine.rb +2 -4
  103. data/lib/surveyor/helpers/asset_pipeline.rb +13 -0
  104. data/lib/surveyor/helpers/formtastic_custom_input.rb +17 -0
  105. data/lib/surveyor/helpers/surveyor_helper_methods.rb +10 -8
  106. data/lib/surveyor/models/answer_methods.rb +3 -0
  107. data/lib/surveyor/models/dependency_condition_methods.rb +27 -28
  108. data/lib/surveyor/models/dependency_methods.rb +3 -0
  109. data/lib/surveyor/models/question_group_methods.rb +3 -0
  110. data/lib/surveyor/models/question_methods.rb +10 -7
  111. data/lib/surveyor/models/response_methods.rb +16 -0
  112. data/lib/surveyor/models/response_set_methods.rb +71 -64
  113. data/lib/surveyor/models/survey_methods.rb +19 -28
  114. data/lib/surveyor/models/survey_section_methods.rb +3 -0
  115. data/lib/surveyor/models/validation_condition_methods.rb +4 -2
  116. data/lib/surveyor/models/validation_methods.rb +3 -0
  117. data/lib/surveyor/parser.rb +198 -148
  118. data/lib/surveyor/redcap_parser.rb +120 -80
  119. data/lib/surveyor/surveyor_controller_methods.rb +86 -37
  120. data/lib/surveyor/version.rb +2 -2
  121. data/lib/surveyor.rb +5 -6
  122. data/lib/tasks/surveyor_tasks.rake +19 -7
  123. data/spec/controllers/surveyor_controller_spec.rb +166 -92
  124. data/spec/factories.rb +33 -32
  125. data/spec/helpers/formtastic_custom_input_spec.rb +16 -0
  126. data/spec/lib/common_spec.rb +0 -39
  127. data/spec/lib/redcap_parser_spec.rb +24 -24
  128. data/spec/models/answer_spec.rb +12 -0
  129. data/spec/models/dependency_condition_spec.rb +279 -323
  130. data/spec/models/dependency_spec.rb +10 -0
  131. data/spec/models/question_group_spec.rb +12 -0
  132. data/spec/models/question_spec.rb +12 -0
  133. data/spec/models/response_set_spec.rb +189 -139
  134. data/spec/models/response_spec.rb +60 -0
  135. data/spec/models/survey_section_spec.rb +9 -0
  136. data/spec/models/survey_spec.rb +72 -9
  137. data/spec/models/validation_condition_spec.rb +9 -1
  138. data/spec/models/validation_spec.rb +10 -0
  139. data/spec/spec_helper.rb +25 -6
  140. data/surveyor.gemspec +5 -4
  141. metadata +332 -291
  142. data/features/step_definitions/common_steps.rb +0 -3
  143. data/lib/formtastic/surveyor_builder.rb +0 -82
  144. data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery.blockUI.js +0 -499
@@ -258,7 +258,7 @@ $.extend( $.ui, {
258
258
  if ( !set || !instance.element[ 0 ].parentNode ) {
259
259
  return;
260
260
  }
261
-
261
+
262
262
  for ( var i = 0; i < set.length; i++ ) {
263
263
  if ( instance.options[ set[ i ][ 0 ] ] ) {
264
264
  set[ i ][ 1 ].apply( instance.element, args );
@@ -266,29 +266,29 @@ $.extend( $.ui, {
266
266
  }
267
267
  }
268
268
  },
269
-
269
+
270
270
  // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
271
271
  contains: function( a, b ) {
272
272
  return document.compareDocumentPosition ?
273
273
  a.compareDocumentPosition( b ) & 16 :
274
274
  a !== b && a.contains( b );
275
275
  },
276
-
276
+
277
277
  // only used by resizable
278
278
  hasScroll: function( el, a ) {
279
-
279
+
280
280
  //If overflow is hidden, the element might have extra content, but the user wants to hide it
281
281
  if ( $( el ).css( "overflow" ) === "hidden") {
282
282
  return false;
283
283
  }
284
-
284
+
285
285
  var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
286
286
  has = false;
287
-
287
+
288
288
  if ( el[ scroll ] > 0 ) {
289
289
  return true;
290
290
  }
291
-
291
+
292
292
  // TODO: determine which cases actually cause this to happen
293
293
  // if the element doesn't have the scroll set, see if it's possible to
294
294
  // set the scroll
@@ -297,7 +297,7 @@ $.extend( $.ui, {
297
297
  el[ scroll ] = 0;
298
298
  return has;
299
299
  },
300
-
300
+
301
301
  // these are odd functions, fix the API or move into individual plugins
302
302
  isOverAxis: function( x, reference, size ) {
303
303
  //Determines when x coordinate is over "b" element axis
@@ -669,7 +669,7 @@ $.widget("ui.mouse", {
669
669
  .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
670
670
 
671
671
  event.preventDefault();
672
-
672
+
673
673
  mouseHandled = true;
674
674
  return true;
675
675
  },
@@ -813,7 +813,7 @@ $.widget("ui.draggable", $.ui.mouse, {
813
813
  this.handle = this._getHandle(event);
814
814
  if (!this.handle)
815
815
  return false;
816
-
816
+
817
817
  $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
818
818
  $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
819
819
  .css({
@@ -897,10 +897,10 @@ $.widget("ui.draggable", $.ui.mouse, {
897
897
 
898
898
  this.helper.addClass("ui-draggable-dragging");
899
899
  this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
900
-
900
+
901
901
  //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
902
902
  if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
903
-
903
+
904
904
  return true;
905
905
  },
906
906
 
@@ -939,7 +939,7 @@ $.widget("ui.draggable", $.ui.mouse, {
939
939
  dropped = this.dropped;
940
940
  this.dropped = false;
941
941
  }
942
-
942
+
943
943
  //if the original element is removed, don't bother to continue if helper is set to "original"
944
944
  if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
945
945
  return false;
@@ -959,30 +959,30 @@ $.widget("ui.draggable", $.ui.mouse, {
959
959
 
960
960
  return false;
961
961
  },
962
-
962
+
963
963
  _mouseUp: function(event) {
964
964
  if (this.options.iframeFix === true) {
965
- $("div.ui-draggable-iframeFix").each(function() {
966
- this.parentNode.removeChild(this);
965
+ $("div.ui-draggable-iframeFix").each(function() {
966
+ this.parentNode.removeChild(this);
967
967
  }); //Remove frame helpers
968
968
  }
969
-
969
+
970
970
  //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
971
971
  if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
972
-
972
+
973
973
  return $.ui.mouse.prototype._mouseUp.call(this, event);
974
974
  },
975
-
975
+
976
976
  cancel: function() {
977
-
977
+
978
978
  if(this.helper.is(".ui-draggable-dragging")) {
979
979
  this._mouseUp({});
980
980
  } else {
981
981
  this._clear();
982
982
  }
983
-
983
+
984
984
  return this;
985
-
985
+
986
986
  },
987
987
 
988
988
  _getHandle: function(event) {
@@ -1307,12 +1307,12 @@ $.ui.plugin.add("draggable", "connectToSortable", {
1307
1307
  };
1308
1308
 
1309
1309
  $.each(inst.sortables, function(i) {
1310
-
1310
+
1311
1311
  //Copy over some variables to allow calling the sortable's native _intersectsWith
1312
1312
  this.instance.positionAbs = inst.positionAbs;
1313
1313
  this.instance.helperProportions = inst.helperProportions;
1314
1314
  this.instance.offset.click = inst.offset.click;
1315
-
1315
+
1316
1316
  if(this.instance._intersectsWith(this.instance.containerCache)) {
1317
1317
 
1318
1318
  //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
@@ -1355,13 +1355,13 @@ $.ui.plugin.add("draggable", "connectToSortable", {
1355
1355
 
1356
1356
  this.instance.isOver = 0;
1357
1357
  this.instance.cancelHelperRemoval = true;
1358
-
1358
+
1359
1359
  //Prevent reverting on this forced stop
1360
1360
  this.instance.options.revert = false;
1361
-
1361
+
1362
1362
  // The out event needs to be triggered independently
1363
1363
  this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1364
-
1364
+
1365
1365
  this.instance._mouseStop(event, true);
1366
1366
  this.instance.options.helper = this.instance.options._helper;
1367
1367
 
@@ -1531,7 +1531,7 @@ $.ui.plugin.add("draggable", "stack", {
1531
1531
  return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1532
1532
  });
1533
1533
  if (!group.length) { return; }
1534
-
1534
+
1535
1535
  var min = parseInt(group[0].style.zIndex) || 0;
1536
1536
  $(group).each(function(i) {
1537
1537
  this.style.zIndex = min + i;
@@ -2443,7 +2443,7 @@ $.ui.plugin.add("resizable", "alsoResize", {
2443
2443
 
2444
2444
  _alsoResize = function (exp, c) {
2445
2445
  $(exp).each(function() {
2446
- var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2446
+ var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2447
2447
  css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2448
2448
 
2449
2449
  $.each(css, function (i, prop) {
@@ -3037,7 +3037,7 @@ $.widget("ui.sortable", $.ui.mouse, {
3037
3037
  _setOption: function(key, value){
3038
3038
  if ( key === "disabled" ) {
3039
3039
  this.options[ key ] = value;
3040
-
3040
+
3041
3041
  this.widget()
3042
3042
  [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
3043
3043
  } else {
@@ -3477,7 +3477,7 @@ $.widget("ui.sortable", $.ui.mouse, {
3477
3477
  ? [options.connectWith]
3478
3478
  : options.connectWith;
3479
3479
  },
3480
-
3480
+
3481
3481
  _getItemsAsjQuery: function(connected) {
3482
3482
 
3483
3483
  var self = this;
@@ -3650,28 +3650,28 @@ $.widget("ui.sortable", $.ui.mouse, {
3650
3650
  },
3651
3651
 
3652
3652
  _contactContainers: function(event) {
3653
-
3654
- // get innermost container that intersects with item
3655
- var innermostContainer = null, innermostIndex = null;
3656
-
3657
-
3653
+
3654
+ // get innermost container that intersects with item
3655
+ var innermostContainer = null, innermostIndex = null;
3656
+
3657
+
3658
3658
  for (var i = this.containers.length - 1; i >= 0; i--){
3659
3659
 
3660
- // never consider a container that's located within the item itself
3660
+ // never consider a container that's located within the item itself
3661
3661
  if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
3662
3662
  continue;
3663
3663
 
3664
3664
  if(this._intersectsWith(this.containers[i].containerCache)) {
3665
3665
 
3666
- // if we've already found a container and it's more "inner" than this, then continue
3666
+ // if we've already found a container and it's more "inner" than this, then continue
3667
3667
  if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
3668
3668
  continue;
3669
3669
 
3670
- innermostContainer = this.containers[i];
3670
+ innermostContainer = this.containers[i];
3671
3671
  innermostIndex = i;
3672
-
3672
+
3673
3673
  } else {
3674
- // container doesn't intersect. trigger "out" event if necessary
3674
+ // container doesn't intersect. trigger "out" event if necessary
3675
3675
  if(this.containers[i].containerCache.over) {
3676
3676
  this.containers[i]._trigger("out", event, this._uiHash(this));
3677
3677
  this.containers[i].containerCache.over = 0;
@@ -3679,42 +3679,42 @@ $.widget("ui.sortable", $.ui.mouse, {
3679
3679
  }
3680
3680
 
3681
3681
  }
3682
-
3683
- // if no intersecting containers found, return
3684
- if(!innermostContainer) return;
3682
+
3683
+ // if no intersecting containers found, return
3684
+ if(!innermostContainer) return;
3685
3685
 
3686
3686
  // move the item into the container if it's not there already
3687
3687
  if(this.containers.length === 1) {
3688
3688
  this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3689
3689
  this.containers[innermostIndex].containerCache.over = 1;
3690
- } else if(this.currentContainer != this.containers[innermostIndex]) {
3691
-
3692
- //When entering a new container, we will find the item with the least distance and append our item near it
3693
- var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3694
- for (var j = this.items.length - 1; j >= 0; j--) {
3695
- if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3696
- var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
3697
- if(Math.abs(cur - base) < dist) {
3698
- dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3699
- }
3700
- }
3701
-
3702
- if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3703
- return;
3704
-
3705
- this.currentContainer = this.containers[innermostIndex];
3706
- itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3707
- this._trigger("change", event, this._uiHash());
3708
- this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3709
-
3710
- //Update the placeholder
3711
- this.options.placeholder.update(this.currentContainer, this.placeholder);
3712
-
3713
- this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3690
+ } else if(this.currentContainer != this.containers[innermostIndex]) {
3691
+
3692
+ //When entering a new container, we will find the item with the least distance and append our item near it
3693
+ var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3694
+ for (var j = this.items.length - 1; j >= 0; j--) {
3695
+ if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3696
+ var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
3697
+ if(Math.abs(cur - base) < dist) {
3698
+ dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3699
+ }
3700
+ }
3701
+
3702
+ if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3703
+ return;
3704
+
3705
+ this.currentContainer = this.containers[innermostIndex];
3706
+ itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3707
+ this._trigger("change", event, this._uiHash());
3708
+ this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3709
+
3710
+ //Update the placeholder
3711
+ this.options.placeholder.update(this.currentContainer, this.placeholder);
3712
+
3713
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3714
3714
  this.containers[innermostIndex].containerCache.over = 1;
3715
- }
3716
-
3717
-
3715
+ }
3716
+
3717
+
3718
3718
  },
3719
3719
 
3720
3720
  _createHelper: function(event) {
@@ -4222,7 +4222,7 @@ function getElementStyles() {
4222
4222
  }
4223
4223
  }
4224
4224
  }
4225
-
4225
+
4226
4226
  return newStyle;
4227
4227
  }
4228
4228
 
@@ -4246,7 +4246,7 @@ function filterStyles(styles) {
4246
4246
  delete styles[name];
4247
4247
  }
4248
4248
  }
4249
-
4249
+
4250
4250
  return styles;
4251
4251
  }
4252
4252
 
@@ -4487,12 +4487,12 @@ function standardSpeed( speed ) {
4487
4487
  if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
4488
4488
  return true;
4489
4489
  }
4490
-
4490
+
4491
4491
  // invalid strings - treat as "normal" speed
4492
4492
  if ( typeof speed === "string" && !$.effects[ speed ] ) {
4493
4493
  return true;
4494
4494
  }
4495
-
4495
+
4496
4496
  return false;
4497
4497
  }
4498
4498
 
@@ -4507,7 +4507,7 @@ $.fn.extend({
4507
4507
  },
4508
4508
  mode = args2.options.mode,
4509
4509
  effectMethod = $.effects[effect];
4510
-
4510
+
4511
4511
  if ( $.fx.off || !effectMethod ) {
4512
4512
  // delegate to the original method (e.g., .show()) if possible
4513
4513
  if ( mode ) {
@@ -4520,7 +4520,7 @@ $.fn.extend({
4520
4520
  });
4521
4521
  }
4522
4522
  }
4523
-
4523
+
4524
4524
  return effectMethod.call(this, args2);
4525
4525
  },
4526
4526
 
@@ -5711,7 +5711,7 @@ $.widget( "ui.accordion", {
5711
5711
 
5712
5712
  self._createIcons();
5713
5713
  self.resize();
5714
-
5714
+
5715
5715
  // ARIA
5716
5716
  self.element.attr( "role", "tablist" );
5717
5717
 
@@ -5806,7 +5806,7 @@ $.widget( "ui.accordion", {
5806
5806
 
5807
5807
  _setOption: function( key, value ) {
5808
5808
  $.Widget.prototype._setOption.apply( this, arguments );
5809
-
5809
+
5810
5810
  if ( key == "active" ) {
5811
5811
  this.activate( value );
5812
5812
  }
@@ -6549,7 +6549,7 @@ $.widget( "ui.autocomplete", {
6549
6549
  this._trigger( "close", event );
6550
6550
  }
6551
6551
  },
6552
-
6552
+
6553
6553
  _change: function( event ) {
6554
6554
  if ( this.previous !== this.element.val() ) {
6555
6555
  this._trigger( "change", event, { item: this.selectedItem } );
@@ -6653,7 +6653,7 @@ $.extend( $.ui.autocomplete, {
6653
6653
 
6654
6654
  /*
6655
6655
  * jQuery UI Menu (not officially released)
6656
- *
6656
+ *
6657
6657
  * This widget isn't yet finished and the API is subject to change. We plan to finish
6658
6658
  * it for the next release. You're welcome to give it a try anyway and give us feedback,
6659
6659
  * as long as you're okay with migrating your code later on. We can help with that, too.
@@ -6689,7 +6689,7 @@ $.widget("ui.menu", {
6689
6689
  });
6690
6690
  this.refresh();
6691
6691
  },
6692
-
6692
+
6693
6693
  refresh: function() {
6694
6694
  var self = this;
6695
6695
 
@@ -6697,7 +6697,7 @@ $.widget("ui.menu", {
6697
6697
  var items = this.element.children("li:not(.ui-menu-item):has(a)")
6698
6698
  .addClass("ui-menu-item")
6699
6699
  .attr("role", "menuitem");
6700
-
6700
+
6701
6701
  items.children("a")
6702
6702
  .addClass("ui-corner-all")
6703
6703
  .attr("tabindex", -1)
@@ -7162,7 +7162,7 @@ $.widget( "ui.button", {
7162
7162
  .text(),
7163
7163
  icons = this.options.icons,
7164
7164
  multipleIcons = icons.primary && icons.secondary,
7165
- buttonClasses = [];
7165
+ buttonClasses = [];
7166
7166
 
7167
7167
  if ( icons.primary || icons.secondary ) {
7168
7168
  if ( this.options.text ) {
@@ -7199,7 +7199,7 @@ $.widget( "ui.buttonset", {
7199
7199
  _create: function() {
7200
7200
  this.element.addClass( "ui-buttonset" );
7201
7201
  },
7202
-
7202
+
7203
7203
  _init: function() {
7204
7204
  this.refresh();
7205
7205
  },
@@ -7211,10 +7211,10 @@ $.widget( "ui.buttonset", {
7211
7211
 
7212
7212
  $.Widget.prototype._setOption.apply( this, arguments );
7213
7213
  },
7214
-
7214
+
7215
7215
  refresh: function() {
7216
7216
  var ltr = this.element.css( "direction" ) === "ltr";
7217
-
7217
+
7218
7218
  this.buttons = this.element.find( this.options.items )
7219
7219
  .filter( ":ui-button" )
7220
7220
  .button( "refresh" )
@@ -7366,7 +7366,7 @@ function Datepicker() {
7366
7366
  $.extend(Datepicker.prototype, {
7367
7367
  /* Class name added to elements to indicate already configured with a date picker. */
7368
7368
  markerClassName: 'hasDatepicker',
7369
-
7369
+
7370
7370
  //Keep track of the maximum number of rows displayed (see #7043)
7371
7371
  maxRows: 4,
7372
7372
 
@@ -7375,7 +7375,7 @@ $.extend(Datepicker.prototype, {
7375
7375
  if (this.debug)
7376
7376
  console.log.apply('', arguments);
7377
7377
  },
7378
-
7378
+
7379
7379
  // TODO rename to "widget" when switching to widget factory
7380
7380
  _widgetDatepicker: function() {
7381
7381
  return this.dpDiv;
@@ -7768,7 +7768,7 @@ $.extend(Datepicker.prototype, {
7768
7768
  case 9: $.datepicker._hideDatepicker();
7769
7769
  handled = false;
7770
7770
  break; // hide on tab out
7771
- case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
7771
+ case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
7772
7772
  $.datepicker._currentClass + ')', inst.dpDiv);
7773
7773
  if (sel[0])
7774
7774
  $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
@@ -7959,7 +7959,7 @@ $.extend(Datepicker.prototype, {
7959
7959
  // this breaks the change event in IE
7960
7960
  inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
7961
7961
  inst.input.focus();
7962
- // deffered render of the years select (to avoid flashes on Firefox)
7962
+ // deffered render of the years select (to avoid flashes on Firefox)
7963
7963
  if( inst.yearshtml ){
7964
7964
  var origyearshtml = inst.yearshtml;
7965
7965
  setTimeout(function(){
@@ -8802,7 +8802,7 @@ $.extend(Datepicker.prototype, {
8802
8802
  drawMonth = 0;
8803
8803
  drawYear++;
8804
8804
  }
8805
- calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
8805
+ calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
8806
8806
  ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
8807
8807
  group += calender;
8808
8808
  }
@@ -8872,7 +8872,7 @@ $.extend(Datepicker.prototype, {
8872
8872
  '>' + year + '</option>';
8873
8873
  }
8874
8874
  inst.yearshtml += '</select>';
8875
-
8875
+
8876
8876
  html += inst.yearshtml;
8877
8877
  inst.yearshtml = null;
8878
8878
  }
@@ -8983,7 +8983,7 @@ $.extend(Datepicker.prototype, {
8983
8983
  * Bind hover events for datepicker elements.
8984
8984
  * Done via delegate so the binding only occurs once in the lifetime of the parent div.
8985
8985
  * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
8986
- */
8986
+ */
8987
8987
  function bindHover(dpDiv) {
8988
8988
  var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
8989
8989
  return dpDiv.bind('mouseout', function(event) {
@@ -9026,12 +9026,12 @@ function isArray(a) {
9026
9026
  Object - settings for attaching new datepicker functionality
9027
9027
  @return jQuery object */
9028
9028
  $.fn.datepicker = function(options){
9029
-
9029
+
9030
9030
  /* Verify an empty collection wasn't passed - Fixes #6976 */
9031
9031
  if ( !this.length ) {
9032
9032
  return this;
9033
9033
  }
9034
-
9034
+
9035
9035
  /* Initialise the date picker. */
9036
9036
  if (!$.datepicker.initialized) {
9037
9037
  $(document).mousedown($.datepicker._checkExternalClick).
@@ -9178,7 +9178,7 @@ $.widget("ui.dialog", {
9178
9178
  .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
9179
9179
  if (options.closeOnEscape && event.keyCode &&
9180
9180
  event.keyCode === $.ui.keyCode.ESCAPE) {
9181
-
9181
+
9182
9182
  self.close(event);
9183
9183
  event.preventDefault();
9184
9184
  }
@@ -9280,7 +9280,7 @@ $.widget("ui.dialog", {
9280
9280
 
9281
9281
  destroy: function() {
9282
9282
  var self = this;
9283
-
9283
+
9284
9284
  if (self.overlay) {
9285
9285
  self.overlay.destroy();
9286
9286
  }
@@ -9306,7 +9306,7 @@ $.widget("ui.dialog", {
9306
9306
  close: function(event) {
9307
9307
  var self = this,
9308
9308
  maxZ, thisZ;
9309
-
9309
+
9310
9310
  if (false === self._trigger('beforeClose', event)) {
9311
9311
  return;
9312
9312
  }
@@ -9599,7 +9599,7 @@ $.widget("ui.dialog", {
9599
9599
  at: myAt.join(" "),
9600
9600
  offset: offset.join(" ")
9601
9601
  };
9602
- }
9602
+ }
9603
9603
 
9604
9604
  position = $.extend({}, $.ui.dialog.prototype.options.position, position);
9605
9605
  } else {
@@ -9627,7 +9627,7 @@ $.widget("ui.dialog", {
9627
9627
 
9628
9628
  $.each( options, function( key, value ) {
9629
9629
  self._setOption( key, value );
9630
-
9630
+
9631
9631
  if ( key in sizeRelatedOptions ) {
9632
9632
  resize = true;
9633
9633
  }
@@ -9679,7 +9679,7 @@ $.widget("ui.dialog", {
9679
9679
  if ( isDraggable && !value ) {
9680
9680
  uiDialog.draggable( "destroy" );
9681
9681
  }
9682
-
9682
+
9683
9683
  if ( !isDraggable && value ) {
9684
9684
  self._makeDraggable();
9685
9685
  }
@@ -9741,7 +9741,7 @@ $.widget("ui.dialog", {
9741
9741
  })
9742
9742
  .height();
9743
9743
  minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
9744
-
9744
+
9745
9745
  if ( options.height === "auto" ) {
9746
9746
  // only needed for IE6 support
9747
9747
  if ( $.support.minHeight ) {
@@ -9816,7 +9816,7 @@ $.extend($.ui.dialog.overlay, {
9816
9816
  $(document).bind('keydown.dialog-overlay', function(event) {
9817
9817
  if (dialog.options.closeOnEscape && event.keyCode &&
9818
9818
  event.keyCode === $.ui.keyCode.ESCAPE) {
9819
-
9819
+
9820
9820
  dialog.close(event);
9821
9821
  event.preventDefault();
9822
9822
  }
@@ -9852,7 +9852,7 @@ $.extend($.ui.dialog.overlay, {
9852
9852
  }
9853
9853
 
9854
9854
  $el.remove();
9855
-
9855
+
9856
9856
  // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
9857
9857
  var maxZ = 0;
9858
9858
  $.each(this.instances, function() {
@@ -9998,7 +9998,7 @@ $.fn.position = function( options ) {
9998
9998
  }
9999
9999
 
10000
10000
  // force my and at to have valid horizontal and veritcal positions
10001
- // if a value is missing or invalid, it will be converted to center
10001
+ // if a value is missing or invalid, it will be converted to center
10002
10002
  $.each( [ "my", "at" ], function() {
10003
10003
  var pos = ( options[this] || "" ).split( " " );
10004
10004
  if ( pos.length === 1) {
@@ -10173,7 +10173,7 @@ if ( !$.offset.setOffset ) {
10173
10173
  top: (options.top - curOffset.top) + curTop,
10174
10174
  left: (options.left - curOffset.left) + curLeft
10175
10175
  };
10176
-
10176
+
10177
10177
  if ( 'using' in options ) {
10178
10178
  options.using.call( elem, props );
10179
10179
  } else {
@@ -10184,7 +10184,7 @@ if ( !$.offset.setOffset ) {
10184
10184
  $.fn.offset = function( options ) {
10185
10185
  var elem = this[ 0 ];
10186
10186
  if ( !elem || !elem.ownerDocument ) { return null; }
10187
- if ( options ) {
10187
+ if ( options ) {
10188
10188
  return this.each(function() {
10189
10189
  $.offset.setOffset( this, options );
10190
10190
  });
@@ -10379,7 +10379,7 @@ $.widget( "ui.slider", $.ui.mouse, {
10379
10379
  .addClass( "ui-slider-range" +
10380
10380
  // note: this isn't the most fittingly semantic framework class for this element,
10381
10381
  // but worked best visually with a variety of themes
10382
- " ui-widget-header" +
10382
+ " ui-widget-header" +
10383
10383
  ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
10384
10384
  }
10385
10385
 
@@ -10426,11 +10426,11 @@ $.widget( "ui.slider", $.ui.mouse, {
10426
10426
  curVal,
10427
10427
  newVal,
10428
10428
  step;
10429
-
10429
+
10430
10430
  if ( self.options.disabled ) {
10431
10431
  return;
10432
10432
  }
10433
-
10433
+
10434
10434
  switch ( event.keyCode ) {
10435
10435
  case $.ui.keyCode.HOME:
10436
10436
  case $.ui.keyCode.END:
@@ -10451,14 +10451,14 @@ $.widget( "ui.slider", $.ui.mouse, {
10451
10451
  }
10452
10452
  break;
10453
10453
  }
10454
-
10454
+
10455
10455
  step = self.options.step;
10456
10456
  if ( self.options.values && self.options.values.length ) {
10457
10457
  curVal = newVal = self.values( index );
10458
10458
  } else {
10459
10459
  curVal = newVal = self.value();
10460
10460
  }
10461
-
10461
+
10462
10462
  switch ( event.keyCode ) {
10463
10463
  case $.ui.keyCode.HOME:
10464
10464
  newVal = self._valueMin();
@@ -10487,22 +10487,22 @@ $.widget( "ui.slider", $.ui.mouse, {
10487
10487
  newVal = self._trimAlignValue( curVal - step );
10488
10488
  break;
10489
10489
  }
10490
-
10490
+
10491
10491
  self._slide( event, index, newVal );
10492
-
10492
+
10493
10493
  return ret;
10494
-
10494
+
10495
10495
  })
10496
10496
  .keyup(function( event ) {
10497
10497
  var index = $( this ).data( "index.ui-slider-handle" );
10498
-
10498
+
10499
10499
  if ( self._keySliding ) {
10500
10500
  self._keySliding = false;
10501
10501
  self._stop( event, index );
10502
10502
  self._change( event, index );
10503
10503
  $( this ).removeClass( "ui-state-active" );
10504
10504
  }
10505
-
10505
+
10506
10506
  });
10507
10507
 
10508
10508
  this._refreshValue();
@@ -10584,7 +10584,7 @@ $.widget( "ui.slider", $.ui.mouse, {
10584
10584
  closestHandle
10585
10585
  .addClass( "ui-state-active" )
10586
10586
  .focus();
10587
-
10587
+
10588
10588
  offset = closestHandle.offset();
10589
10589
  mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
10590
10590
  this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
@@ -10610,7 +10610,7 @@ $.widget( "ui.slider", $.ui.mouse, {
10610
10610
  _mouseDrag: function( event ) {
10611
10611
  var position = { x: event.pageX, y: event.pageY },
10612
10612
  normValue = this._normValueFromMouse( position );
10613
-
10613
+
10614
10614
  this._slide( event, this._handleIndex, normValue );
10615
10615
 
10616
10616
  return false;
@@ -10629,7 +10629,7 @@ $.widget( "ui.slider", $.ui.mouse, {
10629
10629
 
10630
10630
  return false;
10631
10631
  },
10632
-
10632
+
10633
10633
  _detectOrientation: function() {
10634
10634
  this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
10635
10635
  },
@@ -10686,7 +10686,7 @@ $.widget( "ui.slider", $.ui.mouse, {
10686
10686
  if ( this.options.values && this.options.values.length ) {
10687
10687
  otherVal = this.values( index ? 0 : 1 );
10688
10688
 
10689
- if ( ( this.options.values.length === 2 && this.options.range === true ) &&
10689
+ if ( ( this.options.values.length === 2 && this.options.range === true ) &&
10690
10690
  ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
10691
10691
  ) {
10692
10692
  newVal = otherVal;
@@ -10871,7 +10871,7 @@ $.widget( "ui.slider", $.ui.mouse, {
10871
10871
  return vals;
10872
10872
  }
10873
10873
  },
10874
-
10874
+
10875
10875
  // returns the step-aligned value that val is closest to, between (inclusive) min and max
10876
10876
  _trimAlignValue: function( val ) {
10877
10877
  if ( val <= this._valueMin() ) {
@@ -10900,7 +10900,7 @@ $.widget( "ui.slider", $.ui.mouse, {
10900
10900
  _valueMax: function() {
10901
10901
  return this.options.max;
10902
10902
  },
10903
-
10903
+
10904
10904
  _refreshValue: function() {
10905
10905
  var oRange = this.options.range,
10906
10906
  o = this.options,
@@ -11691,7 +11691,7 @@ $.extend( $.ui.tabs.prototype, {
11691
11691
  var t = o.selected;
11692
11692
  self.select( ++t < self.anchors.length ? t : 0 );
11693
11693
  }, ms );
11694
-
11694
+
11695
11695
  if ( e ) {
11696
11696
  e.stopPropagation();
11697
11697
  }