comboSearch.ex 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. defmodule NITRO.Combo.Search do
  2. require NITRO
  3. require Record
  4. Record.defrecord(:state, pid: [], chunks: 0, value: [], reader: [], opts: [], feed: [])
  5. def start(value, field, feed, opts) do
  6. Supervisor.start_link([], strategy: :one_for_one, name: NITRO.Combo.Search)
  7. state = state(pid: self(), value: value, reader: :erlang.apply(:kvs, :reader, [feed]), opts: opts, feed: feed)
  8. stop(field)
  9. pi =
  10. NITRO.pi(
  11. module: NITRO.Combo.Search,
  12. table: :async,
  13. sup: NITRO.Combo.Search,
  14. state: state,
  15. name: "#{field}",
  16. timeout: :brutal_kill,
  17. restart: :temporary
  18. )
  19. case :nitro_pi.start(pi) do
  20. {pid,_} -> send(pid, {:filterComboValues, :init, value})
  21. x -> x
  22. end
  23. end
  24. def stop(field) do
  25. case :nitro_pi.pid(:async, "#{field}") do
  26. [] -> :ok
  27. pid ->
  28. :erlang.exit(pid, :kill)
  29. try do :nitro_pi.stop(:async, "#{field}") catch _,_ -> :skip end
  30. end
  31. end
  32. def comboScroll(NITRO.comboScroll(dom: field)) do
  33. case :nitro_pi.pid(:async, "#{field}") do
  34. [] -> []
  35. pid -> send(pid, {:filterComboValues, :append, []})
  36. end
  37. end
  38. def keyUp(NITRO.comboKey(value: value, dom: field, feed: feed, delegate: module)) do
  39. opts = [index: NITRO.Combo.index(module), field: field, delegate: module]
  40. comboContainer = :nitro.atom([:comboContainer, :nitro.to_list(field)])
  41. :nitro.display(:nitro.atom([:comboContainer, field]), :block)
  42. :nitro.clear(comboContainer)
  43. :nitro.wire("comboCloseFormById('#{:nitro.atom([:nitro.to_list(field), 'form'])}');")
  44. :nitro.wire("comboLookupChange('#{field}');")
  45. :nitro.wire(NITRO.bind(target: :nitro.to_binary(comboContainer), type: :scroll, postback: onscroll(field, module)))
  46. start(value, field, feed, opts)
  47. end
  48. def onscroll(field, delegate), do:
  49. :erlang.iolist_to_binary([
  50. "if (event.target && (event.target.scrollTop + event.target.offsetHeight + 10 >= event.target.scrollHeight)) {",
  51. "ws.send(enc(tuple(atom('direct'),
  52. tuple(atom('comboScroll'),",
  53. "bin('#{field}'),",
  54. "atom('#{delegate}'))",
  55. ")));",
  56. "}"
  57. ])
  58. def proc(:init, NITRO.pi() = pi), do: {:ok, pi}
  59. def proc({:filterComboValues, cmd, value0}, NITRO.pi(state: state(chunks: chunks) = st) = pi) do
  60. state(feed: feed, reader: r, value: prev, pid: pid, opts: opts) = st
  61. m = Keyword.get(opts, :delegate, [])
  62. field = Keyword.get(opts, :field, [])
  63. value = case cmd do :append -> prev; _ -> :string.lowercase(:unicode.characters_to_list(value0, :unicode)) end
  64. r1 = :erlang.apply(:kvs, :take, [:erlang.apply(:kvs, :setfield, [r, :args, 10])])
  65. case :erlang.apply(:kvs, :field, [r1, :args]) do
  66. [] ->
  67. send(pid, {:direct, NITRO.comboInsert(dom: field, delegate: m, chunks: chunks, status: :finished)})
  68. {:stop, :normal, NITRO.pi(pi, state: state(st, reader: :erlang.apply(:kvs, :setfield, [r1, :args, []])))}
  69. rows ->
  70. filtered =
  71. case value do
  72. 'all' -> rows
  73. _ ->
  74. :lists.filter(fn x -> :lists.any(&filter(value, x, &1), Keyword.get(opts, :index, [])) end, rows)
  75. end
  76. newChunks = chunks + length(filtered)
  77. send(pid, {:direct, NITRO.comboInsert(dom: field, delegate: m, chunks: newChunks, feed: feed, rows: filtered)})
  78. chunks < 100 and
  79. case :nitro_pi.pid(:async, "#{field}") do [] -> []; pid -> send(pid, {:filterComboValues, cmd, value0}) end
  80. {:noreply, NITRO.pi(pi, state: state(st, value: value, chunks: newChunks, reader: :erlang.apply(:kvs, :setfield, [r1, :args, []])))}
  81. end
  82. end
  83. def proc(_, pi), do: {:noreply, pi}
  84. defp filter(val, obj, i) do
  85. fld =
  86. if is_function(i) do
  87. i.(obj)
  88. else
  89. fldVal = :erlang.apply(:kvs, :field, [obj, i])
  90. if fldVal == elem(obj, 0), do: :nitro.to_list(fldVal), else: fldVal
  91. end |> NITRO.Combo.to_list()
  92. fld != elem(obj, 0) and :string.rstr(:string.lowercase(:nitro.to_list(fld)), val) > 0
  93. end
  94. end