Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Shada 55 posts 137 karma points
    May 11, 2015 @ 12:00
    Shada
    0

    Sort in Chosen Multi-Select Menu

    I create a data type based on the chosen multi-select plugin. htnl:

    <div ng-controller="EditDropDown.EddListController" >
      <select 
        name="EddListDropdownList" 
        id ="eddList"  
        class="umb-editor umb-dropdown" 
        multiple
        data-ng-model="model.value" 
        data-ng-options="d.Id as d.Name for d in documents"
        chosen
        >
      </select>
    </div>
    

    controller.js:

    var __indexOf = [].indexOf || function (item) {
        for (var i = 0, l = this.length; i < l; i++) {
            if (i in this && this[i] === item) {
                return i;
            }
        }
        return -1;
    };
    
    angular.module("umbraco").config(function () {
    }
        ).controller("EditDropDown.EddListController", function ($scope, $timeout, assetsService, eddlistResource, notificationsService, contentResource, contentTypeResource) {
            $scope.getRegions = function () {
                eddlistResource.getAll($scope.model.config.textstringvalue).then(function (response) {
                    $scope.documents = response.data;
                }, function (response) {
                    notificationsService.error("Error", "Error loading documents");
                    console.log(response.data);
    
                });
            };
            assetsService.loadCss("/Scripts/chosen/chosen.css");
            assetsService.loadCss("/Scripts/chosen/chosen-spinner.css");
    
            $('#eddList').chosen({
                no_results_text: "Не надено! <a href='javascript:addRegion()'>Добавить регион</a> "
            });
            $('#eddList_chosen').width(338);
    
            $scope.getRegions();
        })
        .directive('chosen', function () {
            var CHOSEN_OPTION_WHITELIST, NG_OPTIONS_REGEXP, isEmpty, snakeCase;
    
            NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/;
            CHOSEN_OPTION_WHITELIST = ['noResultsText', 'allowSingleDeselect', 'disableSearchThreshold', 'disableSearch', 'enableSplitWordSearch', 'inheritSelectClasses', 'maxSelectedOptions', 'placeholderTextMultiple', 'placeholderTextSingle', 'searchContains', 'singleBackstrokeDelete', 'displayDisabledOptions', 'displaySelectedOptions', 'width'];
            snakeCase = function (input) {
                return input.replace(/[A-Z]/g, function ($1) {
                    return "_" + ($1.toLowerCase());
                });
            };
            isEmpty = function (value) {
                var key;
    
                if (angular.isArray(value)) {
                    return value.length === 0;
                } else if (angular.isObject(value)) {
                    for (key in value) {
                        if (value.hasOwnProperty(key)) {
                            return false;
                        }
                    }
                }
                return true;
            };
            return {
                restrict: 'A',
                require: '?ngModel',
                terminal: true,
                link: function (scope, element, attr, ngModel) {
                    var chosen, defaultText, disableWithMessage, empty, initOrUpdate, match, options, origRender, removeEmptyMessage, startLoading, stopLoading, valuesExpr, viewWatch;
    
                    element.addClass('localytics-chosen');
                    options = scope.$eval(attr.chosen) || {};
                    angular.forEach(attr, function (value, key) {
                        if (__indexOf.call(CHOSEN_OPTION_WHITELIST, key) >= 0) {
                            return options[snakeCase(key)] = scope.$eval(value);
                        }
                    });
                    startLoading = function () {
                        return element.addClass('loading').attr('disabled', true).trigger('chosen:updated');
                    };
                    stopLoading = function () {
                        return element.removeClass('loading').attr('disabled', false).trigger('chosen:updated');
                    };
                    chosen = null;
                    defaultText = null;
                    empty = false;
    
                    function sortFunction(a, b) {
                        var ret = [];
                        $('#eddList').siblings().find('.search-choice').each(function () {
                            var selectedValue = $(this).find('a').attr("data-option-array-index");
                            ret.push(scope.documents[selectedValue].Id);
                        });
                        if (ret.indexOf(a) < ret.indexOf(b))
                            return -1
                        if (ret.indexOf(a) > ret.indexOf(b))
                            return 1
                        return 0
                    }
    
    
                    initOrUpdate = function () {
                        if (chosen) {
                            return element.trigger('liszt:updated');
                        } else {
                            chosen = element.chosen(options).data('chosen');
                            return defaultText = chosen.default_text;
                        }
                    };
                    removeEmptyMessage = function () {
                        empty = false;
                        return element.attr('data-placeholder', defaultText);
                    };
                    disableWithMessage = function () {
                        empty = true;
                        return element.attr('data-placeholder', chosen.results_none_found).attr('disabled', true).trigger('chosen:updated');
                    };
                    if (ngModel) {
                        origRender = ngModel.$render;
                        ngModel.$render = function () {
                            origRender();
                            return initOrUpdate();
                        };
                        if (attr.multiple) {
                            viewWatch = function () {
                                return ngModel.$viewValue;
                            };
                            scope.$watch(viewWatch, ngModel.$render, true);
                        }
                    } else {
                        initOrUpdate();
                    }
                    attr.$observe('disabled', function () {
                        return element.trigger('chosen:updated');
                    });
                    if (attr.ngOptions && ngModel) {
                        match = attr.ngOptions.match(NG_OPTIONS_REGEXP);
                        valuesExpr = match[7];
                        return scope.$watchCollection(valuesExpr, function (newVal, oldVal) {
                            if (angular.isUndefined(newVal)) {
                                return startLoading();
                            } else {
                                if (empty) {
                                    removeEmptyMessage();
                                }
                                stopLoading();
                                if (isEmpty(newVal)) {
                                    return disableWithMessage();
                                }
                            }
                        });
                    }
                }
            };
        });
    

    I want to be able to track user selected order. For example, if a user select option2 first then option1, I want to get the result in the order of option2 and option1. But chosen sorts user selected options. So if there is data:

    <select>
    <option value=1>1</option>
    <option value=2>2</option>
    </select>
    

    And if a user selects a value=2, then value=1, then in umbraco.cache will still be recording [1,2]. To solve this problem I wrote a sorting function

    function sortFunction(a, b) {
      var ret = [];
      $('#eddList').siblings().find('.search-choice').each(function() {
      var selectedValue = $(this).find('a').attr("data-option-array-index");
      ret.push(scope.documents[selectedValue].Id);
                        });
      if (ret.indexOf(a) < ret.indexOf(b))
      return -1 
      if (ret.indexOf(a) > ret.indexOf(b))
      return 1 
      return 0                    }
    

    And added a call to the render function:

    ngModel.$render = function () {
                            scope.model.value.sort(sortFunction);
                            origRender();
                            return initOrUpdate();
                        };
    

    This solved my problem with the entry in umbraco.cache, but when I refresh the page though I get scope.model.value = [2,1] I see the chosen outcome [1,2]. Is there a way I can tell chosen to not sorting the result? Thanks

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies