вторник, 15 апреля 2014 г.

Dev: Web: IE8 и кастомные чекбоксы

Один из способов сделать кастомный чекбокс - это скрыть реальный, а на его месте сделать картинку с желаемым видом чекбокса (фактически картинкой задаваемой через стили), но т.к. иногда бывает необхоидмость поддерживать старые браузеры типа IE8(это последняя доступная версия IE у пользователей XP, которых во всяких гос. учреждениях остается еще довольно много, IE9 туда нельзя поставить), промучавшись некоторое время, я создал ряд хаков, чтобы на IE8 кастомные чекбоксы вяглядели и работали также как на современных браузерах.

Для современных браузеров для работы кастомных чекбоксов, достаточно прописать в стилях что-то типа этого(где checkbox.png - атлас с 18x18 картинками для различных стейтов чекбокса и радиобатона):

input[type="checkbox"],
    input[type="radio"] {
        -ms-opacity: 0;
        opacity: 0;
        position: absolute;
        visibility: hidden;
    }

        input[type="checkbox"] + label,
        input[type="radio"] + label {
            position: relative;
        }

            input[type="checkbox"] + label:before,
            input[type="radio"] + label:before {
                background: url("/checkbox.png") no-repeat scroll 0 0 transparent;
                content: "";
                display: inline-block;
                height: 9px;
                margin-left: 2px;
                margin-right: 4px;
                width: 9px;
            }

            input[type="checkbox"] + label:hover,
            input[type="radio"] + label:hover {
                background: #fff1d7;
                color: #000;
            }

            input[type="checkbox"] + label:before {
                background-position: 0 0;
            }


        input[type="checkbox"] + label:active:before,
        input[type="checkbox"]:checked + label:active:before {
            background-position: -36px 0;
        }

        input[type="checkbox"]:checked + label:before {
            background-position: -18px 0;
        }

        input[type="radio"] + label:before {
            background-position: -75px 0;
        }

        input[type="radio"]:checked + label:before {
            background-position: -84px 0;
        }

        input[type="radio"] + label:active:before,
        input[type="radio"]:checked + label:active:before {
            background-position: -111px 0;
        }

        input[type="radio"]:checked + label:before {
            background-position: -84px 0;
        }

Это базовый пример(я не стал писать всякие стили при disable состояниях итд), на всех браузерах современных все работает шикарно, но не на IE8(а так уже вышло, что нужно было обеспечить поддержку IE8), дабы наши красивые чекбоксы работали в IE8 делаем несколько хаков:

1. CSS:


input[type="checkbox"] + label:before {
    content: "";
}

input[type="checkbox"][checked] + label:before {
    background-position: -18px 0;
    content: " ";
}

input[type="checkbox"][checked] + label:hover:before {
    background-position: -9px 0;
    content: " ";
}

input[type="checkbox"][checked] + label:hover:before {
    background-position: -45px 0;
    content: " ";
}

input[type="radio"] + label:before {
    background-position: -75px 0;
    content: "";
}

input[type="radio"][checked] + label:before {
    background-position: -84px 0;
    content: " ";
}

input[type="radio"][checked] + label:before {
    background-position: -84px 0;
    content: " ";
}

IE8 не умеет работать с постфиксом : checked, поэтому для него просто заменяем это дело на селектор аттрибута.

2. JS:

if (window.msie == 8) {
        $('body').on('click', 'label[for]', function () {
            var checkBox = $('input[type=checkbox]#' + $(this).attr('for'));
            if (checkBox.length > 0) {
                if (checkBox.is(':checked')) {
                    checkBox.removeAttr('checked');
                } else {
                    checkBox.attr('checked', 'checked');
                }
                checkBox.change();
            }
            var radio = $('input[type=radio]#' + $(this).attr('for'));
            if (radio.length > 0) {
                if (!radio.is(':checked')) {
                    radio.attr('checked', 'checked');
                }
                $('input[type=radio][name=' + radio.attr("name") + ']').not('#' + radio.attr('id')).each(function () {
                    $(this).removeAttr('checked');
                    $('label[for=' + $(this).attr('id') + ']').focus();
                });
                radio.change();
            }
            $('body').addClass('z').removeClass('z');
        });
    }

Тут все просто: сам IE8 перестает адекватно реагировать ан нажатия label(где наша картинка кастомная и расположена) и изменение связанного с ним чекбокса, если чекбокс скрыт, поэтому мы пишем всю логику за него. Но проставновки атрибута будет не достаочно, поэтому:
  • вызываем change(), чтобы в скриптах на странице можно ыбло хендлить события on('change',...)
  • форсируем перерендеринг всей страницы доабвляя несуществующий класс в боди и удаляя его: $('body').addClass('z').removeClass('z'); Если этого не сделать, то IE8 не перерисует на новую картинку измененые чекбоксы/радиобатонны, он просто игнорирует подобные изменения.

Вот собственно таким не большим костылем можно заставить свои красивые кастомные чекбоксы работать  на IE8 и забыть о том, что нужно поддерживать IE8 на некоторое время)

Комментариев нет:

Отправить комментарий