/* * jQuery Form Styler v1.3.5 * http://dimox.name/jquery-form-styler/ * * Copyright 2012-2013 Dimox (http://dimox.name/) * Released under the MIT license. * * Date: 2013.05.01 * */ (function($) { $.fn.styler = function(opt) { var opt = $.extend({ idSuffix: '-styler', browseText: 'Обзор...', selectVisibleOptions: 0, singleSelectzIndex: '100', selectSmartPositioning: true }, opt); return this.each(function() { var el = $(this); var id = '', cl = '', dataList = ''; if (el.attr('id') !== undefined && el.attr('id') != '') id = ' id="' + el.attr('id') + opt.idSuffix + '"'; if (el.attr('class') !== undefined && el.attr('class') != '') cl = ' ' + el.attr('class'); var data = el.data(); for (var i in data) { if (data[i] != '') dataList += ' data-' + i + '="' + data[i] + '"'; } id += dataList; // checkbox if (el.is(':checkbox')) { el.css({position: 'absolute', left: -9999}).each(function() { if (el.next('span.jq-checkbox').length < 1) { var checkbox = $(''); el.after(checkbox); if (el.is(':checked')) checkbox.addClass('checked'); if (el.is(':disabled')) checkbox.addClass('disabled'); // клик на псевдочекбокс checkbox.click(function() { if (!checkbox.is('.disabled')) { if (el.is(':checked')) { el.prop('checked', false); checkbox.removeClass('checked'); } else { el.prop('checked', true); checkbox.addClass('checked'); } el.change(); return false; } else { return false; } }); // клик на label el.parent('label').add('label[for="' + el.attr('id') + '"]').click(function(e) { checkbox.click(); e.preventDefault(); }); // переключение по Space или Enter el.change(function() { if (el.is(':checked')) checkbox.addClass('checked'); else checkbox.removeClass('checked'); }) // чтобы переключался чекбокс, который находится в теге label .keydown(function(e) { if (el.parent('label').length && (e.which == 13 || e.which == 32)) checkbox.click(); }) .focus(function() { if (!checkbox.is('.disabled')) checkbox.addClass('focused'); }) .blur(function() { checkbox.removeClass('focused'); }); // обновление при динамическом изменении el.on('refresh', function() { if (el.is(':checked')) checkbox.addClass('checked'); else checkbox.removeClass('checked'); if (el.is(':disabled')) checkbox.addClass('disabled'); else checkbox.removeClass('disabled'); }); } }); // radio } else if (el.is(':radio')) { el.css({position: 'absolute', left: -9999}).each(function() { if (el.next('span.jq-radio').length < 1) { var radio = $(''); el.after(radio); if (el.is(':checked')) radio.addClass('checked'); if (el.is(':disabled')) radio.addClass('disabled'); // клик на псевдорадиокнопке radio.click(function() { if (!radio.is('.disabled')) { $('input[name="' + el.attr('name') + '"]').prop('checked', false).next().removeClass('checked'); el.prop('checked', true).next().addClass('checked'); el.change(); return false; } else { return false; } }); // клик на label el.parent('label').add('label[for="' + el.attr('id') + '"]').click(function(e) { radio.click(); e.preventDefault(); }); // переключение стрелками el.change(function() { $('input[name="' + el.attr('name') + '"]').next().removeClass('checked'); el.next().addClass('checked'); }) .focus(function() { if (!radio.is('.disabled')) radio.addClass('focused'); }) .blur(function() { radio.removeClass('focused'); }); // обновление при динамическом изменении el.on('refresh', function() { if (el.is(':checked')) { $('input[name="' + el.attr('name') + '"]').next().removeClass('checked'); radio.addClass('checked'); } else { radio.removeClass('checked'); } if (el.is(':disabled')) radio.addClass('disabled'); else radio.removeClass('disabled'); }); } }); // file } else if (el.is(':file')) { el.css({position: 'absolute', top: '-50%', right: '-50%', fontSize: '200px', opacity: 0}).each(function() { if (el.parent('span.jq-file').length < 1) { var file = $(''); var name = $('
').appendTo(file); var browse = $('
' + opt.browseText + '
').appendTo(file); el.after(file); file.append(el); if (el.is(':disabled')) file.addClass('disabled'); el.change(function() { name.text(el.val().replace(/.+[\\\/]/, '')); }) .focus(function() { file.addClass('focused'); }) .blur(function() { file.removeClass('focused'); }) .click(function() { file.removeClass('focused'); }) // обновление при динамическом изменении .on('refresh', function() { if (el.is(':disabled')) file.addClass('disabled'); else file.removeClass('disabled'); }) } }); // select } else if (el.is('select')) { el.each(function() { if (el.next('span.jqselect').length < 1) { function selectbox() { // запрещаем прокрутку страницы при прокрутке селекта function preventScrolling(selector) { selector.unbind('mousewheel DOMMouseScroll').bind('mousewheel DOMMouseScroll', function(e) { var scrollTo = null; if (e.type == 'mousewheel') { scrollTo = (e.originalEvent.wheelDelta * -1); } else if (e.type == 'DOMMouseScroll') { scrollTo = 40 * e.originalEvent.detail; } if (scrollTo) { e.preventDefault(); $(this).scrollTop(scrollTo + $(this).scrollTop()); } }); } var option = $('option', el); var list = ''; // формируем список селекта function makeList() { for (i = 0, len = option.length; i < len; i++) { var li = '', liClass = '', optionClass = '', optgroupClass = ''; if (option.eq(i).attr('data-category') !== undefined ) optionClass = 'list-item'; if (option.eq(i).attr('data-type') !== undefined) optionClass = 'any-district'; var disabled = 'disabled'; var selDis = 'selected sel disabled'; if (option.eq(i).prop('selected')) liClass = 'selected sel'; if (option.eq(i).is(':disabled')) liClass = disabled; if (option.eq(i).is(':selected:disabled')) liClass = selDis; if (option.eq(i).attr('class') !== undefined) optionClass = ' ' + option.eq(i).attr('class'); if (liClass == '') li = '
  • '+ option.eq(i).text() +'
  • '; else li = '
  • '+ option.eq(i).text() +'
  • '; // если есть optgroup if (option.eq(i).parent().is('optgroup')) { if (option.eq(i).parent().attr('class') !== undefined) optgroupClass = ' ' + option.eq(i).parent().attr('class'); li = '
  • '+ option.eq(i).text() +'
  • '; if (option.eq(i).is(':first-child')) { li = '
  • ' + option.eq(i).parent().attr('label') + '
  • ' + li; } } list += li; } } // end makeList() // одиночный селект function doSelect() { var selectbox = $(''+ '
    '+ '
    '+ '
    '+ ''); el.after(selectbox).css({position: 'absolute', left: -9999}); var divSelect = $('div.jq-selectbox__select', selectbox); var divText = $('div.jq-selectbox__text', selectbox); var optionSelected = option.filter(':selected'); // берем опцию по умолчанию if (optionSelected.length) { divText.text(optionSelected.text()); } else { divText.text(option.first().text()); } // если селект неактивный if (el.is(':disabled')) { selectbox.addClass('disabled'); // если селект активный } else { makeList(); var dropdown = $('
    '+ '
      ' + list + '
    '+ '
    '); selectbox.append(dropdown); var li = $('li', dropdown); if (li.filter('.selected').length < 1) li.first().addClass('selected sel'); var selectHeight = selectbox.outerHeight(); if (dropdown.css('left') == 'auto') dropdown.css({left: 0}); if (dropdown.css('top') == 'auto') dropdown.css({top: selectHeight}); var liHeight = li.outerHeight(); var position = dropdown.css('top'); dropdown.hide(); // при клике на псевдоселекте divSelect.click(function() { el.focus(); // умное позиционирование if (opt.selectSmartPositioning) { var win = $(window); var topOffset = selectbox.offset().top; var bottomOffset = win.height() - selectHeight - (topOffset - win.scrollTop()); var visible = opt.selectVisibleOptions; var minHeight = liHeight * 6; var newHeight = liHeight * visible; if (visible > 0 && visible < 6) minHeight = newHeight; // раскрытие вверх if (bottomOffset < 0 || bottomOffset < minHeight) { dropdown.height('auto').css({top: 'auto', bottom: position}); if (dropdown.outerHeight() > topOffset - win.scrollTop() - 20 ) { dropdown.height(Math.floor((topOffset - win.scrollTop() - 20) / liHeight) * liHeight); if (visible > 0 && visible < 6) { if (dropdown.height() > minHeight) dropdown.height(minHeight); } else if (visible > 6) { if (dropdown.height() > newHeight) dropdown.height(newHeight); } } // раскрытие вниз } else if (bottomOffset > minHeight) { dropdown.height('auto').css({bottom: 'auto', top: position}); if (dropdown.outerHeight() > bottomOffset - 20 ) { dropdown.height(Math.floor((bottomOffset - 20) / liHeight) * liHeight); if (visible > 0 && visible < 6) { if (dropdown.height() > minHeight) dropdown.height(minHeight); } else if (visible > 6) { if (dropdown.height() > newHeight) dropdown.height(newHeight); } } } } $('span.jqselect').css({zIndex: (opt.singleSelectzIndex-1)}).removeClass('focused'); selectbox.css({zIndex: opt.singleSelectzIndex}); if (dropdown.is(':hidden')) { $('div.dropdown:visible').hide(); dropdown.show(); selectbox.addClass('opened'); } else { dropdown.hide(); selectbox.removeClass('opened'); } // прокручиваем до выбранного пункта при открытии списка if (li.filter('.selected').length) { dropdown.scrollTop(dropdown.scrollTop() + li.filter('.selected').position().top - dropdown.innerHeight()/2 + liHeight/2); } preventScrolling(dropdown); return false; }); // при наведении курсора на пункт списка li.hover(function() { $(this).siblings().removeClass('selected'); }); var selectedText = li.filter('.selected').text(); // при клике на пункт списка li.filter(':not(.disabled):not(.optgroup)').click(function() { var t = $(this); var liText = t.text(); if (selectedText != liText) { var index = t.index(); if (t.is('.option')) index -= t.prevAll('.optgroup').length; t.addClass('selected sel').siblings().removeClass('selected sel'); option.prop('selected', false).eq(index).prop('selected', true); selectedText = liText; divText.text(liText); el.change(); } dropdown.hide(); }); dropdown.mouseout(function() { $('li.sel', dropdown).addClass('selected'); }); // изменение селекта el.change(function() { divText.text(option.filter(':selected').text()); li.removeClass('selected sel').not('.optgroup').eq(el[0].selectedIndex).addClass('selected sel'); }) .focus(function() { selectbox.addClass('focused'); }) .blur(function() { selectbox.removeClass('focused'); }) // прокрутки списка с клавиатуры .bind('keydown keyup', function(e) { divText.text(option.filter(':selected').text()); li.removeClass('selected sel').not('.optgroup').eq(el[0].selectedIndex).addClass('selected sel'); // вверх, влево, PageUp if (e.which == 38 || e.which == 37 || e.which == 33) { dropdown.scrollTop(dropdown.scrollTop() + li.filter('.selected').position().top); } // вниз, вправо, PageDown if (e.which == 40 || e.which == 39 || e.which == 34) { dropdown.scrollTop(dropdown.scrollTop() + li.filter('.selected').position().top - dropdown.innerHeight() + liHeight); } if (e.which == 13) { dropdown.hide(); } }); // прячем выпадающий список при клике за пределами селекта $(document).on('click', function(e) { // e.target.nodeName != 'OPTION' - добавлено для обхода бага в Опере // (при изменении селекта с клавиатуры срабатывает событие onclick) if (!$(e.target).parents().hasClass('selectbox') && e.target.nodeName != 'OPTION') { dropdown.hide().find('li.sel').addClass('selected'); selectbox.removeClass('focused opened'); } }); } } // end doSelect() // мультиселект function doMultipleSelect() { var selectbox = $(''); el.after(selectbox).css({position: 'absolute', left: -9999}); makeList(); selectbox.append('
      ' + list + '
    '); var ul = $('ul', selectbox); var li = $('li', selectbox).attr('unselectable', 'on').css({'-webkit-user-select': 'none', '-moz-user-select': 'none', '-ms-user-select': 'none', '-o-user-select': 'none', 'user-select': 'none'}); var size = el.attr('size'); var ulHeight = ul.outerHeight(); var liHeight = li.outerHeight(); if (size !== undefined && size > 0) { ul.css({'height': liHeight * size}); } else { ul.css({'height': liHeight * 4}); } if (ulHeight > selectbox.height()) { ul.css('overflowY', 'scroll'); preventScrolling(ul); // прокручиваем до выбранного пункта if (li.filter('.selected').length) { ul.scrollTop(ul.scrollTop() + li.filter('.selected').position().top); } } if (el.is(':disabled')) { selectbox.addClass('disabled'); option.each(function() { if ($(this).is(':selected')) li.eq($(this).index()).addClass('selected'); }); } else { // при клике на пункт списка li.filter(':not(.disabled):not(.optgroup)').click(function(e) { el.focus(); selectbox.removeClass('focused'); var clkd = $(this); if(!e.ctrlKey) clkd.addClass('selected'); if(!e.shiftKey) clkd.addClass('first'); if(!e.ctrlKey && !e.shiftKey) clkd.siblings().removeClass('selected first'); // выделение пунктов при зажатом Ctrl if(e.ctrlKey) { if (clkd.is('.selected')) clkd.removeClass('selected first'); else clkd.addClass('selected first'); clkd.siblings().removeClass('first'); } // выделение пунктов при зажатом Shift if(e.shiftKey) { var prev = false, next = false; clkd.siblings().removeClass('selected').siblings('.first').addClass('selected'); clkd.prevAll().each(function() { if ($(this).is('.first')) prev = true; }); clkd.nextAll().each(function() { if ($(this).is('.first')) next = true; }); if (prev) { clkd.prevAll().each(function() { if ($(this).is('.selected')) return false; else $(this).not('.disabled, .optgroup').addClass('selected'); }); } if (next) { clkd.nextAll().each(function() { if ($(this).is('.selected')) return false; else $(this).not('.disabled, .optgroup').addClass('selected'); }); } if (li.filter('.selected').length == 1) clkd.addClass('first'); } // отмечаем выбранные мышью option.prop('selected', false); li.filter('.selected').each(function() { var t = $(this); var index = t.index(); if (t.is('.option')) index -= t.prevAll('.optgroup').length; option.eq(index).prop('selected', true); }); el.change(); }); // отмечаем выбранные с клавиатуры option.each(function(i) { $(this).data('optionIndex', i); }); el.change(function() { li.removeClass('selected'); var arrIndexes = []; option.filter(':selected').each(function() { arrIndexes.push($(this).data('optionIndex')); }); li.not('.optgroup').filter(function(i) { return $.inArray(i, arrIndexes) > -1; }).addClass('selected'); }) .focus(function() { selectbox.addClass('focused'); }) .blur(function() { selectbox.removeClass('focused'); }); // прокручиваем с клавиатуры if (ulHeight > selectbox.height()) { el.keydown(function(e) { // вверх, влево, PageUp if (e.which == 38 || e.which == 37 || e.which == 33) { ul.scrollTop(ul.scrollTop() + li.filter('.selected').position().top - liHeight); } // вниз, вправо, PageDown if (e.which == 40 || e.which == 39 || e.which == 34) { ul.scrollTop(ul.scrollTop() + li.filter('.selected:last').position().top - ul.innerHeight() + liHeight*2); } }); } } } // end doMultipleSelect() if (el.is('[multiple]')) doMultipleSelect(); else doSelect(); } // end selectbox() selectbox(); // обновление при динамическом изменении el.on('refresh', function() { el.next().remove(); selectbox(); }); } }); }// end select }); } })(jQuery);