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

Please Sign in or register to post replies

Write your reply to:

Draft