mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #31523 -- Removed jQuery dependency from actions.js.
This commit is contained in:
parent
074844e947
commit
30e59705fc
@ -211,6 +211,10 @@ p img, h1 img, h2 img, h3 img, h4 img, td img {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* TABLES */
|
/* TABLES */
|
||||||
|
|
||||||
table {
|
table {
|
||||||
|
@ -300,7 +300,6 @@
|
|||||||
#changelist .actions span.question {
|
#changelist .actions span.question {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
margin: 0 0.5em;
|
margin: 0 0.5em;
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#changelist .actions:last-child {
|
#changelist .actions:last-child {
|
||||||
|
@ -22,10 +22,6 @@ form .form-row p {
|
|||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FORM LABELS */
|
/* FORM LABELS */
|
||||||
|
|
||||||
label {
|
label {
|
||||||
|
@ -1,154 +1,170 @@
|
|||||||
/*global gettext, interpolate, ngettext*/
|
/*global gettext, interpolate, ngettext*/
|
||||||
'use strict';
|
'use strict';
|
||||||
{
|
{
|
||||||
const $ = django.jQuery;
|
function show(selector) {
|
||||||
let lastChecked;
|
document.querySelectorAll(selector).forEach(function(el) {
|
||||||
|
el.classList.remove('hidden');
|
||||||
$.fn.actions = function(opts) {
|
});
|
||||||
const options = $.extend({}, $.fn.actions.defaults, opts);
|
|
||||||
const actionCheckboxes = $(this);
|
|
||||||
let list_editable_changed = false;
|
|
||||||
const showQuestion = function() {
|
|
||||||
$(options.acrossClears).hide();
|
|
||||||
$(options.acrossQuestions).show();
|
|
||||||
$(options.allContainer).hide();
|
|
||||||
},
|
|
||||||
showClear = function() {
|
|
||||||
$(options.acrossClears).show();
|
|
||||||
$(options.acrossQuestions).hide();
|
|
||||||
$(options.actionContainer).toggleClass(options.selectedClass);
|
|
||||||
$(options.allContainer).show();
|
|
||||||
$(options.counterContainer).hide();
|
|
||||||
},
|
|
||||||
reset = function() {
|
|
||||||
$(options.acrossClears).hide();
|
|
||||||
$(options.acrossQuestions).hide();
|
|
||||||
$(options.allContainer).hide();
|
|
||||||
$(options.counterContainer).show();
|
|
||||||
},
|
|
||||||
clearAcross = function() {
|
|
||||||
reset();
|
|
||||||
$(options.acrossInput).val(0);
|
|
||||||
$(options.actionContainer).removeClass(options.selectedClass);
|
|
||||||
},
|
|
||||||
checker = function(checked) {
|
|
||||||
if (checked) {
|
|
||||||
showQuestion();
|
|
||||||
} else {
|
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
$(actionCheckboxes).prop("checked", checked)
|
|
||||||
.parent().parent().toggleClass(options.selectedClass, checked);
|
function hide(selector) {
|
||||||
},
|
document.querySelectorAll(selector).forEach(function(el) {
|
||||||
updateCounter = function() {
|
el.classList.add('hidden');
|
||||||
const sel = $(actionCheckboxes).filter(":checked").length;
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showQuestion(options) {
|
||||||
|
hide(options.acrossClears);
|
||||||
|
show(options.acrossQuestions);
|
||||||
|
hide(options.allContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showClear(options) {
|
||||||
|
show(options.acrossClears);
|
||||||
|
hide(options.acrossQuestions);
|
||||||
|
document.querySelector(options.actionContainer).classList.remove(options.selectedClass);
|
||||||
|
show(options.allContainer);
|
||||||
|
hide(options.counterContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset(options) {
|
||||||
|
hide(options.acrossClears);
|
||||||
|
hide(options.acrossQuestions);
|
||||||
|
hide(options.allContainer);
|
||||||
|
show(options.counterContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearAcross(options) {
|
||||||
|
reset(options);
|
||||||
|
document.querySelector(options.acrossInput).value = 0;
|
||||||
|
document.querySelector(options.actionContainer).classList.remove(options.selectedClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checker(actionCheckboxes, options, checked) {
|
||||||
|
if (checked) {
|
||||||
|
showQuestion(options);
|
||||||
|
} else {
|
||||||
|
reset(options);
|
||||||
|
}
|
||||||
|
actionCheckboxes.forEach(function(el) {
|
||||||
|
el.checked = checked;
|
||||||
|
el.closest('tr').classList.toggle(options.selectedClass, checked);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCounter(actionCheckboxes, options) {
|
||||||
|
const sel = Array.from(actionCheckboxes).filter(function(el) {
|
||||||
|
return el.checked;
|
||||||
|
}).length;
|
||||||
|
const counter = document.querySelector(options.counterContainer);
|
||||||
// data-actions-icnt is defined in the generated HTML
|
// data-actions-icnt is defined in the generated HTML
|
||||||
// and contains the total amount of objects in the queryset
|
// and contains the total amount of objects in the queryset
|
||||||
const actions_icnt = $('.action-counter').data('actionsIcnt');
|
const actions_icnt = Number(counter.dataset.actionsIcnt);
|
||||||
$(options.counterContainer).html(interpolate(
|
counter.textContent = interpolate(
|
||||||
ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), {
|
ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), {
|
||||||
sel: sel,
|
sel: sel,
|
||||||
cnt: actions_icnt
|
cnt: actions_icnt
|
||||||
}, true));
|
}, true);
|
||||||
$(options.allToggle).prop("checked", function() {
|
const allToggle = document.getElementById(options.allToggleId);
|
||||||
let value;
|
allToggle.checked = sel === actionCheckboxes.length;
|
||||||
if (sel === actionCheckboxes.length) {
|
if (allToggle.checked) {
|
||||||
value = true;
|
showQuestion(options);
|
||||||
showQuestion();
|
|
||||||
} else {
|
} else {
|
||||||
value = false;
|
clearAcross(options);
|
||||||
clearAcross();
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// Show counter by default
|
|
||||||
$(options.counterContainer).show();
|
|
||||||
// Check state of checkboxes and reinit state if needed
|
|
||||||
$(this).filter(":checked").each(function(i) {
|
|
||||||
$(this).parent().parent().toggleClass(options.selectedClass);
|
|
||||||
updateCounter();
|
|
||||||
if ($(options.acrossInput).val() === 1) {
|
|
||||||
showClear();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$(options.allToggle).show().on('click', function() {
|
|
||||||
checker($(this).prop("checked"));
|
|
||||||
updateCounter();
|
|
||||||
});
|
|
||||||
$("a", options.acrossQuestions).on('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
$(options.acrossInput).val(1);
|
|
||||||
showClear();
|
|
||||||
});
|
|
||||||
$("a", options.acrossClears).on('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
$(options.allToggle).prop("checked", false);
|
|
||||||
clearAcross();
|
|
||||||
checker(0);
|
|
||||||
updateCounter();
|
|
||||||
});
|
|
||||||
lastChecked = null;
|
|
||||||
$(actionCheckboxes).on('click', function(event) {
|
|
||||||
if (!event) { event = window.event; }
|
|
||||||
const target = event.target ? event.target : event.srcElement;
|
|
||||||
if (lastChecked && $.data(lastChecked) !== $.data(target) && event.shiftKey === true) {
|
|
||||||
let inrange = false;
|
|
||||||
$(lastChecked).prop("checked", target.checked)
|
|
||||||
.parent().parent().toggleClass(options.selectedClass, target.checked);
|
|
||||||
$(actionCheckboxes).each(function() {
|
|
||||||
if ($.data(this) === $.data(lastChecked) || $.data(this) === $.data(target)) {
|
|
||||||
inrange = (inrange) ? false : true;
|
|
||||||
}
|
|
||||||
if (inrange) {
|
|
||||||
$(this).prop("checked", target.checked)
|
|
||||||
.parent().parent().toggleClass(options.selectedClass, target.checked);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$(target).parent().parent().toggleClass(options.selectedClass, target.checked);
|
|
||||||
lastChecked = target;
|
|
||||||
updateCounter();
|
|
||||||
});
|
|
||||||
$('form#changelist-form table#result_list tr').on('change', 'td:gt(0) :input', function() {
|
|
||||||
list_editable_changed = true;
|
|
||||||
});
|
|
||||||
$('form#changelist-form button[name="index"]').on('click', function(event) {
|
|
||||||
if (list_editable_changed) {
|
|
||||||
return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('form#changelist-form input[name="_save"]').on('click', function(event) {
|
|
||||||
let action_changed = false;
|
|
||||||
$('select option:selected', options.actionContainer).each(function() {
|
|
||||||
if ($(this).val()) {
|
|
||||||
action_changed = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (action_changed) {
|
|
||||||
if (list_editable_changed) {
|
|
||||||
return confirm(gettext("You have selected an action, but you haven’t saved your changes to individual fields yet. Please click OK to save. You’ll need to re-run the action."));
|
|
||||||
} else {
|
|
||||||
return confirm(gettext("You have selected an action, and you haven’t made any changes on individual fields. You’re probably looking for the Go button rather than the Save button."));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
};
|
const defaults = {
|
||||||
/* Setup plugin defaults */
|
|
||||||
$.fn.actions.defaults = {
|
|
||||||
actionContainer: "div.actions",
|
actionContainer: "div.actions",
|
||||||
counterContainer: "span.action-counter",
|
counterContainer: "span.action-counter",
|
||||||
allContainer: "div.actions span.all",
|
allContainer: "div.actions span.all",
|
||||||
acrossInput: "div.actions input.select-across",
|
acrossInput: "div.actions input.select-across",
|
||||||
acrossQuestions: "div.actions span.question",
|
acrossQuestions: "div.actions span.question",
|
||||||
acrossClears: "div.actions span.clear",
|
acrossClears: "div.actions span.clear",
|
||||||
allToggle: "#action-toggle",
|
allToggleId: "action-toggle",
|
||||||
selectedClass: "selected"
|
selectedClass: "selected"
|
||||||
};
|
};
|
||||||
$(document).ready(function() {
|
|
||||||
const $actionsEls = $('tr input.action-select');
|
window.Actions = function(actionCheckboxes, options) {
|
||||||
if ($actionsEls.length > 0) {
|
options = Object.assign({}, defaults, options);
|
||||||
$actionsEls.actions();
|
let list_editable_changed = false;
|
||||||
|
|
||||||
|
document.getElementById(options.allToggleId).addEventListener('click', function(event) {
|
||||||
|
checker(actionCheckboxes, options, this.checked);
|
||||||
|
updateCounter(actionCheckboxes, options);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll(options.acrossQuestions + " a").forEach(function(el) {
|
||||||
|
el.addEventListener('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const acrossInput = document.querySelector(options.acrossInput);
|
||||||
|
acrossInput.value = 1;
|
||||||
|
showClear(options);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll(options.acrossClears + " a").forEach(function(el) {
|
||||||
|
el.addEventListener('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
document.getElementById(options.allToggleId).checked = false;
|
||||||
|
clearAcross(options);
|
||||||
|
checker(actionCheckboxes, options, false);
|
||||||
|
updateCounter(actionCheckboxes, options);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Array.from(document.getElementById('result_list').tBodies).forEach(function(el) {
|
||||||
|
el.addEventListener('change', function(event) {
|
||||||
|
const target = event.target;
|
||||||
|
if (target.classList.contains('action-select')) {
|
||||||
|
target.closest('tr').classList.toggle(options.selectedClass, target.checked);
|
||||||
|
updateCounter(actionCheckboxes, options);
|
||||||
|
} else {
|
||||||
|
list_editable_changed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector('#changelist-form button[name=index]').addEventListener('click', function() {
|
||||||
|
if (list_editable_changed) {
|
||||||
|
const confirmed = confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
|
||||||
|
if (!confirmed) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const el = document.querySelector('#changelist-form input[name=_save]');
|
||||||
|
// The button does not exist if no fields are editable.
|
||||||
|
if (el) {
|
||||||
|
el.addEventListener('click', function(event) {
|
||||||
|
if (document.querySelector('[name=action]').value) {
|
||||||
|
const text = list_editable_changed
|
||||||
|
? gettext("You have selected an action, but you haven’t saved your changes to individual fields yet. Please click OK to save. You’ll need to re-run the action.")
|
||||||
|
: gettext("You have selected an action, and you haven’t made any changes on individual fields. You’re probably looking for the Go button rather than the Save button.");
|
||||||
|
if (!confirm(text)) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call function fn when the DOM is loaded and ready. If it is already
|
||||||
|
// loaded, call the function now.
|
||||||
|
// http://youmightnotneedjquery.com/#ready
|
||||||
|
function ready(fn) {
|
||||||
|
if (document.readyState !== 'loading') {
|
||||||
|
fn();
|
||||||
|
} else {
|
||||||
|
document.addEventListener('DOMContentLoaded', fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ready(function() {
|
||||||
|
const actionsEls = document.querySelectorAll('tr input.action-select');
|
||||||
|
if (actionsEls.length > 0) {
|
||||||
|
Actions(actionsEls);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,11 @@
|
|||||||
{% if actions_selection_counter %}
|
{% if actions_selection_counter %}
|
||||||
<span class="action-counter" data-actions-icnt="{{ cl.result_list|length }}">{{ selection_note }}</span>
|
<span class="action-counter" data-actions-icnt="{{ cl.result_list|length }}">{{ selection_note }}</span>
|
||||||
{% if cl.result_count != cl.result_list|length %}
|
{% if cl.result_count != cl.result_list|length %}
|
||||||
<span class="all">{{ selection_note_all }}</span>
|
<span class="all hidden">{{ selection_note_all }}</span>
|
||||||
<span class="question">
|
<span class="question hidden">
|
||||||
<a href="#" title="{% translate "Click here to select the objects across all pages" %}">{% blocktranslate with cl.result_count as total_count %}Select all {{ total_count }} {{ module_name }}{% endblocktranslate %}</a>
|
<a href="#" title="{% translate "Click here to select the objects across all pages" %}">{% blocktranslate with cl.result_count as total_count %}Select all {{ total_count }} {{ module_name }}{% endblocktranslate %}</a>
|
||||||
</span>
|
</span>
|
||||||
<span class="clear"><a href="#">{% translate "Clear selection" %}</a></span>
|
<span class="clear hidden"><a href="#">{% translate "Clear selection" %}</a></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -11,7 +11,7 @@ QUnit.module('admin.actions', {
|
|||||||
const $ = django.jQuery;
|
const $ = django.jQuery;
|
||||||
$('#qunit-fixture').append($('#result-table').text());
|
$('#qunit-fixture').append($('#result-table').text());
|
||||||
|
|
||||||
$('tr input.action-select').actions();
|
Actions(document.querySelectorAll('tr input.action-select'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
<div id="qunit-fixture">
|
<div id="qunit-fixture">
|
||||||
</div>
|
</div>
|
||||||
<script type="text/html" id="result-table">
|
<script type="text/html" id="result-table">
|
||||||
|
<form id="changelist-form">
|
||||||
|
<button type="submit" class="button" name="index" value="0">Go</button>
|
||||||
|
<span class="action-counter" data-actions-icnt="100"></span>
|
||||||
<table id="result_list">
|
<table id="result_list">
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
@ -23,6 +26,8 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
<input type="submit" name="_save" value="Save">
|
||||||
|
</form>
|
||||||
</script>
|
</script>
|
||||||
<script type="text/html" id="tabular-formset">
|
<script type="text/html" id="tabular-formset">
|
||||||
<input id="id_first-TOTAL_FORMS" value="1">
|
<input id="id_first-TOTAL_FORMS" value="1">
|
||||||
|
Loading…
Reference in New Issue
Block a user