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
@@ -1,3 +0,0 @@
1
- When /^I wait (\d+) seconds$/ do |wait_seconds|
2
- sleep(wait_seconds.to_i)
3
- end
@@ -1,82 +0,0 @@
1
- require 'formtastic'
2
- module Formtastic
3
- class SurveyorBuilder < SemanticFormBuilder
4
- def quiet_input(method, options = {})
5
- html_options = options.delete(:input_html) || strip_formtastic_options(options)
6
- html_options[:id] ||= generate_html_id(method, "")
7
- hidden_field(method, html_options)
8
- end
9
- def surveyor_check_boxes_input(method, options)
10
- collection = find_collection_for_column(method, options)
11
- html_options_are_present = options.key?(:input_html)
12
- html_options = options[:input_html] if html_options_are_present
13
-
14
- input_name = generate_association_input_name(method)
15
- hidden_fields = options.delete(:hidden_fields)
16
- value_as_class = options.delete(:value_as_class)
17
- unchecked_value = options.delete(:unchecked_value) || ''
18
- html_options = { :name => "#{@object_name}[#{input_name}][]" }.merge(html_options)
19
- input_ids = []
20
-
21
- selected_values = find_selected_values_for_column(method, options)
22
- disabled_option_is_present = options.key?(:disabled)
23
- disabled_values = [*options[:disabled]] if disabled_option_is_present
24
-
25
- li_options = value_as_class ? { :class => [method.to_s.singularize, 'default'].join('_') } : {}
26
-
27
- list_item_content = collection.map do |c|
28
- label = c.is_a?(Array) ? c.first : c
29
- value = c.is_a?(Array) ? c.last : c
30
- input_id = generate_html_id(input_name, value.to_s.gsub(/\s/, '_').gsub(/\W/, '').downcase)
31
- input_ids << input_id
32
-
33
- html_options[:checked] = selected_values.include?(value)
34
- html_options[:disabled] = disabled_values.include?(value) if disabled_option_is_present
35
- html_options[:id] = input_id
36
-
37
- li_content = create_hidden_field_for_check_boxes(input_name, value_as_class) unless hidden_fields
38
- li_content << template.content_tag(:label,
39
- Formtastic::Util.html_safe("#{create_check_boxes(input_name, html_options, value, unchecked_value, hidden_fields)} #{escape_html_entities(label)}"),
40
- :for => input_id
41
- )
42
- li_content << Formtastic::Util.html_safe(basic_input_helper(:text_field, :string, :string_value, options)) if options[:response_class] == "other_and_string"
43
- li_content << Formtastic::Util.html_safe(basic_input_helper(:text_field, :string, :string_value, options)) if %w(string other_and_string).include?(options[:response_class])
44
- li_content << Formtastic::Util.html_safe(basic_input_helper(:text_area, :text, :text_value, options)) if options[:response_class] == "text"
45
- # li_options = value_as_class ? { :class => [method.to_s.singularize, value.to_s.downcase].join('_') } : {}
46
- Formtastic::Util.html_safe(li_content)
47
- end
48
-
49
- Formtastic::Util.html_safe(list_item_content.join)
50
- end
51
- def surveyor_radio_input(method, options)
52
- collection = find_collection_for_column(method, options)
53
- html_options = strip_formtastic_options(options).merge(options[:input_html] || {})
54
-
55
- input_name = generate_association_input_name(method)
56
- value_as_class = options.delete(:value_as_class)
57
- input_ids = []
58
-
59
- list_item_content = collection.map do |c|
60
- label = c.is_a?(Array) ? c.first : c
61
- value = c.is_a?(Array) ? c.last : c
62
- input_id = generate_html_id(input_name, value.to_s.gsub(/\s/, '_').gsub(/\W/, '').downcase)
63
- input_ids << input_id
64
-
65
- html_options[:id] = input_id
66
-
67
- li_content = template.content_tag(:label,
68
- Formtastic::Util.html_safe("#{radio_button(input_name, value, html_options)} #{escape_html_entities(label)}"),
69
- :for => input_id
70
- )
71
-
72
- li_content << Formtastic::Util.html_safe(basic_input_helper(:text_field, :string, :integer_value, options)) if options[:response_class] == 'integer'
73
- li_content << Formtastic::Util.html_safe(basic_input_helper(:text_field, :string, :string_value, options)) if options[:response_class] == 'string'
74
-
75
- # li_options = value_as_class ? { :class => [method.to_s.singularize, value.to_s.downcase].join('_') } : {}
76
- Formtastic::Util.html_safe(li_content)
77
- end
78
-
79
- Formtastic::Util.html_safe(list_item_content.join)
80
- end
81
- end
82
- end
@@ -1,499 +0,0 @@
1
- /*!
2
- * jQuery blockUI plugin
3
- * Version 2.39 (23-MAY-2011)
4
- * @requires jQuery v1.2.3 or later
5
- *
6
- * Examples at: http://malsup.com/jquery/block/
7
- * Copyright (c) 2007-2010 M. Alsup
8
- * Dual licensed under the MIT and GPL licenses:
9
- * http://www.opensource.org/licenses/mit-license.php
10
- * http://www.gnu.org/licenses/gpl.html
11
- *
12
- * Thanks to Amir-Hossein Sobhi for some excellent contributions!
13
- */
14
-
15
- ;(function($) {
16
-
17
- if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
18
- alert('blockUI requires jQuery v1.2.3 or later! You are using v' + $.fn.jquery);
19
- return;
20
- }
21
-
22
- $.fn._fadeIn = $.fn.fadeIn;
23
-
24
- var noOp = function() {};
25
-
26
- // this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
27
- // retarded userAgent strings on Vista)
28
- var mode = document.documentMode || 0;
29
- var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8);
30
- var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode;
31
-
32
- // global $ methods for blocking/unblocking the entire page
33
- $.blockUI = function(opts) { install(window, opts); };
34
- $.unblockUI = function(opts) { remove(window, opts); };
35
-
36
- // convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
37
- $.growlUI = function(title, message, timeout, onClose) {
38
- var $m = $('<div class="growlUI"></div>');
39
- if (title) $m.append('<h1>'+title+'</h1>');
40
- if (message) $m.append('<h2>'+message+'</h2>');
41
- if (timeout == undefined) timeout = 3000;
42
- $.blockUI({
43
- message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
44
- timeout: timeout, showOverlay: false,
45
- onUnblock: onClose,
46
- css: $.blockUI.defaults.growlCSS
47
- });
48
- };
49
-
50
- // plugin method for blocking element content
51
- $.fn.block = function(opts) {
52
- return this.unblock({ fadeOut: 0 }).each(function() {
53
- if ($.css(this,'position') == 'static')
54
- this.style.position = 'relative';
55
- if ($.browser.msie)
56
- this.style.zoom = 1; // force 'hasLayout'
57
- install(this, opts);
58
- });
59
- };
60
-
61
- // plugin method for unblocking element content
62
- $.fn.unblock = function(opts) {
63
- return this.each(function() {
64
- remove(this, opts);
65
- });
66
- };
67
-
68
- $.blockUI.version = 2.39; // 2nd generation blocking at no extra cost!
69
-
70
- // override these in your code to change the default behavior and style
71
- $.blockUI.defaults = {
72
- // message displayed when blocking (use null for no message)
73
- message: '<h1>Please wait...</h1>',
74
-
75
- title: null, // title string; only used when theme == true
76
- draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded)
77
-
78
- theme: false, // set to true to use with jQuery UI themes
79
-
80
- // styles for the message when blocking; if you wish to disable
81
- // these and use an external stylesheet then do this in your code:
82
- // $.blockUI.defaults.css = {};
83
- css: {
84
- padding: 0,
85
- margin: 0,
86
- width: '30%',
87
- top: '40%',
88
- left: '35%',
89
- textAlign: 'center',
90
- color: '#000',
91
- border: '3px solid #aaa',
92
- backgroundColor:'#fff',
93
- cursor: 'wait'
94
- },
95
-
96
- // minimal style set used when themes are used
97
- themedCSS: {
98
- width: '30%',
99
- top: '40%',
100
- left: '35%'
101
- },
102
-
103
- // styles for the overlay
104
- overlayCSS: {
105
- backgroundColor: '#000',
106
- opacity: 0.6,
107
- cursor: 'wait'
108
- },
109
-
110
- // styles applied when using $.growlUI
111
- growlCSS: {
112
- width: '350px',
113
- top: '10px',
114
- left: '',
115
- right: '10px',
116
- border: 'none',
117
- padding: '5px',
118
- opacity: 0.6,
119
- cursor: 'default',
120
- color: '#fff',
121
- backgroundColor: '#000',
122
- '-webkit-border-radius': '10px',
123
- '-moz-border-radius': '10px',
124
- 'border-radius': '10px'
125
- },
126
-
127
- // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
128
- // (hat tip to Jorge H. N. de Vasconcelos)
129
- iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
130
-
131
- // force usage of iframe in non-IE browsers (handy for blocking applets)
132
- forceIframe: false,
133
-
134
- // z-index for the blocking overlay
135
- baseZ: 1000,
136
-
137
- // set these to true to have the message automatically centered
138
- centerX: true, // <-- only effects element blocking (page block controlled via css above)
139
- centerY: true,
140
-
141
- // allow body element to be stetched in ie6; this makes blocking look better
142
- // on "short" pages. disable if you wish to prevent changes to the body height
143
- allowBodyStretch: true,
144
-
145
- // enable if you want key and mouse events to be disabled for content that is blocked
146
- bindEvents: true,
147
-
148
- // be default blockUI will supress tab navigation from leaving blocking content
149
- // (if bindEvents is true)
150
- constrainTabKey: true,
151
-
152
- // fadeIn time in millis; set to 0 to disable fadeIn on block
153
- fadeIn: 200,
154
-
155
- // fadeOut time in millis; set to 0 to disable fadeOut on unblock
156
- fadeOut: 400,
157
-
158
- // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
159
- timeout: 0,
160
-
161
- // disable if you don't want to show the overlay
162
- showOverlay: true,
163
-
164
- // if true, focus will be placed in the first available input field when
165
- // page blocking
166
- focusInput: true,
167
-
168
- // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
169
- applyPlatformOpacityRules: true,
170
-
171
- // callback method invoked when fadeIn has completed and blocking message is visible
172
- onBlock: null,
173
-
174
- // callback method invoked when unblocking has completed; the callback is
175
- // passed the element that has been unblocked (which is the window object for page
176
- // blocks) and the options that were passed to the unblock call:
177
- // onUnblock(element, options)
178
- onUnblock: null,
179
-
180
- // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
181
- quirksmodeOffsetHack: 4,
182
-
183
- // class name of the message block
184
- blockMsgClass: 'blockMsg'
185
- };
186
-
187
- // private data and functions follow...
188
-
189
- var pageBlock = null;
190
- var pageBlockEls = [];
191
-
192
- function install(el, opts) {
193
- var full = (el == window);
194
- var msg = opts && opts.message !== undefined ? opts.message : undefined;
195
- opts = $.extend({}, $.blockUI.defaults, opts || {});
196
- opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
197
- var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
198
- var themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
199
- msg = msg === undefined ? opts.message : msg;
200
-
201
- // remove the current block (if there is one)
202
- if (full && pageBlock)
203
- remove(window, {fadeOut:0});
204
-
205
- // if an existing element is being used as the blocking content then we capture
206
- // its current place in the DOM (and current display style) so we can restore
207
- // it when we unblock
208
- if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
209
- var node = msg.jquery ? msg[0] : msg;
210
- var data = {};
211
- $(el).data('blockUI.history', data);
212
- data.el = node;
213
- data.parent = node.parentNode;
214
- data.display = node.style.display;
215
- data.position = node.style.position;
216
- if (data.parent)
217
- data.parent.removeChild(node);
218
- }
219
-
220
- $(el).data('blockUI.onUnblock', opts.onUnblock);
221
- var z = opts.baseZ;
222
-
223
- // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
224
- // layer1 is the iframe layer which is used to supress bleed through of underlying content
225
- // layer2 is the overlay layer which has opacity and a wait cursor (by default)
226
- // layer3 is the message content that is displayed while blocking
227
-
228
- var lyr1 = ($.browser.msie || opts.forceIframe)
229
- ? $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>')
230
- : $('<div class="blockUI" style="display:none"></div>');
231
-
232
- var lyr2 = opts.theme
233
- ? $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>')
234
- : $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
235
-
236
- var lyr3, s;
237
- if (opts.theme && full) {
238
- s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">' +
239
- '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>' +
240
- '<div class="ui-widget-content ui-dialog-content"></div>' +
241
- '</div>';
242
- }
243
- else if (opts.theme) {
244
- s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">' +
245
- '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>' +
246
- '<div class="ui-widget-content ui-dialog-content"></div>' +
247
- '</div>';
248
- }
249
- else if (full) {
250
- s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
251
- }
252
- else {
253
- s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
254
- }
255
- lyr3 = $(s);
256
-
257
- // if we have a message, style it
258
- if (msg) {
259
- if (opts.theme) {
260
- lyr3.css(themedCSS);
261
- lyr3.addClass('ui-widget-content');
262
- }
263
- else
264
- lyr3.css(css);
265
- }
266
-
267
- // style the overlay
268
- if (!opts.theme && (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform))))
269
- lyr2.css(opts.overlayCSS);
270
- lyr2.css('position', full ? 'fixed' : 'absolute');
271
-
272
- // make iframe layer transparent in IE
273
- if ($.browser.msie || opts.forceIframe)
274
- lyr1.css('opacity',0.0);
275
-
276
- //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
277
- var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
278
- $.each(layers, function() {
279
- this.appendTo($par);
280
- });
281
-
282
- if (opts.theme && opts.draggable && $.fn.draggable) {
283
- lyr3.draggable({
284
- handle: '.ui-dialog-titlebar',
285
- cancel: 'li'
286
- });
287
- }
288
-
289
- // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
290
- var expr = setExpr && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
291
- if (ie6 || expr) {
292
- // give body 100% height
293
- if (full && opts.allowBodyStretch && $.boxModel)
294
- $('html,body').css('height','100%');
295
-
296
- // fix ie6 issue when blocked element has a border width
297
- if ((ie6 || !$.boxModel) && !full) {
298
- var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
299
- var fixT = t ? '(0 - '+t+')' : 0;
300
- var fixL = l ? '(0 - '+l+')' : 0;
301
- }
302
-
303
- // simulate fixed position
304
- $.each([lyr1,lyr2,lyr3], function(i,o) {
305
- var s = o[0].style;
306
- s.position = 'absolute';
307
- if (i < 2) {
308
- full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
309
- : s.setExpression('height','this.parentNode.offsetHeight + "px"');
310
- full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
311
- : s.setExpression('width','this.parentNode.offsetWidth + "px"');
312
- if (fixL) s.setExpression('left', fixL);
313
- if (fixT) s.setExpression('top', fixT);
314
- }
315
- else if (opts.centerY) {
316
- if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
317
- s.marginTop = 0;
318
- }
319
- else if (!opts.centerY && full) {
320
- var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0;
321
- var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
322
- s.setExpression('top',expression);
323
- }
324
- });
325
- }
326
-
327
- // show the message
328
- if (msg) {
329
- if (opts.theme)
330
- lyr3.find('.ui-widget-content').append(msg);
331
- else
332
- lyr3.append(msg);
333
- if (msg.jquery || msg.nodeType)
334
- $(msg).show();
335
- }
336
-
337
- if (($.browser.msie || opts.forceIframe) && opts.showOverlay)
338
- lyr1.show(); // opacity is zero
339
- if (opts.fadeIn) {
340
- var cb = opts.onBlock ? opts.onBlock : noOp;
341
- var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
342
- var cb2 = msg ? cb : noOp;
343
- if (opts.showOverlay)
344
- lyr2._fadeIn(opts.fadeIn, cb1);
345
- if (msg)
346
- lyr3._fadeIn(opts.fadeIn, cb2);
347
- }
348
- else {
349
- if (opts.showOverlay)
350
- lyr2.show();
351
- if (msg)
352
- lyr3.show();
353
- if (opts.onBlock)
354
- opts.onBlock();
355
- }
356
-
357
- // bind key and mouse events
358
- bind(1, el, opts);
359
-
360
- if (full) {
361
- pageBlock = lyr3[0];
362
- pageBlockEls = $(':input:enabled:visible',pageBlock);
363
- if (opts.focusInput)
364
- setTimeout(focus, 20);
365
- }
366
- else
367
- center(lyr3[0], opts.centerX, opts.centerY);
368
-
369
- if (opts.timeout) {
370
- // auto-unblock
371
- var to = setTimeout(function() {
372
- full ? $.unblockUI(opts) : $(el).unblock(opts);
373
- }, opts.timeout);
374
- $(el).data('blockUI.timeout', to);
375
- }
376
- };
377
-
378
- // remove the block
379
- function remove(el, opts) {
380
- var full = (el == window);
381
- var $el = $(el);
382
- var data = $el.data('blockUI.history');
383
- var to = $el.data('blockUI.timeout');
384
- if (to) {
385
- clearTimeout(to);
386
- $el.removeData('blockUI.timeout');
387
- }
388
- opts = $.extend({}, $.blockUI.defaults, opts || {});
389
- bind(0, el, opts); // unbind events
390
-
391
- if (opts.onUnblock === null) {
392
- opts.onUnblock = $el.data('blockUI.onUnblock');
393
- $el.removeData('blockUI.onUnblock');
394
- }
395
-
396
- var els;
397
- if (full) // crazy selector to handle odd field errors in ie6/7
398
- els = $('body').children().filter('.blockUI').add('body > .blockUI');
399
- else
400
- els = $('.blockUI', el);
401
-
402
- if (full)
403
- pageBlock = pageBlockEls = null;
404
-
405
- if (opts.fadeOut) {
406
- els.fadeOut(opts.fadeOut);
407
- setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
408
- }
409
- else
410
- reset(els, data, opts, el);
411
- };
412
-
413
- // move blocking element back into the DOM where it started
414
- function reset(els,data,opts,el) {
415
- els.each(function(i,o) {
416
- // remove via DOM calls so we don't lose event handlers
417
- if (this.parentNode)
418
- this.parentNode.removeChild(this);
419
- });
420
-
421
- if (data && data.el) {
422
- data.el.style.display = data.display;
423
- data.el.style.position = data.position;
424
- if (data.parent)
425
- data.parent.appendChild(data.el);
426
- $(el).removeData('blockUI.history');
427
- }
428
-
429
- if (typeof opts.onUnblock == 'function')
430
- opts.onUnblock(el,opts);
431
- };
432
-
433
- // bind/unbind the handler
434
- function bind(b, el, opts) {
435
- var full = el == window, $el = $(el);
436
-
437
- // don't bother unbinding if there is nothing to unbind
438
- if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
439
- return;
440
- if (!full)
441
- $el.data('blockUI.isBlocked', b);
442
-
443
- // don't bind events when overlay is not in use or if bindEvents is false
444
- if (!opts.bindEvents || (b && !opts.showOverlay))
445
- return;
446
-
447
- // bind anchors and inputs for mouse and key events
448
- var events = 'mousedown mouseup keydown keypress';
449
- b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler);
450
-
451
- // former impl...
452
- // var $e = $('a,:input');
453
- // b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
454
- };
455
-
456
- // event handler to suppress keyboard/mouse events when blocking
457
- function handler(e) {
458
- // allow tab navigation (conditionally)
459
- if (e.keyCode && e.keyCode == 9) {
460
- if (pageBlock && e.data.constrainTabKey) {
461
- var els = pageBlockEls;
462
- var fwd = !e.shiftKey && e.target === els[els.length-1];
463
- var back = e.shiftKey && e.target === els[0];
464
- if (fwd || back) {
465
- setTimeout(function(){focus(back)},10);
466
- return false;
467
- }
468
- }
469
- }
470
- var opts = e.data;
471
- // allow events within the message content
472
- if ($(e.target).parents('div.' + opts.blockMsgClass).length > 0)
473
- return true;
474
-
475
- // allow events for content that is not being blocked
476
- return $(e.target).parents().children().filter('div.blockUI').length == 0;
477
- };
478
-
479
- function focus(back) {
480
- if (!pageBlockEls)
481
- return;
482
- var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
483
- if (e)
484
- e.focus();
485
- };
486
-
487
- function center(el, x, y) {
488
- var p = el.parentNode, s = el.style;
489
- var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
490
- var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
491
- if (x) s.left = l > 0 ? (l+'px') : '0';
492
- if (y) s.top = t > 0 ? (t+'px') : '0';
493
- };
494
-
495
- function sz(el, p) {
496
- return parseInt($.css(el,p))||0;
497
- };
498
-
499
- })(jQuery);