Как бороться с различиями в браузерах с неопределенным флажком

Пример. Флажок HTML может быть установлен как indeterminate, что означает, что он не установлен и не установлен. Даже в этом неопределенном состоянии все еще существует базовое логическое состояние checked.

Флажки Mac OS X в разных состояниях


Когда нажимается неопределенный флажок, он теряет свое состояние indeterminate. В зависимости от браузера (Firefox) он может дополнительно переключать свойство checked.

Этот jsfiddle иллюстрирует ситуацию. В Firefox однократное нажатие на любой из флажков приводит к переключению их начального базового состояния checked. В IE свойство checked не используется для первого клика.

Я хотел бы, чтобы все браузеры вели себя одинаково, даже если это означает дополнительный javascript. К сожалению, для свойства indeterminate установлено значение false перед вызовом обработчика onclick (или onchange и jquery change), поэтому я не могу определить, вызывается ли он для щелчка по флажку indeterminate или нет.

События mouseup и keyup (для переключения пробела) показывают предыдущее состояние indeterminate, но я бы не хотел быть таким конкретным: оно кажется хрупким.

Я мог бы сохранить отдельное свойство для флажка (data-indeterminate или подобное), но я хотел знать, есть ли простое решение, которое мне не хватает, и/или есть ли у других людей подобные проблемы.


person aaaidan    schedule 11.04.2012    source источник
comment
Я думаю, что данные могут быть выходом.   -  person James Montagne    schedule 11.04.2012
comment
Safari для Windows также оставляет только checked для первого щелчка.   -  person Pow-Ian    schedule 05.04.2013
comment
это то, что вы ищете для флажка с тремя состояниями? Я спрашиваю, потому что неопределенное свойство является только визуальным свойством. Он предназначен для того, чтобы указать пользователю, что значение флажка может потребоваться изменить.   -  person Pow-Ian    schedule 05.04.2013
comment
Да, я думаю, что тройное состояние — это то, что мне нужно: мы использовали его, чтобы указать, что некоторые (но не все) дочерние элементы узла были выбраны. Я просто хотел, чтобы все браузеры вели себя одинаково при нажатии на такой узел.   -  person aaaidan    schedule 07.04.2013
comment
@aaaidan: прочитайте это, это может помочь вам css-tricks.com/indeterminate-checkboxes   -  person Luca Filosofi    schedule 08.04.2013


Ответы (4)


Если вы хотите установить неопределяемый флажок, который будет установлен во всех браузерах при нажатии (или, по крайней мере, в IE, Chrome и FF5+), вам необходимо правильно инициализировать атрибут checked, как показано здесь http://jsfiddle.net/K6nrT/6/. Я написал следующие функции, чтобы помочь вам:

/// Gives a checkbox the inderminate state and the right
/// checked state so that it becomes checked on click
/// on click on IE, Chrome and Firefox 5+
function makeIndeterminate(checkbox)
{
    checkbox.checked = getCheckedStateForIndeterminate();
    checkbox.indeterminate = true;
}

и интересная функция, основанная на обнаружении признаков:

/// Determine the checked state to give to a checkbox
/// with indeterminate state, so that it becomes checked
/// on click on IE, Chrome and Firefox 5+
function getCheckedStateForIndeterminate()
{
    // Create a unchecked checkbox with indeterminate state
    var test = document.createElement("input");
    test.type = "checkbox";
    test.checked = false;
    test.indeterminate = true;

    // Try to click the checkbox
    var body = document.body;
    body.appendChild(test); // Required to work on FF
    test.click();
    body.removeChild(test); // Required to work on FF

    // Check if the checkbox is now checked and cache the result
    if (test.checked)
    {
        getCheckedStateForIndeterminate = function () { return false; };
        return false;
    }
    else
    {
        getCheckedStateForIndeterminate = function () { return true; };
        return true;
    }
}

Никаких трюков с изображениями, никакого jQuery, никаких дополнительных атрибутов и никакой обработки событий. Это зависит только от простой инициализации JavaScript (обратите внимание, что атрибут «неопределенный» не может быть установлен в разметке HTML, поэтому инициализация JavaScript все равно потребовалась бы).

person Gyum Fox    schedule 18.10.2013
comment
Почему минус? Укажите сценарий, в котором это не работает, чтобы мы могли исправить его. - person Gyum Fox; 18.10.2013
comment
Кстати, я думаю, что ваш вопрос был правильно идентифицирован как дубликат. На самом деле я не принимал ответа до твоего, но, похоже, мы все еще боролись с той же проблемой. :) - person aaaidan; 20.10.2013
comment
Обратите внимание, что событие change не запускается в IE после того, как флажок покидает неопределенное состояние. jsfiddle.net/paska/K6nrT/20 - person Diego; 17.07.2015

Это решило мою проблему

