Как добавить всплывающую подсказку к слайдеру пользовательского интерфейса 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>' ); } }]);