Можно ли установить флажки HTML только для чтения?


818

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

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


39
(Злонамеренный) клиент всегда может изменить значение флажка (или отправить произвольные запросы). Всегда проверяйте правильность проверки на стороне сервера!
Knittl

4
@knittl Но у нормального вистора нет (злого) клиента. И обычный Вистор не хотел менять информацию (в этом readonly
смысл

3
@knittl Вы, кажется, отклонить весь смысл readonly! Почему тогда этот атрибут будет существовать!
Ижар Аазми

10
@IzharAazmi: readonlyэто только атрибут на стороне клиента, который помогает браузеру правильно отображать сайт и затем формировать правильный запрос из него. Сервер не может и не должен знать об readonlyатрибуте отображаемой страницы. Он должен предполагать, что запрос поступил откуда угодно (и, возможно, со злонамеренными намерениями); никогда не полагайтесь на предоставленные пользователем данные. Тем не менее, зачем отправлять значение флажка, которое нельзя отредактировать в запросе (если вы установили значение перед рендерингом, вы уже знаете значение при
отправке

4
@ Knittl Я согласен! Но вы видите, что readonlyатрибут существует там по какой-то причине. Это, конечно, не имеет ничего общего с реализацией на стороне сервера. Но он должен сказать пользователю: «Эй! Здесь предполагается это значение, и / или вы не можете его изменить».
Ижар Аазми

Ответы:


539

Вы можете использовать это:

<input type="checkbox" onclick="return false;"/>

Это работает, потому что возврат false из события click останавливает продолжение цепочки выполнения.


29
Возвращение false в javascript предотвращает продолжение цепочки выполнения для обработчика щелчка или ключа. Не имеет никакого отношения к состоянию флажка
Джессика Браун

9
PS ... если вы хотите, чтобы флажок был в отмеченном состоянии, который вам нужно добавить checked="checked", не связывайтесь с javascript. Javascript просто для того, чтобы заставить игнорировать щелчки мыши на объекте ввода, а не устанавливать состояние флажка.
Джессика Браун

8
Нет визуальной индикации статуса R / O в этом случае.
Джесси Глик

11
Не позволяет использовать TAB для перехода к следующему вводу, хотя.
user327961

7
Сбой полностью, если JavaScript отключен!
Дойн

420

READONLYне работает на флажках , как это мешает вам редактирование поля в значении , но с помощью флажка вы на самом деле редактирование поля в состоянии (на || выкла)

От faqs.org :

Важно понимать, что READONLY просто запрещает пользователю изменять значение поля, а не взаимодействовать с ним. Например, в флажках вы можете включить или отключить их (таким образом, установив состояние CHECKED), но вы не меняете значение поля.

Если вы не хотите использовать, disabledно все еще хотите отправить значение, как насчет отправки значения в виде скрытого поля и простой печати его содержимого пользователю, когда они не соответствуют критериям редактирования? например

// user allowed change
if($user_allowed_edit)
{
    echo '<input type="checkbox" name="my_check"> Check value';
}
else
{
    // Not allowed change - submit value..
    echo '<input type="hidden" name="my_check" value="1" />';
    // .. and show user the value being submitted
    echo '<input type="checkbox" disabled readonly> Check value';
}

135
Работает, но это вроде ... хорошо грязно, только для чтения на флажках следует просто делать то, что говорит интуиция.
Левита

8
Интуиция обманывает нас, как объяснил ConroyP.
2010 года

120
Интуиция не обманывает США, она обманула тех, кто реализовал этот флажок.
Califf

@ConroyP -> «он запрещает вам редактировать значение поля, но с помощью флажка вы фактически редактируете состояние поля (вкл || выкл)». Это действительно слабое оправдание для решения с головой. «Состояние» и «ценность» для большинства из нас во многом совпадают с «toMAYto» и «toMAHto», как вы можете видеть из голосов, сделанных людьми, которые не согласны.
Маколи

343

Это флажок, который вы не можете изменить:

<input type="checkbox" disabled="disabled" checked="checked">

Просто добавьте disabled="disabled"в качестве атрибута.


Изменить, чтобы обратиться к комментариям:

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

<input name="myvalue" type="checkbox" disabled="disabled" checked="checked"/>
<input name="myvalue" type="hidden" value="true"/>

Таким образом, когда флажок установлен на «отключен», он служит только для визуального представления данных, а не на самом деле «связан» с данными. В обратной записи значение скрытого ввода отправляется, когда флажок снят.


331
Обратите внимание, что флажок «отключен» не отправляет значение через данные POST.
бифоб

66
@powtac Вы не можете указать, что он хочет, чтобы данные были опубликованы, ваш пример этого не делает.
Дэвид Мартенсон

70
Ни в коем случае этот ответ не должен иметь 105 голосов. Это идет вразрез со всем, что утверждает ОП.
JM4

15
@nathanhayfield: по этой логике я должен иметь возможность публиковать полезные ответы на любые темы и получать откаты. :(
Майкл Брей

24
@MichaelBray Я предполагаю, что это вызывает много голосов, потому что многие люди хотят знать, как сделать флажки доступными только для чтения, поэтому они делают это: 1) Google "Checkbox только для чтения". 2) Убедитесь, что заголовок этого вопроса соответствует тому, что они хотят сделать, и щелкните по нему. 3) Прокрутите вниз, пока они не найдут этот ответ. 4) Счастье и настроение.
Марк Байерс

