RelatedObjectLookups.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // Handles related-objects functionality: lookup link for raw_id_fields
  2. // and Add Another links.
  3. function html_unescape(text) {
  4. // Unescape a string that was escaped using django.utils.html.escape.
  5. text = text.replace(/&lt;/g, '<');
  6. text = text.replace(/&gt;/g, '>');
  7. text = text.replace(/&quot;/g, '"');
  8. text = text.replace(/&#39;/g, "'");
  9. text = text.replace(/&amp;/g, '&');
  10. return text;
  11. }
  12. // IE doesn't accept periods or dashes in the window name, but the element IDs
  13. // we use to generate popup window names may contain them, therefore we map them
  14. // to allowed characters in a reversible way so that we can locate the correct
  15. // element when the popup window is dismissed.
  16. function id_to_windowname(text) {
  17. text = text.replace(/\./g, '__dot__');
  18. text = text.replace(/\-/g, '__dash__');
  19. return text;
  20. }
  21. function windowname_to_id(text) {
  22. text = text.replace(/__dot__/g, '.');
  23. text = text.replace(/__dash__/g, '-');
  24. return text;
  25. }
  26. function showAdminPopup(triggeringLink, name_regexp) {
  27. var name = triggeringLink.id.replace(name_regexp, '');
  28. name = id_to_windowname(name);
  29. var href = triggeringLink.href;
  30. if (href.indexOf('?') == -1) {
  31. href += '?_popup=1';
  32. } else {
  33. href += '&_popup=1';
  34. }
  35. // Django JET
  36. showRelatedPopup(name, href);
  37. return false;
  38. }
  39. function showRelatedObjectLookupPopup(triggeringLink) {
  40. return showAdminPopup(triggeringLink, /^lookup_/);
  41. }
  42. function dismissRelatedLookupPopup(win, chosenId) {
  43. var name = windowname_to_id(win.name);
  44. var elem = document.getElementById(name);
  45. if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
  46. elem.value += ',' + chosenId;
  47. } else {
  48. document.getElementById(name).value = chosenId;
  49. }
  50. // Django JET
  51. closeRelatedPopup(win);
  52. }
  53. function showRelatedObjectPopup(triggeringLink) {
  54. var name = triggeringLink.id.replace(/^(change|add|delete)_/, '');
  55. name = id_to_windowname(name);
  56. var href = triggeringLink.href;
  57. // Django JET
  58. if (href.indexOf('_popup=1') == -1) {
  59. if (href.indexOf('?') == -1) {
  60. href += '?_popup=1';
  61. } else {
  62. href += '&_popup=1';
  63. }
  64. }
  65. showRelatedPopup(name, href);
  66. return false;
  67. }
  68. function dismissAddRelatedObjectPopup(win, newId, newRepr) {
  69. // newId and newRepr are expected to have previously been escaped by
  70. // django.utils.html.escape.
  71. newId = html_unescape(newId);
  72. newRepr = html_unescape(newRepr);
  73. var name = windowname_to_id(win.name);
  74. var elem = document.getElementById(name);
  75. var o;
  76. if (elem) {
  77. var elemName = elem.nodeName.toUpperCase();
  78. if (elemName == 'SELECT') {
  79. o = new Option(newRepr, newId);
  80. elem.options[elem.options.length] = o;
  81. o.selected = true;
  82. } else if (elemName == 'INPUT') {
  83. if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
  84. elem.value += ',' + newId;
  85. } else {
  86. elem.value = newId;
  87. }
  88. }
  89. // Trigger a change event to update related links if required.
  90. django.jQuery(elem).trigger('change');
  91. } else {
  92. var toId = name + "_to";
  93. o = new Option(newRepr, newId);
  94. SelectBox.add_to_cache(toId, o);
  95. SelectBox.redisplay(toId);
  96. }
  97. // Django JET
  98. closeRelatedPopup(win);
  99. }
  100. function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) {
  101. objId = html_unescape(objId);
  102. newRepr = html_unescape(newRepr);
  103. var id = windowname_to_id(win.name).replace(/^edit_/, '');
  104. var selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
  105. var selects = django.jQuery(selectsSelector);
  106. selects.find('option').each(function() {
  107. if (this.value == objId) {
  108. this.innerHTML = newRepr;
  109. this.value = newId;
  110. }
  111. });
  112. // Django JET
  113. closeRelatedPopup(win);
  114. };
  115. function dismissDeleteRelatedObjectPopup(win, objId) {
  116. objId = html_unescape(objId);
  117. var id = windowname_to_id(win.name).replace(/^delete_/, '');
  118. var selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
  119. var selects = django.jQuery(selectsSelector);
  120. selects.find('option').each(function() {
  121. if (this.value == objId) {
  122. django.jQuery(this).remove();
  123. }
  124. }).trigger('change');
  125. // Django JET
  126. closeRelatedPopup(win);
  127. };
  128. // Kept for backward compatibility
  129. showAddAnotherPopup = showRelatedObjectPopup;
  130. dismissAddAnotherPopup = dismissAddRelatedObjectPopup;
  131. // Django JET
  132. opener = parent.window;
  133. function showRelatedPopup(name, href) {
  134. django.jQuery(function($) {
  135. var $container = $('.related-popup-container', parent.document);
  136. var $loading = $container.find('.loading-indicator', parent.document);
  137. var $body = $('body').addClass('non-scrollable', parent.document);
  138. var $popup = $('<iframe>').attr('name', name).attr('src', href).addClass('related-popup').on('load', function() {
  139. $popup.add($('.related-popup-back')).fadeIn(200, 'swing', function() {
  140. $loading.hide();
  141. });
  142. });
  143. $loading.show();
  144. $container.fadeIn(200, 'swing', function() {
  145. $container.append($popup);
  146. });
  147. $body.addClass('non-scrollable', parent.document);
  148. });
  149. }
  150. function closeRelatedPopup(win) {
  151. jet.jQuery('select').trigger('select:init');
  152. jet.jQuery(win.parent).trigger('related-popup:close');
  153. }
  154. django.jQuery(document).ready(function() {
  155. jet.jQuery(function($){
  156. function updateLinks() {
  157. var $this = $(this);
  158. var siblings = $this.nextAll('.change-related, .delete-related');
  159. if (!siblings.length) return;
  160. var value = $this.val();
  161. if (value) {
  162. siblings.each(function(){
  163. var elm = $(this);
  164. elm.attr('href', elm.attr('data-href-template').replace('__fk__', value));
  165. });
  166. } else siblings.removeAttr('href');
  167. }
  168. var container = $(document);
  169. container.on('change', '.related-widget-wrapper select', updateLinks);
  170. container.find('.related-widget-wrapper select').each(updateLinks);
  171. container.on('click', '.related-widget-wrapper-link', function(event){
  172. if (this.href) {
  173. showRelatedObjectPopup(this);
  174. }
  175. event.preventDefault();
  176. });
  177. });
  178. });