ext_form 0.1.4

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 (333) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +31 -0
  4. data/app/assets/javascripts/ext_form/application.js +78 -0
  5. data/app/assets/javascripts/typeahead.js +1159 -0
  6. data/app/assets/stylesheets/ext_form/application.scss +15 -0
  7. data/app/assets/stylesheets/ext_form/application_bootstrap.css.scss +197 -0
  8. data/app/assets/stylesheets/ext_form/base.css.scss +32 -0
  9. data/config/routes.rb +2 -0
  10. data/lib/ext_form/builders/form_builder_base.rb +224 -0
  11. data/lib/ext_form/builders.rb +10 -0
  12. data/lib/ext_form/components/input_addons.rb +34 -0
  13. data/lib/ext_form/components.rb +7 -0
  14. data/lib/ext_form/engine.rb +14 -0
  15. data/lib/ext_form/helpers/form_helper.rb +222 -0
  16. data/lib/ext_form/helpers/form_tag_helper.rb +60 -0
  17. data/lib/ext_form/helpers/tags/auto_complete.rb +25 -0
  18. data/lib/ext_form/helpers/tags/collection_select.rb +19 -0
  19. data/lib/ext_form/helpers/tags/dt_picker.rb +27 -0
  20. data/lib/ext_form/helpers/tags/grouped_collection_select.rb +19 -0
  21. data/lib/ext_form/helpers/tags.rb +12 -0
  22. data/lib/ext_form/inputs/auto_complete.rb +11 -0
  23. data/lib/ext_form/inputs/base_mixin.rb +11 -0
  24. data/lib/ext_form/inputs/bootstrap_inputs_mixin.rb +13 -0
  25. data/lib/ext_form/inputs/collection_select.rb +15 -0
  26. data/lib/ext_form/inputs/dt_picker.rb +20 -0
  27. data/lib/ext_form/inputs/grouped_collection_select.rb +13 -0
  28. data/lib/ext_form/inputs.rb +15 -0
  29. data/lib/ext_form/layouts/base_layout.rb +82 -0
  30. data/lib/ext_form/layouts/bootstrap_layout.rb +23 -0
  31. data/lib/ext_form/layouts/default_layout.rb +29 -0
  32. data/lib/ext_form/layouts.rb +11 -0
  33. data/lib/ext_form/version.rb +3 -0
  34. data/lib/ext_form/wrappers/many_mixin.rb +18 -0
  35. data/lib/ext_form/wrappers/mixin.rb +49 -0
  36. data/lib/ext_form/wrappers/single_mixin.rb +18 -0
  37. data/lib/ext_form/wrappers.rb +11 -0
  38. data/lib/ext_form.rb +52 -0
  39. data/lib/generators/ext_form/USAGE +3 -0
  40. data/lib/generators/ext_form/install_generator.rb +113 -0
  41. data/lib/generators/ext_form/templates/README +15 -0
  42. data/lib/generators/ext_form/templates/_form.html.erb +12 -0
  43. data/lib/generators/ext_form/templates/_form.html.haml +12 -0
  44. data/lib/generators/ext_form/templates/_form.html.slim +12 -0
  45. data/lib/generators/ext_form/templates/config/initializers/z_ext_form.rb +70 -0
  46. data/lib/generators/ext_form/templates/config/initializers/z_ext_form_bootstrap.rb +59 -0
  47. data/lib/generators/ext_form/templates/config/locales/ext_form.en.yml +2 -0
  48. data/lib/tasks/ext_form_tasks.rake +4 -0
  49. data/spec/builders/ext_form_builder_bs_spec.rb +78 -0
  50. data/spec/builders/ext_form_builder_spec.rb +100 -0
  51. data/spec/dummy/README.rdoc +28 -0
  52. data/spec/dummy/Rakefile +6 -0
  53. data/spec/dummy/app/assets/javascripts/application.js +27 -0
  54. data/spec/dummy/app/assets/javascripts/order_headers.js +2 -0
  55. data/spec/dummy/app/assets/javascripts/order_lines.js +2 -0
  56. data/spec/dummy/app/assets/javascripts/shipments.js +2 -0
  57. data/spec/dummy/app/assets/stylesheets/application.css.scss +17 -0
  58. data/spec/dummy/app/assets/stylesheets/order_headers.css +4 -0
  59. data/spec/dummy/app/assets/stylesheets/order_lines.css +4 -0
  60. data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
  61. data/spec/dummy/app/assets/stylesheets/shipments.css +4 -0
  62. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  63. data/spec/dummy/app/controllers/order_headers_controller.rb +62 -0
  64. data/spec/dummy/app/controllers/order_lines_controller.rb +58 -0
  65. data/spec/dummy/app/controllers/shipments_controller.rb +58 -0
  66. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  67. data/spec/dummy/app/helpers/order_headers_helper.rb +2 -0
  68. data/spec/dummy/app/helpers/order_lines_helper.rb +2 -0
  69. data/spec/dummy/app/helpers/shipments_helper.rb +2 -0
  70. data/spec/dummy/app/models/order_header.rb +9 -0
  71. data/spec/dummy/app/models/order_line.rb +6 -0
  72. data/spec/dummy/app/models/order_type.rb +2 -0
  73. data/spec/dummy/app/models/shipment.rb +3 -0
  74. data/spec/dummy/app/views/layouts/application.html.erb +17 -0
  75. data/spec/dummy/app/views/order_headers/_form.html.erb +53 -0
  76. data/spec/dummy/app/views/order_headers/edit.html.erb +3 -0
  77. data/spec/dummy/app/views/order_headers/index.html.erb +29 -0
  78. data/spec/dummy/app/views/order_headers/new.html.erb +5 -0
  79. data/spec/dummy/app/views/order_headers/show.html.erb +14 -0
  80. data/spec/dummy/app/views/order_lines/_form.html.erb +33 -0
  81. data/spec/dummy/app/views/order_lines/edit.html.erb +6 -0
  82. data/spec/dummy/app/views/order_lines/index.html.erb +33 -0
  83. data/spec/dummy/app/views/order_lines/new.html.erb +5 -0
  84. data/spec/dummy/app/views/order_lines/show.html.erb +24 -0
  85. data/spec/dummy/app/views/shipments/_form.html.erb +37 -0
  86. data/spec/dummy/app/views/shipments/edit.html.erb +6 -0
  87. data/spec/dummy/app/views/shipments/index.html.erb +35 -0
  88. data/spec/dummy/app/views/shipments/new.html.erb +5 -0
  89. data/spec/dummy/app/views/shipments/show.html.erb +29 -0
  90. data/spec/dummy/bin/bundle +3 -0
  91. data/spec/dummy/bin/rails +4 -0
  92. data/spec/dummy/bin/rake +4 -0
  93. data/spec/dummy/config/application.rb +28 -0
  94. data/spec/dummy/config/boot.rb +5 -0
  95. data/spec/dummy/config/database.yml +25 -0
  96. data/spec/dummy/config/environment.rb +5 -0
  97. data/spec/dummy/config/environments/development.rb +29 -0
  98. data/spec/dummy/config/environments/production.rb +80 -0
  99. data/spec/dummy/config/environments/test.rb +36 -0
  100. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  101. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  102. data/spec/dummy/config/initializers/inflections.rb +16 -0
  103. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  104. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  105. data/spec/dummy/config/initializers/session_store.rb +3 -0
  106. data/spec/dummy/config/initializers/simple_form.rb +145 -0
  107. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  108. data/spec/dummy/config/initializers/z_ext_form.rb +70 -0
  109. data/spec/dummy/config/initializers/z_ext_form_bootstrap.rb +59 -0
  110. data/spec/dummy/config/locales/en.yml +23 -0
  111. data/spec/dummy/config/locales/ext_form.en.yml +26 -0
  112. data/spec/dummy/config/locales/simple_form.en.yml +26 -0
  113. data/spec/dummy/config/routes.rb +10 -0
  114. data/spec/dummy/config.ru +4 -0
  115. data/spec/dummy/db/development.sqlite3 +0 -0
  116. data/spec/dummy/db/migrate/20130822091938_create_order_headers.rb +10 -0
  117. data/spec/dummy/db/migrate/20130822092035_create_order_lines.rb +12 -0
  118. data/spec/dummy/db/migrate/20130822092136_create_shipments.rb +13 -0
  119. data/spec/dummy/db/migrate/20130913025429_add_order_date_to_order_headers.rb +5 -0
  120. data/spec/dummy/db/migrate/20130913082503_add_bill_to_customer_to_order_headers.rb +7 -0
  121. data/spec/dummy/db/migrate/20130914101200_create_order_types.rb +9 -0
  122. data/spec/dummy/db/migrate/20130914101232_add_order_type_id_to_order_headers.rb +5 -0
  123. data/spec/dummy/db/schema.rb +64 -0
  124. data/spec/dummy/db/seeds.rb +3 -0
  125. data/spec/dummy/db/test.sqlite3 +0 -0
  126. data/spec/dummy/lib/templates/erb/scaffold/_form.html.erb +12 -0
  127. data/spec/dummy/lib/templates/slim/scaffold/_form.html.slim +12 -0
  128. data/spec/dummy/log/development.log +30851 -0
  129. data/spec/dummy/log/test.log +8888 -0
  130. data/spec/dummy/public/404.html +58 -0
  131. data/spec/dummy/public/422.html +58 -0
  132. data/spec/dummy/public/500.html +57 -0
  133. data/spec/dummy/public/favicon.ico +0 -0
  134. data/spec/dummy/public/javascripts/nested_form.js +120 -0
  135. data/spec/dummy/spec/factories/order_types.rb +7 -0
  136. data/spec/dummy/tmp/cache/assets/development/sass/0be6a8d566db001f251fcb3d330b625bdcde50b0/select2.css.scssc +0 -0
  137. data/spec/dummy/tmp/cache/assets/development/sass/0f754ef2ba2bade74c446fd0dc8d2c538b2ee4ba/bootstrap-datetimepicker.cssc +0 -0
  138. data/spec/dummy/tmp/cache/assets/development/sass/43e39f3776203b555edf4427cbeca13a3e80bf4e/application.scssc +0 -0
  139. data/spec/dummy/tmp/cache/assets/development/sass/43e39f3776203b555edf4427cbeca13a3e80bf4e/application_bootstrap.css.scssc +0 -0
  140. data/spec/dummy/tmp/cache/assets/development/sass/43e39f3776203b555edf4427cbeca13a3e80bf4e/base.css.scssc +0 -0
  141. data/spec/dummy/tmp/cache/assets/development/sass/95877ca3fb97306427e6a8c3200a77fa726c2979/bootstrap-responsive.scssc +0 -0
  142. data/spec/dummy/tmp/cache/assets/development/sass/95877ca3fb97306427e6a8c3200a77fa726c2979/bootstrap.scssc +0 -0
  143. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_accordion.scssc +0 -0
  144. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_alerts.scssc +0 -0
  145. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_breadcrumbs.scssc +0 -0
  146. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_button-groups.scssc +0 -0
  147. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_buttons.scssc +0 -0
  148. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_carousel.scssc +0 -0
  149. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_close.scssc +0 -0
  150. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_code.scssc +0 -0
  151. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_component-animations.scssc +0 -0
  152. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_dropdowns.scssc +0 -0
  153. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_forms.scssc +0 -0
  154. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_grid.scssc +0 -0
  155. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_hero-unit.scssc +0 -0
  156. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_labels-badges.scssc +0 -0
  157. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_layouts.scssc +0 -0
  158. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_media.scssc +0 -0
  159. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_mixins.scssc +0 -0
  160. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_modals.scssc +0 -0
  161. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_navbar.scssc +0 -0
  162. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_navs.scssc +0 -0
  163. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_pager.scssc +0 -0
  164. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_pagination.scssc +0 -0
  165. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_popovers.scssc +0 -0
  166. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_progress-bars.scssc +0 -0
  167. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_reset.scssc +0 -0
  168. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_responsive-1200px-min.scssc +0 -0
  169. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_responsive-767px-max.scssc +0 -0
  170. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_responsive-768px-979px.scssc +0 -0
  171. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_responsive-navbar.scssc +0 -0
  172. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_responsive-utilities.scssc +0 -0
  173. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_scaffolding.scssc +0 -0
  174. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_sprites.scssc +0 -0
  175. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_tables.scssc +0 -0
  176. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_thumbnails.scssc +0 -0
  177. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_tooltip.scssc +0 -0
  178. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_type.scssc +0 -0
  179. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_utilities.scssc +0 -0
  180. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_variables.scssc +0 -0
  181. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/_wells.scssc +0 -0
  182. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/bootstrap.scssc +0 -0
  183. data/spec/dummy/tmp/cache/assets/development/sass/c75ed21fe4fe5a931216dc17f876dea4e6c936a7/responsive.scssc +0 -0
  184. data/spec/dummy/tmp/cache/assets/development/sass/d8cdc3e1698ff449e2e9ab35ca24a00a8d724935/application.css.scssc +0 -0
  185. data/spec/dummy/tmp/cache/assets/development/sass/d8cdc3e1698ff449e2e9ab35ca24a00a8d724935/scaffolds.css.scssc +0 -0
  186. data/spec/dummy/tmp/cache/assets/development/sass/d8cdc3e1698ff449e2e9ab35ca24a00a8d724935/test_scaflds.css.scssc +0 -0
  187. data/spec/dummy/tmp/cache/assets/development/sprockets/00171108bd75279e653c1ffb5b4650b8 +0 -0
  188. data/spec/dummy/tmp/cache/assets/development/sprockets/05029f2e1c68338ac88af8005acab3ca +0 -0
  189. data/spec/dummy/tmp/cache/assets/development/sprockets/08318fdb5f5b783c22442a6aeb73730e +0 -0
  190. data/spec/dummy/tmp/cache/assets/development/sprockets/08f00d4a1bac197d382c2269a184f9e4 +0 -0
  191. data/spec/dummy/tmp/cache/assets/development/sprockets/0b6c06f6bcf535567c19f70f7aa5144d +0 -0
  192. data/spec/dummy/tmp/cache/assets/development/sprockets/0b9076b70e22dd7976e589018cdf65ca +0 -0
  193. data/spec/dummy/tmp/cache/assets/development/sprockets/0e8461b429e0249b8dc74d457fcc17d3 +0 -0
  194. data/spec/dummy/tmp/cache/assets/development/sprockets/0f074c0ea10680a3ba979bbd1d2ff756 +0 -0
  195. data/spec/dummy/tmp/cache/assets/development/sprockets/0f5877c1fb159c1a5f1602569a0cdde2 +0 -0
  196. data/spec/dummy/tmp/cache/assets/development/sprockets/0f8cf3c40768cf2ab52c613a7efc30cb +0 -0
  197. data/spec/dummy/tmp/cache/assets/development/sprockets/10fcfbe6ebae11a40c8eac41939a1b9a +0 -0
  198. data/spec/dummy/tmp/cache/assets/development/sprockets/126ebaa8ad57e48772c035caac2ed632 +0 -0
  199. data/spec/dummy/tmp/cache/assets/development/sprockets/13c6f1c4603d5736407a6b5f7889a056 +0 -0
  200. data/spec/dummy/tmp/cache/assets/development/sprockets/13f8355b45d7c46c05177fef3b7f6283 +0 -0
  201. data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  202. data/spec/dummy/tmp/cache/assets/development/sprockets/157d2eedb817dece09700185cd4101e3 +0 -0
  203. data/spec/dummy/tmp/cache/assets/development/sprockets/16039dc737e753516f4399dcd38d6de7 +0 -0
  204. data/spec/dummy/tmp/cache/assets/development/sprockets/19699f0bd9bbacb926aa665d057d7dcc +0 -0
  205. data/spec/dummy/tmp/cache/assets/development/sprockets/2013f24e3245656ca1e5890649a0b023 +0 -0
  206. data/spec/dummy/tmp/cache/assets/development/sprockets/26bd44751cc9640593dc583d6be8410d +0 -0
  207. data/spec/dummy/tmp/cache/assets/development/sprockets/272f5096d49f011351e9f4780c313741 +0 -0
  208. data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  209. data/spec/dummy/tmp/cache/assets/development/sprockets/32ef1c9e94a83350bad5e887c416c5b6 +0 -0
  210. data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  211. data/spec/dummy/tmp/cache/assets/development/sprockets/367865b241c60ef0e9a85c9f9910f7d4 +0 -0
  212. data/spec/dummy/tmp/cache/assets/development/sprockets/371bf96e99717688ed7313a0c53f4212 +0 -0
  213. data/spec/dummy/tmp/cache/assets/development/sprockets/37984c7de5e7d22002a378234035e51c +0 -0
  214. data/spec/dummy/tmp/cache/assets/development/sprockets/4201264f7710f91dc1c389a2497eda7d +0 -0
  215. data/spec/dummy/tmp/cache/assets/development/sprockets/4843087e4f4577291013564353d9be98 +0 -0
  216. data/spec/dummy/tmp/cache/assets/development/sprockets/490b125495df24b66caa52d70f8aa64d +0 -0
  217. data/spec/dummy/tmp/cache/assets/development/sprockets/4c9470e682578ab5fc183f98fae5f42d +0 -0
  218. data/spec/dummy/tmp/cache/assets/development/sprockets/4e81b6b6eb1e1462b1eea2caee6bfcc6 +0 -0
  219. data/spec/dummy/tmp/cache/assets/development/sprockets/510da110ae528e2d22533be39ff696c5 +0 -0
  220. data/spec/dummy/tmp/cache/assets/development/sprockets/518c73ecd762cbf6d85a3ae693e08d01 +0 -0
  221. data/spec/dummy/tmp/cache/assets/development/sprockets/56401bbafd08927b55572c8ef7e88883 +0 -0
  222. data/spec/dummy/tmp/cache/assets/development/sprockets/5865993e4fa54b7f6f0186ebaffff12b +0 -0
  223. data/spec/dummy/tmp/cache/assets/development/sprockets/59f25755df49e4db5915553e3d2ef412 +0 -0
  224. data/spec/dummy/tmp/cache/assets/development/sprockets/5a48dae6fe5b78da3082b1347022ee01 +0 -0
  225. data/spec/dummy/tmp/cache/assets/development/sprockets/5f62321f43b55988b6cb95367556d822 +0 -0
  226. data/spec/dummy/tmp/cache/assets/development/sprockets/61fab520b090f94084c9a7ffc402ad3c +0 -0
  227. data/spec/dummy/tmp/cache/assets/development/sprockets/653178c2e0c5d134069e58196f7bf28e +0 -0
  228. data/spec/dummy/tmp/cache/assets/development/sprockets/661c74f15a009d482fdad85f811e6f8e +0 -0
  229. data/spec/dummy/tmp/cache/assets/development/sprockets/6668d3ee30c1513097c95bcc0a27696a +0 -0
  230. data/spec/dummy/tmp/cache/assets/development/sprockets/690b40f9a765547b660ac81cbd5ed378 +0 -0
  231. data/spec/dummy/tmp/cache/assets/development/sprockets/6bdff36d9dbeb7ae3e6802b482a04668 +0 -0
  232. data/spec/dummy/tmp/cache/assets/development/sprockets/6eaa97256ef2d58208ab91c60707acdb +0 -0
  233. data/spec/dummy/tmp/cache/assets/development/sprockets/6fa120c855c745c904828746e82b2b07 +0 -0
  234. data/spec/dummy/tmp/cache/assets/development/sprockets/6fc757c2c8329244ca95d6909865bbc2 +0 -0
  235. data/spec/dummy/tmp/cache/assets/development/sprockets/715840f8887bc1e70ef3cc18b429cbc8 +0 -0
  236. data/spec/dummy/tmp/cache/assets/development/sprockets/754b02ea2ed1c85b7756de6452f4aeb7 +0 -0
  237. data/spec/dummy/tmp/cache/assets/development/sprockets/764fdaef2f219fafc8db0923a56c23a3 +0 -0
  238. data/spec/dummy/tmp/cache/assets/development/sprockets/78fdc1d9add39ed3fdcbf7cae3df4190 +0 -0
  239. data/spec/dummy/tmp/cache/assets/development/sprockets/7a7280187e89f6c4256217ea0fe1e787 +0 -0
  240. data/spec/dummy/tmp/cache/assets/development/sprockets/7b2d3e5e25b0901f78fbf8c9cb9570c4 +0 -0
  241. data/spec/dummy/tmp/cache/assets/development/sprockets/84eb79ed8e43cf9414e6ecfd38c5a19f +0 -0
  242. data/spec/dummy/tmp/cache/assets/development/sprockets/87172f2d7a412d1fe87d7775d589b883 +0 -0
  243. data/spec/dummy/tmp/cache/assets/development/sprockets/871fe15e38e1cf354ac33b4faf796fd3 +0 -0
  244. data/spec/dummy/tmp/cache/assets/development/sprockets/875849c72f053c7a7674e9fd72ee2cd4 +0 -0
  245. data/spec/dummy/tmp/cache/assets/development/sprockets/87a55c890eedab0cc5d1e3f2c2b2da4b +0 -0
  246. data/spec/dummy/tmp/cache/assets/development/sprockets/88741eb863751c5d5adb82282f6df5cd +0 -0
  247. data/spec/dummy/tmp/cache/assets/development/sprockets/8ab512c9b33ac90e699b73469d71f061 +0 -0
  248. data/spec/dummy/tmp/cache/assets/development/sprockets/8cc360b254f1bff91753f954e7591a9b +0 -0
  249. data/spec/dummy/tmp/cache/assets/development/sprockets/8ec990d84f5dedd35001397078415137 +0 -0
  250. data/spec/dummy/tmp/cache/assets/development/sprockets/9181401ef96921b28b49d4ec48261a4d +0 -0
  251. data/spec/dummy/tmp/cache/assets/development/sprockets/9409af55392b7f03edb441d5b53b931c +0 -0
  252. data/spec/dummy/tmp/cache/assets/development/sprockets/94e46c0e76c8f392586af76b0f6c6e93 +0 -0
  253. data/spec/dummy/tmp/cache/assets/development/sprockets/968566581a35be861fa4f8fed757dcae +0 -0
  254. data/spec/dummy/tmp/cache/assets/development/sprockets/96f8ac0ca90b5e46fb770d1695a77b2d +0 -0
  255. data/spec/dummy/tmp/cache/assets/development/sprockets/9b51a99e821d1802733dceac6764d18f +0 -0
  256. data/spec/dummy/tmp/cache/assets/development/sprockets/9d8681a4ce63f327a868f759096673e8 +0 -0
  257. data/spec/dummy/tmp/cache/assets/development/sprockets/a004f4ca229f6e9e761d2c86226e04f4 +0 -0
  258. data/spec/dummy/tmp/cache/assets/development/sprockets/a0a671e624f03533a82b1ec899bf3b21 +0 -0
  259. data/spec/dummy/tmp/cache/assets/development/sprockets/a0f669003bef02490064a16cfdb916fe +0 -0
  260. data/spec/dummy/tmp/cache/assets/development/sprockets/a411f643e05384fdb860f193e1dbe8f8 +0 -0
  261. data/spec/dummy/tmp/cache/assets/development/sprockets/a4abc5f3fc1bfe41be3470836766d110 +0 -0
  262. data/spec/dummy/tmp/cache/assets/development/sprockets/a82a869a86d5cbcbb101123eb6448f0c +0 -0
  263. data/spec/dummy/tmp/cache/assets/development/sprockets/a97cd428904e5968d05f7d3a5fd50f85 +0 -0
  264. data/spec/dummy/tmp/cache/assets/development/sprockets/aa87366fe7cd02f1be035665580cf066 +0 -0
  265. data/spec/dummy/tmp/cache/assets/development/sprockets/ada9a8c9882e963e6b98cdcaf20af34f +0 -0
  266. data/spec/dummy/tmp/cache/assets/development/sprockets/af326fcf9b4f69ff70d3610d0696b585 +0 -0
  267. data/spec/dummy/tmp/cache/assets/development/sprockets/af5ab48d2f371513fb609f8bdec3ac42 +0 -0
  268. data/spec/dummy/tmp/cache/assets/development/sprockets/b245fe00601bf4b4c2bd6ce9286a53dc +0 -0
  269. data/spec/dummy/tmp/cache/assets/development/sprockets/b51a3679ccee92d6e374deac3359cc69 +0 -0
  270. data/spec/dummy/tmp/cache/assets/development/sprockets/baed877d386dc374496dcd62af36bc5b +0 -0
  271. data/spec/dummy/tmp/cache/assets/development/sprockets/bc6f2f1da483ac27102f9412ee294dbf +0 -0
  272. data/spec/dummy/tmp/cache/assets/development/sprockets/bcca522c6302f184f12fe0e8a7d7e71a +0 -0
  273. data/spec/dummy/tmp/cache/assets/development/sprockets/bd3936370d0f952ada5774e2230046ed +0 -0
  274. data/spec/dummy/tmp/cache/assets/development/sprockets/c04a836e22ec09c7eae6eae9349efee3 +0 -0
  275. data/spec/dummy/tmp/cache/assets/development/sprockets/c13fc73ceafa45876a901b3e775b83ae +0 -0
  276. data/spec/dummy/tmp/cache/assets/development/sprockets/c2816385f6bc1d4ef24315437e9353d3 +0 -0
  277. data/spec/dummy/tmp/cache/assets/development/sprockets/c4e265ba144f19c1f646f9d8271c0702 +0 -0
  278. data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  279. data/spec/dummy/tmp/cache/assets/development/sprockets/d4c36568a5145e04bfbbefd37fecdde7 +0 -0
  280. data/spec/dummy/tmp/cache/assets/development/sprockets/d63d1c956772687b2dd2c9b43533e795 +0 -0
  281. data/spec/dummy/tmp/cache/assets/development/sprockets/d75dd624db3682fd4fed243c5f6f2e69 +0 -0
  282. data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  283. data/spec/dummy/tmp/cache/assets/development/sprockets/d7d3659361bd25606f9efaba128bf4c1 +0 -0
  284. data/spec/dummy/tmp/cache/assets/development/sprockets/d9fa58e1385bfb03f2ede65c90f36d70 +0 -0
  285. data/spec/dummy/tmp/cache/assets/development/sprockets/da8e37f2c9e3ea8f443def70515d1df0 +0 -0
  286. data/spec/dummy/tmp/cache/assets/development/sprockets/dcff3d1cd16d434b55e09399722e68be +0 -0
  287. data/spec/dummy/tmp/cache/assets/development/sprockets/e18f7bb0b671acf59ad700724547a456 +0 -0
  288. data/spec/dummy/tmp/cache/assets/development/sprockets/e459168835a5f27b832ace20874f7c10 +0 -0
  289. data/spec/dummy/tmp/cache/assets/development/sprockets/e618b87b000e1c8d606542b2a7b4936f +0 -0
  290. data/spec/dummy/tmp/cache/assets/development/sprockets/e6df0f40358bfc2568038d9cf71859a5 +0 -0
  291. data/spec/dummy/tmp/cache/assets/development/sprockets/ebe8c427280f71fed250770f7d5e0af8 +0 -0
  292. data/spec/dummy/tmp/cache/assets/development/sprockets/edefa48dfc6b66b08d68e6438d1344b4 +0 -0
  293. data/spec/dummy/tmp/cache/assets/development/sprockets/ee70ec49c833625099b94820cbfaf238 +0 -0
  294. data/spec/dummy/tmp/cache/assets/development/sprockets/eea8d1c182d93d92a52f24a90d5c92af +0 -0
  295. data/spec/dummy/tmp/cache/assets/development/sprockets/efe3e82d4fe0ca8a3427678a9cd1d070 +0 -0
  296. data/spec/dummy/tmp/cache/assets/development/sprockets/f024e5fd86a61ac8399d564f8202bbc8 +0 -0
  297. data/spec/dummy/tmp/cache/assets/development/sprockets/f12542794a06e22b1dbd97250d49deb1 +0 -0
  298. data/spec/dummy/tmp/cache/assets/development/sprockets/f34759266a45010771006dcbb608d179 +0 -0
  299. data/spec/dummy/tmp/cache/assets/development/sprockets/f466a3fe42e17653acb9980dae9be11a +0 -0
  300. data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  301. data/spec/dummy/tmp/cache/assets/development/sprockets/f86d0394f2c6bebf4ad490ce4a37d754 +0 -0
  302. data/spec/dummy/tmp/cache/assets/development/sprockets/fd5a31651e4fc8cf4a3199e8db16d53e +0 -0
  303. data/spec/dummy/tmp/cache/assets/development/sprockets/fd71e811fb40f0e16e339622af4c771f +0 -0
  304. data/spec/dummy/tmp/cache/assets/development/sprockets/fd843e12fcdd9539f8e3d7384a19bb31 +0 -0
  305. data/spec/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  306. data/spec/dummy/tmp/cache/assets/test/sprockets/19699f0bd9bbacb926aa665d057d7dcc +0 -0
  307. data/spec/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  308. data/spec/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  309. data/spec/dummy/tmp/cache/assets/test/sprockets/371bf96e99717688ed7313a0c53f4212 +0 -0
  310. data/spec/dummy/tmp/cache/assets/test/sprockets/59f25755df49e4db5915553e3d2ef412 +0 -0
  311. data/spec/dummy/tmp/cache/assets/test/sprockets/6fc757c2c8329244ca95d6909865bbc2 +0 -0
  312. data/spec/dummy/tmp/cache/assets/test/sprockets/764fdaef2f219fafc8db0923a56c23a3 +0 -0
  313. data/spec/dummy/tmp/cache/assets/test/sprockets/87172f2d7a412d1fe87d7775d589b883 +0 -0
  314. data/spec/dummy/tmp/cache/assets/test/sprockets/88741eb863751c5d5adb82282f6df5cd +0 -0
  315. data/spec/dummy/tmp/cache/assets/test/sprockets/96f8ac0ca90b5e46fb770d1695a77b2d +0 -0
  316. data/spec/dummy/tmp/cache/assets/test/sprockets/a4abc5f3fc1bfe41be3470836766d110 +0 -0
  317. data/spec/dummy/tmp/cache/assets/test/sprockets/af326fcf9b4f69ff70d3610d0696b585 +0 -0
  318. data/spec/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  319. data/spec/dummy/tmp/cache/assets/test/sprockets/d63d1c956772687b2dd2c9b43533e795 +0 -0
  320. data/spec/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  321. data/spec/dummy/tmp/cache/assets/test/sprockets/d7d3659361bd25606f9efaba128bf4c1 +0 -0
  322. data/spec/dummy/tmp/cache/assets/test/sprockets/f024e5fd86a61ac8399d564f8202bbc8 +0 -0
  323. data/spec/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  324. data/spec/dummy/tmp/cache/assets/test/sprockets/fd5a31651e4fc8cf4a3199e8db16d53e +0 -0
  325. data/spec/ext_form_spec.rb +12 -0
  326. data/spec/factories/order_header_factory.rb +22 -0
  327. data/spec/helpers/dt_picker_spec.rb +66 -0
  328. data/spec/helpers/dt_picker_tag_spec.rb +65 -0
  329. data/spec/helpers/form_helper_bs_spec.rb +102 -0
  330. data/spec/helpers/form_helper_spec.rb +109 -0
  331. data/spec/spec_helper.rb +15 -0
  332. data/spec/support/form_helper.rb +21 -0
  333. metadata +787 -0