63
<input type="checkbox" onclick="this.checked=!this.checked;">

Но вы абсолютно ДОЛЖНЫ проверить данные на сервере, чтобы убедиться, что они не были изменены.


4
Я нашел это, чтобы быть лучшим решением; Кроме того, я могу вызвать другой фрагмент кода (скажем, некоторый jquery-материал), чтобы отобразить симпатичный маленький знак, который говорит: «Вы не можете изменить это, пока не сделаете сначала x». Так что-то вроде: "... onclick = 'this.checked =! This.checked; javascript: theCheckboxWasClicked ();' ..."
Бейн

Это не затеняет коробки, как в ответе от Powtac, поэтому он получил мой голос
EHarpham

Это немного хакерский, но это гениальный, совершенный, почти элегантный маленький хак.
Рассел

Лучшее решение. Должен быть помечен как правильный ответ.
Скотти

3
Как указано выше, это не работает при двойном щелчке в IE. Я использовал: onchange = "this.checked = true;"
Ритикеш

57

другое «простое решение»:

<!-- field that holds the data -->
<input type="hidden" name="my_name" value="1" /> 
<!-- visual dummy for the user -->
<input type="checkbox" name="my_name_visual_dummy" value="1" checked="checked" disabled="disabled" />

disabled = "disabled" / disabled = true


1
Это решает все проблемы: создает флажок «только для чтения», отправляет данные POST и обеспечивает визуальную индикацию «только для чтения» (в отличие от всех решений javascript)
Далибор Фривальдский,

2
Вы также можете упасть nameи valueатрибуты из вашего манекена коробки, также ="checked"и ="diabled"ATTRIB-значения могут быть понижены. w3.org/TR/html-markup/input.checkbox.html
Сампо Саррала - codidact.org

Наиболее важно, что это решение представляет собой обычный старый HTML и не использует Javascript.
GlennG

45

Это представляет некоторую проблему юзабилити.

Если вы хотите отобразить флажок, но не позволить ему взаимодействовать, тогда зачем тогда даже флажок?

Однако мой подход заключается в том, чтобы использовать отключенный (пользователь ожидает, что отключенный флажок будет недоступен для редактирования, вместо использования JS, чтобы сделать включенный флажок неработающим), и добавьте обработчик отправки формы, используя javascript, который включает флажки прямо перед тем, как форма будет Отправлено. Таким образом, вы публикуете свои значения.

т.е. как то так:

var form = document.getElementById('yourform');
form.onSubmit = function () 
{ 
    var formElems = document.getElementsByTagName('INPUT');
    for (var i = 0; i , formElems.length; i++)
    {  
       if (formElems[i].type == 'checkbox')
       { 
          formElems[i].disabled = false;
       }
    }
}

22
Другой вариант заключается в том, чтобы отобразить отключенный флажок (или изображение или что-либо еще, чтобы обозначить отмеченный / не отмеченный) и иметь скрытый ввод, который обрабатывается сервером.
Хуан Мендес

