-1

I don't like select elements with the multiple attribute, the ones with prop('type') of select-multiple. One is always forced to combine keyboard keys together with mouse clicks in order to select options. Plus, it's not easy to make selections on a mobile device.

However, there's this one Vendor's product that uses this form field with so many options that represent user's roles in the system. I thought of making the use of this control easier by adding undo and redo features to it, otherwise user have to refresh the page to load the default values before making and saving their changes. And what better way to manage the state of the select than to use data attributes.

I added minimal HTML to the page and attached a JavaScript file. Is there a way to simplify the JavaScript?

<select name="userRole" class="user-role" multiple="multiple">
    <option>administrator</option>
    <option>staff</option>
    <option>faculty</option>
    <option>angel</option>
    <option>moodle</option>
    <option>user</option>
</select>
<button class="undo">UNDO</button>
<button class="redo">REDO</button>

And the JavaScript:

var sel = $('select.user-role'),
    changeRole = function() {
        var that = $(this),
            curValue = that.val(),
            curUndo  = that.data('undo');
        curUndo.push( curValue );
        that.data( 'undo', curUndo );
    },

    undo = function() {
        var curUndo = sel.data( 'undo' ),
            curRedo = sel.data( 'redo' );
        if( curUndo.length > 0 ) {
            curRedo.push( curUndo.pop() );
            sel.data({undo:curUndo,redo:curRedo});
            sel.val( curUndo.length ? curUndo.slice(-1)[0] : [] );
        }
    },

    redo = function() {
        var curUndo = sel.data( 'undo' ),
            curRedo = sel.data( 'redo' );
        if( curRedo.length > 0 ) {
            curUndo.push( curRedo.pop() );
            sel.data({undo:curUndo,redo:curRedo});
            sel.val( curUndo.length ? curUndo.slice(-1)[0] : [] );
        }
    };

sel.on('change', changeRole).change();
$('button.undo').on('click', undo);
$('button.redo').on('click', redo);
PeterKA
  • 24,158
  • 5
  • 26
  • 48

1 Answers1

-1

Yes, the code can be simplified. As mentioned in this excellent post data variables are stored in the node object. Also variables defined are references to the node object. Thus the code would become:

var sel = $('select.user-role'),
    changeRole = function() {
        var that = $(this);
        that.data()['undo'].push( that.val() );
    },

    undo = function() {
        var d = sel.data();
        if( d['undo'].length > 0 ) {
            d['redo'].push( d['undo'].pop() );
            sel.val( d['undo'].length ? d['undo'].slice(-1)[0] : [] );
        }
    },

    redo = function() {
        var d = sel.data();
        if( d['redo'].length > 0 ) {
            d['undo'].push( d['redo'].pop() );
            sel.val( d['undo'].length ? d['undo'].slice(-1)[0] : [] );
        }
    };

sel.on('change', changeRole).change();
$('button.undo').on('click', undo);
$('button.redo').on('click', redo);
Community
  • 1
  • 1
PeterKA
  • 24,158
  • 5
  • 26
  • 48