Bez popisu

jquery.grp_autocomplete_fk.js 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /**
  2. * GRAPPELLI AUTOCOMPLETE FK
  3. * foreign-key lookup with autocomplete
  4. */
  5. (function($){
  6. var methods = {
  7. init: function(options) {
  8. options = $.extend({}, $.fn.grp_autocomplete_fk.defaults, options);
  9. return this.each(function() {
  10. var $this = $(this);
  11. // assign attributes
  12. $this.attr({
  13. "tabindex": "-1",
  14. "readonly": "readonly"
  15. }).addClass("grp-autocomplete-hidden-field");
  16. // remove djangos object representation (if given)
  17. if ($this.next().next() && $this.next().next().attr("class") != "errorlist" && $this.next().next().attr("class") != "grp-help") $this.next().next().remove();
  18. // build autocomplete wrapper
  19. $this.next().after(loader).after(remove_link($this.attr('id')));
  20. $this.parent().wrapInner("<div class='grp-autocomplete-wrapper-fk'></div>");
  21. $this.parent().prepend("<input id='" + $this.attr("id") + "-autocomplete' type='text' class='vTextField' value='' />");
  22. // extend options
  23. options = $.extend({
  24. wrapper_autocomplete: $this.parent(),
  25. input_field: $this.prev(),
  26. remove_link: $this.next().next().hide(),
  27. loader: $this.next().next().next().hide()
  28. }, $.fn.grp_autocomplete_fk.defaults, options);
  29. // lookup
  30. lookup_id($this, options); // lookup when loading page
  31. lookup_autocomplete($this, options); // autocomplete-handler
  32. $this.on("change focus keyup", function() { // id-handler
  33. lookup_id($this, options);
  34. });
  35. // labels
  36. $("label[for='"+$this.attr('id')+"']").each(function() {
  37. $(this).attr("for", $this.attr("id")+"-autocomplete");
  38. });
  39. });
  40. }
  41. };
  42. $.fn.grp_autocomplete_fk = function(method) {
  43. if (methods[method]) {
  44. return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  45. } else if (typeof method === 'object' || ! method) {
  46. return methods.init.apply(this, arguments);
  47. } else {
  48. $.error('Method ' + method + ' does not exist on jQuery.grp_autocomplete_fk');
  49. }
  50. return false;
  51. };
  52. var loader = function() {
  53. var loader = $('<div class="grp-loader">loader</div>');
  54. return loader;
  55. };
  56. var remove_link = function(id) {
  57. var removelink = $('<a class="grp-related-remove"></a>');
  58. removelink.attr('id', 'remove_'+id);
  59. removelink.attr('href', 'javascript://');
  60. removelink.attr('onClick', 'return removeRelatedObject(this);');
  61. removelink.hover(function() {
  62. $(this).parent().toggleClass("grp-autocomplete-preremove");
  63. });
  64. return removelink;
  65. };
  66. var lookup_autocomplete = function(elem, options) {
  67. options.wrapper_autocomplete.find("input:first")
  68. .on("focus", function() {
  69. options.wrapper_autocomplete.addClass("grp-state-focus");
  70. })
  71. .on("blur", function() {
  72. options.wrapper_autocomplete.removeClass("grp-state-focus");
  73. })
  74. .autocomplete({
  75. minLength: 1,
  76. autoFocus: true,
  77. delay: 1000,
  78. source: function(request, response) {
  79. $.ajax({
  80. url: options.autocomplete_lookup_url,
  81. dataType: 'json',
  82. data: "term=" + encodeURIComponent(request.term) + "&app_label=" + grappelli.get_app_label(elem) + "&model_name=" + grappelli.get_model_name(elem) + "&query_string=" + grappelli.get_query_string(elem) + "&to_field=" + grappelli.get_to_field(elem),
  83. beforeSend: function (XMLHttpRequest) {
  84. options.loader.show();
  85. },
  86. success: function(data){
  87. response($.map(data, function(item) {
  88. return {label: item.label, value: item.value};
  89. }));
  90. },
  91. complete: function (XMLHttpRequest, textStatus) {
  92. options.loader.hide();
  93. }
  94. });
  95. },
  96. focus: function() { // prevent value inserted on focus
  97. return false;
  98. },
  99. select: function(event, ui) {
  100. options.input_field.val(ui.item.label);
  101. elem.val(ui.item.value);
  102. elem.trigger('change');
  103. elem.val() ? $(options.remove_link).show() : $(options.remove_link).hide();
  104. return false;
  105. }
  106. })
  107. .data("ui-autocomplete")._renderItem = function(ul,item) {
  108. if (!item.value) {
  109. return $("<li class='ui-state-disabled'></li>")
  110. .data( "item.autocomplete", item )
  111. .append($("<span class='error'></span>").text(item.label))
  112. .appendTo(ul);
  113. } else {
  114. return $("<li></li>")
  115. .data( "item.autocomplete", item )
  116. .append($("<a></a>").text(item.label))
  117. .appendTo(ul);
  118. }
  119. };
  120. };
  121. var lookup_id = function(elem, options) {
  122. $.getJSON(options.lookup_url, {
  123. object_id: elem.val(),
  124. app_label: grappelli.get_app_label(elem),
  125. model_name: grappelli.get_model_name(elem),
  126. query_string: grappelli.get_query_string(elem),
  127. to_field: grappelli.get_to_field(elem)
  128. }, function(data) {
  129. $.each(data, function(index) {
  130. options.input_field.val(data[index].label);
  131. elem.val() ? $(options.remove_link).show() : $(options.remove_link).hide();
  132. });
  133. });
  134. };
  135. $.fn.grp_autocomplete_fk.defaults = {
  136. autocomplete_lookup_url: '',
  137. lookup_url: ''
  138. };
  139. })(grp.jQuery);