CSS is pretty slim already and the `.ui.toggle.checkbox` sliders on admin page also still work. The only necessary JS is the one that links `input` and `label` so that it can be toggled via label. All checkboxes except the markdown ones render at `--checkbox-size: 16px` now. <img width="174" alt="Screenshot 2024-03-28 at 22 15 10" src="https://github.com/go-gitea/gitea/assets/115237/3455c1bb-166b-47e4-9847-2d20dd1f04db"> <img width="499" alt="Screenshot 2024-03-28 at 21 00 07" src="https://github.com/go-gitea/gitea/assets/115237/412be2b3-d5a0-478a-b17b-43e6bc12e8ce"> <img width="83" alt="Screenshot 2024-03-28 at 22 14 34" src="https://github.com/go-gitea/gitea/assets/115237/d8c89838-a420-4723-8c49-89405bb39474"> --------- Co-authored-by: delvh <dev.lh@web.de>tags/v1.22.0-rc1
<dt>{{ctx.Locale.Tr "admin.config.disable_gravatar"}}</dt> | <dt>{{ctx.Locale.Tr "admin.config.disable_gravatar"}}</dt> | ||||
<dd> | <dd> | ||||
<div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.disable_gravatar"}}"> | <div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.disable_gravatar"}}"> | ||||
<input type="checkbox" data-config-dyn-key="picture.disable_gravatar" {{if .SystemConfig.Picture.DisableGravatar.Value ctx}}checked{{end}}> | |||||
<input type="checkbox" data-config-dyn-key="picture.disable_gravatar" {{if .SystemConfig.Picture.DisableGravatar.Value ctx}}checked{{end}}><label></label> | |||||
</div> | </div> | ||||
</dd> | </dd> | ||||
<div class="divider"></div> | <div class="divider"></div> | ||||
<dt>{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}</dt> | <dt>{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}</dt> | ||||
<dd> | <dd> | ||||
<div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}"> | <div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}"> | ||||
<input type="checkbox" data-config-dyn-key="picture.enable_federated_avatar" {{if .SystemConfig.Picture.EnableFederatedAvatar.Value ctx}}checked{{end}}> | |||||
<input type="checkbox" data-config-dyn-key="picture.enable_federated_avatar" {{if .SystemConfig.Picture.EnableFederatedAvatar.Value ctx}}checked{{end}}><label></label> | |||||
</div> | </div> | ||||
</dd> | </dd> | ||||
</dl> | </dl> |
{{if and (not (eq .Issue.PullRequest.HeadRepo.FullName .Issue.PullRequest.BaseRepo.FullName)) .CanWriteToHeadRepo}} | {{if and (not (eq .Issue.PullRequest.HeadRepo.FullName .Issue.PullRequest.BaseRepo.FullName)) .CanWriteToHeadRepo}} | ||||
<div class="divider"></div> | <div class="divider"></div> | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<div class="ui checkbox" id="allow-edits-from-maintainers" | |||||
<div class="ui checkbox small-loading-icon" id="allow-edits-from-maintainers" | |||||
data-url="{{.Issue.Link}}" | data-url="{{.Issue.Link}}" | ||||
data-tooltip-content="{{ctx.Locale.Tr "repo.pulls.allow_edits_from_maintainers_desc"}}" | data-tooltip-content="{{ctx.Locale.Tr "repo.pulls.allow_edits_from_maintainers_desc"}}" | ||||
data-prompt-error="{{ctx.Locale.Tr "repo.pulls.allow_edits_from_maintainers_err"}}" | data-prompt-error="{{ctx.Locale.Tr "repo.pulls.allow_edits_from_maintainers_err"}}" |
--height-loading: 16rem; | --height-loading: 16rem; | ||||
--min-height-textarea: 132px; /* padding + 6 lines + border = calc(1.57142em + 6lh + 2px), but lh is not fully supported */ | --min-height-textarea: 132px; /* padding + 6 lines + border = calc(1.57142em + 6lh + 2px), but lh is not fully supported */ | ||||
--tab-size: 4; | --tab-size: 4; | ||||
--checkbox-size: 16px; /* height and width of checkbox and radio inputs */ | |||||
} | } | ||||
:root * { | :root * { |
.ui.form input[type="text"], | .ui.form input[type="text"], | ||||
.ui.form input[type="time"], | .ui.form input[type="time"], | ||||
.ui.form input[type="url"], | .ui.form input[type="url"], | ||||
.ui.selection.dropdown, | |||||
.ui.checkbox label::before, | |||||
.ui.checkbox input:checked ~ label::before, | |||||
.ui.checkbox input:not([type="radio"]):indeterminate ~ label::before { | |||||
.ui.selection.dropdown { | |||||
background: var(--color-input-background); | background: var(--color-input-background); | ||||
border-color: var(--color-input-border); | border-color: var(--color-input-border); | ||||
color: var(--color-input-text); | color: var(--color-input-text); | ||||
.ui.form input[type="text"]:hover, | .ui.form input[type="text"]:hover, | ||||
.ui.form input[type="time"]:hover, | .ui.form input[type="time"]:hover, | ||||
.ui.form input[type="url"]:hover, | .ui.form input[type="url"]:hover, | ||||
.ui.selection.dropdown:hover, | |||||
.ui.checkbox label:hover::before, | |||||
.ui.checkbox label:active::before, | |||||
.ui.radio.checkbox label::after, | |||||
.ui.radio.checkbox input:focus ~ label::before, | |||||
.ui.radio.checkbox input:checked ~ label::before { | |||||
.ui.selection.dropdown:hover { | |||||
background: var(--color-input-background); | background: var(--color-input-background); | ||||
border-color: var(--color-input-border-hover); | border-color: var(--color-input-border-hover); | ||||
color: var(--color-input-text); | color: var(--color-input-text); | ||||
.ui.form input[type="text"]:focus, | .ui.form input[type="text"]:focus, | ||||
.ui.form input[type="time"]:focus, | .ui.form input[type="time"]:focus, | ||||
.ui.form input[type="url"]:focus, | .ui.form input[type="url"]:focus, | ||||
.ui.selection.dropdown:focus, | |||||
.ui.checkbox input:focus ~ label::before, | |||||
.ui.checkbox input:not([type="radio"]):indeterminate:focus ~ label::before, | |||||
.ui.checkbox input:checked:focus ~ label::before, | |||||
.ui.radio.checkbox input:focus:checked ~ label::before { | |||||
.ui.selection.dropdown:focus { | |||||
background: var(--color-input-background); | background: var(--color-input-background); | ||||
border-color: var(--color-primary); | border-color: var(--color-primary); | ||||
color: var(--color-input-text); | color: var(--color-input-text); | ||||
.ui.form .inline.fields .field > label, | .ui.form .inline.fields .field > label, | ||||
.ui.form .inline.fields .field > p, | .ui.form .inline.fields .field > p, | ||||
.ui.form .inline.field > label, | .ui.form .inline.field > label, | ||||
.ui.form .inline.field > p, | |||||
.ui.checkbox label, | |||||
.ui.checkbox + label, | |||||
.ui.checkbox label:hover, | |||||
.ui.checkbox + label:hover, | |||||
.ui.checkbox input:focus ~ label, | |||||
.ui.checkbox input:active ~ label { | |||||
.ui.form .inline.field > p { | |||||
color: var(--color-text); | color: var(--color-text); | ||||
} | } | ||||
.ui.form .required.fields:not(.grouped) > .field > label::after, | .ui.form .required.fields:not(.grouped) > .field > label::after, | ||||
.ui.form .required.fields.grouped > label::after, | .ui.form .required.fields.grouped > label::after, | ||||
.ui.form .required.field > label::after, | .ui.form .required.field > label::after, | ||||
.ui.form .required.fields:not(.grouped) > .field > .checkbox::after, | |||||
.ui.form .required.field > .checkbox::after, | |||||
.ui.form label.required::after { | .ui.form label.required::after { | ||||
color: var(--color-red); | color: var(--color-red); | ||||
} | } | ||||
.ui.input, | |||||
.ui.checkbox input:focus ~ label::after, | |||||
.ui.checkbox input:checked ~ label::after, | |||||
.ui.checkbox label:active::after, | |||||
.ui.checkbox input:not([type="radio"]):indeterminate ~ label::after, | |||||
.ui.checkbox input:not([type="radio"]):indeterminate:focus ~ label::after, | |||||
.ui.checkbox input:checked:focus ~ label::after, | |||||
.ui.disabled.checkbox label, | |||||
.ui.checkbox input[disabled] ~ label { | |||||
.ui.input { | |||||
color: var(--color-input-text); | color: var(--color-input-text); | ||||
} | } | ||||
.ui.radio.checkbox input:focus ~ label::after, | |||||
.ui.radio.checkbox input:checked ~ label::after, | |||||
.ui.radio.checkbox input:focus:checked ~ label::after { | |||||
background: var(--color-input-text); | |||||
} | |||||
.ui.toggle.checkbox label::before { | |||||
background: var(--color-input-toggle-background); | |||||
} | |||||
.ui.toggle.checkbox label, | |||||
.ui.toggle.checkbox input:checked ~ label, | |||||
.ui.toggle.checkbox input:focus:checked ~ label { | |||||
color: var(--color-text) !important; | |||||
} | |||||
.ui.toggle.checkbox input:checked ~ label::before, | |||||
.ui.toggle.checkbox input:focus:checked ~ label::before { | |||||
background: var(--color-primary) !important; | |||||
} | |||||
/* match <select> padding to <input> */ | /* match <select> padding to <input> */ | ||||
.ui.form select { | .ui.form select { | ||||
padding: 0.67857143em 1em; | padding: 0.67857143em 1em; |
@import "./modules/message.css"; | @import "./modules/message.css"; | ||||
@import "./modules/table.css"; | @import "./modules/table.css"; | ||||
@import "./modules/card.css"; | @import "./modules/card.css"; | ||||
@import "./modules/checkbox.css"; | |||||
@import "./modules/modal.css"; | @import "./modules/modal.css"; | ||||
@import "./modules/select.css"; | @import "./modules/select.css"; |
.is-loading { | .is-loading { | ||||
pointer-events: none !important; | pointer-events: none !important; | ||||
position: relative !important; | position: relative !important; | ||||
overflow: hidden !important; | |||||
} | } | ||||
.is-loading > * { | .is-loading > * { |
/* based on Fomantic UI checkbox module, with just the parts extracted that we use. If you find any | |||||
unused rules here after refactoring, please remove them. */ | |||||
input[type="checkbox"], | |||||
input[type="radio"] { | |||||
width: var(--checkbox-size); | |||||
height: var(--checkbox-size); | |||||
} | |||||
.ui.checkbox { | |||||
position: relative; | |||||
display: inline-block; | |||||
vertical-align: baseline; | |||||
min-height: var(--checkbox-size); | |||||
line-height: var(--checkbox-size); | |||||
min-width: var(--checkbox-size); | |||||
padding: 1px; | |||||
} | |||||
.ui.checkbox input[type="checkbox"], | |||||
.ui.checkbox input[type="radio"] { | |||||
position: absolute; | |||||
top: 0; | |||||
left: 0; | |||||
width: var(--checkbox-size); | |||||
height: var(--checkbox-size); | |||||
} | |||||
.ui.checkbox input[type="checkbox"]:enabled, | |||||
.ui.checkbox input[type="radio"]:enabled, | |||||
.ui.checkbox label:enabled { | |||||
cursor: pointer; | |||||
} | |||||
.ui.checkbox label { | |||||
cursor: auto; | |||||
position: relative; | |||||
display: block; | |||||
user-select: none; | |||||
} | |||||
.ui.checkbox label, | |||||
.ui.radio.checkbox label { | |||||
padding-left: 1.85714em; | |||||
} | |||||
.ui.checkbox + label { | |||||
vertical-align: middle; | |||||
} | |||||
.ui.disabled.checkbox label, | |||||
.ui.checkbox input[disabled] ~ label { | |||||
cursor: default !important; | |||||
opacity: 0.5; | |||||
pointer-events: none; | |||||
} | |||||
.ui.radio.checkbox { | |||||
min-height: var(--checkbox-size); | |||||
} | |||||
/* "switch" styled checkbox */ | |||||
.ui.toggle.checkbox { | |||||
min-height: 1.5rem; | |||||
} | |||||
.ui.toggle.checkbox input { | |||||
width: 3.5rem; | |||||
height: 1.5rem; | |||||
opacity: 0; | |||||
z-index: 3; | |||||
} | |||||
.ui.toggle.checkbox label { | |||||
min-height: 1.5rem; | |||||
padding-left: 4.5rem; | |||||
padding-top: 0.15em; | |||||
} | |||||
.ui.toggle.checkbox label::before { | |||||
display: block; | |||||
position: absolute; | |||||
content: ""; | |||||
z-index: 1; | |||||
top: 0; | |||||
width: 3.5rem; | |||||
height: 1.5rem; | |||||
border-radius: 500rem; | |||||
left: 0; | |||||
} | |||||
.ui.toggle.checkbox label::after { | |||||
background: var(--color-white); | |||||
position: absolute; | |||||
content: ""; | |||||
opacity: 1; | |||||
z-index: 2; | |||||
width: 1.5rem; | |||||
height: 1.5rem; | |||||
top: 0; | |||||
left: 0; | |||||
border-radius: 500rem; | |||||
transition: background 0.3s ease, left 0.3s ease; | |||||
} | |||||
.ui.toggle.checkbox input ~ label::after { | |||||
left: -0.05rem; | |||||
} | |||||
.ui.toggle.checkbox input:checked ~ label::after { | |||||
left: 2.15rem; | |||||
} | |||||
.ui.toggle.checkbox input:focus ~ label::before, | |||||
.ui.toggle.checkbox label::before { | |||||
background: var(--color-input-toggle-background); | |||||
} | |||||
.ui.toggle.checkbox label, | |||||
.ui.toggle.checkbox input:checked ~ label, | |||||
.ui.toggle.checkbox input:focus:checked ~ label { | |||||
color: var(--color-text) !important; | |||||
} | |||||
.ui.toggle.checkbox input:checked ~ label::before, | |||||
.ui.toggle.checkbox input:focus:checked ~ label::before { | |||||
background: var(--color-primary) !important; | |||||
} |
text-align: center; | text-align: center; | ||||
} | } | ||||
.organization.options input { | |||||
min-width: 300px; | |||||
} | |||||
.page-content.organization .org-avatar { | .page-content.organization .org-avatar { | ||||
margin-right: 15px; | margin-right: 15px; | ||||
} | } |
.issue-list-toolbar-left { | .issue-list-toolbar-left { | ||||
display: flex; | display: flex; | ||||
align-items: center; | |||||
} | } | ||||
.issue-list-toolbar-right .filter.menu { | .issue-list-toolbar-right .filter.menu { |
Theme Overrides | Theme Overrides | ||||
*******************************/ | *******************************/ | ||||
/******************************* | |||||
Site Overrides | |||||
*******************************/ | |||||
/*! | |||||
* # Fomantic-UI - Checkbox | |||||
* http://github.com/fomantic/Fomantic-UI/ | |||||
* | |||||
* | |||||
* Released under the MIT license | |||||
* http://opensource.org/licenses/MIT | |||||
* | |||||
*/ | |||||
/******************************* | |||||
Checkbox | |||||
*******************************/ | |||||
/*-------------- | |||||
Content | |||||
---------------*/ | |||||
.ui.checkbox { | |||||
position: relative; | |||||
display: inline-block; | |||||
backface-visibility: hidden; | |||||
outline: none; | |||||
vertical-align: baseline; | |||||
font-style: normal; | |||||
min-height: 17px; | |||||
font-size: 1em; | |||||
line-height: 17px; | |||||
min-width: 17px; | |||||
} | |||||
/* HTML Checkbox */ | |||||
.ui.checkbox input[type="checkbox"], | |||||
.ui.checkbox input[type="radio"] { | |||||
cursor: pointer; | |||||
position: absolute; | |||||
top: 0; | |||||
left: 0; | |||||
opacity: 0 !important; | |||||
outline: none; | |||||
z-index: 3; | |||||
width: 17px; | |||||
height: 17px; | |||||
} | |||||
.ui.checkbox label { | |||||
cursor: auto; | |||||
position: relative; | |||||
display: block; | |||||
padding-left: 1.85714em; | |||||
outline: none; | |||||
font-size: 1em; | |||||
} | |||||
.ui.checkbox label:before { | |||||
position: absolute; | |||||
top: 0; | |||||
left: 0; | |||||
width: 17px; | |||||
height: 17px; | |||||
content: ''; | |||||
background: #FFFFFF; | |||||
border-radius: 0.21428571rem; | |||||
transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease; | |||||
border: 1px solid #D4D4D5; | |||||
} | |||||
/*-------------- | |||||
Checkmark | |||||
---------------*/ | |||||
.ui.checkbox label:after { | |||||
position: absolute; | |||||
font-size: 14px; | |||||
top: 0; | |||||
left: 0; | |||||
width: 17px; | |||||
height: 17px; | |||||
text-align: center; | |||||
opacity: 0; | |||||
color: rgba(0, 0, 0, 0.87); | |||||
transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease; | |||||
} | |||||
/*-------------- | |||||
Label | |||||
---------------*/ | |||||
/* Inside */ | |||||
.ui.checkbox label, | |||||
.ui.checkbox + label { | |||||
color: rgba(0, 0, 0, 0.87); | |||||
transition: color 0.1s ease; | |||||
} | |||||
/* Outside */ | |||||
.ui.checkbox + label { | |||||
vertical-align: middle; | |||||
} | |||||
/******************************* | |||||
States | |||||
*******************************/ | |||||
/*-------------- | |||||
Hover | |||||
---------------*/ | |||||
.ui.checkbox label:hover::before { | |||||
background: #FFFFFF; | |||||
border-color: rgba(34, 36, 38, 0.35); | |||||
} | |||||
.ui.checkbox label:hover, | |||||
.ui.checkbox + label:hover { | |||||
color: rgba(0, 0, 0, 0.8); | |||||
} | |||||
/*-------------- | |||||
Down | |||||
---------------*/ | |||||
.ui.checkbox label:active::before { | |||||
background: #F9FAFB; | |||||
border-color: rgba(34, 36, 38, 0.35); | |||||
} | |||||
.ui.checkbox label:active::after { | |||||
color: rgba(0, 0, 0, 0.95); | |||||
} | |||||
.ui.checkbox input:active ~ label { | |||||
color: rgba(0, 0, 0, 0.95); | |||||
} | |||||
/*-------------- | |||||
Focus | |||||
---------------*/ | |||||
.ui.checkbox input:focus ~ label:before { | |||||
background: #FFFFFF; | |||||
border-color: #96C8DA; | |||||
} | |||||
.ui.checkbox input:focus ~ label:after { | |||||
color: rgba(0, 0, 0, 0.95); | |||||
} | |||||
.ui.checkbox input:focus ~ label { | |||||
color: rgba(0, 0, 0, 0.95); | |||||
} | |||||
/*-------------- | |||||
Active | |||||
---------------*/ | |||||
.ui.checkbox input:checked ~ label:before { | |||||
background: #FFFFFF; | |||||
border-color: rgba(34, 36, 38, 0.35); | |||||
} | |||||
.ui.checkbox input:checked ~ label:after { | |||||
opacity: 1; | |||||
color: rgba(0, 0, 0, 0.95); | |||||
} | |||||
/*-------------- | |||||
Indeterminate | |||||
---------------*/ | |||||
.ui.checkbox input:not([type=radio]):indeterminate ~ label:before { | |||||
background: #FFFFFF; | |||||
border-color: rgba(34, 36, 38, 0.35); | |||||
} | |||||
.ui.checkbox input:not([type=radio]):indeterminate ~ label:after { | |||||
opacity: 1; | |||||
color: rgba(0, 0, 0, 0.95); | |||||
} | |||||
.ui.indeterminate.toggle.checkbox input:not([type=radio]):indeterminate ~ label:before { | |||||
background: rgba(0, 0, 0, 0.15); | |||||
} | |||||
.ui.indeterminate.toggle.checkbox input:not([type=radio]) ~ label:after { | |||||
left: 1.075rem; | |||||
} | |||||
/*-------------- | |||||
Active Focus | |||||
---------------*/ | |||||
.ui.checkbox input:not([type=radio]):indeterminate:focus ~ label:before, | |||||
.ui.checkbox input:checked:focus ~ label:before { | |||||
background: #FFFFFF; | |||||
border-color: #96C8DA; | |||||
} | |||||
.ui.checkbox input:not([type=radio]):indeterminate:focus ~ label:after, | |||||
.ui.checkbox input:checked:focus ~ label:after { | |||||
color: rgba(0, 0, 0, 0.95); | |||||
} | |||||
/*-------------- | |||||
Read-Only | |||||
---------------*/ | |||||
.ui.read-only.checkbox, | |||||
.ui.read-only.checkbox label { | |||||
cursor: default; | |||||
} | |||||
/*-------------- | |||||
Disabled | |||||
---------------*/ | |||||
.ui.disabled.checkbox label, | |||||
.ui.checkbox input[disabled] ~ label { | |||||
cursor: default !important; | |||||
opacity: 0.5; | |||||
color: #000000; | |||||
pointer-events: none; | |||||
} | |||||
/*-------------- | |||||
Hidden | |||||
---------------*/ | |||||
/* Initialized checkbox moves input below element | |||||
to prevent manually triggering */ | |||||
.ui.checkbox input.hidden { | |||||
z-index: -1; | |||||
} | |||||
/* Selectable Label */ | |||||
.ui.checkbox input.hidden + label { | |||||
cursor: pointer; | |||||
-webkit-user-select: none; | |||||
-moz-user-select: none; | |||||
user-select: none; | |||||
} | |||||
/******************************* | |||||
Types | |||||
*******************************/ | |||||
/*-------------- | |||||
Radio | |||||
---------------*/ | |||||
.ui.radio.checkbox { | |||||
min-height: 15px; | |||||
} | |||||
.ui.radio.checkbox label { | |||||
padding-left: 1.85714em; | |||||
} | |||||
/* Box */ | |||||
.ui.radio.checkbox label:before { | |||||
content: ''; | |||||
transform: none; | |||||
width: 15px; | |||||
height: 15px; | |||||
border-radius: 500rem; | |||||
top: 1px; | |||||
left: 0; | |||||
} | |||||
/* Bullet */ | |||||
.ui.radio.checkbox label:after { | |||||
border: none; | |||||
content: '' !important; | |||||
line-height: 15px; | |||||
top: 1px; | |||||
left: 0; | |||||
width: 15px; | |||||
height: 15px; | |||||
border-radius: 500rem; | |||||
transform: scale(0.46666667); | |||||
background-color: rgba(0, 0, 0, 0.87); | |||||
} | |||||
/* Focus */ | |||||
.ui.radio.checkbox input:focus ~ label:before { | |||||
background-color: #FFFFFF; | |||||
} | |||||
.ui.radio.checkbox input:focus ~ label:after { | |||||
background-color: rgba(0, 0, 0, 0.95); | |||||
} | |||||
/* Indeterminate */ | |||||
.ui.radio.checkbox input:indeterminate ~ label:after { | |||||
opacity: 0; | |||||
} | |||||
/* Active */ | |||||
.ui.radio.checkbox input:checked ~ label:before { | |||||
background-color: #FFFFFF; | |||||
} | |||||
.ui.radio.checkbox input:checked ~ label:after { | |||||
background-color: rgba(0, 0, 0, 0.95); | |||||
} | |||||
/* Active Focus */ | |||||
.ui.radio.checkbox input:focus:checked ~ label:before { | |||||
background-color: #FFFFFF; | |||||
} | |||||
.ui.radio.checkbox input:focus:checked ~ label:after { | |||||
background-color: rgba(0, 0, 0, 0.95); | |||||
} | |||||
/*-------------- | |||||
Slider | |||||
---------------*/ | |||||
.ui.slider.checkbox { | |||||
min-height: 1.25rem; | |||||
} | |||||
/* Input */ | |||||
.ui.slider.checkbox input { | |||||
width: 3.5rem; | |||||
height: 1.25rem; | |||||
} | |||||
/* Label */ | |||||
.ui.slider.checkbox label { | |||||
padding-left: 4.5rem; | |||||
line-height: 1rem; | |||||
color: rgba(0, 0, 0, 0.4); | |||||
} | |||||
/* Line */ | |||||
.ui.slider.checkbox label:before { | |||||
display: block; | |||||
position: absolute; | |||||
content: ''; | |||||
transform: none; | |||||
border: none !important; | |||||
left: 0; | |||||
z-index: 1; | |||||
top: 0.4rem; | |||||
background-color: rgba(0, 0, 0, 0.05); | |||||
width: 3.5rem; | |||||
height: 0.21428571rem; | |||||
border-radius: 500rem; | |||||
transition: background 0.3s ease; | |||||
} | |||||
/* Handle */ | |||||
.ui.slider.checkbox label:after { | |||||
background: #FFFFFF linear-gradient(transparent, rgba(0, 0, 0, 0.05)); | |||||
position: absolute; | |||||
content: '' !important; | |||||
opacity: 1; | |||||
z-index: 2; | |||||
border: none; | |||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset; | |||||
width: 1.5rem; | |||||
height: 1.5rem; | |||||
top: -0.25rem; | |||||
left: 0; | |||||
transform: none; | |||||
border-radius: 500rem; | |||||
transition: left 0.3s ease; | |||||
} | |||||
/* Focus */ | |||||
.ui.slider.checkbox input:focus ~ label:before { | |||||
background-color: rgba(0, 0, 0, 0.15); | |||||
border: none; | |||||
} | |||||
/* Hover */ | |||||
.ui.slider.checkbox label:hover { | |||||
color: rgba(0, 0, 0, 0.8); | |||||
} | |||||
.ui.slider.checkbox label:hover::before { | |||||
background: rgba(0, 0, 0, 0.15); | |||||
} | |||||
/* Active */ | |||||
.ui.slider.checkbox input:checked ~ label { | |||||
color: rgba(0, 0, 0, 0.95) !important; | |||||
} | |||||
.ui.slider.checkbox input:checked ~ label:before { | |||||
background-color: #545454 !important; | |||||
} | |||||
.ui.slider.checkbox input:checked ~ label:after { | |||||
left: 2rem; | |||||
} | |||||
/* Active Focus */ | |||||
.ui.slider.checkbox input:focus:checked ~ label { | |||||
color: rgba(0, 0, 0, 0.95) !important; | |||||
} | |||||
.ui.slider.checkbox input:focus:checked ~ label:before { | |||||
background-color: #000000 !important; | |||||
} | |||||
/*-------------- | |||||
Toggle | |||||
---------------*/ | |||||
.ui.toggle.checkbox { | |||||
min-height: 1.5rem; | |||||
} | |||||
/* Input */ | |||||
.ui.toggle.checkbox input { | |||||
width: 3.5rem; | |||||
height: 1.5rem; | |||||
} | |||||
/* Label */ | |||||
.ui.toggle.checkbox label { | |||||
min-height: 1.5rem; | |||||
padding-left: 4.5rem; | |||||
color: rgba(0, 0, 0, 0.87); | |||||
} | |||||
.ui.toggle.checkbox label { | |||||
padding-top: 0.15em; | |||||
} | |||||
/* Switch */ | |||||
.ui.toggle.checkbox label:before { | |||||
display: block; | |||||
position: absolute; | |||||
content: ''; | |||||
z-index: 1; | |||||
transform: none; | |||||
border: none; | |||||
top: 0; | |||||
background: rgba(0, 0, 0, 0.05); | |||||
box-shadow: none; | |||||
width: 3.5rem; | |||||
height: 1.5rem; | |||||
border-radius: 500rem; | |||||
} | |||||
/* Handle */ | |||||
.ui.toggle.checkbox label:after { | |||||
background: #FFFFFF linear-gradient(transparent, rgba(0, 0, 0, 0.05)); | |||||
position: absolute; | |||||
content: '' !important; | |||||
opacity: 1; | |||||
z-index: 2; | |||||
border: none; | |||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset; | |||||
width: 1.5rem; | |||||
height: 1.5rem; | |||||
top: 0; | |||||
left: 0; | |||||
border-radius: 500rem; | |||||
transition: background 0.3s ease, left 0.3s ease; | |||||
} | |||||
.ui.toggle.checkbox input ~ label:after { | |||||
left: -0.05rem; | |||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset; | |||||
} | |||||
/* Focus */ | |||||
.ui.toggle.checkbox input:focus ~ label:before { | |||||
background-color: rgba(0, 0, 0, 0.15); | |||||
border: none; | |||||
} | |||||
/* Hover */ | |||||
.ui.toggle.checkbox label:hover::before { | |||||
background-color: rgba(0, 0, 0, 0.15); | |||||
border: none; | |||||
} | |||||
/* Active */ | |||||
.ui.toggle.checkbox input:checked ~ label { | |||||
color: rgba(0, 0, 0, 0.95) !important; | |||||
} | |||||
.ui.toggle.checkbox input:checked ~ label:before { | |||||
background-color: #2185D0 !important; | |||||
} | |||||
.ui.toggle.checkbox input:checked ~ label:after { | |||||
left: 2.15rem; | |||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset; | |||||
} | |||||
/* Active Focus */ | |||||
.ui.toggle.checkbox input:focus:checked ~ label { | |||||
color: rgba(0, 0, 0, 0.95) !important; | |||||
} | |||||
.ui.toggle.checkbox input:focus:checked ~ label:before { | |||||
background-color: #0d71bb !important; | |||||
} | |||||
/******************************* | |||||
Variations | |||||
*******************************/ | |||||
/*-------------- | |||||
Fitted | |||||
---------------*/ | |||||
.ui.fitted.checkbox label { | |||||
padding-left: 0 !important; | |||||
} | |||||
.ui.fitted.toggle.checkbox { | |||||
width: 3.5rem; | |||||
} | |||||
.ui.fitted.slider.checkbox { | |||||
width: 3.5rem; | |||||
} | |||||
/*-------------------- | |||||
Size | |||||
---------------------*/ | |||||
.ui.mini.checkbox { | |||||
font-size: 0.78571429em; | |||||
} | |||||
.ui.tiny.checkbox { | |||||
font-size: 0.85714286em; | |||||
} | |||||
.ui.small.checkbox { | |||||
font-size: 0.92857143em; | |||||
} | |||||
.ui.large.checkbox { | |||||
font-size: 1.14285714em; | |||||
} | |||||
.ui.large.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after, | |||||
.ui.large.checkbox:not(.slider):not(.toggle):not(.radio) label:after, | |||||
.ui.large.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before, | |||||
.ui.large.checkbox:not(.slider):not(.toggle):not(.radio) label:before { | |||||
transform: scale(1.14285714); | |||||
transform-origin: left; | |||||
} | |||||
.ui.large.form .checkbox.radio label:before, | |||||
.ui.large.checkbox.radio label:before { | |||||
transform: scale(1.14285714); | |||||
transform-origin: left; | |||||
} | |||||
.ui.large.form .checkbox.radio label:after, | |||||
.ui.large.checkbox.radio label:after { | |||||
transform: scale(0.57142857); | |||||
transform-origin: left; | |||||
left: 0.33571429em; | |||||
} | |||||
.ui.big.checkbox { | |||||
font-size: 1.28571429em; | |||||
} | |||||
.ui.big.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after, | |||||
.ui.big.checkbox:not(.slider):not(.toggle):not(.radio) label:after, | |||||
.ui.big.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before, | |||||
.ui.big.checkbox:not(.slider):not(.toggle):not(.radio) label:before { | |||||
transform: scale(1.28571429); | |||||
transform-origin: left; | |||||
} | |||||
.ui.big.form .checkbox.radio label:before, | |||||
.ui.big.checkbox.radio label:before { | |||||
transform: scale(1.28571429); | |||||
transform-origin: left; | |||||
} | |||||
.ui.big.form .checkbox.radio label:after, | |||||
.ui.big.checkbox.radio label:after { | |||||
transform: scale(0.64285714); | |||||
transform-origin: left; | |||||
left: 0.37142857em; | |||||
} | |||||
.ui.huge.checkbox { | |||||
font-size: 1.42857143em; | |||||
} | |||||
.ui.huge.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after, | |||||
.ui.huge.checkbox:not(.slider):not(.toggle):not(.radio) label:after, | |||||
.ui.huge.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before, | |||||
.ui.huge.checkbox:not(.slider):not(.toggle):not(.radio) label:before { | |||||
transform: scale(1.42857143); | |||||
transform-origin: left; | |||||
} | |||||
.ui.huge.form .checkbox.radio label:before, | |||||
.ui.huge.checkbox.radio label:before { | |||||
transform: scale(1.42857143); | |||||
transform-origin: left; | |||||
} | |||||
.ui.huge.form .checkbox.radio label:after, | |||||
.ui.huge.checkbox.radio label:after { | |||||
transform: scale(0.71428571); | |||||
transform-origin: left; | |||||
left: 0.40714286em; | |||||
} | |||||
.ui.massive.checkbox { | |||||
font-size: 1.71428571em; | |||||
} | |||||
.ui.massive.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after, | |||||
.ui.massive.checkbox:not(.slider):not(.toggle):not(.radio) label:after, | |||||
.ui.massive.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before, | |||||
.ui.massive.checkbox:not(.slider):not(.toggle):not(.radio) label:before { | |||||
transform: scale(1.71428571); | |||||
transform-origin: left; | |||||
} | |||||
.ui.massive.form .checkbox.radio label:before, | |||||
.ui.massive.checkbox.radio label:before { | |||||
transform: scale(1.71428571); | |||||
transform-origin: left; | |||||
} | |||||
.ui.massive.form .checkbox.radio label:after, | |||||
.ui.massive.checkbox.radio label:after { | |||||
transform: scale(0.85714286); | |||||
transform-origin: left; | |||||
left: 0.47857143em; | |||||
} | |||||
/******************************* | |||||
Theme Overrides | |||||
*******************************/ | |||||
@font-face { | |||||
font-family: 'Checkbox'; | |||||
src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBD8AAAC8AAAAYGNtYXAYVtCJAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5Zn4huwUAAAF4AAABYGhlYWQGPe1ZAAAC2AAAADZoaGVhB30DyAAAAxAAAAAkaG10eBBKAEUAAAM0AAAAHGxvY2EAmgESAAADUAAAABBtYXhwAAkALwAAA2AAAAAgbmFtZSC8IugAAAOAAAABknBvc3QAAwAAAAAFFAAAACAAAwMTAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADoAgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6AL//f//AAAAAAAg6AD//f//AAH/4xgEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAEUAUQO7AvgAGgAAARQHAQYjIicBJjU0PwE2MzIfAQE2MzIfARYVA7sQ/hQQFhcQ/uMQEE4QFxcQqAF2EBcXEE4QAnMWEP4UEBABHRAXFhBOEBCoAXcQEE4QFwAAAAABAAABbgMlAkkAFAAAARUUBwYjISInJj0BNDc2MyEyFxYVAyUQEBf9SRcQEBAQFwK3FxAQAhJtFxAQEBAXbRcQEBAQFwAAAAABAAAASQMlA24ALAAAARUUBwYrARUUBwYrASInJj0BIyInJj0BNDc2OwE1NDc2OwEyFxYdATMyFxYVAyUQEBfuEBAXbhYQEO4XEBAQEBfuEBAWbhcQEO4XEBACEm0XEBDuFxAQEBAX7hAQF20XEBDuFxAQEBAX7hAQFwAAAQAAAAIAAHRSzT9fDzz1AAsEAAAAAADRsdR3AAAAANGx1HcAAAAAA7sDbgAAAAgAAgAAAAAAAAABAAADwP/AAAAEAAAAAAADuwABAAAAAAAAAAAAAAAAAAAABwQAAAAAAAAAAAAAAAIAAAAEAABFAyUAAAMlAAAAAAAAAAoAFAAeAE4AcgCwAAEAAAAHAC0AAQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAIAAAAAQAAAAAAAgAHAGkAAQAAAAAAAwAIADkAAQAAAAAABAAIAH4AAQAAAAAABQALABgAAQAAAAAABgAIAFEAAQAAAAAACgAaAJYAAwABBAkAAQAQAAgAAwABBAkAAgAOAHAAAwABBAkAAwAQAEEAAwABBAkABAAQAIYAAwABBAkABQAWACMAAwABBAkABgAQAFkAAwABBAkACgA0ALBDaGVja2JveABDAGgAZQBjAGsAYgBvAHhWZXJzaW9uIDIuMABWAGUAcgBzAGkAbwBuACAAMgAuADBDaGVja2JveABDAGgAZQBjAGsAYgBvAHhDaGVja2JveABDAGgAZQBjAGsAYgBvAHhSZWd1bGFyAFIAZQBnAHUAbABhAHJDaGVja2JveABDAGgAZQBjAGsAYgBvAHhGb250IGdlbmVyYXRlZCBieSBJY29Nb29uLgBGAG8AbgB0ACAAZwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAC4AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('truetype'); | |||||
} | |||||
/* Checkmark */ | |||||
.ui.checkbox label:after, | |||||
.ui.checkbox .box:after { | |||||
font-family: 'Checkbox'; | |||||
} | |||||
/* Checked */ | |||||
.ui.checkbox input:checked ~ .box:after, | |||||
.ui.checkbox input:checked ~ label:after { | |||||
content: '\e800'; | |||||
} | |||||
/* Indeterminate */ | |||||
.ui.checkbox input:indeterminate ~ .box:after, | |||||
.ui.checkbox input:indeterminate ~ label:after { | |||||
font-size: 12px; | |||||
content: '\e801'; | |||||
} | |||||
/* UTF Reference | |||||
.check:before { content: '\e800'; } | |||||
.dash:before { content: '\e801'; } | |||||
.plus:before { content: '\e802'; } | |||||
*/ | |||||
/******************************* | /******************************* | ||||
Site Overrides | Site Overrides | ||||
*******************************/ | *******************************/ |
})( jQuery, window, document ); | |||||
/*! | |||||
* # Fomantic-UI - Checkbox | |||||
* http://github.com/fomantic/Fomantic-UI/ | |||||
* | |||||
* | |||||
* Released under the MIT license | |||||
* http://opensource.org/licenses/MIT | |||||
* | |||||
*/ | |||||
;(function ($, window, document, undefined) { | |||||
'use strict'; | |||||
$.isFunction = $.isFunction || function(obj) { | |||||
return typeof obj === "function" && typeof obj.nodeType !== "number"; | |||||
}; | |||||
window = (typeof window != 'undefined' && window.Math == Math) | |||||
? window | |||||
: (typeof self != 'undefined' && self.Math == Math) | |||||
? self | |||||
: Function('return this')() | |||||
; | |||||
$.fn.checkbox = function(parameters) { | |||||
var | |||||
$allModules = $(this), | |||||
moduleSelector = $allModules.selector || '', | |||||
time = new Date().getTime(), | |||||
performance = [], | |||||
query = arguments[0], | |||||
methodInvoked = (typeof query == 'string'), | |||||
queryArguments = [].slice.call(arguments, 1), | |||||
returnedValue | |||||
; | |||||
$allModules | |||||
.each(function() { | |||||
var | |||||
settings = $.extend(true, {}, $.fn.checkbox.settings, parameters), | |||||
className = settings.className, | |||||
namespace = settings.namespace, | |||||
selector = settings.selector, | |||||
error = settings.error, | |||||
eventNamespace = '.' + namespace, | |||||
moduleNamespace = 'module-' + namespace, | |||||
$module = $(this), | |||||
$label = $(this).children(selector.label), | |||||
$input = $(this).children(selector.input), | |||||
input = $input[0], | |||||
initialLoad = false, | |||||
shortcutPressed = false, | |||||
instance = $module.data(moduleNamespace), | |||||
observer, | |||||
element = this, | |||||
module | |||||
; | |||||
module = { | |||||
initialize: function() { | |||||
module.verbose('Initializing checkbox', settings); | |||||
module.create.label(); | |||||
module.bind.events(); | |||||
module.set.tabbable(); | |||||
module.hide.input(); | |||||
module.observeChanges(); | |||||
module.instantiate(); | |||||
module.setup(); | |||||
}, | |||||
instantiate: function() { | |||||
module.verbose('Storing instance of module', module); | |||||
instance = module; | |||||
$module | |||||
.data(moduleNamespace, module) | |||||
; | |||||
}, | |||||
destroy: function() { | |||||
module.verbose('Destroying module'); | |||||
module.unbind.events(); | |||||
module.show.input(); | |||||
$module.removeData(moduleNamespace); | |||||
}, | |||||
fix: { | |||||
reference: function() { | |||||
if( $module.is(selector.input) ) { | |||||
module.debug('Behavior called on <input> adjusting invoked element'); | |||||
$module = $module.closest(selector.checkbox); | |||||
module.refresh(); | |||||
} | |||||
} | |||||
}, | |||||
setup: function() { | |||||
module.set.initialLoad(); | |||||
if( module.is.indeterminate() ) { | |||||
module.debug('Initial value is indeterminate'); | |||||
module.indeterminate(); | |||||
} | |||||
else if( module.is.checked() ) { | |||||
module.debug('Initial value is checked'); | |||||
module.check(); | |||||
} | |||||
else { | |||||
module.debug('Initial value is unchecked'); | |||||
module.uncheck(); | |||||
} | |||||
module.remove.initialLoad(); | |||||
}, | |||||
refresh: function() { | |||||
$label = $module.children(selector.label); | |||||
$input = $module.children(selector.input); | |||||
input = $input[0]; | |||||
}, | |||||
hide: { | |||||
input: function() { | |||||
module.verbose('Modifying <input> z-index to be unselectable'); | |||||
$input.addClass(className.hidden); | |||||
} | |||||
}, | |||||
show: { | |||||
input: function() { | |||||
module.verbose('Modifying <input> z-index to be selectable'); | |||||
$input.removeClass(className.hidden); | |||||
} | |||||
}, | |||||
observeChanges: function() { | |||||
if('MutationObserver' in window) { | |||||
observer = new MutationObserver(function(mutations) { | |||||
module.debug('DOM tree modified, updating selector cache'); | |||||
module.refresh(); | |||||
}); | |||||
observer.observe(element, { | |||||
childList : true, | |||||
subtree : true | |||||
}); | |||||
module.debug('Setting up mutation observer', observer); | |||||
} | |||||
}, | |||||
attachEvents: function(selector, event) { | |||||
var | |||||
$element = $(selector) | |||||
; | |||||
event = $.isFunction(module[event]) | |||||
? module[event] | |||||
: module.toggle | |||||
; | |||||
if($element.length > 0) { | |||||
module.debug('Attaching checkbox events to element', selector, event); | |||||
$element | |||||
.on('click' + eventNamespace, event) | |||||
; | |||||
} | |||||
else { | |||||
module.error(error.notFound); | |||||
} | |||||
}, | |||||
preventDefaultOnInputTarget: function() { | |||||
if(typeof event !== 'undefined' && event !== null && $(event.target).is(selector.input)) { | |||||
module.verbose('Preventing default check action after manual check action'); | |||||
event.preventDefault(); | |||||
} | |||||
}, | |||||
event: { | |||||
change: function(event) { | |||||
if( !module.should.ignoreCallbacks() ) { | |||||
settings.onChange.call(input); | |||||
} | |||||
}, | |||||
click: function(event) { | |||||
var | |||||
$target = $(event.target) | |||||
; | |||||
if( $target.is(selector.input) ) { | |||||
module.verbose('Using default check action on initialized checkbox'); | |||||
return; | |||||
} | |||||
if( $target.is(selector.link) ) { | |||||
module.debug('Clicking link inside checkbox, skipping toggle'); | |||||
return; | |||||
} | |||||
module.toggle(); | |||||
$input.focus(); | |||||
event.preventDefault(); | |||||
}, | |||||
keydown: function(event) { | |||||
var | |||||
key = event.which, | |||||
keyCode = { | |||||
enter : 13, | |||||
space : 32, | |||||
escape : 27, | |||||
left : 37, | |||||
up : 38, | |||||
right : 39, | |||||
down : 40 | |||||
} | |||||
; | |||||
var r = module.get.radios(), | |||||
rIndex = r.index($module), | |||||
rLen = r.length, | |||||
checkIndex = false; | |||||
if(key == keyCode.left || key == keyCode.up) { | |||||
checkIndex = (rIndex === 0 ? rLen : rIndex) - 1; | |||||
} else if(key == keyCode.right || key == keyCode.down) { | |||||
checkIndex = rIndex === rLen-1 ? 0 : rIndex+1; | |||||
} | |||||
if (!module.should.ignoreCallbacks() && checkIndex !== false) { | |||||
if(settings.beforeUnchecked.apply(input)===false) { | |||||
module.verbose('Option not allowed to be unchecked, cancelling key navigation'); | |||||
return false; | |||||
} | |||||
if (settings.beforeChecked.apply($(r[checkIndex]).children(selector.input)[0])===false) { | |||||
module.verbose('Next option should not allow check, cancelling key navigation'); | |||||
return false; | |||||
} | |||||
} | |||||
if(key == keyCode.escape) { | |||||
module.verbose('Escape key pressed blurring field'); | |||||
$input.blur(); | |||||
shortcutPressed = true; | |||||
} | |||||
else if(!event.ctrlKey && ( key == keyCode.space || (key == keyCode.enter && settings.enableEnterKey)) ) { | |||||
module.verbose('Enter/space key pressed, toggling checkbox'); | |||||
module.toggle(); | |||||
shortcutPressed = true; | |||||
} | |||||
else { | |||||
shortcutPressed = false; | |||||
} | |||||
}, | |||||
keyup: function(event) { | |||||
if(shortcutPressed) { | |||||
event.preventDefault(); | |||||
} | |||||
} | |||||
}, | |||||
check: function() { | |||||
if( !module.should.allowCheck() ) { | |||||
return; | |||||
} | |||||
module.debug('Checking checkbox', $input); | |||||
module.set.checked(); | |||||
if( !module.should.ignoreCallbacks() ) { | |||||
settings.onChecked.call(input); | |||||
module.trigger.change(); | |||||
} | |||||
module.preventDefaultOnInputTarget(); | |||||
}, | |||||
uncheck: function() { | |||||
if( !module.should.allowUncheck() ) { | |||||
return; | |||||
} | |||||
module.debug('Unchecking checkbox'); | |||||
module.set.unchecked(); | |||||
if( !module.should.ignoreCallbacks() ) { | |||||
settings.onUnchecked.call(input); | |||||
module.trigger.change(); | |||||
} | |||||
module.preventDefaultOnInputTarget(); | |||||
}, | |||||
indeterminate: function() { | |||||
if( module.should.allowIndeterminate() ) { | |||||
module.debug('Checkbox is already indeterminate'); | |||||
return; | |||||
} | |||||
module.debug('Making checkbox indeterminate'); | |||||
module.set.indeterminate(); | |||||
if( !module.should.ignoreCallbacks() ) { | |||||
settings.onIndeterminate.call(input); | |||||
module.trigger.change(); | |||||
} | |||||
}, | |||||
determinate: function() { | |||||
if( module.should.allowDeterminate() ) { | |||||
module.debug('Checkbox is already determinate'); | |||||
return; | |||||
} | |||||
module.debug('Making checkbox determinate'); | |||||
module.set.determinate(); | |||||
if( !module.should.ignoreCallbacks() ) { | |||||
settings.onDeterminate.call(input); | |||||
module.trigger.change(); | |||||
} | |||||
}, | |||||
enable: function() { | |||||
if( module.is.enabled() ) { | |||||
module.debug('Checkbox is already enabled'); | |||||
return; | |||||
} | |||||
module.debug('Enabling checkbox'); | |||||
module.set.enabled(); | |||||
if( !module.should.ignoreCallbacks() ) { | |||||
settings.onEnable.call(input); | |||||
// preserve legacy callbacks | |||||
settings.onEnabled.call(input); | |||||
module.trigger.change(); | |||||
} | |||||
}, | |||||
disable: function() { | |||||
if( module.is.disabled() ) { | |||||
module.debug('Checkbox is already disabled'); | |||||
return; | |||||
} | |||||
module.debug('Disabling checkbox'); | |||||
module.set.disabled(); | |||||
if( !module.should.ignoreCallbacks() ) { | |||||
settings.onDisable.call(input); | |||||
// preserve legacy callbacks | |||||
settings.onDisabled.call(input); | |||||
module.trigger.change(); | |||||
} | |||||
}, | |||||
get: { | |||||
radios: function() { | |||||
var | |||||
name = module.get.name() | |||||
; | |||||
return $('input[name="' + name + '"]').closest(selector.checkbox); | |||||
}, | |||||
otherRadios: function() { | |||||
return module.get.radios().not($module); | |||||
}, | |||||
name: function() { | |||||
return $input.attr('name'); | |||||
} | |||||
}, | |||||
is: { | |||||
initialLoad: function() { | |||||
return initialLoad; | |||||
}, | |||||
radio: function() { | |||||
return ($input.hasClass(className.radio) || $input.attr('type') == 'radio'); | |||||
}, | |||||
indeterminate: function() { | |||||
return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate'); | |||||
}, | |||||
checked: function() { | |||||
return $input.prop('checked') !== undefined && $input.prop('checked'); | |||||
}, | |||||
disabled: function() { | |||||
return $input.prop('disabled') !== undefined && $input.prop('disabled'); | |||||
}, | |||||
enabled: function() { | |||||
return !module.is.disabled(); | |||||
}, | |||||
determinate: function() { | |||||
return !module.is.indeterminate(); | |||||
}, | |||||
unchecked: function() { | |||||
return !module.is.checked(); | |||||
} | |||||
}, | |||||
should: { | |||||
allowCheck: function() { | |||||
if(module.is.determinate() && module.is.checked() && !module.is.initialLoad() ) { | |||||
module.debug('Should not allow check, checkbox is already checked'); | |||||
return false; | |||||
} | |||||
if(!module.should.ignoreCallbacks() && settings.beforeChecked.apply(input) === false) { | |||||
module.debug('Should not allow check, beforeChecked cancelled'); | |||||
return false; | |||||
} | |||||
return true; | |||||
}, | |||||
allowUncheck: function() { | |||||
if(module.is.determinate() && module.is.unchecked() && !module.is.initialLoad() ) { | |||||
module.debug('Should not allow uncheck, checkbox is already unchecked'); | |||||
return false; | |||||
} | |||||
if(!module.should.ignoreCallbacks() && settings.beforeUnchecked.apply(input) === false) { | |||||
module.debug('Should not allow uncheck, beforeUnchecked cancelled'); | |||||
return false; | |||||
} | |||||
return true; | |||||
}, | |||||
allowIndeterminate: function() { | |||||
if(module.is.indeterminate() && !module.is.initialLoad() ) { | |||||
module.debug('Should not allow indeterminate, checkbox is already indeterminate'); | |||||
return false; | |||||
} | |||||
if(!module.should.ignoreCallbacks() && settings.beforeIndeterminate.apply(input) === false) { | |||||
module.debug('Should not allow indeterminate, beforeIndeterminate cancelled'); | |||||
return false; | |||||
} | |||||
return true; | |||||
}, | |||||
allowDeterminate: function() { | |||||
if(module.is.determinate() && !module.is.initialLoad() ) { | |||||
module.debug('Should not allow determinate, checkbox is already determinate'); | |||||
return false; | |||||
} | |||||
if(!module.should.ignoreCallbacks() && settings.beforeDeterminate.apply(input) === false) { | |||||
module.debug('Should not allow determinate, beforeDeterminate cancelled'); | |||||
return false; | |||||
} | |||||
return true; | |||||
}, | |||||
ignoreCallbacks: function() { | |||||
return (initialLoad && !settings.fireOnInit); | |||||
} | |||||
}, | |||||
can: { | |||||
change: function() { | |||||
return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') ); | |||||
}, | |||||
uncheck: function() { | |||||
return (typeof settings.uncheckable === 'boolean') | |||||
? settings.uncheckable | |||||
: !module.is.radio() | |||||
; | |||||
} | |||||
}, | |||||
set: { | |||||
initialLoad: function() { | |||||
initialLoad = true; | |||||
}, | |||||
checked: function() { | |||||
module.verbose('Setting class to checked'); | |||||
$module | |||||
.removeClass(className.indeterminate) | |||||
.addClass(className.checked) | |||||
; | |||||
if( module.is.radio() ) { | |||||
module.uncheckOthers(); | |||||
} | |||||
if(!module.is.indeterminate() && module.is.checked()) { | |||||
module.debug('Input is already checked, skipping input property change'); | |||||
return; | |||||
} | |||||
module.verbose('Setting state to checked', input); | |||||
$input | |||||
.prop('indeterminate', false) | |||||
.prop('checked', true) | |||||
; | |||||
}, | |||||
unchecked: function() { | |||||
module.verbose('Removing checked class'); | |||||
$module | |||||
.removeClass(className.indeterminate) | |||||
.removeClass(className.checked) | |||||
; | |||||
if(!module.is.indeterminate() && module.is.unchecked() ) { | |||||
module.debug('Input is already unchecked'); | |||||
return; | |||||
} | |||||
module.debug('Setting state to unchecked'); | |||||
$input | |||||
.prop('indeterminate', false) | |||||
.prop('checked', false) | |||||
; | |||||
}, | |||||
indeterminate: function() { | |||||
module.verbose('Setting class to indeterminate'); | |||||
$module | |||||
.addClass(className.indeterminate) | |||||
; | |||||
if( module.is.indeterminate() ) { | |||||
module.debug('Input is already indeterminate, skipping input property change'); | |||||
return; | |||||
} | |||||
module.debug('Setting state to indeterminate'); | |||||
$input | |||||
.prop('indeterminate', true) | |||||
; | |||||
}, | |||||
determinate: function() { | |||||
module.verbose('Removing indeterminate class'); | |||||
$module | |||||
.removeClass(className.indeterminate) | |||||
; | |||||
if( module.is.determinate() ) { | |||||
module.debug('Input is already determinate, skipping input property change'); | |||||
return; | |||||
} | |||||
module.debug('Setting state to determinate'); | |||||
$input | |||||
.prop('indeterminate', false) | |||||
; | |||||
}, | |||||
disabled: function() { | |||||
module.verbose('Setting class to disabled'); | |||||
$module | |||||
.addClass(className.disabled) | |||||
; | |||||
if( module.is.disabled() ) { | |||||
module.debug('Input is already disabled, skipping input property change'); | |||||
return; | |||||
} | |||||
module.debug('Setting state to disabled'); | |||||
$input | |||||
.prop('disabled', 'disabled') | |||||
; | |||||
}, | |||||
enabled: function() { | |||||
module.verbose('Removing disabled class'); | |||||
$module.removeClass(className.disabled); | |||||
if( module.is.enabled() ) { | |||||
module.debug('Input is already enabled, skipping input property change'); | |||||
return; | |||||
} | |||||
module.debug('Setting state to enabled'); | |||||
$input | |||||
.prop('disabled', false) | |||||
; | |||||
}, | |||||
tabbable: function() { | |||||
module.verbose('Adding tabindex to checkbox'); | |||||
if( $input.attr('tabindex') === undefined) { | |||||
$input.attr('tabindex', 0); | |||||
} | |||||
} | |||||
}, | |||||
remove: { | |||||
initialLoad: function() { | |||||
initialLoad = false; | |||||
} | |||||
}, | |||||
trigger: { | |||||
change: function() { | |||||
var | |||||
inputElement = $input[0] | |||||
; | |||||
if(inputElement) { | |||||
var events = document.createEvent('HTMLEvents'); | |||||
module.verbose('Triggering native change event'); | |||||
events.initEvent('change', true, false); | |||||
inputElement.dispatchEvent(events); | |||||
} | |||||
} | |||||
}, | |||||
create: { | |||||
label: function() { | |||||
if($input.prevAll(selector.label).length > 0) { | |||||
$input.prev(selector.label).detach().insertAfter($input); | |||||
module.debug('Moving existing label', $label); | |||||
} | |||||
else if( !module.has.label() ) { | |||||
$label = $('<label>').insertAfter($input); | |||||
module.debug('Creating label', $label); | |||||
} | |||||
} | |||||
}, | |||||
has: { | |||||
label: function() { | |||||
return ($label.length > 0); | |||||
} | |||||
}, | |||||
bind: { | |||||
events: function() { | |||||
module.verbose('Attaching checkbox events'); | |||||
$module | |||||
.on('click' + eventNamespace, module.event.click) | |||||
.on('change' + eventNamespace, module.event.change) | |||||
.on('keydown' + eventNamespace, selector.input, module.event.keydown) | |||||
.on('keyup' + eventNamespace, selector.input, module.event.keyup) | |||||
; | |||||
} | |||||
}, | |||||
unbind: { | |||||
events: function() { | |||||
module.debug('Removing events'); | |||||
$module | |||||
.off(eventNamespace) | |||||
; | |||||
} | |||||
}, | |||||
uncheckOthers: function() { | |||||
var | |||||
$radios = module.get.otherRadios() | |||||
; | |||||
module.debug('Unchecking other radios', $radios); | |||||
$radios.removeClass(className.checked); | |||||
}, | |||||
toggle: function() { | |||||
if( !module.can.change() ) { | |||||
if(!module.is.radio()) { | |||||
module.debug('Checkbox is read-only or disabled, ignoring toggle'); | |||||
} | |||||
return; | |||||
} | |||||
if( module.is.indeterminate() || module.is.unchecked() ) { | |||||
module.debug('Currently unchecked'); | |||||
module.check(); | |||||
} | |||||
else if( module.is.checked() && module.can.uncheck() ) { | |||||
module.debug('Currently checked'); | |||||
module.uncheck(); | |||||
} | |||||
}, | |||||
setting: function(name, value) { | |||||
module.debug('Changing setting', name, value); | |||||
if( $.isPlainObject(name) ) { | |||||
$.extend(true, settings, name); | |||||
} | |||||
else if(value !== undefined) { | |||||
if($.isPlainObject(settings[name])) { | |||||
$.extend(true, settings[name], value); | |||||
} | |||||
else { | |||||
settings[name] = value; | |||||
} | |||||
} | |||||
else { | |||||
return settings[name]; | |||||
} | |||||
}, | |||||
internal: function(name, value) { | |||||
if( $.isPlainObject(name) ) { | |||||
$.extend(true, module, name); | |||||
} | |||||
else if(value !== undefined) { | |||||
module[name] = value; | |||||
} | |||||
else { | |||||
return module[name]; | |||||
} | |||||
}, | |||||
debug: function() { | |||||
if(!settings.silent && settings.debug) { | |||||
if(settings.performance) { | |||||
module.performance.log(arguments); | |||||
} | |||||
else { | |||||
module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); | |||||
module.debug.apply(console, arguments); | |||||
} | |||||
} | |||||
}, | |||||
verbose: function() { | |||||
if(!settings.silent && settings.verbose && settings.debug) { | |||||
if(settings.performance) { | |||||
module.performance.log(arguments); | |||||
} | |||||
else { | |||||
module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); | |||||
module.verbose.apply(console, arguments); | |||||
} | |||||
} | |||||
}, | |||||
error: function() { | |||||
if(!settings.silent) { | |||||
module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); | |||||
module.error.apply(console, arguments); | |||||
} | |||||
}, | |||||
performance: { | |||||
log: function(message) { | |||||
var | |||||
currentTime, | |||||
executionTime, | |||||
previousTime | |||||
; | |||||
if(settings.performance) { | |||||
currentTime = new Date().getTime(); | |||||
previousTime = time || currentTime; | |||||
executionTime = currentTime - previousTime; | |||||
time = currentTime; | |||||
performance.push({ | |||||
'Name' : message[0], | |||||
'Arguments' : [].slice.call(message, 1) || '', | |||||
'Element' : element, | |||||
'Execution Time' : executionTime | |||||
}); | |||||
} | |||||
clearTimeout(module.performance.timer); | |||||
module.performance.timer = setTimeout(module.performance.display, 500); | |||||
}, | |||||
display: function() { | |||||
var | |||||
title = settings.name + ':', | |||||
totalTime = 0 | |||||
; | |||||
time = false; | |||||
clearTimeout(module.performance.timer); | |||||
$.each(performance, function(index, data) { | |||||
totalTime += data['Execution Time']; | |||||
}); | |||||
title += ' ' + totalTime + 'ms'; | |||||
if(moduleSelector) { | |||||
title += ' \'' + moduleSelector + '\''; | |||||
} | |||||
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { | |||||
console.groupCollapsed(title); | |||||
if(console.table) { | |||||
console.table(performance); | |||||
} | |||||
else { | |||||
$.each(performance, function(index, data) { | |||||
console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); | |||||
}); | |||||
} | |||||
console.groupEnd(); | |||||
} | |||||
performance = []; | |||||
} | |||||
}, | |||||
invoke: function(query, passedArguments, context) { | |||||
var | |||||
object = instance, | |||||
maxDepth, | |||||
found, | |||||
response | |||||
; | |||||
passedArguments = passedArguments || queryArguments; | |||||
context = element || context; | |||||
if(typeof query == 'string' && object !== undefined) { | |||||
query = query.split(/[\. ]/); | |||||
maxDepth = query.length - 1; | |||||
$.each(query, function(depth, value) { | |||||
var camelCaseValue = (depth != maxDepth) | |||||
? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) | |||||
: query | |||||
; | |||||
if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { | |||||
object = object[camelCaseValue]; | |||||
} | |||||
else if( object[camelCaseValue] !== undefined ) { | |||||
found = object[camelCaseValue]; | |||||
return false; | |||||
} | |||||
else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { | |||||
object = object[value]; | |||||
} | |||||
else if( object[value] !== undefined ) { | |||||
found = object[value]; | |||||
return false; | |||||
} | |||||
else { | |||||
module.error(error.method, query); | |||||
return false; | |||||
} | |||||
}); | |||||
} | |||||
if ( $.isFunction( found ) ) { | |||||
response = found.apply(context, passedArguments); | |||||
} | |||||
else if(found !== undefined) { | |||||
response = found; | |||||
} | |||||
if(Array.isArray(returnedValue)) { | |||||
returnedValue.push(response); | |||||
} | |||||
else if(returnedValue !== undefined) { | |||||
returnedValue = [returnedValue, response]; | |||||
} | |||||
else if(response !== undefined) { | |||||
returnedValue = response; | |||||
} | |||||
return found; | |||||
} | |||||
}; | |||||
if(methodInvoked) { | |||||
if(instance === undefined) { | |||||
module.initialize(); | |||||
} | |||||
module.invoke(query); | |||||
} | |||||
else { | |||||
if(instance !== undefined) { | |||||
instance.invoke('destroy'); | |||||
} | |||||
module.initialize(); | |||||
} | |||||
}) | |||||
; | |||||
return (returnedValue !== undefined) | |||||
? returnedValue | |||||
: this | |||||
; | |||||
}; | |||||
$.fn.checkbox.settings = { | |||||
name : 'Checkbox', | |||||
namespace : 'checkbox', | |||||
silent : false, | |||||
debug : false, | |||||
verbose : true, | |||||
performance : true, | |||||
// delegated event context | |||||
uncheckable : 'auto', | |||||
fireOnInit : false, | |||||
enableEnterKey : true, | |||||
onChange : function(){}, | |||||
beforeChecked : function(){}, | |||||
beforeUnchecked : function(){}, | |||||
beforeDeterminate : function(){}, | |||||
beforeIndeterminate : function(){}, | |||||
onChecked : function(){}, | |||||
onUnchecked : function(){}, | |||||
onDeterminate : function() {}, | |||||
onIndeterminate : function() {}, | |||||
onEnable : function(){}, | |||||
onDisable : function(){}, | |||||
// preserve misspelled callbacks (will be removed in 3.0) | |||||
onEnabled : function(){}, | |||||
onDisabled : function(){}, | |||||
className : { | |||||
checked : 'checked', | |||||
indeterminate : 'indeterminate', | |||||
disabled : 'disabled', | |||||
hidden : 'hidden', | |||||
radio : 'radio', | |||||
readOnly : 'read-only' | |||||
}, | |||||
error : { | |||||
method : 'The method you called is not defined' | |||||
}, | |||||
selector : { | |||||
checkbox : '.ui.checkbox', | |||||
label : 'label, .box', | |||||
input : 'input[type="checkbox"], input[type="radio"]', | |||||
link : 'a[href]' | |||||
} | |||||
}; | |||||
})( jQuery, window, document ); | })( jQuery, window, document ); | ||||
/*! | /*! |
"components": [ | "components": [ | ||||
"api", | "api", | ||||
"button", | "button", | ||||
"checkbox", | |||||
"dimmer", | "dimmer", | ||||
"dropdown", | "dropdown", | ||||
"form", | "form", |
}); | }); | ||||
// Select actions | // Select actions | ||||
const $checkboxes = $('.select.table .ui.checkbox'); | |||||
const checkboxes = document.querySelectorAll('.select.table .ui.checkbox input'); | |||||
$('.select.action').on('click', function () { | $('.select.action').on('click', function () { | ||||
switch ($(this).data('action')) { | switch ($(this).data('action')) { | ||||
case 'select-all': | case 'select-all': | ||||
$checkboxes.checkbox('check'); | |||||
for (const checkbox of checkboxes) { | |||||
checkbox.checked = true; | |||||
} | |||||
break; | break; | ||||
case 'deselect-all': | case 'deselect-all': | ||||
$checkboxes.checkbox('uncheck'); | |||||
for (const checkbox of checkboxes) { | |||||
checkbox.checked = false; | |||||
} | |||||
break; | break; | ||||
case 'inverse': | case 'inverse': | ||||
$checkboxes.checkbox('toggle'); | |||||
for (const checkbox of checkboxes) { | |||||
checkbox.checked = !checkbox.checked; | |||||
} | |||||
break; | break; | ||||
} | } | ||||
}); | }); | ||||
e.preventDefault(); | e.preventDefault(); | ||||
this.classList.add('is-loading', 'disabled'); | this.classList.add('is-loading', 'disabled'); | ||||
const data = new FormData(); | const data = new FormData(); | ||||
$checkboxes.each(function () { | |||||
if ($(this).checkbox('is checked')) { | |||||
data.append('ids[]', this.getAttribute('data-id')); | |||||
for (const checkbox of checkboxes) { | |||||
if (checkbox.checked) { | |||||
data.append('ids[]', checkbox.closest('.ui.checkbox').getAttribute('data-id')); | |||||
} | } | ||||
}); | |||||
} | |||||
await POST(this.getAttribute('data-link'), {data}); | await POST(this.getAttribute('data-link'), {data}); | ||||
window.location.href = this.getAttribute('data-redirect'); | window.location.href = this.getAttribute('data-redirect'); | ||||
}); | }); |
$uiDropdowns.filter('.upward').dropdown('setting', 'direction', 'upward'); | $uiDropdowns.filter('.upward').dropdown('setting', 'direction', 'upward'); | ||||
$uiDropdowns.filter('.downward').dropdown('setting', 'direction', 'downward'); | $uiDropdowns.filter('.downward').dropdown('setting', 'direction', 'downward'); | ||||
$('.ui.checkbox').checkbox(); | |||||
$('.tabular.menu .item').tab(); | $('.tabular.menu .item').tab(); | ||||
initSubmitEventPolyfill(); | initSubmitEventPolyfill(); |
} | } | ||||
export function initRepoPullRequestAllowMaintainerEdit() { | export function initRepoPullRequestAllowMaintainerEdit() { | ||||
const checkbox = document.getElementById('allow-edits-from-maintainers'); | |||||
if (!checkbox) return; | |||||
const $checkbox = $(checkbox); | |||||
const promptError = checkbox.getAttribute('data-prompt-error'); | |||||
$checkbox.checkbox({ | |||||
'onChange': async () => { | |||||
const checked = $checkbox.checkbox('is checked'); | |||||
let url = checkbox.getAttribute('data-url'); | |||||
url += '/set_allow_maintainer_edit'; | |||||
$checkbox.checkbox('set disabled'); | |||||
try { | |||||
const response = await POST(url, { | |||||
data: {allow_maintainer_edit: checked}, | |||||
}); | |||||
if (!response.ok) { | |||||
throw new Error('Failed to update maintainer edit permission'); | |||||
} | |||||
} catch (error) { | |||||
console.error(error); | |||||
showTemporaryTooltip(checkbox, promptError); | |||||
} finally { | |||||
$checkbox.checkbox('set enabled'); | |||||
const wrapper = document.getElementById('allow-edits-from-maintainers'); | |||||
if (!wrapper) return; | |||||
wrapper.querySelector('input[type="checkbox"]')?.addEventListener('change', async (e) => { | |||||
const checked = e.target.checked; | |||||
const url = `${wrapper.getAttribute('data-url')}/set_allow_maintainer_edit`; | |||||
wrapper.classList.add('is-loading'); | |||||
e.target.disabled = true; | |||||
try { | |||||
const response = await POST(url, {data: {allow_maintainer_edit: checked}}); | |||||
if (!response.ok) { | |||||
throw new Error('Failed to update maintainer edit permission'); | |||||
} | } | ||||
}, | |||||
} catch (error) { | |||||
console.error(error); | |||||
showTemporaryTooltip(wrapper, wrapper.getAttribute('data-prompt-error')); | |||||
} finally { | |||||
wrapper.classList.remove('is-loading'); | |||||
e.target.disabled = false; | |||||
} | |||||
}); | }); | ||||
} | } | ||||
export function initGiteaFomantic() { | export function initGiteaFomantic() { | ||||
// Silence fomantic's error logging when tabs are used without a target content element | // Silence fomantic's error logging when tabs are used without a target content element | ||||
$.fn.tab.settings.silent = true; | $.fn.tab.settings.silent = true; | ||||
// Disable the behavior of fomantic to toggle the checkbox when you press enter on a checkbox element. | |||||
$.fn.checkbox.settings.enableEnterKey = false; | |||||
// By default, use "exact match" for full text search | // By default, use "exact match" for full text search | ||||
$.fn.dropdown.settings.fullTextSearch = 'exact'; | $.fn.dropdown.settings.fullTextSearch = 'exact'; |
<label><input type="checkbox"> ... </label> | <label><input type="checkbox"> ... </label> | ||||
``` | ``` | ||||
However, related CSS styles aren't supported (not implemented) yet, so at the moment, | |||||
almost all the checkboxes are still using Fomantic UI checkbox. | |||||
## Fomantic UI Checkbox | |||||
However, the templates still have the Fomantic-style HTML layout: | |||||
```html | ```html | ||||
<div class="ui checkbox"> | <div class="ui checkbox"> | ||||
<input type="checkbox"> <!-- class "hidden" will be added by $.checkbox() --> | |||||
<input type="checkbox"> | |||||
<label>...</label> | <label>...</label> | ||||
</div> | </div> | ||||
``` | ``` | ||||
Then the JS `$.checkbox()` should be called to make it work with keyboard and label-clicking, | |||||
then it works like the ideal checkboxes. | |||||
There is still a problem: Fomantic UI checkbox is not friendly to screen readers, | |||||
so we add IDs to all the Fomantic UI checkboxes automatically by JS. | |||||
If the `label` part is empty, then the checkbox needs to get the `aria-label` attribute manually. | |||||
We call `initAriaCheckboxPatch` to link the `input` and `label` which makes clicking the | |||||
label etc. work. There is still a problem: These checkboxes are not friendly to screen readers, | |||||
so we add IDs to all the Fomantic UI checkboxes automatically by JS. If the `label` part is empty, | |||||
then the checkbox needs to get the `aria-label` attribute manually. | |||||
# Fomantic Dropdown | # Fomantic Dropdown | ||||
import $ from 'jquery'; | |||||
import {generateAriaId} from './base.js'; | import {generateAriaId} from './base.js'; | ||||
const ariaPatchKey = '_giteaAriaPatchCheckbox'; | |||||
const fomanticCheckboxFn = $.fn.checkbox; | |||||
// use our own `$.fn.checkbox` to patch Fomantic's checkbox module | |||||
export function initAriaCheckboxPatch() { | export function initAriaCheckboxPatch() { | ||||
if ($.fn.checkbox === ariaCheckboxFn) throw new Error('initAriaCheckboxPatch could only be called once'); | |||||
$.fn.checkbox = ariaCheckboxFn; | |||||
ariaCheckboxFn.settings = fomanticCheckboxFn.settings; | |||||
} | |||||
// the patched `$.fn.checkbox` checkbox function | |||||
// * it does the one-time attaching on the first call | |||||
function ariaCheckboxFn(...args) { | |||||
const ret = fomanticCheckboxFn.apply(this, args); | |||||
for (const el of this) { | |||||
if (el[ariaPatchKey]) continue; | |||||
attachInit(el); | |||||
// link the label and the input element so it's clickable and accessible | |||||
for (const el of document.querySelectorAll('.ui.checkbox')) { | |||||
if (el.hasAttribute('data-checkbox-patched')) continue; | |||||
const label = el.querySelector('label'); | |||||
const input = el.querySelector('input'); | |||||
if (!label || !input || input.getAttribute('id') || label.getAttribute('for')) continue; | |||||
const id = generateAriaId(); | |||||
input.setAttribute('id', id); | |||||
label.setAttribute('for', id); | |||||
el.setAttribute('data-checkbox-patched', 'true'); | |||||
} | } | ||||
return ret; | |||||
} | |||||
function attachInit(el) { | |||||
// Fomantic UI checkbox needs to be something like: <div class="ui checkbox"><label /><input /></div> | |||||
// It doesn't work well with <label><input />...</label> | |||||
// To make it work with aria, the "id"/"for" attributes are necessary, so add them automatically if missing. | |||||
// In the future, refactor to use native checkbox directly, then this patch could be removed. | |||||
el[ariaPatchKey] = {}; // record that this element has been patched | |||||
const label = el.querySelector('label'); | |||||
const input = el.querySelector('input'); | |||||
if (!label || !input || input.getAttribute('id')) return; | |||||
const id = generateAriaId(); | |||||
input.setAttribute('id', id); | |||||
label.setAttribute('for', id); | |||||
} | } |