diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 85c5feaf883..60e58ade1cd 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -86,7 +86,7 @@ This file is generated by `grunt build`, do not edit it by hand. watch: default: files: ['coffee/**/*.coffee', 'sass/*.scss'] - tasks: ['build', 'jasmine'] + tasks: ['coffeelint', 'build', 'jasmine'] test: files: ['spec/**/*.coffee'] tasks: ['jasmine'] @@ -108,6 +108,12 @@ This file is generated by `grunt build`, do not edit it by hand. specs: 'spec/public/proto_specs.js' src: [ 'public/chosen.proto.js' ] + coffeelint: + main: + src: [ 'coffee/**/*.coffee' ] + options: + configFile: 'coffeelint.json' + grunt.loadTasks 'tasks' grunt.registerTask 'default', ['build'] diff --git a/coffee/chosen.jquery.coffee b/coffee/chosen.jquery.coffee index 95b7b878bb8..524cba7437b 100644 --- a/coffee/chosen.jquery.coffee +++ b/coffee/chosen.jquery.coffee @@ -26,18 +26,18 @@ class Chosen extends AbstractChosen @current_selectedIndex = @form_field.selectedIndex set_up_html: -> - container_classes = ["chosen-container"] - container_classes.push "chosen-container-" + (if @is_multiple then "multi" else "single") + container_classes = ['chosen-container'] + container_classes.push 'chosen-container-' + (if @is_multiple then 'multi' else 'single') container_classes.push @form_field.className if @inherit_select_classes && @form_field.className - container_classes.push "chosen-rtl" if @is_rtl + container_classes.push 'chosen-rtl' if @is_rtl container_props = - 'class': container_classes.join ' ' - 'title': @form_field.title + class: container_classes.join ' ' + title: @form_field.title - container_props.id = @form_field.id.replace(/[^\w]/g, '_') + "_chosen" if @form_field.id.length + container_props.id = @form_field.id.replace(/[^\w]/g, '_') + '_chosen' if @form_field.id.length - @container = ($ "
", container_props) + @container = $('', container_props) # CSP without 'unsafe-inline' doesn't allow setting the style attribute directly @container.width this.container_width() @@ -68,7 +68,7 @@ class Chosen extends AbstractChosen this.set_label_behavior() on_ready: -> - @form_field_jq.trigger("chosen:ready", {chosen: this}) + @form_field_jq.trigger('chosen:ready', { chosen: this }) register_observers: -> @container.bind 'touchstart.chosen', (evt) => this.container_mousedown(evt); return @@ -88,10 +88,10 @@ class Chosen extends AbstractChosen @search_results.bind 'touchmove.chosen', (evt) => this.search_results_touchmove(evt); return @search_results.bind 'touchend.chosen', (evt) => this.search_results_touchend(evt); return - @form_field_jq.bind "chosen:updated.chosen", (evt) => this.results_update_field(evt); return - @form_field_jq.bind "chosen:activate.chosen", (evt) => this.activate_field(evt); return - @form_field_jq.bind "chosen:open.chosen", (evt) => this.container_mousedown(evt); return - @form_field_jq.bind "chosen:close.chosen", (evt) => this.close_field(evt); return + @form_field_jq.bind 'chosen:updated.chosen', (evt) => this.results_update_field(evt); return + @form_field_jq.bind 'chosen:activate.chosen', (evt) => this.activate_field(evt); return + @form_field_jq.bind 'chosen:open.chosen', (evt) => this.container_mousedown(evt); return + @form_field_jq.bind 'chosen:close.chosen', (evt) => this.close_field(evt); return @search_field.bind 'blur.chosen', (evt) => this.input_blur(evt); return @search_field.bind 'keyup.chosen', (evt) => this.keyup_checker(evt); return @@ -136,19 +136,20 @@ class Chosen extends AbstractChosen if evt and evt.type in ['mousedown', 'touchstart'] and not @results_showing evt.preventDefault() - if not (evt? and ($ evt.target).hasClass "search-choice-close") + if not (evt? and ($ evt.target).hasClass 'search-choice-close') if not @active_field - @search_field.val "" if @is_multiple + @search_field.val '' if @is_multiple $(@container[0].ownerDocument).bind 'click.chosen', @click_test_action this.results_show() - else if not @is_multiple and evt and (($(evt.target)[0] == @selected_item[0]) || $(evt.target).parents("a.chosen-single").length) - evt.preventDefault() - this.results_toggle() + else if not @is_multiple and evt + if $(evt.target)[0] == @selected_item[0] or $(evt.target).parents('a.chosen-single').length + evt.preventDefault() + this.results_toggle() this.activate_field() container_mouseup: (evt) -> - this.results_reset(evt) if evt.target.nodeName is "ABBR" and not @is_disabled + this.results_reset(evt) if evt.target.nodeName is 'ABBR' and not @is_disabled search_results_mousewheel: (evt) -> delta = evt.originalEvent.deltaY or -evt.originalEvent.wheelDelta or evt.originalEvent.detail if evt.originalEvent @@ -158,15 +159,15 @@ class Chosen extends AbstractChosen @search_results.scrollTop(delta + @search_results.scrollTop()) blur_test: (evt) -> - this.close_field() if not @active_field and @container.hasClass "chosen-container-active" + this.close_field() if not @active_field and @container.hasClass 'chosen-container-active' close_field: -> - $(@container[0].ownerDocument).unbind "click.chosen", @click_test_action + $(@container[0].ownerDocument).unbind 'click.chosen', @click_test_action @active_field = false this.results_hide() - @container.removeClass "chosen-container-active" + @container.removeClass 'chosen-container-active' this.clear_backstroke() this.show_search_field_default() @@ -176,7 +177,7 @@ class Chosen extends AbstractChosen activate_field: -> return if @is_disabled - @container.addClass "chosen-container-active" + @container.addClass 'chosen-container-active' @active_field = true @search_field.val(@search_field.val()) @@ -197,17 +198,17 @@ class Chosen extends AbstractChosen @results_data = SelectParser.select_to_array @form_field if @is_multiple - @search_choices.find("li.search-choice").remove() + @search_choices.find('li.search-choice').remove() else if not @is_multiple this.single_set_selected_text() if @disable_search or @form_field.options.length <= @disable_search_threshold @search_field[0].readOnly = true - @container.addClass "chosen-container-single-nosearch" + @container.addClass 'chosen-container-single-nosearch' else @search_field[0].readOnly = false - @container.removeClass "chosen-container-single-nosearch" + @container.removeClass 'chosen-container-single-nosearch' - this.update_results_content this.results_option_build({first:true}) + this.update_results_content this.results_option_build({ first: true }) this.search_field_disabled() this.show_search_field_default() @@ -220,9 +221,9 @@ class Chosen extends AbstractChosen this.result_clear_highlight() @result_highlight = el - @result_highlight.addClass "highlighted" + @result_highlight.addClass 'highlighted' - maxHeight = parseInt @search_results.css("maxHeight"), 10 + maxHeight = parseInt @search_results.css('maxHeight'), 10 visible_top = @search_results.scrollTop() visible_bottom = maxHeight + visible_top @@ -235,22 +236,22 @@ class Chosen extends AbstractChosen @search_results.scrollTop high_top result_clear_highlight: -> - @result_highlight.removeClass "highlighted" if @result_highlight + @result_highlight.removeClass 'highlighted' if @result_highlight @result_highlight = null results_show: -> if @is_multiple and @max_selected_options <= this.choices_count() - @form_field_jq.trigger("chosen:maxselected", {chosen: this}) + @form_field_jq.trigger('chosen:maxselected', { chosen: this }) return false - @container.addClass "chosen-with-drop" + @container.addClass 'chosen-with-drop' @results_showing = true @search_field.focus() @search_field.val this.get_search_field_value() this.winnow_results() - @form_field_jq.trigger("chosen:showing_dropdown", {chosen: this}) + @form_field_jq.trigger('chosen:showing_dropdown', { chosen: this }) update_results_content: (content) -> @search_results.html content @@ -259,8 +260,8 @@ class Chosen extends AbstractChosen if @results_showing this.result_clear_highlight() - @container.removeClass "chosen-with-drop" - @form_field_jq.trigger("chosen:hiding_dropdown", {chosen: this}) + @container.removeClass 'chosen-with-drop' + @form_field_jq.trigger('chosen:hiding_dropdown', { chosen: this }) @results_showing = false @@ -272,7 +273,7 @@ class Chosen extends AbstractChosen @search_field[0].tabIndex = ti set_label_behavior: -> - @form_field_label = @form_field_jq.parents("label") # first check for a parent label + @form_field_label = @form_field_jq.parents('label') # first check for a parent label if not @form_field_label.length and @form_field.id.length @form_field_label = $("label[for='#{@form_field.id}']") #next check for a for=#{id} @@ -282,27 +283,34 @@ class Chosen extends AbstractChosen show_search_field_default: -> if @is_multiple and this.choices_count() < 1 and not @active_field @search_field.val(@default_text) - @search_field.addClass "default" + @search_field.addClass 'default' else - @search_field.val("") - @search_field.removeClass "default" + @search_field.val('') + @search_field.removeClass 'default' search_results_mouseup: (evt) -> - target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first() + target = if $(evt.target).hasClass 'active-result' + $(evt.target) + else + $(evt.target).parents('.active-result').first() if target.length @result_highlight = target this.result_select(evt) @search_field.focus() search_results_mouseover: (evt) -> - target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first() + target = if $(evt.target).hasClass 'active-result' + $(evt.target) + else + $(evt.target).parents('.active-result').first() this.result_do_highlight( target ) if target search_results_mouseout: (evt) -> - this.result_clear_highlight() if $(evt.target).hasClass "active-result" or $(evt.target).parents('.active-result').first() + if $(evt.target).hasClass 'active-result' or $(evt.target).parents('.active-result').first() + this.result_clear_highlight() choice_build: (item) -> - choice = $('', { class: "search-choice" }).html("#{this.choice_label(item)}") + choice = $('', { class: 'search-choice' }).html("#{this.choice_label(item)}") if item.disabled choice.addClass 'search-choice-disabled' @@ -319,7 +327,7 @@ class Chosen extends AbstractChosen this.choice_destroy $(evt.target) unless @is_disabled choice_destroy: (link) -> - if this.result_deselect( link[0].getAttribute("data-option-array-index") ) + if this.result_deselect( link[0].getAttribute('data-option-array-index') ) if @active_field @search_field.focus() else @@ -342,7 +350,7 @@ class Chosen extends AbstractChosen results_reset_cleanup: -> @current_selectedIndex = @form_field.selectedIndex - @selected_item.find("abbr").remove() + @selected_item.find('abbr').remove() result_select: (evt) -> if @result_highlight @@ -351,17 +359,17 @@ class Chosen extends AbstractChosen this.result_clear_highlight() if @is_multiple and @max_selected_options <= this.choices_count() - @form_field_jq.trigger("chosen:maxselected", {chosen: this}) + @form_field_jq.trigger('chosen:maxselected', { chosen: this }) return false if @is_multiple - high.removeClass("active-result") + high.removeClass('active-result') else this.reset_single_select_options() - high.addClass("result-selected") + high.addClass('result-selected') - item = @results_data[ high[0].getAttribute("data-option-array-index") ] + item = @results_data[ high[0].getAttribute('data-option-array-index') ] item.selected = true @form_field.options[item.options_index].selected = true @@ -376,21 +384,22 @@ class Chosen extends AbstractChosen this.results_hide() this.show_search_field_default() - this.trigger_form_field_change selected: @form_field.options[item.options_index].value if @is_multiple || @form_field.selectedIndex != @current_selectedIndex + if @is_multiple || @form_field.selectedIndex != @current_selectedIndex + this.trigger_form_field_change selected: @form_field.options[item.options_index].value @current_selectedIndex = @form_field.selectedIndex evt.preventDefault() this.search_field_scale() - single_set_selected_text: (text=@default_text) -> + single_set_selected_text: (text = @default_text) -> if text is @default_text - @selected_item.addClass("chosen-default") + @selected_item.addClass('chosen-default') else this.single_deselect_control_build() - @selected_item.removeClass("chosen-default") + @selected_item.removeClass('chosen-default') - @selected_item.find("span").html(text) + @selected_item.find('span').html(text) result_deselect: (pos) -> result_data = @results_data[pos] @@ -413,8 +422,9 @@ class Chosen extends AbstractChosen single_deselect_control_build: -> return unless @allow_single_deselect - @selected_item.find("span").first().after "" unless @selected_item.find("abbr").length - @selected_item.addClass("chosen-single-with-deselect") + unless @selected_item.find('abbr').length + @selected_item.find('span').first().after '' + @selected_item.addClass('chosen-single-with-deselect') get_search_field_value: -> @search_field.val() @@ -426,22 +436,25 @@ class Chosen extends AbstractChosen $('').text(text).html() winnow_results_set_highlight: -> - selected_results = if not @is_multiple then @search_results.find(".result-selected.active-result") else [] - do_high = if selected_results.length then selected_results.first() else @search_results.find(".active-result").first() + selected_results = if not @is_multiple then @search_results.find('.result-selected.active-result') else [] + do_high = if selected_results.length + selected_results.first() + else + @search_results.find('.active-result').first() this.result_do_highlight do_high if do_high? no_results: (terms) -> no_results_html = this.get_no_results_html(terms) @search_results.append no_results_html - @form_field_jq.trigger("chosen:no_results", {chosen:this}) + @form_field_jq.trigger('chosen:no_results', { chosen: this }) no_results_clear: -> - @search_results.find(".no-results").remove() + @search_results.find('.no-results').remove() keydown_arrow: -> if @results_showing and @result_highlight - next_sib = @result_highlight.nextAll("li.active-result").first() + next_sib = @result_highlight.nextAll('li.active-result').first() this.result_do_highlight next_sib if next_sib else this.results_show() @@ -450,7 +463,7 @@ class Chosen extends AbstractChosen if not @results_showing and not @is_multiple this.results_show() else if @result_highlight - prev_sibs = @result_highlight.prevAll("li.active-result") + prev_sibs = @result_highlight.prevAll('li.active-result') if prev_sibs.length this.result_do_highlight prev_sibs.first() @@ -460,19 +473,19 @@ class Chosen extends AbstractChosen keydown_backstroke: -> if @pending_backstroke - this.choice_destroy @pending_backstroke.find("a").first() + this.choice_destroy @pending_backstroke.find('a').first() this.clear_backstroke() else - next_available_destroy = @search_container.siblings("li.search-choice").last() - if next_available_destroy.length and not next_available_destroy.hasClass("search-choice-disabled") + next_available_destroy = @search_container.siblings('li.search-choice').last() + if next_available_destroy.length and not next_available_destroy.hasClass('search-choice-disabled') @pending_backstroke = next_available_destroy if @single_backstroke_delete @keydown_backstroke() else - @pending_backstroke.addClass "search-choice-focus" + @pending_backstroke.addClass 'search-choice-focus' clear_backstroke: -> - @pending_backstroke.removeClass "search-choice-focus" if @pending_backstroke + @pending_backstroke.removeClass 'search-choice-focus' if @pending_backstroke @pending_backstroke = null search_field_scale: -> @@ -504,5 +517,5 @@ class Chosen extends AbstractChosen @search_field.width(width) trigger_form_field_change: (extra) -> - @form_field_jq.trigger "input", extra - @form_field_jq.trigger "change", extra + @form_field_jq.trigger 'input', extra + @form_field_jq.trigger 'change', extra diff --git a/coffee/chosen.proto.coffee b/coffee/chosen.proto.coffee index 218308280b7..c8b1576b14e 100644 --- a/coffee/chosen.proto.coffee +++ b/coffee/chosen.proto.coffee @@ -3,23 +3,17 @@ class @Chosen extends AbstractChosen setup: -> @current_selectedIndex = @form_field.selectedIndex - set_default_values: -> - super() - - # HTML Templates - @no_results_temp = new Template(this.get_no_results_html('#{terms}')) - set_up_html: -> - container_classes = ["chosen-container"] - container_classes.push "chosen-container-" + (if @is_multiple then "multi" else "single") + container_classes = ['chosen-container'] + container_classes.push 'chosen-container-' + (if @is_multiple then 'multi' else 'single') container_classes.push @form_field.className if @inherit_select_classes && @form_field.className - container_classes.push "chosen-rtl" if @is_rtl + container_classes.push 'chosen-rtl' if @is_rtl container_props = - 'class': container_classes.join ' ' - 'title': @form_field.title + class: container_classes.join ' ' + title: @form_field.title - container_props.id = @form_field.id.replace(/[^\w]/g, '_') + "_chosen" if @form_field.id.length + container_props.id = @form_field.id.replace(/[^\w]/g, '_') + '_chosen' if @form_field.id.length @container = new Element('div', container_props) @@ -52,46 +46,46 @@ class @Chosen extends AbstractChosen this.set_label_behavior() on_ready: -> - @form_field.fire("chosen:ready", {chosen: this}) + @form_field.fire('chosen:ready', { chosen: this }) register_observers: -> - @container.observe "touchstart", (evt) => this.container_mousedown(evt) - @container.observe "touchend", (evt) => this.container_mouseup(evt) - - @container.observe "mousedown", (evt) => this.container_mousedown(evt) - @container.observe "mouseup", (evt) => this.container_mouseup(evt) - @container.observe "mouseenter", (evt) => this.mouse_enter(evt) - @container.observe "mouseleave", (evt) => this.mouse_leave(evt) - - @search_results.observe "mouseup", (evt) => this.search_results_mouseup(evt) - @search_results.observe "mouseover", (evt) => this.search_results_mouseover(evt) - @search_results.observe "mouseout", (evt) => this.search_results_mouseout(evt) - @search_results.observe "mousewheel", (evt) => this.search_results_mousewheel(evt) - @search_results.observe "DOMMouseScroll", (evt) => this.search_results_mousewheel(evt) - - @search_results.observe "touchstart", (evt) => this.search_results_touchstart(evt) - @search_results.observe "touchmove", (evt) => this.search_results_touchmove(evt) - @search_results.observe "touchend", (evt) => this.search_results_touchend(evt) - - @form_field.observe "chosen:updated", (evt) => this.results_update_field(evt) - @form_field.observe "chosen:activate", (evt) => this.activate_field(evt) - @form_field.observe "chosen:open", (evt) => this.container_mousedown(evt) - @form_field.observe "chosen:close", (evt) => this.close_field(evt) - - @search_field.observe "blur", (evt) => this.input_blur(evt) - @search_field.observe "keyup", (evt) => this.keyup_checker(evt) - @search_field.observe "keydown", (evt) => this.keydown_checker(evt) - @search_field.observe "focus", (evt) => this.input_focus(evt) - @search_field.observe "cut", (evt) => this.clipboard_event_checker(evt) - @search_field.observe "paste", (evt) => this.clipboard_event_checker(evt) + @container.observe 'touchstart', (evt) => this.container_mousedown(evt) + @container.observe 'touchend', (evt) => this.container_mouseup(evt) + + @container.observe 'mousedown', (evt) => this.container_mousedown(evt) + @container.observe 'mouseup', (evt) => this.container_mouseup(evt) + @container.observe 'mouseenter', (evt) => this.mouse_enter(evt) + @container.observe 'mouseleave', (evt) => this.mouse_leave(evt) + + @search_results.observe 'mouseup', (evt) => this.search_results_mouseup(evt) + @search_results.observe 'mouseover', (evt) => this.search_results_mouseover(evt) + @search_results.observe 'mouseout', (evt) => this.search_results_mouseout(evt) + @search_results.observe 'mousewheel', (evt) => this.search_results_mousewheel(evt) + @search_results.observe 'DOMMouseScroll', (evt) => this.search_results_mousewheel(evt) + + @search_results.observe 'touchstart', (evt) => this.search_results_touchstart(evt) + @search_results.observe 'touchmove', (evt) => this.search_results_touchmove(evt) + @search_results.observe 'touchend', (evt) => this.search_results_touchend(evt) + + @form_field.observe 'chosen:updated', (evt) => this.results_update_field(evt) + @form_field.observe 'chosen:activate', (evt) => this.activate_field(evt) + @form_field.observe 'chosen:open', (evt) => this.container_mousedown(evt) + @form_field.observe 'chosen:close', (evt) => this.close_field(evt) + + @search_field.observe 'blur', (evt) => this.input_blur(evt) + @search_field.observe 'keyup', (evt) => this.keyup_checker(evt) + @search_field.observe 'keydown', (evt) => this.keydown_checker(evt) + @search_field.observe 'focus', (evt) => this.input_focus(evt) + @search_field.observe 'cut', (evt) => this.clipboard_event_checker(evt) + @search_field.observe 'paste', (evt) => this.clipboard_event_checker(evt) if @is_multiple - @search_choices.observe "click", (evt) => this.choices_click(evt) + @search_choices.observe 'click', (evt) => this.choices_click(evt) else - @container.observe "click", (evt) => evt.preventDefault() # gobble click of anchor + @container.observe 'click', (evt) -> evt.preventDefault() # gobble click of anchor destroy: -> - @container.ownerDocument.stopObserving "click", @click_test_action + @container.ownerDocument.stopObserving 'click', @click_test_action for event in ['chosen:updated', 'chosen:activate', 'chosen:open', 'chosen:close'] @form_field.stopObserving(event) @@ -103,7 +97,7 @@ class @Chosen extends AbstractChosen if @is_multiple @search_choices.stopObserving() - @container.select(".search-choice-close").each (choice) -> + @container.select('.search-choice-close').each (choice) -> choice.stopObserving() else @selected_item.stopObserving() @@ -138,18 +132,18 @@ class @Chosen extends AbstractChosen if evt and evt.type in ['mousedown', 'touchstart'] and not @results_showing evt.preventDefault() - if not (evt? and evt.target.hasClassName "search-choice-close") + if not (evt? and evt.target.hasClassName 'search-choice-close') if not @active_field @search_field.clear() if @is_multiple - @container.ownerDocument.observe "click", @click_test_action + @container.ownerDocument.observe 'click', @click_test_action this.results_show() - else if not @is_multiple and evt and (evt.target is @selected_item || evt.target.up("a.chosen-single")) + else if not @is_multiple and evt and (evt.target is @selected_item || evt.target.up('a.chosen-single')) this.results_toggle() this.activate_field() container_mouseup: (evt) -> - this.results_reset(evt) if evt.target.nodeName is "ABBR" and not @is_disabled + this.results_reset(evt) if evt.target.nodeName is 'ABBR' and not @is_disabled search_results_mousewheel: (evt) -> delta = evt.deltaY or -evt.wheelDelta or evt.detail @@ -159,15 +153,15 @@ class @Chosen extends AbstractChosen @search_results.scrollTop = delta + @search_results.scrollTop blur_test: (evt) -> - this.close_field() if not @active_field and @container.hasClassName("chosen-container-active") + this.close_field() if not @active_field and @container.hasClassName('chosen-container-active') close_field: -> - @container.ownerDocument.stopObserving "click", @click_test_action + @container.ownerDocument.stopObserving 'click', @click_test_action @active_field = false this.results_hide() - @container.removeClassName "chosen-container-active" + @container.removeClassName 'chosen-container-active' this.clear_backstroke() this.show_search_field_default() @@ -177,7 +171,7 @@ class @Chosen extends AbstractChosen activate_field: -> return if @is_disabled - @container.addClassName "chosen-container-active" + @container.addClassName 'chosen-container-active' @active_field = true @search_field.value = this.get_search_field_value() @@ -196,17 +190,17 @@ class @Chosen extends AbstractChosen @results_data = SelectParser.select_to_array @form_field if @is_multiple - @search_choices.select("li.search-choice").invoke("remove") + @search_choices.select('li.search-choice').invoke('remove') else if not @is_multiple this.single_set_selected_text() if @disable_search or @form_field.options.length <= @disable_search_threshold @search_field.readOnly = true - @container.addClassName "chosen-container-single-nosearch" + @container.addClassName 'chosen-container-single-nosearch' else @search_field.readOnly = false - @container.removeClassName "chosen-container-single-nosearch" + @container.removeClassName 'chosen-container-single-nosearch' - this.update_results_content this.results_option_build({first:true}) + this.update_results_content this.results_option_build(first: true) this.search_field_disabled() this.show_search_field_default() @@ -215,22 +209,22 @@ class @Chosen extends AbstractChosen @parsing = false result_do_highlight: (el) -> - this.result_clear_highlight() + this.result_clear_highlight() - @result_highlight = el - @result_highlight.addClassName "highlighted" + @result_highlight = el + @result_highlight.addClassName 'highlighted' - maxHeight = parseInt @search_results.getStyle('maxHeight'), 10 - visible_top = @search_results.scrollTop - visible_bottom = maxHeight + visible_top + maxHeight = parseInt @search_results.getStyle('maxHeight'), 10 + visible_top = @search_results.scrollTop + visible_bottom = maxHeight + visible_top - high_top = @result_highlight.positionedOffset().top - high_bottom = high_top + @result_highlight.getHeight() + high_top = @result_highlight.positionedOffset().top + high_bottom = high_top + @result_highlight.getHeight() - if high_bottom >= visible_bottom - @search_results.scrollTop = if (high_bottom - maxHeight) > 0 then (high_bottom - maxHeight) else 0 - else if high_top < visible_top - @search_results.scrollTop = high_top + if high_bottom >= visible_bottom + @search_results.scrollTop = if (high_bottom - maxHeight) > 0 then (high_bottom - maxHeight) else 0 + else if high_top < visible_top + @search_results.scrollTop = high_top result_clear_highlight: -> @result_highlight.removeClassName('highlighted') if @result_highlight @@ -238,17 +232,17 @@ class @Chosen extends AbstractChosen results_show: -> if @is_multiple and @max_selected_options <= this.choices_count() - @form_field.fire("chosen:maxselected", {chosen: this}) + @form_field.fire('chosen:maxselected', { chosen: this }) return false - @container.addClassName "chosen-with-drop" + @container.addClassName 'chosen-with-drop' @results_showing = true @search_field.focus() @search_field.value = this.get_search_field_value() this.winnow_results() - @form_field.fire("chosen:showing_dropdown", {chosen: this}) + @form_field.fire('chosen:showing_dropdown', { chosen: this }) update_results_content: (content) -> @search_results.update content @@ -257,8 +251,8 @@ class @Chosen extends AbstractChosen if @results_showing this.result_clear_highlight() - @container.removeClassName "chosen-with-drop" - @form_field.fire("chosen:hiding_dropdown", {chosen: this}) + @container.removeClassName 'chosen-with-drop' + @form_field.fire('chosen:hiding_dropdown', { chosen: this }) @results_showing = false @@ -270,43 +264,43 @@ class @Chosen extends AbstractChosen @search_field.tabIndex = ti set_label_behavior: -> - @form_field_label = @form_field.up("label") # first check for a parent label + @form_field_label = @form_field.up('label') # first check for a parent label if not @form_field_label? @form_field_label = $$("label[for='#{@form_field.id}']").first() #next check for a for=#{id} if @form_field_label? - @form_field_label.observe "click", this.label_click_handler + @form_field_label.observe 'click', this.label_click_handler show_search_field_default: -> if @is_multiple and this.choices_count() < 1 and not @active_field @search_field.value = @default_text - @search_field.addClassName "default" + @search_field.addClassName 'default' else - @search_field.value = "" - @search_field.removeClassName "default" + @search_field.value = '' + @search_field.removeClassName 'default' search_results_mouseup: (evt) -> - target = if evt.target.hasClassName("active-result") then evt.target else evt.target.up(".active-result") + target = if evt.target.hasClassName('active-result') then evt.target else evt.target.up('.active-result') if target @result_highlight = target this.result_select(evt) @search_field.focus() search_results_mouseover: (evt) -> - target = if evt.target.hasClassName("active-result") then evt.target else evt.target.up(".active-result") + target = if evt.target.hasClassName('active-result') then evt.target else evt.target.up('.active-result') this.result_do_highlight( target ) if target search_results_mouseout: (evt) -> this.result_clear_highlight() if evt.target.hasClassName('active-result') or evt.target.up('.active-result') choice_build: (item) -> - choice = new Element('li', { class: "search-choice" }).update("#{this.choice_label(item)}") + choice = new Element('li', { class: 'search-choice' }).update("#{this.choice_label(item)}") if item.disabled choice.addClassName 'search-choice-disabled' else close_link = new Element('a', { href: '#', class: 'search-choice-close', rel: item.array_index }) - close_link.observe "click", (evt) => this.choice_destroy_link_click(evt) + close_link.observe 'click', (evt) => this.choice_destroy_link_click(evt) choice.insert close_link @search_container.insert { before: choice } @@ -317,7 +311,7 @@ class @Chosen extends AbstractChosen this.choice_destroy evt.target unless @is_disabled choice_destroy: (link) -> - if this.result_deselect link.readAttribute("rel") + if this.result_deselect link.readAttribute('rel') if @active_field @search_field.focus() else @@ -340,7 +334,7 @@ class @Chosen extends AbstractChosen results_reset_cleanup: -> @current_selectedIndex = @form_field.selectedIndex - deselect_trigger = @selected_item.down("abbr") + deselect_trigger = @selected_item.down('abbr') deselect_trigger.remove() if(deselect_trigger) result_select: (evt) -> @@ -349,17 +343,17 @@ class @Chosen extends AbstractChosen this.result_clear_highlight() if @is_multiple and @max_selected_options <= this.choices_count() - @form_field.fire("chosen:maxselected", {chosen: this}) + @form_field.fire('chosen:maxselected', { chosen: this }) return false if @is_multiple - high.removeClassName("active-result") + high.removeClassName('active-result') else this.reset_single_select_options() - high.addClassName("result-selected") + high.addClassName('result-selected') - item = @results_data[ high.getAttribute("data-option-array-index") ] + item = @results_data[ high.getAttribute('data-option-array-index') ] item.selected = true @form_field.options[item.options_index].selected = true @@ -381,14 +375,14 @@ class @Chosen extends AbstractChosen this.search_field_scale() - single_set_selected_text: (text=@default_text) -> + single_set_selected_text: (text = @default_text) -> if text is @default_text - @selected_item.addClassName("chosen-default") + @selected_item.addClassName('chosen-default') else this.single_deselect_control_build() - @selected_item.removeClassName("chosen-default") + @selected_item.removeClassName('chosen-default') - @selected_item.down("span").update(text) + @selected_item.down('span').update(text) result_deselect: (pos) -> result_data = @results_data[pos] @@ -410,8 +404,9 @@ class @Chosen extends AbstractChosen single_deselect_control_build: -> return unless @allow_single_deselect - @selected_item.down("span").insert { after: "" } unless @selected_item.down("abbr") - @selected_item.addClassName("chosen-single-with-deselect") + unless @selected_item.down('abbr') + @selected_item.down('span').insert { after: '' } + @selected_item.addClassName('chosen-single-with-deselect') get_search_field_value: -> @search_field.value @@ -424,20 +419,20 @@ class @Chosen extends AbstractChosen winnow_results_set_highlight: -> if not @is_multiple - do_high = @search_results.down(".result-selected.active-result") + do_high = @search_results.down('.result-selected.active-result') if not do_high? - do_high = @search_results.down(".active-result") + do_high = @search_results.down('.active-result') this.result_do_highlight do_high if do_high? no_results: (terms) -> - @search_results.insert @no_results_temp.evaluate( terms: terms ) - @form_field.fire("chosen:no_results", {chosen: this}) + @search_results.insert this.get_no_results_html(terms) + @form_field.fire('chosen:no_results', { chosen: this }) no_results_clear: -> nr = null - nr.remove() while nr = @search_results.down(".no-results") + nr.remove() while nr = @search_results.down('.no-results') keydown_arrow: -> @@ -452,7 +447,7 @@ class @Chosen extends AbstractChosen this.results_show() else if @result_highlight sibs = @result_highlight.previousSiblings() - actives = @search_results.select("li.active-result") + actives = @search_results.select('li.active-result') prevs = sibs.intersect(actives) if prevs.length @@ -463,20 +458,21 @@ class @Chosen extends AbstractChosen keydown_backstroke: -> if @pending_backstroke - this.choice_destroy @pending_backstroke.down("a") + this.choice_destroy @pending_backstroke.down('a') this.clear_backstroke() else next_available_destroy = @search_container.siblings().last() - if next_available_destroy and next_available_destroy.hasClassName("search-choice") and not next_available_destroy.hasClassName("search-choice-disabled") + if next_available_destroy and next_available_destroy.hasClassName('search-choice') and + not next_available_destroy.hasClassName('search-choice-disabled') @pending_backstroke = next_available_destroy - @pending_backstroke.addClassName("search-choice-focus") if @pending_backstroke + @pending_backstroke.addClassName('search-choice-focus') if @pending_backstroke if @single_backstroke_delete @keydown_backstroke() else - @pending_backstroke.addClassName("search-choice-focus") + @pending_backstroke.addClassName('search-choice-focus') clear_backstroke: -> - @pending_backstroke.removeClassName("search-choice-focus") if @pending_backstroke + @pending_backstroke.removeClassName('search-choice-focus') if @pending_backstroke @pending_backstroke = null search_field_scale: -> @@ -508,7 +504,7 @@ class @Chosen extends AbstractChosen @search_field.setStyle(width: width + 'px') - trigger_form_field_change: -> + trigger_form_field_change: -> triggerHtmlEvent @form_field, 'input' triggerHtmlEvent @form_field, 'change' @@ -518,7 +514,7 @@ class @Chosen extends AbstractChosen evt = new Event(eventType, bubbles: true, cancelable: true) catch evt = document.createEvent('HTMLEvents') - evt.initEvent(eventType, true, true); + evt.initEvent(eventType, true, true) element.dispatchEvent(evt) else # Old IE: - element.fireEvent("on#{eventType}", document.createEventObject()); + element.fireEvent("on#{eventType}", document.createEventObject()) diff --git a/coffee/lib/abstract-chosen.coffee b/coffee/lib/abstract-chosen.coffee index bf0e785a1ae..4a8f9a39f8c 100644 --- a/coffee/lib/abstract-chosen.coffee +++ b/coffee/lib/abstract-chosen.coffee @@ -1,6 +1,6 @@ class AbstractChosen - constructor: (@form_field, @options={}) -> + constructor: (@form_field, @options = {}) -> return unless AbstractChosen.browser_is_supported() @is_multiple = @form_field.multiple this.set_default_text() @@ -21,7 +21,10 @@ class AbstractChosen @results_showing = false @result_highlighted = null @is_rtl = @options.rtl || /\bchosen-rtl\b/.test(@form_field.className) - @allow_single_deselect = if @options.allow_single_deselect? and @form_field.options[0]? and @form_field.options[0].text is "" then @options.allow_single_deselect else false + @allow_single_deselect = if @options.allow_single_deselect? and @form_field.options[0]?.text is '' + @options.allow_single_deselect + else + false @disable_search_threshold = @options.disable_search_threshold || 0 @disable_search = @options.disable_search || false @enable_split_word_search = if @options.enable_split_word_search? then @options.enable_split_word_search else true @@ -38,16 +41,17 @@ class AbstractChosen @hide_results_on_select = if @options.hide_results_on_select? then @options.hide_results_on_select else true set_default_text: -> - if @form_field.getAttribute("data-placeholder") - @default_text = @form_field.getAttribute("data-placeholder") + @default_text = if @form_field.getAttribute('data-placeholder') + @form_field.getAttribute('data-placeholder') else if @is_multiple - @default_text = @options.placeholder_text_multiple || @options.placeholder_text || AbstractChosen.default_multiple_text + @options.placeholder_text_multiple || @options.placeholder_text || AbstractChosen.default_multiple_text else - @default_text = @options.placeholder_text_single || @options.placeholder_text || AbstractChosen.default_single_text + @options.placeholder_text_single || @options.placeholder_text || AbstractChosen.default_single_text @default_text = this.escape_html(@default_text) - @results_none_found = @form_field.getAttribute("data-no_results_text") || @options.no_results_text || AbstractChosen.default_no_result_text + @results_none_found = @form_field.getAttribute('data-no_results_text') || + @options.no_results_text || AbstractChosen.default_no_result_text choice_label: (item) -> if @include_group_label_in_selected and item.group_label? @@ -106,16 +110,16 @@ class AbstractChosen return '' unless this.include_option_in_results(option) classes = [] - classes.push "active-result" if !option.disabled and !(option.selected and @is_multiple) - classes.push "disabled-result" if option.disabled and !(option.selected and @is_multiple) - classes.push "result-selected" if option.selected - classes.push "group-option" if option.group_array_index? - classes.push option.classes if option.classes != "" - - option_el = document.createElement("li") - option_el.className = classes.join(" ") + classes.push 'active-result' if !option.disabled and !(option.selected and @is_multiple) + classes.push 'disabled-result' if option.disabled and !(option.selected and @is_multiple) + classes.push 'result-selected' if option.selected + classes.push 'group-option' if option.group_array_index? + classes.push option.classes if option.classes != '' + + option_el = document.createElement('li') + option_el.className = classes.join(' ') option_el.style.cssText = option.style - option_el.setAttribute("data-option-array-index", option.array_index) + option_el.setAttribute('data-option-array-index', option.array_index) option_el.innerHTML = option.search_text option_el.title = option.title if option.title @@ -126,11 +130,11 @@ class AbstractChosen return '' unless group.active_options > 0 classes = [] - classes.push "group-result" + classes.push 'group-result' classes.push group.classes if group.classes - group_el = document.createElement("li") - group_el.className = classes.join(" ") + group_el = document.createElement('li') + group_el.className = classes.join(' ') group_el.innerHTML = group.search_text group_el.title = group.title if group.title @@ -143,7 +147,7 @@ class AbstractChosen this.results_build() this.winnow_results() if @results_showing - reset_single_select_options: () -> + reset_single_select_options: -> for result in @results_data result.selected = false if result.selected @@ -165,7 +169,7 @@ class AbstractChosen results = 0 searchText = this.get_search_text() - escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') regex = this.get_search_regex(escapedSearchText) highlightRegex = this.get_highlight_regex(escapedSearchText) @@ -194,7 +198,8 @@ class AbstractChosen if option.search_match if searchText.length startpos = option.search_text.search highlightRegex - text = option.search_text.substr(0, startpos + searchText.length) + '' + option.search_text.substr(startpos + searchText.length) + text = option.search_text.substr(0, startpos + searchText.length) + '' + + option.search_text.substr(startpos + searchText.length) option.search_text = text.substr(0, startpos) + '' + text.substr(startpos) results_group.group_match = true if results_group? @@ -205,28 +210,28 @@ class AbstractChosen this.result_clear_highlight() if results < 1 and searchText.length - this.update_results_content "" + this.update_results_content '' this.no_results searchText else this.update_results_content this.results_option_build() this.winnow_results_set_highlight() get_search_regex: (escaped_search_string) -> - regex_anchor = if @search_contains then "" else "^" - regex_flag = if @case_sensitive_search then "" else "i" + regex_anchor = if @search_contains then '' else '^' + regex_flag = if @case_sensitive_search then '' else 'i' new RegExp(regex_anchor + escaped_search_string, regex_flag) get_highlight_regex: (escaped_search_string) -> - regex_anchor = if @search_contains then "" else "\\b" - regex_flag = if @case_sensitive_search then "" else "i" + regex_anchor = if @search_contains then '' else '\\b' + regex_flag = if @case_sensitive_search then '' else 'i' new RegExp(regex_anchor + escaped_search_string, regex_flag) search_string_match: (search_string, regex) -> if regex.test search_string return true - else if @enable_split_word_search and (search_string.indexOf(" ") >= 0 or search_string.indexOf("[") == 0) + else if @enable_split_word_search and (search_string.indexOf(' ') >= 0 or search_string.indexOf('[') == 0) #TODO: replace this substitution of /\[\]/ with a list of characters to skip. - parts = search_string.replace(/\[|\]/g, "").split(" ") + parts = search_string.replace(/\[|\]/g, '').split(' ') if parts.length for part in parts if regex.test part @@ -329,7 +334,7 @@ class AbstractChosen outerHTML: (element) -> return element.outerHTML if element.outerHTML - tmp = document.createElement("div") + tmp = document.createElement('div') tmp.appendChild(element) tmp.innerHTML @@ -369,7 +374,7 @@ class AbstractChosen # class methods and variables ============================================================ @browser_is_supported: -> - if "Microsoft Internet Explorer" is window.navigator.appName + if 'Microsoft Internet Explorer' is window.navigator.appName return document.documentMode >= 8 if /iP(od|hone)/i.test(window.navigator.userAgent) or /IEMobile/i.test(window.navigator.userAgent) or @@ -380,7 +385,6 @@ class AbstractChosen return false return true - @default_multiple_text: "Select Some Options" - @default_single_text: "Select an Option" - @default_no_result_text: "No results match" - + @default_multiple_text: 'Select Some Options' + @default_single_text: 'Select an Option' + @default_no_result_text: 'No results match' diff --git a/coffee/lib/select-parser.coffee b/coffee/lib/select-parser.coffee index 3cd0637b2d0..47b9cb1dd01 100644 --- a/coffee/lib/select-parser.coffee +++ b/coffee/lib/select-parser.coffee @@ -5,7 +5,7 @@ class SelectParser @parsed = [] add_node: (child) -> - if child.nodeName.toUpperCase() is "OPTGROUP" + if child.nodeName.toUpperCase() is 'OPTGROUP' this.add_group child else this.add_option child @@ -23,8 +23,8 @@ class SelectParser this.add_option( option, group_position, group.disabled ) for option in group.childNodes add_option: (option, group_position, group_disabled) -> - if option.nodeName.toUpperCase() is "OPTION" - if option.text != "" + if option.nodeName.toUpperCase() is 'OPTION' + if option.text != '' if group_position? @parsed[group_position].children += 1 @parsed.push @@ -49,18 +49,18 @@ class SelectParser escapeExpression: (text) -> if not text? or text is false - return "" + return '' unless /[\&\<\>\"\'\`]/.test(text) return text map = - "<": "<" - ">": ">" - '"': """ - "'": "'" - "`": "`" + '<': '<' + '>': '>' + '"': '"' + "'": ''' + '`': '`' unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g text.replace unsafe_chars, (chr) -> - map[chr] || "&" + map[chr] || '&' SelectParser.select_to_array = (select) -> parser = new SelectParser() diff --git a/coffeelint.json b/coffeelint.json new file mode 100644 index 00000000000..0f5132a5e94 --- /dev/null +++ b/coffeelint.json @@ -0,0 +1,135 @@ +{ + "arrow_spacing": { + "level": "error" + }, + "braces_spacing": { + "level": "error", + "spaces": 1, + "empty_object_spaces": 0 + }, + "camel_case_classes": { + "level": "error" + }, + "coffeescript_error": { + "level": "error" + }, + "colon_assignment_spacing": { + "level": "error", + "spacing": { + "left": 0, + "right": 1 + } + }, + "cyclomatic_complexity": { + "level": "ignore", + "value": 10 + }, + "duplicate_key": { + "level": "error" + }, + "empty_constructor_needs_parens": { + "level": "ignore" + }, + "ensure_comprehensions": { + "level": "warn" + }, + "eol_last": { + "level": "error" + }, + "indentation": { + "value": 2, + "level": "error" + }, + "line_endings": { + "level": "ignore", + "value": "unix" + }, + "max_line_length": { + "value": 120, + "level": "error", + "limitComments": true + }, + "missing_fat_arrows": { + "level": "ignore", + "is_strict": false + }, + "newlines_after_classes": { + "value": 3, + "level": "ignore" + }, + "no_backticks": { + "level": "error" + }, + "no_debugger": { + "level": "warn", + "console": false + }, + "no_empty_functions": { + "level": "ignore" + }, + "no_empty_param_list": { + "level": "warn" + }, + "no_implicit_braces": { + "level": "ignore", + "strict": true + }, + "no_implicit_parens": { + "level": "ignore", + "strict": true + }, + "no_interpolation_in_single_quotes": { + "level": "warn" + }, + "no_nested_string_interpolation": { + "level": "warn" + }, + "no_plusplus": { + "level": "ignore" + }, + "no_private_function_fat_arrows": { + "level": "warn" + }, + "no_stand_alone_at": { + "level": "error" + }, + "no_tabs": { + "level": "error" + }, + "no_this": { + "level": "ignore" + }, + "no_throwing_strings": { + "level": "error" + }, + "no_trailing_semicolons": { + "level": "error" + }, + "no_trailing_whitespace": { + "level": "error", + "allowed_in_comments": false, + "allowed_in_empty_lines": true + }, + "no_unnecessary_double_quotes": { + "level": "error" + }, + "no_unnecessary_fat_arrows": { + "level": "error" + }, + "non_empty_constructor_needs_parens": { + "level": "ignore" + }, + "prefer_english_operator": { + "level": "ignore", + "doubleNotLevel": "ignore" + }, + "space_operators": { + "level": "error" + }, + "spacing_after_comma": { + "level": "error" + }, + "transform_messes_up_line_numbers": { + "level": "warn" + } +} diff --git a/package.json b/package.json index e075144b0ba..13d26d54976 100644 --- a/package.json +++ b/package.json @@ -19,13 +19,14 @@ "node": ">=0.4.0" }, "scripts": { - "test": "grunt test" + "test": "grunt coffeelint test" }, "dependencies": {}, "devDependencies": { "autoprefixer": "^6.1.2", "coffee-script": ">= 1.6", "grunt": "~0.4.1", + "grunt-coffeelint": "^0.0.16", "grunt-contrib-coffee": "~0.6.4", "grunt-contrib-concat": "~0.1.3", "grunt-contrib-cssmin": "~0.6.1", diff --git a/spec/jquery/basic.spec.coffee b/spec/jquery/basic.spec.coffee index cbb78589548..3615cdd8574 100644 --- a/spec/jquery/basic.spec.coffee +++ b/spec/jquery/basic.spec.coffee @@ -1,87 +1,87 @@ -describe "Basic setup", -> - it "should add chosen to jQuery object", -> +describe 'Basic setup', -> + it 'should add chosen to jQuery object', -> expect(jQuery.fn.chosen).toBeDefined() - it "should create very basic chosen", -> - tmpl = " -