trln-chosen-rails 1.8.7

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.
@@ -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