您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

142 行
2.8 KiB

  1. import Awesomplete from 'awesomplete';
  2. frappe.ui.form.ControlAutocomplete = class ControlAutoComplete extends frappe.ui.form.ControlData {
  3. static trigger_change_on_input_event = false
  4. make_input() {
  5. super.make_input();
  6. this.setup_awesomplete();
  7. this.set_options();
  8. }
  9. set_options() {
  10. if (this.df.options) {
  11. let options = this.df.options || [];
  12. this._data = this.parse_options(options);
  13. }
  14. }
  15. get_awesomplete_settings() {
  16. var me = this;
  17. return {
  18. minChars: 0,
  19. maxItems: this.df.max_items || 99,
  20. autoFirst: true,
  21. list: this.get_data(),
  22. data: function(item) {
  23. if (!(item instanceof Object)) {
  24. var d = { value: item };
  25. item = d;
  26. }
  27. return {
  28. label: item.label || item.value,
  29. value: item.value
  30. };
  31. },
  32. filter: function(item, input) {
  33. let hay = item.label + item.value;
  34. return Awesomplete.FILTER_CONTAINS(hay, input);
  35. },
  36. item: function(item) {
  37. var d = this.get_item(item.value);
  38. if (!d) {
  39. d = item;
  40. }
  41. if (!d.label) {
  42. d.label = d.value;
  43. }
  44. var _label = me.translate_values ? __(d.label) : d.label;
  45. var html = '<strong>' + _label + '</strong>';
  46. if (d.description) {
  47. html += '<br><span class="small">' + __(d.description) + '</span>';
  48. }
  49. return $('<li></li>')
  50. .data('item.autocomplete', d)
  51. .prop('aria-selected', 'false')
  52. .html('<a><p>' + html + '</p></a>')
  53. .get(0);
  54. },
  55. sort: () => {
  56. return 0;
  57. }
  58. };
  59. }
  60. setup_awesomplete() {
  61. this.awesomplete = new Awesomplete(
  62. this.input,
  63. this.get_awesomplete_settings()
  64. );
  65. $(this.input_area)
  66. .find('.awesomplete ul')
  67. .css('min-width', '100%');
  68. this.$input.on(
  69. 'input',
  70. frappe.utils.debounce(() => {
  71. this.awesomplete.list = this.get_data();
  72. }, 500)
  73. );
  74. this.$input.on('focus', () => {
  75. if (!this.$input.val()) {
  76. this.$input.val('');
  77. this.$input.trigger('input');
  78. }
  79. });
  80. this.$input.on("awesomplete-open", () => {
  81. this.autocomplete_open = true;
  82. });
  83. this.$input.on("awesomplete-close", () => {
  84. this.autocomplete_open = false;
  85. });
  86. this.$input.on('awesomplete-selectcomplete', () => {
  87. this.$input.trigger('change');
  88. });
  89. }
  90. validate(value) {
  91. if (this.df.ignore_validation) {
  92. return value || '';
  93. }
  94. let valid_values = this.awesomplete._list.map(d => d.value);
  95. if (!valid_values.length) {
  96. return value;
  97. }
  98. if (valid_values.includes(value)) {
  99. return value;
  100. } else {
  101. return '';
  102. }
  103. }
  104. parse_options(options) {
  105. if (typeof options === 'string') {
  106. options = options.split('\n');
  107. }
  108. if (typeof options[0] === 'string') {
  109. options = options.map(o => ({ label: o, value: o }));
  110. }
  111. return options;
  112. }
  113. get_data() {
  114. return this._data || [];
  115. }
  116. set_data(data) {
  117. data = this.parse_options(data);
  118. if (this.awesomplete) {
  119. this.awesomplete.list = data;
  120. }
  121. this._data = data;
  122. }
  123. };