From 3f18c8521350e62e317ddee2babec5f8f38f2086 Mon Sep 17 00:00:00 2001 From: Jordan Stephens Date: Mon, 16 Jun 2014 18:52:37 -0400 Subject: [PATCH] allow native select interfaces for iOS and android --- coffee/chosen.jquery.coffee | 12 ++++++++---- coffee/chosen.proto.coffee | 13 ++++++++++--- coffee/lib/abstract-chosen.coffee | 13 +++++++++---- sass/chosen.scss | 10 ++++++++++ 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/coffee/chosen.jquery.coffee b/coffee/chosen.jquery.coffee index 6ebcfbd8703..f16c9ec9a3c 100644 --- a/coffee/chosen.jquery.coffee +++ b/coffee/chosen.jquery.coffee @@ -29,6 +29,7 @@ class Chosen extends AbstractChosen 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 "use-native-interface" if this.use_native_interface() container_props = 'class': container_classes.join ' ' @@ -39,12 +40,14 @@ class Chosen extends AbstractChosen @container = ($ "
", container_props) + @form_field_jq = @form_field_jq.wrap(@container) + @container = @form_field_jq.parent() + if @is_multiple - @container.html '
    ' + @container.append '
      ' else - @container.html '' + @default_text + '
        ' + @container.append '' + @default_text + '
          ' - @form_field_jq.hide().after @container @dropdown = @container.find('div.chosen-drop').first() @search_field = @container.find('input').first() @@ -83,6 +86,7 @@ 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 "change.chosen", (evt) => this.results_update_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 @@ -122,7 +126,7 @@ class Chosen extends AbstractChosen @selected_item.bind "focus.chosen", @activate_action if !@is_multiple container_mousedown: (evt) -> - if !@is_disabled + unless @is_disabled or @use_native_interface if evt and evt.type is "mousedown" and not @results_showing evt.preventDefault() diff --git a/coffee/chosen.proto.coffee b/coffee/chosen.proto.coffee index 25c48ea8d5f..30e0e9ffdba 100644 --- a/coffee/chosen.proto.coffee +++ b/coffee/chosen.proto.coffee @@ -17,6 +17,7 @@ class @Chosen extends AbstractChosen 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 "use-native-interface" if this.use_native_interface() container_props = 'class': container_classes.join ' ' @@ -25,9 +26,14 @@ class @Chosen extends AbstractChosen container_props.id = @form_field.id.replace(/[^\w]/g, '_') + "_chosen" if @form_field.id.length - @container = if @is_multiple then new Element('div', container_props).update( @multi_temp.evaluate({ "default": @default_text}) ) else new Element('div', container_props).update( @single_temp.evaluate({ "default":@default_text }) ) + @container = new Element('div', container_props) + @container = @form_field.wrap(@container) + + if @is_multiple + @container.insert({ bottom: @multi_temp.evaluate({ "default": @default_text }) }) + else + @container.insert({ bottom: @single_temp.evaluate({ "default": @default_text }) }) - @form_field.hide().insert({ after: @container }) @dropdown = @container.down('div.chosen-drop') @search_field = @container.down('input') @@ -67,6 +73,7 @@ class @Chosen extends AbstractChosen @search_results.observe "touchmove", (evt) => this.search_results_touchmove(evt) @search_results.observe "touchend", (evt) => this.search_results_touchend(evt) + @form_field.observe "change", (evt) => this.results_update_field(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) @@ -119,7 +126,7 @@ class @Chosen extends AbstractChosen @selected_item.observe "focus", @activate_action if !@is_multiple container_mousedown: (evt) -> - if !@is_disabled + unless @is_disabled or @use_native_interface if evt and evt.type is "mousedown" and not @results_showing evt.stop() diff --git a/coffee/lib/abstract-chosen.coffee b/coffee/lib/abstract-chosen.coffee index 21c9637d87c..7672c6f1d16 100644 --- a/coffee/lib/abstract-chosen.coffee +++ b/coffee/lib/abstract-chosen.coffee @@ -255,15 +255,20 @@ class AbstractChosen tmp.appendChild(element) tmp.innerHTML + use_native_interface: -> + if @options.use_native_interface + return @options.use_native_interface + if /iP(od|hone)/i.test(window.navigator.userAgent) + return true + if /Android/i.test(window.navigator.userAgent) + return true if /Mobile/i.test(window.navigator.userAgent) + return false + # class methods and variables ============================================================ @browser_is_supported: -> if window.navigator.appName == "Microsoft Internet Explorer" return document.documentMode >= 8 - if /iP(od|hone)/i.test(window.navigator.userAgent) - return false - if /Android/i.test(window.navigator.userAgent) - return false if /Mobile/i.test(window.navigator.userAgent) return true @default_multiple_text: "Select Some Options" diff --git a/sass/chosen.scss b/sass/chosen.scss index 44bcbcdb9d1..3afbc849b9e 100644 --- a/sass/chosen.scss +++ b/sass/chosen.scss @@ -32,6 +32,16 @@ $chosen-sprite-retina: image-url('chosen-sprite@2x.png') !default; a{ cursor: pointer; } + select { + display: none; + } + &.use-native-interface select { + display: initial; + height: 100%; + opacity: 0; + position: absolute; + z-index: 100; + } } /* @end */