$(".checkbox").click(function(){
    $(this).change();
});
person Bitan Biswas    schedule 23.04.2015
comment
Хотя этот ответ, вероятно, правильный и полезный, желательно, чтобы вы включили в него какое-то объяснение, объясняющее, как это помогает решить проблему. Это становится особенно полезным в будущем, если есть изменение (возможно, не связанное с этим), из-за которого оно перестает работать, и пользователям нужно понять, как оно когда-то работало. - person Kevin Brown; 23.04.2015
comment
когда флажок установлен щелчком мыши, одновременно происходят два события: одно для щелчка и одно для изменения. Теперь в случае неопределенного состояния у вас нет события клика. Так что в каком-то браузере, если вы нажмете неопределенный флажок, он переключится на проверку (например, chrome), но для IE он будет снят. Для сыча этот код может быть полезен $(".checkbox").click(function(e){ e.preventDefault(); $(this).change(); }); - person Bitan Biswas; 24.04.2015

Я не уверен, что использование функции для установки значения для неопределенных флажков будет хорошим решением, потому что:

  • вам придется менять каждое место, где вы их используете,
  • если пользователь отправляет форму, не нажимая флажки, значение, которое получит ваш сервер, будет отличаться в зависимости от браузера.

Но мне нравится умный способ определить, как работает браузер. Таким образом, вы можете проверить isCheckedAfterIndeterminate() вместо обычного window.navigator.userAgent.indexOf('Trident') >= 0, чтобы увидеть, что это IE (или, может быть, другой браузер, который работает необычным образом).

Итак, мое решение будет:

/// Determine the checked state to give to a checkbox
/// with indeterminate state, so that it becomes checked
/// on click on IE, Chrome and Firefox 5+
function isCheckedAfterIndeterminate()
{
    // Create a unchecked checkbox with indeterminate state
    var test = document.createElement("input");
    test.type = "checkbox";
    test.checked = false;
    test.indeterminate = true;

    // Try to click the checkbox
    var body = document.body;
    body.appendChild(test); // Required to work on FF
    test.click();
    body.removeChild(test); // Required to work on FF

    // Check if the checkbox is now checked and cache the result
    if (test.checked) {
        isCheckedAfterIndeterminate = function () { return false; };
        return false;
    } else {
        isCheckedAfterIndeterminate = function () { return true; };
        return true;
    }
}

// Fix indeterminate checkbox behavoiur for some browsers.
if ( isCheckedAfterIndeterminate() ) {
    $(function(){
        $(document).on('mousedown', 'input', function(){
            // Only fire the change event if the input is indeterminate.
            if ( this.indeterminate ) {
                this.indeterminate = false;
                $(this).trigger('change');
            }
        });
    });
}
person Артур Курицын    schedule 07.11.2016

Что ж, создайте свое собственное кликабельное изображение и используйте какой-нибудь java (скрипт), чтобы оно вело себя так. Я сомневаюсь, что многие пользователи поймут это состояние, поэтому будьте осторожны, где вы его используете.

person user613326    schedule 03.04.2013
comment
Спасибо за Ваш ответ! Вы должны получить от меня +50 репутации. - person Connor Gurney; 03.04.2013
comment
спасибо, хорошо, я рад, что наконец-то смог помочь кому-то здесь. - person user613326; 04.04.2013
comment
Рад, что это помогает Коннору, но у меня есть оговорки по поводу использования изображения вместо элемента формы, потому что в моем случае важна доступность. Это также означает, что вы не можете использовать флажок операционной системы, что может понравиться некоторым людям. - person aaaidan; 05.04.2013
comment
А, я понимаю, что вы говорите. Вы можете использовать флажок и что-то сделать с ним в jQuery/javascript, но я не могу сказать, что/как... :( - person Connor Gurney; 06.04.2013
comment
Да, я думаю, что это консенсус, Коннор: если вы хотите использовать встроенные элементы формы, чтобы заставить их вести себя одинаково в разных браузерах, единственным вариантом является сохранение какого-то свойства, не определяющего данные, с помощью javascript. Ваше здоровье! - person aaaidan; 07.04.2013
comment
Ага, @aaaidan, именно об этом я и подумал. ОП: Срок действия моей награды истекает в течение следующих 24 часов, так что вы получите от меня 50+ репутации! :) - person Connor Gurney; 07.04.2013
comment
мне просто интересно, что Эйден регистрирует проблему, а Коннор назначает награду за вопрос? - person user613326; 08.04.2013
comment
@ConnorGurney Поскольку ответ не был принят как лучший ответ, user613326 получит только половину, если только вы не присудите всю награду вручную! Просто и к вашему сведению. - person Jesse; 08.04.2013
comment
Я только что присудил полную награду OP! :) - person Connor Gurney; 08.04.2013
comment
Да, должен сказать, необычно, когда награда назначается за вопрос другим пользователем, верно? (Не жалуюсь!) - person aaaidan; 09.04.2013