jquery_sortable_tree 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +22 -0
  3. data/README.md +319 -0
  4. data/Rakefile +36 -0
  5. data/app/assets/images/iconza/icons/add.png +0 -0
  6. data/app/assets/images/iconza/icons/delete.png +0 -0
  7. data/app/assets/images/iconza/icons/edit.png +0 -0
  8. data/app/assets/images/iconza/icons/move.png +0 -0
  9. data/app/assets/images/iconza/icons/red_add.png +0 -0
  10. data/app/assets/images/iconza/icons/red_delete.png +0 -0
  11. data/app/assets/images/iconza/icons/red_edit.png +0 -0
  12. data/app/assets/images/iconza/icons/red_move.png +0 -0
  13. data/app/assets/javascripts/expandable_tree/expandable_tree.js.coffee +104 -0
  14. data/app/assets/javascripts/expandable_tree/hashchange.js.coffee +33 -0
  15. data/app/assets/javascripts/expandable_tree/initializer.js +6 -0
  16. data/app/assets/javascripts/expandable_tree/jquery.cookie.coffee +68 -0
  17. data/app/assets/javascripts/expandable_tree/restorable.js.coffee +125 -0
  18. data/app/assets/javascripts/nested_sortable/inline_operations.js.coffee +56 -0
  19. data/app/assets/javascripts/nested_sortable/jquery.ui.nestedSortable.js +358 -0
  20. data/app/assets/javascripts/render_tree_helper.js.coffee +82 -0
  21. data/app/assets/javascripts/sortable_tree/initializer.js +3 -0
  22. data/app/assets/javascripts/sortable_tree/sortable_tree.js.coffee +60 -0
  23. data/app/assets/stylesheets/expandable_tree.css.scss +26 -0
  24. data/app/assets/stylesheets/nested_options.css.scss +25 -0
  25. data/app/assets/stylesheets/sortable_tree.css.scss +108 -0
  26. data/app/assets/stylesheets/tree.css.scss +35 -0
  27. data/app/controllers/jquery_sortable_tree_controller.rb +93 -0
  28. data/app/helpers/jquery_sortable_tree_helper/render_expandable_tree_helper.rb +27 -0
  29. data/app/helpers/jquery_sortable_tree_helper/render_indented_options_helper.rb +37 -0
  30. data/app/helpers/jquery_sortable_tree_helper/render_nested_options_helper.rb +29 -0
  31. data/app/helpers/jquery_sortable_tree_helper/render_sortable_tree_helper.rb +65 -0
  32. data/app/helpers/jquery_sortable_tree_helper/render_tree_helper.rb +23 -0
  33. data/app/helpers/jquery_sortable_tree_helper.rb +142 -0
  34. data/app/inputs/indented_collection_select_input.rb +12 -0
  35. data/lib/fake.example +44 -0
  36. data/lib/generators/jquery_sortable_tree/views_generator.rb +56 -0
  37. data/lib/jquery_sortable_tree/engine.rb +6 -0
  38. data/lib/jquery_sortable_tree/version.rb +3 -0
  39. data/lib/jquery_sortable_tree.rb +13 -0
  40. data/spec/dummy_app/Gemfile +38 -0
  41. data/spec/dummy_app/Gemfile.lock +206 -0
  42. data/spec/dummy_app/README.md +48 -0
  43. data/spec/dummy_app/Rakefile +7 -0
  44. data/spec/dummy_app/_test/fixtures/admin/pages.yml +7 -0
  45. data/spec/dummy_app/_test/fixtures/article_categories.yml +9 -0
  46. data/spec/dummy_app/_test/fixtures/comments.yml +13 -0
  47. data/spec/dummy_app/_test/fixtures/inventory/categories.yml +9 -0
  48. data/spec/dummy_app/_test/functional/inventory/category_controller_test.rb +14 -0
  49. data/spec/dummy_app/_test/performance/browsing_test.rb +12 -0
  50. data/spec/dummy_app/_test/test_helper.rb +13 -0
  51. data/spec/dummy_app/_test/unit/admin/page_test.rb +7 -0
  52. data/spec/dummy_app/_test/unit/article_category_test.rb +7 -0
  53. data/spec/dummy_app/_test/unit/comment_test.rb +7 -0
  54. data/spec/dummy_app/_test/unit/helpers/inventory/category_helper_test.rb +4 -0
  55. data/spec/dummy_app/_test/unit/inventory/category_test.rb +7 -0
  56. data/spec/dummy_app/app/assets/images/rails.png +0 -0
  57. data/spec/dummy_app/app/assets/javascripts/application.js +11 -0
  58. data/spec/dummy_app/app/assets/stylesheets/application.css +11 -0
  59. data/spec/dummy_app/app/controllers/admin/pages_controller.rb +35 -0
  60. data/spec/dummy_app/app/controllers/application_controller.rb +3 -0
  61. data/spec/dummy_app/app/controllers/article_categories_controller.rb +11 -0
  62. data/spec/dummy_app/app/controllers/inventory/categories_controller.rb +15 -0
  63. data/spec/dummy_app/app/controllers/pages_controller.rb +30 -0
  64. data/spec/dummy_app/app/controllers/welcome_controller.rb +3 -0
  65. data/spec/dummy_app/app/models/admin/page.rb +4 -0
  66. data/spec/dummy_app/app/models/admin.rb +5 -0
  67. data/spec/dummy_app/app/models/article_category.rb +4 -0
  68. data/spec/dummy_app/app/models/inventory/category.rb +4 -0
  69. data/spec/dummy_app/app/models/inventory.rb +5 -0
  70. data/spec/dummy_app/app/models/page.rb +4 -0
  71. data/spec/dummy_app/app/views/admin/pages/indented_options.html.haml +3 -0
  72. data/spec/dummy_app/app/views/admin/pages/index.html.haml +8 -0
  73. data/spec/dummy_app/app/views/admin/pages/manage.html.haml +3 -0
  74. data/spec/dummy_app/app/views/admin/pages/namespaced_link.html.haml +3 -0
  75. data/spec/dummy_app/app/views/admin/pages/nested_options.html.haml +3 -0
  76. data/spec/dummy_app/app/views/admin/pages/node_manage.html.haml +12 -0
  77. data/spec/dummy_app/app/views/article_categories/index.html.haml +3 -0
  78. data/spec/dummy_app/app/views/article_categories/manage.html.haml +4 -0
  79. data/spec/dummy_app/app/views/inventory/categories/index.html.haml +3 -0
  80. data/spec/dummy_app/app/views/inventory/categories/manage.html.haml +4 -0
  81. data/spec/dummy_app/app/views/layouts/application.html.erb +18 -0
  82. data/spec/dummy_app/app/views/pages/expand.html.haml +8 -0
  83. data/spec/dummy_app/app/views/pages/expand_node.html.haml +1 -0
  84. data/spec/dummy_app/app/views/pages/indented_options.html.haml +3 -0
  85. data/spec/dummy_app/app/views/pages/index.html.haml +3 -0
  86. data/spec/dummy_app/app/views/pages/manage.html.haml +7 -0
  87. data/spec/dummy_app/app/views/pages/nested_options.html.haml +3 -0
  88. data/spec/dummy_app/app/views/welcome/index.html.haml +42 -0
  89. data/spec/dummy_app/config/application.rb +48 -0
  90. data/spec/dummy_app/config/boot.rb +6 -0
  91. data/spec/dummy_app/config/database.yml +7 -0
  92. data/spec/dummy_app/config/database.yml.example +7 -0
  93. data/spec/dummy_app/config/environment.rb +5 -0
  94. data/spec/dummy_app/config/environments/development.rb +30 -0
  95. data/spec/dummy_app/config/environments/production.rb +61 -0
  96. data/spec/dummy_app/config/environments/test.rb +42 -0
  97. data/spec/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
  98. data/spec/dummy_app/config/initializers/inflections.rb +10 -0
  99. data/spec/dummy_app/config/initializers/mime_types.rb +5 -0
  100. data/spec/dummy_app/config/initializers/secret_token.rb +7 -0
  101. data/spec/dummy_app/config/initializers/session_store.rb +8 -0
  102. data/spec/dummy_app/config/initializers/wrap_parameters.rb +14 -0
  103. data/spec/dummy_app/config/locales/en.yml +28 -0
  104. data/spec/dummy_app/config/routes.rb +53 -0
  105. data/spec/dummy_app/config.ru +4 -0
  106. data/spec/dummy_app/db/development.db +0 -0
  107. data/spec/dummy_app/db/migrate/20120211053457_create_pages.rb +16 -0
  108. data/spec/dummy_app/db/migrate/20120503173258_create_article_categories.rb +16 -0
  109. data/spec/dummy_app/db/migrate/20120508093823_create_inventory_categories.rb +16 -0
  110. data/spec/dummy_app/db/migrate/20130128160328_create_admin_pages.rb +16 -0
  111. data/spec/dummy_app/db/schema.rb +64 -0
  112. data/spec/dummy_app/db/seeds.rb +97 -0
  113. data/spec/dummy_app/db/test.db +0 -0
  114. data/spec/dummy_app/doc/README_FOR_APP +2 -0
  115. data/spec/dummy_app/lib/tasks/db_bootstrap.rake +16 -0
  116. data/spec/dummy_app/log/development.log +22714 -0
  117. data/spec/dummy_app/public/404.html +26 -0
  118. data/spec/dummy_app/public/422.html +26 -0
  119. data/spec/dummy_app/public/500.html +26 -0
  120. data/spec/dummy_app/public/favicon.ico +0 -0
  121. data/spec/dummy_app/public/robots.txt +5 -0
  122. data/spec/dummy_app/script/rails +6 -0
  123. data/spec/dummy_app/spec/build_tree_helper.rb +39 -0
  124. data/spec/dummy_app/spec/spec_helper.rb +52 -0
  125. data/spec/dummy_app/spec/views/pages/index.html.haml_spec.rb +48 -0
  126. data/spec/dummy_app/tmp/cache/assets/development/sass/8ecb1409c36a90649b49ac975da6493b50db6d95/expandable_tree.css.scssc +0 -0
  127. data/spec/dummy_app/tmp/cache/assets/development/sass/8ecb1409c36a90649b49ac975da6493b50db6d95/nested_options.css.scssc +0 -0
  128. data/spec/dummy_app/tmp/cache/assets/development/sass/8ecb1409c36a90649b49ac975da6493b50db6d95/sortable_tree.css.scssc +0 -0
  129. data/spec/dummy_app/tmp/cache/assets/development/sass/8ecb1409c36a90649b49ac975da6493b50db6d95/tree.css.scssc +0 -0
  130. data/spec/dummy_app/tmp/cache/assets/development/sprockets/058d9080443081a540c61e79945ebf47 +0 -0
  131. data/spec/dummy_app/tmp/cache/assets/development/sprockets/06512a74da586fbbce22e1cd023f5f9b +0 -0
  132. data/spec/dummy_app/tmp/cache/assets/development/sprockets/06f9ffc86fda6ef4279cabf09f68e631 +0 -0
  133. data/spec/dummy_app/tmp/cache/assets/development/sprockets/0702872e43cbcc4c2b6d097f7fe035e7 +0 -0
  134. data/spec/dummy_app/tmp/cache/assets/development/sprockets/07400ad691b6b3bbcf10ee74e64d72b7 +0 -0
  135. data/spec/dummy_app/tmp/cache/assets/development/sprockets/0a382d7e102e254c52006bed6975001d +0 -0
  136. data/spec/dummy_app/tmp/cache/assets/development/sprockets/0a8a33aec09977105c0190f6b8c2ca49 +0 -0
  137. data/spec/dummy_app/tmp/cache/assets/development/sprockets/0b2e7c9a5645a67e6af72feeaa70b633 +0 -0
  138. data/spec/dummy_app/tmp/cache/assets/development/sprockets/0c5e7aa7ad8e39ced2e25d911b060c3a +0 -0
  139. data/spec/dummy_app/tmp/cache/assets/development/sprockets/0fc4a5842f45f40d2e1283df0025ac7e +0 -0
  140. data/spec/dummy_app/tmp/cache/assets/development/sprockets/12eb4832c22cd32076db3d3eddcd941b +0 -0
  141. data/spec/dummy_app/tmp/cache/assets/development/sprockets/13d999d14a434a925372c43c3633f355 +0 -0
  142. data/spec/dummy_app/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  143. data/spec/dummy_app/tmp/cache/assets/development/sprockets/14805e3ed08782f4b821fe6cfd03d911 +0 -0
  144. data/spec/dummy_app/tmp/cache/assets/development/sprockets/15cc819db1fd73a5d6ccd95fba030668 +0 -0
  145. data/spec/dummy_app/tmp/cache/assets/development/sprockets/1607bba44953c4434330d20d0cd747f4 +0 -0
  146. data/spec/dummy_app/tmp/cache/assets/development/sprockets/16b9e0f8dc1fdd8bea7b606f065d205d +0 -0
  147. data/spec/dummy_app/tmp/cache/assets/development/sprockets/1a780b90bf4d532e88e6943e93f18320 +0 -0
  148. data/spec/dummy_app/tmp/cache/assets/development/sprockets/1e445aefca5bc750ef4f584ec1dc0849 +0 -0
  149. data/spec/dummy_app/tmp/cache/assets/development/sprockets/1e9c5d8fa6de36416732b4eb490ceb6f +0 -0
  150. data/spec/dummy_app/tmp/cache/assets/development/sprockets/1ea633756c6cc95716a7887e44f88da7 +0 -0
  151. data/spec/dummy_app/tmp/cache/assets/development/sprockets/1ece2c45f188a29a36b208442154f8a2 +0 -0
  152. data/spec/dummy_app/tmp/cache/assets/development/sprockets/2172c90088dc36adff9ec10b3384286e +0 -0
  153. data/spec/dummy_app/tmp/cache/assets/development/sprockets/2489731b3ac988935fe92593f0f2edbf +0 -0
  154. data/spec/dummy_app/tmp/cache/assets/development/sprockets/27c712c397ece8a28de4ff2044a3f722 +0 -0
  155. data/spec/dummy_app/tmp/cache/assets/development/sprockets/28eefd9e9c7ea2e1414cd10a6d184ae5 +0 -0
  156. data/spec/dummy_app/tmp/cache/assets/development/sprockets/2a013e71f11699ea897968c03d3f4355 +0 -0
  157. data/spec/dummy_app/tmp/cache/assets/development/sprockets/2c4f283baa7b297e503fe2d75f959b06 +0 -0
  158. data/spec/dummy_app/tmp/cache/assets/development/sprockets/2cf86cf22c1bd9a69271904cb4a1c131 +0 -0
  159. data/spec/dummy_app/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  160. data/spec/dummy_app/tmp/cache/assets/development/sprockets/2fa38257718e8b4641d97f10b43d1ac7 +0 -0
  161. data/spec/dummy_app/tmp/cache/assets/development/sprockets/2fd038eaf9bbdb2d1f4fe4afd3aeb654 +0 -0
  162. data/spec/dummy_app/tmp/cache/assets/development/sprockets/303d5268aec48d5bd29ea616e15ea1cd +0 -0
  163. data/spec/dummy_app/tmp/cache/assets/development/sprockets/309e5bc3a9891c7dfcb01887b7c973a5 +0 -0
  164. data/spec/dummy_app/tmp/cache/assets/development/sprockets/30f138394dc8bad04a7ad6c19f3ee922 +0 -0
  165. data/spec/dummy_app/tmp/cache/assets/development/sprockets/31036ef469da85883b40b6b4ee37e61e +0 -0
  166. data/spec/dummy_app/tmp/cache/assets/development/sprockets/31a9b7e7b828d0633af58b75c59273de +0 -0
  167. data/spec/dummy_app/tmp/cache/assets/development/sprockets/332ad2cb8debd7079dda31bd72d43806 +0 -0
  168. data/spec/dummy_app/tmp/cache/assets/development/sprockets/344185411a898184d8eaa3f96536e50f +0 -0
  169. data/spec/dummy_app/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  170. data/spec/dummy_app/tmp/cache/assets/development/sprockets/364e7109a425ab206d5f8881b5d37cfc +0 -0
  171. data/spec/dummy_app/tmp/cache/assets/development/sprockets/37dd73a179070963cb766a24703a58a1 +0 -0
  172. data/spec/dummy_app/tmp/cache/assets/development/sprockets/39c9026282a865c56fac8e234419eb61 +0 -0
  173. data/spec/dummy_app/tmp/cache/assets/development/sprockets/3a592f975983e33afd63283ecac1de80 +0 -0
  174. data/spec/dummy_app/tmp/cache/assets/development/sprockets/3a7a7c1950ba3ca0968d0c8ffc9b8635 +0 -0
  175. data/spec/dummy_app/tmp/cache/assets/development/sprockets/3ab09536f24f9fbe56a56a012bf266d7 +0 -0
  176. data/spec/dummy_app/tmp/cache/assets/development/sprockets/3b22caac59de2c2af20c0e8bf86cf015 +0 -0
  177. data/spec/dummy_app/tmp/cache/assets/development/sprockets/3dbf5c413607e86fa3ff1f931887217e +0 -0
  178. data/spec/dummy_app/tmp/cache/assets/development/sprockets/4063ac4ee22e83471de121940c9a9689 +0 -0
  179. data/spec/dummy_app/tmp/cache/assets/development/sprockets/425aa438199f939cf930519e27539355 +0 -0
  180. data/spec/dummy_app/tmp/cache/assets/development/sprockets/43485146d4435be69b94512f4871b48a +0 -0
  181. data/spec/dummy_app/tmp/cache/assets/development/sprockets/43c3c0bfd40d48fa470d6369b70c4ed5 +0 -0
  182. data/spec/dummy_app/tmp/cache/assets/development/sprockets/44290e987cc9e134606381c2ed4c3e19 +0 -0
  183. data/spec/dummy_app/tmp/cache/assets/development/sprockets/450d1a68e0d88f6f859522ccf0e7fa75 +0 -0
  184. data/spec/dummy_app/tmp/cache/assets/development/sprockets/46ff8eb0f50fc17b55b2e65a1a9a1832 +0 -0
  185. data/spec/dummy_app/tmp/cache/assets/development/sprockets/498d1a8d06e7b8bd347f41609dfe7dbc +0 -0
  186. data/spec/dummy_app/tmp/cache/assets/development/sprockets/4da7d8ac21ee8ee7cbdde2edd894cc4e +0 -0
  187. data/spec/dummy_app/tmp/cache/assets/development/sprockets/505027f29aa1c70c5425d19ea9fb77ce +0 -0
  188. data/spec/dummy_app/tmp/cache/assets/development/sprockets/5073b1f44a8a2ee95c4368fb2610360d +0 -0
  189. data/spec/dummy_app/tmp/cache/assets/development/sprockets/50b1ef23635589d50f9b31642903f67c +0 -0
  190. data/spec/dummy_app/tmp/cache/assets/development/sprockets/51663175018a723eb6432251c4ff2e2a +0 -0
  191. data/spec/dummy_app/tmp/cache/assets/development/sprockets/5287e92c354e3bafe071e5853eb65ced +0 -0
  192. data/spec/dummy_app/tmp/cache/assets/development/sprockets/52955fb6b1313a736917570386d038f7 +0 -0
  193. data/spec/dummy_app/tmp/cache/assets/development/sprockets/54603322364591c06b6250b0584ab27e +0 -0
  194. data/spec/dummy_app/tmp/cache/assets/development/sprockets/55d364519e6304a1d512d881ced67211 +0 -0
  195. data/spec/dummy_app/tmp/cache/assets/development/sprockets/56d487b917bb9ff84706849c66fee0c7 +0 -0
  196. data/spec/dummy_app/tmp/cache/assets/development/sprockets/59f72211dfd90317c1bc78a481ae189d +0 -0
  197. data/spec/dummy_app/tmp/cache/assets/development/sprockets/5c6b037458b3843da5366697c858985e +0 -0
  198. data/spec/dummy_app/tmp/cache/assets/development/sprockets/5e8f4ca85fe26be682d2e563f23f1f9e +0 -0
  199. data/spec/dummy_app/tmp/cache/assets/development/sprockets/5f6cb8d54ddfd855f5fbfb72a4aac107 +0 -0
  200. data/spec/dummy_app/tmp/cache/assets/development/sprockets/6016aac84581a1ff8e9503adf790f0eb +0 -0
  201. data/spec/dummy_app/tmp/cache/assets/development/sprockets/604f08938cbe197b663267d4ac623b3c +0 -0
  202. data/spec/dummy_app/tmp/cache/assets/development/sprockets/63703decf049effbdea24cb40c7d8feb +0 -0
  203. data/spec/dummy_app/tmp/cache/assets/development/sprockets/65a64732023d6edc64645f6d67ab6376 +0 -0
  204. data/spec/dummy_app/tmp/cache/assets/development/sprockets/67e64bdc647ff62357f616466875cc05 +0 -0
  205. data/spec/dummy_app/tmp/cache/assets/development/sprockets/685130c66086333bc60a3e13426e637d +0 -0
  206. data/spec/dummy_app/tmp/cache/assets/development/sprockets/68bc948f8a4f37f1b96c1ccef3501603 +0 -0
  207. data/spec/dummy_app/tmp/cache/assets/development/sprockets/68df326b958b409f9811f1aa1ae3df75 +0 -0
  208. data/spec/dummy_app/tmp/cache/assets/development/sprockets/693bc2b458236fe0f3db96348cb0d0dc +0 -0
  209. data/spec/dummy_app/tmp/cache/assets/development/sprockets/699daefc627fb5fde880b9a0791933b6 +0 -0
  210. data/spec/dummy_app/tmp/cache/assets/development/sprockets/6aba4f56935b86463d039d0849f8a4b4 +0 -0
  211. data/spec/dummy_app/tmp/cache/assets/development/sprockets/6ff566ad21a9b0caa51f55b63848d1d5 +0 -0
  212. data/spec/dummy_app/tmp/cache/assets/development/sprockets/729d2237d10c9e2170d23785478ca63f +0 -0
  213. data/spec/dummy_app/tmp/cache/assets/development/sprockets/76a8cd7f52d42a76574338632a5356d6 +0 -0
  214. data/spec/dummy_app/tmp/cache/assets/development/sprockets/779d045bffa46a9da91572f71bb4f33a +0 -0
  215. data/spec/dummy_app/tmp/cache/assets/development/sprockets/78762c001b9b200fa9963eee922b41d0 +0 -0
  216. data/spec/dummy_app/tmp/cache/assets/development/sprockets/7991e04eb66b191a868dbb38c761d2da +0 -0
  217. data/spec/dummy_app/tmp/cache/assets/development/sprockets/7af26b28f05d60534b847b073340b9d0 +0 -0
  218. data/spec/dummy_app/tmp/cache/assets/development/sprockets/7c3ec870c8e901cb6ca171c7345618c2 +0 -0
  219. data/spec/dummy_app/tmp/cache/assets/development/sprockets/7d5d91f945b7415354d7f6d3653e7d80 +0 -0
  220. data/spec/dummy_app/tmp/cache/assets/development/sprockets/7eecec59a10631fead107d7e8c265910 +0 -0
  221. data/spec/dummy_app/tmp/cache/assets/development/sprockets/8497b02b98b9d3a6e78388d6c1bab1f1 +0 -0
  222. data/spec/dummy_app/tmp/cache/assets/development/sprockets/858868dacf187de97fe2580f31d09dbe +0 -0
  223. data/spec/dummy_app/tmp/cache/assets/development/sprockets/859c3817c6f5b6d64e457ccd9a33d5a2 +0 -0
  224. data/spec/dummy_app/tmp/cache/assets/development/sprockets/86f13c507e9e995021b05371d252c33c +0 -0
  225. data/spec/dummy_app/tmp/cache/assets/development/sprockets/8717579ef5b551df9b2635f59120a0e1 +0 -0
  226. data/spec/dummy_app/tmp/cache/assets/development/sprockets/888dd6c485e0655b1ca9bfde716acdda +0 -0
  227. data/spec/dummy_app/tmp/cache/assets/development/sprockets/88b7acf651a9d0e1c9b3c8e6db719467 +0 -0
  228. data/spec/dummy_app/tmp/cache/assets/development/sprockets/88f65fc30613c8283f186e248253c020 +0 -0
  229. data/spec/dummy_app/tmp/cache/assets/development/sprockets/8a6aebb20a64dd2680834fa0d28bf832 +0 -0
  230. data/spec/dummy_app/tmp/cache/assets/development/sprockets/8a7d0e83eaa7cfb2826796e2c1a81a65 +0 -0
  231. data/spec/dummy_app/tmp/cache/assets/development/sprockets/902a894fafabac558abf12953428d975 +0 -0
  232. data/spec/dummy_app/tmp/cache/assets/development/sprockets/90c19158b0d4f03b467216c6f9b61af2 +0 -0
  233. data/spec/dummy_app/tmp/cache/assets/development/sprockets/91da1a8fa92fc4acdb6f8fb1658eff85 +0 -0
  234. data/spec/dummy_app/tmp/cache/assets/development/sprockets/958c546e8b56eecbfd2357ee9984f986 +0 -0
  235. data/spec/dummy_app/tmp/cache/assets/development/sprockets/977fe9c1da3ce7cbef3ec54cd7681b57 +0 -0
  236. data/spec/dummy_app/tmp/cache/assets/development/sprockets/98048e0cb396b79d4352a7d10737bc22 +0 -0
  237. data/spec/dummy_app/tmp/cache/assets/development/sprockets/9828e6214ad484fda452904b4591a6ba +0 -0
  238. data/spec/dummy_app/tmp/cache/assets/development/sprockets/9915a7d7fc327736e2852c02cf683916 +0 -0
  239. data/spec/dummy_app/tmp/cache/assets/development/sprockets/99dd18a65861aff71f60940f3f904dc4 +0 -0
  240. data/spec/dummy_app/tmp/cache/assets/development/sprockets/9b8b02558a49e17f6230fd1a84af03ac +0 -0
  241. data/spec/dummy_app/tmp/cache/assets/development/sprockets/9daf110b844179988cda473c3702cd36 +0 -0
  242. data/spec/dummy_app/tmp/cache/assets/development/sprockets/9e98d3ede9a4ae58ad176c09aac8784c +0 -0
  243. data/spec/dummy_app/tmp/cache/assets/development/sprockets/9f2acc37eeea8b15228a38ecbcfe12ec +0 -0
  244. data/spec/dummy_app/tmp/cache/assets/development/sprockets/9f304eccc018ffb73d8dbdea67ff4c45 +0 -0
  245. data/spec/dummy_app/tmp/cache/assets/development/sprockets/a0ac3dab292e1eb99d5e8a524e6dfded +0 -0
  246. data/spec/dummy_app/tmp/cache/assets/development/sprockets/a19531c0b551d0e8aaa386a2cba28621 +0 -0
  247. data/spec/dummy_app/tmp/cache/assets/development/sprockets/a1b5928996636a64ed28d5c815722fc0 +0 -0
  248. data/spec/dummy_app/tmp/cache/assets/development/sprockets/a2c39932df9ec8c9bcd8e1f4a84240dd +0 -0
  249. data/spec/dummy_app/tmp/cache/assets/development/sprockets/a2e4e33192daa77f118bde803b5f469e +0 -0
  250. data/spec/dummy_app/tmp/cache/assets/development/sprockets/a43272bdd86ec2506b047bc1e4ce8876 +0 -0
  251. data/spec/dummy_app/tmp/cache/assets/development/sprockets/a7e1c04200e6e4bda31455a74405ff27 +0 -0
  252. data/spec/dummy_app/tmp/cache/assets/development/sprockets/a971e4dcd80c8771557c6770de027db9 +0 -0
  253. data/spec/dummy_app/tmp/cache/assets/development/sprockets/aa295fd96f916013ffee63976fc76a95 +0 -0
  254. data/spec/dummy_app/tmp/cache/assets/development/sprockets/aa5ab09e4efff43a501273bba49aff5a +0 -0
  255. data/spec/dummy_app/tmp/cache/assets/development/sprockets/ab7de79e9f45ea0210ca722448a61ee6 +0 -0
  256. data/spec/dummy_app/tmp/cache/assets/development/sprockets/abc033045fbf49313622395790a41449 +0 -0
  257. data/spec/dummy_app/tmp/cache/assets/development/sprockets/ac5ba64ea91a44c78d859322e8007b51 +0 -0
  258. data/spec/dummy_app/tmp/cache/assets/development/sprockets/ae56fc628b3fcbc09e9d6bc9cfcfa47f +0 -0
  259. data/spec/dummy_app/tmp/cache/assets/development/sprockets/af312b037fcda8a7c4d4314bbb1294d6 +0 -0
  260. data/spec/dummy_app/tmp/cache/assets/development/sprockets/b0a443220285aa4214c99886f304be36 +0 -0
  261. data/spec/dummy_app/tmp/cache/assets/development/sprockets/b12fd4d4c75c5d4ecedeb33e9015d240 +0 -0
  262. data/spec/dummy_app/tmp/cache/assets/development/sprockets/b24f7fb90e26a052f58af7aec2887f99 +0 -0
  263. data/spec/dummy_app/tmp/cache/assets/development/sprockets/b31281285c049738a71f17d3bce0cb07 +0 -0
  264. data/spec/dummy_app/tmp/cache/assets/development/sprockets/b3ebffc5d529a910f098e186052959ec +0 -0
  265. data/spec/dummy_app/tmp/cache/assets/development/sprockets/b6767aa65b283214e52c1b488053348a +0 -0
  266. data/spec/dummy_app/tmp/cache/assets/development/sprockets/b76e4c022c5b8441b34d7fd884f01591 +0 -0
  267. data/spec/dummy_app/tmp/cache/assets/development/sprockets/b7832ccf4cb727dbb1db2fa906ba58ce +0 -0
  268. data/spec/dummy_app/tmp/cache/assets/development/sprockets/b7fda322633dec2bac36ebd075fca86b +0 -0
  269. data/spec/dummy_app/tmp/cache/assets/development/sprockets/b993ae256cdd45c1f983da2d611049a3 +0 -0
  270. data/spec/dummy_app/tmp/cache/assets/development/sprockets/badb668711397918483b38b6452a19ce +0 -0
  271. data/spec/dummy_app/tmp/cache/assets/development/sprockets/bc96c4fb801c05f926e1bc3fa935418b +0 -0
  272. data/spec/dummy_app/tmp/cache/assets/development/sprockets/bd574a8c5be676a00338f53b536d16c7 +0 -0
  273. data/spec/dummy_app/tmp/cache/assets/development/sprockets/bdff1b5babecc1dd5f99a5878c240298 +0 -0
  274. data/spec/dummy_app/tmp/cache/assets/development/sprockets/beebf50fccb9786a6b9c15060939e196 +0 -0
  275. data/spec/dummy_app/tmp/cache/assets/development/sprockets/c0ecb07d07862572d3e52a8b48245757 +0 -0
  276. data/spec/dummy_app/tmp/cache/assets/development/sprockets/c1d57e1af37bb3d7fec10b83b501c561 +0 -0
  277. data/spec/dummy_app/tmp/cache/assets/development/sprockets/c32f36794c5f61e47ff16beed6cd32ee +0 -0
  278. data/spec/dummy_app/tmp/cache/assets/development/sprockets/c546515632c00eb37eb345e92d604abc +0 -0
  279. data/spec/dummy_app/tmp/cache/assets/development/sprockets/c7383cde7ee415f0a343bfe658885afc +0 -0
  280. data/spec/dummy_app/tmp/cache/assets/development/sprockets/c93eebdbd34ccde24867d33a75ba23bb +0 -0
  281. data/spec/dummy_app/tmp/cache/assets/development/sprockets/cc343c6575f3d88e77e5d0c54208f131 +0 -0
  282. data/spec/dummy_app/tmp/cache/assets/development/sprockets/cc66ba8f2c55f0e0201e9c5d3fb9756a +0 -0
  283. data/spec/dummy_app/tmp/cache/assets/development/sprockets/cd0ab14140d01fee32d8cd011f558895 +0 -0
  284. data/spec/dummy_app/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  285. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d0182afb2a6b3793c9b793d174a32c52 +0 -0
  286. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d0ff728fdab90faf6864895c4388b9a3 +0 -0
  287. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d22147d54feb1d5083b1858b3f0ca9d4 +0 -0
  288. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d281f19fc3b6a6755f669021ba1f1e6c +0 -0
  289. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d383bce808d440db9243b6a766172489 +0 -0
  290. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d3bc3752c772eeb2e0b3c2918cc863a6 +0 -0
  291. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  292. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d7fb14951075b1ec677cc130302a26b2 +0 -0
  293. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d893535a31ef07ab97ed6965cb3f0fb5 +0 -0
  294. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d8e009b8040122f415eeab5ea2b48e58 +0 -0
  295. data/spec/dummy_app/tmp/cache/assets/development/sprockets/d99ca00bff5f10b356270d8c956f4012 +0 -0
  296. data/spec/dummy_app/tmp/cache/assets/development/sprockets/db193f817e5de1268f9e9397829aa188 +0 -0
  297. data/spec/dummy_app/tmp/cache/assets/development/sprockets/dd22a990e8e9fc359a59039954abc0c3 +0 -0
  298. data/spec/dummy_app/tmp/cache/assets/development/sprockets/dddcb7f44b3421803102a90cef903b2a +0 -0
  299. data/spec/dummy_app/tmp/cache/assets/development/sprockets/de89d996da9e70756b13c808c1db5251 +0 -0
  300. data/spec/dummy_app/tmp/cache/assets/development/sprockets/dea7e9cb07d7e5890a38c24eba35e55e +0 -0
  301. data/spec/dummy_app/tmp/cache/assets/development/sprockets/df2e404f81bab3f3b50423d7aa652844 +0 -0
  302. data/spec/dummy_app/tmp/cache/assets/development/sprockets/e076be05d795e33011e9165ce3565719 +0 -0
  303. data/spec/dummy_app/tmp/cache/assets/development/sprockets/e16add15b2c7174bd21c0d70d318f4fc +0 -0
  304. data/spec/dummy_app/tmp/cache/assets/development/sprockets/e2158064cf90553ca96435e06073bb60 +0 -0
  305. data/spec/dummy_app/tmp/cache/assets/development/sprockets/e4cef9cfcc9f94843f54b52b318f593c +0 -0
  306. data/spec/dummy_app/tmp/cache/assets/development/sprockets/e54d18d8cbe7b6ab25445a607c15674c +0 -0
  307. data/spec/dummy_app/tmp/cache/assets/development/sprockets/e5f6b1c85d1d4ec5a26284694ab8d660 +0 -0
  308. data/spec/dummy_app/tmp/cache/assets/development/sprockets/e7cc7fb019fd86a28d82c7f63d749ebe +0 -0
  309. data/spec/dummy_app/tmp/cache/assets/development/sprockets/e8b94e5699ca066cbff81d9ed6727dbf +0 -0
  310. data/spec/dummy_app/tmp/cache/assets/development/sprockets/e901ea625274dfd094b70154e09d58b2 +0 -0
  311. data/spec/dummy_app/tmp/cache/assets/development/sprockets/eb794751bdec36ee921a2fbebfb6c7e6 +0 -0
  312. data/spec/dummy_app/tmp/cache/assets/development/sprockets/eccc72c3ec8522b88d235892cd8f45f2 +0 -0
  313. data/spec/dummy_app/tmp/cache/assets/development/sprockets/f1365895382790389d013528129a140a +0 -0
  314. data/spec/dummy_app/tmp/cache/assets/development/sprockets/f27b5dad4fdaec1c4ede5f174b64de32 +0 -0
  315. data/spec/dummy_app/tmp/cache/assets/development/sprockets/f2c23c8157dd64d926ee77c4b955f6b6 +0 -0
  316. data/spec/dummy_app/tmp/cache/assets/development/sprockets/f3e483f413d3151c5849cbd83476ce0a +0 -0
  317. data/spec/dummy_app/tmp/cache/assets/development/sprockets/f76fdcf47a0b7ee91ca690326d152bee +0 -0
  318. data/spec/dummy_app/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  319. data/spec/dummy_app/tmp/cache/assets/development/sprockets/f903a7ee38dcd742dca81df64e11733e +0 -0
  320. data/spec/dummy_app/tmp/cache/assets/development/sprockets/f9295b3b0f4d6dc11fdffaa7e0d02f72 +0 -0
  321. data/spec/dummy_app/tmp/cache/assets/development/sprockets/fa12d1dad434ff516a64628a635c07c8 +0 -0
  322. data/spec/dummy_app/tmp/cache/assets/development/sprockets/fae07930e81fdd4084871f66e4634e8a +0 -0
  323. data/spec/dummy_app/tmp/cache/assets/development/sprockets/fc182fc9375dd4ba9b0e0039d71f0944 +0 -0
  324. data/spec/dummy_app/tmp/cache/assets/development/sprockets/fd5d00a09369cb7c59b53d72ca896828 +0 -0
  325. data/spec/dummy_app/tmp/cache/assets/development/sprockets/fdf1d8b5d1d7b6c5fe5e2f5b467812a3 +0 -0
  326. data/spec/dummy_app/tmp/cache/assets/development/sprockets/fef1622202b16661f9ae083c25eaa0cd +0 -0
  327. data/spec/dummy_app/tmp/cache/assets/development/sprockets/ff5a0e8ee643dae44f31640f626ce94a +0 -0
  328. metadata +726 -0
