/* FORMS */ ;(function ($) { $(document).ready(function () { // Function to update labels of text fields Materialize.updateTextFields = function () { var input_selector = 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea' $(input_selector).each(function (index, element) { if ($(element).val().length > 0 || element.autofocus || $(this).attr('placeholder') !== undefined || $(element)[0].validity.badInput === true) { $(this).siblings('label, i').addClass('active') }else { $(this).siblings('label, i').removeClass('active') } }) } // Text based inputs var input_selector = 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea' // Add active if form auto complete $(document).on('change', input_selector, function () { if ($(this).val().length !== 0 || $(this).attr('placeholder') !== undefined) { $(this).siblings('label').addClass('active') } validate_field($(this)) }) // Add active if input element has been pre-populated on document ready $(document).ready(function () { Materialize.updateTextFields() }) // HTML DOM FORM RESET handling $(document).on('reset', function (e) { var formReset = $(e.target) if (formReset.is('form')) { formReset.find(input_selector).removeClass('valid').removeClass('invalid') formReset.find(input_selector).each(function () { if ($(this).attr('value') === '') { $(this).siblings('label, i').removeClass('active') } }) // Reset select formReset.find('select.initialized').each(function () { var reset_text = formReset.find('option[selected]').text() formReset.siblings('input.select-dropdown').val(reset_text) }) } }) // Add active when element has focus $(document).on('focus', input_selector, function () { $(this).siblings('label, i').addClass('active') }) $(document).on('blur', input_selector, function () { var $inputElement = $(this) if ($inputElement.val().length === 0 && $inputElement[0].validity.badInput !== true && $inputElement.attr('placeholder') === undefined) { $inputElement.siblings('label, i').removeClass('active') } if ($inputElement.val().length === 0 && $inputElement[0].validity.badInput !== true && $inputElement.attr('placeholder') !== undefined) { $inputElement.siblings('i').removeClass('active') } validate_field($inputElement) }) window.validate_field = function (object) { var hasLength = object.attr('length') !== undefined var lenAttr = parseInt(object.attr('length')) var len = object.val().length if (object.val().length === 0 && object[0].validity.badInput === false) { if (object.hasClass('validate')) { object.removeClass('valid') object.removeClass('invalid') } }else { if (object.hasClass('validate')) { // Check for character counter attributes if ((object.is(':valid') && hasLength && (len <= lenAttr)) || (object.is(':valid') && !hasLength)) { object.removeClass('invalid') object.addClass('valid') }else { object.removeClass('valid') object.addClass('invalid') } } } } // Textarea Auto Resize var hiddenDiv = $('.hiddendiv').first() if (!hiddenDiv.length) { hiddenDiv = $('
') $('body').append(hiddenDiv) } var text_area_selector = '.materialize-textarea' function textareaAutoResize ($textarea) { // Set font properties of hiddenDiv var fontFamily = $textarea.css('font-family') var fontSize = $textarea.css('font-size') if (fontSize) { hiddenDiv.css('font-size', fontSize); } if (fontFamily) { hiddenDiv.css('font-family', fontFamily); } if ($textarea.attr('wrap') === 'off') { hiddenDiv.css('overflow-wrap', 'normal') .css('white-space', 'pre') } hiddenDiv.text($textarea.val() + '\n') var content = hiddenDiv.html().replace(/\n/g, '
') hiddenDiv.html(content) // When textarea is hidden, width goes crazy. // Approximate with half of window size if ($textarea.is(':visible')) { hiddenDiv.css('width', $textarea.width()) }else { hiddenDiv.css('width', $(window).width() / 2) } $textarea.css('height', hiddenDiv.height()) } $(text_area_selector).each(function () { var $textarea = $(this) if ($textarea.val().length) { textareaAutoResize($textarea) } }) $('body').on('keyup keydown autoresize', text_area_selector, function () { textareaAutoResize($(this)) }) // File Input Path $(document).on('change', '.file-field input[type="file"]', function () { var file_field = $(this).closest('.file-field') var path_input = file_field.find('input.file-path') var files = $(this)[0].files var file_names = [] for (var i = 0; i < files.length; i++) { file_names.push(files[i].name) } path_input.val(file_names.join(', ')) path_input.trigger('change') }) /**************** * Range Input * ****************/ var range_type = 'input[type=range]' var range_mousedown = false var left $(range_type).each(function () { var thumb = $('') $(this).after(thumb) }) var range_wrapper = '.range-field' $(document).on('change', range_type, function (e) { var thumb = $(this).siblings('.thumb') thumb.find('.value').html($(this).val()) }) $(document).on('input mousedown touchstart', range_type, function (e) { var thumb = $(this).siblings('.thumb') var width = $(this).outerWidth() // If thumb indicator does not exist yet, create it if (thumb.length <= 0) { thumb = $('') $(this).after(thumb) } // Set indicator value thumb.find('.value').html($(this).val()) range_mousedown = true $(this).addClass('active') if (!thumb.hasClass('active')) { thumb.velocity({ height: '30px', width: '30px', top: '-20px', marginLeft: '-15px'}, { duration: 300, easing: 'easeOutExpo' }) } if (e.type !== 'input') { if (e.pageX === undefined || e.pageX === null) { // mobile left = e.originalEvent.touches[0].pageX - $(this).offset().left }else { // desktop left = e.pageX - $(this).offset().left } if (left < 0) { left = 0 } else if (left > width) { left = width } thumb.addClass('active').css('left', left) } thumb.find('.value').html($(this).val()) }) $(document).on('mouseup touchend', range_wrapper, function () { range_mousedown = false $(this).removeClass('active') }) $(document).on('mousemove touchmove', range_wrapper, function (e) { var thumb = $(this).children('.thumb') var left if (range_mousedown) { if (!thumb.hasClass('active')) { thumb.velocity({ height: '30px', width: '30px', top: '-20px', marginLeft: '-15px'}, { duration: 300, easing: 'easeOutExpo' }) } if (e.pageX === undefined || e.pageX === null) { // mobile left = e.originalEvent.touches[0].pageX - $(this).offset().left }else { // desktop left = e.pageX - $(this).offset().left } var width = $(this).outerWidth() if (left < 0) { left = 0 } else if (left > width) { left = width } thumb.addClass('active').css('left', left) thumb.find('.value').html(thumb.siblings(range_type).val()) } }) $(document).on('mouseout touchleave', range_wrapper, function () { if (!range_mousedown) { var thumb = $(this).children('.thumb') if (thumb.hasClass('active')) { thumb.velocity({ height: '0', width: '0', top: '10px', marginLeft: '-6px'}, { duration: 100 }) } thumb.removeClass('active') } }) }); // End of $(document).ready /******************* * Select Plugin * ******************/ $.fn.material_select = function (callback) { $(this).each(function () { var $select = $(this) if ($select.hasClass('browser-default')) { return; // Continue to next (return false breaks out of entire loop) } var multiple = $select.attr('multiple') ? true : false, lastID = $select.data('select-id') // Tear down structure if Select needs to be rebuilt if (lastID) { $select.parent().find('span.caret').remove() $select.parent().find('input').remove() $select.unwrap() $('ul#select-options-' + lastID).remove() } // If destroying the select, remove the selelct-id and reset it to it's uninitialized state. if (callback === 'destroy') { $select.data('select-id', null).removeClass('initialized') return } var uniqueID = Materialize.guid() $select.data('select-id', uniqueID) var wrapper = $('
') wrapper.addClass($select.attr('class')) var options = $(''), selectChildren = $select.children('option, optgroup'), valuesSelected = [], optionsHover = false var label = $select.find('option:selected').html() || $select.find('option:first').html() || '' // Function that renders and appends the option taking into // account type and possible image icon. var appendOptionWithIcon = function (select, option, type) { // Add disabled attr if disabled var disabledClass = (option.is(':disabled')) ? 'disabled ' : '' // add icons var icon_url = option.data('icon') var classes = option.attr('class') if (!!icon_url) { var classString = '' if (!!classes) classString = ' class="' + classes + '"' // Check for multiple type. if (type === 'multiple') { options.append($('
  • ' + option.html() + '
  • ')) } else { options.append($('
  • ' + option.html() + '
  • ')) } return true } // Check for multiple type. if (type === 'multiple') { options.append($('
  • ' + option.html() + '
  • ')) } else { options.append($('
  • ' + option.html() + '
  • ')) } } /* Create dropdown structure. */ if (selectChildren.length) { selectChildren.each(function () { if ($(this).is('option')) { // Direct descendant option. if (multiple) { appendOptionWithIcon($select, $(this), 'multiple') } else { appendOptionWithIcon($select, $(this)) } } else if ($(this).is('optgroup')) { // Optgroup. var selectOptions = $(this).children('option') options.append($('
  • ' + $(this).attr('label') + '
  • ')) selectOptions.each(function () { appendOptionWithIcon($select, $(this)) }) } }) } options.find('li:not(.optgroup)').each(function (i) { $(this).click(function (e) { // Check if option element is disabled if (!$(this).hasClass('disabled') && !$(this).hasClass('optgroup')) { var selected = true if (multiple) { $('input[type="checkbox"]', this).prop('checked', function (i, v) { return !v; }) selected = toggleEntryFromArray(valuesSelected, $(this).index(), $select) $newSelect.trigger('focus') } else { options.find('li').removeClass('active') $(this).toggleClass('active') $newSelect.val($(this).text()) } activateOption(options, $(this)) $select.find('option').eq(i).prop('selected', selected) // Trigger onchange() event $select.trigger('change') if (typeof callback !== 'undefined') callback() } e.stopPropagation() }) }) // Wrap Elements $select.wrap(wrapper) // Add Select Display Element var dropdownIcon = $('') if ($select.is(':disabled')) dropdownIcon.addClass('disabled') // escape double quotes var sanitizedLabelHtml = label.replace(/"/g, '"') var $newSelect = $('') $select.before($newSelect) $newSelect.before(dropdownIcon) $newSelect.after(options) // Check if section element is disabled if (!$select.is(':disabled')) { $newSelect.dropdown({'hover': false, 'closeOnClick': false}) } // Copy tabindex if ($select.attr('tabindex')) { $($newSelect[0]).attr('tabindex', $select.attr('tabindex')) } $select.addClass('initialized') $newSelect.on({ 'focus': function () { if ($('ul.select-dropdown').not(options[0]).is(':visible')) { $('input.select-dropdown').trigger('close') } if (!options.is(':visible')) { $(this).trigger('open', ['focus']) var label = $(this).val() var selectedOption = options.find('li').filter(function () { return $(this).text().toLowerCase() === label.toLowerCase() })[0] activateOption(options, selectedOption) } }, 'touchend click': function (e) { e.stopPropagation() } }) $newSelect.on('blur', function () { if (!multiple) { $(this).trigger('close') } options.find('li.selected').removeClass('selected') }) options.hover(function () { optionsHover = true }, function () { optionsHover = false }) $(window).on({ 'click': function () { multiple && (optionsHover || $newSelect.trigger('close')) } }) // Add initial multiple selections. if (multiple) { $select.find('option:selected:not(:disabled)').each(function () { var index = $(this).index() toggleEntryFromArray(valuesSelected, index, $select) options.find('li').eq(index).find(':checkbox').prop('checked', true) }) } // Make option as selected and scroll to selected position activateOption = function (collection, newOption) { if (newOption) { collection.find('li.selected').removeClass('selected') var option = $(newOption) option.addClass('selected') options.scrollTo(option) } } // Allow user to search by typing // this array is cleared after 1 second var filterQuery = [], onKeyDown = function (e) { // TAB - switch to another input if (e.which == 9) { $newSelect.trigger('close') return } // ARROW DOWN WHEN SELECT IS CLOSED - open select options if (e.which == 40 && !options.is(':visible')) { $newSelect.trigger('open') return } // ENTER WHEN SELECT IS CLOSED - submit form if (e.which == 13 && !options.is(':visible')) { return } e.preventDefault() // CASE WHEN USER TYPE LETTERS var letter = String.fromCharCode(e.which).toLowerCase(), nonLetters = [9, 13, 27, 38, 40] if (letter && (nonLetters.indexOf(e.which) === -1)) { filterQuery.push(letter) var string = filterQuery.join(''), newOption = options.find('li').filter(function () { return $(this).text().toLowerCase().indexOf(string) === 0 })[0] if (newOption) { activateOption(options, newOption) } } // ENTER - select option and close when select options are opened if (e.which == 13) { var activeOption = options.find('li.selected:not(.disabled)')[0] if (activeOption) { $(activeOption).trigger('click') if (!multiple) { $newSelect.trigger('close') } } } // ARROW DOWN - move to next not disabled option if (e.which == 40) { if (options.find('li.selected').length) { newOption = options.find('li.selected').next('li:not(.disabled)')[0] } else { newOption = options.find('li:not(.disabled)')[0] } activateOption(options, newOption) } // ESC - close options if (e.which == 27) { $newSelect.trigger('close') } // ARROW UP - move to previous not disabled option if (e.which == 38) { newOption = options.find('li.selected').prev('li:not(.disabled)')[0] if (newOption) activateOption(options, newOption) } // Automaticaly clean filter query so user can search again by starting letters setTimeout(function () { filterQuery = []; }, 1000) } $newSelect.on('keydown', onKeyDown) }) function toggleEntryFromArray (entriesArray, entryIndex, select) { var index = entriesArray.indexOf(entryIndex), notAdded = index === -1 if (notAdded) { entriesArray.push(entryIndex) } else { entriesArray.splice(index, 1) } select.siblings('ul.dropdown-content').find('li').eq(entryIndex).toggleClass('active') // use notAdded instead of true (to detect if the option is selected or not) select.find('option').eq(entryIndex).prop('selected', notAdded) setValueToInput(entriesArray, select) return notAdded } function setValueToInput (entriesArray, select) { var value = '' for (var i = 0, count = entriesArray.length; i < count; i++) { var text = select.find('option').eq(entriesArray[i]).text() i === 0 ? value += text : value += ', ' + text } if (value === '') { value = select.find('option:disabled').eq(0).text() } select.siblings('input.select-dropdown').val(value) } } }(jQuery)); jQuery('select').siblings('input.select-dropdown').on('mousedown', function (e) { if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { if (e.clientX >= e.target.clientWidth || e.clientY >= e.target.clientHeight) { e.preventDefault() } } });