semanticui-8.x-1.x-dev/js/floating-labels.js
js/floating-labels.js
/**
* Updates field labels to use "floating label" behaviour.
*/
(function ($) {
Drupal.semanticui = Drupal.semanticui || {};
Drupal.semanticui.floatingLabels = Drupal.semanticui.floatingLabels || {
duration: 700,
delay: 100
};
/**
* Attaches floating labels to text fields.
*/
Drupal.behaviors.semanticuiTextFloatingLabels = {
attach: function (context, settings) {
// Set a short timeout to properly handle autofilled fields (e.g. with
// saved password or login).
setTimeout(function() {
// Initialise default label state.
$('input[type=text], input[type=email], input[type=password], input[type=number], input[type=url]', context).each(function () {
let $helperLabel = $(this).parent().find('.floating-label');
if (!$helperLabel.length) {
const $mainLabel = $(this).parent().find('label');
$helperLabel = $mainLabel.clone();
$helperLabel.addClass('floating-label').addClass('transition').addClass('hidden');
$(this).parent().prepend($helperLabel);
$mainLabel.addClass('main');
}
if ($(this).is('*:-webkit-autofill') || $(this).val() !== '' || $(this).is(':focus')) {
$(this).parent().find('label.floating-label').removeClass('hidden');
$(this).parent().find('label.main').addClass('transition').addClass('hidden');
}
});
}, 100);
// Process focus and blur events.
$('input[type=text], input[type=email], input[type=password], input[type=number], input[type=url]', context).once('floating-label').each(function () {
$(this).on('focus blur', function () {
if ($(this).is('*:-webkit-autofill') || $(this).val() !== '') {
return;
}
const $field = $(this).parent();
$field.find('label.main').transition('fade');
setTimeout(function () {
$field.find('label.floating-label').transition({
animation: 'fade',
duration: Drupal.semanticui.floatingLabels.duration
});
}, Drupal.semanticui.floatingLabels.delay);
});
});
}
};
/**
* Attaches floating labels to autocomplete dropdown fields.
*/
Drupal.behaviors.semanticuiAutocompleteFloatingLabels = {
attach: function (context, settings) {
$('.js-form-type-entity-autocomplete > .dropdown > input[data-autocomplete-path], .js-form-type-autocomplete > .dropdown > input[data-autocomplete-path] ', context).each(function () {
let $helperLabel = $(this).closest('.field').find('.floating-label');
if (!$helperLabel.length) {
const $mainLabel = $(this).closest('.field').find('label');
$helperLabel = $mainLabel.clone();
$helperLabel.addClass('floating-label').addClass('transition').addClass('hidden');
$(this).closest('.field').prepend($helperLabel);
$mainLabel.addClass('main');
}
if ($(this).val() !== '') {
$(this).closest('.field').find('label.floating-label').removeClass('hidden').addClass('visible');
$(this).closest('.field').find('label.main').addClass('transition').addClass('hidden');
}
});
// Catch "focusin" event as autocomplete dropdown may be initialized after
// floating labels were attached. For example, when the field is loaded
// with AJAX.
const $autocompleteElements = $('.js-form-type-entity-autocomplete > .dropdown, .js-form-type-autocomplete > .dropdown');
$autocompleteElements.each(function () {
$(this).on('focusin', function () {
const $searchElements = $(this).find('> input.search');
$searchElements.once('floating-label').each(function () {
const $dropdown = $(this).closest('.ui.dropdown');
const $field = $(this).closest('.field');
const $floatingLabel = $field.find('label.floating-label');
const $mainLabel = $field.find('label.main');
$(this).on('focus', function (event) {
if ($dropdown.find('input[data-autocomplete-path]').val() !== '' && $floatingLabel.hasClass('visible') && !$floatingLabel.hasClass('animating')) {
return;
}
if ($floatingLabel.hasClass('animating') || $mainLabel.hasClass('animating')) {
return;
}
if ($dropdown.dropdown('get value') === '') {
if ($floatingLabel.hasClass('visible') && !$floatingLabel.hasClass('animating')) {
return;
}
$mainLabel.transition('fade');
setTimeout(function () {
$floatingLabel.transition({
animation: 'fade',
duration: Drupal.semanticui.floatingLabels.duration
});
}, Drupal.semanticui.floatingLabels.delay);
}
});
$(this).on('blur', function (event) {
// Skip processing the labels if the user clicks on the dropdown
// menu and it's value is not empty.
if ((event.relatedTarget && $(event.relatedTarget).hasClass('menu')) || $dropdown.find('> .search').val() !== '') {
return;
}
if ($dropdown.find('input[data-autocomplete-path]').val() !== '' && $floatingLabel.hasClass('visible') && !$floatingLabel.hasClass('animating')) {
return;
}
if ($dropdown.dropdown('get value') === '') {
if ($mainLabel.hasClass('visible') && !$mainLabel.hasClass('animating')) {
return;
}
$mainLabel.transition('fade');
setTimeout(function () {
$floatingLabel.transition({
animation: 'fade',
duration: Drupal.semanticui.floatingLabels.duration
});
}, Drupal.semanticui.floatingLabels.delay);
}
});
});
});
});
}
};
/**
* Attaches floating labels to dropdown fields.
*/
Drupal.behaviors.semanticuiDropdownFloatingLabels = {
attach: function (context, settings) {
$('.ui.selection.dropdown', context).once('floating-label').each(function () {
const $form = $(context).hasClass('form') && $(context).hasClass('ui') ?
$(context) : $(this).closest('.ui.form');
const $dropdown = $(this);
$dropdown.parent().removeClass('floating-label-active');
if ($(this).dropdown('get value')) {
$dropdown.parent().find('> label').addClass('floating-label');
}
// There is default (greyed) text, don't show the label.
if ($(this).find('> .default.text').length) {
$dropdown.parent().find('> label').addClass('transition').addClass('hidden').removeClass('visible');
}
// The value was changed, show the label if it was hidden.
$dropdown.find('select').on('change', function () {
if (!$dropdown.parent().find('> label').hasClass('hidden')) {
return;
}
$dropdown.parent().find('> label').addClass('floating-label').transition('fade');
});
$dropdown.dropdown('setting', 'onShow', function () {
// Remove helper class from all other elements except the current one.
$('.field.floating-label-active', $form).removeClass('floating-label-active');
$dropdown.parent().addClass('floating-label-active');
});
$dropdown.bind('mouseover', function () {
// Skip attaching helper class if some of the dropdown elements has
// active menu.
if ($('.ui.dropdown > .menu.visible', $form).length || $('.ui.dropdown > .menu.animating', $form).length) {
return;
}
$dropdown.parent().addClass('floating-label-active');
});
$dropdown.bind('mouseout', function () {
if ($dropdown.hasClass('active') || $dropdown.find('> .menu').hasClass('animating')) {
return;
}
$dropdown.parent().removeClass('floating-label-active');
});
});
}
};
/**
* Attaches floating labels to textarea fields.
*/
Drupal.behaviors.semanticuiTextareaFloatingLabels = {
attach: function (context, settings) {
const initTextarea = function ($textarea) {
};
$('textarea', context).each(function () {
const $textFormat = $(this).closest('.js-text-format-wrapper').find('.filter-wrapper .ui.dropdown');
let $helperLabel = $(this).closest('.js-form-type-textarea').find('.floating-label');
if (!$helperLabel.length) {
const $mainLabel = $(this).closest('.js-form-type-textarea').find('label');
$helperLabel = $mainLabel.clone();
$helperLabel.addClass('floating-label').addClass('transition').addClass('hidden');
$(this).closest('.js-form-type-textarea').prepend($helperLabel);
$mainLabel.addClass('main');
}
$helperLabel = $(this).closest('.webform-component-textarea').find('.floating-label');
if (!$helperLabel.length) {
$helperLabel = $(this).closest('.webform-component-textarea').find('label').clone();
$helperLabel.addClass('floating-label').addClass('transition').addClass('hidden');
$(this).closest('.webform-component-textarea').prepend($helperLabel);
}
if ($textFormat.length && $textFormat.dropdown('get value') !== 'restricted_html') {
$(this).closest('.js-form-type-textarea').find('label.floating-label').removeClass('hidden');
$(this).closest('.js-form-type-textarea').find('label.main').addClass('transition').removeClass('visible').addClass('hidden');
return;
}
if ($(this).val() !== '' || $(this).is(':focus')) {
$(this).closest('.js-form-type-textarea').find('label.floating-label').removeClass('hidden');
$(this).closest('.js-form-type-textarea').find('label.main').addClass('transition').addClass('hidden');
$(this).closest('.webform-component-textarea').find('label.floating-label').removeClass('hidden');
$(this).closest('.webform-component-textarea').find('label.main').addClass('transition').addClass('hidden');
}
});
$('textarea', context).once('floating-label').each(function () {
const $textarea = $(this);
const $regularField = $textarea.closest('.js-form-type-textarea');
$(this).on('focus blur', function () {
const $textFormat = $textarea.closest('.js-text-format-wrapper').find('.filter-wrapper .ui.dropdown');
// Textarea with bar uses the label in the upper position.
if ($textFormat.length && $textFormat.dropdown('get value') !== 'restricted_html') {
$textarea.closest('.js-form-type-textarea').find('label.floating-label').removeClass('hidden');
$textarea.closest('.js-form-type-textarea').find('label.main').addClass('transition').removeClass('visible').addClass('hidden');
return;
}
if ($(this).val() !== '') {
return;
}
$regularField.find('label.main').transition('fade');
setTimeout(function () {
$regularField.find('label.floating-label').transition({
animation: 'fade',
duration: Drupal.semanticui.floatingLabels.duration
});
}, Drupal.semanticui.floatingLabels.delay);
const $webformField = $(this).closest('.webform-component-textarea');
$webformField.find('label.main').transition('fade');
setTimeout(function () {
$webformField.find('label.floating-label').transition({
animation: 'fade',
duration: Drupal.semanticui.floatingLabels.duration
});
}, Drupal.semanticui.floatingLabels.delay);
});
// Switch the label depending on text format (as there may be a bar with
// formatting options).
const $textFormat = $regularField.parent().find('.filter-wrapper .ui.dropdown');
if ($textFormat.length) {
$textFormat.dropdown('setting', 'onChange', function (value) {
$textarea.trigger('blur');
});
}
});
}
};
/**
* Attaches floating labels to Date and Time fields.
*/
Drupal.behaviors.semanticuiDateTimeFloatingLabels = {
attach: function (context, settings) {
const $fields = $('input[type="date"], input[type="time"]', context);
$fields.each(function () {
// Walk by inputs and get related parent element as the wrapper may use
// ".js-form-type-date" class for Time fields (e.g. while creating a
// node).
const $field = $(this).parent();
let $helperLabel = $('> label.floating-label', $field);
if (!$helperLabel.length) {
let $mainLabel = $('> label', $field);
$helperLabel = $mainLabel.clone();
$helperLabel.addClass('floating-label').addClass('transition').addClass('hidden');
$field.prepend($helperLabel);
$mainLabel.addClass('main');
}
// Show floating label in the upper position as browsers uses custom
// placeholder for Date and Time fields.
$('> label.floating-label', $field).removeClass('hidden');
$('> label.main', $field).addClass('transition').addClass('hidden');
});
}
};
})(jQuery);
