3
\$\begingroup\$

I have JavaScript code that activates a button and deactivates another if a select is changed.

HTML

<select name="list" id="list">
     <option value="">choose</option>
     <option value="1">1</option>
     <option value="1">2</option>
     <option value="3">3</option>                
</select>
<input name="refresh" type="button" value="refresh" disabled="" />
<input name="add" type="button" value="add"  />

JavaScript

$('select').change(function () {
    var op = $(this).val();
    if (op != '') {
        $('input[name="refresh"]').prop('disabled', false);
    } else {
        $('input[name="refresh"]').prop('disabled', true);
    }
});
$('select').change(function () {
    var op = $(this).val();
    if (op != '') {
        $('input[name="add"]').prop('disabled', true);
    } else {
        $('input[name="add"]').prop('disabled', false);
    }
});

I need to expand the function to all fields in the form with minimal code. I could use the same code for the rest of inputs, but the code will be very long. I'm looking for a short version.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Targetting elements

$('select') is generic selector and will select all <select> elements on the page. There might be some <select> elements which are not needed to target for this functionality.

You can target only required elements using

  1. Unique parent selector + descendant selector

    In this, there will be a main container element and using this all the descendant <select> elements can be targeted.

    Example:

    HTML:

    <div id="container">
        <select name="list" id="list">
            <option value="">...</option>
        </select>
        <input name="refresh" />
        <input name="add" type="button" value="add" />
    
        <select name="list1" id="list1">
            <option value="">...</option>
        </select>
        <input name="refresh1" />
        <input name="add1" type="button" value="add1" />
    
        ...
    </div>
    

    JavaScript:

    $('#container select').change(function() {
    
  2. Using common class Sometimes, adding all the elements under a container is not possible. In such cases, adding a common class to all the elements will allow to select elements using class selector.

    $('.someCommonClass').change(function() {
    

    Common attributes can also be added and selected using Attribute Equals Selector [name=”value”]. However, this can be slower than class selectors.

Similarly, another common + unique class should be applied to buttons.

<input name="refresh" class="anotherUnique" />
<input name="add" class="anotherUnique" />

Then, to disable/enable these buttons, they can be referenced.

HTML5 data-* attributes

HTML5's custom data-* attribute can be used to store custom data on HTML elements.

<select name="list" id="list" data-key="value">

Getting data-* attribute value

jQuery provides data(name) method to get the value of the data-name attribute value. Core JavaScript has dataset property that allows access to data attributes.

$('elemSelector').data('key')

Using prop() with value

prop() accepts second parameter which will be converted to Boolean internally and depending on the value, the action will be taken. So, the if and else statements in the question can be combined as

$('elemSelector').prop('disabled', booleanValueHere);

If second parameter is truthy, element will be disabled. If falsy then element will be enabled.

Putting it all together

// Bind change event on all select elements
// having unique class
$('select.unique').change(function () {
    // Cache this
    var $this = $(this);

    // Get the data-* attribute values
    var button1 = $this.data('button1'),
        button2 = $this.data('button2');

    // Get the value of this select box
    // Use this as second parameter to prop
    $('input[name="' + button1 + '"]').prop('disabled', this.value);
    $('input[name="' + button2 + '"]').prop('disabled', !this.value);
});
/* For Demo Purpose */
input {
  color: green;
  font-weight: bold;
}
input:disabled {
  color: gray;
  opacity: .5;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<select name="list" id="list" class="unique" data-button1="refresh" data-button2="add">
    <option value="">choose</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<input name="refresh" type="button" class="anotherUnique" value="Refresh" />
<input name="add" type="button" class="anotherUnique" value="Add" disabled />

<hr />
<!-- Another select box -->
<select name="list1" id="list1" class="unique" data-button1="refresh1" data-button2="add1">
    <option value="">choose</option>
    <option value="10">10</option>
    <option value="20">20</option>
    <option value="30">30</option>
</select>
<input name="refresh1" type="button" class="anotherUnique1" value="Refresh 1" />
<input name="add1" type="button" class="anotherUnique1" value="Add 1" disabled />

Conclusion

Now, the JavaScript code don't have to be written again for each new select element. Just adding the markup with required attributes will automatically work. The relation between HTML element-JavaScript handler is reduced from many to many to many to one.

\$\endgroup\$
2
  • \$\begingroup\$ Hello Tushar! Nice to see you! \$\endgroup\$
    – user90823
    Commented Sep 7, 2016 at 15:55
  • 1
    \$\begingroup\$ @Yvette Welcome to CR! \$\endgroup\$
    – Tushar
    Commented Sep 7, 2016 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.