mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #35940 -- Disabled SelectFilter add/remove buttons when appropriate.
This commit is contained in:
parent
2f6b096b83
commit
55aff109bb
@ -631,7 +631,7 @@ input[type="submit"], button {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.active.selector-remove:focus, .active.selector-remove:hover {
|
||||
:enabled.selector-remove:focus, :enabled.selector-remove:hover {
|
||||
background-position: 0 -24px;
|
||||
}
|
||||
|
||||
@ -639,7 +639,7 @@ input[type="submit"], button {
|
||||
background-position: 0 -48px;
|
||||
}
|
||||
|
||||
.active.selector-add:focus, .active.selector-add:hover {
|
||||
:enabled.selector-add:focus, :enabled.selector-add:hover {
|
||||
background-position: 0 -72px;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .active.selector-remove:focus, .active.selector-remove:hover {
|
||||
[dir="rtl"] :enabled.selector-remove:focus, :enabled.selector-remove:hover {
|
||||
background-position: 0 -24px;
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
background-position: 0 -48px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .active.selector-add:focus, .active.selector-add:hover {
|
||||
[dir="rtl"] :enabled.selector-add:focus, :enabled.selector-add:hover {
|
||||
background-position: 0 -72px;
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ fieldset .fieldBox {
|
||||
background-size: 24px auto;
|
||||
}
|
||||
|
||||
.active.selector-add:focus, .active.selector-add:hover {
|
||||
:enabled.selector-add:focus, :enabled.selector-add:hover {
|
||||
background-position: 0 -120px;
|
||||
}
|
||||
|
||||
@ -233,7 +233,7 @@ fieldset .fieldBox {
|
||||
background-size: 24px auto;
|
||||
}
|
||||
|
||||
.active.selector-remove:focus, .active.selector-remove:hover {
|
||||
:enabled.selector-remove:focus, :enabled.selector-remove:hover {
|
||||
background-position: 0 -168px;
|
||||
}
|
||||
|
||||
@ -241,7 +241,7 @@ fieldset .fieldBox {
|
||||
background: url(../img/selector-icons.svg) right -128px no-repeat;
|
||||
}
|
||||
|
||||
.active.selector-chooseall:focus, .active.selector-chooseall:hover {
|
||||
:enabled.selector-chooseall:focus, :enabled.selector-chooseall:hover {
|
||||
background-position: 100% -144px;
|
||||
}
|
||||
|
||||
@ -249,7 +249,7 @@ fieldset .fieldBox {
|
||||
background: url(../img/selector-icons.svg) 0 -160px no-repeat;
|
||||
}
|
||||
|
||||
.active.selector-clearall:focus, .active.selector-clearall:hover {
|
||||
:enabled.selector-clearall:focus, :enabled.selector-clearall:hover {
|
||||
background-position: 0 -176px;
|
||||
}
|
||||
|
||||
|
@ -129,11 +129,11 @@
|
||||
border: none;
|
||||
}
|
||||
|
||||
.active.selector-add, .active.selector-remove {
|
||||
:enabled.selector-add, :enabled.selector-remove {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.active.selector-add:hover, .active.selector-remove:hover {
|
||||
:enabled.selector-add:hover, :enabled.selector-remove:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@
|
||||
background-size: 24px auto;
|
||||
}
|
||||
|
||||
.active.selector-add:focus, .active.selector-add:hover {
|
||||
:enabled.selector-add:focus, :enabled.selector-add:hover {
|
||||
background-position: 0 -168px;
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@
|
||||
background-size: 24px auto;
|
||||
}
|
||||
|
||||
.active.selector-remove:focus, .active.selector-remove:hover {
|
||||
:enabled.selector-remove:focus, :enabled.selector-remove:hover {
|
||||
background-position: 0 -120px;
|
||||
}
|
||||
|
||||
@ -169,16 +169,16 @@
|
||||
border: none;
|
||||
}
|
||||
|
||||
.active.selector-chooseall:focus, .active.selector-clearall:focus,
|
||||
.active.selector-chooseall:hover, .active.selector-clearall:hover {
|
||||
:enabled.selector-chooseall:focus, :enabled.selector-clearall:focus,
|
||||
:enabled.selector-chooseall:hover, :enabled.selector-clearall:hover {
|
||||
color: var(--link-fg);
|
||||
}
|
||||
|
||||
.active.selector-chooseall, .active.selector-clearall {
|
||||
:enabled.selector-chooseall, :enabled.selector-clearall {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.active.selector-chooseall:hover, .active.selector-clearall:hover {
|
||||
:enabled.selector-chooseall:hover, :enabled.selector-clearall:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.active.selector-chooseall:focus, .active.selector-chooseall:hover {
|
||||
:enabled.selector-chooseall:focus, :enabled.selector-chooseall:hover {
|
||||
background-position: 100% -176px;
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.active.selector-clearall:focus, .active.selector-clearall:hover {
|
||||
:enabled.selector-clearall:focus, :enabled.selector-clearall:hover {
|
||||
background-position: 0 -144px;
|
||||
}
|
||||
|
||||
@ -252,12 +252,12 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.stacked .active.selector-add {
|
||||
.stacked :enabled.selector-add {
|
||||
background-position: 0 -48px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stacked .active.selector-add:focus, .stacked .active.selector-add:hover {
|
||||
.stacked :enabled.selector-add:focus, .stacked :enabled.selector-add:hover {
|
||||
background-position: 0 -72px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -268,12 +268,12 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.stacked .active.selector-remove {
|
||||
.stacked :enabled.selector-remove {
|
||||
background-position: 0 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stacked .active.selector-remove:focus, .stacked .active.selector-remove:hover {
|
||||
.stacked :enabled.selector-remove:focus, .stacked :enabled.selector-remove:hover {
|
||||
background-position: 0 -24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ Requires core.js and SelectBox.js.
|
||||
|
||||
// Set up the JavaScript event handlers for the select box filter interface
|
||||
const move_selection = function(e, elem, move_func, from, to) {
|
||||
if (elem.classList.contains('active')) {
|
||||
if (!elem.hasAttribute('disabled')) {
|
||||
move_func(from, to);
|
||||
SelectFilter.refresh_icons(field_id);
|
||||
SelectFilter.refresh_filtered_selects(field_id);
|
||||
@ -248,13 +248,12 @@ Requires core.js and SelectBox.js.
|
||||
refresh_icons: function(field_id) {
|
||||
const from = document.getElementById(field_id + '_from');
|
||||
const to = document.getElementById(field_id + '_to');
|
||||
// Active if at least one item is selected
|
||||
document.getElementById(field_id + '_add').classList.toggle('active', SelectFilter.any_selected(from));
|
||||
document.getElementById(field_id + '_remove').classList.toggle('active', SelectFilter.any_selected(to));
|
||||
// Active if the corresponding box isn't empty
|
||||
document.getElementById(field_id + '_add_all').classList.toggle('active', from.querySelector('option'));
|
||||
document.getElementById(field_id + '_remove_all').classList.toggle('active', to.querySelector('option'));
|
||||
SelectFilter.refresh_filtered_warning(field_id);
|
||||
// Disabled if no items are selected.
|
||||
document.getElementById(field_id + '_add').disabled = !SelectFilter.any_selected(from);
|
||||
document.getElementById(field_id + '_remove').disabled = !SelectFilter.any_selected(to);
|
||||
// Disabled if the corresponding box is empty.
|
||||
document.getElementById(field_id + '_add_all').disabled = !from.querySelector('option');
|
||||
document.getElementById(field_id + '_remove_all').disabled = !to.querySelector('option');
|
||||
},
|
||||
filter_key_press: function(event, field_id, source, target) {
|
||||
const source_box = document.getElementById(field_id + source);
|
||||
|
@ -218,19 +218,16 @@ class AdminSeleniumTestCase(SeleniumTestCase, StaticLiveServerTestCase):
|
||||
"""
|
||||
self._assertOptionsValues("%s > option:checked" % selector, values)
|
||||
|
||||
def has_css_class(self, selector, klass):
|
||||
def is_disabled(self, selector):
|
||||
"""
|
||||
Return True if the element identified by `selector` has the CSS class
|
||||
`klass`.
|
||||
Return True if the element identified by `selector` has the `disabled`
|
||||
attribute.
|
||||
"""
|
||||
from selenium.webdriver.common.by import By
|
||||
|
||||
return (
|
||||
self.selenium.find_element(
|
||||
By.CSS_SELECTOR,
|
||||
selector,
|
||||
self.selenium.find_element(By.CSS_SELECTOR, selector).get_attribute(
|
||||
"disabled"
|
||||
)
|
||||
.get_attribute("class")
|
||||
.find(klass)
|
||||
!= -1
|
||||
== "true"
|
||||
)
|
||||
|
@ -1254,21 +1254,27 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase):
|
||||
self.arthur = Student.objects.create(name="Arthur")
|
||||
self.school = School.objects.create(name="School of Awesome")
|
||||
|
||||
def assertActiveButtons(
|
||||
self, mode, field_name, choose, remove, choose_all=None, remove_all=None
|
||||
def assertButtonsDisabled(
|
||||
self,
|
||||
mode,
|
||||
field_name,
|
||||
choose_btn_disabled=False,
|
||||
remove_btn_disabled=False,
|
||||
choose_all_btn_disabled=False,
|
||||
remove_all_btn_disabled=False,
|
||||
):
|
||||
choose_button = "#id_%s_add" % field_name
|
||||
choose_all_button = "#id_%s_add_all" % field_name
|
||||
remove_button = "#id_%s_remove" % field_name
|
||||
remove_all_button = "#id_%s_remove_all" % field_name
|
||||
self.assertEqual(self.has_css_class(choose_button, "active"), choose)
|
||||
self.assertEqual(self.has_css_class(remove_button, "active"), remove)
|
||||
self.assertEqual(self.is_disabled(choose_button), choose_btn_disabled)
|
||||
self.assertEqual(self.is_disabled(remove_button), remove_btn_disabled)
|
||||
if mode == "horizontal":
|
||||
self.assertEqual(
|
||||
self.has_css_class(choose_all_button, "active"), choose_all
|
||||
self.is_disabled(choose_all_button), choose_all_btn_disabled
|
||||
)
|
||||
self.assertEqual(
|
||||
self.has_css_class(remove_all_button, "active"), remove_all
|
||||
self.is_disabled(remove_all_button), remove_all_btn_disabled
|
||||
)
|
||||
|
||||
def execute_basic_operations(self, mode, field_name):
|
||||
@ -1296,7 +1302,14 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase):
|
||||
],
|
||||
)
|
||||
self.assertSelectOptions(to_box, [str(self.lisa.id), str(self.peter.id)])
|
||||
self.assertActiveButtons(mode, field_name, False, False, True, True)
|
||||
self.assertButtonsDisabled(
|
||||
mode,
|
||||
field_name,
|
||||
choose_btn_disabled=True,
|
||||
remove_btn_disabled=True,
|
||||
choose_all_btn_disabled=False,
|
||||
remove_all_btn_disabled=False,
|
||||
)
|
||||
|
||||
# Click 'Choose all' --------------------------------------------------
|
||||
if mode == "horizontal":
|
||||
@ -1323,7 +1336,14 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase):
|
||||
str(self.john.id),
|
||||
],
|
||||
)
|
||||
self.assertActiveButtons(mode, field_name, False, False, False, True)
|
||||
self.assertButtonsDisabled(
|
||||
mode,
|
||||
field_name,
|
||||
choose_btn_disabled=True,
|
||||
remove_btn_disabled=True,
|
||||
choose_all_btn_disabled=True,
|
||||
remove_all_btn_disabled=False,
|
||||
)
|
||||
|
||||
# Click 'Remove all' --------------------------------------------------
|
||||
if mode == "horizontal":
|
||||
@ -1350,7 +1370,14 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase):
|
||||
],
|
||||
)
|
||||
self.assertSelectOptions(to_box, [])
|
||||
self.assertActiveButtons(mode, field_name, False, False, True, False)
|
||||
self.assertButtonsDisabled(
|
||||
mode,
|
||||
field_name,
|
||||
choose_btn_disabled=True,
|
||||
remove_btn_disabled=True,
|
||||
choose_all_btn_disabled=False,
|
||||
remove_all_btn_disabled=True,
|
||||
)
|
||||
|
||||
# Choose some options ------------------------------------------------
|
||||
from_lisa_select_option = self.selenium.find_element(
|
||||
@ -1367,9 +1394,23 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase):
|
||||
self.select_option(from_box, str(self.jason.id))
|
||||
self.select_option(from_box, str(self.bob.id))
|
||||
self.select_option(from_box, str(self.john.id))
|
||||
self.assertActiveButtons(mode, field_name, True, False, True, False)
|
||||
self.assertButtonsDisabled(
|
||||
mode,
|
||||
field_name,
|
||||
choose_btn_disabled=False,
|
||||
remove_btn_disabled=True,
|
||||
choose_all_btn_disabled=False,
|
||||
remove_all_btn_disabled=True,
|
||||
)
|
||||
self.selenium.find_element(By.ID, choose_button).click()
|
||||
self.assertActiveButtons(mode, field_name, False, False, True, True)
|
||||
self.assertButtonsDisabled(
|
||||
mode,
|
||||
field_name,
|
||||
choose_btn_disabled=True,
|
||||
remove_btn_disabled=True,
|
||||
choose_all_btn_disabled=False,
|
||||
remove_all_btn_disabled=False,
|
||||
)
|
||||
|
||||
self.assertSelectOptions(
|
||||
from_box,
|
||||
@ -1402,9 +1443,23 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase):
|
||||
# Remove some options -------------------------------------------------
|
||||
self.select_option(to_box, str(self.lisa.id))
|
||||
self.select_option(to_box, str(self.bob.id))
|
||||
self.assertActiveButtons(mode, field_name, False, True, True, True)
|
||||
self.assertButtonsDisabled(
|
||||
mode,
|
||||
field_name,
|
||||
choose_btn_disabled=True,
|
||||
remove_btn_disabled=False,
|
||||
choose_all_btn_disabled=False,
|
||||
remove_all_btn_disabled=False,
|
||||
)
|
||||
self.selenium.find_element(By.ID, remove_button).click()
|
||||
self.assertActiveButtons(mode, field_name, False, False, True, True)
|
||||
self.assertButtonsDisabled(
|
||||
mode,
|
||||
field_name,
|
||||
choose_btn_disabled=True,
|
||||
remove_btn_disabled=True,
|
||||
choose_all_btn_disabled=False,
|
||||
remove_all_btn_disabled=False,
|
||||
)
|
||||
|
||||
self.assertSelectOptions(
|
||||
from_box,
|
||||
|
Loading…
Reference in New Issue
Block a user