This repository has been archived on 2025-01-19. You can view files and clone it, but cannot push or open issues or pull requests.
drupalcampbristol/web/modules/contrib/webform/js/webform.element.range.js
2018-11-23 12:29:20 +00:00

149 lines
4.7 KiB
JavaScript

/**
* @file
* JavaScript behaviors for range element integration.
*/
(function ($, Drupal) {
'use strict';
/**
* Display HTML5 range output in a left/right aligned number input.
*
* @type {Drupal~behavior}
*/
Drupal.behaviors.webformRangeOutputNumber = {
attach: function (context) {
$(context).find('.js-form-type-range').once('webform-range-output-number').each(function () {
// Handle browser that don't support the HTML5 range input.
if (Modernizr.inputtypes.range === false) {
return;
}
var $element = $(this);
var $input = $element.find('input[type="range"]');
var $output = $element.find('input[type="number"]');
if (!$output.length) {
return;
}
// Set output value.
$output.val($input.val());
// Sync input and output values.
$input.on('input', function () {
$output.val($input.val());
});
$output.on('input', function () {
$input.val($output.val());
});
});
}
};
/**
* Display HTML5 range output in a floating bubble.
*
* @type {Drupal~behavior}
*
* @see https://css-tricks.com/value-bubbles-for-range-inputs/
* @see https://stackoverflow.com/questions/33794123/absolute-positioning-in-relation-to-a-inputtype-range
*/
Drupal.behaviors.webformRangeOutputBubble = {
attach: function (context) {
$(context).find('.js-form-type-range').once('webform-range-output-bubble').each(function () {
// Handle browser that don't support the HTML5 range input.
if (Modernizr.inputtypes.range === false) {
return;
}
var $element = $(this);
var $input = $element.find('input[type="range"]');
var $output = $element.find('output');
var display = $output.attr('data-display');
if (!$output.length) {
return;
}
$element.css('position', 'relative');
$input.on('input', function () {
var inputValue = $input.val();
// Set output text with prefix and suffix.
var text = ($output.attr('data-field-prefix') || '') +
inputValue +
($output.attr('data-field-suffix') || '');
$output.text(text);
// Set output top position.
var top;
if (display === 'above') {
top = $input.position().top - $output.outerHeight() + 2;
}
else {
top = $input.position().top + $input.outerHeight() + 2;
}
// It is impossible to accurately calculate the exact position of the
// range's buttons so we only incrementally move the output bubble.
var inputWidth = $input.outerWidth();
var buttonPosition = Math.floor(inputWidth * (inputValue - $input.attr('min')) / ($input.attr('max') - $input.attr('min')));
var increment = Math.floor(inputWidth / 5);
var outputWidth = $output.outerWidth();
// Set output left position.
var left;
if (buttonPosition <= increment) {
left = 0;
}
else if (buttonPosition <= increment * 2) {
left = (increment * 1.5) - outputWidth;
if (left < 0) {
left = 0;
}
}
else if (buttonPosition <= increment * 3) {
left = (increment * 2.5) - (outputWidth / 2);
}
else if (buttonPosition <= increment * 4) {
left = (increment * 4) - outputWidth;
if (left > (increment * 5) - outputWidth) {
left = (increment * 5) - outputWidth;
}
}
else if (buttonPosition <= inputWidth) {
left = (increment * 5) - outputWidth;
}
// Also make sure to include the input's left position.
left = Math.floor($input.position().left + left);
// Finally, position the output.
$output.css({top: top, left: left});
})
// Fake a change to position output at page load.
.trigger('input');
// Add fade in/out event handlers if opacity is defined.
var defaultOpacity = $output.css('opacity');
if (defaultOpacity < 1) {
// Fade in/out on focus/blur of the input.
$input.on('focus mouseover', function () {
$output.stop().fadeTo('slow', 1);
});
$input.on('blur mouseout', function () {
$output.stop().fadeTo('slow', defaultOpacity);
});
// Also fade in when focusing the output.
$output.on('touchstart mouseover', function () {
$output.stop().fadeTo('slow', 1);
});
}
});
}
};
})(jQuery, Drupal);