combo.ex 6.4 KB

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