@@ -0,0 +1,1159 @@
1
+ /*!
2
+ * typeahead.js 0.9.3
3
+ * https://github.com/twitter/typeahead
4
+ * Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT
5
+ */
6
+
7
+ (function ($) {
8
+ var VERSION = "0.9.3";
9
+ var utils = {
10
+ isMsie: function () {
11
+ var match = /(msie) ([\w.]+)/i.exec(navigator.userAgent);
12
+ return match ? parseInt(match[2], 10) : false;
13
+ },
14
+ isBlankString: function (str) {
15
+ return !str || /^\s*$/.test(str);
16
+ },
17
+ escapeRegExChars: function (str) {
18
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
19
+ },
20
+ isString: function (obj) {
21
+ return typeof obj === "string";
22
+ },
23
+ isNumber: function (obj) {
24
+ return typeof obj === "number";
25
+ },
26
+ isArray: $.isArray,
27
+ isFunction: $.isFunction,
28
+ isObject: $.isPlainObject,
29
+ isUndefined: function (obj) {
30
+ return typeof obj === "undefined";
31
+ },
32
+ bind: $.proxy,
33
+ bindAll: function (obj) {
34
+ var val;
35
+ for (var key in obj) {
36
+ $.isFunction(val = obj[key]) && (obj[key] = $.proxy(val, obj));
37
+ }
38
+ },
39
+ indexOf: function (haystack, needle) {
40
+ for (var i = 0; i < haystack.length; i++) {
41
+ if (haystack[i] === needle) {
42
+ return i;
43
+ }
44
+ }
45
+ return -1;
46
+ },
47
+ each: $.each,
48
+ map: $.map,
49
+ filter: $.grep,
50
+ every: function (obj, test) {
51
+ var result = true;
52
+ if (!obj) {
53
+ return result;
54
+ }
55
+ $.each(obj, function (key, val) {
56
+ if (!(result = test.call(null, val, key, obj))) {
57
+ return false;
58
+ }
59
+ });
60
+ return !!result;
61
+ },
62
+ some: function (obj, test) {
63
+ var result = false;
64
+ if (!obj) {
65
+ return result;
66
+ }
67
+ $.each(obj, function (key, val) {
68
+ if (result = test.call(null, val, key, obj)) {
69
+ return false;
70
+ }
71
+ });
72
+ return !!result;
73
+ },
74
+ mixin: $.extend,
75
+ getUniqueId: function () {
76
+ var counter = 0;
77
+ return function () {
78
+ return counter++;
79
+ };
80
+ }(),
81
+ defer: function (fn) {
82
+ setTimeout(fn, 0);
83
+ },
84
+ debounce: function (func, wait, immediate) {
85
+ var timeout, result;
86
+ return function () {
87
+ var context = this, args = arguments, later, callNow;
88
+ later = function () {
89
+ timeout = null;
90
+ if (!immediate) {
91
+ result = func.apply(context, args);
92
+ }
93
+ };
94
+ callNow = immediate && !timeout;
95
+ clearTimeout(timeout);
96
+ timeout = setTimeout(later, wait);
97
+ if (callNow) {
98
+ result = func.apply(context, args);
99
+ }
100
+ return result;
101
+ };
102
+ },
103
+ throttle: function (func, wait) {
104
+ var context, args, timeout, result, previous, later;
105
+ previous = 0;
106
+ later = function () {
107
+ previous = new Date();
108
+ timeout = null;
109
+ result = func.apply(context, args);
110
+ };
111
+ return function () {
112
+ var now = new Date(), remaining = wait - (now - previous);
113
+ context = this;
114
+ args = arguments;
115
+ if (remaining <= 0) {
116
+ clearTimeout(timeout);
117
+ timeout = null;
118
+ previous = now;
119
+ result = func.apply(context, args);
120
+ } else if (!timeout) {
121
+ timeout = setTimeout(later, remaining);
122
+ }
123
+ return result;
124
+ };
125
+ },
126
+ tokenizeQuery: function (str) {
127
+ return $.trim(str).toLowerCase().split(/[\s]+/);
128
+ },
129
+ tokenizeText: function (str) {
130
+ return $.trim(str).toLowerCase().split(/[\s\-_]+/);
131
+ },
132
+ getProtocol: function () {
133
+ return location.protocol;
134
+ },
135
+ noop: function () {
136
+ }
137
+ };
138
+ var EventTarget = function () {
139
+ var eventSplitter = /\s+/;
140
+ return {
141
+ on: function (events, callback) {
142
+ var event;
143
+ if (!callback) {
144
+ return this;
145
+ }
146
+ this._callbacks = this._callbacks || {};
147
+ events = events.split(eventSplitter);
148
+ while (event = events.shift()) {
149
+ this._callbacks[event] = this._callbacks[event] || [];
150
+ this._callbacks[event].push(callback);
151
+ }
152
+ return this;
153
+ },
154
+ trigger: function (events, data) {
155
+ var event, callbacks;
156
+ if (!this._callbacks) {
157
+ return this;
158
+ }
159
+ events = events.split(eventSplitter);
160
+ while (event = events.shift()) {
161
+ if (callbacks = this._callbacks[event]) {
162
+ for (var i = 0; i < callbacks.length; i += 1) {
163
+ callbacks[i].call(this, {
164
+ type: event,
165
+ data: data
166
+ });
167
+ }
168
+ }
169
+ }
170
+ return this;
171
+ }
172
+ };
173
+ }();
174
+ var EventBus = function () {
175
+ var namespace = "typeahead:";
176
+
177
+ function EventBus(o) {
178
+ if (!o || !o.el) {
179
+ $.error("EventBus initialized without el");
180
+ }
181
+ this.$el = $(o.el);
182
+ }
183
+
184
+ utils.mixin(EventBus.prototype, {
185
+ trigger: function (type) {
186
+ var args = [].slice.call(arguments, 1);
187
+ this.$el.trigger(namespace + type, args);
188
+ }
189
+ });
190
+ return EventBus;
191
+ }();
192
+ var PersistentStorage = function () {
193
+ var ls, methods;
194
+ try {
195
+ ls = window.localStorage;
196
+ ls.setItem("~~~", "!");
197
+ ls.removeItem("~~~");
198
+ } catch (err) {
199
+ ls = null;
200
+ }
201
+ function PersistentStorage(namespace) {
202
+ this.prefix = [ "__", namespace, "__" ].join("");
203
+ this.ttlKey = "__ttl__";
204
+ this.keyMatcher = new RegExp("^" + this.prefix);
205
+ }
206
+
207
+ if (ls && window.JSON) {
208
+ methods = {
209
+ _prefix: function (key) {
210
+ return this.prefix + key;
211
+ },
212
+ _ttlKey: function (key) {
213
+ return this._prefix(key) + this.ttlKey;
214
+ },
215
+ get: function (key) {
216
+ if (this.isExpired(key)) {
217
+ this.remove(key);
218
+ }
219
+ return decode(ls.getItem(this._prefix(key)));
220
+ },
221
+ set: function (key, val, ttl) {
222
+ if (utils.isNumber(ttl)) {
223
+ ls.setItem(this._ttlKey(key), encode(now() + ttl));
224
+ } else {
225
+ ls.removeItem(this._ttlKey(key));
226
+ }
227
+ return ls.setItem(this._prefix(key), encode(val));
228
+ },
229
+ remove: function (key) {
230
+ ls.removeItem(this._ttlKey(key));
231
+ ls.removeItem(this._prefix(key));
232
+ return this;
233
+ },
234
+ clear: function () {
235
+ var i, key, keys = [], len = ls.length;
236
+ for (i = 0; i < len; i++) {
237
+ if ((key = ls.key(i)).match(this.keyMatcher)) {
238
+ keys.push(key.replace(this.keyMatcher, ""));
239
+ }
240
+ }
241
+ for (i = keys.length; i--;) {
242
+ this.remove(keys[i]);
243
+ }
244
+ return this;
245
+ },
246
+ isExpired: function (key) {
247
+ var ttl = decode(ls.getItem(this._ttlKey(key)));
248
+ return utils.isNumber(ttl) && now() > ttl ? true : false;
249
+ }
250
+ };
251
+ } else {
252
+ methods = {
253
+ get: utils.noop,
254
+ set: utils.noop,
255
+ remove: utils.noop,
256
+ clear: utils.noop,
257
+ isExpired: utils.noop
258
+ };
259
+ }
260
+ utils.mixin(PersistentStorage.prototype, methods);
261
+ return PersistentStorage;
262
+ function now() {
263
+ return new Date().getTime();
264
+ }
265
+
266
+ function encode(val) {
267
+ return JSON.stringify(utils.isUndefined(val) ? null : val);
268
+ }
269
+
270
+ function decode(val) {
271
+ return JSON.parse(val);
272
+ }
273
+ }();
274
+ var RequestCache = function () {
275
+ function RequestCache(o) {
276
+ utils.bindAll(this);
277
+ o = o || {};
278
+ this.sizeLimit = o.sizeLimit || 10;
279
+ this.cache = {};
280
+ this.cachedKeysByAge = [];
281
+ }
282
+
283
+ utils.mixin(RequestCache.prototype, {
284
+ get: function (url) {
285
+ return this.cache[url];
286
+ },
287
+ set: function (url, resp) {
288
+ var requestToEvict;
289
+ if (this.cachedKeysByAge.length === this.sizeLimit) {
290
+ requestToEvict = this.cachedKeysByAge.shift();
291
+ delete this.cache[requestToEvict];
292
+ }
293
+ this.cache[url] = resp;
294
+ this.cachedKeysByAge.push(url);
295
+ }
296
+ });
297
+ return RequestCache;
298
+ }();
299
+ var Transport = function () {
300
+ var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests, requestCache;
301
+
302
+ function Transport(o) {
303
+ utils.bindAll(this);
304
+ o = utils.isString(o) ? {
305
+ url: o
306
+ } : o;
307
+ requestCache = requestCache || new RequestCache();
308
+ maxPendingRequests = utils.isNumber(o.maxParallelRequests) ? o.maxParallelRequests : maxPendingRequests || 6;
309
+ this.url = o.url;
310
+ this.wildcard = o.wildcard || "%QUERY";
311
+ this.filter = o.filter;
312
+ this.replace = o.replace;
313
+ this.ajaxSettings = {
314
+ type: "get",
315
+ cache: o.cache,
316
+ timeout: o.timeout,
317
+ dataType: o.dataType || "json",
318
+ beforeSend: o.beforeSend
319
+ };
320
+ this._get = (/^throttle$/i.test(o.rateLimitFn) ? utils.throttle : utils.debounce)(this._get, o.rateLimitWait || 300);
321
+ }
322
+
323
+ utils.mixin(Transport.prototype, {
324
+ _get: function (url, cb) {
325
+ var that = this;
326
+ if (belowPendingRequestsThreshold()) {
327
+ this._sendRequest(url).done(done);
328
+ } else {
329
+ this.onDeckRequestArgs = [].slice.call(arguments, 0);
330
+ }
331
+ function done(resp) {
332
+ var data = that.filter ? that.filter(resp) : resp;
333
+ cb && cb(data);
334
+ requestCache.set(url, resp);
335
+ }
336
+ },
337
+ _sendRequest: function (url) {
338
+ var that = this, jqXhr = pendingRequests[url];
339
+ if (!jqXhr) {
340
+ incrementPendingRequests();
341
+ jqXhr = pendingRequests[url] = $.ajax(url, this.ajaxSettings).always(always);
342
+ }
343
+ return jqXhr;
344
+ function always() {
345
+ decrementPendingRequests();
346
+ pendingRequests[url] = null;
347
+ if (that.onDeckRequestArgs) {
348
+ that._get.apply(that, that.onDeckRequestArgs);
349
+ that.onDeckRequestArgs = null;
350
+ }
351
+ }
352
+ },
353
+ get: function (query, cb) {
354
+ var that = this, encodedQuery = encodeURIComponent(query || ""), url, resp;
355
+ cb = cb || utils.noop;
356
+ url = this.replace ? this.replace(this.url, encodedQuery) : this.url.replace(this.wildcard, encodedQuery);
357
+ if (resp = requestCache.get(url)) {
358
+ utils.defer(function () {
359
+ cb(that.filter ? that.filter(resp) : resp);
360
+ });
361
+ } else {
362
+ this._get(url, cb);
363
+ }
364
+ return !!resp;
365
+ }
366
+ });
367
+ return Transport;
368
+ function incrementPendingRequests() {
369
+ pendingRequestsCount++;
370
+ }
371
+
372
+ function decrementPendingRequests() {
373
+ pendingRequestsCount--;
374
+ }
375
+
376
+ function belowPendingRequestsThreshold() {
377
+ return pendingRequestsCount < maxPendingRequests;
378
+ }
379
+ }();
380
+ var Dataset = function () {
381
+ var keys = {
382
+ thumbprint: "thumbprint",
383
+ protocol: "protocol",
384
+ itemHash: "itemHash",
385
+ adjacencyList: "adjacencyList"
386
+ };
387
+
388
+ function Dataset(o) {
389
+ utils.bindAll(this);
390
+ if (utils.isString(o.template) && !o.engine) {
391
+ $.error("no template engine specified");
392
+ }
393
+ if (!o.local && !o.prefetch && !o.remote) {
394
+ $.error("one of local, prefetch, or remote is required");
395
+ }
396
+ this.name = o.name || utils.getUniqueId();
397
+ this.limit = o.limit || 5;
398
+ this.minLength = o.minLength || 1;
399
+ this.header = o.header;
400
+ this.footer = o.footer;
401
+ this.valueKey = o.valueKey || "value";
402
+ this.template = compileTemplate(o.template, o.engine, this.valueKey);
403
+ this.local = o.local;
404
+ this.prefetch = o.prefetch;
405
+ this.remote = o.remote;
406
+ this.itemHash = {};
407
+ this.adjacencyList = {};
408
+ this.storage = o.name ? new PersistentStorage(o.name) : null;
409
+ }
410
+
411
+ utils.mixin(Dataset.prototype, {
412
+ _processLocalData: function (data) {
413
+ this._mergeProcessedData(this._processData(data));
414
+ },
415
+ _loadPrefetchData: function (o) {
416
+ var that = this, thumbprint = VERSION + (o.thumbprint || ""), storedThumbprint, storedProtocol, storedItemHash, storedAdjacencyList, isExpired, deferred;
417
+ if (this.storage) {
418
+ storedThumbprint = this.storage.get(keys.thumbprint);
419
+ storedProtocol = this.storage.get(keys.protocol);
420
+ storedItemHash = this.storage.get(keys.itemHash);
421
+ storedAdjacencyList = this.storage.get(keys.adjacencyList);
422
+ }
423
+ isExpired = storedThumbprint !== thumbprint || storedProtocol !== utils.getProtocol();
424
+ o = utils.isString(o) ? {
425
+ url: o
426
+ } : o;
427
+ o.ttl = utils.isNumber(o.ttl) ? o.ttl : 24 * 60 * 60 * 1e3;
428
+ if (storedItemHash && storedAdjacencyList && !isExpired) {
429
+ this._mergeProcessedData({
430
+ itemHash: storedItemHash,
431
+ adjacencyList: storedAdjacencyList
432
+ });
433
+ deferred = $.Deferred().resolve();
434
+ } else {
435
+ deferred = $.getJSON(o.url).done(processPrefetchData);
436
+ }
437
+ return deferred;
438
+ function processPrefetchData(data) {
439
+ var filteredData = o.filter ? o.filter(data) : data, processedData = that._processData(filteredData), itemHash = processedData.itemHash, adjacencyList = processedData.adjacencyList;
440
+ if (that.storage) {
441
+ that.storage.set(keys.itemHash, itemHash, o.ttl);
442
+ that.storage.set(keys.adjacencyList, adjacencyList, o.ttl);
443
+ that.storage.set(keys.thumbprint, thumbprint, o.ttl);
444
+ that.storage.set(keys.protocol, utils.getProtocol(), o.ttl);
445
+ }
446
+ that._mergeProcessedData(processedData);
447
+ }
448
+ },
449
+ _transformDatum: function (datum) {
450
+ var value = utils.isString(datum) ? datum : datum[this.valueKey], tokens = datum.tokens || utils.tokenizeText(value), item = {
451
+ value: value,
452
+ tokens: tokens
453
+ };
454
+ if (utils.isString(datum)) {
455
+ item.datum = {};
456
+ item.datum[this.valueKey] = datum;
457
+ } else {
458
+ item.datum = datum;
459
+ }
460
+ item.tokens = utils.filter(item.tokens, function (token) {
461
+ return !utils.isBlankString(token);
462
+ });
463
+ item.tokens = utils.map(item.tokens, function (token) {
464
+ return token.toLowerCase();
465
+ });
466
+ return item;
467
+ },
468
+ _processData: function (data) {
469
+ var that = this, itemHash = {}, adjacencyList = {};
470
+ utils.each(data, function (i, datum) {
471
+ var item = that._transformDatum(datum), id = utils.getUniqueId(item.value);
472
+ itemHash[id] = item;
473
+ utils.each(item.tokens, function (i, token) {
474
+ var character = token.charAt(0), adjacency = adjacencyList[character] || (adjacencyList[character] = [ id ]);
475
+ !~utils.indexOf(adjacency, id) && adjacency.push(id);
476
+ });
477
+ });
478
+ return {
479
+ itemHash: itemHash,
480
+ adjacencyList: adjacencyList
481
+ };
482
+ },
483
+ _mergeProcessedData: function (processedData) {
484
+ var that = this;
485
+ utils.mixin(this.itemHash, processedData.itemHash);
486
+ utils.each(processedData.adjacencyList, function (character, adjacency) {
487
+ var masterAdjacency = that.adjacencyList[character];
488
+ that.adjacencyList[character] = masterAdjacency ? masterAdjacency.concat(adjacency) : adjacency;
489
+ });
490
+ },
491
+ _getLocalSuggestions: function (terms) {
492
+ var that = this, firstChars = [], lists = [], shortestList, suggestions = [];
493
+ utils.each(terms, function (i, term) {
494
+ var firstChar = term.charAt(0);
495
+ !~utils.indexOf(firstChars, firstChar) && firstChars.push(firstChar);
496
+ });
497
+ utils.each(firstChars, function (i, firstChar) {
498
+ var list = that.adjacencyList[firstChar];
499
+ if (!list) {
500
+ return false;
501
+ }
502
+ lists.push(list);
503
+ if (!shortestList || list.length < shortestList.length) {
504
+ shortestList = list;
505
+ }
506
+ });
507
+ if (lists.length < firstChars.length) {
508
+ return [];
509
+ }
510
+ utils.each(shortestList, function (i, id) {
511
+ var item = that.itemHash[id], isCandidate, isMatch;
512
+ isCandidate = utils.every(lists, function (list) {
513
+ return ~utils.indexOf(list, id);
514
+ });
515
+ isMatch = isCandidate && utils.every(terms, function (term) {
516
+ return utils.some(item.tokens, function (token) {
517
+ return token.indexOf(term) === 0;
518
+ });
519
+ });
520
+ isMatch && suggestions.push(item);
521
+ });
522
+ return suggestions;
523
+ },
524
+ initialize: function () {
525
+ var deferred;
526
+ this.local && this._processLocalData(this.local);
527
+ this.transport = this.remote ? new Transport(this.remote) : null;
528
+ deferred = this.prefetch ? this._loadPrefetchData(this.prefetch) : $.Deferred().resolve();
529
+ this.local = this.prefetch = this.remote = null;
530
+ this.initialize = function () {
531
+ return deferred;
532
+ };
533
+ return deferred;
534
+ },
535
+ getSuggestions: function (query, cb) {
536
+ var that = this, terms, suggestions, cacheHit = false;
537
+ if (query.length < this.minLength) {
538
+ return;
539
+ }
540
+ terms = utils.tokenizeQuery(query);
541
+ suggestions = this._getLocalSuggestions(terms).slice(0, this.limit);
542
+ if (suggestions.length < this.limit && this.transport) {
543
+ cacheHit = this.transport.get(query, processRemoteData);
544
+ }
545
+ !cacheHit && cb && cb(suggestions);
546
+ function processRemoteData(data) {
547
+ suggestions = suggestions.slice(0);
548
+ utils.each(data, function (i, datum) {
549
+ var item = that._transformDatum(datum), isDuplicate;
550
+ isDuplicate = utils.some(suggestions, function (suggestion) {
551
+ return item.value === suggestion.value;
552
+ });
553
+ !isDuplicate && suggestions.push(item);
554
+ return suggestions.length < that.limit;
555
+ });
556
+ cb && cb(suggestions);
557
+ }
558
+ }
559
+ });
560
+ return Dataset;
561
+ function compileTemplate(template, engine, valueKey) {
562
+ var renderFn, compiledTemplate;
563
+ if (utils.isFunction(template)) {
564
+ renderFn = template;
565
+ } else if (utils.isString(template)) {
566
+ compiledTemplate = engine.compile(template);
567
+ renderFn = utils.bind(compiledTemplate.render, compiledTemplate);
568
+ } else {
569
+ renderFn = function (context) {
570
+ return "<p>" + context[valueKey] + "</p>";
571
+ };
572
+ }
573
+ return renderFn;
574
+ }
575
+ }();
576
+ var InputView = function () {
577
+ function InputView(o) {
578
+ var that = this;
579
+ utils.bindAll(this);
580
+ this.specialKeyCodeMap = {
581
+ 9: "tab",
582
+ 27: "esc",
583
+ 37: "left",
584
+ 39: "right",
585
+ 13: "enter",
586
+ 38: "up",
587
+ 40: "down"
588
+ };
589
+ this.$hint = $(o.hint);
590
+ this.$input = $(o.input).on("blur.tt", this._handleBlur).on("focus.tt", this._handleFocus).on("keydown.tt", this._handleSpecialKeyEvent);
591
+ if (!utils.isMsie()) {
592
+ this.$input.on("input.tt", this._compareQueryToInputValue);
593
+ } else {
594
+ this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function ($e) {
595
+ if (that.specialKeyCodeMap[$e.which || $e.keyCode]) {
596
+ return;
597
+ }
598
+ utils.defer(that._compareQueryToInputValue);
599
+ });
600
+ }
601
+ this.query = this.$input.val();
602
+ this.$overflowHelper = buildOverflowHelper(this.$input);
603
+ }
604
+
605
+ utils.mixin(InputView.prototype, EventTarget, {
606
+ _handleFocus: function () {
607
+ this.trigger("focused");
608
+ },
609
+ _handleBlur: function () {
610
+ this.trigger("blured");
611
+ },
612
+ _handleSpecialKeyEvent: function ($e) {
613
+ var keyName = this.specialKeyCodeMap[$e.which || $e.keyCode];
614
+ keyName && this.trigger(keyName + "Keyed", $e);
615
+ },
616
+ _compareQueryToInputValue: function () {
617
+ var inputValue = this.getInputValue(), isSameQuery = compareQueries(this.query, inputValue), isSameQueryExceptWhitespace = isSameQuery ? this.query.length !== inputValue.length : false;
618
+ if (isSameQueryExceptWhitespace) {
619
+ this.trigger("whitespaceChanged", {
620
+ value: this.query
621
+ });
622
+ } else if (!isSameQuery) {
623
+ this.trigger("queryChanged", {
624
+ value: this.query = inputValue
625
+ });
626
+ }
627
+ },
628
+ destroy: function () {
629
+ this.$hint.off(".tt");
630
+ this.$input.off(".tt");
631
+ this.$hint = this.$input = this.$overflowHelper = null;
632
+ },
633
+ focus: function () {
634
+ this.$input.focus();
635
+ },
636
+ blur: function () {
637
+ this.$input.blur();
638
+ },
639
+ getQuery: function () {
640
+ return this.query;
641
+ },
642
+ setQuery: function (query) {
643
+ this.query = query;
644
+ },
645
+ getInputValue: function () {
646
+ return this.$input.val();
647
+ },
648
+ setInputValue: function (value, silent) {
649
+ this.$input.val(value);
650
+ !silent && this._compareQueryToInputValue();
651
+ },
652
+ getHintValue: function () {
653
+ return this.$hint.val();
654
+ },
655
+ setHintValue: function (value) {
656
+ this.$hint.val(value);
657
+ },
658
+ getLanguageDirection: function () {
659
+ return (this.$input.css("direction") || "ltr").toLowerCase();
660
+ },
661
+ isOverflow: function () {
662
+ this.$overflowHelper.text(this.getInputValue());
663
+ return this.$overflowHelper.width() > this.$input.width();
664
+ },
665
+ isCursorAtEnd: function () {
666
+ var valueLength = this.$input.val().length, selectionStart = this.$input[0].selectionStart, range;
667
+ if (utils.isNumber(selectionStart)) {
668
+ return selectionStart === valueLength;
669
+ } else if (document.selection) {
670
+ range = document.selection.createRange();
671
+ range.moveStart("character", -valueLength);
672
+ return valueLength === range.text.length;
673
+ }
674
+ return true;
675
+ }
676
+ });
677
+ return InputView;
678
+ function buildOverflowHelper($input) {
679
+ return $("<span></span>").css({
680
+ position: "absolute",
681
+ left: "-9999px",
682
+ visibility: "hidden",
683
+ whiteSpace: "nowrap",
684
+ fontFamily: $input.css("font-family"),
685
+ fontSize: $input.css("font-size"),
686
+ fontStyle: $input.css("font-style"),
687
+ fontVariant: $input.css("font-variant"),
688
+ fontWeight: $input.css("font-weight"),
689
+ wordSpacing: $input.css("word-spacing"),
690
+ letterSpacing: $input.css("letter-spacing"),
691
+ textIndent: $input.css("text-indent"),
692
+ textRendering: $input.css("text-rendering"),
693
+ textTransform: $input.css("text-transform")
694
+ }).insertAfter($input);
695
+ }
696
+
697
+ function compareQueries(a, b) {
698
+ a = (a || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
699
+ b = (b || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
700
+ return a === b;
701
+ }
702
+ }();
703
+ var DropdownView = function () {
704
+ var html = {
705
+ suggestionsList: '<span class="tt-suggestions"></span>'
706
+ }, css = {
707
+ suggestionsList: {
708
+ display: "block"
709
+ },
710
+ suggestion: {
711
+ whiteSpace: "nowrap",
712
+ cursor: "pointer"
713
+ },
714
+ suggestionChild: {
715
+ whiteSpace: "normal"
716
+ }
717
+ };
718
+
719
+ function DropdownView(o) {
720
+ utils.bindAll(this);
721
+ this.isOpen = false;
722
+ this.isEmpty = true;
723
+ this.isMouseOverDropdown = false;
724
+ this.$menu = $(o.menu).on("mouseenter.tt", this._handleMouseenter).on("mouseleave.tt", this._handleMouseleave).on("click.tt", ".tt-suggestion", this._handleSelection).on("mouseover.tt", ".tt-suggestion", this._handleMouseover);
725
+ }
726
+
727
+ utils.mixin(DropdownView.prototype, EventTarget, {
728
+ _handleMouseenter: function () {
729
+ this.isMouseOverDropdown = true;
730
+ },
731
+ _handleMouseleave: function () {
732
+ this.isMouseOverDropdown = false;
733
+ },
734
+ _handleMouseover: function ($e) {
735
+ var $suggestion = $($e.currentTarget);
736
+ this._getSuggestions().removeClass("tt-is-under-cursor");
737
+ $suggestion.addClass("tt-is-under-cursor");
738
+ },
739
+ _handleSelection: function ($e) {
740
+ var $suggestion = $($e.currentTarget);
741
+ this.trigger("suggestionSelected", extractSuggestion($suggestion));
742
+ },
743
+ _show: function () {
744
+ this.$menu.css("display", "block");
745
+ },
746
+ _hide: function () {
747
+ this.$menu.hide();
748
+ },
749
+ _moveCursor: function (increment) {
750
+ var $suggestions, $cur, nextIndex, $underCursor;
751
+ if (!this.isVisible()) {
752
+ return;
753
+ }
754
+ $suggestions = this._getSuggestions();
755
+ $cur = $suggestions.filter(".tt-is-under-cursor");
756
+ $cur.removeClass("tt-is-under-cursor");
757
+ nextIndex = $suggestions.index($cur) + increment;
758
+ nextIndex = (nextIndex + 1) % ($suggestions.length + 1) - 1;
759
+ if (nextIndex === -1) {
760
+ this.trigger("cursorRemoved");
761
+ return;
762
+ } else if (nextIndex < -1) {
763
+ nextIndex = $suggestions.length - 1;
764
+ }
765
+ $underCursor = $suggestions.eq(nextIndex).addClass("tt-is-under-cursor");
766
+ this._ensureVisibility($underCursor);
767
+ this.trigger("cursorMoved", extractSuggestion($underCursor));
768
+ },
769
+ _getSuggestions: function () {
770
+ return this.$menu.find(".tt-suggestions > .tt-suggestion");
771
+ },
772
+ _ensureVisibility: function ($el) {
773
+ var menuHeight = this.$menu.height() + parseInt(this.$menu.css("paddingTop"), 10) + parseInt(this.$menu.css("paddingBottom"), 10), menuScrollTop = this.$menu.scrollTop(), elTop = $el.position().top, elBottom = elTop + $el.outerHeight(true);
774
+ if (elTop < 0) {
775
+ this.$menu.scrollTop(menuScrollTop + elTop);
776
+ } else if (menuHeight < elBottom) {
777
+ this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));
778
+ }
779
+ },
780
+ destroy: function () {
781
+ this.$menu.off(".tt");
782
+ this.$menu = null;
783
+ },
784
+ isVisible: function () {
785
+ return this.isOpen && !this.isEmpty;
786
+ },
787
+ closeUnlessMouseIsOverDropdown: function () {
788
+ if (!this.isMouseOverDropdown) {
789
+ this.close();
790
+ }
791
+ },
792
+ close: function () {
793
+ if (this.isOpen) {
794
+ this.isOpen = false;
795
+ this.isMouseOverDropdown = false;
796
+ this._hide();
797
+ this.$menu.find(".tt-suggestions > .tt-suggestion").removeClass("tt-is-under-cursor");
798
+ this.trigger("closed");
799
+ }
800
+ },
801
+ open: function () {
802
+ if (!this.isOpen) {
803
+ this.isOpen = true;
804
+ !this.isEmpty && this._show();
805
+ this.trigger("opened");
806
+ }
807
+ },
808
+ setLanguageDirection: function (dir) {
809
+ var ltrCss = {
810
+ left: "0",
811
+ right: "auto"
812
+ }, rtlCss = {
813
+ left: "auto",
814
+ right: " 0"
815
+ };
816
+ dir === "ltr" ? this.$menu.css(ltrCss) : this.$menu.css(rtlCss);
817
+ },
818
+ moveCursorUp: function () {
819
+ this._moveCursor(-1);
820
+ },
821
+ moveCursorDown: function () {
822
+ this._moveCursor(+1);
823
+ },
824
+ getSuggestionUnderCursor: function () {
825
+ var $suggestion = this._getSuggestions().filter(".tt-is-under-cursor").first();
826
+ return $suggestion.length > 0 ? extractSuggestion($suggestion) : null;
827
+ },
828
+ getFirstSuggestion: function () {
829
+ var $suggestion = this._getSuggestions().first();
830
+ return $suggestion.length > 0 ? extractSuggestion($suggestion) : null;
831
+ },
832
+ renderSuggestions: function (dataset, suggestions) {
833
+ var datasetClassName = "tt-dataset-" + dataset.name, wrapper = '<div class="tt-suggestion">%body</div>', compiledHtml, $suggestionsList, $dataset = this.$menu.find("." + datasetClassName), elBuilder, fragment, $el;
834
+ if ($dataset.length === 0) {
835
+ $suggestionsList = $(html.suggestionsList).css(css.suggestionsList);
836
+ $dataset = $("<div></div>").addClass(datasetClassName).append(dataset.header).append($suggestionsList).append(dataset.footer).appendTo(this.$menu);
837
+ }
838
+ if (suggestions.length > 0) {
839
+ this.isEmpty = false;
840
+ this.isOpen && this._show();
841
+ elBuilder = document.createElement("div");
842
+ fragment = document.createDocumentFragment();
843
+ utils.each(suggestions, function (i, suggestion) {
844
+ suggestion.dataset = dataset.name;
845
+ compiledHtml = dataset.template(suggestion.datum);
846
+ elBuilder.innerHTML = wrapper.replace("%body", compiledHtml);
847
+ $el = $(elBuilder.firstChild).css(css.suggestion).data("suggestion", suggestion);
848
+ $el.children().each(function () {
849
+ $(this).css(css.suggestionChild);
850
+ });
851
+ fragment.appendChild($el[0]);
852
+ });
853
+ $dataset.show().find(".tt-suggestions").html(fragment);
854
+ } else {
855
+ this.clearSuggestions(dataset.name);
856
+ }
857
+ this.trigger("suggestionsRendered");
858
+ },
859
+ clearSuggestions: function (datasetName) {
860
+ var $datasets = datasetName ? this.$menu.find(".tt-dataset-" + datasetName) : this.$menu.find('[class^="tt-dataset-"]'), $suggestions = $datasets.find(".tt-suggestions");
861
+ $datasets.hide();
862
+ $suggestions.empty();
863
+ if (this._getSuggestions().length === 0) {
864
+ this.isEmpty = true;
865
+ this._hide();
866
+ }
867
+ }
868
+ });
869
+ return DropdownView;
870
+ function extractSuggestion($el) {
871
+ return $el.data("suggestion");
872
+ }
873
+ }();
874
+ var TypeaheadView = function () {
875
+ var html = {
876
+ wrapper: '<span class="twitter-typeahead"></span>',
877
+ hint: '<input class="tt-hint" type="text" autocomplete="off" spellcheck="off" disabled>',
878
+ dropdown: '<span class="tt-dropdown-menu"></span>'
879
+ }, css = {
880
+ wrapper: {
881
+ position: "relative",
882
+ display: "inline-block"
883
+ },
884
+ hint: {
885
+ position: "absolute",
886
+ top: "0",
887
+ left: "0",
888
+ borderColor: "transparent",
889
+ boxShadow: "none"
890
+ },
891
+ query: {
892
+ position: "relative",
893
+ verticalAlign: "top",
894
+ backgroundColor: "transparent"
895
+ },
896
+ dropdown: {
897
+ position: "absolute",
898
+ top: "100%",
899
+ left: "0",
900
+ zIndex: "100",
901
+ display: "none"
902
+ }
903
+ };
904
+ if (utils.isMsie()) {
905
+ utils.mixin(css.query, {
906
+ backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
907
+ });
908
+ }
909
+ if (utils.isMsie() && utils.isMsie() <= 7) {
910
+ utils.mixin(css.wrapper, {
911
+ display: "inline",
912
+ zoom: "1"
913
+ });
914
+ utils.mixin(css.query, {
915
+ marginTop: "-1px"
916
+ });
917
+ }
918
+ function TypeaheadView(o) {
919
+ var $menu, $input, $hint;
920
+ utils.bindAll(this);
921
+ this.$node = buildDomStructure(o.input);
922
+ this.datasets = o.datasets;
923
+ this.dir = null;
924
+ this.eventBus = o.eventBus;
925
+ $menu = this.$node.find(".tt-dropdown-menu");
926
+ $input = this.$node.find(".tt-query");
927
+ $hint = this.$node.find(".tt-hint");
928
+ this.dropdownView = new DropdownView({
929
+ menu: $menu
930
+ }).on("suggestionSelected", this._handleSelection).on("cursorMoved", this._clearHint).on("cursorMoved", this._setInputValueToSuggestionUnderCursor).on("cursorRemoved", this._setInputValueToQuery).on("cursorRemoved", this._updateHint).on("suggestionsRendered", this._updateHint).on("opened", this._updateHint).on("closed", this._clearHint).on("opened closed", this._propagateEvent);
931
+ this.inputView = new InputView({
932
+ input: $input,
933
+ hint: $hint
934
+ }).on("focused", this._openDropdown).on("blured", this._closeDropdown).on("blured", this._setInputValueToQuery).on("enterKeyed tabKeyed", this._handleSelection).on("queryChanged", this._clearHint).on("queryChanged", this._clearSuggestions).on("queryChanged", this._getSuggestions).on("whitespaceChanged", this._updateHint).on("queryChanged whitespaceChanged", this._openDropdown).on("queryChanged whitespaceChanged", this._setLanguageDirection).on("escKeyed", this._closeDropdown).on("escKeyed", this._setInputValueToQuery).on("tabKeyed upKeyed downKeyed", this._managePreventDefault).on("upKeyed downKeyed", this._moveDropdownCursor).on("upKeyed downKeyed", this._openDropdown).on("tabKeyed leftKeyed rightKeyed", this._autocomplete);
935
+ }
936
+
937
+ utils.mixin(TypeaheadView.prototype, EventTarget, {
938
+ _managePreventDefault: function (e) {
939
+ var $e = e.data, hint, inputValue, preventDefault = false;
940
+ switch (e.type) {
941
+ case "tabKeyed":
942
+ hint = this.inputView.getHintValue();
943
+ inputValue = this.inputView.getInputValue();
944
+ preventDefault = hint && hint !== inputValue;
945
+ break;
946
+
947
+ case "upKeyed":
948
+ case "downKeyed":
949
+ preventDefault = !$e.shiftKey && !$e.ctrlKey && !$e.metaKey;
950
+ break;
951
+ }
952
+ preventDefault && $e.preventDefault();
953
+ },
954
+ _setLanguageDirection: function () {
955
+ var dir = this.inputView.getLanguageDirection();
956
+ if (dir !== this.dir) {
957
+ this.dir = dir;
958
+ this.$node.css("direction", dir);
959
+ this.dropdownView.setLanguageDirection(dir);
960
+ }
961
+ },
962
+ _updateHint: function () {
963
+ var suggestion = this.dropdownView.getFirstSuggestion(), hint = suggestion ? suggestion.value : null, dropdownIsVisible = this.dropdownView.isVisible(), inputHasOverflow = this.inputView.isOverflow(), inputValue, query, escapedQuery, beginsWithQuery, match;
964
+ if (hint && dropdownIsVisible && !inputHasOverflow) {
965
+ inputValue = this.inputView.getInputValue();
966
+ query = inputValue.replace(/\s{2,}/g, " ").replace(/^\s+/g, "");
967
+ escapedQuery = utils.escapeRegExChars(query);
968
+ beginsWithQuery = new RegExp("^(?:" + escapedQuery + ")(.*$)", "i");
969
+ match = beginsWithQuery.exec(hint);
970
+ this.inputView.setHintValue(inputValue + (match ? match[1] : ""));
971
+ }
972
+ },
973
+ _clearHint: function () {
974
+ this.inputView.setHintValue("");
975
+ },
976
+ _clearSuggestions: function () {
977
+ this.dropdownView.clearSuggestions();
978
+ },
979
+ _setInputValueToQuery: function () {
980
+ this.inputView.setInputValue(this.inputView.getQuery());
981
+ },
982
+ _setInputValueToSuggestionUnderCursor: function (e) {
983
+ var suggestion = e.data;
984
+ this.inputView.setInputValue(suggestion.value, true);
985
+ },
986
+ _openDropdown: function () {
987
+ this.dropdownView.open();
988
+ },
989
+ _closeDropdown: function (e) {
990
+ this.dropdownView[e.type === "blured" ? "closeUnlessMouseIsOverDropdown" : "close"]();
991
+ },
992
+ _moveDropdownCursor: function (e) {
993
+ var $e = e.data;
994
+ if (!$e.shiftKey && !$e.ctrlKey && !$e.metaKey) {
995
+ this.dropdownView[e.type === "upKeyed" ? "moveCursorUp" : "moveCursorDown"]();
996
+ }
997
+ },
998
+ _handleSelection: function (e) {
999
+ var byClick = e.type === "suggestionSelected", suggestion = byClick ? e.data : this.dropdownView.getSuggestionUnderCursor();
1000
+ if (suggestion) {
1001
+ this.inputView.setInputValue(suggestion.value);
1002
+ byClick ? this.inputView.focus() : e.data.preventDefault();
1003
+ byClick && utils.isMsie() ? utils.defer(this.dropdownView.close) : this.dropdownView.close();
1004
+ this.eventBus.trigger("selected", suggestion.datum, suggestion.dataset);
1005
+ }
1006
+ },
1007
+ _getSuggestions: function () {
1008
+ var that = this, query = this.inputView.getQuery();
1009
+ if (utils.isBlankString(query)) {
1010
+ return;
1011
+ }
1012
+ utils.each(this.datasets, function (i, dataset) {
1013
+ dataset.getSuggestions(query, function (suggestions) {
1014
+ if (query === that.inputView.getQuery()) {
1015
+ that.dropdownView.renderSuggestions(dataset, suggestions);
1016
+ }
1017
+ });
1018
+ });
1019
+ },
1020
+ _autocomplete: function (e) {
1021
+ var isCursorAtEnd, ignoreEvent, query, hint, suggestion;
1022
+ if (e.type === "rightKeyed" || e.type === "leftKeyed") {
1023
+ isCursorAtEnd = this.inputView.isCursorAtEnd();
1024
+ ignoreEvent = this.inputView.getLanguageDirection() === "ltr" ? e.type === "leftKeyed" : e.type === "rightKeyed";
1025
+ if (!isCursorAtEnd || ignoreEvent) {
1026
+ return;
1027
+ }
1028
+ }
1029
+ query = this.inputView.getQuery();
1030
+ hint = this.inputView.getHintValue();
1031
+ if (hint !== "" && query !== hint) {
1032
+ suggestion = this.dropdownView.getFirstSuggestion();
1033
+ this.inputView.setInputValue(suggestion.value);
1034
+ this.eventBus.trigger("autocompleted", suggestion.datum, suggestion.dataset);
1035
+ }
1036
+ },
1037
+ _propagateEvent: function (e) {
1038
+ this.eventBus.trigger(e.type);
1039
+ },
1040
+ destroy: function () {
1041
+ this.inputView.destroy();
1042
+ this.dropdownView.destroy();
1043
+ destroyDomStructure(this.$node);
1044
+ this.$node = null;
1045
+ },
1046
+ setQuery: function (query) {
1047
+ this.inputView.setQuery(query);
1048
+ this.inputView.setInputValue(query);
1049
+ this._clearHint();
1050
+ this._clearSuggestions();
1051
+ this._getSuggestions();
1052
+ }
1053
+ });
1054
+ return TypeaheadView;
1055
+ function buildDomStructure(input) {
1056
+ var $wrapper = $(html.wrapper), $dropdown = $(html.dropdown), $input = $(input), $hint = $(html.hint);
1057
+ $wrapper = $wrapper.css(css.wrapper);
1058
+ $dropdown = $dropdown.css(css.dropdown);
1059
+ $hint.css(css.hint).css({
1060
+ backgroundAttachment: $input.css("background-attachment"),
1061
+ backgroundClip: $input.css("background-clip"),
1062
+ backgroundColor: $input.css("background-color"),
1063
+ backgroundImage: $input.css("background-image"),
1064
+ backgroundOrigin: $input.css("background-origin"),
1065
+ backgroundPosition: $input.css("background-position"),
1066
+ backgroundRepeat: $input.css("background-repeat"),
1067
+ backgroundSize: $input.css("background-size")
1068
+ });
1069
+ $input.data("ttAttrs", {
1070
+ dir: $input.attr("dir"),
1071
+ autocomplete: $input.attr("autocomplete"),
1072
+ spellcheck: $input.attr("spellcheck"),
1073
+ style: $input.attr("style")
1074
+ });
1075
+ $input.addClass("tt-query").attr({
1076
+ autocomplete: "off",
1077
+ spellcheck: false
1078
+ }).css(css.query);
1079
+ try {
1080
+ !$input.attr("dir") && $input.attr("dir", "auto");
1081
+ } catch (e) {
1082
+ }
1083
+ return $input.wrap($wrapper).parent().prepend($hint).append($dropdown);
1084
+ }
1085
+
1086
+ function destroyDomStructure($node) {
1087
+ var $input = $node.find(".tt-query");
1088
+ utils.each($input.data("ttAttrs"), function (key, val) {
1089
+ utils.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
1090
+ });
1091
+ $input.detach().removeData("ttAttrs").removeClass("tt-query").insertAfter($node);
1092
+ $node.remove();
1093
+ }
1094
+ }();
1095
+ (function () {
1096
+ var cache = {}, viewKey = "ttView", methods;
1097
+ methods = {
1098
+ initialize: function (datasetDefs) {
1099
+ var datasets;
1100
+ datasetDefs = utils.isArray(datasetDefs) ? datasetDefs : [ datasetDefs ];
1101
+ if (datasetDefs.length === 0) {
1102
+ $.error("no datasets provided");
1103
+ }
1104
+ datasets = utils.map(datasetDefs, function (o) {
1105
+ var dataset = cache[o.name] ? cache[o.name] : new Dataset(o);
1106
+ if (o.name) {
1107
+ cache[o.name] = dataset;
1108
+ }
1109
+ return dataset;
1110
+ });
1111
+ return this.each(initialize);
1112
+ function initialize() {
1113
+ var $input = $(this), deferreds, eventBus = new EventBus({
1114
+ el: $input
1115
+ });
1116
+ deferreds = utils.map(datasets, function (dataset) {
1117
+ return dataset.initialize();
1118
+ });
1119
+ $input.data(viewKey, new TypeaheadView({
1120
+ input: $input,
1121
+ eventBus: eventBus = new EventBus({
1122
+ el: $input
1123
+ }),
1124
+ datasets: datasets
1125
+ }));
1126
+ $.when.apply($, deferreds).always(function () {
1127
+ utils.defer(function () {
1128
+ eventBus.trigger("initialized");
1129
+ });
1130
+ });
1131
+ }
1132
+ },
1133
+ destroy: function () {
1134
+ return this.each(destroy);
1135
+ function destroy() {
1136
+ var $this = $(this), view = $this.data(viewKey);
1137
+ if (view) {
1138
+ view.destroy();
1139
+ $this.removeData(viewKey);
1140
+ }
1141
+ }
1142
+ },
1143
+ setQuery: function (query) {
1144
+ return this.each(setQuery);
1145
+ function setQuery() {
1146
+ var view = $(this).data(viewKey);
1147
+ view && view.setQuery(query);
1148
+ }
1149
+ }
1150
+ };
1151
+ jQuery.fn.typeahead = function (method) {
1152
+ if (methods[method]) {
1153
+ return methods[method].apply(this, [].slice.call(arguments, 1));
1154
+ } else {
1155
+ return methods.initialize.apply(this, arguments);
1156
+ }
1157
+ };
1158
+ })();
1159
+ })(window.jQuery);