5
Это не проблема удобства использования, когда вы получили форму, в которой часть вашего решения влияет на некоторые другие входные данные (иначе говоря: установка значения, к которому нельзя прикоснуться, если вы не отмените свое первое действие.). Я ненавижу, когда люди пытаются передумать, а не отвечать (это не про тебя @FlySwat, ты ответил).
Pherrymason

7
Цель состоит в том, чтобы использовать флажок в качестве поля отображения «this value is true», которое легче сканировать в таблице, чем набор «true» / «false» -s. Конечно, вы могли бы использовать значок, но в форме, кажется, флажки, готовые для использования.
Оли

1
Я обычно использую это решение, но .. иногда пользователи, особенно при медленном соединении, видят кнопки ввода, включенные после отправки формы, и решают поиграть с ней.
systempuntoout

2
Предположим, у вас есть ряд «функций», которые могут быть включены или нет, поэтому у вас есть шаблон, который показывает флажок на функцию. Но иногда функция является обязательным условием для чего-то другого ... поэтому она ДОЛЖНА быть включена, но вы не хотите менять свой шаблон. Это именно то, для чего установлен флажок Они были вокруг навсегда, поэтому я надеюсь, что вопрос «почему даже флажок» был риторическим.
Трийнко

38
<input type="checkbox" readonly="readonly" name="..." />

с помощью jquery:

$(':checkbox[readonly]').click(function(){
            return false;
        });

все еще может быть хорошей идеей дать некоторый визуальный намек (css, text, ...), что элемент управления не будет принимать входные данные.


Это не сработало в ie6 для меня, фильтр атрибутов только для чтения не работает правильно. Я взял это из фильтра и поместил проверку атрибута в тело функции, и она отлично работает в ie6.
gt124

3
Я использовал «data-readonly = true» вместо стандартного атрибута, и он отлично работает во всех браузерах. Мне нравится это решение больше, чем другие выше +1
peipst9lker

1
Селектор должен $(':checkbox[readonly]')выбирать все флажки-кандидаты, так как readonlyзначение атрибута необязательно.
Ижар Аазми

21

Я использовал это для достижения результатов:

<input type=checkbox onclick="return false;" onkeydown="return false;" />

В моем случае это работает без точки с запятой, иначе это не так.
Мвиза

12

Я случайно заметил решение, данное ниже. Нашел это мое исследование по той же проблеме. Не знаю, кто это опубликовал, но я не сделал это. Он использует jQuery:

$(document).ready(function() {
    $(":checkbox").bind("click", false);
});

Это сделало бы флажки только для чтения, что было бы полезно для показа данных только для чтения клиенту.


1
Вопрос требует чекбокса только для чтения, а не отключенного. Так что это самый правильный ответ.
NileshChauhan

9
onclick="javascript: return false;"

Хм ... это работает для ложного / непроверенного случая, но onclick="javascript: return true;"просто заставляет его действовать как обычный флажок. Советы? Спасибо!
Оли

@ Оли, добавь checkedатрибут и оставь falseна месте.
Qwertiy

7

Запоздалый ответ, но большинство ответов, кажется, слишком усложняют его.

Насколько я понимаю, ОП в основном хотел:

  1. Флажок только для чтения, чтобы показать статус.
  2. Значение возвращается с формой.

Необходимо отметить, что:

  1. ФП предпочел не использовать disabled атрибут, потому что они «хотят, чтобы отмеченные флажки были отправлены вместе с остальной частью формы».
  2. Не отмеченные флажки не отправляются вместе с формой, так как цитата из OP в 1. выше указывает, что они уже знали. По сути, значение флажка существует, только если оно отмечено.
  3. Отключенный флажок однозначно указывает на то, что он не может быть изменен по своему замыслу, поэтому пользователь вряд ли попытается изменить его.
  4. Значение флажка не ограничивается указанием его статуса, например yesили false, но может быть любым текстом.

