input.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import {InputItem} from "./base";
  2. import {deep_copy, make_set} from "../../utils"
  3. import {state} from "../../state";
  4. const datalist_tpl = `
  5. {{#datalist}}
  6. <option>{{.}}</option>
  7. {{/datalist}}`;
  8. const common_input_tpl = `
  9. <div class="form-group">
  10. {{#label}}<label for="{{id_name}}">{{label}}</label>{{/label}}
  11. {{#action}}<div class="input-group">{{/action}}
  12. <input type="{{type}}" id="{{id_name}}" aria-describedby="{{id_name}}_action_btn" list="{{id_name}}-list" class="form-control" >
  13. <datalist id="{{id_name}}-list">
  14. ${datalist_tpl}
  15. </datalist>
  16. {{#action}}
  17. <div class="input-group-append">
  18. <button class="btn btn-outline-secondary single-input-action-btn" type="button" id="{{id_name}}_action_btn" data-callbackid="{{callback_id}}">{{label}}</button>
  19. </div>
  20. {{/action}}
  21. <div class="invalid-feedback">{{invalid_feedback}}</div>
  22. <div class="valid-feedback">{{valid_feedback}}</div>
  23. {{#action}}</div>{{/action}}
  24. <small id="{{id_name}}_help" class="form-text text-muted">{{help_text}}</small>
  25. </div>`;
  26. export class Input extends InputItem {
  27. static accept_input_types: string[] = ["text", "password", "number", "float", "color", "date", "range", "time", "email", "url"];
  28. constructor(spec: any, task_id: string, on_input_event: (event_name: string, input_item: InputItem) => void) {
  29. super(spec, task_id, on_input_event);
  30. }
  31. create_element(): JQuery {
  32. let spec = deep_copy(this.spec);
  33. const id_name = spec.name + '-' + Math.floor(Math.random() * Math.floor(9999));
  34. spec['id_name'] = id_name;
  35. if (spec['type'] == 'float') spec['type'] = 'text';
  36. let html = Mustache.render(common_input_tpl, spec);
  37. this.element = $(html);
  38. this.element.find(`#${id_name}_action_btn`).on('click', function (e) {
  39. let btn = $(this);
  40. state.CurrentSession.send_message({
  41. event: "callback",
  42. task_id: btn.data('callbackid') as string,
  43. data: null
  44. });
  45. });
  46. let input_elem = this.element.find('input');
  47. if (spec.onblur) {
  48. // blur事件时,发送当前值到服务器
  49. input_elem.on("blur", (e) => {
  50. if (this.get_value())
  51. this.on_input_event("blur", this);
  52. });
  53. }
  54. if (spec.onchange) {
  55. input_elem.on("input", (e) => {
  56. this.on_input_event("change", this);
  57. });
  58. }
  59. // 将额外的html参数加到input标签上
  60. const ignore_keys = make_set(['action', 'type', 'label', 'invalid_feedback', 'valid_feedback', 'help_text',
  61. 'options', 'datalist', 'multiple', 'onchange', 'onblur']);
  62. for (let key in this.spec) {
  63. if (key in ignore_keys) continue;
  64. input_elem.attr(key, this.spec[key]);
  65. }
  66. return this.element;
  67. }
  68. update_input(spec: any): any {
  69. let attributes = spec.attributes;
  70. if ('datalist' in attributes) {
  71. const datalist_html = Mustache.render(datalist_tpl, {datalist: attributes.datalist});
  72. this.element.find('datalist').empty().append(datalist_html);
  73. delete attributes['datalist'];
  74. }
  75. this.update_input_helper(-1, attributes);
  76. }
  77. get_value(): any {
  78. let val = this.element.find('input').val();
  79. if (this.spec['type'] == 'number')
  80. val = parseInt(val as string);
  81. else if (this.spec['type'] == 'float')
  82. val = parseFloat(val as string);
  83. return val;
  84. }
  85. }