PageRenderTime 61ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/statics/grappelli/js/jquery.grp_inline.js

https://bitbucket.org/asolka/nie-typowa-studencka-lod-wka
JavaScript | 185 lines | 141 code | 12 blank | 32 comment | 18 complexity | c8b8344c93eb717132ba57a6331f0f3c MD5 | raw file
  1. /**
  2. * GRAPPELLI INLINES
  3. * jquery-plugin for inlines (stacked and tabular)
  4. */
  5. (function($) {
  6. $.fn.grp_inline = function(options) {
  7. var defaults = {
  8. prefix: "form", // The form prefix for your django formset
  9. addText: "add another", // Text for the add link
  10. deleteText: "remove", // Text for the delete link
  11. addCssClass: "grp-add-handler", // CSS class applied to the add link
  12. removeCssClass: "grp-remove-handler", // CSS class applied to the remove link
  13. deleteCssClass: "grp-delete-handler", // CSS class applied to the delete link
  14. emptyCssClass: "grp-empty-form", // CSS class applied to the empty row
  15. formCssClass: "grp-dynamic-form", // CSS class applied to each form in a formset
  16. predeleteCssClass: "grp-predelete",
  17. onBeforeInit: function(form) {}, // Function called before a form is initialized
  18. onBeforeAdded: function(inline) {}, // Function called before a form is added
  19. onBeforeRemoved: function(form) {}, // Function called before a form is removed
  20. onBeforeDeleted: function(form) {}, // Function called before a form is deleted
  21. onAfterInit: function(form) {}, // Function called after a form has been initialized
  22. onAfterAdded: function(form) {}, // Function called after a form has been added
  23. onAfterRemoved: function(inline) {}, // Function called after a form has been removed
  24. onAfterDeleted: function(form) {} // Function called after a form has been deleted
  25. };
  26. options = $.extend(defaults, options);
  27. return this.each(function() {
  28. var inline = $(this); // the current inline node
  29. var totalForms = inline.find("#id_" + options.prefix + "-TOTAL_FORMS");
  30. // set autocomplete to off in order to prevent the browser from keeping the current value after reload
  31. totalForms.attr("autocomplete", "off");
  32. // init inline and add-buttons
  33. initInlineForms(inline, options);
  34. initAddButtons(inline, options);
  35. // button handlers
  36. addButtonHandler(inline.find("a." + options.addCssClass), options);
  37. removeButtonHandler(inline.find("a." + options.removeCssClass), options);
  38. deleteButtonHandler(inline.find("a." + options.deleteCssClass), options);
  39. });
  40. };
  41. updateFormIndex = function(elem, options, replace_regex, replace_with) {
  42. elem.find(':input,span,table,iframe,label,a,ul,p,img,div').each(function() {
  43. var node = $(this),
  44. node_id = node.attr('id'),
  45. node_name = node.attr('name'),
  46. node_for = node.attr('for'),
  47. node_href = node.attr("href");
  48. node_class = node.attr("class");
  49. if (node_id) { node.attr('id', node_id.replace(replace_regex, replace_with)); }
  50. if (node_name) { node.attr('name', node_name.replace(replace_regex, replace_with)); }
  51. if (node_for) { node.attr('for', node_for.replace(replace_regex, replace_with)); }
  52. if (node_href) { node.attr('href', node_href.replace(replace_regex, replace_with)); }
  53. if (node_class) { node.attr('class', node_class.replace(replace_regex, replace_with)); }
  54. });
  55. };
  56. initInlineForms = function(elem, options) {
  57. elem.find("div.grp-module").each(function() {
  58. var form = $(this);
  59. // callback
  60. options.onBeforeInit(form);
  61. // add options.formCssClass to all forms in the inline
  62. // except table/theader/add-item
  63. if (form.attr('id') !== "") {
  64. form.not("." + options.emptyCssClass).not(".grp-table").not(".grp-thead").not(".add-item").addClass(options.formCssClass);
  65. }
  66. // add options.predeleteCssClass to forms with the delete checkbox checked
  67. form.find("li.grp-delete-handler-container input").each(function() {
  68. if ($(this).attr("checked") && form.hasClass("has_original")) {
  69. form.toggleClass(options.predeleteCssClass);
  70. }
  71. });
  72. // callback
  73. options.onAfterInit(form);
  74. });
  75. };
  76. initAddButtons = function(elem, options) {
  77. var totalForms = elem.find("#id_" + options.prefix + "-TOTAL_FORMS");
  78. var maxForms = elem.find("#id_" + options.prefix + "-MAX_NUM_FORMS");
  79. var addButtons = elem.find("a." + options.addCssClass);
  80. // hide add button in case we've hit the max, except we want to add infinitely
  81. if ((maxForms.val() !== '') && (maxForms.val()-totalForms.val()) <= 0) {
  82. hideAddBottons(elem, options);
  83. }
  84. };
  85. addButtonHandler = function(elem, options) {
  86. elem.bind("click", function() {
  87. var inline = elem.parents(".grp-group"),
  88. totalForms = inline.find("#id_" + options.prefix + "-TOTAL_FORMS"),
  89. maxForms = inline.find("#id_" + options.prefix + "-MAX_NUM_FORMS"),
  90. addButtons = inline.find("a." + options.addCssClass),
  91. empty_template = inline.find("#" + options.prefix + "-empty");
  92. // callback
  93. options.onBeforeAdded(inline);
  94. // create new form
  95. var index = parseInt(totalForms.val(), 10),
  96. form = empty_template.clone(true);
  97. form.removeClass(options.emptyCssClass)
  98. .attr("id", empty_template.attr('id').replace("-empty", index));
  99. // update form index
  100. var re = /__prefix__/g;
  101. updateFormIndex(form, options, re, index);
  102. // after "__prefix__" strings has been substituted with the number
  103. // of the inline, we can add the form to DOM, not earlier.
  104. // This way we can support handlers that track live element
  105. // adding/removing, like those used in django-autocomplete-light
  106. form.insertBefore(empty_template)
  107. .addClass(options.formCssClass);
  108. // update total forms
  109. totalForms.val(index + 1);
  110. // hide add button in case we've hit the max, except we want to add infinitely
  111. if ((maxForms.val() !== 0) && (maxForms.val() !== "") && (maxForms.val() - totalForms.val()) <= 0) {
  112. hideAddBottons(inline, options);
  113. }
  114. // callback
  115. options.onAfterAdded(form);
  116. });
  117. };
  118. removeButtonHandler = function(elem, options) {
  119. elem.bind("click", function() {
  120. var inline = elem.parents(".grp-group"),
  121. form = $(this).parents("." + options.formCssClass).first(),
  122. totalForms = inline.find("#id_" + options.prefix + "-TOTAL_FORMS"),
  123. maxForms = inline.find("#id_" + options.prefix + "-MAX_NUM_FORMS");
  124. // callback
  125. options.onBeforeRemoved(form);
  126. // remove form
  127. form.remove();
  128. // update total forms
  129. var index = parseInt(totalForms.val(), 10);
  130. totalForms.val(index - 1);
  131. // show add button in case we've dropped below max
  132. if ((maxForms.val() !== 0) && (maxForms.val() - totalForms.val()) > 0) {
  133. showAddButtons(inline, options);
  134. }
  135. // update form index (for all forms)
  136. var re = /-\d+-/g,
  137. i = 0;
  138. inline.find("." + options.formCssClass).each(function() {
  139. updateFormIndex($(this), options, re, "-" + i + "-");
  140. i++;
  141. });
  142. // callback
  143. options.onAfterRemoved(inline);
  144. });
  145. };
  146. deleteButtonHandler = function(elem, options) {
  147. elem.bind("click", function() {
  148. var deleteInput = $(this).prev(),
  149. form = $(this).parents("." + options.formCssClass).first();
  150. // callback
  151. options.onBeforeDeleted(form);
  152. // toggle options.predeleteCssClass and toggle checkbox
  153. if (form.hasClass("has_original")) {
  154. form.toggleClass(options.predeleteCssClass);
  155. if (deleteInput.attr("checked")) {
  156. deleteInput.removeAttr("checked");
  157. } else {
  158. deleteInput.attr("checked", 'checked');
  159. }
  160. }
  161. // callback
  162. options.onAfterDeleted(form);
  163. });
  164. };
  165. hideAddBottons = function(elem, options) {
  166. var addButtons = elem.find("a." + options.addCssClass);
  167. addButtons.hide().parents('.grp-add-item').hide();
  168. };
  169. showAddButtons = function(elem, options) {
  170. var addButtons = elem.find("a." + options.addCssClass);
  171. addButtons.show().parents('.grp-add-item').show();
  172. };
  173. })(grp.jQuery);