selectField = Luca.register "Luca.fields.SelectField" selectField.extends "Luca.core.Field" selectField.triggers "after:select", "on:change" selectField.publicConfiguration # Enables multi-select UI element. allowMultiple: false # Includes a blank option in addition to all of the items # in the underlying collection. Defaults to `true` includeBlank: true # determines which value is sent when # the blank option is selected? blankValue: '' # Determines the text displayed when # the blank option is selected blankText: 'Select One' # Specifying a value for maxDisplayLength will truncate # values displayed in the select field when they reach # past a certain point, using the _.str truncate method. # Leave at 0 if you want to keep this feature disabled. maxDisplayLength: 0 # When the underlying collection is reset and we re-render # the options elements, should we keep the value that was set # on this field prior to that? Defaults to `true` unless otherwise # specified. retainValue: undefined # Determines which value is rendered in the label element that gets # rendered along with this control group. label: undefined selectField.privateConfiguration template: "fields/select_field" events: "change select" : "change_handler" selectField.publicMethods # sets the value of this select field. setValue: (value)-> @currentValue = value Luca.core.Field::setValue.apply @, arguments # returns the value of the select field. runs # the value through the getParsedValue method which # enforces the valueType type conversion. getValue: ()-> raw = @getInputElement()?.val() if @allowMultiple _.map raw, (value)=> @getParsedValue(value) else @getParsedValue(raw) selectField.privateMethods initialize: (@options={})-> _.extend @, @options _.extend @, Luca.concerns.Deferrable _.bindAll @, "change_handler" if _.isArray(@collection) @collection = data: @collection Luca.core.Field::initialize.apply @, arguments @input_id ||= _.uniqueId('field') @input_name ||= @name @valueType ||= Luca.config.idAttributeType if @valueField is "id" @label ||= @name @retainValue = true unless @retainValue? afterInitialize: ()-> if @collection?.data @valueField ||= "id" @displayField ||= "name" @sortOptionsBy ||= @displayField @parseData() try @configure_collection( @setAsDeferrable ) catch e console.log "Error Configuring Collection", @, e.message @collection?.bind "before:fetch", @beforeFetch, @ @collection?.bind "reset", @populateOptions, @ # if the select field is configured with a data property # then parse that data into the proper format. either # an array of objects with the valueField and displayField # properties, or an array of arrays with [valueField, displayField] parseData: ()-> @collection.data = _( @collection.data ).map (record)=> return record if not _.isArray( record ) hash = {} hash[ @valueField ] = record[0] hash[ @displayField ] = record[1] || record[0] hash getInputElement: ()-> @input ||= @$('select').eq(0) afterRender: ()-> if @collection?.models?.length > 0 @populateOptions() else @collection?.trigger("reset") beforeFetch: ()-> @resetOptions() change_handler: (e)-> @trigger "on:change", @, e resetOptions: ()-> @getInputElement().html('') if @allowMultiple @getInputElement().attr(multiple: true) else if @includeBlank @getInputElement().append("") populateOptions: ()-> @resetOptions() if @collection?.length > 0 if @sortOptionsBy? models = @collection.sortBy (model)=> if model.read? model.read( @sortOptionsBy ) else model.get( @sortOptionsBy ) else models = @collection.models for model in models v = model.read?( @valueField ) || model.get(@valueField) d = model.read?( @displayField ) || model.get(@displayField) if @maxDisplayLength and @maxDisplayLength > 0 d = _.str.truncate(d, @maxDisplayLength) selected = "selected" if @selected and v is @selected option = "" @getInputElement().append( option ) @trigger "after:populate:options", @ @setValue( @currentValue ) selectField.register()