Следовательно, поскольку readonlyатрибут не работает, лучшее решение, не требующее JavaScript, это:

  1. Отключенный флажок, без имени или значения.
  2. Если флажок должен отображаться как отмеченный, скрытое поле с именем и значением хранится на сервере.

Итак, для установленного флажка:

<input type="checkbox" checked="checked" disabled="disabled" />
<input type="hidden" name="fieldname" value="fieldvalue" />

Для непроверенного флажка:

<input type="checkbox" disabled="disabled" />

Основная проблема с отключенными входами, особенно флажками, заключается в их плохой контрастности, что может быть проблемой для некоторых людей с определенными нарушениями зрения. Может быть лучше указать значение простыми словами, такими как Status: noneили Status: implemented, но включая скрытый ввод выше, когда последний используется, такой как:

<p>Status: Implemented<input type="hidden" name="status" value="implemented" /></p>


7

Большинство текущих ответов имеют одну или несколько из следующих проблем:

  1. Проверьте только мышь, а не клавиатуру.
  2. Проверяйте только при загрузке страницы.
  3. Подцепите все популярные изменения или отправьте события, которые не всегда сработают, если их подключит что-то другое.
  4. Требуется скрытый ввод или другие специальные элементы / атрибуты, которые необходимо отменить, чтобы снова включить флажок с помощью JavaScript.

Следующее просто и не имеет ни одной из этих проблем.

$('input[type="checkbox"]').on('click keyup keypress keydown', function (event) {
    if($(this).is('[readonly]')) { return false; }
});

Если флажок доступен только для чтения, он не изменится. Если это не так, это будет. Он использует jquery, но вы, вероятно, уже используете это ...

Оно работает.



6

Если вы хотите, чтобы они были отправлены на сервер с формой, но не были интерактивными для пользователя, вы можете использовать pointer-events: noneв css ( работает во всех современных браузерах, кроме IE10 и Opera 12 ) и установить tab-index,  -1чтобы предотвратить изменение с клавиатуры. Также обратите внимание, что вы не можете использовать labelтег, так как нажатие на него все равно изменит состояние.

input[type="checkbox"][readonly] {
  pointer-events: none !important;
}

td {
  min-width: 5em;
  text-align: center;
}

td:last-child {
  text-align: left;
}
<table>
  <tr>
    <th>usual
    <th>readonly
    <th>disabled
  </tr><tr>
    <td><input type=checkbox />
    <td><input type=checkbox readonly tabindex=-1 />
    <td><input type=checkbox disabled />
    <td>works
  </tr><tr>
    <td><input type=checkbox checked />
    <td><input type=checkbox readonly checked tabindex=-1 />
    <td><input type=checkbox disabled checked />
    <td>also works
  </tr><tr>
    <td><label><input type=checkbox checked /></label>
    <td><label><input type=checkbox readonly checked tabindex=-1 /></label>
    <td><label><input type=checkbox disabled checked /></label>
    <td>broken - don't use label tag
  </tr>
</table>


Позвольте мне повторить ваше последнее предложение (я пропустил его и потратил впустую драгоценное время): ваша техника бесполезна, если есть <label> (в Firefox она работает отлично, на самом деле. Проблема в Chrome).
Никколо М.

@NiccoloM., Но если вы знаете, что это только для чтения, зачем оборачивать его в ярлык? Также вы можете поставить метку после нее и использовать forатрибут. В этом случае вы можете использовать input[type="checkbox"][readonly] + label { pointer-events: none !important; }.
Qwertiy

@KevinBui, вы удалили labelи добавили tabindex? Как настроить фокусировку на элементе без фокусировки, чтобы нажать на него пробел?
Qwertiy


5

Некоторые ответы здесь кажутся немного окольными, но вот небольшой взлом.

<form id="aform" name="aform" method="POST">
    <input name="chkBox_1" type="checkbox" checked value="1" disabled="disabled" />
    <input id="submitBttn" type="button" value="Submit" onClick='return submitPage();'>
</form>

тогда в jquery вы можете выбрать один из двух вариантов:

$(document).ready(function(){
    //first option, you don't need the disabled attribute, this will prevent
    //the user from changing the checkbox values
    $("input[name^='chkBox_1']").click(function(e){
        e.preventDefault();
    });

    //second option, keep the disabled attribute, and disable it upon submit
    $("#submitBttn").click(function(){
        $("input[name^='chkBox_1']").attr("disabled",false);
        $("#aform").submit();
    });

});

демо: http://jsfiddle.net/5WFYt/


3
И это не "карусель" ??
KoZm0kNoT

нет это довольно прямо .. это просто не лаконично
sksallaj

4

Опираясь на приведенные выше ответы, при использовании jQuery это может быть хорошим решением для всех входных данных:

<script>
    $(function () {
        $('.readonly input').attr('readonly', 'readonly');
        $('.readonly textarea').attr('readonly', 'readonly');
        $('.readonly input:checkbox').click(function(){return false;});
        $('.readonly input:checkbox').keydown(function () { return false; });
    });
</script>

Я использую это с Asp.Net MVC, чтобы установить некоторые элементы формы только для чтения. Вышеприведенное работает для текста и флажков, устанавливая любой родительский контейнер как .readonly, например, в следующих сценариях:

<div class="editor-field readonly">
    <input id="Date" name="Date" type="datetime" value="11/29/2012 4:01:06 PM" />
</div>
<fieldset class="flags-editor readonly">
     <input checked="checked" class="flags-editor" id="Flag1" name="Flags" type="checkbox" value="Flag1" />
</fieldset>


4

Я знаю, что «отключен» не является приемлемым ответом, так как ОП хочет его опубликовать. Однако вам всегда придется проверять значения на стороне сервера ДАЖЕ, если у вас установлена ​​опция только для чтения. Это потому, что вы не можете запретить злоумышленнику публиковать значения с помощью атрибута readonly.

Я предлагаю сохранить исходное значение (на стороне сервера) и отключить его. Затем, когда они отправляют форму, игнорируют любые опубликованные значения и принимают исходные значения, которые вы сохранили.

Это будет выглядеть и вести себя так, как будто это значение только для чтения. И он обрабатывает (игнорирует) сообщения от злоумышленников. Ты убиваешь 2 зайцев одним выстрелом.


3

Я бы прокомментировал ответ ConroyP, но это требует 50 репутации, которой у меня нет. У меня достаточно репутации, чтобы опубликовать другой ответ. Сожалею.

Проблема с ответом ConroyP заключается в том, что этот флажок становится неизменным, даже не включая его на странице. Хотя Electrons_Ahoy не оговаривает так много, лучшим ответом будет тот, в котором неизменяемый флажок будет выглядеть аналогично, если не совпадает с изменяемым флажком, как в случае, когда применяется атрибут «отключен». Решение, которое учитывает две причины, которые Electrons_Ahoy указывает на нежелание использовать атрибут «disabled», не будет обязательно будет недействительным, поскольку в нем используется атрибут «disabled».

Предположим, две логические переменные, $ checked и $ disabled:

if ($checked && $disabled)
    echo '<input type="hidden" name="my_name" value="1" />';
echo '<input type="checkbox" name="my_name" value="1" ',
    $checked ? 'checked="checked" ' : '',
    $disabled ? 'disabled="disabled" ' : '', '/>';

Флажок отображается как флажок, если $ флажок равен true. Флажок отображается как непроверенный, если $ флажок равен false. Пользователь может изменить состояние флажка, если и только если $ disabled имеет значение false. Параметр «my_name» не публикуется, когда флажок снят, пользователем или нет. Параметр «my_name = 1» публикуется, когда флажок установлен, пользователем или нет. Я верю, что это то, что искал Electrons_Ahoy.


3

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

Но вы можете сделать их только для чтения с JavaScript!

Добавьте этот код в любое время и в любом месте, чтобы сделать флажки доступными только для чтения, как предполагается, и запретите пользователю изменять его каким-либо образом.

