blacklight 3.4.2 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. data/Gemfile +4 -0
  2. data/VERSION +1 -1
  3. data/app/assets/javascripts/blacklight/blacklight.js +15 -474
  4. data/app/assets/javascripts/blacklight/bookmark_toggle.js +21 -0
  5. data/app/assets/javascripts/blacklight/checkbox_submit.js +126 -0
  6. data/app/assets/javascripts/blacklight/core.js +2 -0
  7. data/app/assets/javascripts/blacklight/facet_expand_contract.js +40 -0
  8. data/app/assets/javascripts/blacklight/folder_toggle.js +24 -0
  9. data/app/assets/javascripts/blacklight/lightbox_dialog.js +15 -0
  10. data/app/assets/javascripts/blacklight/more_facets.js +15 -0
  11. data/app/assets/javascripts/blacklight/search_context.js +26 -0
  12. data/app/assets/javascripts/blacklight/select_submit.js +18 -0
  13. data/app/assets/javascripts/blacklight/zebra_stripe.js +13 -0
  14. data/app/assets/javascripts/jquery.uiExt.ajaxyDialog.js +180 -0
  15. data/app/controllers/bookmarks_controller.rb +9 -9
  16. data/app/controllers/feedback_controller.rb +3 -3
  17. data/app/controllers/folder_controller.rb +3 -3
  18. data/app/controllers/saved_searches_controller.rb +7 -7
  19. data/app/controllers/search_history_controller.rb +2 -2
  20. data/app/helpers/blacklight/blacklight_helper_behavior.rb +6 -10
  21. data/app/helpers/blacklight/catalog_helper_behavior.rb +8 -11
  22. data/app/helpers/blacklight/facets_helper_behavior.rb +2 -2
  23. data/app/helpers/blacklight/search_history_constraints_helper_behavior.rb +2 -2
  24. data/app/models/bookmark.rb +5 -0
  25. data/app/models/record_mailer.rb +5 -11
  26. data/app/views/_user_util_links.html.erb +6 -6
  27. data/app/views/bookmarks/index.html.erb +8 -8
  28. data/app/views/catalog/_bookmark_control.html.erb +2 -2
  29. data/app/views/catalog/_bookmark_form.html.erb +3 -3
  30. data/app/views/catalog/_citation.html.erb +3 -3
  31. data/app/views/catalog/_constraints.html.erb +1 -1
  32. data/app/views/catalog/_constraints_element.html.erb +2 -2
  33. data/app/views/catalog/_did_you_mean.html.erb +2 -7
  34. data/app/views/catalog/_document.html.erb +1 -1
  35. data/app/views/catalog/_email_form.html.erb +4 -4
  36. data/app/views/catalog/_facet_limit.html.erb +1 -1
  37. data/app/views/catalog/_facet_pagination.html.erb +7 -7
  38. data/app/views/catalog/_facets.html.erb +1 -1
  39. data/app/views/catalog/_folder_control.html.erb +1 -1
  40. data/app/views/catalog/_home_text.html.erb +1 -1
  41. data/app/views/catalog/_marc_view.html.erb +2 -2
  42. data/app/views/catalog/_refworks_form.html.erb +2 -2
  43. data/app/views/catalog/_results_pagination.html.erb +1 -1
  44. data/app/views/catalog/_search_form.html.erb +5 -5
  45. data/app/views/catalog/_show_tools.html.erb +6 -6
  46. data/app/views/catalog/_sms_form.html.erb +5 -5
  47. data/app/views/catalog/_sort_and_per_page.html.erb +6 -9
  48. data/app/views/catalog/index.atom.builder +3 -3
  49. data/app/views/catalog/index.html.erb +2 -2
  50. data/app/views/catalog/index.rss.builder +3 -3
  51. data/app/views/catalog/show.html.erb +2 -2
  52. data/app/views/feedback/complete.html.erb +2 -2
  53. data/app/views/feedback/show.html.erb +5 -5
  54. data/app/views/folder/_tools.html.erb +4 -4
  55. data/app/views/folder/index.html.erb +1 -1
  56. data/app/views/layouts/blacklight.html.erb +1 -1
  57. data/app/views/record_mailer/email_record.text.erb +2 -2
  58. data/app/views/record_mailer/sms_record.text.erb +1 -1
  59. data/app/views/saved_searches/index.html.erb +6 -6
  60. data/app/views/search_history/index.html.erb +6 -6
  61. data/config/locales/blacklight.en.yml +227 -0
  62. data/lib/blacklight.rb +0 -2
  63. data/lib/blacklight/catalog.rb +11 -13
  64. data/lib/blacklight/configurable.rb +0 -3
  65. data/lib/blacklight/configuration.rb +0 -42
  66. data/lib/blacklight/configuration/fields.rb +2 -0
  67. data/lib/blacklight/routes.rb +14 -2
  68. data/lib/blacklight/search_fields.rb +1 -1
  69. data/lib/blacklight/solr/document/email.rb +6 -6
  70. data/lib/blacklight/solr/document/sms.rb +4 -4
  71. data/lib/blacklight/solr_helper.rb +1 -3
  72. data/lib/generators/blacklight/blacklight_generator.rb +3 -0
  73. data/lib/railties/blacklight_cucumber.rake +12 -3
  74. data/lib/railties/blacklight_rspec.rake +9 -2
  75. data/test_support/alternate_controller.rb +4 -0
  76. data/test_support/bin/test.sh +13 -1
  77. data/test_support/features/bookmarks.feature +1 -1
  78. data/test_support/features/librarian_view.feature +2 -1
  79. data/test_support/features/record_view.feature +1 -0
  80. data/test_support/features/search.feature +1 -0
  81. data/test_support/features/step_definitions/general_steps.rb +4 -0
  82. data/test_support/features/support/env.rb +12 -1
  83. data/test_support/features/support/paths.rb +2 -1
  84. data/test_support/spec/helpers/blacklight_helper_spec.rb +8 -2
  85. data/test_support/spec/helpers/search_history_constraints_helper_spec.rb +6 -18
  86. data/test_support/spec/lib/search_fields_spec.rb +18 -25
  87. data/test_support/spec/models/record_mailer_spec.rb +5 -4
  88. data/test_support/spec/requests/alternate_controller_spec.rb +15 -0
  89. data/test_support/spec/spec_helper.rb +12 -0
  90. data/test_support/spec/views/catalog/_index_default.erb_spec.rb +6 -17
  91. data/test_support/spec/views/catalog/_show_default.erb_spec.rb +7 -17
  92. metadata +19 -8
  93. data/config/locales/kaminari.yml +0 -10
  94. data/lib/blacklight/global_configurable.rb +0 -46
  95. data/test_support/spec/lib/global_configurable_spec.rb +0 -98
