mirror of
https://github.com/pi-hole/web.git
synced 2025-12-24 20:55:28 +00:00
Merge pull request #1186 from Th3M3/th3m3/improve_group-select
improve group selection
This commit is contained in:
@@ -26,6 +26,7 @@ function get_groups() {
|
||||
$(document).ready(function() {
|
||||
$("#btnAdd").on("click", addAdlist);
|
||||
|
||||
utils.bsSelect_defaults();
|
||||
get_groups();
|
||||
});
|
||||
|
||||
@@ -47,6 +48,8 @@ function initTable() {
|
||||
],
|
||||
drawCallback: function() {
|
||||
$('button[id^="deleteAdlist_"]').on("click", deleteAdlist);
|
||||
// Remove visible dropdown to prevent orphaning
|
||||
$("body > .bootstrap-select.dropdown").remove();
|
||||
},
|
||||
rowCallback: function(row, data) {
|
||||
$(row).attr("data-id", data.id);
|
||||
@@ -88,61 +91,73 @@ function initTable() {
|
||||
|
||||
$("td:eq(3)", row).empty();
|
||||
$("td:eq(3)", row).append(
|
||||
'<div id="selectHome_' +
|
||||
data.id +
|
||||
'">' +
|
||||
'<select id="multiselect_' +
|
||||
data.id +
|
||||
'" multiple="multiple"></select></div>'
|
||||
'<select class="selectpicker" id="multiselect_' + data.id + '" multiple></select>'
|
||||
);
|
||||
var selectEl = $("#multiselect_" + data.id, row);
|
||||
// Add all known groups
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
var extra = "";
|
||||
var data_sub = "";
|
||||
if (!groups[i].enabled) {
|
||||
extra = " (disabled)";
|
||||
data_sub = 'data-subtext="(disabled)"';
|
||||
}
|
||||
|
||||
selectEl.append(
|
||||
$("<option />")
|
||||
$("<option " + data_sub + "/>")
|
||||
.val(groups[i].id)
|
||||
.text(groups[i].name + extra)
|
||||
.text(groups[i].name)
|
||||
);
|
||||
}
|
||||
|
||||
// Select assigned groups
|
||||
selectEl.val(data.groups);
|
||||
// Initialize multiselect
|
||||
selectEl.multiselect({
|
||||
includeSelectAllOption: true,
|
||||
buttonContainer: '<div id="container_' + data.id + '" class="btn-group"/>',
|
||||
maxHeight: 200,
|
||||
onDropdownShown: function() {
|
||||
var el = $("#container_" + data.id);
|
||||
var top = el[0].getBoundingClientRect().top;
|
||||
var bottom = $(window).height() - top - el.height();
|
||||
if (bottom < 200) {
|
||||
el.addClass("dropup");
|
||||
// Initialize bootstrap-select
|
||||
selectEl
|
||||
// fix dropdown if it would stick out right of the viewport
|
||||
.on("show.bs.select", function() {
|
||||
var winWidth = $(window).width();
|
||||
var dropdownEl = $("body > .bootstrap-select.dropdown");
|
||||
if (dropdownEl.length > 0) {
|
||||
dropdownEl.removeClass("align-right");
|
||||
var width = dropdownEl.width();
|
||||
var left = dropdownEl.offset().left;
|
||||
if (left + width > winWidth) {
|
||||
dropdownEl.addClass("align-right");
|
||||
}
|
||||
}
|
||||
|
||||
if (bottom > 200) {
|
||||
el.removeClass("dropup");
|
||||
})
|
||||
.on("changed.bs.select", function() {
|
||||
// enable Apply button
|
||||
if ($(ApplyBtn).prop("disabled")) {
|
||||
$(ApplyBtn)
|
||||
.addClass("btn-success")
|
||||
.prop("disabled", false)
|
||||
.on("click", function() {
|
||||
editAdlist.call(selectEl);
|
||||
});
|
||||
}
|
||||
})
|
||||
.on("hide.bs.select", function() {
|
||||
// Restore values if drop-down menu is closed without clicking the Apply button
|
||||
if (!$(ApplyBtn).prop("disabled")) {
|
||||
$(this)
|
||||
.val(data.groups)
|
||||
.selectpicker("refresh");
|
||||
$(ApplyBtn)
|
||||
.removeClass("btn-success")
|
||||
.prop("disabled", true)
|
||||
.off("click");
|
||||
}
|
||||
})
|
||||
.selectpicker()
|
||||
.siblings(".dropdown-menu")
|
||||
.find(".bs-actionsbox")
|
||||
.prepend(
|
||||
'<button type="button" id=btn_apply_' +
|
||||
data.id +
|
||||
' class="btn btn-block btn-sm" disabled>Apply</button>'
|
||||
);
|
||||
|
||||
var offset = el.offset();
|
||||
$("body").append(el);
|
||||
el.css("position", "absolute");
|
||||
el.css("top", offset.top + "px");
|
||||
el.css("left", offset.left + "px");
|
||||
},
|
||||
onDropdownHide: function() {
|
||||
var el = $("#container_" + data.id);
|
||||
var home = $("#selectHome_" + data.id);
|
||||
home.append(el);
|
||||
el.removeAttr("style");
|
||||
}
|
||||
});
|
||||
selectEl.on("change", editAdlist);
|
||||
var ApplyBtn = "#btn_apply_" + data.id;
|
||||
|
||||
var button =
|
||||
'<button class="btn btn-danger btn-xs" type="button" id="deleteAdlist_' +
|
||||
@@ -230,6 +245,7 @@ function addAdlist() {
|
||||
"Successfully added adlist",
|
||||
address
|
||||
);
|
||||
table.ajax.reload(null, false);
|
||||
$("#new_address").val("");
|
||||
$("#new_comment").val("");
|
||||
table.ajax.reload();
|
||||
@@ -304,6 +320,7 @@ function editAdlist() {
|
||||
"Successfully " + done + " adlist ",
|
||||
address
|
||||
);
|
||||
table.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert(
|
||||
"error",
|
||||
@@ -350,7 +367,8 @@ function deleteAdlist() {
|
||||
table
|
||||
.row(tr)
|
||||
.remove()
|
||||
.draw(false);
|
||||
.draw(false)
|
||||
.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while deleting adlist with ID " + id, response.message);
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ $(document).ready(function() {
|
||||
$("#btnAdd").on("click", addClient);
|
||||
|
||||
reload_client_suggestions();
|
||||
utils.bsSelect_defaults();
|
||||
get_groups();
|
||||
|
||||
$("#select").on("change", function() {
|
||||
@@ -90,6 +91,8 @@ function initTable() {
|
||||
],
|
||||
drawCallback: function() {
|
||||
$('button[id^="deleteClient_"]').on("click", deleteClient);
|
||||
// Remove visible dropdown to prevent orphaning
|
||||
$("body > .bootstrap-select.dropdown").remove();
|
||||
},
|
||||
rowCallback: function(row, data) {
|
||||
$(row).attr("data-id", data.id);
|
||||
@@ -126,61 +129,73 @@ function initTable() {
|
||||
|
||||
$("td:eq(2)", row).empty();
|
||||
$("td:eq(2)", row).append(
|
||||
'<div id="selectHome_' +
|
||||
data.id +
|
||||
'">' +
|
||||
'<select id="multiselect_' +
|
||||
data.id +
|
||||
'" multiple="multiple"></select></div>'
|
||||
'<select class="selectpicker" id="multiselect_' + data.id + '" multiple></select>'
|
||||
);
|
||||
var selectEl = $("#multiselect_" + data.id, row);
|
||||
// Add all known groups
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
var extra = "";
|
||||
var data_sub = "";
|
||||
if (!groups[i].enabled) {
|
||||
extra = " (disabled)";
|
||||
data_sub = 'data-subtext="(disabled)"';
|
||||
}
|
||||
|
||||
selectEl.append(
|
||||
$("<option />")
|
||||
$("<option " + data_sub + "/>")
|
||||
.val(groups[i].id)
|
||||
.text(groups[i].name + extra)
|
||||
.text(groups[i].name)
|
||||
);
|
||||
}
|
||||
|
||||
// Select assigned groups
|
||||
selectEl.val(data.groups);
|
||||
// Initialize multiselect
|
||||
selectEl.multiselect({
|
||||
includeSelectAllOption: true,
|
||||
buttonContainer: '<div id="container_' + data.id + '" class="btn-group"/>',
|
||||
maxHeight: 200,
|
||||
onDropdownShown: function() {
|
||||
var el = $("#container_" + data.id);
|
||||
var top = el[0].getBoundingClientRect().top;
|
||||
var bottom = $(window).height() - top - el.height();
|
||||
if (bottom < 200) {
|
||||
el.addClass("dropup");
|
||||
// Initialize bootstrap-select
|
||||
selectEl
|
||||
// fix dropdown if it would stick out right of the viewport
|
||||
.on("show.bs.select", function() {
|
||||
var winWidth = $(window).width();
|
||||
var dropdownEl = $("body > .bootstrap-select.dropdown");
|
||||
if (dropdownEl.length > 0) {
|
||||
dropdownEl.removeClass("align-right");
|
||||
var width = dropdownEl.width();
|
||||
var left = dropdownEl.offset().left;
|
||||
if (left + width > winWidth) {
|
||||
dropdownEl.addClass("align-right");
|
||||
}
|
||||
}
|
||||
|
||||
if (bottom > 200) {
|
||||
el.removeClass("dropup");
|
||||
})
|
||||
.on("changed.bs.select", function() {
|
||||
// enable Apply button
|
||||
if ($(ApplyBtn).prop("disabled")) {
|
||||
$(ApplyBtn)
|
||||
.addClass("btn-success")
|
||||
.prop("disabled", false)
|
||||
.on("click", function() {
|
||||
editClient.call(selectEl);
|
||||
});
|
||||
}
|
||||
})
|
||||
.on("hide.bs.select", function() {
|
||||
// Restore values if drop-down menu is closed without clicking the Apply button
|
||||
if (!$(ApplyBtn).prop("disabled")) {
|
||||
$(this)
|
||||
.val(data.groups)
|
||||
.selectpicker("refresh");
|
||||
$(ApplyBtn)
|
||||
.removeClass("btn-success")
|
||||
.prop("disabled", true)
|
||||
.off("click");
|
||||
}
|
||||
})
|
||||
.selectpicker()
|
||||
.siblings(".dropdown-menu")
|
||||
.find(".bs-actionsbox")
|
||||
.prepend(
|
||||
'<button type="button" id=btn_apply_' +
|
||||
data.id +
|
||||
' class="btn btn-block btn-sm" disabled>Apply</button>'
|
||||
);
|
||||
|
||||
var offset = el.offset();
|
||||
$("body").append(el);
|
||||
el.css("position", "absolute");
|
||||
el.css("top", offset.top + "px");
|
||||
el.css("left", offset.left + "px");
|
||||
},
|
||||
onDropdownHide: function() {
|
||||
var el = $("#container" + data.id);
|
||||
var home = $("#selectHome" + data.id);
|
||||
home.append(el);
|
||||
el.removeAttr("style");
|
||||
}
|
||||
});
|
||||
selectEl.on("change", editClient);
|
||||
var ApplyBtn = "#btn_apply_" + data.id;
|
||||
|
||||
var button =
|
||||
'<button class="btn btn-danger btn-xs" type="button" id="deleteClient_' +
|
||||
@@ -278,7 +293,7 @@ function addClient() {
|
||||
if (response.success) {
|
||||
utils.showAlert("success", "glyphicon glyphicon-plus", "Successfully added client", ip);
|
||||
reload_client_suggestions();
|
||||
table.ajax.reload();
|
||||
table.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while adding new client", response.message);
|
||||
}
|
||||
@@ -339,10 +354,11 @@ function editClient() {
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-plus",
|
||||
"glyphicon glyphicon-pencil",
|
||||
"Successfully " + done + " client",
|
||||
ip_name
|
||||
);
|
||||
table.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert(
|
||||
"error",
|
||||
@@ -394,7 +410,8 @@ function deleteClient() {
|
||||
table
|
||||
.row(tr)
|
||||
.remove()
|
||||
.draw(false);
|
||||
.draw(false)
|
||||
.ajax.reload(null, false);
|
||||
reload_client_suggestions();
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while deleting client with ID " + id, response.message);
|
||||
|
||||
@@ -129,6 +129,26 @@ function validateIPv6CIDR(ip) {
|
||||
return ipv6validator.test(ip);
|
||||
}
|
||||
|
||||
function bsSelect_defaults() {
|
||||
// set bootstrap-select defaults
|
||||
var pickerDEFAULTS = $.fn.selectpicker.Constructor.DEFAULTS;
|
||||
pickerDEFAULTS.noneSelectedText = "none selected";
|
||||
pickerDEFAULTS.selectedTextFormat = "count > 1";
|
||||
pickerDEFAULTS.actionsBox = true;
|
||||
pickerDEFAULTS.width = "fit";
|
||||
pickerDEFAULTS.container = "body";
|
||||
pickerDEFAULTS.dropdownAlignRight = "auto";
|
||||
pickerDEFAULTS.selectAllText = "All";
|
||||
pickerDEFAULTS.deselectAllText = "None";
|
||||
pickerDEFAULTS.countSelectedText = function(num, total) {
|
||||
if (num === total) {
|
||||
return "All selected (" + num + ")";
|
||||
}
|
||||
|
||||
return num + " selected";
|
||||
};
|
||||
}
|
||||
|
||||
window.utils = (function() {
|
||||
return {
|
||||
showAlert: showAlert,
|
||||
@@ -136,6 +156,7 @@ window.utils = (function() {
|
||||
disableAll: disableAll,
|
||||
enableAll: enableAll,
|
||||
validateIPv4CIDR: validateIPv4CIDR,
|
||||
validateIPv6CIDR: validateIPv6CIDR
|
||||
validateIPv6CIDR: validateIPv6CIDR,
|
||||
bsSelect_defaults: bsSelect_defaults
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -55,6 +55,7 @@ $(document).ready(function() {
|
||||
|
||||
$("#add2black, #add2white").on("click", addDomain);
|
||||
|
||||
utils.bsSelect_defaults();
|
||||
get_groups();
|
||||
});
|
||||
|
||||
@@ -77,6 +78,8 @@ function initTable() {
|
||||
],
|
||||
drawCallback: function() {
|
||||
$('button[id^="deleteDomain_"]').on("click", deleteDomain);
|
||||
// Remove visible dropdown to prevent orphaning
|
||||
$("body > .bootstrap-select.dropdown").remove();
|
||||
},
|
||||
rowCallback: function(row, data) {
|
||||
$(row).attr("data-id", data.id);
|
||||
@@ -153,63 +156,75 @@ function initTable() {
|
||||
if (table.column(5).visible()) {
|
||||
$("td:eq(4)", row).empty();
|
||||
$("td:eq(4)", row).append(
|
||||
'<div id="selectHome_' +
|
||||
data.id +
|
||||
'">' +
|
||||
'<select id="multiselect_' +
|
||||
data.id +
|
||||
'" multiple="multiple"></select></div>'
|
||||
'<select class="selectpicker" id="multiselect_' + data.id + '" multiple></select>'
|
||||
);
|
||||
var selectEl = $("#multiselect_" + data.id, row);
|
||||
// Add all known groups
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
var extra = "";
|
||||
var data_sub = "";
|
||||
if (!groups[i].enabled) {
|
||||
extra = " (disabled)";
|
||||
data_sub = 'data-subtext="(disabled)"';
|
||||
}
|
||||
|
||||
selectEl.append(
|
||||
$("<option />")
|
||||
$("<option " + data_sub + "/>")
|
||||
.val(groups[i].id)
|
||||
.text(groups[i].name + extra)
|
||||
.text(groups[i].name)
|
||||
);
|
||||
}
|
||||
|
||||
// Select assigned groups
|
||||
selectEl.val(data.groups);
|
||||
// Initialize multiselect
|
||||
selectEl.multiselect({
|
||||
includeSelectAllOption: true,
|
||||
buttonContainer: '<div id="container_' + data.id + '" class="btn-group"/>',
|
||||
maxHeight: 200,
|
||||
onDropdownShown: function() {
|
||||
var el = $("#container_" + data.id);
|
||||
var top = el[0].getBoundingClientRect().top;
|
||||
var bottom = $(window).height() - top - el.height();
|
||||
if (bottom < 200) {
|
||||
el.addClass("dropup");
|
||||
// Initialize bootstrap-select
|
||||
selectEl
|
||||
// fix dropdown if it would stick out right of the viewport
|
||||
.on("show.bs.select", function() {
|
||||
var winWidth = $(window).width();
|
||||
var dropdownEl = $("body > .bootstrap-select.dropdown");
|
||||
if (dropdownEl.length > 0) {
|
||||
dropdownEl.removeClass("align-right");
|
||||
var width = dropdownEl.width();
|
||||
var left = dropdownEl.offset().left;
|
||||
if (left + width > winWidth) {
|
||||
dropdownEl.addClass("align-right");
|
||||
}
|
||||
}
|
||||
|
||||
if (bottom > 200) {
|
||||
el.removeClass("dropup");
|
||||
})
|
||||
.on("changed.bs.select", function() {
|
||||
// enable Apply button
|
||||
if ($(ApplyBtn).prop("disabled")) {
|
||||
$(ApplyBtn)
|
||||
.addClass("btn-success")
|
||||
.prop("disabled", false)
|
||||
.on("click", function() {
|
||||
editDomain.call(selectEl);
|
||||
});
|
||||
}
|
||||
|
||||
var offset = el.offset();
|
||||
$("body").append(el);
|
||||
el.css("position", "absolute");
|
||||
el.css("top", offset.top + "px");
|
||||
el.css("left", offset.left + "px");
|
||||
},
|
||||
onDropdownHide: function() {
|
||||
var el = $("#container_" + data.id);
|
||||
var home = $("#selectHome_" + data.id);
|
||||
home.append(el);
|
||||
el.removeAttr("style");
|
||||
}
|
||||
});
|
||||
selectEl.on("change", editDomain);
|
||||
})
|
||||
.on("hide.bs.select", function() {
|
||||
// Restore values if drop-down menu is closed without clicking the Apply button
|
||||
if (!$(ApplyBtn).prop("disabled")) {
|
||||
$(this)
|
||||
.val(data.groups)
|
||||
.selectpicker("refresh");
|
||||
$(ApplyBtn)
|
||||
.removeClass("btn-success")
|
||||
.prop("disabled", true)
|
||||
.off("click");
|
||||
}
|
||||
})
|
||||
.selectpicker()
|
||||
.siblings(".dropdown-menu")
|
||||
.find(".bs-actionsbox")
|
||||
.prepend(
|
||||
'<button type="button" id=btn_apply_' +
|
||||
data.id +
|
||||
' class="btn btn-block btn-sm" disabled>Apply</button>'
|
||||
);
|
||||
}
|
||||
|
||||
var ApplyBtn = "#btn_apply_" + data.id;
|
||||
|
||||
// Highlight row (if url parameter "domainid=" is used)
|
||||
if ("domainid" in GETDict && data.id === parseInt(GETDict.domainid)) {
|
||||
$(row)
|
||||
@@ -364,7 +379,7 @@ function addDomain() {
|
||||
domainEl.val("");
|
||||
commentEl.val("");
|
||||
wildcardEl.prop("checked", false);
|
||||
table.ajax.reload();
|
||||
table.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while adding new " + domain_regex, response.message);
|
||||
}
|
||||
@@ -456,6 +471,7 @@ function editDomain() {
|
||||
"Successfully " + done + " " + domain_regex,
|
||||
domain
|
||||
);
|
||||
table.ajax.reload(null, false);
|
||||
} else
|
||||
utils.showAlert(
|
||||
"error",
|
||||
@@ -509,7 +525,8 @@ function deleteDomain() {
|
||||
table
|
||||
.row(tr)
|
||||
.remove()
|
||||
.draw(false);
|
||||
.draw(false)
|
||||
.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert(
|
||||
"error",
|
||||
|
||||
@@ -223,8 +223,8 @@
|
||||
<script src="scripts/vendor/bootstrap-notify.min.js"></script>
|
||||
|
||||
<?php if(in_array($scriptname, array("groups.php", "groups-clients.php", "groups-domains.php", "groups-adlists.php"))){ ?>
|
||||
<script src="style/vendor/bootstrap/js/bootstrap-multiselect.js"></script>
|
||||
<link rel="stylesheet" href="style/vendor/bootstrap/css/bootstrap-multiselect.css">
|
||||
<script src="style/vendor/bootstrap/js/bootstrap-select.min.js"></script>
|
||||
<link rel="stylesheet" href="style/vendor/bootstrap/css/bootstrap-select.min.css">
|
||||
<script src="style/vendor/bootstrap/js/bootstrap-toggle.min.js"></script>
|
||||
<link rel="stylesheet" href="style/vendor/bootstrap/css/bootstrap-toggle.min.css">
|
||||
<script src="scripts/vendor/moment.min.js"></script>
|
||||
|
||||
@@ -260,4 +260,9 @@ code.breakall
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bootstrap-select.bs-container.align-right {
|
||||
left: unset !important;
|
||||
right: 10px;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
span.multiselect-native-select{position:relative}span.multiselect-native-select select{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px -1px -1px -3px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;left:50%;top:30px}.multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .input-group{margin:5px}.multiselect-container>li{padding:0}.multiselect-container>li>a.multiselect-all label{font-weight:700}.multiselect-container>li.multiselect-group label{margin:0;padding:3px 20px 3px 20px;height:100%;font-weight:700}.multiselect-container>li.multiselect-group-clickable label{cursor:pointer}.multiselect-container>li>a{padding:0}.multiselect-container>li>a>label{margin:0;height:100%;cursor:pointer;font-weight:400;padding:3px 20px 3px 40px}.multiselect-container>li>a>label.radio,.multiselect-container>li>a>label.checkbox{margin:0}.multiselect-container>li>a>label>input[type=checkbox]{margin-bottom:5px}.btn-group>.btn-group:nth-child(2)>.multiselect.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.form-inline .multiselect-container label.checkbox,.form-inline .multiselect-container label.radio{padding:3px 20px 3px 40px}.form-inline .multiselect-container li a label.checkbox input[type=checkbox],.form-inline .multiselect-container li a label.radio input[type=radio]{margin-left:-20px;margin-right:0}
|
||||
6
style/vendor/bootstrap/css/bootstrap-select.min.css
vendored
Normal file
6
style/vendor/bootstrap/css/bootstrap-select.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1716
style/vendor/bootstrap/js/bootstrap-multiselect.js
vendored
1716
style/vendor/bootstrap/js/bootstrap-multiselect.js
vendored
File diff suppressed because it is too large
Load Diff
9
style/vendor/bootstrap/js/bootstrap-select.min.js
vendored
Normal file
9
style/vendor/bootstrap/js/bootstrap-select.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user