jQuery(document).on('click', function(e){
      // check for type, avoid selecting the element for performance
      if(e.target.type == 'checkbox') {
          var el = jQuery(e.target);
          if(el.prop('readonly')) {
              // prevent it from changing state
              e.preventDefault();
          }
      }
});
input[type=checkbox][readonly] {
    cursor: not-allowed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label><input type="checkbox" checked readonly> I'm readonly!</label>

Вы можете добавить этот скрипт в любое время после загрузки jQuery.

Это будет работать для динамически добавленных элементов.

Он работает, собирая событие click (которое происходит до события change) для любого элемента на странице, затем проверяет, является ли этот элемент флажком «только для чтения», и, если это так, блокирует изменение.

Есть так много вариантов, чтобы не влиять на производительность страницы.




2

Если вы хотите, чтобы ВСЕ ваши флажки были «заблокированы», чтобы пользователь не мог изменить состояние «проверено», если присутствует атрибут «только для чтения», тогда вы можете использовать jQuery:

$(':checkbox').click(function () {
    if (typeof ($(this).attr('readonly')) != "undefined") {
        return false;
    }
});

Крутая вещь в этом коде состоит в том, что он позволяет вам изменять атрибут «только для чтения» по всему коду без необходимости повторной привязки каждого флажка.

Это работает и для радио кнопок.


1

Основная причина, по которой люди хотели бы установить флажок «только для чтения» и (также) радиогруппу «только для чтения», заключается в том, что информация, которую нельзя изменить, может быть представлена ​​пользователю в том виде, в котором она была введена.

OK disabled сделает это - к сожалению, отключенные элементы управления не ориентированы на клавиатуру и, следовательно, нарушают все законы о доступности. Это самое большое зависание в HTML, которое я знаю.


1

Содействовать очень, очень поздно ... но все равно. При загрузке страницы используйте jquery, чтобы отключить все флажки, кроме выбранного в данный момент. Затем установите текущий выбранный как только для чтения, чтобы он выглядел так же, как отключенные. Пользователь не может изменить значение, и выбранное значение по-прежнему отправляется.


1

Очень поздно для вечеринки, но я нашел ответ для MVC (5). Я отключил CheckBox и добавил флажок HiddenFor ДО, поэтому, когда он публикуется, сначала находит поле Hidden и использует это значение. Это работает.

 <div class="form-group">
     @Html.LabelFor(model => model.Carrier.Exists, new { @class = "control-label col-md-2" })
         <div class="col-md-10">
              @Html.HiddenFor(model => model.Carrier.Exists)
              @Html.CheckBoxFor(model => model.Carrier.Exists, new { @disabled = "disabled" })
              @Html.ValidationMessageFor(model => model.Carrier.Exists)
          </div>
 </div>

1

Я бы использовал атрибут readonly

<input type="checkbox" readonly>

Затем используйте CSS, чтобы отключить взаимодействие:

input[type='checkbox'][readonly]{
    pointer-events: none;
}

Обратите внимание, что использование псевдокласса: только для чтения здесь не работает.

input[type='checkbox']:read-only{ /*not working*/
    pointer-events: none;
}

0

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

READONLY сам по себе не сработает. Вы можете сделать что-нибудь интересное с CSS, но мы обычно просто отключаем их.

ВНИМАНИЕ: Если они отправлены обратно, клиент может изменить их, точка. Вы не можете полагаться только на чтение, чтобы пользователь не мог что-то изменить. Они всегда могут использовать fiddler или просто изменить html с firebug или что-то подобное.


Вы абсолютно правы, поэтому я также проверяю это на стороне сервера, устанавливая это просто для улучшения взаимодействия с клиентом.
levhita

0

Мое решение на самом деле противоположно решению FlySwat, но я не уверен, будет ли оно работать в вашей ситуации. У меня есть группа флажков, и у каждого есть обработчик onClick, который отправляет форму (они используются для изменения настроек фильтра для таблицы). Я не хочу разрешать множественные клики, поскольку последующие клики после первого игнорируются. Поэтому я отключаю все флажки после первого клика и после отправки формы:

onclick="document.forms['form1'].submit(); $('#filters input').each(function() {this.disabled = true});"

Чекбоксы находятся в элементе span с идентификатором «filters» - вторая часть кода представляет собой оператор jQuery, который перебирает чекбоксы и отключает каждый из них. Таким образом, значения флажков по-прежнему отправляются через форму (поскольку форма была отправлена ​​до их отключения), и это не позволяет пользователю изменять их до перезагрузки страницы.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.