@@ -0,0 +1,21 @@
1
+ //= require blacklight/core
2
+ //= require blacklight/checkbox_submit
3
+ (function($) {
4
+ //change form submit toggle to checkbox
5
+ Blacklight.do_bookmark_toggle_behavior = function() {
6
+ $(Blacklight.do_bookmark_toggle_behavior.selector).bl_checkbox_submit({
7
+ checked_label: "In Bookmarks",
8
+ unchecked_label: "Bookmark",
9
+ progress_label: "Saving...",
10
+ //css_class is added to elements added, plus used for id base
11
+ css_class: "toggle_bookmark"
12
+ });
13
+ };
14
+ Blacklight.do_bookmark_toggle_behavior.selector = "form.bookmark_toggle";
15
+
16
+ $(document).ready(function() {
17
+ Blacklight.do_bookmark_toggle_behavior();
18
+ });
19
+
20
+
21
+ })(jQuery);
@@ -0,0 +1,126 @@
1
+ /* A JQuery plugin (should this be implemented as a widget instead? not sure)
2
+ that will convert a "toggle" form, with single submit button to add/remove
3
+ something, like used for Bookmarks/Folder, into an AJAXy checkbox instead.
4
+
5
+ Apply to a form. Does require certain assumption about the form:
6
+ 1) The same form 'action' href must be used for both ADD and REMOVE
7
+ actions, with the different being the hidden input name="_method"
8
+ being set to "put" or "delete" -- that's the Rails method to pretend
9
+ to be doing a certain HTTP verb. So same URL, PUT to add, DELETE
10
+ to remove. This plugin assumes that.
11
+
12
+ Plus, the form this is applied to should provide a data-doc-id
13
+ attribute (HTML5-style doc-*) that contains the id/primary key
14
+ of the object in question -- used by plugin for a unique value for
15
+ DOM id's.
16
+
17
+ Pass in options for your class name and labels:
18
+ $("form.something").bl_checkbox_submit({
19
+ checked_label: "Selected",
20
+ unchecked_label: "Select",
21
+ progress_label: "Saving...",
22
+ //css_class is added to elements added, plus used for id base
23
+ css_class: "toggle_my_kinda_form",
24
+ success: function(after_success_check_state) {
25
+ #optional callback
26
+ }
27
+ });
28
+ */
29
+ (function($) {
30
+ $.fn.bl_checkbox_submit = function(arg_opts) {
31
+
32
+ this.each(function() {
33
+ var options = $.extend({}, $.fn.bl_checkbox_submit.defaults, arg_opts);
34
+
35
+
36
+ var form = $(this);
37
+ form.children().hide();
38
+ //We're going to use the existing form to actually send our add/removes
39
+ //This works conveneintly because the exact same action href is used
40
+ //for both bookmarks/$doc_id. But let's take out the irrelevant parts
41
+ //of the form to avoid any future confusion.
42
+ form.find("input[type=submit]").remove();
43
+
44
+ //View needs to set data-doc-id so we know a unique value
45
+ //for making DOM id
46
+ var unique_id = form.attr("data-doc-id") || Math.random();
47
+ // if form is currently using method delete to change state,
48
+ // then checkbox is currently checked
49
+ var checked = (form.find("input[name=_method][value=delete]").size() != 0);
50
+
51
+ var checkbox = $('<input type="checkbox">')
52
+ .addClass( options.css_class )
53
+ .attr("id", options.css_class + "_" + unique_id);
54
+ var label = $('<label>')
55
+ .addClass( options.css_class )
56
+ .attr("for", options.css_class + '_' + unique_id)
57
+ .attr("title", form.attr("title") || "");
58
+
59
+
60
+ function update_state_for(state) {
61
+ checkbox.attr("checked", state);
62
+ label.toggleClass("checked", state);
63
+ if (state) {
64
+ //Set the Rails hidden field that fakes an HTTP verb
65
+ //properly for current state action.
66
+ form.find("input[name=_method]").val("delete");
67
+ label.text(options.checked_label);
68
+ } else {
69
+ form.find("input[name=_method]").val("put");
70
+ label.text(options.unchecked_label);
71
+ }
72
+ }
73
+
74
+ form.append(checkbox).append(" ").append(label);
75
+ update_state_for(checked);
76
+
77
+ checkbox.click(function() {
78
+ label.text(options.progress_label).attr("disabled", "disabled");
79
+ checkbox.attr("disabled", "disabled");
80
+
81
+ $.ajax({
82
+ url: form.attr("action"),
83
+ dataType: 'json',
84
+ type: form.attr("method").toUpperCase(),
85
+ data: form.serialize(),
86
+ error: function() {
87
+ alert("Error");
88
+ update_state_for(checked);
89
+ label.removeAttr("disabled");
90
+ checkbox.removeAttr("disabled");
91
+ },
92
+ success: function(data, status, xhr) {
93
+ //if app isn't running at all, xhr annoyingly
94
+ //reports success with status 0.
95
+ if (xhr.status != 0) {
96
+ checked = ! checked;
97
+ update_state_for(checked);
98
+ label.removeAttr("disabled");
99
+ checkbox.removeAttr("disabled");
100
+ options.success.call(form, checked);
101
+ } else {
102
+ alert("Error");
103
+ update_state_for(checked);
104
+ label.removeAttr("disabled");
105
+ checkbox.removeAttr("disabled");
106
+ }
107
+ }
108
+ });
109
+
110
+ return false;
111
+ }); //checkbox.click
112
+
113
+
114
+ }); //this.each
115
+ return this;
116
+ };
117
+
118
+ $.fn.bl_checkbox_submit.defaults = {
119
+ checked_label: "",
120
+ unchecked_label: "",
121
+ progress_label: "Saving...",
122
+ //css_class is added to elements added, plus used for id base
123
+ css_class: "bl_checkbox_submit",
124
+ success: function() {} //callback
125
+ };
126
+ })(jQuery);
@@ -0,0 +1,2 @@
1
+ //= require jquery.uiExt.ajaxyDialog.js
2
+ Blacklight = {};
@@ -0,0 +1,40 @@
1
+ //= require blacklight/core
2
+ (function($) {
3
+ Blacklight.do_facet_expand_contract_behavior = function() {
4
+ $( Blacklight.do_facet_expand_contract_behavior.selector ).each (
5
+ Blacklight.facet_expand_contract
6
+ );
7
+ }
8
+ Blacklight.do_facet_expand_contract_behavior.selector = '#facets h3';
9
+
10
+ /* Behavior that makes facet limit headings in sidebar expand/contract
11
+ their contents. This is kind of fragile code targeted specifically
12
+ at how we currently render facet HTML, which is why I put it in a function
13
+ on Blacklight instead of in a jquery plugin. Perhaps in the future this
14
+ could/should be expanded to a general purpose jquery plugin -- or
15
+ we should just use one of the existing ones for expand/contract? */
16
+ Blacklight.facet_expand_contract = function() {
17
+ $(this).next("ul, div").each(function(){
18
+ var f_content = $(this);
19
+ $(f_content).prev('h3').addClass('twiddle');
20
+ // find all f_content's that don't have any span descendants with a class of "selected"
21
+ if($('span.selected', f_content).length == 0){
22
+ // hide it
23
+ f_content.hide();
24
+ } else {
25
+ $(this).prev('h3').addClass('twiddle-open');
26
+ }
27
+
28
+ // attach the toggle behavior to the h3 tag
29
+ $('h3', f_content.parent()).click(function(){
30
+ // toggle the content
31
+ $(this).toggleClass('twiddle-open');
32
+ $(f_content).slideToggle();
33
+ });
34
+ });
35
+ };
36
+ $(document).ready(function() {
37
+ Blacklight.do_facet_expand_contract_behavior();
38
+ });
39
+ })(jQuery);
40
+
@@ -0,0 +1,24 @@
1
+ //= require blacklight/core
2
+ //= require blacklight/checkbox_submit
3
+ (function($) {
4
+ Blacklight.do_folder_toggle_behavior = function() {
5
+ $( Blacklight.do_folder_toggle_behavior.selector ).bl_checkbox_submit({
6
+ checked_label: "Selected",
7
+ unchecked_label: "Select",
8
+ css_class: "toggle_folder",
9
+ success: function(new_state) {
10
+
11
+ if (new_state) {
12
+ $("#folder_number").text(parseInt($("#folder_number").text()) + 1);
13
+ }
14
+ else {
15
+ $("#folder_number").text(parseInt($("#folder_number").text()) - 1);
16
+ }
17
+ }
18
+ });
19
+ };
20
+ Blacklight.do_folder_toggle_behavior.selector = "form.folder_toggle";
21
+ $(document).ready(function() {
22
+ Blacklight.do_folder_toggle_behavior();
23
+ });
24
+ })(jQuery);
@@ -0,0 +1,15 @@
1
+ //= require blacklight/core
2
+ (function($) {
3
+ Blacklight.do_lightbox_dialog = function() {
4
+ $("a.lightboxLink").ajaxyDialog({
5
+ chainAjaxySelector: false
6
+ });
7
+ //But make the librarian link wider than 300px default.
8
+ $('a.lightboxLink#librarianLink').ajaxyDialog("option", "width", 650);
9
+ //And the email one too needs to be wider to fit the textarea
10
+ $("a.lightboxLink#emailLink").ajaxyDialog("option", "width", 500);
11
+ };
12
+ $(document).ready(function() {
13
+ Blacklight.do_lightbox_dialog();
14
+ });
15
+ })(jQuery);
@@ -0,0 +1,15 @@
1
+ //= require blacklight/core
2
+ (function($) {
3
+ //add ajaxy dialogs to certain links, using the ajaxyDialog widget.
4
+ Blacklight.do_more_facets_behavior = function () {
5
+ $( Blacklight.do_more_facets_behavior.selector ).ajaxyDialog({
6
+ width: $(window).width() / 2,
7
+ chainAjaxySelector: "a.next_page, a.prev_page, a.sort_change"
8
+ });
9
+ };
10
+ Blacklight.do_more_facets_behavior.selector = "a.more_facets_link";
11
+
12
+ $(document).ready(function() {
13
+ Blacklight.do_more_facets_behavior();
14
+ });
15
+ })(jQuery);
@@ -0,0 +1,26 @@
1
+ //= require blacklight/core
2
+ (function($) {
3
+ Blacklight.do_search_context_behavior = function() {
4
+ $('a[data-counter]').click(function(event) {
5
+ var f = document.createElement('form'); f.style.display = 'none';
6
+ this.parentNode.appendChild(f);
7
+ f.method = 'POST';
8
+ f.action = $(this).attr('href');
9
+ if(event.metaKey || event.ctrlKey){f.target = '_blank';};
10
+ var d = document.createElement('input'); d.setAttribute('type', 'hidden');
11
+ d.setAttribute('name', 'counter'); d.setAttribute('value', $(this).data('counter')); f.appendChild(d);
12
+ var m = document.createElement('input'); m.setAttribute('type', 'hidden');
13
+ m.setAttribute('name', '_method'); m.setAttribute('value', 'put'); f.appendChild(m);
14
+ var m = document.createElement('input'); m.setAttribute('type', 'hidden');
15
+ m.setAttribute('name', $('meta[name="csrf-param"]').attr('content')); m.setAttribute('value', $('meta[name="csrf-token"]').attr('content')); f.appendChild(m);
16
+
17
+ f.submit();
18
+
19
+ return false;
20
+ });
21
+
22
+ };
23
+ $(document).ready(function() {
24
+ Blacklight.do_search_context_behavior();
25
+ });
26
+ })(jQuery);
@@ -0,0 +1,18 @@
1
+ //= require blacklight/core
2
+ (function($) {
3
+ // Used for sort-by and per-page controls, hide the submit button
4
+ // and make the select auto-submit
5
+ Blacklight.do_select_submit = function() {
6
+ $(Blacklight.do_select_submit.selector).each(function() {
7
+ var select = $(this);
8
+ select.closest("form").find("input[type=submit]").hide();
9
+ select.bind("change", function() {
10
+ this.form.submit();
11
+ });
12
+ });
13
+ };
14
+ Blacklight.do_select_submit.selector = "form.sort select, form.per_page select";
15
+ $(document).ready(function() {
16
+ Blacklight.do_select_submit();
17
+ });
18
+ })(jQuery);
@@ -0,0 +1,13 @@
1
+ //= require blacklight/core
2
+ (function($) {
3
+ // adds classes for zebra striping table rows
4
+ Blacklight.do_zebra_stripe = function() {
5
+ $(Blacklight.do_zebra_stripe.selector).addClass('zebra_stripe');
6
+ };
7
+ Blacklight.do_zebra_stripe.selector = "table.zebra tr:even, ul.zebra li:even";
8
+
9
+
10
+ $(document).ready(function() {
11
+ Blacklight.do_zebra_stripe();
12
+ });
13
+ })(jQuery);
@@ -0,0 +1,180 @@
1
+ /* A widget written by jrochkind to make a link or form result in
2
+ an in-window ajaxy dialog, instead of page load, using JQuery UI
3
+ Dialog widget.
4
+
5
+ This widget is actually hosted at: https://github.com/jrochkind/jquery.uiExt.ajaxyDialog
6
+
7
+ */
8
+
9
+ (function($) {
10
+ var widgetNamespace = "uiExt";
11
+ var widgetName = "ajaxyDialog";
12
+
13
+ $.widget(widgetNamespace + "." + widgetName, {
14
+ options: {
15
+ extractTitleSelector: "h1, h2, h3, h4, h5",
16
+ chainAjaxySelector: "a:not([target]), form:not([target])",
17
+ closeDialogSelector: "a.dialog-close"
18
+ },
19
+
20
+ _create: function() {
21
+ var self = this;
22
+ var element = self.element[0];
23
+ if (element.tagName.toUpperCase() == "A") {
24
+ $(element).bind("click."+self.widgetName, function(event, ui) {
25
+ self._handleClick();
26
+ return false;
27
+ });
28
+ }
29
+ else if (element.tagName.toUpperCase() == "FORM") {
30
+ $(element).bind("submit."+self.widgetName, function(event, ui) {
31
+ self._handleSubmit();
32
+ return false;
33
+ });
34
+ }
35
+ },
36
+
37
+ open: function() {
38
+ var self = this;
39
+ var element = self.element[0];
40
+
41
+ if ( element.tagName.toUpperCase() == "A") {
42
+ self._handleClick();
43
+ } else if (element.tagName.toUpperCase() == "FORM") {
44
+ self._handleSubmit();
45
+ }
46
+ },
47
+
48
+ close: function() {
49
+ this.dialogContainer().dialog("close");
50
+ },
51
+
52
+ _handleClick: function() {
53
+ var self = this;
54
+ var url = this.element.attr("href");
55
+ var requestDialog = self.dialogContainer();
56
+
57
+ $("body").css("cursor", "progress");
58
+
59
+ $.ajax({
60
+ url: url,
61
+ dataType: "html",
62
+ success: function(resp, status, xhr) {
63
+ if (xhr.status != 0) {
64
+ self._loadToDialog(resp);
65
+ } else {
66
+ //stupid jquery calling this 'success', it's
67
+ //network unavailable.
68
+ self._displayFailure(url, xhr, status);
69
+ }
70
+ },
71
+ error: function(xhr, msg) {
72
+ self._displayFailure(url, xhr, msg);
73
+ }
74
+ });
75
+ },
76
+
77
+ _handleSubmit: function() {
78
+ var self = this;
79
+ var form = self.element;
80
+ var actionUri = form.attr("action");
81
+ var serialized = form.serialize();
82
+
83
+ $("body").css("cursor", "progress");
84
+
85
+ $.ajax({
86
+ url: actionUri,
87
+ data: serialized,
88
+ type: form.attr("method").toUpperCase(),
89
+ dataType: "html",
90
+ success: function(resp, status, xhr) {
91
+ if (xhr.status != 0) {
92
+ self._loadToDialog(resp);
93
+ } else {
94
+ //stupid jquery calling this 'success', it's
95
+ //network unavailable.
96
+ self._displayFailure(url, xhr, status);
97
+ }
98
+ },
99
+ error: function(xhr, msg) {
100
+ self._displayFailure(actionUri, xhr, msg);
101
+ }
102
+ });
103
+ },
104
+
105
+ _loadToDialog: function(html_content) {
106
+ var self = this;
107
+ var dialog = self.dialogContainer();
108
+ //Cheesy way to restore it to it's default options, plus
109
+ //our own local options, since its' a reuseable dialog.
110
+ //for now we insist on modal:true.
111
+ dialog.dialog($.extend({},
112
+ $.ui.dialog.prototype.options,
113
+ self.options,
114
+ {autoOpen:false, modal:true}
115
+ ));
116
+
117
+ if (self._trigger('beforeDisplay', 0, html_content) !== false) {
118
+ dialog.html( html_content );
119
+
120
+ //extract and set title
121
+ var title;
122
+ self.options.extractTitleSelector &&
123
+ (title = dialog.find(self.options.extractTitleSelector).first().remove().text());
124
+ title = title ||
125
+ self.element.attr("title")
126
+ title && dialog.dialog("option", "title", title);
127
+
128
+ //Make any hyperlinks or forms ajaxified, by applying
129
+ //this very same plugin to em, and passing on our options.
130
+ if (self.options.chainAjaxySelector) {
131
+ dialog.find(self.options.chainAjaxySelector).ajaxyDialog(self.options);
132
+ }
133
+
134
+ //Make any links marked dialog-close do so
135
+ if ( self.options.closeDialogSelector ) {
136
+ dialog.find(self.options.closeDialogSelector).unbind("click." + widgetName);
137
+ dialog.find(self.options.closeDialogSelector).bind("click." + widgetName, function() {
138
+ dialog.dialog("close");
139
+ return false;
140
+ });
141
+ }
142
+
143
+ dialog.dialog("open");
144
+ }
145
+ $("body").css("cursor", "auto");
146
+ },
147
+
148
+ _displayFailure: function(uri, xhr, serverMsg) {
149
+ if ( this._trigger("error", 0, {uri:uri, xhr: xhr, serverMsg: serverMsg}) !== false) {
150
+ var dialog = this.dialogContainer();
151
+
152
+ dialog.html("<div class='ui-state-error' style='padding: 1em;'><p><span style='float: left; margin-right: 0.3em;' class='ui-icon ui-icon-alert'></span>Sorry, a software error has occured.</p><p>" + uri + ": " + xhr.status + " " + serverMsg+"</p></div>");
153
+ dialog.dialog("option", "title", "Sorry, an error has occured.");
154
+ dialog.dialog("option", "buttons", {"OK": function() { dialog.dialog("close"); }});
155
+ dialog.dialog("open");
156
+ }
157
+ $("body").css("cursor", "auto");
158
+ },
159
+
160
+ // The DOM element which has a ui dialog() called on it.
161
+ // Right now we insist upon modal dialogs, and re-use the same
162
+ // <div>.dialog() for all of them. It's lazily created here.
163
+ // If client calls dialog("destroy") on it, no problem, it'll
164
+ // be lazily created if it's needed again.
165
+ dialogContainer: function() {
166
+ var existing = $("#reusableModalDialog");
167
+ if ( existing.size() > 0) {
168
+ return existing.first();
169
+ }
170
+ else {
171
+ //single shared element for modal dialogs
172
+ var requestDialog = $('<div id="reusableModalDialog" style="display:none"></div>').appendTo('body').
173
+ dialog({autoOpen: false});
174
+ return requestDialog;
175
+ }
176
+ }
177
+
178
+ });
179
+ }(jQuery));
180
+