2017-03-16 15:29:07 +00:00
/ * *
* @ file
2018-11-23 12:29:20 +00:00
* JavaScript behaviors for range element integration .
2017-03-16 15:29:07 +00:00
* /
( function ( $ , Drupal ) {
'use strict' ;
/ * *
2018-11-23 12:29:20 +00:00
* Display HTML5 range output in a left / right aligned number input .
2017-03-16 15:29:07 +00:00
*
* @ type { Drupal ~ behavior }
* /
2018-11-23 12:29:20 +00:00
Drupal . behaviors . webformRangeOutputNumber = {
2017-03-16 15:29:07 +00:00
attach : function ( context ) {
2018-11-23 12:29:20 +00:00
$ ( context ) . find ( '.js-form-type-range' ) . once ( 'webform-range-output-number' ) . each ( function ( ) {
2017-03-16 15:29:07 +00:00
// Handle browser that don't support the HTML5 range input.
if ( Modernizr . inputtypes . range === false ) {
return ;
}
2018-11-23 12:29:20 +00:00
var $element = $ ( this ) ;
var $input = $element . find ( 'input[type="range"]' ) ;
var $output = $element . find ( 'input[type="number"]' ) ;
if ( ! $output . length ) {
return ;
}
2017-03-16 15:29:07 +00:00
2018-11-23 12:29:20 +00:00
// Set output value.
$output . val ( $input . val ( ) ) ;
2017-03-16 15:29:07 +00:00
2018-11-23 12:29:20 +00:00
// Sync input and output values.
$input . on ( 'input' , function ( ) {
$output . val ( $input . val ( ) ) ;
2017-03-16 15:29:07 +00:00
} ) ;
$output . on ( 'input' , function ( ) {
2018-11-23 12:29:20 +00:00
$input . val ( $output . val ( ) ) ;
2017-03-16 15:29:07 +00:00
} ) ;
2018-11-23 12:29:20 +00:00
} ) ;
}
} ;
/ * *
* 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 ) ;
} ) ;
}
} ) ;
2017-03-16 15:29:07 +00:00
}
} ;
} ) ( jQuery , Drupal ) ;