actions.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*global gettext, interpolate, ngettext*/
  2. (function($) {
  3. 'use strict';
  4. var lastChecked;
  5. $.fn.actions = function(opts) {
  6. var options = $.extend({}, $.fn.actions.defaults, opts);
  7. var actionCheckboxes = $(this);
  8. var list_editable_changed = false;
  9. var showQuestion = function() {
  10. $(options.acrossClears).hide();
  11. $(options.acrossQuestions).show();
  12. $(options.allContainer).hide();
  13. },
  14. showClear = function() {
  15. $(options.acrossClears).show();
  16. $(options.acrossQuestions).hide();
  17. $(options.actionContainer).toggleClass(options.selectedClass);
  18. $(options.allContainer).show();
  19. $(options.counterContainer).hide();
  20. },
  21. reset = function() {
  22. $(options.acrossClears).hide();
  23. $(options.acrossQuestions).hide();
  24. $(options.allContainer).hide();
  25. $(options.counterContainer).show();
  26. },
  27. clearAcross = function() {
  28. reset();
  29. $(options.acrossInput).val(0);
  30. $(options.actionContainer).removeClass(options.selectedClass);
  31. },
  32. checker = function(checked) {
  33. if (checked) {
  34. showQuestion();
  35. } else {
  36. reset();
  37. }
  38. $(actionCheckboxes).prop("checked", checked)
  39. .parent().parent().toggleClass(options.selectedClass, checked);
  40. },
  41. updateCounter = function() {
  42. var sel = $(actionCheckboxes).filter(":checked").length;
  43. // data-actions-icnt is defined in the generated HTML
  44. // and contains the total amount of objects in the queryset
  45. var actions_icnt = $('.action-counter').data('actionsIcnt');
  46. $(options.counterContainer).html(interpolate(
  47. ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), {
  48. sel: sel,
  49. cnt: actions_icnt
  50. }, true));
  51. $(options.allToggle).prop("checked", function() {
  52. var value;
  53. if (sel === actionCheckboxes.length) {
  54. value = true;
  55. showQuestion();
  56. } else {
  57. value = false;
  58. clearAcross();
  59. }
  60. return value;
  61. });
  62. };
  63. // Show counter by default
  64. $(options.counterContainer).show();
  65. // Check state of checkboxes and reinit state if needed
  66. $(this).filter(":checked").each(function(i) {
  67. $(this).parent().parent().toggleClass(options.selectedClass);
  68. updateCounter();
  69. if ($(options.acrossInput).val() === 1) {
  70. showClear();
  71. }
  72. });
  73. $(options.allToggle).show().click(function() {
  74. checker($(this).prop("checked"));
  75. updateCounter();
  76. });
  77. $("a", options.acrossQuestions).click(function(event) {
  78. event.preventDefault();
  79. $(options.acrossInput).val(1);
  80. showClear();
  81. });
  82. $("a", options.acrossClears).click(function(event) {
  83. event.preventDefault();
  84. $(options.allToggle).prop("checked", false);
  85. clearAcross();
  86. checker(0);
  87. updateCounter();
  88. });
  89. lastChecked = null;
  90. $(actionCheckboxes).click(function(event) {
  91. if (!event) { event = window.event; }
  92. var target = event.target ? event.target : event.srcElement;
  93. if (lastChecked && $.data(lastChecked) !== $.data(target) && event.shiftKey === true) {
  94. var inrange = false;
  95. $(lastChecked).prop("checked", target.checked)
  96. .parent().parent().toggleClass(options.selectedClass, target.checked);
  97. $(actionCheckboxes).each(function() {
  98. if ($.data(this) === $.data(lastChecked) || $.data(this) === $.data(target)) {
  99. inrange = (inrange) ? false : true;
  100. }
  101. if (inrange) {
  102. $(this).prop("checked", target.checked)
  103. .parent().parent().toggleClass(options.selectedClass, target.checked);
  104. }
  105. });
  106. }
  107. $(target).parent().parent().toggleClass(options.selectedClass, target.checked);
  108. lastChecked = target;
  109. updateCounter();
  110. });
  111. $('form#changelist-form table#result_list tr').find('td:gt(0) :input').change(function() {
  112. list_editable_changed = true;
  113. });
  114. $('form#changelist-form button[name="index"]').click(function(event) {
  115. if (list_editable_changed) {
  116. return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
  117. }
  118. });
  119. $('form#changelist-form input[name="_save"]').click(function(event) {
  120. var action_changed = false;
  121. $('select option:selected', options.actionContainer).each(function() {
  122. if ($(this).val()) {
  123. action_changed = true;
  124. }
  125. });
  126. if (action_changed) {
  127. if (list_editable_changed) {
  128. 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."));
  129. } else {
  130. 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."));
  131. }
  132. }
  133. });
  134. };
  135. /* Setup plugin defaults */
  136. $.fn.actions.defaults = {
  137. actionContainer: "div.actions",
  138. counterContainer: "span.action-counter",
  139. allContainer: "div.actions span.all",
  140. acrossInput: "div.actions input.select-across",
  141. acrossQuestions: "div.actions span.question",
  142. acrossClears: "div.actions span.clear",
  143. allToggle: "#action-toggle",
  144. selectedClass: "selected"
  145. };
  146. $(document).ready(function() {
  147. var $actionsEls = $('tr input.action-select');
  148. if ($actionsEls.length > 0) {
  149. $actionsEls.actions();
  150. }
  151. });
  152. })(django.jQuery);