rails_admin 3.3.1 → 4.0.0.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -3
  3. data/README.md +11 -11
  4. data/Rakefile +3 -11
  5. data/app/assets/builds/rails_admin.css +10 -0
  6. data/app/assets/builds/rails_admin.js +34 -0
  7. data/app/controllers/rails_admin/main_controller.rb +3 -14
  8. data/app/helpers/rails_admin/application_helper.rb +3 -15
  9. data/app/helpers/rails_admin/form_builder.rb +6 -6
  10. data/app/views/layouts/rails_admin/_head.html.erb +10 -27
  11. data/app/views/layouts/rails_admin/_head_custom.html.erb +3 -0
  12. data/app/views/layouts/rails_admin/_secondary_navigation.html.erb +1 -1
  13. data/app/views/rails_admin/main/_dashboard_history.html.erb +1 -1
  14. data/app/views/rails_admin/main/_delete_notice.html.erb +3 -3
  15. data/app/views/rails_admin/main/_form_boolean.html.erb +9 -13
  16. data/app/views/rails_admin/main/_submit_buttons.html.erb +4 -4
  17. data/app/views/rails_admin/main/bulk_delete.html.erb +2 -2
  18. data/app/views/rails_admin/main/dashboard.html.erb +3 -3
  19. data/app/views/rails_admin/main/delete.html.erb +2 -2
  20. data/app/views/rails_admin/main/export.html.erb +2 -2
  21. data/app/views/rails_admin/main/history.html.erb +2 -2
  22. data/app/views/rails_admin/main/index.html.erb +3 -3
  23. data/config/initializers/active_record_extensions.rb +1 -4
  24. data/lib/generators/rails_admin/install_generator.rb +37 -92
  25. data/lib/generators/rails_admin/templates/rails_admin.scss.erb +1 -1
  26. data/lib/rails_admin/abstract_model.rb +69 -191
  27. data/lib/rails_admin/adapters/active_record/property.rb +7 -0
  28. data/lib/rails_admin/adapters/active_record/reflection.rb +87 -0
  29. data/lib/rails_admin/adapters/active_record/repository.rb +216 -0
  30. data/lib/rails_admin/adapters/active_record/statement_builder.rb +148 -0
  31. data/lib/rails_admin/adapters/active_record/where_builder.rb +40 -0
  32. data/lib/rails_admin/adapters/active_record.rb +7 -360
  33. data/lib/rails_admin/adapters/mongoid/extension.rb +16 -6
  34. data/lib/rails_admin/adapters/mongoid/property.rb +7 -0
  35. data/lib/rails_admin/adapters/mongoid/reflection.rb +58 -0
  36. data/lib/rails_admin/adapters/mongoid/repository.rb +237 -0
  37. data/lib/rails_admin/adapters/mongoid/statement_builder.rb +93 -0
  38. data/lib/rails_admin/adapters/mongoid.rb +7 -305
  39. data/lib/rails_admin/adapters/reflection.rb +105 -0
  40. data/lib/rails_admin/adapters/repository.rb +169 -0
  41. data/lib/rails_admin/adapters/statement_builder.rb +109 -0
  42. data/lib/rails_admin/adapters.rb +94 -0
  43. data/lib/rails_admin/config/actions/base.rb +8 -0
  44. data/lib/rails_admin/config/actions/bulk_delete.rb +4 -4
  45. data/lib/rails_admin/config/actions/dashboard.rb +1 -1
  46. data/lib/rails_admin/config/actions/edit.rb +3 -2
  47. data/lib/rails_admin/config/actions/export.rb +1 -2
  48. data/lib/rails_admin/config/actions/index.rb +3 -3
  49. data/lib/rails_admin/config/actions/new.rb +3 -2
  50. data/lib/rails_admin/config/actions/show.rb +1 -1
  51. data/lib/rails_admin/config/configurable.rb +3 -2
  52. data/lib/rails_admin/config/fields/association.rb +9 -8
  53. data/lib/rails_admin/config/fields/base.rb +55 -37
  54. data/lib/rails_admin/config/fields/collection_association.rb +2 -2
  55. data/lib/rails_admin/config/fields/factories/carrierwave.rb +35 -20
  56. data/lib/rails_admin/config/fields/factories/dragonfly.rb +30 -18
  57. data/lib/rails_admin/config/fields/factories/enum.rb +14 -8
  58. data/lib/rails_admin/config/fields/factories/paperclip.rb +29 -19
  59. data/lib/rails_admin/config/fields/factories/shrine.rb +19 -8
  60. data/lib/rails_admin/config/fields/singular_association.rb +6 -1
  61. data/lib/rails_admin/config/fields/types/active_record_enum.rb +3 -7
  62. data/lib/rails_admin/config/fields/types/belongs_to_association.rb +8 -4
  63. data/lib/rails_admin/config/fields/types/bson_object_id.rb +1 -1
  64. data/lib/rails_admin/config/fields/types/datetime.rb +0 -4
  65. data/lib/rails_admin/config/fields/types/dragonfly.rb +1 -1
  66. data/lib/rails_admin/config/fields/types/enum.rb +11 -2
  67. data/lib/rails_admin/config/fields/types/multiple_file_upload.rb +0 -2
  68. data/lib/rails_admin/config/fields/types/polymorphic_association.rb +4 -4
  69. data/lib/rails_admin/config/fields/types/time.rb +1 -1
  70. data/lib/rails_admin/config/model.rb +27 -5
  71. data/lib/rails_admin/config/sections/list.rb +0 -8
  72. data/lib/rails_admin/config.rb +7 -21
  73. data/lib/rails_admin/criteria/path.rb +66 -0
  74. data/lib/rails_admin/criteria/period.rb +67 -0
  75. data/lib/rails_admin/engine.rb +11 -15
  76. data/lib/rails_admin/extensions/pundit/authorization_adapter.rb +2 -3
  77. data/lib/rails_admin/extensions/url_for_extension.rb +8 -0
  78. data/lib/rails_admin/support/asset_source.rb +42 -0
  79. data/lib/rails_admin/support/composite_keys_serializer.rb +28 -2
  80. data/lib/rails_admin/support/csv_converter.rb +3 -10
  81. data/lib/rails_admin/version.rb +8 -7
  82. data/lib/rails_admin.rb +7 -1
  83. data/lib/tasks/assets.rake +23 -0
  84. data/package.json +12 -7
  85. data/src/rails_admin/base.js +18 -15
  86. data/src/rails_admin/filter-box.js +7 -4
  87. data/src/rails_admin/filtering-multiselect.js +1 -1
  88. data/src/rails_admin/filtering-select.js +8 -8
  89. data/src/rails_admin/flatpickr.js +14 -0
  90. data/src/rails_admin/remote-form.js +74 -48
  91. data/src/rails_admin/styles/base/theming.scss +48 -25
  92. data/src/rails_admin/styles/base.scss +25 -1
  93. data/src/rails_admin/styles/filtering-select.scss +23 -62
  94. data/src/rails_admin/ui.js +1 -1
  95. data/src/rails_admin/vendor/jquery_nested_form.js +4 -4
  96. data/src/rails_admin/widgets.js +44 -11
  97. metadata +30 -124
  98. data/app/assets/javascripts/rails_admin/application.js.erb +0 -30
  99. data/app/assets/javascripts/rails_admin/custom/ui.js +0 -1
  100. data/app/assets/stylesheets/rails_admin/application.scss.erb +0 -35
  101. data/app/assets/stylesheets/rails_admin/custom/mixins.scss +0 -11
  102. data/app/assets/stylesheets/rails_admin/custom/theming.scss +0 -13
  103. data/app/assets/stylesheets/rails_admin/custom/variables.scss +0 -15
  104. data/lib/generators/rails_admin/importmap_formatter.rb +0 -29
  105. data/lib/generators/rails_admin/templates/rails_admin.vite.js +0 -2
  106. data/lib/generators/rails_admin/templates/rails_admin.webpacker.js +0 -2
  107. data/lib/rails_admin/adapters/active_record/object_extension.rb +0 -13
  108. data/lib/rails_admin/adapters/mongoid/object_extension.rb +0 -29
  109. data/lib/rails_admin/support/es_module_processor.rb +0 -23
  110. data/lib/rails_admin/support/serialization_schema.rb +0 -72
  111. data/vendor/assets/fonts/rails_admin/fa-solid-900.ttf +0 -0
  112. data/vendor/assets/javascripts/rails_admin/bootstrap.js +0 -5046
  113. data/vendor/assets/javascripts/rails_admin/flatpickr-with-locales.js +0 -11246
  114. data/vendor/assets/javascripts/rails_admin/jquery-ui/data.js +0 -41
  115. data/vendor/assets/javascripts/rails_admin/jquery-ui/effect.js +0 -1637
  116. data/vendor/assets/javascripts/rails_admin/jquery-ui/ie.js +0 -17
  117. data/vendor/assets/javascripts/rails_admin/jquery-ui/keycode.js +0 -47
  118. data/vendor/assets/javascripts/rails_admin/jquery-ui/position.js +0 -500
  119. data/vendor/assets/javascripts/rails_admin/jquery-ui/safe-active-element.js +0 -42
  120. data/vendor/assets/javascripts/rails_admin/jquery-ui/scroll-parent.js +0 -47
  121. data/vendor/assets/javascripts/rails_admin/jquery-ui/unique-id.js +0 -51
  122. data/vendor/assets/javascripts/rails_admin/jquery-ui/version.js +0 -17
  123. data/vendor/assets/javascripts/rails_admin/jquery-ui/widget.js +0 -735
  124. data/vendor/assets/javascripts/rails_admin/jquery-ui/widgets/autocomplete.js +0 -689
  125. data/vendor/assets/javascripts/rails_admin/jquery-ui/widgets/menu.js +0 -680
  126. data/vendor/assets/javascripts/rails_admin/jquery-ui/widgets/mouse.js +0 -230
  127. data/vendor/assets/javascripts/rails_admin/jquery-ui/widgets/sortable.js +0 -1561
  128. data/vendor/assets/javascripts/rails_admin/jquery3.js +0 -10881
  129. data/vendor/assets/javascripts/rails_admin/popper.js +0 -1974
  130. data/vendor/assets/stylesheets/rails_admin/bootstrap/_accordion.scss +0 -118
  131. data/vendor/assets/stylesheets/rails_admin/bootstrap/_alert.scss +0 -57
  132. data/vendor/assets/stylesheets/rails_admin/bootstrap/_badge.scss +0 -29
  133. data/vendor/assets/stylesheets/rails_admin/bootstrap/_breadcrumb.scss +0 -28
  134. data/vendor/assets/stylesheets/rails_admin/bootstrap/_button-group.scss +0 -139
  135. data/vendor/assets/stylesheets/rails_admin/bootstrap/_buttons.scss +0 -111
  136. data/vendor/assets/stylesheets/rails_admin/bootstrap/_card.scss +0 -216
  137. data/vendor/assets/stylesheets/rails_admin/bootstrap/_carousel.scss +0 -229
  138. data/vendor/assets/stylesheets/rails_admin/bootstrap/_close.scss +0 -40
  139. data/vendor/assets/stylesheets/rails_admin/bootstrap/_containers.scss +0 -41
  140. data/vendor/assets/stylesheets/rails_admin/bootstrap/_dropdown.scss +0 -240
  141. data/vendor/assets/stylesheets/rails_admin/bootstrap/_forms.scss +0 -9
  142. data/vendor/assets/stylesheets/rails_admin/bootstrap/_functions.scss +0 -302
  143. data/vendor/assets/stylesheets/rails_admin/bootstrap/_grid.scss +0 -33
  144. data/vendor/assets/stylesheets/rails_admin/bootstrap/_helpers.scss +0 -9
  145. data/vendor/assets/stylesheets/rails_admin/bootstrap/_images.scss +0 -42
  146. data/vendor/assets/stylesheets/rails_admin/bootstrap/_list-group.scss +0 -174
  147. data/vendor/assets/stylesheets/rails_admin/bootstrap/_mixins.scss +0 -43
  148. data/vendor/assets/stylesheets/rails_admin/bootstrap/_modal.scss +0 -209
  149. data/vendor/assets/stylesheets/rails_admin/bootstrap/_nav.scss +0 -139
  150. data/vendor/assets/stylesheets/rails_admin/bootstrap/_navbar.scss +0 -335
  151. data/vendor/assets/stylesheets/rails_admin/bootstrap/_offcanvas.scss +0 -83
  152. data/vendor/assets/stylesheets/rails_admin/bootstrap/_pagination.scss +0 -64
  153. data/vendor/assets/stylesheets/rails_admin/bootstrap/_placeholders.scss +0 -51
  154. data/vendor/assets/stylesheets/rails_admin/bootstrap/_popover.scss +0 -158
  155. data/vendor/assets/stylesheets/rails_admin/bootstrap/_progress.scss +0 -48
  156. data/vendor/assets/stylesheets/rails_admin/bootstrap/_reboot.scss +0 -625
  157. data/vendor/assets/stylesheets/rails_admin/bootstrap/_root.scss +0 -54
  158. data/vendor/assets/stylesheets/rails_admin/bootstrap/_spinners.scss +0 -69
  159. data/vendor/assets/stylesheets/rails_admin/bootstrap/_tables.scss +0 -155
  160. data/vendor/assets/stylesheets/rails_admin/bootstrap/_toasts.scss +0 -51
  161. data/vendor/assets/stylesheets/rails_admin/bootstrap/_tooltip.scss +0 -115
  162. data/vendor/assets/stylesheets/rails_admin/bootstrap/_transitions.scss +0 -27
  163. data/vendor/assets/stylesheets/rails_admin/bootstrap/_type.scss +0 -104
  164. data/vendor/assets/stylesheets/rails_admin/bootstrap/_utilities.scss +0 -630
  165. data/vendor/assets/stylesheets/rails_admin/bootstrap/_variables.scss +0 -1641
  166. data/vendor/assets/stylesheets/rails_admin/bootstrap/bootstrap.scss +0 -53
  167. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_floating-labels.scss +0 -63
  168. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-check.scss +0 -152
  169. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-control.scss +0 -219
  170. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-range.scss +0 -91
  171. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-select.scss +0 -72
  172. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-text.scss +0 -11
  173. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_input-group.scss +0 -121
  174. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_labels.scss +0 -36
  175. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_validation.scss +0 -12
  176. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_clearfix.scss +0 -3
  177. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_colored-links.scss +0 -12
  178. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_position.scss +0 -30
  179. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_ratio.scss +0 -26
  180. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_stacks.scss +0 -15
  181. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_stretched-link.scss +0 -15
  182. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_text-truncation.scss +0 -7
  183. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_visually-hidden.scss +0 -8
  184. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_vr.scss +0 -8
  185. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_alert.scss +0 -11
  186. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_backdrop.scss +0 -14
  187. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_border-radius.scss +0 -78
  188. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_box-shadow.scss +0 -18
  189. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_breakpoints.scss +0 -127
  190. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_buttons.scss +0 -133
  191. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_caret.scss +0 -64
  192. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_clearfix.scss +0 -9
  193. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_color-scheme.scss +0 -7
  194. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_container.scss +0 -9
  195. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_deprecate.scss +0 -10
  196. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_forms.scss +0 -144
  197. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_gradients.scss +0 -47
  198. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_grid.scss +0 -151
  199. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_image.scss +0 -16
  200. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_list-group.scss +0 -24
  201. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_lists.scss +0 -7
  202. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_pagination.scss +0 -31
  203. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_reset-text.scss +0 -17
  204. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_resize.scss +0 -6
  205. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_table-variants.scss +0 -21
  206. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_text-truncate.scss +0 -8
  207. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_transition.scss +0 -26
  208. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_utilities.scss +0 -89
  209. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_visually-hidden.scss +0 -29
  210. data/vendor/assets/stylesheets/rails_admin/bootstrap/utilities/_api.scss +0 -47
  211. data/vendor/assets/stylesheets/rails_admin/bootstrap/vendor/_rfs.scss +0 -354
  212. data/vendor/assets/stylesheets/rails_admin/flatpickr.css +0 -791
  213. data/vendor/assets/stylesheets/rails_admin/font-awesome.scss +0 -6351