@@ -0,0 +1,26 @@
1
+ .sortable_tree{
2
+ &.expandable{
3
+ h4{
4
+ margin-left: 50px;
5
+ }
6
+ }
7
+
8
+ .expand{
9
+ float: left;
10
+ cursor: pointer;
11
+
12
+ border: 1px solid lightgray;
13
+ color: lightgray;
14
+
15
+ font-size: 13px;
16
+ font-weight: normal;
17
+ line-height: 13px;
18
+ text-align: center;
19
+
20
+ width: 13px;
21
+ height: 13px;
22
+ margin: 3px 10px 0 0;
23
+
24
+ &.empty{ display:none !important; }
25
+ }
26
+ }
@@ -0,0 +1,25 @@
1
+ .nested_options{
2
+ padding: 3px;
3
+ font-size: 18px;
4
+ font-family: Arial;
5
+ border: 1px solid gray;
6
+
7
+ option{
8
+ color: black; padding: 3px;
9
+ &.selected{ font-weight: bold; color: red; }
10
+ }
11
+
12
+ @for $i from 1 through 2{
13
+ .l_#{$i}{
14
+ padding-left: #{($i - 1)*15}px;
15
+ font-size: #{(100 - $i * 10) + '%'};
16
+ }
17
+ }
18
+
19
+ @for $i from 3 through 10{
20
+ .l_#{$i}{
21
+ padding-left: #{($i - 1)*15}px;
22
+ font-size: 70%;
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,108 @@
1
+ .sortable_tree{
2
+ margin: 0; padding: 0;
3
+ *{ margin: 0; padding: 0; }
4
+
5
+ ol{
6
+ margin: 0 0 0 13px;
7
+ padding: 0 0 0 15px;
8
+ border-left: 1px dashed gray;
9
+ list-style: none outside none;
10
+ }
11
+
12
+ li{
13
+ margin-bottom:5px;
14
+ position: relative;
15
+ list-style: none outside none;
16
+ }
17
+
18
+ a{
19
+ color:#000;
20
+ font-size:10pt;
21
+ font-weight:normal;
22
+ text-decoration:none;
23
+ line-height: 150%;
24
+ margin-left:30px;
25
+ margin-right:120px;
26
+ display:block;
27
+ &:hover{ text-decoration: underline; }
28
+ }
29
+
30
+ h4{
31
+ margin-left: 30px;
32
+
33
+ a{
34
+ color: #333;
35
+ font-size: 14px;
36
+ margin-left: 0;
37
+ &:hover{ background: #eee; }
38
+ }
39
+ }
40
+
41
+ p{
42
+ margin-right: 75px;
43
+ padding: 5px;
44
+ }
45
+
46
+ .handle{
47
+ background: transparent image-url("iconza/icons/move.png");
48
+ background-position: center center;
49
+
50
+ width: 16px;
51
+ height: 16px;
52
+ margin: 3px 10px 0 0;
53
+ float: left;
54
+ cursor: move;
55
+
56
+ &:hover{ background: transparent image-url("iconza/icons/red_move.png"); }
57
+ }
58
+
59
+ .item{
60
+ padding: 5px;
61
+ background: #f7f7f7;
62
+ border-radius: 3px;
63
+ margin-bottom: 5px;
64
+ &:hover{ background: #eee; }
65
+ }
66
+
67
+ .placeholder {
68
+ background-color: #EEF;
69
+ border: 1px dashed blue;
70
+ }
71
+
72
+ .ui-nestedSortable-error {
73
+ background: #FAA;
74
+ color: #8a1f11;
75
+ }
76
+
77
+ .controls{
78
+ position: absolute;
79
+ top: 1px; right: 10px;
80
+
81
+ a{
82
+ width: 20px;
83
+ height: 20px;
84
+ display: block;
85
+
86
+ float: left;
87
+ padding: 5px;
88
+ cursor: pointer;
89
+ position: relative;
90
+
91
+ margin: 0 0 5px 5px;
92
+ overflow: hidden; zoom: 1;
93
+
94
+ &.new{
95
+ background: transparent image-url("iconza/icons/add.png") no-repeat scroll center center;
96
+ &:hover{ background: transparent image-url("iconza/icons/red_add.png") no-repeat scroll center center; }
97
+ }
98
+ &.edit{
99
+ background: transparent image-url("iconza/icons/edit.png") no-repeat scroll center center;
100
+ &:hover{ background: transparent image-url("iconza/icons/red_edit.png") no-repeat scroll center center; }
101
+ }
102
+ &.delete{
103
+ background: transparent image-url("iconza/icons/delete.png") no-repeat scroll center center;
104
+ &:hover{ background: transparent image-url("iconza/icons/red_delete.png") no-repeat scroll center center; }
105
+ }
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,35 @@
1
+ .tree{
2
+ margin:0; padding:0;
3
+ *{ margin: 0; padding: 0; }
4
+
5
+ ol{
6
+ margin: 0 0 0 13px;
7
+ padding: 0 0 0 15px;
8
+ border-left: 1px dashed gray;
9
+ list-style: none outside none;
10
+ }
11
+
12
+ li{
13
+ margin-bottom:5px;
14
+ position: relative;
15
+ list-style: none outside none;
16
+ }
17
+
18
+ a{
19
+ color: black;
20
+ font-size: 14px;
21
+
22
+ &:hover {
23
+ color: black;
24
+ background: #ddd;
25
+ }
26
+ }
27
+
28
+ .item{
29
+ padding: 5px;
30
+ background: #eee;
31
+ margin-bottom: 5px;
32
+ border-radius: 3px;
33
+ &:hover{ background: #ddd; }
34
+ }
35
+ }
@@ -0,0 +1,93 @@
1
+ module JquerySortableTreeController
2
+ module DefineVariablesMethod
3
+ def sortable_model
4
+ @sortable_model ||= self.class.to_s.split(':').last.sub(/Controller/, '').singularize.constantize
5
+ end
6
+
7
+ def sortable_collection
8
+ @sortable_collection ||= self.class.to_s.split(':').last.sub(/Controller/,'').underscore.downcase
9
+ end
10
+
11
+ def the_define_common_variables
12
+ ["@#{sortable_collection.singularize}", sortable_collection, sortable_model]
13
+ end
14
+
15
+ def id
16
+ @id ||= params[:id].to_i
17
+ end
18
+
19
+ def parent_id
20
+ @parent_id ||= params[:parent_id].to_i
21
+ end
22
+
23
+ def sort
24
+ @sort ||= params[:tree_sort] == 'reversed' ? 'reversed_nested_set' : 'nested_set'
25
+ end
26
+
27
+ def prev_id
28
+ @prev_id ||= params[:prev_id].to_i
29
+ end
30
+
31
+ def next_id
32
+ @next_id ||= params[:next_id].to_i
33
+ end
34
+
35
+ def move_to_prev
36
+ @move_to_prev ||= params[:tree_sort] == 'reversed' ? :move_to_left_of : :move_to_right_of
37
+ end
38
+
39
+ def move_to_next
40
+ @move_to_next ||= params[:tree_sort] == 'reversed' ? :move_to_right_of : :move_to_left_of
41
+ end
42
+
43
+ def move_to_parent
44
+ :move_to_child_of
45
+ end
46
+
47
+ def object_to_rebuild
48
+ self.sortable_model.find(id)
49
+ end
50
+
51
+ def move_to_nowhere?
52
+ parent_id.zero? && prev_id.zero? && next_id.zero?
53
+ end
54
+
55
+ def prev_next_parent
56
+ return 'prev' unless prev_id.zero?
57
+ return 'next' unless next_id.zero?
58
+ return 'parent' unless parent_id.zero?
59
+ end
60
+
61
+ def move_to
62
+ send("move_to_#{prev_next_parent}")
63
+ end
64
+
65
+ def node_id
66
+ send("#{prev_next_parent}_id")
67
+ end
68
+
69
+ def node
70
+ sortable_model.find(node_id)
71
+ end
72
+ end
73
+
74
+ module ExpandNode
75
+ include DefineVariablesMethod
76
+
77
+ def expand_node
78
+ @children = object_to_rebuild.children.send(sort) if id && sort
79
+ return render(nothing: true, status: :no_content) if !@children || @children.count.zero?
80
+ render layout: false, template: "#{sortable_collection}/expand_node"
81
+ end
82
+ end
83
+
84
+ module Rebuild
85
+ include DefineVariablesMethod
86
+
87
+ def rebuild
88
+ return render(nothing: true, status: :no_content) if move_to_nowhere?
89
+ object_to_rebuild.send(move_to, node)
90
+ render(nothing: true, status: :ok)
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,27 @@
1
+ # DOC:
2
+ # We use Helper Methods for tree building,
3
+ # because it's faster than View Templates and Partials
4
+
5
+ # SECURITY note
6
+ # Prepare your data on server side for rendering
7
+ # or use h.html_escape(node.content)
8
+ # for escape potentially dangerous content
9
+ module JquerySortableTreeHelper
10
+ module RenderExpandableTreeHelper
11
+ class Render < JquerySortableTreeHelper::RenderSortableTreeHelper::Render
12
+ attr_accessor :h, :options
13
+
14
+ def initialize(h, options)
15
+ @h, @options = h, options
16
+ end
17
+
18
+ def div_item
19
+ h.content_tag(:div, handle + expand_button + edit_link + controls, class: :item)
20
+ end
21
+
22
+ def expand_button
23
+ h.content_tag(:b, '+', class: 'expand plus')
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ module JquerySortableTreeHelper
2
+ module RenderIndentedOptionsHelper
3
+ class Render
4
+ attr_accessor :h, :options
5
+
6
+ def initialize(h, options)
7
+ @h, @options = h, options
8
+ end
9
+
10
+ def render_node
11
+ h.content_tag(:option, title, tag_options) + children
12
+ end
13
+
14
+ def title
15
+ "\u202f" * (@options[:spacing] || 3).to_i * (@options[:level]-1) + node.send(@options[:title])
16
+ end
17
+
18
+ def tag_options
19
+ html_options = { value: node.id }
20
+
21
+ if options[:selected] == node
22
+ html_options[:selected] = 'selected'
23
+ html_options[:class] = 'selected'
24
+ end
25
+ html_options
26
+ end
27
+
28
+ def node
29
+ @options[:node]
30
+ end
31
+
32
+ def children
33
+ @options[:children].html_safe
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ module JquerySortableTreeHelper
2
+ module RenderNestedOptionsHelper
3
+ class Render
4
+ attr_accessor :h, :options
5
+
6
+ def initialize(h, options)
7
+ @h, @options = h, options
8
+ end
9
+
10
+ def render_node
11
+ @h.content_tag(:option, options[:node].send(options[:title]), tag_options) + children
12
+ end
13
+
14
+ def children
15
+ @options[:children].html_safe
16
+ end
17
+
18
+ def tag_options
19
+ opts = { class: "l_#{@options[:level]}", value: @options[:node][:id] }
20
+
21
+ if @options[:selected] == @options[:node]
22
+ opts[:class] += ' selected'
23
+ opts[:selected] = :selected
24
+ end
25
+ opts
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,65 @@
1
+ # DOC:
2
+ # We use Helper Methods for tree building,
3
+ # because it's faster than View Templates and Partials
4
+
5
+ # SECURITY note
6
+ # Prepare your data on server side for rendering
7
+ # or use h.html_escape(node.content)
8
+ # for escape potentially dangerous content
9
+ module JquerySortableTreeHelper
10
+ module RenderSortableTreeHelper
11
+ class Render
12
+ attr_accessor :h, :options
13
+
14
+ def initialize(h, options)
15
+ @h, @options = h, options
16
+ end
17
+
18
+ def render_node
19
+ return h.content_tag(:li, div_item + children,
20
+ class: :node,
21
+ data: { node_id: options[:node].id }
22
+ )
23
+ end
24
+
25
+ def div_item
26
+ h.content_tag(:div, handle + edit_link + controls, class: :item)
27
+ end
28
+
29
+ def handle
30
+ h.content_tag(:i, '', class: :handle)
31
+ end
32
+
33
+ def edit_link
34
+ h.content_tag(:h4, h.link_to(options[:node].send(options[:title]), show_path, class: :edit))
35
+ end
36
+
37
+ def show_link
38
+ h.content_tag(:h4,
39
+ h.link_to(options[:node].send(options[:title]),
40
+ h.url_for(options[:namespace] + [options[:node]]))
41
+ )
42
+ end
43
+
44
+ def controls
45
+ link_options = {
46
+ class: :delete,
47
+ method: :delete,
48
+ data: {
49
+ confirm: I18n.t('are_you_sure', default: 'Are you sure?'),
50
+ remote: true
51
+ }
52
+ }
53
+ h.content_tag(:div, h.link_to('', show_path, link_options), class: :controls)
54
+ end
55
+
56
+ def children
57
+ h.content_tag(:ol, options[:children].html_safe, class: :nested_set) unless options[:children].blank?
58
+ end
59
+
60
+ def show_path
61
+ h.url_for(controller: (options[:controller] || (options[:klass] && options[:klass].pluralize)), action: :show, id: options[:node].id, format: :json)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,23 @@
1
+ # DOC:
2
+ # We use Helper Methods for tree building,
3
+ # because it's faster than View Templates and Partials
4
+
5
+ # SECURITY note
6
+ # Prepare your data on server side for rendering
7
+ # or use h.html_escape(node.content)
8
+ # for escape potentially dangerous content
9
+ module JquerySortableTreeHelper
10
+ module RenderTreeHelper
11
+ class Render < JquerySortableTreeHelper::RenderSortableTreeHelper::Render
12
+ attr_accessor :h, :options
13
+
14
+ def initialize(h, options)
15
+ @h, @options = h, options
16
+ end
17
+
18
+ def div_item
19
+ h.content_tag(:div, show_link, class: :item)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,142 @@
1
+ module JquerySortableTreeHelper
2
+ # Ilya Zykin, zykin-ilya@ya.ru, Russia [Ivanovo, Saint Petersburg] 2009-2014
3
+ # github.com/the-teacher
4
+ TREE_RENDERERS = {
5
+ tree: RenderTreeHelper,
6
+ sortable: RenderSortableTreeHelper,
7
+ expandable: RenderExpandableTreeHelper,
8
+ nested_options: RenderNestedOptionsHelper,
9
+ indented_options: RenderIndentedOptionsHelper
10
+ }.freeze
11
+
12
+ ###############################################
13
+ # Common Base Methods
14
+ ###############################################
15
+
16
+ def define_class_of_elements_of tree
17
+ case
18
+ when tree.is_a?(ActiveRecord::Relation) then tree.name.to_s.underscore.downcase
19
+ when tree.empty? then nil
20
+ else tree.first.class.to_s.underscore.downcase
21
+ end
22
+ end
23
+
24
+ def build_tree_html context, render_module, options = {}
25
+ render_module::Render.new(context, options).render_node
26
+ end
27
+
28
+ ###############################################
29
+ # Shortcuts
30
+ ###############################################
31
+
32
+ def just_tree(tree, options = {})
33
+ build_server_tree(tree, { type: :tree }.merge!(options))
34
+ end
35
+
36
+ def base_data
37
+ {
38
+ model: params[:controller].singularize,
39
+ title: 'title',
40
+ max_levels: 5,
41
+ parent_id: params[:parent_id],
42
+ rebuild_url: send("rebuild_#{params[:controller]}_url"),
43
+ url: url_for(controller: params[:controller], action: :show, id: ':id', format: :json)
44
+ }
45
+ end
46
+
47
+ def space(height)
48
+ content_tag(:div, '&nbsp;'.html_safe, style: "height: #{height}px;")
49
+ end
50
+
51
+ def fake_node(options)
52
+ OpenStruct.new(options[:title] => '', id: ':id', children: nil)
53
+ end
54
+
55
+ def sortable_tree(tree, options = {})
56
+ space(20) +
57
+ add_new_node_form(base_data.merge(options)) +
58
+ content_tag(:ol, build_tree_html(self, TREE_RENDERERS[:sortable], base_options.merge(options).merge({ node: fake_node(options) })), class: 'fake-node hidden', style: 'display: none;') +
59
+ content_tag(:ol, build_server_tree(tree, { type: :sortable }.merge!(options)),
60
+ class: 'sortable_tree',
61
+ data: base_data.merge(options.slice(:parent_id, :model, :rebuild_url, :title, :max_levels))
62
+ )
63
+ end
64
+
65
+ def form_for_options(options)
66
+ {
67
+ html: { id: "new-#{options[:model]}-form" },
68
+ url: send("#{options[:model].pluralize}_path", format: :json),
69
+ method: :post,
70
+ remote: true
71
+ }
72
+ end
73
+
74
+ def add_new_node_form(options)
75
+ capture do
76
+ form_for(options[:model].to_sym, form_for_options(options)) do |f|
77
+ title_field = f.text_field options[:title].to_sym, required: true, class: 'form-control', placeholder: I18n.t('sortable_tree.title_of_new_node', default: "The #{options[:title]} of new #{options[:model]}")
78
+ concat content_tag(:div, title_field, class: 'form-group')
79
+ concat f.hidden_field :parent_id, value: options[:parent_id]
80
+ end
81
+ end
82
+ end
83
+
84
+ def nested_options(tree, options = {})
85
+ build_server_tree(tree, { type: :nested_options }.merge!(options))
86
+ end
87
+
88
+ def indented_options(tree, options = {})
89
+ build_server_tree(tree, { type: :indented_options }.merge!(options))
90
+ end
91
+
92
+ def expandable_tree(tree, options = {})
93
+ build_server_tree(tree, { type: :expandable }.merge!(options))
94
+ end
95
+
96
+ ###############################################
97
+ # Server Side Render Tree Helper
98
+ ###############################################
99
+
100
+ def base_options
101
+ {
102
+ id: :id,
103
+ title: :title,
104
+ node: nil,
105
+ type: :tree,
106
+ root: false,
107
+ level: 0,
108
+ namespace: [],
109
+ controller: params[:controller]
110
+ }
111
+ end
112
+
113
+ def build_children(tree, opts)
114
+ children = (opts[:boost][opts[:node].id.to_i] || [])
115
+ children.reduce('') { |r, elem| r + build_server_tree(tree, opts.merge(node: elem, root: false, level: opts[:level].next)) }
116
+ end
117
+
118
+ def roots(tree)
119
+ min_parent_id = tree.map(&:parent_id).compact.min
120
+ tree.select { |e| e.parent_id == min_parent_id }
121
+ end
122
+
123
+ def merge_base_options(tree, options)
124
+ opts = base_options.merge(options)
125
+ opts[:namespace] = [*opts[:namespace]]
126
+ opts[:render_module] ||= TREE_RENDERERS[opts[:type]]
127
+ opts[:klass] ||= define_class_of_elements_of(tree)
128
+ opts[:boost] ||= tree.group_by { |item| item.parent_id.to_i }
129
+ opts
130
+ end
131
+
132
+ def build_server_tree(tree, options = {})
133
+ tree = [*tree]
134
+ opts = merge_base_options(tree, options)
135
+
136
+ if opts[:node]
137
+ raw build_tree_html(self, opts[:render_module], opts.merge(children: build_children(tree, opts)))
138
+ else
139
+ raw (roots(tree) || []).reduce('') { |r, root| r + build_server_tree(tree, opts.merge(node: root, root: true, level: opts[:level].next)) }
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,12 @@
1
+ class IndentedCollectionSelectInput < SimpleForm::Inputs::CollectionSelectInput
2
+ def input
3
+ label_method, value_method = detect_collection_methods
4
+ collection.map! do |o|
5
+ depth_method = options[:depth_method] || :depth
6
+ spacing = (options[:spacing] || 3).to_i
7
+ label = "\u202f" * spacing * o.send(depth_method) + o.send(label_method)
8
+ [label, o.send(value_method)]
9
+ end
10
+ super
11
+ end
12
+ end
data/lib/fake.example ADDED
@@ -0,0 +1,44 @@
1
+ book = {
2
+ 'Programs' => {
3
+ 'Lexical Structure' => [
4
+ 'Comments',
5
+ 'Documentation',
6
+ 'Whitespace',
7
+ 'Literals',
8
+ 'Identifiers'
9
+ ]
10
+ }
11
+ }
12
+
13
+ def create_hub user, title
14
+ obj = user.send(:hubs).new
15
+ obj.title = title
16
+ obj.hub_type = :book
17
+ obj.state = :published
18
+ obj.save!
19
+ obj
20
+ end
21
+
22
+ def build_page_tree user, book, parent_obj = nil
23
+ book.each_pair do |key, value|
24
+ obj = create_hub(user, key)
25
+ obj.move_to_child_of(parent_obj) if parent_obj
26
+ parent_obj = obj
27
+
28
+ if value.is_a? Hash
29
+ build_page_tree(user, value, parent_obj)
30
+ end
31
+
32
+ if value.is_a? Array
33
+ value.each do |key|
34
+ obj = create_hub(user, key)
35
+ obj.move_to_child_of(parent_obj)
36
+ end
37
+ end
38
+
39
+ end
40
+ end
41
+
42
+ build_page_tree(User.first, book)
43
+
44
+ Hub.roots.of_(:book).last.self_and_descendants