<commit_before>define [
    '../core'
    '../controls'
    'inputio'
    'tpl!templates/views/field-control.html'
], (c, controls, InputIO, templates...) ->

    templates = c._.object ['control'], templates

    FORM_ELEMENTS = 'input,select,textarea'

    # Encapsulates a group of control elements that represents a
    # ContextNode, i.e. a single condition or branch of nodes. When
    # the data is ready to be saved, the view will utilize various
    # methods to extract and populate the ContextNode model instance.
    # ---
    # A node property can be represented as a static value via an attribute
    # (e.g. data-id="39") or as a dynamic value via a form element.

    class FieldControl extends controls.Control

        template: templates.control

        options:
            # A flag denoting whether or not this FieldControl is managed
            # by a ConceptControlView. Managed views have their validation errors
            # caught by the parent view. Default to false
            managed: false

            # Selectors of elements that pertain to the data attribute
            # for the node. The `nullSelector` is used to flag whether
            # or not to include empty and/or NULL values. The `nullsSelector`
            # must be a checkbox, unless the `nullsAttr` has a value set.
            idSelector: '[data-id]'
            valueSelector: '[data-value]'
            operatorSelector: '[data-operator]'
            nullsSelector: '[data-nulls]'

            # Attribute-based properties representing a constant value
            idAttr: 'data-id'
            valueAttr: 'data-value'
            operatorAttr: 'data-operator'
            nullsAttr: 'data-nulls'

        events:
            'keyup input': 'change'
            'change select': 'change'
            'click input[type=radio],input[type=checkbox]': 'change'

        initialize: ->
            @managed = @options.managed

            @idSelector = @options.idSelector
            @valueSelector = @options.valueSelector
            @operatorSelector = @options.operatorSelector
            @nullsSelector = @options.nullsSelector

            @idAttr = @options.idAttr
            @valueAttr = @options.valueAttr
            @operatorAttr = @options.operatorAttr
            @nullsAttr = @options.nullsAttr

            @_resetReferences()

        # This must be called if the underlying DOM elements change
        _resetReferences: ->
            @$id = if @$el.is @idSelector then @$el else @$ @idSelector
            @$operator = if @$el.is @operatorSelector then @$el else @$ @operatorSelector
            @$value = if @$el.is @valueSelector then @$el else @$ @valueSelector
            @$nulls = if @$el.is @nullsSelector then @$el else @$ @nullsSelector

        # Given a client id, deference the node
        _deferenceNode: (cid) ->
            if (node = @_nodeCache[cid])?
                delete @_nodeCache[cid]
                # Delete reference here
                if @node.cid is id then delete @node
                return node

        # Gets the DataField `id`
        getId: ->
            if @model.id
                @model.id
            else
                if @$id.is FORM_ELEMENTS
                    id = InputIO.get @$id
                else
                    id = @$id.attr @idAttr
                @cleanId id

        # Get the operator
        getOperator: ->
            if @$operator.is FORM_ELEMENTS
                operator = InputIO.get @$operator
            else
                operator = @$operator.attr @operatorAttr
            @cleanOperator operator

        getValue: ->
            if @$value.is FORM_ELEMENTS
                value = InputIO.get @$value
            else
                value = @$value.attr @valueAttr
            @cleanValue value

        getNulls: ->
            if @$nulls.is FORM_ELEMENTS
                nulls = InputIO.get @$nulls
            else
                nulls = @$nulls.attr @nullsAttr
            @cleanNulls nulls

        setId: (id) ->
            if @model.id then return
            if @$id.is FORM_ELEMENTS
                InputIO.set @$id, id
            else
                @$id.attr @idAttr, id
            return

        setOperator: (operator) ->
            if @$operator.is FORM_ELEMENTS
                InputIO.set @$operator, operator
            else
                @$operator.attr @operatorAttr, operator
            return

        setValue: (value) ->
            if @$value.is FORM_ELEMENTS
                InputIO.set @$value, value
            else
                @$value.attr @valueAttr, value
            return

        # Special case since this is purely a boolean field
        setNulls: (value) ->
            value = Boolean value
            if @$nulls.is FORM_ELEMENTS
                InputIO.set @$nulls, value
            else
                @$nulls.attr @nullsAttr, value
            return

        # Triggered any time the control contents have changed
        change: (event) ->
            @trigger 'change', @, @get()

        # Creates a new node with the control contents
        add: ->
            @node = node = new c.models.ContextNode @get()
            @_nodeCache[node.cid] = node
            if not @managed
                @$add.hide()
                @$update.show()
            @trigger 'add', @, node

        # Updates the current node with the control contents
        update: ->
            @node.set @get()
            @trigger 'update', @, @node

        # Removes a node, but leaves the control contents alone.
        remove: (cid) ->
            node = @_deferenceNode cid
            if not @managed and not @node
                @$update.hide()
                @$add.show()
            @trigger 'remove', @, node

        reset: -> @set()

    { FieldControl }<commit_msg>Simply base getter/setter, change selectors to use ui property<commit_after>define [
    '../core'
    '../controls'
    'inputio'
    'tpl!templates/views/field-control.html'
], (c, controls, InputIO, templates...) ->

    templates = c._.object ['control'], templates

    FORM_ELEMENTS = 'input,select,textarea'

    # Encapsulates a group of control elements that represents a
    # ContextNode, i.e. a single condition or branch of nodes. When
    # the data is ready to be saved, the view will utilize various
    # methods to extract and populate the ContextNode model instance.
    # ---
    # A node property can be represented as a static value via an attribute
    # (e.g. data-id="39") or as a dynamic value via a form element.

    class FieldControl extends controls.Control
        className: 'field-control'

        template: templates.control

        options:
            # A flag denoting whether or not this FieldControl is managed
            # by a ConceptControlView. Managed views have their validation errors
            # caught by the parent view. Default to false
            managed: true

        events:
            'keyup input': 'change'
            'change select': 'change'
            'click input[type=radio],input[type=checkbox]': 'change'

        constructor: ->
            super
            # Various ways to define the UI elements
            @ui = _.extend {}, @constructor.defaultUI, @ui, @options.ui
            @attrs = _.extend {}, @constructor.defaultAttrs, @attrs, @options.attrs

        # Given a client id, deference the node
        _deferenceNode: (cid) ->
            if (node = @_nodeCache[cid])?
                delete @_nodeCache[cid]
                # Delete reference here
                if @node.cid is id then delete @node
                return node

        # Gets the value corresonding to the property.
        _getProp: (prop) ->
            if not ($el = @ui[prop])? then return
            if $el.is(FORM_ELEMENTS)
                InputIO.get($el)
            else
                $el.attr(@options.attrs[prop])

        _setProp: (prop, value) ->
            if not ($el = @ui[prop])? then return
            if $el.is(FORM_ELEMENTS)
                InputIO.set($el, value)
            else
                $el.attr(@options.attrs[prop], value)
            return

        getId: -> @model.id or @_getProp('id')
        getOperator: -> @_getProp('operator')
        getValue: -> @_getProp('value')
        getNulls: -> @_getProp('nulls')

        setId: (value) -> not @model.id and @_setProp('id', value)
        setOperator: (value) -> @_setProp('operator', value)
        setValue: (value) -> @_setProp('value', value)
        setNulls: (value) -> @_setProp('nulls', Boolean(value))

        # Triggered any time the control contents have changed
        change: (event) -> @trigger 'change', @, @get()

        # Creates a new node with the control contents
        add: ->
            @node = node = new c.models.ContextNode @get()
            @_nodeCache[node.cid] = node
            if not @managed
                @$add.hide()
                @$update.show()
            @trigger 'add', @, node

        # Updates the current node with the control contents
        update: ->
            @node.set @get()
            @trigger 'update', @, @node

        # Removes a node, but leaves the control contents alone.
        remove: (cid) ->
            node = @_deferenceNode cid
            if not @managed and not @node
                @$update.hide()
                @$add.show()
            @trigger 'remove', @, node

        reset: -> @set()


    # Selectors of elements that pertain to the data attribute
    # for the node. The `nulls` selector is used to flag whether
    # or not to include empty and/or NULL values.
    FieldControl.defaultUI =
        id: '[name=id],[data-id]'
        value: '[name=value],[data-value]'
        operator: '[name=operator],[data-operator]'
        nulls: '[name=nulls],[data-nulls]'


    # Attribute-based properties representing a constant value
    FieldControl.defaultAttrs =
        id: 'data-id'
        value: 'data-value'
        operator: 'data-operator'
        nulls: 'data-nulls'


    { FieldControl }
{'fraction_non_alphanumeric': 0.09953312804211781, 'fraction_numerical': 0.0003973378364954803, 'mean_word_length': 1.6948608137044967, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7473739', 'n_tokens_mistral': 2755, 'n_tokens_neox': 2635, 'n_words': 863}