combo.ex 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. defmodule NITRO.Combo do
  2. require NITRO
  3. require Record
  4. def to_list(fld) when is_atom(fld), do: fld
  5. def to_list(fld), do: :unicode.characters_to_list(fld, :unicode)
  6. def new(_name, obj, module, options) do
  7. dom = :proplists.get_value(:dom, options)
  8. feed = :proplists.get_value(:feed, options)
  9. dropDown(obj, dom, module, feed)
  10. end
  11. def proto(NITRO.comboKey(value: "")), do: []
  12. def proto(NITRO.comboKey(delegate: []) = msg), do: NITRO.Combo.Search.keyUp(msg)
  13. def proto(NITRO.comboScroll(delegate: []) = msg), do: NITRO.Combo.Search.comboScroll(msg)
  14. def proto(NITRO.comboInsert(delegate: []) = msg), do: comboInsert(msg)
  15. def proto(NITRO.comboKey(delegate: module) = msg) do
  16. case has_function(module, :keyUp) do
  17. true -> module.keyUp(msg)
  18. false -> NITRO.Combo.Search.keyUp(msg)
  19. end
  20. end
  21. def proto(NITRO.comboScroll(delegate: module) = msg) do
  22. case has_function(module, :comboScroll) do
  23. true -> module.comboScroll(msg)
  24. false -> NITRO.Combo.Search.comboScroll(msg)
  25. end
  26. end
  27. def proto(NITRO.comboSelect(delegate: module) = msg) do
  28. case has_function(module, :select) do
  29. true -> module.select(msg)
  30. false -> :skip
  31. end
  32. end
  33. def proto(NITRO.comboInsert(delegate: module) = msg) do
  34. case has_function(module, :comboInsert) do
  35. true -> module.comboInsert(msg)
  36. false -> comboInsert(msg)
  37. end
  38. end
  39. def comboInsert(NITRO.comboInsert(chunks: 0, dom: field, status: :finished)) do
  40. NITRO.Combo.Search.stop(field)
  41. :nitro.wire("activeCombo = undefined; currentItem = undefined;")
  42. :nitro.hide(:nitro.atom([:comboContainer, :nitro.to_list(field)]))
  43. :nitro.wire("comboOpenFormById('#{:nitro.atom([:nitro.to_list(field), 'form'])}');")
  44. end
  45. def comboInsert(NITRO.comboInsert(dom: field, rows: rows, delegate: module, feed: feed)) do
  46. :lists.foreach(fn row ->
  47. :nitro.insert_bottom(
  48. :nitro.atom([:comboContainer, :nitro.to_list(field)]),
  49. :nitro.render(dropDown0(row, :nitro.to_list(field), module, feed))
  50. )
  51. end, rows)
  52. end
  53. def dropDownList0(filtered, field, module, feed) do
  54. if has_function(module, :dropDownList) do
  55. module.dropDownList(filtered, field, module, feed)
  56. else
  57. dropDownList(filtered, field, module, feed)
  58. end
  59. end
  60. def dropDownList(filtered, field, module, feed) do
  61. formId = :nitro.atom([field, "form"])
  62. if filtered == [] do
  63. :nitro.wire("activeCombo = undefined; currentItem = undefined;")
  64. :nitro.hide(:nitro.atom([:comboContainer, field]))
  65. :nitro.wire("comboOpenFormById('#{formId}');")
  66. else
  67. :nitro.display(:nitro.atom([:comboContainer, field]), :block)
  68. :nitro.wire("comboCloseFormById('#{formId}');")
  69. end
  70. Enum.each(filtered, fn obj ->
  71. form = dropDown0(obj, field, module, feed)
  72. :nitro.insert_top(
  73. :nitro.atom([:comboContainer, field]),
  74. :nitro.render(form)
  75. )
  76. end)
  77. end
  78. def dropDown0(obj, dom0, module, feed) do
  79. case has_function(module, :dropDown) do
  80. true ->
  81. module.dropDown(obj, dom0, feed)
  82. false ->
  83. dropDown(obj, dom0, module, feed)
  84. end
  85. end
  86. def view_value(obj, _, _) when obj in ["", [], :undefined], do: []
  87. def view_value(obj, module, feed) do
  88. case :erlang.function_exported(module, :view_value, 2) do
  89. true ->
  90. module.view_value(obj, feed)
  91. false ->
  92. if has_function(module, :view_value) do
  93. module.view_value(obj)
  94. else
  95. view_value(obj)
  96. end
  97. end
  98. end
  99. def view_value(obj) when obj in ["", [], :undefined], do: []
  100. def view_value(obj), do: :nitro.jse(:erlang.iolist_to_binary(apply(:kvs,:field,[obj, hd(index([]))])))
  101. def dropDown(obj, dom0, module, feed) do
  102. view_value = view_value(obj, module, feed)
  103. dom = :nitro.to_list(dom0)
  104. id = :nitro.jse(:erlang.iolist_to_binary(:nitro.atom([dom, :erlang.element(2, obj)])))
  105. item = :nitro.to_list(item(obj, module))
  106. source = :erlang.iolist_to_binary(feed)
  107. click = :nitro.jse("comboSelect('#{dom}', '#{view_value}', '#{source}', '#{module}', '#{id}')")
  108. move = :nitro.jse("comboLookupMouseMove('#{dom}')")
  109. NITRO.panel(
  110. id: id,
  111. class: ['dropdown-item'],
  112. bind: :base64.encode(:erlang.term_to_binary(obj)),
  113. onclick: click,
  114. onmousemove: move,
  115. body: [
  116. NITRO.p(body: item)
  117. ]
  118. )
  119. end
  120. def index([]), do: [:name, :id]
  121. def index(module) do
  122. case has_function(module, :index) do
  123. true -> module.index()
  124. false -> index([])
  125. end
  126. end
  127. def item(obj, []), do: view_value(obj)
  128. def item(obj, module) do
  129. case has_function(module, :item) do
  130. true -> module.item(obj)
  131. false -> item(obj, [])
  132. end
  133. end
  134. def update_comboVec(_parent, dom, feed, module, default, elem) do
  135. vector = view_value(default, module, feed)
  136. clear = "createSortable('##{dom}_list');"
  137. append = :lists.map(fn emp -> bind = emp |> :erlang.term_to_binary |> :base64.encode
  138. "appendItemFromBind('#{dom}_list','#{module.cn(emp)}','#{bind}');" end, vector)
  139. |> :erlang.iolist_to_binary
  140. render = :nitro.render elem
  141. command = "elem = qi('#{dom}'); elem.outerHTML = '#{render}';"
  142. :nitro.wire(command <> append <> clear) # reverse
  143. end
  144. def update_combo(id, feed, module), do: :nitro.update(:nitro.atom([:lookup, id]), NITRO.comboLookup(id: id, feed: feed, delegate: module))
  145. def update_combo_value(dom, value, feed, module) do
  146. view_value = view_value(value, module, feed)
  147. update_combo_value(dom, value, feed, module, view_value)
  148. end
  149. def update_combo_value(dom, value, feed, module, view_value) do
  150. bind = :base64.encode(:erlang.term_to_binary(value))
  151. update_combo(dom, feed, module)
  152. command = "elem = qi('#{dom}'); elem.setAttribute('data-bind', '#{bind}'); elem.value = '#{view_value}';"
  153. :nitro.wire(command)
  154. end
  155. def has_function(m, f) do
  156. functions = apply(m, :module_info, [:exports])
  157. isF = Keyword.get(functions, f, -1)
  158. isF != -1
  159. end
  160. end