discerner 1.1.18
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +97 -0
- data/Rakefile +29 -0
- data/app/assets/images/discerner/add.png +0 -0
- data/app/assets/images/discerner/ajax-loader.gif +0 -0
- data/app/assets/images/discerner/bar.gif +0 -0
- data/app/assets/images/discerner/bullet_arrow_down.png +0 -0
- data/app/assets/images/discerner/bullet_arrow_up.png +0 -0
- data/app/assets/images/discerner/cog.png +0 -0
- data/app/assets/images/discerner/delete.png +0 -0
- data/app/assets/images/discerner/edit.png +0 -0
- data/app/assets/images/discerner/excel.png +0 -0
- data/app/assets/images/discerner/greencheck.gif +0 -0
- data/app/assets/images/discerner/rails.png +0 -0
- data/app/assets/images/discerner/show.png +0 -0
- data/app/assets/images/discerner/switch_minus.gif +0 -0
- data/app/assets/images/discerner/switch_plus.gif +0 -0
- data/app/assets/javascripts/discerner/application.js +20 -0
- data/app/assets/javascripts/discerner/combobox.js +301 -0
- data/app/assets/javascripts/discerner/discerner.js +19 -0
- data/app/assets/javascripts/discerner/export_parameters.js +13 -0
- data/app/assets/javascripts/discerner/jquery/jquery.blockUI.js +576 -0
- data/app/assets/javascripts/discerner/jquery/jquery.form.js +1074 -0
- data/app/assets/javascripts/discerner/nested_attributes.js +69 -0
- data/app/assets/javascripts/discerner/search_combinations.js +49 -0
- data/app/assets/javascripts/discerner/search_parameter.js +131 -0
- data/app/assets/javascripts/discerner/search_parameter_value.js +172 -0
- data/app/assets/javascripts/discerner/searches.js +93 -0
- data/app/assets/javascripts/discerner/url.js +42 -0
- data/app/assets/stylesheets/discerner/application.css +16 -0
- data/app/assets/stylesheets/discerner/buttons.sass +13 -0
- data/app/assets/stylesheets/discerner/categorized_autocompleter.sass +53 -0
- data/app/assets/stylesheets/discerner/discerner.sass +51 -0
- data/app/assets/stylesheets/discerner/export_parameters.sass +43 -0
- data/app/assets/stylesheets/discerner/links.sass +29 -0
- data/app/assets/stylesheets/discerner/searches.sass +205 -0
- data/app/assets/stylesheets/discerner/tables.sass +32 -0
- data/app/controllers/discerner/application_controller.rb +2 -0
- data/app/controllers/discerner/export_parameters_controller.rb +5 -0
- data/app/controllers/discerner/parameters_controller.rb +5 -0
- data/app/controllers/discerner/searches_controller.rb +5 -0
- data/app/helpers/discerner/application_helper.rb +4 -0
- data/app/helpers/discerner/parameters_helper.rb +5 -0
- data/app/helpers/discerner/searches_helper.rb +5 -0
- data/app/models/discerner/dictionary.rb +5 -0
- data/app/models/discerner/export_parameter.rb +5 -0
- data/app/models/discerner/operator.rb +5 -0
- data/app/models/discerner/parameter.rb +5 -0
- data/app/models/discerner/parameter_category.rb +5 -0
- data/app/models/discerner/parameter_type.rb +5 -0
- data/app/models/discerner/parameter_value.rb +5 -0
- data/app/models/discerner/parameter_value_categorization.rb +5 -0
- data/app/models/discerner/parameter_value_category.rb +5 -0
- data/app/models/discerner/search.rb +5 -0
- data/app/models/discerner/search_combination.rb +5 -0
- data/app/models/discerner/search_parameter.rb +5 -0
- data/app/models/discerner/search_parameter_value.rb +5 -0
- data/app/views/discerner/export_parameters/index.html.haml +55 -0
- data/app/views/discerner/parameters/_values_autocompleter.html.haml +49 -0
- data/app/views/discerner/parameters/values.html.haml +1 -0
- data/app/views/discerner/searches/_form.html.haml +21 -0
- data/app/views/discerner/searches/_form_combined_searches.html.haml +32 -0
- data/app/views/discerner/searches/_form_controls.html.haml +8 -0
- data/app/views/discerner/searches/_form_header.html.haml +39 -0
- data/app/views/discerner/searches/_form_search_parameters.html.haml +28 -0
- data/app/views/discerner/searches/_list.html.haml +17 -0
- data/app/views/discerner/searches/_search_combination_fields.html.haml +22 -0
- data/app/views/discerner/searches/_search_parameter_fields.html.haml +48 -0
- data/app/views/discerner/searches/_search_parameter_value_fields.html.haml +62 -0
- data/app/views/discerner/searches/_summary.html.haml +25 -0
- data/app/views/discerner/searches/edit.html.haml +8 -0
- data/app/views/discerner/searches/index.html.haml +13 -0
- data/app/views/discerner/searches/index.js.haml +1 -0
- data/app/views/discerner/searches/new.html.haml +3 -0
- data/app/views/discerner/searches/rename.html.haml +6 -0
- data/app/views/discerner/searches/update.js.haml +7 -0
- data/app/views/discerner/shared/_categorized_autocompleter_items.html.haml +15 -0
- data/app/views/discerner/shared/_error_messages.html.haml +5 -0
- data/app/views/layouts/discerner/searches.html.erb +17 -0
- data/config/cucumber.yml +8 -0
- data/config/routes.rb +17 -0
- data/db/migrate/20121004040716_create_discerner_dictionaries.rb +11 -0
- data/db/migrate/20121004153043_create_discerner_parameter_categories.rb +12 -0
- data/db/migrate/20121005194843_create_discerner_parameter_types.rb +11 -0
- data/db/migrate/20121005203223_create_discerner_parameters.rb +14 -0
- data/db/migrate/20121008154855_create_discerner_operators.rb +13 -0
- data/db/migrate/20121008160313_create_discerner_operators_parameter_types.rb +8 -0
- data/db/migrate/20121008161455_create_discerner_parameter_values.rb +13 -0
- data/db/migrate/20121008180829_create_discerner_searches.rb +11 -0
- data/db/migrate/20121008182443_create_discerner_search_parameters.rb +11 -0
- data/db/migrate/20121011205130_create_discerner_search_parameter_values.rb +15 -0
- data/db/migrate/20121211213215_add_dictionary_id_to_discerner_searches.rb +5 -0
- data/db/migrate/20130205193602_create_discerner_search_combinations.rb +12 -0
- data/db/migrate/20130211230636_create_discerner_export_parameters.rb +9 -0
- data/db/migrate/20130213185818_add_search_columns_to_discerner_parameters.rb +38 -0
- data/db/migrate/20130213205255_rename_database_name_to_search_value_in_discerner_parameter_values.rb +5 -0
- data/db/migrate/20130215165416_add_searchable_to_discerner_parameters.rb +5 -0
- data/db/migrate/20130218230257_add_exclusive_to_discerner_parameters.rb +5 -0
- data/db/migrate/20130220163015_replace_integer_type_with_numeric.rb +22 -0
- data/db/migrate/20130221172826_add_unique_identifier_to_discerner_parameters.rb +5 -0
- data/db/migrate/20130222052924_change_search_attribute_to_method.rb +29 -0
- data/db/migrate/20130222070959_add_export_columns_to_discerner_parameters.rb +6 -0
- data/db/migrate/20130227031747_add_unique_identifier_to_discerner_operators.rb +16 -0
- data/db/migrate/20130306015019_change_discerner_parameter_values_name.rb +9 -0
- data/db/migrate/20130306212430_add_deleted_at_to_discerner_search_parameters.rb +5 -0
- data/db/migrate/20130306212504_add_deleted_at_to_discerner_search_parameter_values.rb +5 -0
- data/db/migrate/20130306212527_add_deleted_at_to_discerner_search_combinations.rb +5 -0
- data/db/migrate/20130306212818_add_deleted_at_to_discerner_export_parameters.rb +5 -0
- data/db/migrate/20130311190717_add_operator_type_to_discerner_operators.rb +5 -0
- data/db/migrate/20131212175110_remove_extra_search_parameter_values.rb +10 -0
- data/db/migrate/20140204170625_create_discerner_parameter_value_categories.rb +16 -0
- data/db/migrate/20140204170646_create_discerner_parameter_value_categorizations.rb +12 -0
- data/db/migrate/20140227191827_remove_blank_parameter_values_from_export_parameters.rb +10 -0
- data/db/seeds.rb +0 -0
- data/lib/discerner/engine.rb +16 -0
- data/lib/discerner/methods/controllers/export_parameters_controller.rb +38 -0
- data/lib/discerner/methods/controllers/parameters_controller.rb +30 -0
- data/lib/discerner/methods/controllers/searches_controller.rb +204 -0
- data/lib/discerner/methods/helpers/searches_helper.rb +145 -0
- data/lib/discerner/methods/models/dictionary.rb +54 -0
- data/lib/discerner/methods/models/export_parameter.rb +35 -0
- data/lib/discerner/methods/models/operator.rb +42 -0
- data/lib/discerner/methods/models/parameter.rb +90 -0
- data/lib/discerner/methods/models/parameter_category.rb +60 -0
- data/lib/discerner/methods/models/parameter_type.rb +33 -0
- data/lib/discerner/methods/models/parameter_value.rb +87 -0
- data/lib/discerner/methods/models/parameter_value_categorization.rb +21 -0
- data/lib/discerner/methods/models/parameter_value_category.rb +45 -0
- data/lib/discerner/methods/models/search.rb +147 -0
- data/lib/discerner/methods/models/search_combination.rb +50 -0
- data/lib/discerner/methods/models/search_parameter.rb +128 -0
- data/lib/discerner/methods/models/search_parameter_value.rb +130 -0
- data/lib/discerner/methods/models/soft_delete.rb +35 -0
- data/lib/discerner/methods/models/warning.rb +15 -0
- data/lib/discerner/parser.rb +497 -0
- data/lib/discerner/version.rb +3 -0
- data/lib/discerner.rb +4 -0
- data/lib/generators/discerner/dictionary/dictionary_generator.rb +38 -0
- data/lib/generators/discerner/dictionary/templates/model.rb +15 -0
- data/lib/generators/discerner/dictionary/templates/show.xls.erb +37 -0
- data/lib/generators/discerner/dictionary/templates/view.html.haml +2 -0
- data/lib/generators/discerner/install/install_generator.rb +153 -0
- data/lib/generators/discerner/install/templates/controllers/export_parameters_controller.rb +20 -0
- data/lib/generators/discerner/install/templates/controllers/parameters_controller.rb +15 -0
- data/lib/generators/discerner/install/templates/controllers/searches_controller.rb +39 -0
- data/lib/generators/discerner/install/templates/dictionaries.yml +236 -0
- data/lib/generators/discerner/install/templates/helpers/searches_helper.rb +9 -0
- data/lib/generators/discerner/install/templates/models/book.rb +15 -0
- data/lib/generators/discerner/install/templates/models/dictionary.rb +9 -0
- data/lib/generators/discerner/install/templates/models/export_parameter.rb +9 -0
- data/lib/generators/discerner/install/templates/models/operator.rb +9 -0
- data/lib/generators/discerner/install/templates/models/parameter.rb +10 -0
- data/lib/generators/discerner/install/templates/models/parameter_category.rb +9 -0
- data/lib/generators/discerner/install/templates/models/parameter_type.rb +9 -0
- data/lib/generators/discerner/install/templates/models/parameter_value.rb +9 -0
- data/lib/generators/discerner/install/templates/models/parameter_value_categorization.rb +9 -0
- data/lib/generators/discerner/install/templates/models/parameter_value_category.rb +9 -0
- data/lib/generators/discerner/install/templates/models/search.rb +9 -0
- data/lib/generators/discerner/install/templates/models/search_combination.rb +9 -0
- data/lib/generators/discerner/install/templates/models/search_parameter.rb +9 -0
- data/lib/generators/discerner/install/templates/models/search_parameter_value.rb +9 -0
- data/lib/generators/discerner/install/templates/views/layouts/searches.html.erb +17 -0
- data/lib/setup/operators.yml +91 -0
- data/lib/tasks/cucumber.rake +65 -0
- data/lib/tasks/discerner_tasks.rake +30 -0
- metadata +531 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: ecb4c17f2e220beb34f78081d0343faed81e933d
|
|
4
|
+
data.tar.gz: e9a87d805da56897978848a1b18a222ade053255
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7bb80f4d67f66ef9de64556061661afc6b33c1f3f8864d1ee7bd52b138e34e897ff3e64ef41bec204a1b39590bb818384d43d33a5a73284ccaf0d6252f2c0163
|
|
7
|
+
data.tar.gz: 00a4af1d6d7021621496f8fb684db7244b4f1ca0ee60914de05a4ad68524c1af8573ba4a56ef7c18f88b05b1200259b601dc852e4828d01a9f77f904a06218ce
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2012 YOURNAME
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Discerner
|
|
2
|
+
|
|
3
|
+
Discerner is an engine for Rails that provides basic search UI, search reqults export UI and allows to configure available search parameters/values. Discerner is not aimed to be a SQL-generator, but it allows the host application to access stored search conditions and provide search results.
|
|
4
|
+
|
|
5
|
+
Reader's note: this README uses [YARD][] markup to provide links to
|
|
6
|
+
Discerner's API documentation. If you aren't already, consider reading it
|
|
7
|
+
on [rubydoc.info][] so that the links will be followable.
|
|
8
|
+
|
|
9
|
+
[YARD]: http://yardoc.org/
|
|
10
|
+
[rubydoc.info]: http://rubydoc.info/github/NUBIC/discerner/master/file/README.md
|
|
11
|
+
|
|
12
|
+
# Requirements
|
|
13
|
+
|
|
14
|
+
This code has been run and tested on Ruby 1.9. and Ruby 2.1
|
|
15
|
+
|
|
16
|
+
# Dependencies
|
|
17
|
+
|
|
18
|
+
* haml
|
|
19
|
+
* sass
|
|
20
|
+
* jquery-rails
|
|
21
|
+
* jquery-ui-rails
|
|
22
|
+
|
|
23
|
+
# Installation
|
|
24
|
+
|
|
25
|
+
## Install gem with Bundler
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
gem 'discerner'
|
|
29
|
+
bundle install
|
|
30
|
+
```
|
|
31
|
+
## Run the installer
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
rails generate discerner:install
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
By default, Discerner installer performs following tasks:
|
|
38
|
+
|
|
39
|
+
* it copies Discerner's migrations into db/migrate and runs migrations
|
|
40
|
+
* it sets up default Discerner operators. As of now, default operators cannot be changed.
|
|
41
|
+
* it prompts for current_user helper name and inserts `discerner_user` method into the application controller. This allows Discerner to attibure created searches to the current user.
|
|
42
|
+
* it adds discerner helpers used for configuring dicerner functionality into application helper. This will be changed in the future.
|
|
43
|
+
* show_discerner_results? - helper used to determine if search results should be displayed.
|
|
44
|
+
* export_discerner_results? - helper used to determine if search results should be exportable.
|
|
45
|
+
* enable_combined_searches? - helper used to determine if search interface should allow to combine searches
|
|
46
|
+
* it mounts Discerner::Engine
|
|
47
|
+
* it copies sample search dictionary into lib/setup
|
|
48
|
+
|
|
49
|
+
Discerner installer accepts following parameters:
|
|
50
|
+
|
|
51
|
+
* --no-migrate - prevent installer from running migrations. If this flag is set, Discerner operators would have to be loaded manually using **rake discerner:setup:operators**
|
|
52
|
+
* --current-user-helper - allows to specify current user method name
|
|
53
|
+
* --customize-controllers - copy Discerner controllers into application, so they can be customized
|
|
54
|
+
* --customize-models - copy Discerner models into application, so they can be customized
|
|
55
|
+
* --customize-helpers - copy Discerner helpers into application, so they can be customized
|
|
56
|
+
* --customize-layout - copy Discerner layout into application, so it can be customized
|
|
57
|
+
* --customize-all - copy Discerner controllers, models, helpers, and layout into application, so they can be customized
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# Usage
|
|
61
|
+
## Setting up dictionaries
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
rails generate discerner:dictionary [FILENAME]
|
|
65
|
+
```
|
|
66
|
+
Discerner uses dictionaries to define parameters and values that can be used for constructing searches. Discerner dictionary generator performs following tasks:
|
|
67
|
+
|
|
68
|
+
* it parses provided file and sets up or updates corresponding search dictionary, its parameter categories, parameters and parameter values
|
|
69
|
+
* it creates a model for each specified dictionary that is expected to implement "search" and "export" methods.
|
|
70
|
+
* it generates template views for search results and export.
|
|
71
|
+
|
|
72
|
+
Discerner dictionary generator accepts following parameters:
|
|
73
|
+
|
|
74
|
+
* --no-load - skip dictionary generation/update
|
|
75
|
+
* --no-models - skip models generation
|
|
76
|
+
* --no-views - skip views generation
|
|
77
|
+
|
|
78
|
+
Installer adds a sample dictionary than can be used as a template anr/or can be parsed and used to explore Discerner Search UI:
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
rails generate discerner:dictionary lib/setup/dictionaries.yml
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Updating dictionaries
|
|
85
|
+
|
|
86
|
+
In most cases, dictionary generator needs to be run only once per dictionary. Dictionary updates, excluding name change, should be handled by re-parcing definition file with Discerner parser:
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
rails discerner:setup:dictionaries FILE=xxx
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Discerner parser processes YML definition file line by line, detecting and creating/updating dictionaries, parameter categories, parameters and parameter values. It runs in silent mode by default, --trace option can be used to make it verbose.
|
|
93
|
+
|
|
94
|
+
## User Interface
|
|
95
|
+
|
|
96
|
+
Index of all saved searches scoped by current user (if available) can be accessed from '/searches' route.
|
|
97
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
begin
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'cucumber/rake/task'
|
|
5
|
+
require 'rspec/core/rake_task'
|
|
6
|
+
require 'rubygems/package_task'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
gemspec = eval(File.read('discerner.gemspec'), binding, 'discerner.gemspec')
|
|
10
|
+
Gem::PackageTask.new(gemspec).define
|
|
11
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
|
12
|
+
$:.unshift File.join(File.dirname(__FILE__), 'spec','support')
|
|
13
|
+
load 'rails/tasks/engine.rake' if File.exists?(APP_RAKEFILE)
|
|
14
|
+
load 'lib/tasks/discerner_tasks.rake'
|
|
15
|
+
load 'test/lib/tasks/discerner_test_tasks.rake'
|
|
16
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
17
|
+
task :default => :spec
|
|
18
|
+
|
|
19
|
+
namespace :cucumber do
|
|
20
|
+
Cucumber::Rake::Task.new(:wip, 'Run features that are being worked on') do |t|
|
|
21
|
+
t.profile = 'wip'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
|
25
|
+
t.cucumber_opts = "features --format pretty"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
task :cucumber => 'cucumber:features'
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
+
// the compiled file.
|
|
9
|
+
//
|
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
|
12
|
+
//
|
|
13
|
+
//= require jquery
|
|
14
|
+
//= require jquery_ujs
|
|
15
|
+
//= require jquery.ui.widget
|
|
16
|
+
//= require jquery.ui.autocomplete
|
|
17
|
+
//= require jquery.ui.datepicker
|
|
18
|
+
//= require jquery.ui.button
|
|
19
|
+
//= require discerner/jquery/jquery.blockUI
|
|
20
|
+
//= require_tree .
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
// courtesy of https://github.com/garyzhu/jquery.ui.combobox/blob/master/jquery.ui.combobox.js
|
|
2
|
+
// more courtesy https://github.com/garyzhu/jquery.ui.combobox/commit/65433ee5af6e9b87b594e5bb5c4b16b030806e24
|
|
3
|
+
/*
|
|
4
|
+
* Combobox widget. This widget extends the jQuery UI autocomplete widget.
|
|
5
|
+
*
|
|
6
|
+
* usage: $("#select_element").combox();
|
|
7
|
+
* $("#input_element").combox( {minLength: 2, delay: 200, source: anArray} );
|
|
8
|
+
*
|
|
9
|
+
* For select elements, the source list is automatically generated from the option elements.
|
|
10
|
+
*
|
|
11
|
+
* To configure a label decorator (i.e. "[admin]"), set the decoratorField when you
|
|
12
|
+
* initialize the combobox. The field corresponds to the object field, if the source is
|
|
13
|
+
* an array of objects. Or it's the attribute in <option> if the source is a select drop-down menu.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
(function($) {
|
|
17
|
+
$.widget("ui.combobox", $.ui.autocomplete, {
|
|
18
|
+
options: {
|
|
19
|
+
/* override default values here */
|
|
20
|
+
minLength: 2,
|
|
21
|
+
/* the argument to pass to ajax to get the complete list */
|
|
22
|
+
ajaxGetAll: {
|
|
23
|
+
get: "all"
|
|
24
|
+
},
|
|
25
|
+
/* you can specify the field to use as a label decorator,
|
|
26
|
+
* it's appended to the end of the label and is excluded
|
|
27
|
+
* from pattern matching.
|
|
28
|
+
*/
|
|
29
|
+
decoratorField: null
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
_create: function() {
|
|
33
|
+
if (this.element.is("SELECT")) {
|
|
34
|
+
this._selectInit();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
$.ui.autocomplete.prototype._create.call(this);
|
|
38
|
+
var input = this.element,
|
|
39
|
+
watermark = ('Search for ' + this.options.watermark); // custom watermark
|
|
40
|
+
|
|
41
|
+
// custom part - setting and removing watermark
|
|
42
|
+
function clearWatermark () {
|
|
43
|
+
if (input.val() === watermark) {
|
|
44
|
+
input.val('');
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
function setWatermark () {
|
|
49
|
+
input.val(watermark);
|
|
50
|
+
input.bind('focus', clearWatermark);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
if (input.not("SELECT")) {
|
|
54
|
+
input.blur( function (e) {
|
|
55
|
+
if ($(this).val() === '') {
|
|
56
|
+
input.val(watermark);
|
|
57
|
+
}
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
return false;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
$(document).ready(function () {
|
|
63
|
+
if ($(input).val() === '') {
|
|
64
|
+
setWatermark();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
// end of custom part
|
|
69
|
+
|
|
70
|
+
input.addClass("ui-widget ui-widget-content ui-corner-left").click(function() {
|
|
71
|
+
this.select();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
this.button = $("<button type='button'> </button>")
|
|
75
|
+
.attr("tabIndex", -1)
|
|
76
|
+
.attr("title", "Show All Items")
|
|
77
|
+
.insertAfter(input).button({
|
|
78
|
+
disabled: true,
|
|
79
|
+
// to be enabled when the menu is ready.
|
|
80
|
+
icons: {
|
|
81
|
+
primary: "ui-icon-triangle-1-s"
|
|
82
|
+
},
|
|
83
|
+
text: false
|
|
84
|
+
})
|
|
85
|
+
.removeClass("ui-corner-all")
|
|
86
|
+
.addClass("ui-corner-right ui-button-icon")
|
|
87
|
+
.click(function(event) {
|
|
88
|
+
// when user clicks the show all button, we display the cached full menu
|
|
89
|
+
var data = input.data("ui-combobox");
|
|
90
|
+
clearTimeout(data.closing);
|
|
91
|
+
if (!input.isFullMenu) {
|
|
92
|
+
data._swapMenu();
|
|
93
|
+
}
|
|
94
|
+
/* input/select that are initially hidden (display=none, i.e. second level menus),
|
|
95
|
+
will not have position cordinates until they are visible. */
|
|
96
|
+
input.combobox("widget").css("display", "block").position($.extend({
|
|
97
|
+
of: input
|
|
98
|
+
}, data.options.position));
|
|
99
|
+
input.focus();
|
|
100
|
+
data._trigger("open");
|
|
101
|
+
// containers such as jquery-ui dialog box will adjust it's zIndex to overlay above other elements.
|
|
102
|
+
// this becomes a problem if the combobox is inside of a dialog box, the full drop down will show
|
|
103
|
+
// under the dialog box.
|
|
104
|
+
if (input.combobox("widget").zIndex() <= input.parent().zIndex()) {
|
|
105
|
+
input.combobox("widget").zIndex(input.parent().zIndex() + 1);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
/* to better handle large lists, put in a queue and process sequentially */
|
|
110
|
+
$(document).queue(function() {
|
|
111
|
+
var data = input.data("ui-combobox");
|
|
112
|
+
if ($.isArray(data.options.source)) {
|
|
113
|
+
$.ui.combobox.prototype._renderFullMenu.call(data, data.options.source);
|
|
114
|
+
} else if (typeof data.options.source === "string") {
|
|
115
|
+
$.getJSON(data.options.source, data.options.ajaxGetAll, function(source) {
|
|
116
|
+
$.ui.combobox.prototype._renderFullMenu.call(data, source);
|
|
117
|
+
});
|
|
118
|
+
} else {
|
|
119
|
+
$.ui.combobox.prototype._renderFullMenu.call(data, data.source());
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
/* initialize the full list of items, this menu will be reused whenever the user clicks the show all button */
|
|
125
|
+
_renderFullMenu: function(source) {
|
|
126
|
+
var self = this,
|
|
127
|
+
input = this.element,
|
|
128
|
+
ul = input.data("ui-combobox").menu.element,
|
|
129
|
+
lis = [];
|
|
130
|
+
source = this._normalize(source);
|
|
131
|
+
input.data("ui-combobox").menuAll = input.data("ui-combobox").menu.element.clone(true).appendTo("body")[0];
|
|
132
|
+
for (var i = 0; i < source.length; i++) {
|
|
133
|
+
var item = source[i],
|
|
134
|
+
label = item.label;
|
|
135
|
+
if (this.options.decoratorField != null) {
|
|
136
|
+
var d = item[this.options.decoratorField] || (item.option && $(item.option).attr(this.options.decoratorField));
|
|
137
|
+
if (d != undefined) label = label + " " + d;
|
|
138
|
+
}
|
|
139
|
+
lis[i] = "<li class=\"ui-menu-item\" role=\"menuitem\"><a class=\"ui-corner-all\" tabindex=\"-1\">" + label + "</a></li>";
|
|
140
|
+
}
|
|
141
|
+
ul[0].innerHTML = lis.join("");
|
|
142
|
+
this._resizeMenu();
|
|
143
|
+
|
|
144
|
+
var items = $("li", ul).on("mouseover", "mouseout", function(event) {
|
|
145
|
+
if (event.type == "mouseover") {
|
|
146
|
+
self.menu.focus(event, $(this));
|
|
147
|
+
} else {
|
|
148
|
+
self.menu.blur();
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
for (var i = 0; i < items.length; i++) {
|
|
152
|
+
$(items[i]).data("ui-autocomplete-item", source[i]);
|
|
153
|
+
}
|
|
154
|
+
input.isFullMenu = true;
|
|
155
|
+
this._swapMenu()
|
|
156
|
+
// full menu has been rendered, now we can enable the show all button.
|
|
157
|
+
self.button.button("enable");
|
|
158
|
+
setTimeout(function() {
|
|
159
|
+
$(document).dequeue();
|
|
160
|
+
}, 0);
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
/* overwrite. make the matching string bold and added label decorator */
|
|
164
|
+
_renderItem: function(ul, item) {
|
|
165
|
+
var label = item.label.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(this.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
|
|
166
|
+
if (this.options.decoratorField != null) {
|
|
167
|
+
var d = item[this.options.decoratorField] || (item.option && $(item.option).attr(this.options.decoratorField));
|
|
168
|
+
if (d != undefined) {
|
|
169
|
+
label = label + " " + d;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return $("<li></li>")
|
|
173
|
+
.data("ui-autocomplete-item", item)
|
|
174
|
+
.append("<a>" + label + "</a>")
|
|
175
|
+
.appendTo(ul);
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
close: function() {
|
|
179
|
+
if (this.element.isFullMenu) {
|
|
180
|
+
this._swapMenu();
|
|
181
|
+
}
|
|
182
|
+
// super()
|
|
183
|
+
$.ui.autocomplete.prototype.close.call(this);
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
/* overwrite. to cleanup additional stuff that was added */
|
|
187
|
+
destroy: function() {
|
|
188
|
+
if (this.element.is("SELECT")) {
|
|
189
|
+
this.input.removeData("ui-combobox", "menuAll");
|
|
190
|
+
this.input.remove();
|
|
191
|
+
this.element.removeData().show();
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
// super()
|
|
195
|
+
$.ui.autocomplete.prototype.destroy.call(this);
|
|
196
|
+
// clean up new stuff
|
|
197
|
+
this.element.removeClass("ui-widget ui-widget-content ui-corner-left");
|
|
198
|
+
this.button.remove();
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
/* overwrite. to swap out and preserve the full menu */
|
|
202
|
+
search: function(value, event) {
|
|
203
|
+
var input = this.element;
|
|
204
|
+
if (input.isFullMenu) {
|
|
205
|
+
this._swapMenu();
|
|
206
|
+
}
|
|
207
|
+
// super()
|
|
208
|
+
$.ui.autocomplete.prototype.search.call(this, value, event);
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
_change: function(event) {
|
|
212
|
+
if (!this.selectedItem) {
|
|
213
|
+
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(this.element.val()) + "$", "i"),
|
|
214
|
+
match = $.grep(this.options.source, function(value) {
|
|
215
|
+
return matcher.test(value.label);
|
|
216
|
+
});
|
|
217
|
+
if (match.length) {
|
|
218
|
+
if (match[0].option != undefined) match[0].option.selected = true;
|
|
219
|
+
} else {
|
|
220
|
+
// remove invalid value, as it didn't match anything
|
|
221
|
+
if (this.options.selectElement) {
|
|
222
|
+
var firstItem = this.options.selectElement.children("option:first");
|
|
223
|
+
this.element.val(firstItem.text());
|
|
224
|
+
firstItem.prop("selected", true);
|
|
225
|
+
} else {
|
|
226
|
+
this.element.val("");
|
|
227
|
+
}
|
|
228
|
+
$(event.target).data("ui-combobox").previous = null; // this will force a change event
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// super()
|
|
232
|
+
$.ui.autocomplete.prototype._change.call(this, event);
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
_swapMenu: function() {
|
|
236
|
+
var input = this.element,
|
|
237
|
+
data = input.data("ui-combobox"),
|
|
238
|
+
tmp = data.menuAll;
|
|
239
|
+
data.menuAll = data.menu.element.hide()[0];
|
|
240
|
+
data.menu.element[0] = tmp;
|
|
241
|
+
input.isFullMenu = !input.isFullMenu;
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
/* build the source array from the options of the select element */
|
|
245
|
+
_selectInit: function() {
|
|
246
|
+
var select = this.element,
|
|
247
|
+
selectClass = select.attr("class"),
|
|
248
|
+
selectStyle = select.attr("style"),
|
|
249
|
+
selected = select.children(":selected"),
|
|
250
|
+
value = $.trim(selected.text());
|
|
251
|
+
select.hide();
|
|
252
|
+
this.options.source = select.children("option").map(function() {
|
|
253
|
+
return {
|
|
254
|
+
label: $.trim(this.text),
|
|
255
|
+
option: this
|
|
256
|
+
};
|
|
257
|
+
}).toArray();
|
|
258
|
+
var userSelectCallback = this.options.select;
|
|
259
|
+
var userSelectedCallback = this.options.selected;
|
|
260
|
+
this.options.select = function(event, ui) {
|
|
261
|
+
ui.item.option.selected = true;
|
|
262
|
+
select.change();
|
|
263
|
+
if (userSelectCallback) userSelectCallback(event, ui);
|
|
264
|
+
// compatibility with jQuery UI's combobox.
|
|
265
|
+
if (userSelectedCallback) userSelectedCallback(event, ui);
|
|
266
|
+
};
|
|
267
|
+
this.options.selectElement = select;
|
|
268
|
+
this.input = $("<input>").insertAfter(select).val(value);
|
|
269
|
+
if (selectStyle) {
|
|
270
|
+
this.input.attr("style", selectStyle);
|
|
271
|
+
}
|
|
272
|
+
if (selectClass) {
|
|
273
|
+
this.input.attr("class", selectClass);
|
|
274
|
+
}
|
|
275
|
+
this.input.combobox(this.options);
|
|
276
|
+
},
|
|
277
|
+
inputbox: function() {
|
|
278
|
+
if (this.element.is("SELECT")) {
|
|
279
|
+
return this.input;
|
|
280
|
+
} else {
|
|
281
|
+
return this.element;
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
|
|
285
|
+
// custom part - setting combobox value
|
|
286
|
+
setValue: function (value) {
|
|
287
|
+
var input = $(this.element[0]).siblings('input.ui-autocomplete-input').first(),
|
|
288
|
+
selectEl = document.getElementById(this.element.attr('id')),
|
|
289
|
+
options = selectEl.options,
|
|
290
|
+
length = options.length;
|
|
291
|
+
for (var a = 0; a < length; a += 1) {
|
|
292
|
+
if (options[a].text === value) {
|
|
293
|
+
selectEl.selectedIndex = a;
|
|
294
|
+
input.val(options[a].text);
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
// end of custom part
|
|
300
|
+
});
|
|
301
|
+
})(jQuery);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Discerner = {};
|
|
2
|
+
Discerner.Constants = {};
|
|
3
|
+
Discerner.Search = {};
|
|
4
|
+
Discerner.SearchParameter = {};
|
|
5
|
+
Discerner.SearchParameterValue = {}
|
|
6
|
+
Discerner.SearchCombination = {};
|
|
7
|
+
Discerner.CategorizedAutocomplter = {};
|
|
8
|
+
Discerner.ExportParameters = {};
|
|
9
|
+
Discerner.Url = {};
|
|
10
|
+
NestedAttributes = {};
|
|
11
|
+
|
|
12
|
+
Discerner.Constants.EFFECT_SPEED = 1750;
|
|
13
|
+
|
|
14
|
+
$(function() {
|
|
15
|
+
$(document).on('keyup', '#discerner_searches_filter input[type="text"]', function() {
|
|
16
|
+
$.get($("#discerner_searches_filter").attr("action"), $("#discerner_searches_filter").serialize(), null, "script");
|
|
17
|
+
return false;
|
|
18
|
+
});
|
|
19
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Discerner.ExportParameters.UI = function() {
|
|
2
|
+
$(document).on('click','#discerner_exportable_fields a.select_all_parameters', function(){
|
|
3
|
+
$(this).closest("div[class^='parameter_category_']").find("input[type='checkbox']:not(:checked)").prop('checked', true);
|
|
4
|
+
$(this).removeClass('select_all_parameters').addClass('deselect_all_parameters').html('Deselect all');
|
|
5
|
+
return false
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
$(document).on('click','#discerner_exportable_fields a.deselect_all_parameters', function(){
|
|
9
|
+
$(this).closest("div[class^='parameter_category_']").find("input[type='checkbox']:checked").prop('checked', false);
|
|
10
|
+
$(this).removeClass('deselect_all_parameters').addClass('select_all_parameters').html('Select all');
|
|
11
|
+
return false
|
|
12
|
+
});
|
|
13
|
+
}
|