bitlove-rollout_ui 0.1.0

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 (70) hide show
  1. data/README.markdown +73 -0
  2. data/Rakefile +12 -0
  3. data/lib/rollout_ui.rb +25 -0
  4. data/lib/rollout_ui/engine/Rakefile +12 -0
  5. data/lib/rollout_ui/engine/app/assets/images/rollout_ui/dark_brick_wall.png +0 -0
  6. data/lib/rollout_ui/engine/app/assets/images/rollout_ui/rollout.png +0 -0
  7. data/lib/rollout_ui/engine/app/assets/javascripts/rollout_ui/application.js +9 -0
  8. data/lib/rollout_ui/engine/app/assets/stylesheets/rollout_ui/application.css +9 -0
  9. data/lib/rollout_ui/engine/app/assets/stylesheets/rollout_ui/layout.css +108 -0
  10. data/lib/rollout_ui/engine/app/controllers/rollout_ui/application_controller.rb +4 -0
  11. data/lib/rollout_ui/engine/app/controllers/rollout_ui/features_controller.rb +25 -0
  12. data/lib/rollout_ui/engine/app/helpers/rollout_ui/application_helper.rb +4 -0
  13. data/lib/rollout_ui/engine/app/views/layouts/rollout_ui/application.html.erb +29 -0
  14. data/lib/rollout_ui/engine/app/views/rollout_ui/features/_feature.html.erb +34 -0
  15. data/lib/rollout_ui/engine/app/views/rollout_ui/features/index.html.erb +14 -0
  16. data/lib/rollout_ui/engine/config/routes.rb +5 -0
  17. data/lib/rollout_ui/engine/lib/rollout_ui/engine.rb +5 -0
  18. data/lib/rollout_ui/engine/lib/tasks/rollout_ui_tasks.rake +4 -0
  19. data/lib/rollout_ui/engine/script/rails +6 -0
  20. data/lib/rollout_ui/engine/vendor/assets/images/rollout_ui/chosen-sprite.png +0 -0
  21. data/lib/rollout_ui/engine/vendor/assets/javascripts/chosen.jquery.js +1011 -0
  22. data/lib/rollout_ui/engine/vendor/assets/javascripts/jquery-ujs.js +367 -0
  23. data/lib/rollout_ui/engine/vendor/assets/stylesheets/chosen.css +369 -0
  24. data/lib/rollout_ui/engine/vendor/assets/stylesheets/normalize.css +431 -0
  25. data/lib/rollout_ui/feature.rb +50 -0
  26. data/lib/rollout_ui/monkey_patch.rb +8 -0
  27. data/lib/rollout_ui/server.rb +71 -0
  28. data/lib/rollout_ui/server/public/rollout_ui/application.css +916 -0
  29. data/lib/rollout_ui/server/public/rollout_ui/application.js +45 -0
  30. data/lib/rollout_ui/server/public/rollout_ui/chosen-sprite.png +0 -0
  31. data/lib/rollout_ui/server/public/rollout_ui/dark_brick_wall.png +0 -0
  32. data/lib/rollout_ui/server/public/rollout_ui/rollout.png +0 -0
  33. data/lib/rollout_ui/server/views/feature.erb +34 -0
  34. data/lib/rollout_ui/server/views/index.erb +5 -0
  35. data/lib/rollout_ui/server/views/layout.erb +32 -0
  36. data/lib/rollout_ui/version.rb +3 -0
  37. data/lib/rollout_ui/wrapper.rb +28 -0
  38. data/spec/dummy/Rakefile +7 -0
  39. data/spec/dummy/app/assets/javascripts/application.js +7 -0
  40. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  41. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  42. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  43. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  44. data/spec/dummy/config.ru +12 -0
  45. data/spec/dummy/config/application.rb +45 -0
  46. data/spec/dummy/config/boot.rb +10 -0
  47. data/spec/dummy/config/database.yml +14 -0
  48. data/spec/dummy/config/environment.rb +5 -0
  49. data/spec/dummy/config/environments/development.rb +30 -0
  50. data/spec/dummy/config/environments/production.rb +60 -0
  51. data/spec/dummy/config/environments/test.rb +39 -0
  52. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  53. data/spec/dummy/config/initializers/inflections.rb +10 -0
  54. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  55. data/spec/dummy/config/initializers/rollout.rb +6 -0
  56. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  57. data/spec/dummy/config/initializers/session_store.rb +8 -0
  58. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  59. data/spec/dummy/config/locales/en.yml +5 -0
  60. data/spec/dummy/config/routes.rb +5 -0
  61. data/spec/dummy/public/404.html +26 -0
  62. data/spec/dummy/public/422.html +26 -0
  63. data/spec/dummy/public/500.html +26 -0
  64. data/spec/dummy/public/favicon.ico +0 -0
  65. data/spec/dummy/script/rails +6 -0
  66. data/spec/lib/rollout_ui/feature_spec.rb +52 -0
  67. data/spec/lib/rollout_ui/wrapper_spec.rb +63 -0
  68. data/spec/requests/engine/engine_spec.rb +95 -0
  69. data/spec/spec_helper.rb +22 -0
  70. metadata +267 -0
