select.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import {InputItem} from "./base";
  2. import {Session} from "../../session";
  3. import {deep_copy} from "../../utils"
  4. const options_tpl = `
  5. {{#options}}
  6. <option {{#selected}}selected{{/selected}} {{#disabled}}disabled{{/disabled}}>{{label}}</option>
  7. {{/options}}
  8. `;
  9. const select_input_tpl = `
  10. <div class="form-group">
  11. {{#label}}<label for="{{id_name}}">{{label}}</label>{{/label}}
  12. <select id="{{id_name}}" aria-describedby="{{id_name}}_help" class="form-control" {{#multiple}}multiple{{/multiple}}>
  13. ${options_tpl}
  14. </select>
  15. <div class="invalid-feedback">{{invalid_feedback}}</div>
  16. <div class="valid-feedback">{{valid_feedback}}</div>
  17. <small id="{{id_name}}_help" class="form-text text-muted">{{help_text}}</small>
  18. </div>`;
  19. export class Select extends InputItem {
  20. static accept_input_types: string[] = ["select"];
  21. constructor(session: Session, task_id: string, spec: any) {
  22. super(session, task_id, spec);
  23. }
  24. create_element(): JQuery {
  25. let spec = deep_copy(this.spec);
  26. const id_name = spec.name + '-' + Math.floor(Math.random() * Math.floor(9999));
  27. spec['id_name'] = id_name;
  28. let html = Mustache.render(select_input_tpl, spec);
  29. this.element = $(html);
  30. this.setup_select_options(this.element, spec.options);
  31. if(spec.onblur) {
  32. // blur事件时,发送当前值到服务器
  33. this.element.find('select').on("blur", (e) => {
  34. this.send_value_listener(this, e);
  35. });
  36. }
  37. if(spec.onchange){
  38. this.element.find('select').on("change", (e) => {
  39. this.send_value_listener(this, e);
  40. });
  41. }
  42. return this.element;
  43. }
  44. setup_select_options(elem: JQuery, options: any) {
  45. let input_elem = elem.find('select');
  46. let opts = input_elem.find('option');
  47. for (let idx = 0; idx < options.length; idx++)
  48. opts.eq(idx).val(JSON.stringify(options[idx].value));
  49. // 将额外的html参数加到input标签上
  50. const ignore_keys = {
  51. 'type': '',
  52. 'label': '',
  53. 'invalid_feedback': '',
  54. 'valid_feedback': '',
  55. 'help_text': '',
  56. 'options': '',
  57. 'datalist': '',
  58. 'multiple': ''
  59. };
  60. for (let key in this.spec) {
  61. if (key in ignore_keys) continue;
  62. input_elem.attr(key, this.spec[key]);
  63. }
  64. }
  65. update_input(spec: any): any {
  66. let attributes = spec.attributes;
  67. if ('options' in attributes) {
  68. const opts_html = Mustache.render(options_tpl, {options: attributes.options});
  69. this.element.find('select').empty().append(opts_html);
  70. this.setup_select_options(this.element, attributes.options);
  71. delete attributes['options'];
  72. }
  73. this.update_input_helper(-1, attributes);
  74. }
  75. get_value(): any {
  76. let raw_val = this.element.find('select').val();
  77. if (this.spec.multiple) {
  78. let res: any[] = [];
  79. for (let i of (raw_val as string[]))
  80. res.push(JSON.parse(i));
  81. return res;
  82. } else {
  83. return JSON.parse(raw_val as string);
  84. }
  85. }
  86. }