Your PC can't even




DrivingLists.js

This page demonstrates how to use a custom script named DrivingLists.js I made a bit ago.

Why? How is this useful?

  • I’ve had a bunch of instances where I’ve needed to render dropdowns dependant on criteria from another dropdown. It’s not fun creating custom code everytime you need to do that. To get around this, I made a script that uses data attributes to drive other dropdowns.

  • Here’s a link if you want a copy

To the Source!

		

(function (win) {
            //Author: CM
            //Notes: Wanted a global way to have select lists drive the values of other select lists so long as they share the same key
    win.DrivingList = function (defaults) {
            if (defaults !== undefined) {
            this.form = $(defaults.form);
            this.Readonly = defaults.Readonly;
        }
    };
    win.DrivingList.prototype = function () {
            var Wireup = function () {
            //set aside conext of 'this' for when we enter a new scope
            var that = this;
            //First unwire any wireups that we have had in the past, we do not want multiple from subsequent calls
            $(this.form.find('select[data-driver-for]')).unbind('change');
            //Now collect every element in our form that qualifies as a driver
            $(this.form.find('select[data-driver-for]')).on('change', function () {
            var driver = $(this);
            //grab the name for this select list, this will allow us to build our collection based upon the driver's name
            var name = driver.attr('name');
            //grab a collection of passengers this selection is driving for
            var passengers = driver.data('driver-for').split('|');
            //grab the driver's selected option
            var selectedOption = driver.find('option:selected');
            //the name of the key to match options on
            var driverKey = driver.data('driver-key');
            //the key to sort groups by based on driver key
            var optionKey = selectedOption.data(driverKey);
            //attempt to dereference our collection based upon the name of our selected driver
            //if none exists we need to create one and shove it into the collection
                that.DrivingCollection = that.DrivingCollection || {};
                that.DrivingCollection[name] = that.DrivingCollection[name] || {};
                
            //now we need to find each passenger that is closest to our driver.
                $.each(passengers, function (index, element) {
            var currentParent = driver.parent();
            var passenger = undefined;
            while (currentParent !== 0 && passenger === undefined) {
            var attempt = currentParent.find('select[data-passenger-name="' + element + '"]');
            if (attempt.length !== 0) {
                            passenger = $(attempt);
                        }
            else {
                            currentParent = currentParent.parent();
                        }
                    }
            if (passenger !== undefined && passenger.length !== 0) {
            //We have located one of the passengers with respect to the current driver
            //Buckle up buckaroo!
            //now we need to find out if we have options for this guy
            if (that.DrivingCollection[name][element] === undefined || that.DrivingCollection[name][element].length === 0) {
                            that.DrivingCollection[name][element] =  {};
            //no options for this guy, go ahead and build up a list 
                            $.each(passenger.find('option'), function (_index, _element) {
            //grab the current option for this passenger (There will be multiple options and each will belong to a single group)
            var passengerOption = $(this);
            //Based upon the option key we grabbed from our driver, grab the group the passenger belongs to
            var passengerFilter = passengerOption.data(driverKey);
            //pull back the collection of items that belong to the group, this will either be a new collection (1st run)
            //or an existing collection of items we can add to
            var passengerGroup = that.DrivingCollection[name][element][passengerFilter] || [];
            //push out option into the collection
                                passengerGroup.push(passengerOption.clone());
            //replace the existing collection with our collection that has the newly added entry
                                that.DrivingCollection[name][element][passengerFilter] = passengerGroup;
                            });
                        }
            //now do the things using the collection, this will either be the newly created group or the existing one inside of our prototype
            var passengerOptions = that.DrivingCollection[name][element][optionKey];
            if (passengerOptions === undefined || passengerOptions.length === 0) {
            //This passenger does not have options
                            passenger.find('option:not([data-override])').remove();
            //passenger.find('option').remove();
            if (that.Readonly !== undefined && that.Readonly === true) {
                                passenger.prop('readonly', true);
                            }
            else {
                                passenger.prop('disabled', true);
                            }
            //passenger.prop('disabled', true);
            //passenger.prop('readonly', true);
                        }
            else {
            //Before we assign the family otpions, we should make sure it doesn't already have this family assigned
            var needsFilter = false;
                            $.each(passenger.find('option:not([data-override])'), function (_index, _element) {
            var keyVal = $(this).data(driverKey);
            if (keyVal !== optionKey) {
                                    needsFilter = true;
                                }
                            });
            if (needsFilter === true || passenger.find('option:not([data-override])').length === 0) {
            //If passenger has conflicting filters or currently has no assigned options, assign our group
                                passenger.find('option:not([data-override])').remove();
            //passenger.find('option').remove();
                                $.each(passengerOptions, function (_index, _element) {
                                    passenger.append(_element.clone());
                                });
            //Now that the element has changed, we need to trigger the change events
                                passenger.trigger('change');
                            }
                            passenger.prop('disabled', false);
                        }
                    }
                });
            });
        };
            var TriggerWireup = function () {
            this.form.find('select[data-driver-for]').trigger('change');
        };
            var GetContext = function(){
            return this;
        }
            return {
            Wireup: Wireup,
            TriggerWireup: TriggerWireup,
            GetContext: GetContext
        };
    }();
}(window = window || {}));
		
		
How to do the things

Your elements need a driver, passenger, and key. These are represented by the following data attributes

  • data-driver-for=”your-passenger-name-here”
  • data-passenger-name=”your-passenger-name-here”
  • data-driver-key=”you-key-for-option-elements”
			
<form id="demoform">
            <div class="row">
            <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12">
            <select name="SelectedCountry" id="SelectedCountry" data-driver-for="state-province" data-driver-key="country" class="form-control" >
            <option value="" data-country="" selected="selected">Select Country . . .</option>
            <option value="United States" data-country="United States">United States</option>
            </select>
            </div>
            <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12">
            <select name="SelectedState" id="SelectedState" data-passenger-name="state-province" class="form-control" >
            <option data-country="United States" value="">Select State . . .</option>
            <option data-country="United States" value="California">California</option>
            </select>
            </div>
            </div>
</form>
			
	

Wire it up with some JS

		
$(document).ready(function(){
            var Form = $("#demoform");
            //Make a driver list
            var drivingList = new DrivingList({
            form: Form
	});
            //wireup
	drivingList.Wireup();
            //trigger the wireup
	drivingList.TriggerWireup();
});
		
	
Demo!
(Try selecting ‘United States’, ‘Canada’, ‘Australia’ to render dependencies)