@@ -1,689 +0,0 @@
1
- //= require rails_admin/jquery-ui/widgets/menu
2
- //= require rails_admin/jquery-ui/keycode
3
- //= require rails_admin/jquery-ui/position
4
- //= require rails_admin/jquery-ui/safe-active-element
5
- //= require rails_admin/jquery-ui/version
6
- //= require rails_admin/jquery-ui/widget
7
-
8
- /*!
9
- * jQuery UI Autocomplete 1.12.1
10
- * http://jqueryui.com
11
- *
12
- * Copyright jQuery Foundation and other contributors
13
- * Released under the MIT license.
14
- * http://jquery.org/license
15
- */
16
-
17
- //>>label: Autocomplete
18
- //>>group: Widgets
19
- //>>description: Lists suggested words as the user is typing.
20
- //>>docs: http://api.jqueryui.com/autocomplete/
21
- //>>demos: http://jqueryui.com/autocomplete/
22
- //>>css.structure: ../../themes/base/core.css
23
- //>>css.structure: ../../themes/base/autocomplete.css
24
- //>>css.theme: ../../themes/base/theme.css
25
-
26
- ( function( factory ) {
27
- if ( typeof define === "function" && define.amd ) {
28
-
29
- // AMD. Register as an anonymous module.
30
- define( [
31
- "jquery",
32
- "./menu",
33
- "../keycode",
34
- "../position",
35
- "../safe-active-element",
36
- "../version",
37
- "../widget"
38
- ], factory );
39
- } else {
40
-
41
- // Browser globals
42
- factory( jQuery );
43
- }
44
- }( function( $ ) {
45
-
46
- $.widget( "ui.autocomplete", {
47
- version: "1.12.1",
48
- defaultElement: "<input>",
49
- options: {
50
- appendTo: null,
51
- autoFocus: false,
52
- delay: 300,
53
- minLength: 1,
54
- position: {
55
- my: "left top",
56
- at: "left bottom",
57
- collision: "none"
58
- },
59
- source: null,
60
-
61
- // Callbacks
62
- change: null,
63
- close: null,
64
- focus: null,
65
- open: null,
66
- response: null,
67
- search: null,
68
- select: null
69
- },
70
-
71
- requestIndex: 0,
72
- pending: 0,
73
-
74
- _create: function() {
75
-
76
- // Some browsers only repeat keydown events, not keypress events,
77
- // so we use the suppressKeyPress flag to determine if we've already
78
- // handled the keydown event. #7269
79
- // Unfortunately the code for & in keypress is the same as the up arrow,
80
- // so we use the suppressKeyPressRepeat flag to avoid handling keypress
81
- // events when we know the keydown event was used to modify the
82
- // search term. #7799
83
- var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
84
- nodeName = this.element[ 0 ].nodeName.toLowerCase(),
85
- isTextarea = nodeName === "textarea",
86
- isInput = nodeName === "input";
87
-
88
- // Textareas are always multi-line
89
- // Inputs are always single-line, even if inside a contentEditable element
90
- // IE also treats inputs as contentEditable
91
- // All other element types are determined by whether or not they're contentEditable
92
- this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
93
-
94
- this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
95
- this.isNewMenu = true;
96
-
97
- this._addClass( "ui-autocomplete-input" );
98
- this.element.attr( "autocomplete", "off" );
99
-
100
- this._on( this.element, {
101
- keydown: function( event ) {
102
- if ( this.element.prop( "readOnly" ) ) {
103
- suppressKeyPress = true;
104
- suppressInput = true;
105
- suppressKeyPressRepeat = true;
106
- return;
107
- }
108
-
109
- suppressKeyPress = false;
110
- suppressInput = false;
111
- suppressKeyPressRepeat = false;
112
- var keyCode = $.ui.keyCode;
113
- switch ( event.keyCode ) {
114
- case keyCode.PAGE_UP:
115
- suppressKeyPress = true;
116
- this._move( "previousPage", event );
117
- break;
118
- case keyCode.PAGE_DOWN:
119
- suppressKeyPress = true;
120
- this._move( "nextPage", event );
121
- break;
122
- case keyCode.UP:
123
- suppressKeyPress = true;
124
- this._keyEvent( "previous", event );
125
- break;
126
- case keyCode.DOWN:
127
- suppressKeyPress = true;
128
- this._keyEvent( "next", event );
129
- break;
130
- case keyCode.ENTER:
131
-
132
- // when menu is open and has focus
133
- if ( this.menu.active ) {
134
-
135
- // #6055 - Opera still allows the keypress to occur
136
- // which causes forms to submit
137
- suppressKeyPress = true;
138
- event.preventDefault();
139
- this.menu.select( event );
140
- }
141
- break;
142
- case keyCode.TAB:
143
- if ( this.menu.active ) {
144
- this.menu.select( event );
145
- }
146
- break;
147
- case keyCode.ESCAPE:
148
- if ( this.menu.element.is( ":visible" ) ) {
149
- if ( !this.isMultiLine ) {
150
- this._value( this.term );
151
- }
152
- this.close( event );
153
-
154
- // Different browsers have different default behavior for escape
155
- // Single press can mean undo or clear
156
- // Double press in IE means clear the whole form
157
- event.preventDefault();
158
- }
159
- break;
160
- default:
161
- suppressKeyPressRepeat = true;
162
-
163
- // search timeout should be triggered before the input value is changed
164
- this._searchTimeout( event );
165
- break;
166
- }
167
- },
168
- keypress: function( event ) {
169
- if ( suppressKeyPress ) {
170
- suppressKeyPress = false;
171
- if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
172
- event.preventDefault();
173
- }
174
- return;
175
- }
176
- if ( suppressKeyPressRepeat ) {
177
- return;
178
- }
179
-
180
- // Replicate some key handlers to allow them to repeat in Firefox and Opera
181
- var keyCode = $.ui.keyCode;
182
- switch ( event.keyCode ) {
183
- case keyCode.PAGE_UP:
184
- this._move( "previousPage", event );
185
- break;
186
- case keyCode.PAGE_DOWN:
187
- this._move( "nextPage", event );
188
- break;
189
- case keyCode.UP:
190
- this._keyEvent( "previous", event );
191
- break;
192
- case keyCode.DOWN:
193
- this._keyEvent( "next", event );
194
- break;
195
- }
196
- },
197
- input: function( event ) {
198
- if ( suppressInput ) {
199
- suppressInput = false;
200
- event.preventDefault();
201
- return;
202
- }
203
- this._searchTimeout( event );
204
- },
205
- focus: function() {
206
- this.selectedItem = null;
207
- this.previous = this._value();
208
- },
209
- blur: function( event ) {
210
- if ( this.cancelBlur ) {
211
- delete this.cancelBlur;
212
- return;
213
- }
214
-
215
- clearTimeout( this.searching );
216
- this.close( event );
217
- this._change( event );
218
- }
219
- } );
220
-
221
- this._initSource();
222
- this.menu = $( "<ul>" )
223
- .appendTo( this._appendTo() )
224
- .menu( {
225
-
226
- // disable ARIA support, the live region takes care of that
227
- role: null
228
- } )
229
- .hide()
230
- .menu( "instance" );
231
-
232
- this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
233
- this._on( this.menu.element, {
234
- mousedown: function( event ) {
235
-
236
- // prevent moving focus out of the text field
237
- event.preventDefault();
238
-
239
- // IE doesn't prevent moving focus even with event.preventDefault()
240
- // so we set a flag to know when we should ignore the blur event
241
- this.cancelBlur = true;
242
- this._delay( function() {
243
- delete this.cancelBlur;
244
-
245
- // Support: IE 8 only
246
- // Right clicking a menu item or selecting text from the menu items will
247
- // result in focus moving out of the input. However, we've already received
248
- // and ignored the blur event because of the cancelBlur flag set above. So
249
- // we restore focus to ensure that the menu closes properly based on the user's
250
- // next actions.
251
- if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
252
- this.element.trigger( "focus" );
253
- }
254
- } );
255
- },
256
- menufocus: function( event, ui ) {
257
- var label, item;
258
-
259
- // support: Firefox
260
- // Prevent accidental activation of menu items in Firefox (#7024 #9118)
261
- if ( this.isNewMenu ) {
262
- this.isNewMenu = false;
263
- if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
264
- this.menu.blur();
265
-
266
- this.document.one( "mousemove", function() {
267
- $( event.target ).trigger( event.originalEvent );
268
- } );
269
-
270
- return;
271
- }
272
- }
273
-
274
- item = ui.item.data( "ui-autocomplete-item" );
275
- if ( false !== this._trigger( "focus", event, { item: item } ) ) {
276
-
277
- // use value to match what will end up in the input, if it was a key event
278
- if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
279
- this._value( item.value );
280
- }
281
- }
282
-
283
- // Announce the value in the liveRegion
284
- label = ui.item.attr( "aria-label" ) || item.value;
285
- if ( label && $.trim( label ).length ) {
286
- this.liveRegion.children().hide();
287
- $( "<div>" ).text( label ).appendTo( this.liveRegion );
288
- }
289
- },
290
- menuselect: function( event, ui ) {
291
- var item = ui.item.data( "ui-autocomplete-item" ),
292
- previous = this.previous;
293
-
294
- // Only trigger when focus was lost (click on menu)
295
- if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
296
- this.element.trigger( "focus" );
297
- this.previous = previous;
298
-
299
- // #6109 - IE triggers two focus events and the second
300
- // is asynchronous, so we need to reset the previous
301
- // term synchronously and asynchronously :-(
302
- this._delay( function() {
303
- this.previous = previous;
304
- this.selectedItem = item;
305
- } );
306
- }
307
-
308
- if ( false !== this._trigger( "select", event, { item: item } ) ) {
309
- this._value( item.value );
310
- }
311
-
312
- // reset the term after the select event
313
- // this allows custom select handling to work properly
314
- this.term = this._value();
315
-
316
- this.close( event );
317
- this.selectedItem = item;
318
- }
319
- } );
320
-
321
- this.liveRegion = $( "<div>", {
322
- role: "status",
323
- "aria-live": "assertive",
324
- "aria-relevant": "additions"
325
- } )
326
- .appendTo( this.document[ 0 ].body );
327
-
328
- this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
329
-
330
- // Turning off autocomplete prevents the browser from remembering the
331
- // value when navigating through history, so we re-enable autocomplete
332
- // if the page is unloaded before the widget is destroyed. #7790
333
- this._on( this.window, {
334
- beforeunload: function() {
335
- this.element.removeAttr( "autocomplete" );
336
- }
337
- } );
338
- },
339
-
340
- _destroy: function() {
341
- clearTimeout( this.searching );
342
- this.element.removeAttr( "autocomplete" );
343
- this.menu.element.remove();
344
- this.liveRegion.remove();
345
- },
346
-
347
- _setOption: function( key, value ) {
348
- this._super( key, value );
349
- if ( key === "source" ) {
350
- this._initSource();
351
- }
352
- if ( key === "appendTo" ) {
353
- this.menu.element.appendTo( this._appendTo() );
354
- }
355
- if ( key === "disabled" && value && this.xhr ) {
356
- this.xhr.abort();
357
- }
358
- },
359
-
360
- _isEventTargetInWidget: function( event ) {
361
- var menuElement = this.menu.element[ 0 ];
362
-
363
- return event.target === this.element[ 0 ] ||
364
- event.target === menuElement ||
365
- $.contains( menuElement, event.target );
366
- },
367
-
368
- _closeOnClickOutside: function( event ) {
369
- if ( !this._isEventTargetInWidget( event ) ) {
370
- this.close();
371
- }
372
- },
373
-
374
- _appendTo: function() {
375
- var element = this.options.appendTo;
376
-
377
- if ( element ) {
378
- element = element.jquery || element.nodeType ?
379
- $( element ) :
380
- this.document.find( element ).eq( 0 );
381
- }
382
-
383
- if ( !element || !element[ 0 ] ) {
384
- element = this.element.closest( ".ui-front, dialog" );
385
- }
386
-
387
- if ( !element.length ) {
388
- element = this.document[ 0 ].body;
389
- }
390
-
391
- return element;
392
- },
393
-
394
- _initSource: function() {
395
- var array, url,
396
- that = this;
397
- if ( $.isArray( this.options.source ) ) {
398
- array = this.options.source;
399
- this.source = function( request, response ) {
400
- response( $.ui.autocomplete.filter( array, request.term ) );
401
- };
402
- } else if ( typeof this.options.source === "string" ) {
403
- url = this.options.source;
404
- this.source = function( request, response ) {
405
- if ( that.xhr ) {
406
- that.xhr.abort();
407
- }
408
- that.xhr = $.ajax( {
409
- url: url,
410
- data: request,
411
- dataType: "json",
412
- success: function( data ) {
413
- response( data );
414
- },
415
- error: function() {
416
- response( [] );
417
- }
418
- } );
419
- };
420
- } else {
421
- this.source = this.options.source;
422
- }
423
- },
424
-
425
- _searchTimeout: function( event ) {
426
- clearTimeout( this.searching );
427
- this.searching = this._delay( function() {
428
-
429
- // Search if the value has changed, or if the user retypes the same value (see #7434)
430
- var equalValues = this.term === this._value(),
431
- menuVisible = this.menu.element.is( ":visible" ),
432
- modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
433
-
434
- if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
435
- this.selectedItem = null;
436
- this.search( null, event );
437
- }
438
- }, this.options.delay );
439
- },
440
-
441
- search: function( value, event ) {
442
- value = value != null ? value : this._value();
443
-
444
- // Always save the actual value, not the one passed as an argument
445
- this.term = this._value();
446
-
447
- if ( value.length < this.options.minLength ) {
448
- return this.close( event );
449
- }
450
-
451
- if ( this._trigger( "search", event ) === false ) {
452
- return;
453
- }
454
-
455
- return this._search( value );
456
- },
457
-
458
- _search: function( value ) {
459
- this.pending++;
460
- this._addClass( "ui-autocomplete-loading" );
461
- this.cancelSearch = false;
462
-
463
- this.source( { term: value }, this._response() );
464
- },
465
-
466
- _response: function() {
467
- var index = ++this.requestIndex;
468
-
469
- return $.proxy( function( content ) {
470
- if ( index === this.requestIndex ) {
471
- this.__response( content );
472
- }
473
-
474
- this.pending--;
475
- if ( !this.pending ) {
476
- this._removeClass( "ui-autocomplete-loading" );
477
- }
478
- }, this );
479
- },
480
-
481
- __response: function( content ) {
482
- if ( content ) {
483
- content = this._normalize( content );
484
- }
485
- this._trigger( "response", null, { content: content } );
486
- if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
487
- this._suggest( content );
488
- this._trigger( "open" );
489
- } else {
490
-
491
- // use ._close() instead of .close() so we don't cancel future searches
492
- this._close();
493
- }
494
- },
495
-
496
- close: function( event ) {
497
- this.cancelSearch = true;
498
- this._close( event );
499
- },
500
-
501
- _close: function( event ) {
502
-
503
- // Remove the handler that closes the menu on outside clicks
504
- this._off( this.document, "mousedown" );
505
-
506
- if ( this.menu.element.is( ":visible" ) ) {
507
- this.menu.element.hide();
508
- this.menu.blur();
509
- this.isNewMenu = true;
510
- this._trigger( "close", event );
511
- }
512
- },
513
-
514
- _change: function( event ) {
515
- if ( this.previous !== this._value() ) {
516
- this._trigger( "change", event, { item: this.selectedItem } );
517
- }
518
- },
519
-
520
- _normalize: function( items ) {
521
-
522
- // assume all items have the right format when the first item is complete
523
- if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
524
- return items;
525
- }
526
- return $.map( items, function( item ) {
527
- if ( typeof item === "string" ) {
528
- return {
529
- label: item,
530
- value: item
531
- };
532
- }
533
- return $.extend( {}, item, {
534
- label: item.label || item.value,
535
- value: item.value || item.label
536
- } );
537
- } );
538
- },
539
-
540
- _suggest: function( items ) {
541
- var ul = this.menu.element.empty();
542
- this._renderMenu( ul, items );
543
- this.isNewMenu = true;
544
- this.menu.refresh();
545
-
546
- // Size and position menu
547
- ul.show();
548
- this._resizeMenu();
549
- ul.position( $.extend( {
550
- of: this.element
551
- }, this.options.position ) );
552
-
553
- if ( this.options.autoFocus ) {
554
- this.menu.next();
555
- }
556
-
557
- // Listen for interactions outside of the widget (#6642)
558
- this._on( this.document, {
559
- mousedown: "_closeOnClickOutside"
560
- } );
561
- },
562
-
563
- _resizeMenu: function() {
564
- var ul = this.menu.element;
565
- ul.outerWidth( Math.max(
566
-
567
- // Firefox wraps long text (possibly a rounding bug)
568
- // so we add 1px to avoid the wrapping (#7513)
569
- ul.width( "" ).outerWidth() + 1,
570
- this.element.outerWidth()
571
- ) );
572
- },
573
-
574
- _renderMenu: function( ul, items ) {
575
- var that = this;
576
- $.each( items, function( index, item ) {
577
- that._renderItemData( ul, item );
578
- } );
579
- },
580
-
581
- _renderItemData: function( ul, item ) {
582
- return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
583
- },
584
-
585
- _renderItem: function( ul, item ) {
586
- return $( "<li>" )
587
- .append( $( "<div>" ).text( item.label ) )
588
- .appendTo( ul );
589
- },
590
-
591
- _move: function( direction, event ) {
592
- if ( !this.menu.element.is( ":visible" ) ) {
593
- this.search( null, event );
594
- return;
595
- }
596
- if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
597
- this.menu.isLastItem() && /^next/.test( direction ) ) {
598
-
599
- if ( !this.isMultiLine ) {
600
- this._value( this.term );
601
- }
602
-
603
- this.menu.blur();
604
- return;
605
- }
606
- this.menu[ direction ]( event );
607
- },
608
-
609
- widget: function() {
610
- return this.menu.element;
611
- },
612
-
613
- _value: function() {
614
- return this.valueMethod.apply( this.element, arguments );
615
- },
616
-
617
- _keyEvent: function( keyEvent, event ) {
618
- if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
619
- this._move( keyEvent, event );
620
-
621
- // Prevents moving cursor to beginning/end of the text field in some browsers
622
- event.preventDefault();
623
- }
624
- },
625
-
626
- // Support: Chrome <=50
627
- // We should be able to just use this.element.prop( "isContentEditable" )
628
- // but hidden elements always report false in Chrome.
629
- // https://code.google.com/p/chromium/issues/detail?id=313082
630
- _isContentEditable: function( element ) {
631
- if ( !element.length ) {
632
- return false;
633
- }
634
-
635
- var editable = element.prop( "contentEditable" );
636
-
637
- if ( editable === "inherit" ) {
638
- return this._isContentEditable( element.parent() );
639
- }
640
-
641
- return editable === "true";
642
- }
643
- } );
644
-
645
- $.extend( $.ui.autocomplete, {
646
- escapeRegex: function( value ) {
647
- return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
648
- },
649
- filter: function( array, term ) {
650
- var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
651
- return $.grep( array, function( value ) {
652
- return matcher.test( value.label || value.value || value );
653
- } );
654
- }
655
- } );
656
-
657
- // Live region extension, adding a `messages` option
658
- // NOTE: This is an experimental API. We are still investigating
659
- // a full solution for string manipulation and internationalization.
660
- $.widget( "ui.autocomplete", $.ui.autocomplete, {
661
- options: {
662
- messages: {
663
- noResults: "No search results.",
664
- results: function( amount ) {
665
- return amount + ( amount > 1 ? " results are" : " result is" ) +
666
- " available, use up and down arrow keys to navigate.";
667
- }
668
- }
669
- },
670
-
671
- __response: function( content ) {
672
- var message;
673
- this._superApply( arguments );
674
- if ( this.options.disabled || this.cancelSearch ) {
675
- return;
676
- }
677
- if ( content && content.length ) {
678
- message = this.options.messages.results( content.length );
679
- } else {
680
- message = this.options.messages.noResults;
681
- }
682
- this.liveRegion.children().hide();
683
- $( "<div>" ).text( message ).appendTo( this.liveRegion );
684
- }
685
- } );
686
-
687
- return $.ui.autocomplete;
688
-
689
- } ) );