Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm looking to take my JS skills to the next level - please be harsh...

define(["serviceApp", 'appConfig', "services/vehicleService"], function (serviceApp, appConfig) {
    serviceApp.directive('vehicleSelector', [
        '$compile', 'vehicleService', function ($compile, vehicleService) {
            return {
                restrict: 'EA',
                transclude: true,
                link: function(scope, element) {
                    function selectorItems(model, name, service, method, prev) {
                        var self = this;
                        this.items = [];
                        this.model = model;
                        this.name = name;
                        this.service = service;
                        this.method = method;
                        this.isLoading = false;
                        this.prev = prev;
                        this.next = null;
                        this.isVisible = true;
                        this.get = function() {
                            return self.model[self.name];
                        };
                        this.set = function(value) {
                            self.model[self.name] = value;
                        };
                        this.setItems = function(items) {
                            self.items = items;
                        };
                        this.args = function() {
                            var curr = this.prev,
                                args = [];
                            while (curr != null) {
                                args.push(curr.get());
                                curr = curr.prev;
                            }
                            return args.reverse();
                        };
                        this.load = function() {
                            self.isLoading = true;
                            self.service[self.method].apply(null, self.args())
                                .then(function (resp) {
                                    self.setItems(resp);
                                    if (resp == null || resp.length == 0) self.hide();
                                })
                                .finally(function() {
                                    self.isLoading = false;
                                });
                            if (self.next != null && self.next.get()) self.next.load();
                        };
                        this.hide = function () {
                            self.isVisible = false;
                            if (self.next != null) self.next.hide();
                        }
                        this.clear = function() {
                            if (self.next != null) self.next.clear();
                            self.setItems([]);
                            self.set(null);
                        };
                        this.onChange = function() {
                            if (self.next != null) {
                                self.next.clear();
                                self.next.load();
                            }
                        };
                        this.isEmpty = function() {
                            return self.items.length < 1;
                        };
                        this.prompt = function () {
                            return self.isLoading ? "loading" : self.isEmpty() ? "" : "select a " + self.name;
                        }
                        this.setNext = function(obj) {
                            self.next = obj;
                            if (self.prev != null) self.prev.setNext(self);
                        };
                    }

                    scope.years = new selectorItems(scope.vehicle, "year", vehicleService, "GetYears", null);
                    scope.makes = new selectorItems(scope.vehicle, "make", vehicleService, "GetMakes", scope.years);
                    scope.models = new selectorItems(scope.vehicle, "model", vehicleService, "GetModels", scope.makes);
                    scope.trims = new selectorItems(scope.vehicle, "trim", vehicleService, "GetTrims", scope.models);
                    scope.trims.setNext(null);

                    function copyAttrs(names, source, dest) {
                        for (var i = 0; i < names.length; ++i) {
                            var name = names[i];
                            var value = source.attr(name);
                            if (value) dest.attr(name, value);
                        }
                    }

                    function replace(replaceClass, withClass) {
                        var found = $(replaceClass, element);
                        var replacement = element.find(withClass);
                        if (found.length == 0) {
                            replacement.remove();
                            return;
                        }
                        // if additional attributes need to be copied from the placeholder
                        // to the dropdown, they can be added here
                        copyAttrs(['tabindex'], found, replacement);
                        found.replaceWith(replacement);
                        $compile(replacement) (scope);
                    };

                    replace('.vehicleYear', '.selectYear');
                    replace('.vehicleMake', '.selectMake');
                    replace('.vehicleModel', '.selectModel');
                    replace('.vehicleTrim', '.selectTrim');

                    scope.years.load();
                },
                templateUrl: appConfig.templateRoot + '/vehicleSelector.html'
            };
        }
    ]);
});
share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.