@@ -0,0 +1,73 @@
1
+ RolloutUI: A slick way to rollout features in your web app.
2
+ ==========================================================
3
+
4
+ What does it do?
5
+ ----------------
6
+
7
+ RolloutUI provides a zero-configuration user interface for James Golick's [rollout](https://github.com/jamesgolick/rollout). RolloutUI auto-detects features defined in rollout in your application.
8
+ It allows you to release features to groups, users or a percentage of your userbase through a nice interface rather than digging around in the console or modifying redis directly.
9
+
10
+ It looks something like this:
11
+ -----------------------------
12
+
13
+ ![RolloutUI](https://img.skitch.com/20111018-kyqx954fxeny9tbjf6q3n7pymi.jpg)
14
+
15
+ Installing RolloutUI
16
+ --------------------
17
+
18
+ First, get [rollout](https://github.com/jamesgolick/rollout) set up and running on your app and define at least one feature.
19
+
20
+ Then you're ready to use RolloutUI.
21
+
22
+ Add it to your gemfile:
23
+
24
+ gem "rollout_ui"
25
+
26
+ Wrap your rollout instance:
27
+
28
+ $rollout = Rollout.new($redis)
29
+ RolloutUi.wrap($rollout)
30
+
31
+ ### Rails 3.1
32
+
33
+ Mount the Rails engine in your routes.rb file:
34
+
35
+ mount RolloutUi::Engine => "/rollout"
36
+
37
+ ### Other
38
+
39
+ Run the sinatra app. You can either run it as it's own app, or run it in
40
+ tandom with other rack apps. Example: using Rack's `URLMap` in your `config.ru`:
41
+
42
+ run Rack::URLMap.new \
43
+ "/" => Your::App.new,
44
+ "/rollout" => RolloutUi::Server.new
45
+
46
+ Protecting the sinatra app with HTTP basic auth is probably a good idea.
47
+ Put this somewhere before the `URLMap` in your `config.ru`:
48
+
49
+ RolloutUi::Server.use Rack::Auth::Basic do |username, password|
50
+ username == '<some username>' && password == '<some password>'
51
+ end
52
+
53
+ Resources
54
+ ---------
55
+
56
+ * Rollout: <https://github.com/jamesgolick/rollout>
57
+ * Redis: <http://redis.io>
58
+
59
+ Patches/Pull Requests
60
+ ---------------------
61
+
62
+ * Fork the project.
63
+ * Make your feature addition or bug fix.
64
+ * Add tests for it. This is important so I don't break it in a
65
+ future version unintentionally.
66
+ * Send me a pull request.
67
+
68
+ Thanks
69
+ ------
70
+ * Thanks to James Golick for the great [rollout gem](https://github.com/jamesgolick/rollout).
71
+ * Thanks to [ChallengePost](http://challengepost.com) for sponsoring additional development and
72
+ supporting open sourcing it from the start.
73
+ * Thanks to [Holly Tiwari](http://holly-smith.com/) for the design!
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core'
5
+ require "rspec/core/rake_task"
6
+
7
+ RSpec::Core::RakeTask.new do |t|
8
+ t.pattern = "./**/*_spec.rb"
9
+ end
10
+
11
+ task :default => :spec
12
+
@@ -0,0 +1,25 @@
1
+ require 'redis'
2
+ require 'rollout'
3
+ require 'rollout_ui/monkey_patch'
4
+
5
+ # Hack so we only load the engine when Rails will support it.
6
+ # TODO: find a better way
7
+ if defined?(Rails) && Rails::VERSION::STRING.to_f >= 3.1
8
+ $:.unshift File.expand_path("rollout_ui/engine/lib", File.dirname(__FILE__))
9
+ require 'rollout_ui/engine'
10
+ end
11
+
12
+ module RolloutUi
13
+ autoload :Version, 'rollout_ui/version'
14
+ autoload :Wrapper, 'rollout_ui/wrapper'
15
+ autoload :Feature, 'rollout_ui/feature'
16
+ autoload :Server, 'rollout_ui/server'
17
+
18
+ def self.wrap(rollout)
19
+ @@rollout = rollout
20
+ end
21
+
22
+ def self.rollout
23
+ @@rollout
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
9
+ load 'rails/tasks/engine.rake'
10
+
11
+
12
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,9 @@
1
+ // This is a manifest file that'll be compiled into including all the files listed below.
2
+ // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
3
+ // be included in the compiled file accessible from http://example.com/assets/application.js
4
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5
+ // the compiled file.
6
+ //
7
+ //= require jquery-ujs
8
+ //= require chosen.jquery
9
+ //= require_tree .
@@ -0,0 +1,9 @@
1
+ /*
2
+ * This is a manifest file that'll automatically include all the stylesheets available in this directory
3
+ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
4
+ * the top of the compiled file, but it's generally better to create a new file per style scope.
5
+ *= require normalize
6
+ *= require chosen
7
+ *= require_self
8
+ *= require_tree .
9
+ */
@@ -0,0 +1,108 @@
1
+ body {
2
+ font-family: Helvetica, sans-serif;
3
+ background: #232323 url(/assets/rollout_ui/dark_brick_wall.png);
4
+ color: #aeaeae;
5
+ }
6
+
7
+ h1 img {
8
+ height: 75px;
9
+ }
10
+
11
+ /* For modern browsers */
12
+ .clearfix:before,
13
+ .clearfix:after {
14
+ content:"";
15
+ display:table;
16
+ }
17
+
18
+ .clearfix:after {
19
+ clear:both;
20
+ }
21
+
22
+ /* For IE 6/7 (trigger hasLayout) */
23
+ .clearfix {
24
+ zoom:1;
25
+ }
26
+
27
+ .col {
28
+ float: left;
29
+ width: 270px;
30
+ padding: 0 25px;
31
+ }
32
+
33
+ #container {
34
+ width: 960px;
35
+ margin: 0 auto;
36
+ }
37
+
38
+ #container h1 {
39
+ text-align: center;
40
+ margin: 43px 0 15px;
41
+ }
42
+
43
+ #features {
44
+ list-style-type: none;
45
+ padding: 0px;
46
+ }
47
+
48
+ #features .feature {
49
+ background-color: #121212;
50
+ padding: 20px 0;
51
+ border-radius: 10px;
52
+ margin-bottom: 25px;
53
+ }
54
+
55
+ #features .feature h2 {
56
+ margin: 0px 0 23px;
57
+ text-align: center;
58
+ font-size: 20px;
59
+ font-weight: normal;
60
+ letter-spacing: 1px;
61
+ }
62
+
63
+ #features .feature .groups {
64
+ height: 1.5em;
65
+ }
66
+
67
+ #features .feature label {
68
+ float: left;
69
+ font-size: 14px;
70
+ line-height: 2em;
71
+ color: #fcc334;
72
+ margin-right: 10px;
73
+ }
74
+
75
+ #features .feature select,
76
+ #features .feature .users {
77
+ line-height: 26px;
78
+ }
79
+
80
+ #features .feature .users {
81
+ width: 172px;
82
+ line-height: 27px;
83
+ }
84
+
85
+ #features .feature .percentage {
86
+ width: 187px;
87
+ }
88
+
89
+ #features .feature .groups {
90
+ width: 213px;
91
+ }
92
+
93
+ #features .feature .chzn-container-multi .chzn-choices {
94
+ -webkit-border-radius: 4px;
95
+ -moz-border-radius: 4px;
96
+ border-radius: 4px;
97
+ }
98
+ #features input[type='submit'] {
99
+ display: none;
100
+ }
101
+
102
+ #footer {
103
+ font-family: 'Ultra', serif;
104
+ font-size: 16px;
105
+ text-align: center;
106
+ color: #f4b71d;
107
+ text-shadow: 0 -1px 2px rgba(0,0,0,1);
108
+ }
@@ -0,0 +1,4 @@
1
+ module RolloutUi
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,25 @@
1
+ module RolloutUi
2
+ class FeaturesController < ApplicationController
3
+ before_filter :wrapper
4
+
5
+ def index
6
+ @features = @wrapper.features.map{ |feature| RolloutUi::Feature.new(feature) }
7
+ end
8
+
9
+ def update
10
+ @feature = RolloutUi::Feature.new(params[:id])
11
+
12
+ @feature.percentage = params["percentage"] if params["percentage"]
13
+ @feature.groups = params["groups"] if params["groups"]
14
+ @feature.user_ids = params["users"] if params["users"]
15
+
16
+ redirect_to features_path
17
+ end
18
+
19
+ private
20
+
21
+ def wrapper
22
+ @wrapper = RolloutUi::Wrapper.new
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,4 @@
1
+ module RolloutUi
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,29 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>RolloutUI</title>
5
+ <link href='http://fonts.googleapis.com/css?family=Ultra' rel='stylesheet' type='text/css'>
6
+ <%= stylesheet_link_tag "rollout_ui/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+
10
+ <body>
11
+ <div id="container">
12
+ <h1><%= image_tag "rollout_ui/rollout.png", :alt => "Rollout" %></h1>
13
+ <%= yield %>
14
+ </div>
15
+
16
+ <div id="footer">
17
+ <p>Powered by RolloutUi v<%= RolloutUi::Version %></p>
18
+ </div>
19
+ </body>
20
+
21
+ <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
22
+ <%= javascript_include_tag "rollout_ui/application" %>
23
+
24
+ <script type="text/javascript">
25
+ $(function() {
26
+ <%= yield :onready %>
27
+ });
28
+ </script>
29
+ </html>
@@ -0,0 +1,34 @@
1
+ <h2><%= feature.name %></h2>
2
+
3
+ <div class="col">
4
+ <%= form_tag feature_path(feature.name), :class => "percentage_form", :method => :put, :remote => true do %>
5
+ <label>Percentage</label>
6
+ <select class="percentage" name="percentage">
7
+ <% 101.times do |i| %>
8
+ <option value="<%= i %>"<%= " selected='selected'" if feature.percentage == i.to_s %>><%= i %>%</option>
9
+ <% end %>
10
+ </select>
11
+ <input type="submit" value="Save" />
12
+ <% end %>
13
+ </div>
14
+
15
+ <div class="col">
16
+ <%= form_tag feature_path(feature.name), :class => "groups_form", :method => :put, :remote => true do %>
17
+ <label>Groups</label>
18
+ <select id="<%= feature.name %>_groups" class="groups" name="groups[]" multiple="multiple" data-placeholder="Choose a group">
19
+ <% @wrapper.groups.each do |group| %>
20
+ <option<%= " selected='selected'" if feature.groups.include?(group) %>><%= group %></option>
21
+ <% end %>
22
+ </select>
23
+ <%= hidden_field_tag "groups[]", "" %>
24
+ <input type="submit" value="Save" />
25
+ <% end %>
26
+ </div>
27
+
28
+ <div class="col">
29
+ <%= form_tag feature_path(feature.name), :class => "users_form", :method => :put, :remote => true do %>
30
+ <label>Add User ID</label>
31
+ <input class="users" type="text" name="users[]" value="<%= feature.user_ids.join(",") %>" data-placeholder="Enter User ID" />
32
+ <input type="submit" value="Save" />
33
+ <% end %>
34
+ </div>
@@ -0,0 +1,14 @@
1
+ <ul id="features">
2
+ <% @features.each do |feature| %>
3
+ <li id="<%= feature.name %>" class="feature clearfix"><%= render 'feature', :feature => feature %></li>
4
+ <% end %>
5
+ </ul>
6
+
7
+ <% content_for :onready do %>
8
+ $("select").chosen({no_results_text: "No groups matched"});
9
+ $("input.users").chosen();
10
+
11
+ $("select, input.users").change(function() {
12
+ $(this).closest("form").submit();
13
+ });
14
+ <% end %>
@@ -0,0 +1,5 @@
1
+ RolloutUi::Engine.routes.draw do
2
+ resources :features, :only => [:index, :update]
3
+
4
+ root :to => "features#index"
5
+ end
@@ -0,0 +1,5 @@
1
+ module RolloutUi
2
+ class Engine < Rails::Engine
3
+ isolate_namespace RolloutUi
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :rollout_ui do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ #!/usr/bin/env ruby
3
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
4
+
5
+ ENGINE_PATH = File.expand_path('../..', __FILE__)
6
+ load File.expand_path('../../test/dummy/script/rails', __FILE__)
@@ -0,0 +1,1011 @@
1
+ // Chosen, a Select Box Enhancer for jQuery and Protoype
2
+ // by Patrick Filler for Harvest, http://getharvest.com
3
+ //
4
+ // Version 0.9.5
5
+ // Full source at https://github.com/harvesthq/chosen
6
+ // Copyright (c) 2011 Harvest http://getharvest.com
7
+
8
+ // MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
9
+ // This file is generated by `cake build`, do not edit it by hand.
10
+ (function() {
11
+ var SelectParser;
12
+ SelectParser = (function() {
13
+ function SelectParser() {
14
+ this.options_index = 0;
15
+ this.parsed = [];
16
+ }
17
+ SelectParser.prototype.add_node = function(child) {
18
+ if (child.nodeName === "OPTGROUP") {
19
+ return this.add_group(child);
20
+ } else {
21
+ return this.add_option(child);
22
+ }
23
+ };
24
+ SelectParser.prototype.add_group = function(group) {
25
+ var group_position, option, _i, _len, _ref, _results;
26
+ group_position = this.parsed.length;
27
+ this.parsed.push({
28
+ array_index: group_position,
29
+ group: true,
30
+ label: group.label,
31
+ children: 0,
32
+ disabled: group.disabled
33
+ });
34
+ _ref = group.childNodes;
35
+ _results = [];
36
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
37
+ option = _ref[_i];
38
+ _results.push(this.add_option(option, group_position, group.disabled));
39
+ }
40
+ return _results;
41
+ };
42
+ SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
43
+ if (option.nodeName === "OPTION") {
44
+ if (option.text !== "") {
45
+ if (group_position != null) {
46
+ this.parsed[group_position].children += 1;
47
+ }
48
+ this.parsed.push({
49
+ array_index: this.parsed.length,
50
+ options_index: this.options_index,
51
+ value: option.value,
52
+ text: option.text,
53
+ html: option.innerHTML,
54
+ selected: option.selected,
55
+ disabled: group_disabled === true ? group_disabled : option.disabled,
56
+ group_array_index: group_position,
57
+ classes: option.className,
58
+ style: option.style.cssText
59
+ });
60
+ } else {
61
+ this.parsed.push({
62
+ array_index: this.parsed.length,
63
+ options_index: this.options_index,
64
+ empty: true
65
+ });
66
+ }
67
+ return this.options_index += 1;
68
+ }
69
+ };
70
+ return SelectParser;
71
+ })();
72
+ SelectParser.select_to_array = function(select) {
73
+ var child, parser, _i, _len, _ref;
74
+ parser = new SelectParser();
75
+ _ref = select.childNodes;
76
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
77
+ child = _ref[_i];
78
+ parser.add_node(child);
79
+ }
80
+ return parser.parsed;
81
+ };
82
+ this.SelectParser = SelectParser;
83
+ }).call(this);
84
+ (function() {
85
+ /*
86
+ Chosen source: generate output using 'cake build'
87
+ Copyright (c) 2011 by Harvest
88
+ */
89
+ var AbstractChosen, root;
90
+ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
91
+ root = this;
92
+ AbstractChosen = (function() {
93
+ function AbstractChosen(form_field, options) {
94
+ this.form_field = form_field;
95
+ this.options = options != null ? options : {};
96
+ this.set_default_values();
97
+ this.is_multiple = this.form_field.multiple;
98
+ this.default_text_default = this.form_field.multiple ? "Select Some Options" : "Select an Option";
99
+ this.setup();
100
+ this.set_up_html();
101
+ this.register_observers();
102
+ this.finish_setup();
103
+ }
104
+ AbstractChosen.prototype.set_default_values = function() {
105
+ this.click_test_action = __bind(function(evt) {
106
+ return this.test_active_click(evt);
107
+ }, this);
108
+ this.activate_action = __bind(function(evt) {
109
+ return this.activate_field(evt);
110
+ }, this);
111
+ this.active_field = false;
112
+ this.mouse_on_container = false;
113
+ this.results_showing = false;
114
+ this.result_highlighted = null;
115
+ this.result_single_selected = null;
116
+ this.allow_single_deselect = (this.options.allow_single_deselect != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
117
+ this.disable_search_threshold = this.options.disable_search_threshold || 0;
118
+ this.choices = 0;
119
+ return this.results_none_found = this.options.no_results_text || "No results match";
120
+ };
121
+ AbstractChosen.prototype.mouse_enter = function() {
122
+ return this.mouse_on_container = true;
123
+ };
124
+ AbstractChosen.prototype.mouse_leave = function() {
125
+ return this.mouse_on_container = false;
126
+ };
127
+ AbstractChosen.prototype.input_focus = function(evt) {
128
+ if (!this.active_field) {
129
+ return setTimeout((__bind(function() {
130
+ return this.container_mousedown();
131
+ }, this)), 50);
132
+ }
133
+ };
134
+ AbstractChosen.prototype.input_blur = function(evt) {
135
+ if (!this.mouse_on_container) {
136
+ this.active_field = false;
137
+ return setTimeout((__bind(function() {
138
+ return this.blur_test();
139
+ }, this)), 100);
140
+ }
141
+ };
142
+ AbstractChosen.prototype.result_add_option = function(option) {
143
+ var classes, style;
144
+ if (!option.disabled) {
145
+ option.dom_id = this.container_id + "_o_" + option.array_index;
146
+ classes = option.selected && this.is_multiple ? [] : ["active-result"];
147
+ if (option.selected) {
148
+ classes.push("result-selected");
149
+ }
150
+ if (option.group_array_index != null) {
151
+ classes.push("group-option");
152
+ }
153
+ if (option.classes !== "") {
154
+ classes.push(option.classes);
155
+ }
156
+ style = option.style.cssText !== "" ? " style=\"" + option.style + "\"" : "";
157
+ return '<li id="' + option.dom_id + '" class="' + classes.join(' ') + '"' + style + '>' + option.html + '</li>';
158
+ } else {
159
+ return "";
160
+ }
161
+ };
162
+ AbstractChosen.prototype.results_update_field = function() {
163
+ this.result_clear_highlight();
164
+ this.result_single_selected = null;
165
+ return this.results_build();
166
+ };
167
+ AbstractChosen.prototype.results_toggle = function() {
168
+ if (this.results_showing) {
169
+ return this.results_hide();
170
+ } else {
171
+ return this.results_show();
172
+ }
173
+ };
174
+ AbstractChosen.prototype.results_search = function(evt) {
175
+ if (this.results_showing) {
176
+ return this.winnow_results();
177
+ } else {
178
+ return this.results_show();
179
+ }
180
+ };
181
+ AbstractChosen.prototype.keyup_checker = function(evt) {
182
+ var stroke, _ref;
183
+ stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
184
+ this.search_field_scale();
185
+ switch (stroke) {
186
+ case 8:
187
+ if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) {
188
+ return this.keydown_backstroke();
189
+ } else if (!this.pending_backstroke) {
190
+ this.result_clear_highlight();
191
+ return this.results_search();
192
+ }
193
+ break;
194
+ case 13:
195
+ evt.preventDefault();
196
+ if (this.results_showing) {
197
+ return this.result_select(evt);
198
+ } else if (this.is_tag) {
199
+ return this.choice_append();
200
+ }
201
+ break;
202
+ case 27:
203
+ if (this.results_showing) {
204
+ return this.results_hide();
205
+ }
206
+ break;
207
+ case 9:
208
+ case 38:
209
+ case 40:
210
+ case 16:
211
+ case 91:
212
+ case 17:
213
+ break;
214
+ default:
215
+ return this.results_search();
216
+ }
217
+ };
218
+ AbstractChosen.prototype.generate_field_id = function() {
219
+ var new_id;
220
+ new_id = this.generate_random_id();
221
+ this.form_field.id = new_id;
222
+ return new_id;
223
+ };
224
+ AbstractChosen.prototype.generate_random_char = function() {
225
+ var chars, newchar, rand;
226
+ chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ";
227
+ rand = Math.floor(Math.random() * chars.length);
228
+ return newchar = chars.substring(rand, rand + 1);
229
+ };
230
+ return AbstractChosen;
231
+ })();
232
+ root.AbstractChosen = AbstractChosen;
233
+ }).call(this);
234
+ (function() {
235
+ /*
236
+ Chosen source: generate output using 'cake build'
237
+ Copyright (c) 2011 by Harvest
238
+ */
239
+ var $, Chosen, get_side_border_padding, root;
240
+ var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
241
+ for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
242
+ function ctor() { this.constructor = child; }
243
+ ctor.prototype = parent.prototype;
244
+ child.prototype = new ctor;
245
+ child.__super__ = parent.prototype;
246
+ return child;
247
+ }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
248
+ root = this;
249
+ $ = jQuery;
250
+ $.fn.extend({
251
+ chosen: function(options) {
252
+ if ($.browser.msie && ($.browser.version === "6.0" || $.browser.version === "7.0")) {
253
+ return this;
254
+ }
255
+ return $(this).each(function(input_field) {
256
+ if (!($(this)).hasClass("chzn-done")) {
257
+ return new Chosen(this, options);
258
+ }
259
+ });
260
+ }
261
+ });
262
+ Chosen = (function() {
263
+ __extends(Chosen, AbstractChosen);
264
+ function Chosen() {
265
+ Chosen.__super__.constructor.apply(this, arguments);
266
+ }
267
+ Chosen.prototype.setup = function() {
268
+ var tag, tags, val, _i, _len, _results;
269
+ this.form_field_jq = $(this.form_field);
270
+ this.is_tag = this.form_field_jq.attr("type") === "text";
271
+ this.is_multiple = this.is_tag ? true : this.is_multiple;
272
+ this.default_text_default = this.is_tag ? "Enter Tags" : this.default_text_default;
273
+ this.is_rtl = this.form_field_jq.hasClass("chzn-rtl");
274
+ this.tags = [];
275
+ if (this.is_tag) {
276
+ val = this.form_field.value;
277
+ this.form_field.value = '';
278
+ if (val !== '') {
279
+ tags = val.split(',');
280
+ _results = [];
281
+ for (_i = 0, _len = tags.length; _i < _len; _i++) {
282
+ tag = tags[_i];
283
+ _results.push(this.tags.push(unescape(tag)));
284
+ }
285
+ return _results;
286
+ }
287
+ }
288
+ };
289
+ Chosen.prototype.finish_setup = function() {
290
+ var tag, _i, _len, _ref, _results;
291
+ this.form_field_jq.addClass("chzn-done");
292
+ _ref = this.tags;
293
+ _results = [];
294
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
295
+ tag = _ref[_i];
296
+ _results.push(this.choice_append(tag, tag));
297
+ }
298
+ return _results;
299
+ };
300
+ Chosen.prototype.set_up_html = function() {
301
+ var container_div, dd_top, dd_width, sf_width;
302
+ this.container_id = this.form_field.id.length ? this.form_field.id.replace(/(:|\.)/g, '_') : this.generate_field_id();
303
+ this.container_id += "_chzn";
304
+ this.f_width = this.form_field_jq.outerWidth();
305
+ this.default_text = this.form_field_jq.data('placeholder') ? this.form_field_jq.data('placeholder') : this.default_text_default;
306
+ container_div = $("<div />", {
307
+ id: this.container_id,
308
+ "class": "chzn-container" + (this.is_rtl ? ' chzn-rtl' : ''),
309
+ style: 'width: ' + this.f_width + 'px;'
310
+ });
311
+ if (this.is_multiple) {
312
+ container_div.html('<ul class="chzn-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chzn-drop" style="left:-9000px;"><ul class="chzn-results"></ul></div>');
313
+ } else {
314
+ container_div.html('<a href="javascript:void(0)" class="chzn-single"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chzn-drop" style="left:-9000px;"><div class="chzn-search"><input type="text" autocomplete="off" /></div><ul class="chzn-results"></ul></div>');
315
+ }
316
+ this.form_field_jq.hide().after(container_div);
317
+ this.container = $('#' + this.container_id);
318
+ this.container.addClass("chzn-container-" + (this.is_multiple ? "multi" : "single"));
319
+ if (!this.is_multiple && this.form_field.options.length <= this.disable_search_threshold) {
320
+ this.container.addClass("chzn-container-single-nosearch");
321
+ }
322
+ this.dropdown = this.container.find('div.chzn-drop').first();
323
+ dd_top = this.container.height();
324
+ dd_width = this.f_width - get_side_border_padding(this.dropdown);
325
+ this.dropdown.css({
326
+ "width": dd_width + "px",
327
+ "top": dd_top + "px"
328
+ });
329
+ this.search_field = this.container.find('input').first();
330
+ this.search_results = this.container.find('ul.chzn-results').first();
331
+ this.search_field_scale();
332
+ this.search_no_results = this.container.find('li.no-results').first();
333
+ if (this.is_multiple) {
334
+ this.search_choices = this.container.find('ul.chzn-choices').first();
335
+ this.search_container = this.container.find('li.search-field').first();
336
+ } else {
337
+ this.search_container = this.container.find('div.chzn-search').first();
338
+ this.selected_item = this.container.find('.chzn-single').first();
339
+ sf_width = dd_width - get_side_border_padding(this.search_container) - get_side_border_padding(this.search_field);
340
+ this.search_field.css({
341
+ "width": sf_width + "px"
342
+ });
343
+ }
344
+ if (this.is_tag) {
345
+ this.container.prepend('<select id="' + this.container_id + '_shadow" name="' + this.form_field.name + '" style="display: none;" multiple="multiple"></select>');
346
+ this.form_field_jq = $('#' + this.container_id + '_shadow');
347
+ this.form_field = this.form_field_jq.get(0);
348
+ }
349
+ this.results_build();
350
+ return this.set_tab_index();
351
+ };
352
+ Chosen.prototype.register_observers = function() {
353
+ this.container.mousedown(__bind(function(evt) {
354
+ return this.container_mousedown(evt);
355
+ }, this));
356
+ this.container.mouseup(__bind(function(evt) {
357
+ return this.container_mouseup(evt);
358
+ }, this));
359
+ this.container.mouseenter(__bind(function(evt) {
360
+ return this.mouse_enter(evt);
361
+ }, this));
362
+ this.container.mouseleave(__bind(function(evt) {
363
+ return this.mouse_leave(evt);
364
+ }, this));
365
+ this.search_results.mouseup(__bind(function(evt) {
366
+ return this.search_results_mouseup(evt);
367
+ }, this));
368
+ this.search_results.mouseover(__bind(function(evt) {
369
+ return this.search_results_mouseover(evt);
370
+ }, this));
371
+ this.search_results.mouseout(__bind(function(evt) {
372
+ return this.search_results_mouseout(evt);
373
+ }, this));
374
+ this.form_field_jq.bind("liszt:updated", __bind(function(evt) {
375
+ return this.results_update_field(evt);
376
+ }, this));
377
+ this.search_field.blur(__bind(function(evt) {
378
+ return this.input_blur(evt);
379
+ }, this));
380
+ this.search_field.keyup(__bind(function(evt) {
381
+ return this.keyup_checker(evt);
382
+ }, this));
383
+ this.search_field.keydown(__bind(function(evt) {
384
+ return this.keydown_checker(evt);
385
+ }, this));
386
+ if (this.is_multiple) {
387
+ this.search_choices.click(__bind(function(evt) {
388
+ return this.choices_click(evt);
389
+ }, this));
390
+ return this.search_field.focus(__bind(function(evt) {
391
+ return this.input_focus(evt);
392
+ }, this));
393
+ }
394
+ };
395
+ Chosen.prototype.search_field_disabled = function() {
396
+ this.is_disabled = this.form_field_jq.attr('disabled');
397
+ if (this.is_disabled) {
398
+ this.container.addClass('chzn-disabled');
399
+ this.search_field.attr('disabled', true);
400
+ if (!this.is_multiple) {
401
+ this.selected_item.unbind("focus", this.activate_action);
402
+ }
403
+ return this.close_field();
404
+ } else {
405
+ this.container.removeClass('chzn-disabled');
406
+ this.search_field.attr('disabled', false);
407
+ if (!this.is_multiple) {
408
+ return this.selected_item.bind("focus", this.activate_action);
409
+ }
410
+ }
411
+ };
412
+ Chosen.prototype.container_mousedown = function(evt) {
413
+ var target_closelink;
414
+ if (!this.is_disabled) {
415
+ target_closelink = evt != null ? ($(evt.target)).hasClass("search-choice-close") : false;
416
+ if (evt && evt.type === "mousedown") {
417
+ evt.stopPropagation();
418
+ }
419
+ if (!this.pending_destroy_click && !target_closelink) {
420
+ if (!this.active_field) {
421
+ if (this.is_multiple) {
422
+ this.search_field.val("");
423
+ }
424
+ $(document).click(this.click_test_action);
425
+ this.results_show();
426
+ } else if (!this.is_multiple && evt && ($(evt.target) === this.selected_item || $(evt.target).parents("a.chzn-single").length)) {
427
+ evt.preventDefault();
428
+ this.results_toggle();
429
+ }
430
+ return this.activate_field();
431
+ } else {
432
+ return this.pending_destroy_click = false;
433
+ }
434
+ }
435
+ };
436
+ Chosen.prototype.container_mouseup = function(evt) {
437
+ if (evt.target.nodeName === "ABBR") {
438
+ return this.results_reset(evt);
439
+ }
440
+ };
441
+ Chosen.prototype.blur_test = function(evt) {
442
+ if (!this.active_field && this.container.hasClass("chzn-container-active")) {
443
+ return this.close_field();
444
+ }
445
+ };
446
+ Chosen.prototype.close_field = function() {
447
+ $(document).unbind("click", this.click_test_action);
448
+ if (!this.is_multiple) {
449
+ this.selected_item.attr("tabindex", this.search_field.attr("tabindex"));
450
+ this.search_field.attr("tabindex", -1);
451
+ }
452
+ this.active_field = false;
453
+ this.results_hide();
454
+ this.container.removeClass("chzn-container-active");
455
+ this.winnow_results_clear();
456
+ this.clear_backstroke();
457
+ this.show_search_field_default();
458
+ return this.search_field_scale();
459
+ };
460
+ Chosen.prototype.activate_field = function() {
461
+ if (!this.is_multiple && !this.active_field) {
462
+ this.search_field.attr("tabindex", this.selected_item.attr("tabindex"));
463
+ this.selected_item.attr("tabindex", -1);
464
+ }
465
+ this.container.addClass("chzn-container-active");
466
+ this.active_field = true;
467
+ this.search_field.val(this.search_field.val());
468
+ return this.search_field.focus();
469
+ };
470
+ Chosen.prototype.test_active_click = function(evt) {
471
+ if ($(evt.target).parents('#' + this.container_id).length) {
472
+ return this.active_field = true;
473
+ } else {
474
+ return this.close_field();
475
+ }
476
+ };
477
+ Chosen.prototype.results_build = function() {
478
+ var content, data, hash, i, opt, result, startTime, _i, _j, _len, _len2, _len3, _ref, _ref2;
479
+ startTime = new Date();
480
+ this.parsing = true;
481
+ if (this.is_tag && (typeof results !== "undefined" && results !== null)) {
482
+ hash = {};
483
+ _ref = this.form_field.options;
484
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
485
+ opt = _ref[_i];
486
+ if (opt.selected) {
487
+ hash[opt.value] = true;
488
+ }
489
+ }
490
+ this.results_data = [];
491
+ for (i = 0, _len2 = results.length; i < _len2; i++) {
492
+ result = results[i];
493
+ this.results_data.push({
494
+ array_index: i,
495
+ options_index: i,
496
+ value: result.value,
497
+ text: result.text,
498
+ html: result.text,
499
+ selected: result.value in hash ? 1 : 0,
500
+ disabled: 0,
501
+ group_array_index: null
502
+ });
503
+ }
504
+ } else {
505
+ this.results_data = root.SelectParser.select_to_array(this.form_field);
506
+ if (this.is_multiple && this.choices > 0) {
507
+ this.search_choices.find("li.search-choice").remove();
508
+ this.choices = 0;
509
+ } else if (!this.is_multiple) {
510
+ this.selected_item.find("span").text(this.default_text);
511
+ }
512
+ }
513
+ content = '';
514
+ _ref2 = this.results_data;
515
+ for (_j = 0, _len3 = _ref2.length; _j < _len3; _j++) {
516
+ data = _ref2[_j];
517
+ if (data.group) {
518
+ content += this.result_add_group(data);
519
+ } else if (!data.empty) {
520
+ content += this.result_add_option(data);
521
+ if (this.is_tag && (typeof results !== "undefined" && results !== null)) {
522
+ continue;
523
+ }
524
+ if (data.selected && this.is_multiple) {
525
+ this.choice_build(data);
526
+ } else if (data.selected && !this.is_multiple) {
527
+ this.selected_item.find("span").text(data.text);
528
+ if (this.allow_single_deselect) {
529
+ this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
530
+ }
531
+ }
532
+ }
533
+ }
534
+ if (this.is_tag && (typeof results !== "undefined" && results !== null)) {
535
+ this.search_results.html(content);
536
+ this.results_show();
537
+ } else {
538
+ this.search_field_disabled();
539
+ this.show_search_field_default();
540
+ this.search_field_scale();
541
+ this.search_results.html(content);
542
+ }
543
+ return this.parsing = false;
544
+ };
545
+ Chosen.prototype.result_add_group = function(group) {
546
+ if (!group.disabled) {
547
+ group.dom_id = this.container_id + "_g_" + group.array_index;
548
+ return '<li id="' + group.dom_id + '" class="group-result">' + $("<div />").text(group.label).html() + '</li>';
549
+ } else {
550
+ return "";
551
+ }
552
+ };
553
+ Chosen.prototype.result_do_highlight = function(el) {
554
+ var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
555
+ if (el.length) {
556
+ this.result_clear_highlight();
557
+ this.result_highlight = el;
558
+ this.result_highlight.addClass("highlighted");
559
+ maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
560
+ visible_top = this.search_results.scrollTop();
561
+ visible_bottom = maxHeight + visible_top;
562
+ high_top = this.result_highlight.position().top + this.search_results.scrollTop();
563
+ high_bottom = high_top + this.result_highlight.outerHeight();
564
+ if (high_bottom >= visible_bottom) {
565
+ return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
566
+ } else if (high_top < visible_top) {
567
+ return this.search_results.scrollTop(high_top);
568
+ }
569
+ }
570
+ };
571
+ Chosen.prototype.result_clear_highlight = function() {
572
+ if (this.result_highlight) {
573
+ this.result_highlight.removeClass("highlighted");
574
+ }
575
+ return this.result_highlight = null;
576
+ };
577
+ Chosen.prototype.results_show = function() {
578
+ var dd_top;
579
+ if (!this.is_multiple) {
580
+ this.selected_item.addClass("chzn-single-with-drop");
581
+ if (this.result_single_selected) {
582
+ this.result_do_highlight(this.result_single_selected);
583
+ }
584
+ }
585
+ dd_top = this.is_multiple ? this.container.height() : this.container.height() - 1;
586
+ this.dropdown.css({
587
+ "top": dd_top + "px",
588
+ "left": 0
589
+ });
590
+ this.results_showing = true;
591
+ this.search_field.focus();
592
+ this.search_field.val(this.search_field.val());
593
+ return this.winnow_results();
594
+ };
595
+ Chosen.prototype.results_hide = function() {
596
+ if (!this.is_multiple) {
597
+ this.selected_item.removeClass("chzn-single-with-drop");
598
+ }
599
+ this.result_clear_highlight();
600
+ this.dropdown.css({
601
+ "left": "-9000px"
602
+ });
603
+ return this.results_showing = false;
604
+ };
605
+ Chosen.prototype.set_tab_index = function(el) {
606
+ var ti;
607
+ if (this.form_field_jq.attr("tabindex")) {
608
+ ti = this.form_field_jq.attr("tabindex");
609
+ this.form_field_jq.attr("tabindex", -1);
610
+ if (this.is_multiple) {
611
+ return this.search_field.attr("tabindex", ti);
612
+ } else {
613
+ this.selected_item.attr("tabindex", ti);
614
+ return this.search_field.attr("tabindex", -1);
615
+ }
616
+ }
617
+ };
618
+ Chosen.prototype.show_search_field_default = function() {
619
+ if (this.is_multiple && this.choices < 1 && !this.active_field) {
620
+ this.search_field.val(this.default_text);
621
+ return this.search_field.addClass("default");
622
+ } else {
623
+ this.search_field.val("");
624
+ return this.search_field.removeClass("default");
625
+ }
626
+ };
627
+ Chosen.prototype.search_results_mouseup = function(evt) {
628
+ var target;
629
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
630
+ if (target.length) {
631
+ this.result_highlight = target;
632
+ return this.result_select(evt);
633
+ }
634
+ };
635
+ Chosen.prototype.search_results_mouseover = function(evt) {
636
+ var target;
637
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
638
+ if (target) {
639
+ return this.result_do_highlight(target);
640
+ }
641
+ };
642
+ Chosen.prototype.search_results_mouseout = function(evt) {
643
+ if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
644
+ return this.result_clear_highlight();
645
+ }
646
+ };
647
+ Chosen.prototype.choices_click = function(evt) {
648
+ evt.preventDefault();
649
+ if (this.active_field && !($(evt.target).hasClass("search-choice" || $(evt.target).parents('.search-choice').first)) && !this.results_showing) {
650
+ return this.results_show();
651
+ }
652
+ };
653
+ Chosen.prototype.choice_append = function(text, value) {
654
+ var i, item, opt, result, txt, val, _i, _len, _len2, _ref, _ref2;
655
+ txt = text != null ? text : $.trim(this.search_field.val());
656
+ val = value != null ? value : txt;
657
+ if (txt.length < 1 || val.length < 1) {
658
+ return this.results_hide();
659
+ }
660
+ _ref = this.form_field.options;
661
+ for (i = 0, _len = _ref.length; i < _len; i++) {
662
+ opt = _ref[i];
663
+ if (opt.value === val) {
664
+ if (opt.selected) {
665
+ return this.results_hide();
666
+ } else {
667
+ break;
668
+ }
669
+ }
670
+ }
671
+ _ref2 = this.results_data;
672
+ for (_i = 0, _len2 = _ref2.length; _i < _len2; _i++) {
673
+ result = _ref2[_i];
674
+ if (result.value === val) {
675
+ result.selected = true;
676
+ break;
677
+ }
678
+ }
679
+ if (i === this.form_field.length) {
680
+ this.form_field.options[i] = new Option(txt, val);
681
+ }
682
+ this.form_field.options[i].selected = true;
683
+ item = {
684
+ array_index: i,
685
+ options_index: i,
686
+ value: val,
687
+ text: txt,
688
+ html: txt,
689
+ selected: 1,
690
+ disabled: 0,
691
+ group_array_index: null
692
+ };
693
+ this.choice_build(item);
694
+ this.results_hide();
695
+ this.search_field.val("");
696
+ this.form_field_jq.trigger("change");
697
+ return this.search_field_scale();
698
+ };
699
+ Chosen.prototype.choice_build = function(item) {
700
+ var choice_id, link;
701
+ choice_id = this.container_id + "_c_" + item.array_index;
702
+ this.choices += 1;
703
+ this.search_container.before('<li class="search-choice" id="' + choice_id + '"><span>' + item.html + '</span><a href="javascript:void(0)" class="search-choice-close" rel="' + item.array_index + '"></a></li>');
704
+ link = $('#' + choice_id).find("a").first();
705
+ return link.click(__bind(function(evt) {
706
+ return this.choice_destroy_link_click(evt);
707
+ }, this));
708
+ };
709
+ Chosen.prototype.choice_destroy_link_click = function(evt) {
710
+ evt.preventDefault();
711
+ if (!this.is_disabled) {
712
+ this.pending_destroy_click = true;
713
+ return this.choice_destroy($(evt.target));
714
+ } else {
715
+ return evt.stopPropagation;
716
+ }
717
+ };
718
+ Chosen.prototype.choice_destroy = function(link) {
719
+ this.choices -= 1;
720
+ this.show_search_field_default();
721
+ if (this.is_multiple && this.choices > 0 && this.search_field.val().length < 1) {
722
+ this.results_hide();
723
+ }
724
+ this.result_deselect(link.attr("rel"));
725
+ return link.parents('li').first().remove();
726
+ };
727
+ Chosen.prototype.results_reset = function(evt) {
728
+ this.form_field.options[0].selected = true;
729
+ this.selected_item.find("span").text(this.default_text);
730
+ this.show_search_field_default();
731
+ $(evt.target).remove();
732
+ this.form_field_jq.trigger("change");
733
+ if (this.active_field) {
734
+ return this.results_hide();
735
+ }
736
+ };
737
+ Chosen.prototype.result_select = function(evt) {
738
+ var high, high_id, item, position;
739
+ if (this.result_highlight) {
740
+ high = this.result_highlight;
741
+ high_id = high.attr("id");
742
+ this.result_clear_highlight();
743
+ if (this.is_multiple) {
744
+ this.result_deactivate(high);
745
+ } else {
746
+ this.search_results.find(".result-selected").removeClass("result-selected");
747
+ this.result_single_selected = high;
748
+ }
749
+ high.addClass("result-selected");
750
+ position = high_id.substr(high_id.lastIndexOf("_") + 1);
751
+ item = this.results_data[position];
752
+ item.selected = true;
753
+ if (this.is_tag) {
754
+ this.choice_append(item.text, item.value);
755
+ } else {
756
+ this.form_field.options[item.options_index].selected = true;
757
+ if (this.is_multiple) {
758
+ this.choice_build(item);
759
+ } else {
760
+ this.selected_item.find("span").first().text(item.text);
761
+ if (this.allow_single_deselect) {
762
+ this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
763
+ }
764
+ }
765
+ }
766
+ if (!(evt.metaKey && this.is_multiple)) {
767
+ this.results_hide();
768
+ }
769
+ this.search_field.val("");
770
+ this.form_field_jq.trigger("change");
771
+ return this.search_field_scale();
772
+ }
773
+ };
774
+ Chosen.prototype.result_activate = function(el) {
775
+ return el.addClass("active-result");
776
+ };
777
+ Chosen.prototype.result_deactivate = function(el) {
778
+ return el.removeClass("active-result");
779
+ };
780
+ Chosen.prototype.result_deselect = function(pos) {
781
+ var result, result_data;
782
+ if (this.is_tag) {
783
+ this.form_field.options[pos].selected = false;
784
+ } else {
785
+ result_data = this.results_data[pos];
786
+ result_data.selected = false;
787
+ this.form_field.options[result_data.options_index].selected = false;
788
+ }
789
+ result = $("#" + this.container_id + "_o_" + pos);
790
+ result.removeClass("result-selected").addClass("active-result").show();
791
+ this.result_clear_highlight();
792
+ this.winnow_results();
793
+ this.form_field_jq.trigger("change");
794
+ return this.search_field_scale();
795
+ };
796
+ Chosen.prototype.winnow_results = function() {
797
+ var found, option, part, parts, regex, result_id, results, searchText, startTime, startpos, text, zregex, _i, _j, _len, _len2, _ref;
798
+ startTime = new Date();
799
+ this.no_results_clear();
800
+ results = 0;
801
+ searchText = this.search_field.val() === this.default_text ? "" : $('<div/>').text($.trim(this.search_field.val())).html();
802
+ regex = new RegExp('^' + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
803
+ zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
804
+ _ref = this.results_data;
805
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
806
+ option = _ref[_i];
807
+ if (!option.disabled && !option.empty) {
808
+ if (option.group) {
809
+ $('#' + option.dom_id).hide();
810
+ } else if (!(this.is_multiple && option.selected)) {
811
+ found = false;
812
+ result_id = option.dom_id;
813
+ if (regex.test(option.html)) {
814
+ found = true;
815
+ results += 1;
816
+ } else if (option.html.indexOf(" ") >= 0 || option.html.indexOf("[") === 0) {
817
+ parts = option.html.replace(/\[|\]/g, "").split(" ");
818
+ if (parts.length) {
819
+ for (_j = 0, _len2 = parts.length; _j < _len2; _j++) {
820
+ part = parts[_j];
821
+ if (regex.test(part)) {
822
+ found = true;
823
+ results += 1;
824
+ }
825
+ }
826
+ }
827
+ }
828
+ if (found) {
829
+ if (searchText.length) {
830
+ startpos = option.html.search(zregex);
831
+ text = option.html.substr(0, startpos + searchText.length) + '</em>' + option.html.substr(startpos + searchText.length);
832
+ text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
833
+ } else {
834
+ text = option.html;
835
+ }
836
+ if ($("#" + result_id).html !== text) {
837
+ $("#" + result_id).html(text);
838
+ }
839
+ this.result_activate($("#" + result_id));
840
+ if (option.group_array_index != null) {
841
+ $("#" + this.results_data[option.group_array_index].dom_id).show();
842
+ }
843
+ } else {
844
+ if (this.result_highlight && result_id === this.result_highlight.attr('id')) {
845
+ this.result_clear_highlight();
846
+ }
847
+ this.result_deactivate($("#" + result_id));
848
+ }
849
+ }
850
+ }
851
+ }
852
+ if (results < 1 && searchText.length) {
853
+ return this.no_results(searchText);
854
+ } else {
855
+ return this.winnow_results_set_highlight();
856
+ }
857
+ };
858
+ Chosen.prototype.winnow_results_clear = function() {
859
+ var li, lis, _i, _len, _results;
860
+ this.search_field.val("");
861
+ lis = this.search_results.find("li");
862
+ _results = [];
863
+ for (_i = 0, _len = lis.length; _i < _len; _i++) {
864
+ li = lis[_i];
865
+ li = $(li);
866
+ _results.push(li.hasClass("group-result") ? li.show() : !this.is_multiple || !li.hasClass("result-selected") ? this.result_activate(li) : void 0);
867
+ }
868
+ return _results;
869
+ };
870
+ Chosen.prototype.winnow_results_set_highlight = function() {
871
+ var do_high, selected_results;
872
+ if (!this.result_highlight) {
873
+ selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
874
+ do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
875
+ if (do_high != null) {
876
+ return this.result_do_highlight(do_high);
877
+ }
878
+ }
879
+ };
880
+ Chosen.prototype.no_results = function(terms) {
881
+ var no_results_html;
882
+ if (this.is_tag) {
883
+ return this.results_hide();
884
+ }
885
+ no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
886
+ no_results_html.find("span").first().html(terms);
887
+ return this.search_results.append(no_results_html);
888
+ };
889
+ Chosen.prototype.no_results_clear = function() {
890
+ return this.search_results.find(".no-results").remove();
891
+ };
892
+ Chosen.prototype.keydown_arrow = function() {
893
+ var first_active, next_sib;
894
+ if (!this.result_highlight) {
895
+ first_active = this.search_results.find("li.active-result").first();
896
+ if (first_active) {
897
+ this.result_do_highlight($(first_active));
898
+ }
899
+ } else if (this.results_showing) {
900
+ next_sib = this.result_highlight.nextAll("li.active-result").first();
901
+ if (next_sib) {
902
+ this.result_do_highlight(next_sib);
903
+ }
904
+ }
905
+ if (!this.results_showing) {
906
+ return this.results_show();
907
+ }
908
+ };
909
+ Chosen.prototype.keyup_arrow = function() {
910
+ var prev_sibs;
911
+ if (!this.results_showing && !this.is_multiple) {
912
+ return this.results_show();
913
+ } else if (this.result_highlight) {
914
+ prev_sibs = this.result_highlight.prevAll("li.active-result");
915
+ if (prev_sibs.length) {
916
+ return this.result_do_highlight(prev_sibs.first());
917
+ } else {
918
+ if (this.choices > 0) {
919
+ this.results_hide();
920
+ }
921
+ return this.result_clear_highlight();
922
+ }
923
+ }
924
+ };
925
+ Chosen.prototype.keydown_backstroke = function() {
926
+ if (this.pending_backstroke) {
927
+ this.choice_destroy(this.pending_backstroke.find("a").first());
928
+ return this.clear_backstroke();
929
+ } else {
930
+ this.pending_backstroke = this.search_container.siblings("li.search-choice").last();
931
+ return this.pending_backstroke.addClass("search-choice-focus");
932
+ }
933
+ };
934
+ Chosen.prototype.clear_backstroke = function() {
935
+ if (this.pending_backstroke) {
936
+ this.pending_backstroke.removeClass("search-choice-focus");
937
+ }
938
+ return this.pending_backstroke = null;
939
+ };
940
+ Chosen.prototype.keydown_checker = function(evt) {
941
+ var stroke, _ref;
942
+ stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
943
+ this.search_field_scale();
944
+ if (stroke !== 8 && this.pending_backstroke) {
945
+ this.clear_backstroke();
946
+ }
947
+ switch (stroke) {
948
+ case 8:
949
+ this.backstroke_length = this.search_field.val().length;
950
+ break;
951
+ case 9:
952
+ this.mouse_on_container = false;
953
+ break;
954
+ case 13:
955
+ evt.preventDefault();
956
+ break;
957
+ case 38:
958
+ evt.preventDefault();
959
+ this.keyup_arrow();
960
+ break;
961
+ case 40:
962
+ this.keydown_arrow();
963
+ break;
964
+ }
965
+ };
966
+ Chosen.prototype.search_field_scale = function() {
967
+ var dd_top, div, h, style, style_block, styles, w, _i, _len;
968
+ if (this.is_multiple) {
969
+ h = 0;
970
+ w = 0;
971
+ style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
972
+ styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
973
+ for (_i = 0, _len = styles.length; _i < _len; _i++) {
974
+ style = styles[_i];
975
+ style_block += style + ":" + this.search_field.css(style) + ";";
976
+ }
977
+ div = $('<div />', {
978
+ 'style': style_block
979
+ });
980
+ div.text(this.search_field.val());
981
+ $('body').append(div);
982
+ w = div.width() + 25;
983
+ div.remove();
984
+ if (w > this.f_width - 10) {
985
+ w = this.f_width - 10;
986
+ }
987
+ this.search_field.css({
988
+ 'width': w + 'px'
989
+ });
990
+ dd_top = this.container.height();
991
+ return this.dropdown.css({
992
+ "top": dd_top + "px"
993
+ });
994
+ }
995
+ };
996
+ Chosen.prototype.generate_random_id = function() {
997
+ var string;
998
+ string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char();
999
+ while ($("#" + string).length > 0) {
1000
+ string += this.generate_random_char();
1001
+ }
1002
+ return string;
1003
+ };
1004
+ return Chosen;
1005
+ })();
1006
+ get_side_border_padding = function(elmt) {
1007
+ var side_border_padding;
1008
+ return side_border_padding = elmt.outerWidth() - elmt.width();
1009
+ };
1010
+ root.get_side_border_padding = get_side_border_padding;
1011
+ }).call(this);