Torakami Ответов: 0

Как добавить всплывающую подсказку к слайдеру пользовательского интерфейса angular 1


Я создаю директиву слайдера углового пользовательского интерфейса. Но можете добавить всплывающую подсказку для элемента управления "ползунок". Пожалуйста, предложите

Что я уже пробовал:

angular.module('lt.directives').directive('slider', ['$templateCache', '$parseOptions', function ($templateCache, $parseOptions) {
    // Move these defaults into a value object
    var UPDATE_DELAY_MS = 100,
        NUM_TICKS = 20,
        MIN = 0,
        MAX = 5000,
        VALUE = 1500,
        STEPS = 100,
        DEFAULT_HTML = '<div class="ui-slider-bwrap">' +
                                '<div class="ui-slider-ticks">' +
                                '   <span class="ui-tick-mark" ng-style="{left: (5 * $index) + \'%\'}" ng-repeat="tick in ticks" />' +
                                '</div>' +
                                '<div class="ui-slider"></div>' +
                                '<div class="ui-slider-labels">' +
                                '   <span class="minLabel">{{labelMin}}</span>' +
                                '   <span class="maxLabel">{{labelMax + (value == max && showLabelMaxPlus && "+" || "")}}</span>' +
                                '</div>' +
                            '</div>';

    return {
        require: 'ngModel',
        scope: {
            value: '=ngModel',
            defaultValue: '=?',
            sliderData: '=?',
            min: '=?',
            max: '=?',
            step: '=?',
            labelMin: '@',
            labelMax: '@'
        },
        template: function (element, attrs) {
            // In the future, vary the template based on attrs.slider
            return DEFAULT_HTML;
        },
        link: function (scope, element, attrs, ngModel) {
            // Set defaults if none exist
            _.defaults(scope, {
                value: scope.defaultValue,
                labelMin: '0%',
                labelMax: '100%'
            });

            // Don't set isolate scope if min/max are undefined, 
            // since it'll result in a non-assignable expression error.
            if (_.every([scope.min, scope.max], angular.isDefined)) {
                _.defaults(scope, {
                    min: MIN,
                    max: MAX
                });
            }

            // Only check for existance of the attribute
            scope.showLabelMaxPlus = angular.isDefined(attrs.showLabelMaxPlus);

            var staggerStepObj = scope.$eval(attrs.staggerStep),
                modelMapObj = scope.$eval(attrs.modelMap),
                parsedOptions = angular.isDefined(attrs.sliderOptions) ? $parseOptions(attrs.sliderOptions) : undefined,
                slider = element.find('.ui-slider'),
                sliderObj,
                optionsList = [],
                valuesArr = [];

            // Stagger-step and ng-options sliders are both mapped value sliders
            var buildMappedValueSlider = function () {
                // Since the slider uses a different value system, find the index
                // that the ngModel maps to.
                // Ensure index is less than valuesArr length..
                var newVal = parseFloat(scope.value, 10);
                var initialIndex = Math.min(_.sortedIndex(valuesArr, scope.value), valuesArr.length - 1);

                // .. and greater than 0
                initialIndex = Math.max(initialIndex, 0);

                // Normalize the value
                scope.value = valuesArr[initialIndex];
                if (newVal < valuesArr[initialIndex] && (valuesArr[initialIndex] % 2) !== 0 && initialIndex > 0) {
                    scope.value = valuesArr[initialIndex-1];
                }

                // Set real min and max on scope if no attrs exist
                if (angular.isUndefined(scope.min)) {
                    scope.min = valuesArr[0];
                }
                if (angular.isUndefined(scope.max)) {
                    scope.max = valuesArr[valuesArr.length - 1];
                }
                
                // Attach label to parent scope (bad!)
                if (angular.isDefined(parsedOptions)) {
                    scope.$parent.sliderLabel = _.findWhere(optionsList, { value: scope.value }).label;
                }

                sliderObj = {
                    range: 'min',
                    min: 0,
                    max: valuesArr.length - 1,
                    value: initialIndex
                };

                slider.slider(sliderObj);
            };

            // Watch ng-model, min, and max - if any change, update the slider

            if (angular.isDefined(parsedOptions)) {
                // Values may be async, so wait until it returns before
                // initializing the slider.
                // Use scope.$parent so that we can access data outside of the
                // isolate scope.
                // Assumption: "value as label for obj in array"-like syntax is being used
                parsedOptions.valuesFn(scope.$parent, ngModel).then(function (values) {
                    optionsList = values;
                    valuesArr = _.pluck(values, 'value');

                    buildMappedValueSlider();
                });
            }
            else if (angular.isObject(staggerStepObj)) {
                var staggerStepKeys = _.map(_.keys(staggerStepObj), function (key) {
                    return parseFloat(key, 10);
                });

                // Create the full array of values
                for (var i = 0, ii = staggerStepKeys.length; i < ii; i++) {
                    var rangeMin = staggerStepKeys[i],
                        rangeMax = (i < staggerStepKeys.length - 1) ? staggerStepKeys[i + 1] : scope.max,
                        rangeStep = staggerStepObj[staggerStepKeys[i]],
                        range = _.map(_.range(rangeMin, rangeMax, rangeStep), function (step) {
                            // _.range doesn't create float ranges correctly, so fix this
                            return parseFloat(accounting.toFixed(step, 3));
                        });

                    valuesArr = valuesArr.concat(range);
                }

                // Pare down the list so that it's between min & max
                valuesArr = _.filter(valuesArr, function (value) {
                    return value >= scope.min && value < scope.max;
                });

                // Add the max value for good measure
                valuesArr.push(scope.max);

                buildMappedValueSlider();
            }
            else {
                sliderObj = {
                    range: 'min',
                    min: scope.min,
                    max: scope.max,
                    value: angular.isObject(modelMapObj) ? _.invert(modelMapObj)[scope.value] : scope.value,
                    step: scope.step || (scope.max - scope.min) / STEPS
                };

                slider.slider(sliderObj);
            }

            var throttledModelUpdate = _.throttle(function (sliderValue) {
                var modelValue = sliderValue;

                // Find the real model value
                if (angular.isObject(staggerStepObj) || angular.isDefined(parsedOptions)) {
                    modelValue = valuesArr[sliderValue];
                }

                // If we've defined a model mapping, perform the translation
                // before setting the model value
                modelValue = angular.isObject(modelMapObj) ? modelMapObj[modelValue] : modelValue;

                // Attach label to parent scope (bad!)
                if (angular.isDefined(parsedOptions)) {
                    scope.$parent.sliderLabel = _.findWhere(optionsList, { value: modelValue }).label;
                }

                scope.$apply(function () {
                    // Push slider value (or mapped value) out to the model
                    ngModel.$setViewValue(modelValue);
                });
            }, UPDATE_DELAY_MS);

            slider.bind({
                slide: function (event, ui) {
                    throttledModelUpdate(ui.value); 
                }
            });

            // Initialize the slider
            // TODO: Watch these values and re-init the slider based on outside changes
            // so that the slider can be updated dynamically
            if (attrs.reset === "on") {
                scope.$watch(function () {
                    return ngModel.$modelValue;
                }, function (newVal, oldVal) {
                    if (newVal !== oldVal) {
                        buildMappedValueSlider();
                    }
                });
            }

            scope.ticks = _.range(NUM_TICKS);
        }
    };
} ]);



angular.module('fossa').run(['$templateCache', 'variation', function ($templateCache, variation) {
    if (variation.getVariationByName('style') === 'tactile') {
        $templateCache.put('ig-desired-loan-amount-slider',
            '<label for="desired-loan-amount-slider" class="control-label" ng-bind-html="groupUtil.getProp(\'label\', \'How much would you like to borrow?\')"></label>' +
            '<div class="row">' +
                '<div class="col-xs-10 col-xs-offset-1">' +
                    '<div slider label-tip reset={{resetSlider}} ng-model="inputs.desiredLoanAmount" label-min="$0" label-max="$400K" show-label-max-plus slider-options="item.value as item.name for item in lists.desiredLoanAmount" />' +
                    '<span ng-show="formData.returnToHE" class="range-update">Range has been updated</span>' +
                '</div>' +
            '</div>'
        );
    }
}]);

0 Ответов