trln-chosen-rails 1.8.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ require 'fileutils'
2
+
3
+ desc 'Create nondigest versions of all chosen digest assets'
4
+ task 'assets:precompile' do
5
+ fingerprint = /\-[0-9a-f]{32}\./
6
+ Dir['public/assets/chosen-*'].each do |file|
7
+ next unless file =~ fingerprint
8
+ nondigest = file.sub fingerprint, '.'
9
+ FileUtils.copy_entry file, nondigest, remove_destination: true
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ module Chosen
2
+ module Rails
3
+ VERSION = '1.8.7'
4
+ CHOSEN_VERSION = '1.8.7'
5
+ end
6
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/chosen-rails/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Tse-Ching Ho', 'Adam Constabaris']
6
+ gem.email = ['tsechingho@gmail.com']
7
+ gem.description = %q{Chosen is a javascript library of select box enhancer for jQuery and Protoype. This gem integrates Chosen with Rails asset pipeline for ease of use. This version removes the dependency on sass}
8
+ gem.summary = %q{Integrate Chosen javascript library with Rails asset pipeline}
9
+ gem.homepage = 'https://github.com/trln/chosen-rails'
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = 'trln-chosen-rails'
15
+ gem.require_paths = ['lib']
16
+ gem.version = Chosen::Rails::VERSION
17
+ gem.license = 'MIT'
18
+
19
+ gem.add_dependency 'railties', '>= 3.0'
20
+ gem.add_dependency 'coffee-rails', '>= 3.2'
21
+ gem.add_dependency 'sassc-rails', '>= 2.1'
22
+
23
+ gem.add_development_dependency 'bundler', '>= 1.0'
24
+ gem.add_development_dependency 'rails', '>= 3.0'
25
+ gem.add_development_dependency 'thor', '>= 0.14'
26
+ end
@@ -0,0 +1,3 @@
1
+ //= require lib/abstract-chosen
2
+ //= require lib/select-parser
3
+ //= require chosen.jquery
@@ -0,0 +1,3 @@
1
+ //= require lib/abstract-chosen
2
+ //= require lib/select-parser
3
+ //= require chosen.proto
@@ -0,0 +1,513 @@
1
+ $ = jQuery
2
+
3
+ $.fn.extend({
4
+ chosen: (options) ->
5
+ # Do no harm and return as soon as possible for unsupported browsers, namely IE6 and IE7
6
+ # Continue on if running IE document type but in compatibility mode
7
+ return this unless AbstractChosen.browser_is_supported()
8
+ this.each (input_field) ->
9
+ $this = $ this
10
+ chosen = $this.data('chosen')
11
+ if options is 'destroy'
12
+ if chosen instanceof Chosen
13
+ chosen.destroy()
14
+ return
15
+ unless chosen instanceof Chosen
16
+ $this.data('chosen', new Chosen(this, options))
17
+
18
+ return
19
+
20
+ })
21
+
22
+ class Chosen extends AbstractChosen
23
+
24
+ setup: ->
25
+ @form_field_jq = $ @form_field
26
+ @current_selectedIndex = @form_field.selectedIndex
27
+
28
+ set_up_html: ->
29
+ container_classes = ["chosen-container"]
30
+ container_classes.push "chosen-container-" + (if @is_multiple then "multi" else "single")
31
+ container_classes.push @form_field.className if @inherit_select_classes && @form_field.className
32
+ container_classes.push "chosen-rtl" if @is_rtl
33
+
34
+ container_props =
35
+ 'class': container_classes.join ' '
36
+ 'title': @form_field.title
37
+
38
+ container_props.id = @form_field.id.replace(/[^\w]/g, '_') + "_chosen" if @form_field.id.length
39
+
40
+ @container = ($ "<div />", container_props)
41
+
42
+ # CSP without 'unsafe-inline' doesn't allow setting the style attribute directly
43
+ @container.width this.container_width()
44
+
45
+ if @is_multiple
46
+ @container.html this.get_multi_html()
47
+ else
48
+ @container.html this.get_single_html()
49
+
50
+ @form_field_jq.hide().after @container
51
+ @dropdown = @container.find('div.chosen-drop').first()
52
+
53
+ @search_field = @container.find('input').first()
54
+ @search_results = @container.find('ul.chosen-results').first()
55
+ this.search_field_scale()
56
+
57
+ @search_no_results = @container.find('li.no-results').first()
58
+
59
+ if @is_multiple
60
+ @search_choices = @container.find('ul.chosen-choices').first()
61
+ @search_container = @container.find('li.search-field').first()
62
+ else
63
+ @search_container = @container.find('div.chosen-search').first()
64
+ @selected_item = @container.find('.chosen-single').first()
65
+
66
+ this.results_build()
67
+ this.set_tab_index()
68
+ this.set_label_behavior()
69
+
70
+ on_ready: ->
71
+ @form_field_jq.trigger("chosen:ready", {chosen: this})
72
+
73
+ register_observers: ->
74
+ @container.on 'touchstart.chosen', (evt) => this.container_mousedown(evt); return
75
+ @container.on 'touchend.chosen', (evt) => this.container_mouseup(evt); return
76
+
77
+ @container.on 'mousedown.chosen', (evt) => this.container_mousedown(evt); return
78
+ @container.on 'mouseup.chosen', (evt) => this.container_mouseup(evt); return
79
+ @container.on 'mouseenter.chosen', (evt) => this.mouse_enter(evt); return
80
+ @container.on 'mouseleave.chosen', (evt) => this.mouse_leave(evt); return
81
+
82
+ @search_results.on 'mouseup.chosen', (evt) => this.search_results_mouseup(evt); return
83
+ @search_results.on 'mouseover.chosen', (evt) => this.search_results_mouseover(evt); return
84
+ @search_results.on 'mouseout.chosen', (evt) => this.search_results_mouseout(evt); return
85
+ @search_results.on 'mousewheel.chosen DOMMouseScroll.chosen', (evt) => this.search_results_mousewheel(evt); return
86
+
87
+ @search_results.on 'touchstart.chosen', (evt) => this.search_results_touchstart(evt); return
88
+ @search_results.on 'touchmove.chosen', (evt) => this.search_results_touchmove(evt); return
89
+ @search_results.on 'touchend.chosen', (evt) => this.search_results_touchend(evt); return
90
+
91
+ @form_field_jq.on "chosen:updated.chosen", (evt) => this.results_update_field(evt); return
92
+ @form_field_jq.on "chosen:activate.chosen", (evt) => this.activate_field(evt); return
93
+ @form_field_jq.on "chosen:open.chosen", (evt) => this.container_mousedown(evt); return
94
+ @form_field_jq.on "chosen:close.chosen", (evt) => this.close_field(evt); return
95
+
96
+ @search_field.on 'blur.chosen', (evt) => this.input_blur(evt); return
97
+ @search_field.on 'keyup.chosen', (evt) => this.keyup_checker(evt); return
98
+ @search_field.on 'keydown.chosen', (evt) => this.keydown_checker(evt); return
99
+ @search_field.on 'focus.chosen', (evt) => this.input_focus(evt); return
100
+ @search_field.on 'cut.chosen', (evt) => this.clipboard_event_checker(evt); return
101
+ @search_field.on 'paste.chosen', (evt) => this.clipboard_event_checker(evt); return
102
+
103
+ if @is_multiple
104
+ @search_choices.on 'click.chosen', (evt) => this.choices_click(evt); return
105
+ else
106
+ @container.on 'click.chosen', (evt) -> evt.preventDefault(); return # gobble click of anchor
107
+
108
+ destroy: ->
109
+ $(@container[0].ownerDocument).off 'click.chosen', @click_test_action
110
+ @form_field_label.off 'click.chosen' if @form_field_label.length > 0
111
+
112
+ if @search_field[0].tabIndex
113
+ @form_field_jq[0].tabIndex = @search_field[0].tabIndex
114
+
115
+ @container.remove()
116
+ @form_field_jq.removeData('chosen')
117
+ @form_field_jq.show()
118
+
119
+ search_field_disabled: ->
120
+ @is_disabled = @form_field.disabled || @form_field_jq.parents('fieldset').is(':disabled')
121
+
122
+ @container.toggleClass 'chosen-disabled', @is_disabled
123
+ @search_field[0].disabled = @is_disabled
124
+
125
+ unless @is_multiple
126
+ @selected_item.off 'focus.chosen', this.activate_field
127
+
128
+ if @is_disabled
129
+ this.close_field()
130
+ else unless @is_multiple
131
+ @selected_item.on 'focus.chosen', this.activate_field
132
+
133
+ container_mousedown: (evt) ->
134
+ return if @is_disabled
135
+
136
+ if evt and evt.type in ['mousedown', 'touchstart'] and not @results_showing
137
+ evt.preventDefault()
138
+
139
+ if not (evt? and ($ evt.target).hasClass "search-choice-close")
140
+ if not @active_field
141
+ @search_field.val "" if @is_multiple
142
+ $(@container[0].ownerDocument).on 'click.chosen', @click_test_action
143
+ this.results_show()
144
+ else if not @is_multiple and evt and (($(evt.target)[0] == @selected_item[0]) || $(evt.target).parents("a.chosen-single").length)
145
+ evt.preventDefault()
146
+ this.results_toggle()
147
+
148
+ this.activate_field()
149
+
150
+ container_mouseup: (evt) ->
151
+ this.results_reset(evt) if evt.target.nodeName is "ABBR" and not @is_disabled
152
+
153
+ search_results_mousewheel: (evt) ->
154
+ delta = evt.originalEvent.deltaY or -evt.originalEvent.wheelDelta or evt.originalEvent.detail if evt.originalEvent
155
+ if delta?
156
+ evt.preventDefault()
157
+ delta = delta * 40 if evt.type is 'DOMMouseScroll'
158
+ @search_results.scrollTop(delta + @search_results.scrollTop())
159
+
160
+ blur_test: (evt) ->
161
+ this.close_field() if not @active_field and @container.hasClass "chosen-container-active"
162
+
163
+ close_field: ->
164
+ $(@container[0].ownerDocument).off "click.chosen", @click_test_action
165
+
166
+ @active_field = false
167
+ this.results_hide()
168
+
169
+ @container.removeClass "chosen-container-active"
170
+ this.clear_backstroke()
171
+
172
+ this.show_search_field_default()
173
+ this.search_field_scale()
174
+ @search_field.blur()
175
+
176
+ activate_field: ->
177
+ return if @is_disabled
178
+
179
+ @container.addClass "chosen-container-active"
180
+ @active_field = true
181
+
182
+ @search_field.val(@search_field.val())
183
+ @search_field.focus()
184
+
185
+
186
+ test_active_click: (evt) ->
187
+ active_container = $(evt.target).closest('.chosen-container')
188
+ if active_container.length and @container[0] == active_container[0]
189
+ @active_field = true
190
+ else
191
+ this.close_field()
192
+
193
+ results_build: ->
194
+ @parsing = true
195
+ @selected_option_count = null
196
+
197
+ @results_data = SelectParser.select_to_array @form_field
198
+
199
+ if @is_multiple
200
+ @search_choices.find("li.search-choice").remove()
201
+ else
202
+ this.single_set_selected_text()
203
+ if @disable_search or @form_field.options.length <= @disable_search_threshold
204
+ @search_field[0].readOnly = true
205
+ @container.addClass "chosen-container-single-nosearch"
206
+ else
207
+ @search_field[0].readOnly = false
208
+ @container.removeClass "chosen-container-single-nosearch"
209
+
210
+ this.update_results_content this.results_option_build({first:true})
211
+
212
+ this.search_field_disabled()
213
+ this.show_search_field_default()
214
+ this.search_field_scale()
215
+
216
+ @parsing = false
217
+
218
+ result_do_highlight: (el) ->
219
+ if el.length
220
+ this.result_clear_highlight()
221
+
222
+ @result_highlight = el
223
+ @result_highlight.addClass "highlighted"
224
+
225
+ maxHeight = parseInt @search_results.css("maxHeight"), 10
226
+ visible_top = @search_results.scrollTop()
227
+ visible_bottom = maxHeight + visible_top
228
+
229
+ high_top = @result_highlight.position().top + @search_results.scrollTop()
230
+ high_bottom = high_top + @result_highlight.outerHeight()
231
+
232
+ if high_bottom >= visible_bottom
233
+ @search_results.scrollTop if (high_bottom - maxHeight) > 0 then (high_bottom - maxHeight) else 0
234
+ else if high_top < visible_top
235
+ @search_results.scrollTop high_top
236
+
237
+ result_clear_highlight: ->
238
+ @result_highlight.removeClass "highlighted" if @result_highlight
239
+ @result_highlight = null
240
+
241
+ results_show: ->
242
+ if @is_multiple and @max_selected_options <= this.choices_count()
243
+ @form_field_jq.trigger("chosen:maxselected", {chosen: this})
244
+ return false
245
+
246
+ @container.addClass "chosen-with-drop"
247
+ @results_showing = true
248
+
249
+ @search_field.focus()
250
+ @search_field.val this.get_search_field_value()
251
+
252
+ this.winnow_results()
253
+ @form_field_jq.trigger("chosen:showing_dropdown", {chosen: this})
254
+
255
+ update_results_content: (content) ->
256
+ @search_results.html content
257
+
258
+ results_hide: ->
259
+ if @results_showing
260
+ this.result_clear_highlight()
261
+
262
+ @container.removeClass "chosen-with-drop"
263
+ @form_field_jq.trigger("chosen:hiding_dropdown", {chosen: this})
264
+
265
+ @results_showing = false
266
+
267
+
268
+ set_tab_index: (el) ->
269
+ if @form_field.tabIndex
270
+ ti = @form_field.tabIndex
271
+ @form_field.tabIndex = -1
272
+ @search_field[0].tabIndex = ti
273
+
274
+ set_label_behavior: ->
275
+ @form_field_label = @form_field_jq.parents("label") # first check for a parent label
276
+ if not @form_field_label.length and @form_field.id.length
277
+ @form_field_label = $("label[for='#{@form_field.id}']") #next check for a for=#{id}
278
+
279
+ if @form_field_label.length > 0
280
+ @form_field_label.on 'click.chosen', this.label_click_handler
281
+
282
+ show_search_field_default: ->
283
+ if @is_multiple and this.choices_count() < 1 and not @active_field
284
+ @search_field.val(@default_text)
285
+ @search_field.addClass "default"
286
+ else
287
+ @search_field.val("")
288
+ @search_field.removeClass "default"
289
+
290
+ search_results_mouseup: (evt) ->
291
+ target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first()
292
+ if target.length
293
+ @result_highlight = target
294
+ this.result_select(evt)
295
+ @search_field.focus()
296
+
297
+ search_results_mouseover: (evt) ->
298
+ target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first()
299
+ this.result_do_highlight( target ) if target
300
+
301
+ search_results_mouseout: (evt) ->
302
+ this.result_clear_highlight() if $(evt.target).hasClass("active-result") or $(evt.target).parents('.active-result').first()
303
+
304
+ choice_build: (item) ->
305
+ choice = $('<li />', { class: "search-choice" }).html("<span>#{this.choice_label(item)}</span>")
306
+
307
+ if item.disabled
308
+ choice.addClass 'search-choice-disabled'
309
+ else
310
+ close_link = $('<a />', { class: 'search-choice-close', 'data-option-array-index': item.array_index })
311
+ close_link.on 'click.chosen', (evt) => this.choice_destroy_link_click(evt)
312
+ choice.append close_link
313
+
314
+ @search_container.before choice
315
+
316
+ choice_destroy_link_click: (evt) ->
317
+ evt.preventDefault()
318
+ evt.stopPropagation()
319
+ this.choice_destroy $(evt.target) unless @is_disabled
320
+
321
+ choice_destroy: (link) ->
322
+ if this.result_deselect( link[0].getAttribute("data-option-array-index") )
323
+ if @active_field
324
+ @search_field.focus()
325
+ else
326
+ this.show_search_field_default()
327
+
328
+ this.results_hide() if @is_multiple and this.choices_count() > 0 and this.get_search_field_value().length < 1
329
+
330
+ link.parents('li').first().remove()
331
+
332
+ this.search_field_scale()
333
+
334
+ results_reset: ->
335
+ this.reset_single_select_options()
336
+ @form_field.options[0].selected = true
337
+ this.single_set_selected_text()
338
+ this.show_search_field_default()
339
+ this.results_reset_cleanup()
340
+ this.trigger_form_field_change()
341
+ this.results_hide() if @active_field
342
+
343
+ results_reset_cleanup: ->
344
+ @current_selectedIndex = @form_field.selectedIndex
345
+ @selected_item.find("abbr").remove()
346
+
347
+ result_select: (evt) ->
348
+ if @result_highlight
349
+ high = @result_highlight
350
+
351
+ this.result_clear_highlight()
352
+
353
+ if @is_multiple and @max_selected_options <= this.choices_count()
354
+ @form_field_jq.trigger("chosen:maxselected", {chosen: this})
355
+ return false
356
+
357
+ if @is_multiple
358
+ high.removeClass("active-result")
359
+ else
360
+ this.reset_single_select_options()
361
+
362
+ high.addClass("result-selected")
363
+
364
+ item = @results_data[ high[0].getAttribute("data-option-array-index") ]
365
+ item.selected = true
366
+
367
+ @form_field.options[item.options_index].selected = true
368
+ @selected_option_count = null
369
+
370
+ if @is_multiple
371
+ this.choice_build item
372
+ else
373
+ this.single_set_selected_text(this.choice_label(item))
374
+
375
+ if @is_multiple && (!@hide_results_on_select || (evt.metaKey or evt.ctrlKey))
376
+ if evt.metaKey or evt.ctrlKey
377
+ this.winnow_results(skip_highlight: true)
378
+ else
379
+ @search_field.val("")
380
+ this.winnow_results()
381
+ else
382
+ this.results_hide()
383
+ this.show_search_field_default()
384
+
385
+ this.trigger_form_field_change selected: @form_field.options[item.options_index].value if @is_multiple || @form_field.selectedIndex != @current_selectedIndex
386
+ @current_selectedIndex = @form_field.selectedIndex
387
+
388
+ evt.preventDefault()
389
+
390
+ this.search_field_scale()
391
+
392
+ single_set_selected_text: (text=@default_text) ->
393
+ if text is @default_text
394
+ @selected_item.addClass("chosen-default")
395
+ else
396
+ this.single_deselect_control_build()
397
+ @selected_item.removeClass("chosen-default")
398
+
399
+ @selected_item.find("span").html(text)
400
+
401
+ result_deselect: (pos) ->
402
+ result_data = @results_data[pos]
403
+
404
+ if not @form_field.options[result_data.options_index].disabled
405
+ result_data.selected = false
406
+
407
+ @form_field.options[result_data.options_index].selected = false
408
+ @selected_option_count = null
409
+
410
+ this.result_clear_highlight()
411
+ this.winnow_results() if @results_showing
412
+
413
+ this.trigger_form_field_change deselected: @form_field.options[result_data.options_index].value
414
+ this.search_field_scale()
415
+
416
+ return true
417
+ else
418
+ return false
419
+
420
+ single_deselect_control_build: ->
421
+ return unless @allow_single_deselect
422
+ @selected_item.find("span").first().after "<abbr class=\"search-choice-close\"></abbr>" unless @selected_item.find("abbr").length
423
+ @selected_item.addClass("chosen-single-with-deselect")
424
+
425
+ get_search_field_value: ->
426
+ @search_field.val()
427
+
428
+ get_search_text: ->
429
+ $.trim this.get_search_field_value()
430
+
431
+ escape_html: (text) ->
432
+ $('<div/>').text(text).html()
433
+
434
+ winnow_results_set_highlight: ->
435
+ selected_results = if not @is_multiple then @search_results.find(".result-selected.active-result") else []
436
+ do_high = if selected_results.length then selected_results.first() else @search_results.find(".active-result").first()
437
+
438
+ this.result_do_highlight do_high if do_high?
439
+
440
+ no_results: (terms) ->
441
+ no_results_html = this.get_no_results_html(terms)
442
+ @search_results.append no_results_html
443
+ @form_field_jq.trigger("chosen:no_results", {chosen:this})
444
+
445
+ no_results_clear: ->
446
+ @search_results.find(".no-results").remove()
447
+
448
+ keydown_arrow: ->
449
+ if @results_showing and @result_highlight
450
+ next_sib = @result_highlight.nextAll("li.active-result").first()
451
+ this.result_do_highlight next_sib if next_sib
452
+ else
453
+ this.results_show()
454
+
455
+ keyup_arrow: ->
456
+ if not @results_showing and not @is_multiple
457
+ this.results_show()
458
+ else if @result_highlight
459
+ prev_sibs = @result_highlight.prevAll("li.active-result")
460
+
461
+ if prev_sibs.length
462
+ this.result_do_highlight prev_sibs.first()
463
+ else
464
+ this.results_hide() if this.choices_count() > 0
465
+ this.result_clear_highlight()
466
+
467
+ keydown_backstroke: ->
468
+ if @pending_backstroke
469
+ this.choice_destroy @pending_backstroke.find("a").first()
470
+ this.clear_backstroke()
471
+ else
472
+ next_available_destroy = @search_container.siblings("li.search-choice").last()
473
+ if next_available_destroy.length and not next_available_destroy.hasClass("search-choice-disabled")
474
+ @pending_backstroke = next_available_destroy
475
+ if @single_backstroke_delete
476
+ @keydown_backstroke()
477
+ else
478
+ @pending_backstroke.addClass "search-choice-focus"
479
+
480
+ clear_backstroke: ->
481
+ @pending_backstroke.removeClass "search-choice-focus" if @pending_backstroke
482
+ @pending_backstroke = null
483
+
484
+ search_field_scale: ->
485
+ return unless @is_multiple
486
+
487
+ style_block =
488
+ position: 'absolute'
489
+ left: '-1000px'
490
+ top: '-1000px'
491
+ display: 'none'
492
+ whiteSpace: 'pre'
493
+
494
+ styles = ['fontSize', 'fontStyle', 'fontWeight', 'fontFamily', 'lineHeight', 'textTransform', 'letterSpacing']
495
+
496
+ for style in styles
497
+ style_block[style] = @search_field.css(style)
498
+
499
+ div = $('<div />').css(style_block)
500
+ div.text this.get_search_field_value()
501
+ $('body').append div
502
+
503
+ width = div.width() + 25
504
+ div.remove()
505
+
506
+ if @container.is(':visible')
507
+ width = Math.min(@container.outerWidth() - 10, width)
508
+
509
+ @search_field.width(width)
510
+
511
+ trigger_form_field_change: (extra) ->
512
+ @form_field_jq.trigger "input", extra
513
+ @form_field_jq.trigger "change", extra