compass-jquery-plugin 0.3.0.beta.24 → 0.3.0.beta.25

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 (341) hide show
  1. data/README.textile +10 -9
  2. data/VERSION.yml +1 -1
  3. data/compass-jquery-plugin.gemspec +292 -288
  4. data/gem_tasks/ical.rake +85 -0
  5. data/gem_tasks/jqtouch.rake +1 -25
  6. data/gem_tasks/jrails.rake +127 -94
  7. data/gem_tasks/jstree.rake +2 -1
  8. data/gem_tasks/mobile.rake +33 -2
  9. data/gem_tasks/rubygems.rake +1 -1
  10. data/gem_tasks/tools.rake +66 -0
  11. data/lib/{compiler.jar → google-compiler-20100917.jar} +0 -0
  12. data/lib/handle_js_files.rb +27 -30
  13. data/lib/jquery/ical.rb +7 -0
  14. data/lib/jquery/{jqical → ical}/calendar.rb +5 -5
  15. data/lib/jquery/{jqical → ical}/event.rb +117 -117
  16. data/lib/jquery/{jqical → ical}/helpers/ui_event_helper.rb +1 -1
  17. data/lib/jquery/tools.rb +2 -0
  18. data/lib/js.jar +0 -0
  19. data/lib/jslint-check.js +36 -0
  20. data/lib/jslint.js +5500 -0
  21. data/templates/dynatree/jquery.dynatree.js +1170 -784
  22. data/templates/dynatree/jquery.dynatree.min.js +77 -67
  23. data/templates/emulators/emulators/blackberry.landscape.scss +1 -0
  24. data/templates/emulators/emulators/blackberry.portrait.scss +2 -2
  25. data/templates/emulators/emulators/blackberry.torch.portrait.png +0 -0
  26. data/templates/emulators/emulators/iphone.landscape.scss +1 -0
  27. data/templates/emulators/emulators/iphone.portrait.png +0 -0
  28. data/templates/emulators/emulators/iphone.portrait.scss +2 -1
  29. data/templates/emulators/emulators/palm.landscape.scss +1 -0
  30. data/templates/emulators/emulators/palm.portrait.scss +3 -2
  31. data/templates/emulators/emulators/palm.pre.portrait.png +0 -0
  32. data/templates/{jqical → ical}/app/views/shared/_ui_event_for.js.haml +0 -0
  33. data/templates/ical/config/initializers/ical.rb +7 -0
  34. data/templates/{jqical/jquery.jqical.js → ical/jquery.ical.js} +0 -0
  35. data/templates/{jqical/jquery.jqical.min.js → ical/jquery.ical.min.js} +0 -0
  36. data/templates/{jqical/jquery/jqical.scss → ical/jquery/ical.scss} +1 -1
  37. data/templates/{jqical/jquery/jqical → ical/jquery/ical}/calendar.png +0 -0
  38. data/templates/{jqical/jquery/jqical → ical/jquery/ical}/clock.png +0 -0
  39. data/templates/ical/manifest.rb +10 -0
  40. data/templates/jqtouch/config/initializers/jqtouch.rb +1 -1
  41. data/templates/jqtouch/manifest.rb +0 -261
  42. data/templates/jrails/config/initializers/jrails.rb +3 -3
  43. data/templates/jrails/{jquery-1.4.3.js → jquery-1.4.4.js} +102 -47
  44. data/templates/jrails/jquery-1.4.4.min.js +152 -0
  45. data/templates/jrails/lib/tasks/haml.rake +55 -0
  46. data/templates/jrails/manifest.rb +4 -2
  47. data/templates/jstree/jquery.jstree.js +148 -64
  48. data/templates/jstree/jquery.jstree.min.js +219 -215
  49. data/templates/mobile/config/initializers/mobile.rb +1 -1
  50. data/templates/jqtouch/jquery/touch/glyphish/Read me first - license.txt b/data/templates/mobile/glyphish/Read me first - → license.txt +0 -0
  51. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/01-refresh.png +0 -0
  52. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/02-redo.png +0 -0
  53. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/03-loopback.png +0 -0
  54. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/04-squiggle.png +0 -0
  55. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/05-shuffle.png +0 -0
  56. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/06-magnifying-glass.png +0 -0
  57. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/07-map-marker.png +0 -0
  58. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/08-chat.png +0 -0
  59. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/09-chat2.png +0 -0
  60. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/10-medical.png +0 -0
  61. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/100-coffee.png +0 -0
  62. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/101-gameplan.png +0 -0
  63. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/102-walk.png +0 -0
  64. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/103-map.png +0 -0
  65. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/104-index-cards.png +0 -0
  66. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/105-piano.png +0 -0
  67. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/106-sliders.png +0 -0
  68. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/107-widescreen.png +0 -0
  69. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/108-badge.png +0 -0
  70. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/109-chicken.png +0 -0
  71. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/11-clock.png +0 -0
  72. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/110-bug.png +0 -0
  73. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/111-user.png +0 -0
  74. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/112-group.png +0 -0
  75. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/113-navigation.png +0 -0
  76. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/114-balloon.png +0 -0
  77. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/115-bow-and-arrow.png +0 -0
  78. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/116-controller.png +0 -0
  79. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/117-todo.png +0 -0
  80. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/118-coathanger.png +0 -0
  81. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/119-piggybank.png +0 -0
  82. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/12-eye.png +0 -0
  83. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/120-headphones.png +0 -0
  84. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/121-lanscape.png +0 -0
  85. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/122-stats.png +0 -0
  86. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/123-id-card.png +0 -0
  87. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/124-bullhorn.png +0 -0
  88. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/125-food.png +0 -0
  89. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/126-moon.png +0 -0
  90. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/127-sock.png +0 -0
  91. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/128-bone.png +0 -0
  92. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/129-golf.png +0 -0
  93. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/13-target.png +0 -0
  94. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/130-dice.png +0 -0
  95. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/14-tag.png +0 -0
  96. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/15-tags.png +0 -0
  97. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/16-line-chart.png +0 -0
  98. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/17-bar-chart.png +0 -0
  99. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/18-envelope.png +0 -0
  100. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/19-gear.png +0 -0
  101. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/20-gear2.png +0 -0
  102. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/21-skull.png +0 -0
  103. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/22-skull-n-crossbones.png +0 -0
  104. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/23-bird.png +0 -0
  105. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/24-gift.png +0 -0
  106. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/25-weather.png +0 -0
  107. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/26-bandaid.png +0 -0
  108. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/27-planet.png +0 -0
  109. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/28-star.png +0 -0
  110. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/29-heart.png +0 -0
  111. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/30-key.png +0 -0
  112. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/31-ipod.png +0 -0
  113. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/32-iphone.png +0 -0
  114. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/33-cabinet.png +0 -0
  115. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/34-coffee.png +0 -0
  116. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/35-shopping-bag.png +0 -0
  117. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/36-toolbox.png +0 -0
  118. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/37-suitcase.png +0 -0
  119. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/38-airplane.png +0 -0
  120. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/39-spraycan.png +0 -0
  121. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/40-inbox.png +0 -0
  122. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/41-picture-frame.png +0 -0
  123. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/42-photos.png +0 -0
  124. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/43-film-roll.png +0 -0
  125. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/44-shoebox.png +0 -0
  126. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/45-movie1.png +0 -0
  127. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/46-movie2.png +0 -0
  128. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/47-fuel.png +0 -0
  129. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/48-fork-and-knife.png +0 -0
  130. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/49-battery.png +0 -0
  131. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/50-beaker.png +0 -0
  132. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/51-outlet.png +0 -0
  133. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/52-pinetree.png +0 -0
  134. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/53-house.png +0 -0
  135. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/54-lock.png +0 -0
  136. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/55-network.png +0 -0
  137. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/56-cloud.png +0 -0
  138. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/57-download.png +0 -0
  139. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/58-bookmark.png +0 -0
  140. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/59-flag.png +0 -0
  141. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/60-signpost.png +0 -0
  142. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/61-brightness.png +0 -0
  143. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/62-contrast.png +0 -0
  144. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/63-runner.png +0 -0
  145. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/64-zap.png +0 -0
  146. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/65-note.png +0 -0
  147. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/66-microphone.png +0 -0
  148. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/67-tshirt.png +0 -0
  149. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/68-paperclip.png +0 -0
  150. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/69-display.png +0 -0
  151. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/70-tv.png +0 -0
  152. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/71-compass.png +0 -0
  153. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/72-pin.png +0 -0
  154. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/73-radar.png +0 -0
  155. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/74-location.png +0 -0
  156. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/75-phone.png +0 -0
  157. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/76-baby.png +0 -0
  158. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/77-ekg.png +0 -0
  159. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/78-stopwatch.png +0 -0
  160. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/79-medical-bag.png +0 -0
  161. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/80-shopping-cart.png +0 -0
  162. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/81-dashboard.png +0 -0
  163. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/82-dogpaw.png +0 -0
  164. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/83-calendar.png +0 -0
  165. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/84-lightbulb.png +0 -0
  166. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/85-trophy.png +0 -0
  167. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/86-camera.png +0 -0
  168. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/87-wineglass.png +0 -0
  169. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/88-beermug.png +0 -0
  170. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/89-dumbbell.png +0 -0
  171. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/90-lifebuoy.png +0 -0
  172. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/91-beaker2.png +0 -0
  173. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/92-testtube.png +0 -0
  174. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/93-thermometer.png +0 -0
  175. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/94-pill.png +0 -0
  176. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/95-equalizer.png +0 -0
  177. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/96-book.png +0 -0
  178. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/97-puzzle.png +0 -0
  179. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/98-palette.png +0 -0
  180. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/icons/99-umbrella.png +0 -0
  181. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/01-refresh.png +0 -0
  182. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/02-redo.png +0 -0
  183. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/03-loopback.png +0 -0
  184. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/04-squiggle.png +0 -0
  185. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/05-shuffle.png +0 -0
  186. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/06-magnifying-glass.png +0 -0
  187. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/07-map-marker.png +0 -0
  188. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/08-chat.png +0 -0
  189. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/09-chat2.png +0 -0
  190. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/10-medical.png +0 -0
  191. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/100-coffee.png +0 -0
  192. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/101-gameplan.png +0 -0
  193. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/102-walk.png +0 -0
  194. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/103-map.png +0 -0
  195. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/104-index-cards.png +0 -0
  196. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/105-piano.png +0 -0
  197. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/106-sliders.png +0 -0
  198. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/107-widescreen.png +0 -0
  199. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/108-badge.png +0 -0
  200. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/109-chicken.png +0 -0
  201. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/11-clock.png +0 -0
  202. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/110-bug.png +0 -0
  203. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/111-user.png +0 -0
  204. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/112-group.png +0 -0
  205. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/113-navigation.png +0 -0
  206. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/114-balloon.png +0 -0
  207. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/115-bow-and-arrow.png +0 -0
  208. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/116-controller.png +0 -0
  209. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/117-todo.png +0 -0
  210. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/118-coathanger.png +0 -0
  211. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/119-piggybank.png +0 -0
  212. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/12-eye.png +0 -0
  213. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/120-headphones.png +0 -0
  214. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/121-lanscape.png +0 -0
  215. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/122-stats.png +0 -0
  216. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/123-id-card.png +0 -0
  217. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/124-bullhorn.png +0 -0
  218. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/125-food.png +0 -0
  219. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/126-moon.png +0 -0
  220. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/127-sock.png +0 -0
  221. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/128-bone.png +0 -0
  222. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/129-golf.png +0 -0
  223. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/13-target.png +0 -0
  224. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/130-dice.png +0 -0
  225. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/14-tag.png +0 -0
  226. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/15-tags.png +0 -0
  227. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/16-line-chart.png +0 -0
  228. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/17-bar-chart.png +0 -0
  229. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/18-envelope.png +0 -0
  230. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/19-gear.png +0 -0
  231. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/20-gear2.png +0 -0
  232. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/21-skull.png +0 -0
  233. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/22-skull-n-crossbones.png +0 -0
  234. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/23-bird.png +0 -0
  235. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/24-gift.png +0 -0
  236. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/25-weather.png +0 -0
  237. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/26-bandaid.png +0 -0
  238. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/27-planet.png +0 -0
  239. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/28-star.png +0 -0
  240. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/29-heart.png +0 -0
  241. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/30-key.png +0 -0
  242. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/31-ipod.png +0 -0
  243. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/32-iphone.png +0 -0
  244. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/33-cabinet.png +0 -0
  245. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/34-coffee.png +0 -0
  246. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/35-shopping-bag.png +0 -0
  247. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/36-toolbox.png +0 -0
  248. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/37-suitcase.png +0 -0
  249. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/38-airplane.png +0 -0
  250. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/39-spraycan.png +0 -0
  251. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/40-inbox.png +0 -0
  252. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/41-picture-frame.png +0 -0
  253. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/42-photos.png +0 -0
  254. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/43-film-roll.png +0 -0
  255. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/44-shoebox.png +0 -0
  256. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/45-movie1.png +0 -0
  257. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/46-movie2.png +0 -0
  258. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/47-fuel.png +0 -0
  259. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/48-fork-and-knife.png +0 -0
  260. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/49-battery.png +0 -0
  261. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/50-beaker.png +0 -0
  262. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/51-outlet.png +0 -0
  263. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/52-pinetree.png +0 -0
  264. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/53-house.png +0 -0
  265. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/54-lock.png +0 -0
  266. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/55-network.png +0 -0
  267. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/56-cloud.png +0 -0
  268. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/57-download.png +0 -0
  269. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/58-bookmark.png +0 -0
  270. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/59-flag.png +0 -0
  271. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/60-signpost.png +0 -0
  272. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/61-brightness.png +0 -0
  273. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/62-contrast.png +0 -0
  274. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/63-runner.png +0 -0
  275. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/64-zap.png +0 -0
  276. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/65-note.png +0 -0
  277. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/66-microphone.png +0 -0
  278. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/67-tshirt.png +0 -0
  279. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/68-paperclip.png +0 -0
  280. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/69-display.png +0 -0
  281. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/70-tv.png +0 -0
  282. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/71-compass.png +0 -0
  283. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/72-pin.png +0 -0
  284. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/73-radar.png +0 -0
  285. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/74-location.png +0 -0
  286. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/75-phone.png +0 -0
  287. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/76-baby.png +0 -0
  288. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/77-ekg.png +0 -0
  289. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/78-stopwatch.png +0 -0
  290. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/79-medical-bag.png +0 -0
  291. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/80-shopping-cart.png +0 -0
  292. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/81-dashboard.png +0 -0
  293. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/82-dogpaw.png +0 -0
  294. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/83-calendar.png +0 -0
  295. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/84-lightbulb.png +0 -0
  296. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/85-trophy.png +0 -0
  297. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/86-camera.png +0 -0
  298. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/87-wineglass.png +0 -0
  299. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/88-beermug.png +0 -0
  300. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/89-dumbbell.png +0 -0
  301. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/90-lifebuoy.png +0 -0
  302. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/91-beaker2.png +0 -0
  303. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/92-testtube.png +0 -0
  304. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/93-thermometer.png +0 -0
  305. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/94-pill.png +0 -0
  306. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/95-equalizer.png +0 -0
  307. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/96-book.png +0 -0
  308. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/97-puzzle.png +0 -0
  309. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/98-palette.png +0 -0
  310. data/templates/{jqtouch/jquery/touch → mobile}/glyphish/mini-icons/99-umbrella.png +0 -0
  311. data/templates/mobile/jquery.mobile.js +380 -179
  312. data/templates/mobile/jquery.mobile.min.js +3 -3
  313. data/templates/mobile/jquery/mobile/_base.scss +9 -10
  314. data/templates/mobile/jquery/mobile/default/ajax-loader.png +0 -0
  315. data/templates/mobile/jquery/mobile/default/icons-18-black.png +0 -0
  316. data/templates/mobile/jquery/mobile/default/icons-18-white.png +0 -0
  317. data/templates/mobile/jquery/mobile/default/icons-36-black.png +0 -0
  318. data/templates/mobile/jquery/mobile/default/icons-36-white.png +0 -0
  319. data/templates/mobile/jquery/mobile/valencia/ajax-loader.png +0 -0
  320. data/templates/mobile/jquery/mobile/valencia/icons-18-black.png +0 -0
  321. data/templates/mobile/jquery/mobile/valencia/icons-18-white.png +0 -0
  322. data/templates/mobile/jquery/mobile/valencia/icons-36-black.png +0 -0
  323. data/templates/mobile/jquery/mobile/valencia/icons-36-white.png +0 -0
  324. data/templates/mobile/lib/tasks/jquery.mobile.rake +106 -0
  325. data/templates/mobile/manifest.rb +262 -2
  326. data/templates/{jqtools/config/initializers/jqtools.rb → tools/config/initializers/tools.rb} +2 -2
  327. data/templates/{jqtools → tools}/jquery.tools.js +0 -0
  328. data/templates/{jqtools → tools}/jquery.tools.min.js +0 -0
  329. data/templates/tools/lib/tasks/jquery.tools.rake +43 -0
  330. data/templates/tools/manifest.rb +7 -0
  331. metadata +293 -289
  332. data/gem_tasks/jqical.rake +0 -86
  333. data/gem_tasks/jqtools.rake +0 -60
  334. data/lib/jquery/jqical.rb +0 -7
  335. data/lib/jquery/jqtools.rb +0 -2
  336. data/templates/jqical/config/initializers/jqical.rb +0 -7
  337. data/templates/jqical/manifest.rb +0 -10
  338. data/templates/jqtools/manifest.rb +0 -6
  339. data/templates/jrails/jquery-1.4.3.min.js +0 -152
  340. data/templates/mobile/jquery/mobile/default/ajax-loader.gif +0 -0
  341. data/templates/mobile/jquery/mobile/valencia/ajax-loader.gif +0 -0
@@ -1,37 +1,38 @@
1
- /*
1
+ /*************************************************************************
2
2
  jquery.dynatree.js
3
3
  Dynamic tree view control, with support for lazy loading of branches.
4
4
 
5
5
  Copyright (c) 2008-2010, Martin Wendt (http://wwWendt.de)
6
6
  Dual licensed under the MIT or GPL Version 2 licenses.
7
7
  http://code.google.com/p/dynatree/wiki/LicenseInfo
8
-
8
+
9
9
  A current version and some documentation is available at
10
10
  http://dynatree.googlecode.com/
11
11
 
12
12
  $Version:$
13
13
  $Revision:$
14
14
 
15
- @depends: jquery.js
16
- @depends: jquery.ui.core.js
17
- @depends: jquery.cookie.js
18
- */
15
+ @depends: jquery.js
16
+ @depends: jquery.ui.core.js
17
+ @depends: jquery.cookie.js
18
+ *************************************************************************/
19
19
 
20
20
 
21
- /*
21
+ /*************************************************************************
22
22
  * Debug functions
23
23
  */
24
24
 
25
- var _canLog = false;
25
+ var _canLog = true;
26
26
 
27
27
  function _log(mode, msg) {
28
- /*
28
+ /**
29
29
  * Usage: logMsg("%o was toggled", this);
30
30
  */
31
- if( !_canLog )
31
+ if( !_canLog ){
32
32
  return;
33
+ }
33
34
  // Remove first argument
34
- var args = Array.prototype.slice.apply(arguments, [1]);
35
+ var args = Array.prototype.slice.apply(arguments, [1]);
35
36
  // Prepend timestamp
36
37
  var dt = new Date();
37
38
  var tag = dt.getHours()+":"+dt.getMinutes()+":"+dt.getSeconds()+"."+dt.getMilliseconds();
@@ -47,10 +48,12 @@ function _log(mode, msg) {
47
48
  break;
48
49
  default:
49
50
  window.console.log.apply(window.console, args);
51
+ break;
50
52
  }
51
53
  } catch(e) {
52
- if( !window.console )
53
- _canLog = false; // Permanently disable, when logging is not supported by the browser
54
+ if( !window.console ){
55
+ _canLog = false; // Permanently disable, when logging is not supported by the browser
56
+ }
54
57
  }
55
58
  }
56
59
 
@@ -63,8 +66,10 @@ function logMsg(msg) {
63
66
  // Forward declaration
64
67
  var getDynaTreePersistData = undefined;
65
68
 
66
- /*
67
- * Constants
69
+
70
+
71
+ /*************************************************************************
72
+ * Constants
68
73
  */
69
74
  var DTNodeStatus_Error = -1;
70
75
  var DTNodeStatus_Loading = 1;
@@ -74,7 +79,7 @@ var DTNodeStatus_Ok = 0;
74
79
  // Start of local namespace
75
80
  ;(function($) {
76
81
 
77
- /*
82
+ /*************************************************************************
78
83
  * Common tool functions.
79
84
  */
80
85
 
@@ -82,49 +87,50 @@ var Class = {
82
87
  create: function() {
83
88
  return function() {
84
89
  this.initialize.apply(this, arguments);
85
- }
90
+ };
86
91
  }
87
- }
92
+ };
88
93
 
89
94
  // Tool function to get dtnode from the event target:
90
95
  function getDtNodeFromElement(el) {
91
96
  var iMax = 5;
92
97
  while( el && iMax-- ) {
93
- if( el.dtnode ) return el.dtnode;
98
+ if(el.dtnode) { return el.dtnode; }
94
99
  el = el.parentNode;
95
- };
100
+ }
96
101
  return null;
97
102
  }
98
103
 
99
- /*
104
+
105
+ /*************************************************************************
100
106
  * Class DynaTreeNode
101
107
  */
102
108
  var DynaTreeNode = Class.create();
103
109
 
104
110
  DynaTreeNode.prototype = {
105
111
  initialize: function(parent, tree, data) {
106
- /*
107
- * @constructor
112
+ /**
113
+ * @constructor
108
114
  */
109
- this.parent = parent;
115
+ this.parent = parent;
110
116
  this.tree = tree;
111
- if ( typeof data == "string" )
117
+ if ( typeof data === "string" ){
112
118
  data = { title: data };
113
- if( data.key == undefined )
119
+ }
120
+ if( data.key === undefined ){
114
121
  data.key = "_" + tree._nodeCount++;
122
+ }
115
123
  this.data = $.extend({}, $.ui.dynatree.nodedatadefaults, data);
116
- // this.div = null; // not yet created
117
124
  this.li = null; // not yet created
118
125
  this.span = null; // not yet created
119
126
  this.ul = null; // not yet created
120
127
  this.childList = null; // no subnodes yet
121
- // this.isRead = false; // Lazy content not yet read
122
128
  this.isLoading = false; // Lazy content is being loaded
123
129
  this.hasSubSel = false;
124
130
  },
125
131
 
126
132
  toString: function() {
127
- return "dtnode<" + this.data.key + ">: '" + this.data.title + "'";
133
+ return "DynaTreeNode<" + this.data.key + ">: '" + this.data.title + "'";
128
134
  },
129
135
 
130
136
  toDict: function(recursive, callback) {
@@ -133,79 +139,89 @@ DynaTreeNode.prototype = {
133
139
  dict.focus = ( this.tree.focusNode === this );
134
140
  dict.expand = this.bExpanded;
135
141
  dict.select = this.bSelected;
136
- if( callback )
142
+ if( callback ){
137
143
  callback(dict);
144
+ }
138
145
  if( recursive && this.childList ) {
139
146
  dict.children = [];
140
- for(var i=0; i<this.childList.length; i++ )
147
+ for(var i=0; i<this.childList.length; i++ ){
141
148
  dict.children.push(this.childList[i].toDict(true, callback));
149
+ }
142
150
  } else {
143
151
  delete dict.children;
144
152
  }
145
153
  return dict;
146
154
  },
147
155
 
156
+ fromDict: function(dict) {
157
+ /**
158
+ * Update node data. If dict contains 'children', then also replace
159
+ * the hole sub tree.
160
+ */
161
+ var children = dict.children;
162
+ if(children === undefined){
163
+ this.data = $.extend(this.data, dict);
164
+ this.render();
165
+ return;
166
+ }
167
+ dict = $.extend({}, dict);
168
+ dict.children = undefined;
169
+ this.data = $.extend(this.data, dict);
170
+ this.removeChildren();
171
+ this.addChild(children);
172
+ },
173
+
148
174
  _getInnerHtml: function() {
149
175
  var opts = this.tree.options;
150
176
  var cache = this.tree.cache;
151
- // parent connectors
152
- // var rootParent = opts.rootVisible ? null : this.tree.tnRoot;
153
- // var bHideFirstExpander = (opts.rootVisible && opts.minExpandLevel>0) || opts.minExpandLevel>1;
154
- // var bHideFirstConnector = opts.rootVisible || opts.minExpandLevel>0;
155
177
  var level = this.getLevel();
156
178
  var res = "";
157
- /*
158
- var p = this.parent;
159
- while( p ) {
160
- // Suppress first connector column, if visible top level is always expanded
161
- if ( bHideFirstConnector && p==rootParent )
162
- break;
163
- res = ( p.isLastSibling() ? cache.tagEmpty : cache.tagVline) + res;
164
- p = p.parent;
165
- }
166
- */
167
179
  // connector (expanded, expandable or simple)
168
-
169
- if( level < opts.minExpandLevel ) {
170
- // skip expander/connector
171
- } else if ( this.childList || this.data.isLazy ) {
172
- res += cache.tagExpander;
180
+ if( level < opts.minExpandLevel ) {
181
+ if(level > 1){
182
+ res += cache.tagConnector;
183
+ }
184
+ // .. else (i.e. for root level) skip expander/connector altogether
185
+ } else if( this.hasChildren() !== false ) {
186
+ res += cache.tagExpander;
173
187
  } else {
174
- res += cache.tagConnector;
188
+ res += cache.tagConnector;
175
189
  }
176
-
177
190
  // Checkbox mode
178
- if( opts.checkbox && this.data.hideCheckbox!=true && !this.data.isStatusNode ) {
179
- res += cache.tagCheckbox;
191
+ if( opts.checkbox && this.data.hideCheckbox !== true && !this.data.isStatusNode ) {
192
+ res += cache.tagCheckbox;
180
193
  }
181
-
182
194
  // folder or doctype icon
183
- if ( this.data.icon ) {
184
- res += "<img src='" + opts.imagePath + this.data.icon + "' alt='' />";
185
- } else if ( this.data.icon == false ) {
186
- // icon == false means 'no icon'
195
+ if ( this.data.icon ) {
196
+ res += "<img src='" + opts.imagePath + this.data.icon + "' alt='' />";
197
+ } else if ( this.data.icon === false ) {
198
+ // icon == false means 'no icon'
187
199
  } else {
188
- // icon == null means 'default icon'
189
- res += cache.tagNodeIcon;
200
+ // icon == null means 'default icon'
201
+ res += cache.tagNodeIcon;
190
202
  }
191
-
192
203
  // node name
193
- var tooltip = ( this.data && typeof this.data.tooltip == "string" ) ? " title='" + this.data.tooltip + "'" : "";
194
- res += "<a href='#' class='" + opts.classNames.title + "'" + tooltip + ">" + this.data.title + "</a>";
204
+ var tooltip = this.data.tooltip ? " title='" + this.data.tooltip + "'" : "";
205
+ if( opts.noLink || this.data.noLink ) {
206
+ res += "<span style='display: inline-block;' class='" + opts.classNames.title + "'" + tooltip + ">" + this.data.title + "</span>";
207
+ }else{
208
+ res += "<a href='#' class='" + opts.classNames.title + "'" + tooltip + ">" + this.data.title + "</a>";
209
+ }
195
210
  return res;
196
211
  },
197
212
 
198
213
 
199
214
  _fixOrder: function() {
200
- /*
215
+ /**
201
216
  * Make sure, that <li> order matches childList order.
202
217
  */
203
- var cl = this.childList;
204
- if( !cl )
218
+ var cl = this.childList;
219
+ if( !cl ){
205
220
  return;
221
+ }
206
222
  var childLI = this.ul.firstChild;
207
223
  for(var i=0; i<cl.length-1; i++) {
208
- var childNode1 = cl[i];
224
+ var childNode1 = cl[i];
209
225
  var childNode2 = childLI.dtnode;
210
226
  if( childNode1 !== childNode2 ) {
211
227
  this.tree.logDebug("_fixOrder: mismatch at index " + i + ": " + childNode1 + " != " + childNode2);
@@ -214,22 +230,23 @@ DynaTreeNode.prototype = {
214
230
  childLI = childLI.nextSibling;
215
231
  }
216
232
  }
217
- },
233
+ },
234
+
218
235
 
219
236
  render: function(useEffects) {
220
- /*
237
+ /**
221
238
  * create <li><span>..</span> .. </li> tags for this node.
222
- *
239
+ *
223
240
  * <li id='key'> // This div contains the node's span and list of child div's.
224
- * <span class='title'>S S S A</span> // Span contains graphic spans and title <a> tag
241
+ * <span class='title'>S S S A</span> // Span contains graphic spans and title <a> tag
225
242
  * <ul> // only present, when node has children
226
243
  * <li>child1</li>
227
244
  * <li>child2</li>
228
245
  * </ul>
229
246
  * </li>
230
247
  */
231
- this.tree.logDebug("%o.render(%s)", this, useEffects);
232
- // ---
248
+ // this.tree.logDebug("%s.render(%s)", this, useEffects);
249
+ // ---
233
250
  var opts = this.tree.options;
234
251
  var cn = opts.classNames;
235
252
  var isLastSib = this.isLastSibling();
@@ -238,62 +255,73 @@ DynaTreeNode.prototype = {
238
255
  // Root node has only a <ul>
239
256
  this.li = this.span = null;
240
257
  this.ul = document.createElement("ul");
241
- if( opts.minExpandLevel > 1 )
258
+ if( opts.minExpandLevel > 1 ){
242
259
  this.ul.className = cn.container + " " + cn.noConnector;
243
- else
260
+ }else{
244
261
  this.ul.className = cn.container;
245
-
262
+ }
246
263
  } else if( this.parent ) {
247
264
  // Create <li><span /> </li>
248
265
  if( ! this.li ) {
249
266
  this.li = document.createElement("li");
250
267
  this.li.dtnode = this;
251
- if( this.data.key && opts.generateIds )
268
+ if( this.data.key && opts.generateIds ){
252
269
  this.li.id = opts.idPrefix + this.data.key;
253
-
270
+ }
254
271
  this.span = document.createElement("span");
255
272
  this.span.className = cn.title;
256
273
  this.li.appendChild(this.span);
257
-
274
+
258
275
  if( !this.parent.ul ) {
259
276
  // This is the parent's first child: create UL tag
260
- // (Hidden, because it will be
277
+ // (Hidden, because it will be
261
278
  this.parent.ul = document.createElement("ul");
262
279
  this.parent.ul.style.display = "none";
263
280
  this.parent.li.appendChild(this.parent.ul);
281
+ // if( opts.minExpandLevel > this.getLevel() ){
282
+ // this.parent.ul.className = cn.noConnector;
283
+ // }
264
284
  }
265
- this.parent.ul.appendChild(this.li);
285
+ this.parent.ul.appendChild(this.li);
266
286
  }
267
287
  // set node connector images, links and text
268
288
  this.span.innerHTML = this._getInnerHtml();
269
-
289
+
270
290
  // Set classes for current status
271
291
  var cnList = [];
272
292
  cnList.push(cn.node);
273
- if( this.data.isFolder )
293
+ if( this.data.isFolder ){
274
294
  cnList.push(cn.folder);
275
- if( this.bExpanded )
295
+ }
296
+ if( this.bExpanded ){
276
297
  cnList.push(cn.expanded);
277
- if( this.childList != null )
298
+ }
299
+ if( this.hasChildren() !== false ){
278
300
  cnList.push(cn.hasChildren);
279
- // if( this.data.isLazy && !this.isRead )
280
- if( this.data.isLazy && this.childList==null )
301
+ }
302
+ if( this.data.isLazy && this.childList === null ){
281
303
  cnList.push(cn.lazy);
282
- if( isLastSib )
304
+ }
305
+ if( isLastSib ){
283
306
  cnList.push(cn.lastsib);
284
- if( this.bSelected )
307
+ }
308
+ if( this.bSelected ){
285
309
  cnList.push(cn.selected);
286
- if( this.hasSubSel )
310
+ }
311
+ if( this.hasSubSel ){
287
312
  cnList.push(cn.partsel);
288
- if( this.tree.activeNode === this )
313
+ }
314
+ if( this.tree.activeNode === this ){
289
315
  cnList.push(cn.active);
290
- if( this.data.addClass )
316
+ }
317
+ if( this.data.addClass ){
291
318
  cnList.push(this.data.addClass);
319
+ }
292
320
  // IE6 doesn't correctly evaluate multiple class names,
293
321
  // so we create combined class names that can be used in the CSS
294
322
  cnList.push(cn.combinedExpanderPrefix
295
323
  + (this.bExpanded ? "e" : "c")
296
- + (this.data.isLazy && this.childList==null ? "d" : "")
324
+ + (this.data.isLazy && this.childList === null ? "d" : "")
297
325
  + (isLastSib ? "l" : "")
298
326
  );
299
327
  cnList.push(cn.combinedIconPrefix
@@ -304,7 +332,7 @@ DynaTreeNode.prototype = {
304
332
 
305
333
  // TODO: we should not set this in the <span> tag also, if we set it here:
306
334
  this.li.className = isLastSib ? cn.lastsib : "";
307
-
335
+
308
336
  // Hide children, if node is collapsed
309
337
  // this.ul.style.display = ( this.bExpanded || !this.parent ) ? "" : "none";
310
338
  }
@@ -317,9 +345,9 @@ DynaTreeNode.prototype = {
317
345
  }
318
346
  // Hide children, if node is collapsed
319
347
  if( this.ul ) {
320
- var isHidden = (this.ul.style.display == "none");
348
+ var isHidden = (this.ul.style.display === "none");
321
349
  // logMsg("isHidden:%s", isHidden);
322
- if( useEffects && opts.fx && !!isHidden == !!this.bExpanded ) {
350
+ if( useEffects && opts.fx && !!isHidden === !!this.bExpanded ) {
323
351
  var duration = opts.fx.duration || 200;
324
352
  $(this.ul).animate(opts.fx, duration);
325
353
  } else {
@@ -327,6 +355,16 @@ DynaTreeNode.prototype = {
327
355
  }
328
356
  }
329
357
  },
358
+ /** Return '/id1/id2/id3'. */
359
+ getKeyPath: function(excludeSelf) {
360
+ var path = [];
361
+ this.visitParents(function(node){
362
+ if(node.parent){
363
+ path.unshift(node.data.key);
364
+ }
365
+ }, !excludeSelf);
366
+ return "/" + path.join(this.tree.options.keyPathSeparator);
367
+ },
330
368
 
331
369
  getParent: function() {
332
370
  return this.parent;
@@ -336,87 +374,120 @@ DynaTreeNode.prototype = {
336
374
  return this.childList;
337
375
  },
338
376
 
377
+ /** Check if node has children (returns undefined, if not sure). */
339
378
  hasChildren: function() {
340
- return this.childList != null;
379
+ if(this.data.isLazy){
380
+ if(this.childList === null || this.childList === undefined){
381
+ // Not yet loaded
382
+ return undefined;
383
+ }else if(this.childList.length === 0){
384
+ // Loaded, but response was empty
385
+ return false;
386
+ }else if(this.childList.length === 1 && this.childList[0].isStatusNode()){
387
+ // Currently loading or load error
388
+ return undefined;
389
+ }
390
+ return true;
391
+ }
392
+ return !!this.childList;
393
+ },
394
+
395
+ isFirstSibling: function() {
396
+ var p = this.parent;
397
+ return !p || p.childList[0] === this;
341
398
  },
342
399
 
343
400
  isLastSibling: function() {
344
401
  var p = this.parent;
345
- if ( !p ) return true;
346
- return p.childList[p.childList.length-1] === this;
402
+ return !p || p.childList[p.childList.length-1] === this;
347
403
  },
348
404
 
349
405
  getPrevSibling: function() {
350
- if( !this.parent ) return null;
406
+ if( !this.parent ){
407
+ return null;
408
+ }
351
409
  var ac = this.parent.childList;
352
- for(var i=1; i<ac.length; i++) // start with 1, so prev(first) = null
353
- if( ac[i] === this )
410
+ for(var i=1; i<ac.length; i++){ // start with 1, so prev(first) = null
411
+ if( ac[i] === this ){
354
412
  return ac[i-1];
413
+ }
414
+ }
355
415
  return null;
356
416
  },
357
417
 
358
418
  getNextSibling: function() {
359
- if( !this.parent ) return null;
419
+ if( !this.parent ){
420
+ return null;
421
+ }
360
422
  var ac = this.parent.childList;
361
- for(var i=0; i<ac.length-1; i++) // up to length-2, so next(last) = null
362
- if( ac[i] === this )
423
+ for(var i=0; i<ac.length-1; i++){ // up to length-2, so next(last) = null
424
+ if( ac[i] === this ){
363
425
  return ac[i+1];
426
+ }
427
+ }
364
428
  return null;
365
429
  },
366
-
430
+
367
431
  isStatusNode: function() {
368
432
  return (this.data.isStatusNode === true);
369
433
  },
370
-
434
+
371
435
  isChildOf: function(otherNode) {
372
436
  return (this.parent && this.parent === otherNode);
373
437
  },
374
-
438
+
375
439
  isDescendantOf: function(otherNode) {
376
- if(!otherNode)
440
+ if(!otherNode){
377
441
  return false;
442
+ }
378
443
  var p = this.parent;
379
444
  while( p ) {
380
- if( p===otherNode )
445
+ if( p === otherNode ){
381
446
  return true;
447
+ }
382
448
  p = p.parent;
383
449
  }
384
450
  return false;
385
451
  },
386
-
452
+
453
+ /**Sort child list by title.
454
+ * cmd: optional compare function.
455
+ * deep: optional: pass true to sort all descendant nodes.
456
+ */
387
457
  sortChildren: function(cmp, deep) {
388
- /*
389
- * Sort child list by title.
390
- * cmd: optional comapre function.
391
- * deep: optional: pass true to sort all descendant nodes.
392
- */
393
458
  var cl = this.childList;
394
- if( !cl )
459
+ if( !cl ){
395
460
  return;
396
- cmp = cmp || function(a, b) {
397
- return a.data.title === b.data.title ? 0 : a.data.title > b.data.title;
461
+ }
462
+ cmp = cmp || function(a, b) {
463
+ return a.data.title === b.data.title ? 0 : a.data.title > b.data.title;
398
464
  };
399
465
  cl.sort(cmp);
400
466
  if( deep ){
401
467
  for(var i=0; i<cl.length; i++){
402
- if( cl[i].childList )
468
+ if( cl[i].childList ){
403
469
  cl[i].sortChildren(cmp, "$norender$");
470
+ }
404
471
  }
405
472
  }
406
- if( deep !== "$norender$" )
473
+ if( deep !== "$norender$" ){
407
474
  this.render();
475
+ }
408
476
  },
409
-
477
+
410
478
  _setStatusNode: function(data) {
411
479
  // Create, modify or remove the status child node (pass 'null', to remove it).
412
480
  var firstChild = ( this.childList ? this.childList[0] : null );
413
481
  if( !data ) {
414
482
  if ( firstChild ) {
415
- this.ul.removeChild(firstChild.li);
416
- if( this.childList.length == 1 )
483
+ try{
484
+ this.ul.removeChild(firstChild.li);
485
+ }catch(e){};
486
+ if( this.childList.length === 1 ){
417
487
  this.childList = null;
418
- else
488
+ }else{
419
489
  this.childList.shift();
490
+ }
420
491
  }
421
492
  } else if ( firstChild ) {
422
493
  data.isStatusNode = true;
@@ -472,15 +543,16 @@ DynaTreeNode.prototype = {
472
543
  var l = [];
473
544
  var dtn = includeSelf ? this : this.parent;
474
545
  while( dtn ) {
475
- if( includeRoot || dtn.parent )
546
+ if( includeRoot || dtn.parent ){
476
547
  l.unshift(dtn);
548
+ }
477
549
  dtn = dtn.parent;
478
- };
550
+ }
479
551
  return l;
480
552
  },
481
553
 
482
554
  getLevel: function() {
483
- /*
555
+ /**
484
556
  * Return node depth. 0: System root node, 1: visible top-level node.
485
557
  */
486
558
  var level = 0;
@@ -488,82 +560,86 @@ DynaTreeNode.prototype = {
488
560
  while( dtn ) {
489
561
  level++;
490
562
  dtn = dtn.parent;
491
- };
563
+ }
492
564
  return level;
493
565
  },
494
566
 
495
567
  _getTypeForOuterNodeEvent: function(event) {
496
- /* Return the inner node span (title, checkbox or expander) if
568
+ /** Return the inner node span (title, checkbox or expander) if
497
569
  * event.target points to the outer span.
498
- * This function should fix issue #93:
570
+ * This function should fix issue #93:
499
571
  * FF2 ignores empty spans, when generating events (returning the parent instead).
500
- */
572
+ */
501
573
  var cns = this.tree.options.classNames;
502
- var target = event.target;
503
- // Only process clicks on an outer node span (probably due to a FF2 event handling bug)
504
- if( target.className.indexOf(cns.node)<0 ) {
505
- return null
506
- }
507
- // Event coordinates, relative to outer node span:
508
- var eventX = event.pageX - target.offsetLeft;
509
- var eventY = event.pageY - target.offsetTop;
510
-
511
- for(var i=0; i<target.childNodes.length; i++) {
512
- var cn = target.childNodes[i];
513
- var x = cn.offsetLeft - target.offsetLeft;
514
- var y = cn.offsetTop - target.offsetTop;
515
- var nx = cn.clientWidth, ny = cn.clientHeight;
574
+ var target = event.target;
575
+ // Only process clicks on an outer node span (probably due to a FF2 event handling bug)
576
+ if( target.className.indexOf(cns.node) < 0 ) {
577
+ return null;
578
+ }
579
+ // Event coordinates, relative to outer node span:
580
+ var eventX = event.pageX - target.offsetLeft;
581
+ var eventY = event.pageY - target.offsetTop;
582
+
583
+ for(var i=0; i<target.childNodes.length; i++) {
584
+ var cn = target.childNodes[i];
585
+ var x = cn.offsetLeft - target.offsetLeft;
586
+ var y = cn.offsetTop - target.offsetTop;
587
+ var nx = cn.clientWidth, ny = cn.clientHeight;
516
588
  // alert (cn.className + ": " + x + ", " + y + ", s:" + nx + ", " + ny);
517
- if( eventX>=x && eventX<=(x+nx) && eventY>=y && eventY<=(y+ny) ) {
589
+ if( eventX >= x && eventX <= (x+nx) && eventY >= y && eventY <= (y+ny) ) {
518
590
  // alert("HIT "+ cn.className);
519
- if( cn.className==cns.title )
520
- return "title";
521
- else if( cn.className==cns.expander )
522
- return "expander";
523
- else if( cn.className==cns.checkbox )
524
- return "checkbox";
525
- else if( cn.className==cns.nodeIcon )
526
- return "icon";
527
- }
528
- }
529
- return "prefix";
591
+ if( cn.className==cns.title ){
592
+ return "title";
593
+ }else if( cn.className==cns.expander ){
594
+ return "expander";
595
+ }else if( cn.className==cns.checkbox ){
596
+ return "checkbox";
597
+ }else if( cn.className==cns.nodeIcon ){
598
+ return "icon";
599
+ }
600
+ }
601
+ }
602
+ return "prefix";
530
603
  },
531
604
 
532
605
  getEventTargetType: function(event) {
533
606
  // Return the part of a node, that a click event occured on.
534
- // Note: there is no check, if the event was fired on TIHS node.
607
+ // Note: there is no check, if the event was fired on TIHS node.
535
608
  var tcn = event && event.target ? event.target.className : "";
536
609
  var cns = this.tree.options.classNames;
537
610
 
538
- if( tcn == cns.title )
611
+ if( tcn === cns.title ){
539
612
  return "title";
540
- else if( tcn==cns.expander )
613
+ }else if( tcn === cns.expander ){
541
614
  return "expander";
542
- else if( tcn==cns.checkbox )
615
+ }else if( tcn === cns.checkbox ){
543
616
  return "checkbox";
544
- else if( tcn==cns.nodeIcon )
617
+ }else if( tcn === cns.nodeIcon ){
545
618
  return "icon";
546
- else if( tcn==cns.empty || tcn==cns.vline || tcn==cns.connector )
619
+ }else if( tcn === cns.empty || tcn === cns.vline || tcn === cns.connector ){
547
620
  return "prefix";
548
- else if( tcn.indexOf(cns.node)>=0 )
621
+ }else if( tcn.indexOf(cns.node) >= 0 ){
549
622
  // FIX issue #93
550
623
  return this._getTypeForOuterNodeEvent(event);
624
+ }
551
625
  return null;
552
626
  },
553
627
 
554
628
  isVisible: function() {
555
629
  // Return true, if all parents are expanded.
556
630
  var parents = this._parentList(true, false);
557
- for(var i=0; i<parents.length; i++)
558
- if( ! parents[i].bExpanded ) return false;
631
+ for(var i=0; i<parents.length; i++){
632
+ if( ! parents[i].bExpanded ){ return false; }
633
+ }
559
634
  return true;
560
635
  },
561
636
 
562
637
  makeVisible: function() {
563
638
  // Make sure, all parents are expanded
564
639
  var parents = this._parentList(true, false);
565
- for(var i=0; i<parents.length; i++)
640
+ for(var i=0; i<parents.length; i++){
566
641
  parents[i]._expand(true);
642
+ }
567
643
  },
568
644
 
569
645
  focus: function() {
@@ -579,43 +655,51 @@ DynaTreeNode.prototype = {
579
655
  // (De)Activate - but not focus - this node.
580
656
  this.tree.logDebug("dtnode._activate(%o, fireEvents=%o) - %o", flag, fireEvents, this);
581
657
  var opts = this.tree.options;
582
- if( this.data.isStatusNode )
658
+ if( this.data.isStatusNode ){
583
659
  return;
584
- if ( fireEvents && opts.onQueryActivate && opts.onQueryActivate.call(this.span, flag, this) == false )
660
+ }
661
+ if ( fireEvents && opts.onQueryActivate && opts.onQueryActivate.call(this.tree, flag, this) === false ){
585
662
  return; // Callback returned false
586
-
663
+ }
664
+
587
665
  if( flag ) {
588
666
  // Activate
589
667
  if( this.tree.activeNode ) {
590
- if( this.tree.activeNode === this )
668
+ if( this.tree.activeNode === this ){
591
669
  return;
670
+ }
592
671
  this.tree.activeNode.deactivate();
593
672
  }
594
- if( opts.activeVisible )
673
+ if( opts.activeVisible ){
595
674
  this.makeVisible();
675
+ }
596
676
  this.tree.activeNode = this;
597
- if( opts.persist )
677
+ if( opts.persist ){
598
678
  $.cookie(opts.cookieId+"-active", this.data.key, opts.cookie);
599
- this.tree.persistence.activeKey = this.data.key;
679
+ }
680
+ this.tree.persistence.activeKey = this.data.key;
600
681
  $(this.span).addClass(opts.classNames.active);
601
- if ( fireEvents && opts.onActivate ) // Pass element as 'this' (jQuery convention)
602
- opts.onActivate.call(this.span, this);
682
+ if ( fireEvents && opts.onActivate ){ // Pass element as 'this' (jQuery convention)
683
+ opts.onActivate.call(this.tree, this);
684
+ }
603
685
  } else {
604
686
  // Deactivate
605
687
  if( this.tree.activeNode === this ) {
606
688
  var opts = this.tree.options;
607
- if ( opts.onQueryActivate && opts.onQueryActivate.call(this.span, false, this) == false )
689
+ if ( opts.onQueryActivate && opts.onQueryActivate.call(this.tree, false, this) === false ){
608
690
  return; // Callback returned false
691
+ }
609
692
  $(this.span).removeClass(opts.classNames.active);
610
- if( opts.persist ) {
611
- // Note: we don't pass null, but ''. So the cookie is not deleted.
612
- // If we pass null, we also have to pass a COPY of opts, because $cookie will override opts.expires (issue 84)
693
+ if( opts.persist ) {
694
+ // Note: we don't pass null, but ''. So the cookie is not deleted.
695
+ // If we pass null, we also have to pass a COPY of opts, because $cookie will override opts.expires (issue 84)
613
696
  $.cookie(opts.cookieId+"-active", "", opts.cookie);
614
- }
615
- this.tree.persistence.activeKey = null;
697
+ }
698
+ this.tree.persistence.activeKey = null;
616
699
  this.tree.activeNode = null;
617
- if ( fireEvents && opts.onDeactivate )
618
- opts.onDeactivate.call(this.span, this);
700
+ if ( fireEvents && opts.onDeactivate ){
701
+ opts.onDeactivate.call(this.tree, this);
702
+ }
619
703
  }
620
704
  }
621
705
  },
@@ -634,7 +718,7 @@ DynaTreeNode.prototype = {
634
718
  isActive: function() {
635
719
  return (this.tree.activeNode === this);
636
720
  },
637
-
721
+
638
722
  _userActivate: function() {
639
723
  // Handle user click / [space] / [enter], according to clickFolderMode.
640
724
  var activate = true;
@@ -650,14 +734,13 @@ DynaTreeNode.prototype = {
650
734
  break;
651
735
  }
652
736
  }
653
- // if( this.parent == null && this.tree.options.minExpandLevel>0 ) {
654
- if( this.parent == null ) {
737
+ if( this.parent === null ) {
655
738
  expand = false;
656
739
  }
657
740
  if( expand ) {
658
741
  this.toggleExpand();
659
742
  this.focus();
660
- }
743
+ }
661
744
  if( activate ) {
662
745
  this.activate();
663
746
  }
@@ -674,13 +757,13 @@ DynaTreeNode.prototype = {
674
757
  },
675
758
 
676
759
  _fixSelectionState: function() {
677
- // fix selection status, for multi-hier mode
760
+ // fix selection status, for multi-hier mode
678
761
  // this.tree.logDebug("_fixSelectionState(%o) - %o", this.bSelected, this);
679
762
  if( this.bSelected ) {
680
763
  // Select all children
681
- this.visit(function(dtnode){
682
- dtnode.parent._setSubSel(true);
683
- dtnode._select(true, false, false);
764
+ this.visit(function(node){
765
+ node.parent._setSubSel(true);
766
+ node._select(true, false, false);
684
767
  });
685
768
  // Select parents, if all children are selected
686
769
  var p = this.parent;
@@ -688,22 +771,23 @@ DynaTreeNode.prototype = {
688
771
  p._setSubSel(true);
689
772
  var allChildsSelected = true;
690
773
  for(var i=0; i<p.childList.length; i++) {
691
- var n = p.childList[i];
774
+ var n = p.childList[i];
692
775
  if( !n.bSelected && !n.data.isStatusNode ) {
693
776
  allChildsSelected = false;
694
777
  break;
695
778
  }
696
779
  }
697
- if( allChildsSelected )
780
+ if( allChildsSelected ){
698
781
  p._select(true, false, false);
782
+ }
699
783
  p = p.parent;
700
784
  }
701
785
  } else {
702
786
  // Deselect all children
703
787
  this._setSubSel(false);
704
- this.visit(function(dtnode){
705
- dtnode._setSubSel(false);
706
- dtnode._select(false, false, false);
788
+ this.visit(function(node){
789
+ node._setSubSel(false);
790
+ node._select(false, false, false);
707
791
  });
708
792
  // Deselect parents, and recalc hasSubSel
709
793
  var p = this.parent;
@@ -721,28 +805,29 @@ DynaTreeNode.prototype = {
721
805
  }
722
806
  }
723
807
  },
724
-
808
+
725
809
  _select: function(sel, fireEvents, deep) {
726
810
  // Select - but not focus - this node.
727
811
  // this.tree.logDebug("dtnode._select(%o) - %o", sel, this);
728
812
  var opts = this.tree.options;
729
- if( this.data.isStatusNode )
813
+ if( this.data.isStatusNode ){
730
814
  return;
731
- //
732
- if( this.bSelected == sel ) {
815
+ }
816
+ //
817
+ if( this.bSelected === sel ) {
733
818
  // this.tree.logDebug("dtnode._select(%o) IGNORED - %o", sel, this);
734
819
  return;
735
820
  }
736
821
  // Allow event listener to abort selection
737
- if ( fireEvents && opts.onQuerySelect && opts.onQuerySelect.call(this.span, sel, this) == false )
822
+ if ( fireEvents && opts.onQuerySelect && opts.onQuerySelect.call(this.tree, sel, this) === false ){
738
823
  return; // Callback returned false
739
-
824
+ }
740
825
  // Force single-selection
741
- if( opts.selectMode==1 && sel ) {
742
- this.tree.visit(function(dtnode){
743
- if( dtnode.bSelected ) {
826
+ if( opts.selectMode==1 && sel ) {
827
+ this.tree.visit(function(node){
828
+ if( node.bSelected ) {
744
829
  // Deselect; assuming that in selectMode:1 there's max. one other selected node
745
- dtnode._select(false, false, false);
830
+ node._select(false, false, false);
746
831
  return false;
747
832
  }
748
833
  });
@@ -750,39 +835,41 @@ DynaTreeNode.prototype = {
750
835
 
751
836
  this.bSelected = sel;
752
837
  // this.tree._changeNodeList("select", this, sel);
753
-
838
+
754
839
  if( sel ) {
755
- if( opts.persist )
840
+ if( opts.persist ){
756
841
  this.tree.persistence.addSelect(this.data.key);
757
-
842
+ }
758
843
  $(this.span).addClass(opts.classNames.selected);
759
844
 
760
- if( deep && opts.selectMode==3 )
845
+ if( deep && opts.selectMode === 3 ){
761
846
  this._fixSelectionState();
762
-
763
- if ( fireEvents && opts.onSelect )
764
- opts.onSelect.call(this.span, true, this);
765
-
847
+ }
848
+ if ( fireEvents && opts.onSelect ){
849
+ opts.onSelect.call(this.tree, true, this);
850
+ }
766
851
  } else {
767
- if( opts.persist )
852
+ if( opts.persist ){
768
853
  this.tree.persistence.clearSelect(this.data.key);
769
-
854
+ }
770
855
  $(this.span).removeClass(opts.classNames.selected);
771
856
 
772
- if( deep && opts.selectMode==3 )
857
+ if( deep && opts.selectMode === 3 ){
773
858
  this._fixSelectionState();
774
-
775
- if ( fireEvents && opts.onSelect )
776
- opts.onSelect.call(this.span, false, this);
859
+ }
860
+ if ( fireEvents && opts.onSelect ){
861
+ opts.onSelect.call(this.tree, false, this);
862
+ }
777
863
  }
778
864
  },
779
865
 
780
866
  select: function(sel) {
781
867
  // Select - but not focus - this node.
782
868
  // this.tree.logDebug("dtnode.select(%o) - %o", sel, this);
783
- if( this.data.unselectable )
869
+ if( this.data.unselectable ){
784
870
  return this.bSelected;
785
- return this._select(sel!=false, true, true);
871
+ }
872
+ return this._select(sel!==false, true, true);
786
873
  },
787
874
 
788
875
  toggleSelect: function() {
@@ -793,13 +880,13 @@ DynaTreeNode.prototype = {
793
880
  isSelected: function() {
794
881
  return this.bSelected;
795
882
  },
796
-
883
+
797
884
  _loadContent: function() {
798
885
  try {
799
886
  var opts = this.tree.options;
800
887
  this.tree.logDebug("_loadContent: start - %o", this);
801
888
  this.setLazyNodeStatus(DTNodeStatus_Loading);
802
- if( true == opts.onLazyRead.call(this.span, this) ) {
889
+ if( true === opts.onLazyRead.call(this.tree, this) ) {
803
890
  // If function returns 'true', we assume that the loading is done:
804
891
  this.setLazyNodeStatus(DTNodeStatus_Ok);
805
892
  // Otherwise (i.e. if the loading was started as an asynchronous process)
@@ -811,78 +898,67 @@ DynaTreeNode.prototype = {
811
898
  this.setLazyNodeStatus(DTNodeStatus_Error, {tooltip: ""+e});
812
899
  }
813
900
  },
814
-
901
+
815
902
  _expand: function(bExpand) {
816
- // this.tree.logDebug("dtnode._expand(%o) - %o", bExpand, this);
817
- if( this.bExpanded == bExpand ) {
818
- // this.tree.logDebug("dtnode._expand(%o) IGNORED - %o", bExpand, this);
903
+ if( this.bExpanded === bExpand ) {
904
+ this.tree.logDebug("dtnode._expand(%o) IGNORED - %o", bExpand, this);
819
905
  return;
820
906
  }
907
+ this.tree.logDebug("dtnode._expand(%o) - %o", bExpand, this);
821
908
  var opts = this.tree.options;
822
909
  if( !bExpand && this.getLevel() < opts.minExpandLevel ) {
823
910
  this.tree.logDebug("dtnode._expand(%o) prevented collapse - %o", bExpand, this);
824
911
  return;
825
912
  }
826
- if ( opts.onQueryExpand && opts.onQueryExpand.call(this.span, bExpand, this) == false )
913
+ if ( opts.onQueryExpand && opts.onQueryExpand.call(this.tree, bExpand, this) === false ){
827
914
  return; // Callback returned false
915
+ }
828
916
  this.bExpanded = bExpand;
829
917
 
830
918
  // Persist expand state
831
919
  if( opts.persist ) {
832
- if( bExpand )
920
+ if( bExpand ){
833
921
  this.tree.persistence.addExpand(this.data.key);
834
- else
922
+ }else{
835
923
  this.tree.persistence.clearExpand(this.data.key);
924
+ }
836
925
  }
837
926
  // Do not apply animations in init phase, or before lazy-loading
838
- var allowEffects = !(this.data.isLazy && this.childList==null) && !this.isLoading;
927
+ var allowEffects = !(this.data.isLazy && this.childList === null) && !this.isLoading;
839
928
  this.render(allowEffects);
840
929
 
841
- // Auto-collapse mode: collapse all siblings
930
+ // Auto-collapse mode: collapse all siblings
842
931
  if( this.bExpanded && this.parent && opts.autoCollapse ) {
843
932
  var parents = this._parentList(false, true);
844
- for(var i=0; i<parents.length; i++)
933
+ for(var i=0; i<parents.length; i++){
845
934
  parents[i].collapseSiblings();
935
+ }
846
936
  }
847
-
848
937
  // If the currently active node is now hidden, deactivate it
849
938
  if( opts.activeVisible && this.tree.activeNode && ! this.tree.activeNode.isVisible() ) {
850
939
  this.tree.activeNode.deactivate();
851
940
  }
852
941
  // Expanding a lazy node: set 'loading...' and call callback
853
- if( bExpand && this.data.isLazy && this.childList==null && !this.isLoading ) {
942
+ if( bExpand && this.data.isLazy && this.childList === null && !this.isLoading ) {
854
943
  this._loadContent();
855
944
  return;
856
945
  }
857
- // this.tree.logDebug("_expand: start div toggle - %o", this);
858
- /*
859
- if( opts.fx ) {
860
- this.render(true);
861
- var duration = opts.fx.duration || 200;
862
- $(this.ul).animate(opts.fx, duration);
863
- } else {
864
- this.render();
865
- logMsg("_expand: got div, start toggle - %o", this);
946
+ if ( opts.onExpand ){
947
+ opts.onExpand.call(this.tree, bExpand, this);
866
948
  }
867
- */
868
-
869
- // this.tree.logDebug("_expand: end div toggle - %o", this);
870
-
871
- if ( opts.onExpand )
872
- opts.onExpand.call(this.span, bExpand, this);
873
949
  },
874
950
 
875
951
  expand: function(flag) {
876
- if( !this.childList && !this.data.isLazy && flag )
952
+ if( !this.childList && !this.data.isLazy && flag ){
877
953
  return; // Prevent expanding empty nodes
878
- // if( this.parent == null && this.tree.options.minExpandLevel>0 && !flag )
879
- if( this.parent == null && !flag )
954
+ } else if( this.parent === null && !flag ){
880
955
  return; // Prevent collapsing the root
956
+ }
881
957
  this._expand(flag);
882
958
  },
883
959
 
884
960
  scheduleAction: function(mode, ms) {
885
- /* Schedule activity for delayed execution (cancel any pending request).
961
+ /** Schedule activity for delayed execution (cancel any pending request).
886
962
  * scheduleAction('cancel') will cancel the request.
887
963
  */
888
964
  if( this.tree.timer ) {
@@ -916,30 +992,44 @@ DynaTreeNode.prototype = {
916
992
  },
917
993
 
918
994
  collapseSiblings: function() {
919
- if( this.parent == null )
995
+ if( this.parent === null ){
920
996
  return;
997
+ }
921
998
  var ac = this.parent.childList;
922
999
  for (var i=0; i<ac.length; i++) {
923
- if ( ac[i] !== this && ac[i].bExpanded )
1000
+ if ( ac[i] !== this && ac[i].bExpanded ){
924
1001
  ac[i]._expand(false);
1002
+ }
925
1003
  }
926
1004
  },
927
1005
 
928
1006
  onClick: function(event) {
929
1007
  // this.tree.logDebug("dtnode.onClick(" + event.type + "): dtnode:" + this + ", button:" + event.button + ", which: " + event.which);
930
1008
  var targetType = this.getEventTargetType(event);
931
- if( targetType == "expander" ) {
1009
+ if( targetType === "expander" ) {
932
1010
  // Clicking the expander icon always expands/collapses
933
1011
  this.toggleExpand();
934
1012
  this.focus(); // issue 95
935
- } else if( targetType == "checkbox" ) {
1013
+ } else if( targetType === "checkbox" ) {
936
1014
  // Clicking the checkbox always (de)selects
937
1015
  this.toggleSelect();
938
1016
  this.focus(); // issue 95
939
1017
  } else {
940
1018
  this._userActivate();
941
- // Chrome and Safari don't focus the a-tag on click
942
- this.span.getElementsByTagName("a")[0].focus();
1019
+ var aTag = this.span.getElementsByTagName("a");
1020
+ if(aTag[0]){
1021
+ // issue 154
1022
+ // TODO: check if still required on IE 9:
1023
+ // Chrome and Safari don't focus the a-tag on click,
1024
+ // but calling focus() seem to have problems on IE:
1025
+ // http://code.google.com/p/dynatree/issues/detail?id=154
1026
+ if(!$.browser.msie){
1027
+ aTag[0].focus();
1028
+ }
1029
+ }else{
1030
+ // 'noLink' option was set
1031
+ return true;
1032
+ }
943
1033
  }
944
1034
  // Make sure that clicks stop, otherwise <a href='#'> jumps to the top
945
1035
  return false;
@@ -959,27 +1049,28 @@ DynaTreeNode.prototype = {
959
1049
  // case 43: // '+'
960
1050
  case 107: // '+'
961
1051
  case 187: // '+' @ Chrome, Safari
962
- if( !this.bExpanded ) this.toggleExpand();
1052
+ if( !this.bExpanded ){ this.toggleExpand(); }
963
1053
  break;
964
1054
  // case 45: // '-'
965
1055
  case 109: // '-'
966
1056
  case 189: // '+' @ Chrome, Safari
967
- if( this.bExpanded ) this.toggleExpand();
1057
+ if( this.bExpanded ){ this.toggleExpand(); }
968
1058
  break;
969
1059
  //~ case 42: // '*'
970
1060
  //~ break;
971
1061
  //~ case 47: // '/'
972
1062
  //~ break;
973
1063
  // case 13: // <enter>
974
- // <enter> on a focused <a> tag seems to generate a click-event.
1064
+ // <enter> on a focused <a> tag seems to generate a click-event.
975
1065
  // this._userActivate();
976
1066
  // break;
977
1067
  case 32: // <space>
978
1068
  this._userActivate();
979
1069
  break;
980
1070
  case 8: // <backspace>
981
- if( this.parent )
1071
+ if( this.parent ){
982
1072
  this.parent.focus();
1073
+ }
983
1074
  break;
984
1075
  case 37: // <left>
985
1076
  if( this.bExpanded ) {
@@ -1000,12 +1091,16 @@ DynaTreeNode.prototype = {
1000
1091
  break;
1001
1092
  case 38: // <up>
1002
1093
  var sib = this.getPrevSibling();
1003
- while( sib && sib.bExpanded && sib.childList )
1094
+ while( sib && sib.bExpanded && sib.childList ){
1004
1095
  sib = sib.childList[sib.childList.length-1];
1096
+ }
1005
1097
  // if( !sib && this.parent && (this.tree.options.rootVisible || this.parent.parent) )
1006
- if( !sib && this.parent && this.parent.parent )
1098
+ if( !sib && this.parent && this.parent.parent ){
1007
1099
  sib = this.parent;
1008
- if( sib ) sib.focus();
1100
+ }
1101
+ if( sib ){
1102
+ sib.focus();
1103
+ }
1009
1104
  break;
1010
1105
  case 40: // <down>
1011
1106
  var sib;
@@ -1015,16 +1110,18 @@ DynaTreeNode.prototype = {
1015
1110
  var parents = this._parentList(false, true);
1016
1111
  for(var i=parents.length-1; i>=0; i--) {
1017
1112
  sib = parents[i].getNextSibling();
1018
- if( sib ) break;
1113
+ if( sib ){ break; }
1019
1114
  }
1020
1115
  }
1021
- if( sib ) sib.focus();
1116
+ if( sib ){
1117
+ sib.focus();
1118
+ }
1022
1119
  break;
1023
1120
  default:
1024
1121
  handled = false;
1025
1122
  }
1026
1123
  // Return false, if handled, to prevent default processing
1027
- return !handled;
1124
+ return !handled;
1028
1125
  },
1029
1126
 
1030
1127
  onKeypress: function(event) {
@@ -1032,19 +1129,22 @@ DynaTreeNode.prototype = {
1032
1129
  // We don't process it, because IE and Safari don't fire keypress for cursor keys.
1033
1130
  // this.tree.logDebug("dtnode.onKeypress(" + event.type + "): dtnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
1034
1131
  },
1035
-
1132
+
1036
1133
  onFocus: function(event) {
1037
1134
  // Handles blur and focus events.
1038
1135
  // this.tree.logDebug("dtnode.onFocus(%o): %o", event, this);
1039
1136
  var opts = this.tree.options;
1040
- if ( event.type=="blur" || event.type=="focusout" ) {
1041
- if ( opts.onBlur ) // Pass element as 'this' (jQuery convention)
1042
- opts.onBlur.call(this.span, this);
1043
- if( this.tree.tnFocused )
1137
+ if ( event.type == "blur" || event.type == "focusout" ) {
1138
+ if ( opts.onBlur ){
1139
+ opts.onBlur.call(this.tree, this);
1140
+ }
1141
+ if( this.tree.tnFocused ){
1044
1142
  $(this.tree.tnFocused.span).removeClass(opts.classNames.focused);
1143
+ }
1045
1144
  this.tree.tnFocused = null;
1046
- if( opts.persist )
1145
+ if( opts.persist ){
1047
1146
  $.cookie(opts.cookieId+"-focus", "", opts.cookie);
1147
+ }
1048
1148
  } else if ( event.type=="focus" || event.type=="focusin") {
1049
1149
  // Fix: sometimes the blur event is not generated
1050
1150
  if( this.tree.tnFocused && this.tree.tnFocused !== this ) {
@@ -1052,67 +1152,82 @@ DynaTreeNode.prototype = {
1052
1152
  $(this.tree.tnFocused.span).removeClass(opts.classNames.focused);
1053
1153
  }
1054
1154
  this.tree.tnFocused = this;
1055
- if ( opts.onFocus ) // Pass element as 'this' (jQuery convention)
1056
- opts.onFocus.call(this.span, this);
1155
+ if ( opts.onFocus ){ // Pass element as 'this' (jQuery convention)
1156
+ opts.onFocus.call(this.tree, this);
1157
+ }
1057
1158
  $(this.tree.tnFocused.span).addClass(opts.classNames.focused);
1058
- if( opts.persist )
1159
+ if( opts.persist ){
1059
1160
  $.cookie(opts.cookieId+"-focus", this.data.key, opts.cookie);
1161
+ }
1060
1162
  }
1061
1163
  // TODO: return anything?
1062
1164
  // return false;
1063
1165
  },
1064
1166
 
1065
- visit: function(fn, data, includeSelf) {
1066
- // Call fn(dtnode, data) for all child nodes. Stop iteration, if fn() returns false.
1067
- var n = 0;
1167
+ visit: function(fn, includeSelf) {
1168
+ // Call fn(node) for all child nodes. Stop iteration, if fn() returns false.
1169
+ var res = true;
1068
1170
  if( includeSelf === true ) {
1069
- if( fn(this, data) === false )
1070
- return 1;
1071
- n++;
1171
+ res = fn(this);
1172
+ if( res === false || res == "skip" ){
1173
+ return res;
1174
+ }
1072
1175
  }
1073
- if ( this.childList )
1074
- for (var i=0; i<this.childList.length; i++)
1075
- n += this.childList[i].visit(fn, data, true);
1076
- return n;
1176
+ if(this.childList){
1177
+ for(var i=0; i<this.childList.length; i++){
1178
+ res = this.childList[i].visit(fn, true);
1179
+ if( res === false ){
1180
+ break;
1181
+ }
1182
+ }
1183
+ }
1184
+ return res;
1077
1185
  },
1078
1186
 
1079
1187
  visitParents: function(fn, includeSelf) {
1080
1188
  // Visit parent nodes (bottom up)
1081
- if(includeSelf && fn(this) === false) {
1189
+ if(includeSelf && fn(this) === false){
1082
1190
  return false;
1083
1191
  }
1084
1192
  var p = this.parent;
1085
1193
  while( p ) {
1086
- if(fn(p) === false)
1194
+ if(fn(p) === false){
1087
1195
  return false;
1196
+ }
1088
1197
  p = p.parent;
1089
1198
  }
1199
+ return true;
1090
1200
  },
1091
1201
 
1092
1202
  remove: function() {
1093
- // Remove this node
1094
- // this.tree.logDebug ("%o.remove()", this);
1095
- if ( this === this.tree.root )
1096
- throw "Cannot remove system root";
1097
- return this.parent.removeChild(this);
1203
+ // Remove this node
1204
+ // this.tree.logDebug ("%s.remove()", this);
1205
+ if ( this === this.tree.root ){
1206
+ throw "Cannot remove system root";
1207
+ }
1208
+ return this.parent.removeChild(this);
1098
1209
  },
1099
1210
 
1100
1211
  removeChild: function(tn) {
1101
1212
  // Remove tn from list of direct children.
1102
1213
  var ac = this.childList;
1103
1214
  if( ac.length == 1 ) {
1104
- if( tn !== ac[0] )
1215
+ if( tn !== ac[0] ){
1105
1216
  throw "removeChild: invalid child";
1217
+ }
1106
1218
  return this.removeChildren();
1107
1219
  }
1108
- if( tn === this.tree.activeNode )
1109
- tn.deactivate();
1110
- if( this.tree.options.persist ) {
1111
- if( tn.bSelected )
1112
- this.tree.persistence.clearSelect(tn.data.key);
1113
- if ( tn.bExpanded )
1114
- this.tree.persistence.clearExpand(tn.data.key);
1115
- }
1220
+ if( tn === this.tree.activeNode ){
1221
+ tn.deactivate();
1222
+ }
1223
+ if( this.tree.options.persist ) {
1224
+ if( tn.bSelected ){
1225
+ this.tree.persistence.clearSelect(tn.data.key);
1226
+ }
1227
+ if ( tn.bExpanded ){
1228
+ this.tree.persistence.clearExpand(tn.data.key);
1229
+ }
1230
+ }
1116
1231
  tn.removeChildren(true);
1117
1232
  // this.div.removeChild(tn.div);
1118
1233
  this.ul.removeChild(tn.li);
@@ -1126,30 +1241,36 @@ DynaTreeNode.prototype = {
1126
1241
  },
1127
1242
 
1128
1243
  removeChildren: function(isRecursiveCall, retainPersistence) {
1129
- // Remove all child nodes (more efficiently than recursive remove())
1130
- // this.tree.logDebug ("%o.removeChildren(%o)", this, isRecursiveCall);
1244
+ // Remove all child nodes (more efficiently than recursive remove())
1245
+ this.tree.logDebug ("%s.removeChildren(%o)", this, isRecursiveCall);
1131
1246
  var tree = this.tree;
1132
- var ac = this.childList;
1133
- if( ac ) {
1134
- for(var i=0; i<ac.length; i++) {
1247
+ var ac = this.childList;
1248
+ if( ac ) {
1249
+ for(var i=0; i<ac.length; i++) {
1135
1250
  var tn=ac[i];
1136
1251
  // this.tree.logDebug ("del %o", tn);
1137
- if ( tn === tree.activeNode && !retainPersistence )
1138
- tn.deactivate();
1139
- if( this.tree.options.persist && !retainPersistence ) {
1140
- if( tn.bSelected )
1141
- this.tree.persistence.clearSelect(tn.data.key);
1142
- if ( tn.bExpanded )
1143
- this.tree.persistence.clearExpand(tn.data.key);
1144
- }
1145
- tn.removeChildren(true, retainPersistence);
1252
+ if ( tn === tree.activeNode && !retainPersistence ){
1253
+ tn.deactivate();
1254
+ }
1255
+ if( this.tree.options.persist && !retainPersistence ) {
1256
+ if( tn.bSelected ){
1257
+ this.tree.persistence.clearSelect(tn.data.key);
1258
+ }
1259
+ if ( tn.bExpanded ){
1260
+ this.tree.persistence.clearExpand(tn.data.key);
1261
+ }
1262
+ }
1263
+ tn.removeChildren(true, retainPersistence);
1146
1264
  // this.div.removeChild(tn.div);
1147
- if( this.ul )
1148
- this.ul.removeChild(tn.li);
1149
- delete tn;
1150
- }
1151
- this.childList = null;
1152
- }
1265
+ try{
1266
+ this.ul.removeChild(tn.li);
1267
+ }catch(e){
1268
+ this.tree.logDebug ("%s.removeChildren: couldnt remove LI", this, e);
1269
+ }
1270
+ delete tn;
1271
+ }
1272
+ this.childList = null;
1273
+ }
1153
1274
  if( ! isRecursiveCall ) {
1154
1275
  // this._expand(false);
1155
1276
  // this.isRead = false;
@@ -1158,35 +1279,115 @@ DynaTreeNode.prototype = {
1158
1279
  }
1159
1280
  },
1160
1281
 
1282
+ setTitle: function(title) {
1283
+ this.fromDict({title: title});
1284
+ },
1285
+
1161
1286
  reload: function(force) {
1162
- // Discard lazy content (and reload, if node was expanded).
1163
- if( this.parent == null )
1164
- return this.tree.reload();
1165
-
1166
- if( ! this.data.isLazy )
1167
- throw "node.reload() requires lazy nodes.";
1287
+ throw "Use reloadChildren() instead";
1288
+ },
1289
+
1290
+ reloadChildren: function(callback) {
1291
+ // Reload lazy content (expansion state is maintained).
1292
+ if( this.parent === null ){
1293
+ throw "Use tree.reload() instead";
1294
+ }else if( ! this.data.isLazy ){
1295
+ throw "node.reloadChildren() requires lazy nodes.";
1296
+ }
1297
+ // appendAjax triggers 'nodeLoaded' event.
1298
+ // We listen to this, if a callback was passed to reloadChildren
1299
+ if(callback){
1300
+ var self = this;
1301
+ var eventType = "nodeLoaded.dynatree." + this.tree.$tree.attr("id")
1302
+ + "." + this.data.key;
1303
+ this.tree.$tree.bind(eventType, function(e, node, isOk){
1304
+ self.tree.$tree.unbind(eventType);
1305
+ self.tree.logInfo("loaded %o, %o, %o", e, node, isOk);
1306
+ if(node !== self){
1307
+ throw "got invalid load event";
1308
+ }
1309
+ callback.call(self.tree, node, isOk);
1310
+ });
1311
+ }
1312
+ // The expansion state is maintained
1168
1313
  if( this.bExpanded ) {
1169
- this.expand(false);
1314
+ // Remove children first, to prevent effects being applied
1170
1315
  this.removeChildren();
1171
- this.expand(true);
1316
+ // then force re-expand to trigger lazy loading
1317
+ // this.expand(false);
1318
+ // this.expand(true);
1319
+ this._loadContent();
1172
1320
  } else {
1173
1321
  this.removeChildren();
1174
- if( force )
1175
- this._loadContent();
1322
+ this._loadContent();
1176
1323
  }
1177
1324
  },
1178
1325
 
1326
+ loadKeyPath: function(keyPath, expand, callback) {
1327
+ this.tree.logDebug("%s.loadKeyPath(%s, %s)", this, keyPath, expand);
1328
+ if(keyPath === ""){
1329
+ this.tree.logDebug("%s.loadKeyPath(%s, %s): end node!", this, keyPath, expand);
1330
+ if( expand ){
1331
+ this.makeVisible();
1332
+ }
1333
+ return;
1334
+ }
1335
+ var segList = keyPath.split(this.tree.options.keyPathSeparator);
1336
+ if(segList[0] == ""){
1337
+ throw "Key path must be relative (don't start with '/')";
1338
+ }
1339
+ var seg = segList.shift();
1340
+
1341
+ for(var i = 0; i < this.childList.length; i++){
1342
+ var child = this.childList[i];
1343
+ if( child.data.key === seg ){
1344
+ if(child.data.isLazy && (child.childlist === null || child.childlist === undefined)){
1345
+ this.tree.logDebug("%s.loadKeyPath(%s, %s) -> reloading %s...", this, keyPath, expand, child);
1346
+ var self = this;
1347
+ child.reloadChildren(function(node, isOk){
1348
+ // After loading, look for direct child with that key
1349
+ if(isOk){
1350
+ self.tree.logDebug("%s.loadKeyPath(%s, %s) -> reloaded %s.", node, keyPath, expand, node);
1351
+ node.loadKeyPath(segList.join(self.tree.options.keyPathSeparator), expand, callback);
1352
+ }else{
1353
+ this.tree.logWarning("%s.loadKeyPath(%s, %s) -> reloadChildren() failed.", self, keyPath, expand);
1354
+ }
1355
+ });
1356
+ } else {
1357
+ // Look for direct child with that key
1358
+ child.loadKeyPath(segList.join(this.tree.options.keyPathSeparator), expand, callback);
1359
+ }
1360
+ return;
1361
+ }
1362
+ }
1363
+ // Could not find key
1364
+ this.tree.logWarning("Node not found: " + seg);
1365
+ return;
1366
+ },
1367
+
1368
+ resetLazy: function() {
1369
+ // Discard lazy content.
1370
+ if( this.parent === null ){
1371
+ throw "Use tree.reload() instead";
1372
+ }else if( ! this.data.isLazy ){
1373
+ throw "node.resetLazy() requires lazy nodes.";
1374
+ }
1375
+ this.expand(false);
1376
+ this.removeChildren();
1377
+ },
1378
+
1179
1379
  _addChildNode: function(dtnode, beforeNode) {
1180
- /*
1380
+ /**
1181
1381
  * Internal function to add one single DynatreeNode as a child.
1382
+ *
1182
1383
  */
1183
1384
  var tree = this.tree;
1184
1385
  var opts = tree.options;
1185
1386
  var pers = tree.persistence;
1186
-
1187
- // tree.logDebug("%o._addChildNode(%o)", this, dtnode);
1188
-
1189
- // --- Update and fix dtnode attributes if necessary
1387
+
1388
+ // tree.logDebug("%s._addChildNode(%o)", this, dtnode);
1389
+
1390
+ // --- Update and fix dtnode attributes if necessary
1190
1391
  dtnode.parent = this;
1191
1392
  // if( beforeNode && (beforeNode.parent !== this || beforeNode === dtnode ) )
1192
1393
  // throw "<beforeNode> must be another child of <this>";
@@ -1200,8 +1401,9 @@ DynaTreeNode.prototype = {
1200
1401
  }
1201
1402
  if( beforeNode ) {
1202
1403
  var iBefore = $.inArray(beforeNode, this.childList);
1203
- if( iBefore < 0 )
1404
+ if( iBefore < 0 ){
1204
1405
  throw "<beforeNode> must be a child of <this>";
1406
+ }
1205
1407
  this.childList.splice(iBefore, 0, dtnode);
1206
1408
  // alert(this.childList);
1207
1409
  } else {
@@ -1209,18 +1411,20 @@ DynaTreeNode.prototype = {
1209
1411
  this.childList.push(dtnode);
1210
1412
  }
1211
1413
 
1212
- // --- Handle persistence
1213
- // Initial status is read from cookies, if persistence is active and
1414
+ // --- Handle persistence
1415
+ // Initial status is read from cookies, if persistence is active and
1214
1416
  // cookies are already present.
1215
1417
  // Otherwise the status is read from the data attributes and then persisted.
1216
1418
  var isInitializing = tree.isInitializing();
1217
1419
  if( opts.persist && pers.cookiesFound && isInitializing ) {
1218
1420
  // Init status from cookies
1219
1421
  // tree.logDebug("init from cookie, pa=%o, dk=%o", pers.activeKey, dtnode.data.key);
1220
- if( pers.activeKey == dtnode.data.key )
1422
+ if( pers.activeKey == dtnode.data.key ){
1221
1423
  tree.activeNode = dtnode;
1222
- if( pers.focusedKey == dtnode.data.key )
1424
+ }
1425
+ if( pers.focusedKey == dtnode.data.key ){
1223
1426
  tree.focusNode = dtnode;
1427
+ }
1224
1428
  dtnode.bExpanded = ($.inArray(dtnode.data.key, pers.expandedKeyList) >= 0);
1225
1429
  dtnode.bSelected = ($.inArray(dtnode.data.key, pers.selectedKeyList) >= 0);
1226
1430
  // tree.logDebug(" key=%o, bSelected=%o", dtnode.data.key, dtnode.bSelected);
@@ -1229,32 +1433,36 @@ DynaTreeNode.prototype = {
1229
1433
  // tree.logDebug("init from data");
1230
1434
  if( dtnode.data.activate ) {
1231
1435
  tree.activeNode = dtnode;
1232
- if( opts.persist )
1436
+ if( opts.persist ){
1233
1437
  pers.activeKey = dtnode.data.key;
1438
+ }
1234
1439
  }
1235
1440
  if( dtnode.data.focus ) {
1236
1441
  tree.focusNode = dtnode;
1237
- if( opts.persist )
1442
+ if( opts.persist ){
1238
1443
  pers.focusedKey = dtnode.data.key;
1444
+ }
1239
1445
  }
1240
- dtnode.bExpanded = ( dtnode.data.expand == true ); // Collapsed by default
1241
- if( dtnode.bExpanded && opts.persist )
1446
+ dtnode.bExpanded = ( dtnode.data.expand === true ); // Collapsed by default
1447
+ if( dtnode.bExpanded && opts.persist ){
1242
1448
  pers.addExpand(dtnode.data.key);
1243
- dtnode.bSelected = ( dtnode.data.select == true ); // Deselected by default
1244
- /*
1449
+ }
1450
+ dtnode.bSelected = ( dtnode.data.select === true ); // Deselected by default
1451
+ /*
1245
1452
  Doesn't work, cause pers.selectedKeyList may be null
1246
- if( dtnode.bSelected && opts.selectMode==1
1453
+ if( dtnode.bSelected && opts.selectMode==1
1247
1454
  && pers.selectedKeyList && pers.selectedKeyList.length>0 ) {
1248
1455
  tree.logWarning("Ignored multi-selection in single-mode for %o", dtnode);
1249
1456
  dtnode.bSelected = false; // Fixing bad input data (multi selection for mode:1)
1250
1457
  }
1251
1458
  */
1252
- if( dtnode.bSelected && opts.persist )
1459
+ if( dtnode.bSelected && opts.persist ){
1253
1460
  pers.addSelect(dtnode.data.key);
1461
+ }
1254
1462
  }
1255
1463
 
1256
1464
  // Always expand, if it's below minExpandLevel
1257
- // tree.logDebug ("%o._addChildNode(%o), l=%o", this, dtnode, dtnode.getLevel());
1465
+ // tree.logDebug ("%s._addChildNode(%o), l=%o", this, dtnode, dtnode.getLevel());
1258
1466
  if ( opts.minExpandLevel >= dtnode.getLevel() ) {
1259
1467
  // tree.logDebug ("Force expand for %o", dtnode);
1260
1468
  this.bExpanded = true;
@@ -1269,28 +1477,29 @@ DynaTreeNode.prototype = {
1269
1477
  if( dtnode.bSelected && opts.selectMode==3 ) {
1270
1478
  var p = this;
1271
1479
  while( p ) {
1272
- if( !p.hasSubSel )
1480
+ if( !p.hasSubSel ){
1273
1481
  p._setSubSel(true);
1482
+ }
1274
1483
  p = p.parent;
1275
1484
  }
1276
1485
  }
1277
1486
  // render this node and the new child
1278
- if ( tree.bEnableUpdate )
1487
+ if ( tree.bEnableUpdate ){
1279
1488
  this.render();
1280
-
1489
+ }
1281
1490
  return dtnode;
1282
1491
  },
1283
1492
 
1284
1493
  addChild: function(obj, beforeNode) {
1285
- /*
1494
+ /**
1286
1495
  * Add a node object as child.
1287
- *
1496
+ *
1288
1497
  * This should be the only place, where a DynaTreeNode is constructed!
1289
1498
  * (Except for the root node creation in the tree constructor)
1290
- *
1499
+ *
1291
1500
  * @param obj A JS object (may be recursive) or an array of those.
1292
1501
  * @param {DynaTreeNode} beforeNode (optional) sibling node.
1293
- *
1502
+ *
1294
1503
  * Data format: array of node objects, with optional 'children' attributes.
1295
1504
  * [
1296
1505
  * { title: "t1", isFolder: true, ... }
@@ -1302,26 +1511,31 @@ DynaTreeNode.prototype = {
1302
1511
  * }
1303
1512
  * ]
1304
1513
  * A simple object is also accepted instead of an array.
1305
- *
1514
+ *
1306
1515
  */
1307
- // this.tree.logDebug("%o.addChild(%o, %o)", this, obj, beforeNode);
1308
- if( !obj || obj.length==0 ) // Passed null or undefined or empty array
1516
+ // this.tree.logDebug("%s.addChild(%o, %o)", this, obj, beforeNode);
1517
+ if( !obj || obj.length === 0 ){ // Passed null or undefined or empty array
1309
1518
  return;
1310
- if( obj instanceof DynaTreeNode )
1519
+ }
1520
+ if( obj instanceof DynaTreeNode ){
1311
1521
  return this._addChildNode(obj, beforeNode);
1312
- if( !obj.length ) // Passed a single data object
1522
+ }
1523
+ if( !obj.length ){ // Passed a single data object
1313
1524
  obj = [ obj ];
1314
-
1525
+ }
1315
1526
  var prevFlag = this.tree.enableUpdate(false);
1316
1527
 
1317
1528
  var tnFirst = null;
1318
1529
  for (var i=0; i<obj.length; i++) {
1319
1530
  var data = obj[i];
1320
1531
  var dtnode = this._addChildNode(new DynaTreeNode(this, this.tree, data), beforeNode);
1321
- if( !tnFirst ) tnFirst = dtnode;
1532
+ if( !tnFirst ){
1533
+ tnFirst = dtnode;
1534
+ }
1322
1535
  // Add child nodes recursively
1323
- if( data.children )
1536
+ if( data.children ){
1324
1537
  dtnode.addChild(data.children, null);
1538
+ }
1325
1539
  }
1326
1540
  this.tree.enableUpdate(prevFlag);
1327
1541
  return tnFirst;
@@ -1339,15 +1553,17 @@ DynaTreeNode.prototype = {
1339
1553
  var self = this;
1340
1554
  var orgSuccess = ajaxOptions.success;
1341
1555
  var orgError = ajaxOptions.error;
1556
+ var eventType = "nodeLoaded.dynatree." + this.tree.$tree.attr("id")
1557
+ + "." + this.data.key;
1342
1558
  var options = $.extend({}, this.tree.options.ajaxDefaults, ajaxOptions, {
1343
1559
  /*
1344
- complete: function(req, textStatus){
1345
- alert("ajax complete");
1346
- },
1347
- timeout: 5000, // 5 sec
1348
- */
1349
- success: function(data, textStatus){
1350
- // <this> is the request options
1560
+ complete: function(req, textStatus){
1561
+ alert("ajax complete");
1562
+ },
1563
+ timeout: 5000, // 5 sec
1564
+ */
1565
+ success: function(data, textStatus){
1566
+ // <this> is the request options
1351
1567
  // self.tree.logDebug("appendAjax().success");
1352
1568
  var prevPhase = self.tree.phase;
1353
1569
  self.tree.phase = "init";
@@ -1355,53 +1571,62 @@ DynaTreeNode.prototype = {
1355
1571
  self.addChild(data, null);
1356
1572
  self.tree.phase = "postInit";
1357
1573
  self.setLazyNodeStatus(DTNodeStatus_Ok);
1358
- if( orgSuccess )
1574
+ if( orgSuccess ){
1359
1575
  orgSuccess.call(options, self);
1576
+ }
1577
+ self.tree.logInfo("trigger "+ eventType);
1578
+ self.tree.$tree.trigger(eventType, [self, true]);
1360
1579
  self.tree.phase = prevPhase;
1361
- },
1362
- error: function(XMLHttpRequest, textStatus, errorThrown){
1363
- // <this> is the request options
1364
- self.tree.logWarning("appendAjax failed:", textStatus, ":\n", XMLHttpRequest, "\n", errorThrown);
1580
+ },
1581
+ error: function(XMLHttpRequest, textStatus, errorThrown){
1582
+ // <this> is the request options
1583
+ self.tree.logWarning("appendAjax failed:", textStatus, ":\n", XMLHttpRequest, "\n", errorThrown);
1365
1584
  self.setLazyNodeStatus(DTNodeStatus_Error, {info: textStatus, tooltip: ""+errorThrown});
1366
- if( orgError )
1585
+ if( orgError ){
1367
1586
  orgError.call(options, self, XMLHttpRequest, textStatus, errorThrown);
1368
- }
1587
+ }
1588
+ self.tree.$tree.trigger(eventType, [self, false]);
1589
+ }
1369
1590
  });
1370
- $.ajax(options);
1591
+ $.ajax(options);
1371
1592
  },
1372
1593
 
1373
1594
  move: function(targetNode, mode) {
1374
- /* Move this node to targetNode.
1595
+ /**Move this node to targetNode.
1375
1596
  * mode 'child': append this node as last child of targetNode.
1376
1597
  * This is the default. To be compatble with the D'n'd
1377
1598
  * hitMode, we also accept 'over'.
1378
1599
  * mode 'before': add this node as sibling before targetNode.
1379
1600
  * mode 'after': add this node as sibling after targetNode.
1380
1601
  */
1381
- if(this === targetNode)
1602
+ if(this === targetNode){
1382
1603
  return;
1383
- if( !this.parent )
1604
+ }
1605
+ if( !this.parent ){
1384
1606
  throw "Cannot move system root";
1385
- if(mode === undefined || mode == "over")
1607
+ }
1608
+ if(mode === undefined || mode == "over"){
1386
1609
  mode = "child";
1610
+ }
1387
1611
  var prevParent = this.parent;
1388
1612
  var targetParent = (mode === "child") ? targetNode : targetNode.parent;
1389
- if( targetParent.isDescendantOf(this) )
1613
+ if( targetParent.isDescendantOf(this) ){
1390
1614
  throw "Cannot move a node to it's own descendant";
1391
-
1615
+ }
1392
1616
  // Unlink this node from current parent
1393
1617
  if( this.parent.childList.length == 1 ) {
1394
1618
  this.parent.childList = null;
1395
1619
  this.parent.bExpanded = false;
1396
1620
  } else {
1397
1621
  var pos = $.inArray(this, this.parent.childList);
1398
- if( pos < 0 )
1622
+ if( pos < 0 ){
1399
1623
  throw "Internal error";
1624
+ }
1400
1625
  this.parent.childList.splice(pos, 1);
1401
1626
  }
1627
+ // Remove from source DOM parent
1402
1628
  this.parent.ul.removeChild(this.li);
1403
- this.li = null;
1404
-
1629
+
1405
1630
  // Insert this node to target parent's child list
1406
1631
  this.parent = targetParent;
1407
1632
  if( targetParent.hasChildren() ) {
@@ -1413,15 +1638,17 @@ DynaTreeNode.prototype = {
1413
1638
  case "before":
1414
1639
  // Insert this node before target node
1415
1640
  var pos = $.inArray(targetNode, targetParent.childList);
1416
- if( pos < 0 )
1641
+ if( pos < 0 ){
1417
1642
  throw "Internal error";
1643
+ }
1418
1644
  targetParent.childList.splice(pos, 0, this);
1419
1645
  break;
1420
1646
  case "after":
1421
1647
  // Insert this node after target node
1422
1648
  var pos = $.inArray(targetNode, targetParent.childList);
1423
- if( pos < 0 )
1649
+ if( pos < 0 ){
1424
1650
  throw "Internal error";
1651
+ }
1425
1652
  targetParent.childList.splice(pos+1, 0, this);
1426
1653
  break;
1427
1654
  default:
@@ -1429,11 +1656,22 @@ DynaTreeNode.prototype = {
1429
1656
  }
1430
1657
  } else {
1431
1658
  targetParent.childList = [ this ];
1659
+ // Parent has no <ul> tag yet:
1660
+ if( !targetParent.ul ) {
1661
+ // This is the parent's first child: create UL tag
1662
+ // (Hidden, because it will be
1663
+ targetParent.ul = document.createElement("ul");
1664
+ targetParent.ul.style.display = "none";
1665
+ targetParent.li.appendChild(targetParent.ul);
1666
+ }
1432
1667
  }
1668
+ // Add to target DOM parent
1669
+ targetParent.ul.appendChild(this.li);
1670
+
1433
1671
  if( this.tree !== targetNode.tree ) {
1434
1672
  // Fix node.tree for all source nodes
1435
- this.visit(function(dtnode){
1436
- dtnode.tree = targetNode.tree;
1673
+ this.visit(function(node){
1674
+ node.tree = targetNode.tree;
1437
1675
  }, null, true);
1438
1676
  throw "Not yet implemented.";
1439
1677
  }
@@ -1441,7 +1679,7 @@ DynaTreeNode.prototype = {
1441
1679
  // TODO: fix active state
1442
1680
  if( !prevParent.isDescendantOf(targetParent)) {
1443
1681
  prevParent.render();
1444
- }
1682
+ }
1445
1683
  if( !targetParent.isDescendantOf(prevParent) ) {
1446
1684
  targetParent.render();
1447
1685
  }
@@ -1450,10 +1688,10 @@ DynaTreeNode.prototype = {
1450
1688
  var tree = this.tree;
1451
1689
  var opts = tree.options;
1452
1690
  var pers = tree.persistence;
1453
-
1691
+
1454
1692
 
1455
1693
  // Always expand, if it's below minExpandLevel
1456
- // tree.logDebug ("%o._addChildNode(%o), l=%o", this, dtnode, dtnode.getLevel());
1694
+ // tree.logDebug ("%s._addChildNode(%o), l=%o", this, dtnode, dtnode.getLevel());
1457
1695
  if ( opts.minExpandLevel >= dtnode.getLevel() ) {
1458
1696
  // tree.logDebug ("Force expand for %o", dtnode);
1459
1697
  this.bExpanded = true;
@@ -1479,14 +1717,14 @@ DynaTreeNode.prototype = {
1479
1717
 
1480
1718
  return dtnode;
1481
1719
 
1482
- */
1720
+ */
1483
1721
  },
1484
1722
 
1485
1723
  // --- end of class
1486
1724
  lastentry: undefined
1487
- }
1725
+ };
1488
1726
 
1489
- /*
1727
+ /*************************************************************************
1490
1728
  * class DynaTreeStatus
1491
1729
  */
1492
1730
 
@@ -1507,11 +1745,12 @@ DynaTreeStatus.prototype = {
1507
1745
  // Constructor
1508
1746
  initialize: function(cookieId, cookieOpts) {
1509
1747
  this._log("DynaTreeStatus: initialize");
1510
- if( cookieId === undefined )
1748
+ if( cookieId === undefined ){
1511
1749
  cookieId = $.ui.dynatree.prototype.options.cookieId;
1750
+ }
1512
1751
  cookieOpts = $.extend({}, $.ui.dynatree.prototype.options.cookie, cookieOpts);
1513
-
1514
- this.cookieId = cookieId;
1752
+
1753
+ this.cookieId = cookieId;
1515
1754
  this.cookieOpts = cookieOpts;
1516
1755
  this.cookiesFound = undefined;
1517
1756
  this.activeKey = null;
@@ -1527,31 +1766,36 @@ DynaTreeStatus.prototype = {
1527
1766
  },
1528
1767
  read: function() {
1529
1768
  this._log("DynaTreeStatus: read");
1530
- // Read or init cookies.
1769
+ // Read or init cookies.
1531
1770
  this.cookiesFound = false;
1532
-
1533
- var cookie = $.cookie(this.cookieId + "-active");
1534
- this.activeKey = ( cookie == null ) ? "" : cookie;
1535
- if( cookie != null ) this.cookiesFound = true;
1536
1771
 
1772
+ var cookie = $.cookie(this.cookieId + "-active");
1773
+ this.activeKey = ( cookie === null ) ? "" : cookie;
1774
+ if( cookie !== null ){
1775
+ this.cookiesFound = true;
1776
+ }
1537
1777
  cookie = $.cookie(this.cookieId + "-focus");
1538
- this.focusedKey = ( cookie == null ) ? "" : cookie;
1539
- if( cookie != null ) this.cookiesFound = true;
1540
-
1778
+ this.focusedKey = ( cookie === null ) ? "" : cookie;
1779
+ if( cookie !== null ){
1780
+ this.cookiesFound = true;
1781
+ }
1541
1782
  cookie = $.cookie(this.cookieId + "-expand");
1542
- this.expandedKeyList = ( cookie == null ) ? [] : cookie.split(",");
1543
- if( cookie != null ) this.cookiesFound = true;
1544
-
1783
+ this.expandedKeyList = ( cookie === null ) ? [] : cookie.split(",");
1784
+ if( cookie !== null ){
1785
+ this.cookiesFound = true;
1786
+ }
1545
1787
  cookie = $.cookie(this.cookieId + "-select");
1546
- this.selectedKeyList = ( cookie == null ) ? [] : cookie.split(",");
1547
- if( cookie != null ) this.cookiesFound = true;
1788
+ this.selectedKeyList = ( cookie === null ) ? [] : cookie.split(",");
1789
+ if( cookie !== null ){
1790
+ this.cookiesFound = true;
1791
+ }
1548
1792
  },
1549
1793
  write: function() {
1550
1794
  this._log("DynaTreeStatus: write");
1551
- $.cookie(this.cookieId + "-active", ( this.activeKey == null ) ? "" : this.activeKey, this.cookieOpts);
1552
- $.cookie(this.cookieId + "-focus", ( this.focusedKey == null ) ? "" : this.focusedKey, this.cookieOpts);
1553
- $.cookie(this.cookieId + "-expand", ( this.expandedKeyList == null ) ? "" : this.expandedKeyList.join(","), this.cookieOpts);
1554
- $.cookie(this.cookieId + "-select", ( this.selectedKeyList == null ) ? "" : this.selectedKeyList.join(","), this.cookieOpts);
1795
+ $.cookie(this.cookieId + "-active", ( this.activeKey === null ) ? "" : this.activeKey, this.cookieOpts);
1796
+ $.cookie(this.cookieId + "-focus", ( this.focusedKey === null ) ? "" : this.focusedKey, this.cookieOpts);
1797
+ $.cookie(this.cookieId + "-expand", ( this.expandedKeyList === null ) ? "" : this.expandedKeyList.join(","), this.cookieOpts);
1798
+ $.cookie(this.cookieId + "-select", ( this.selectedKeyList === null ) ? "" : this.selectedKeyList.join(","), this.cookieOpts);
1555
1799
  },
1556
1800
  addExpand: function(key) {
1557
1801
  this._log("addExpand(%o)", key);
@@ -1562,7 +1806,7 @@ DynaTreeStatus.prototype = {
1562
1806
  },
1563
1807
  clearExpand: function(key) {
1564
1808
  this._log("clearExpand(%o)", key);
1565
- var idx = $.inArray(key, this.expandedKeyList);
1809
+ var idx = $.inArray(key, this.expandedKeyList);
1566
1810
  if( idx >= 0 ) {
1567
1811
  this.expandedKeyList.splice(idx, 1);
1568
1812
  $.cookie(this.cookieId + "-expand", this.expandedKeyList.join(","), this.cookieOpts);
@@ -1577,14 +1821,14 @@ DynaTreeStatus.prototype = {
1577
1821
  },
1578
1822
  clearSelect: function(key) {
1579
1823
  this._log("clearSelect(%o)", key);
1580
- var idx = $.inArray(key, this.selectedKeyList);
1824
+ var idx = $.inArray(key, this.selectedKeyList);
1581
1825
  if( idx >= 0 ) {
1582
1826
  this.selectedKeyList.splice(idx, 1);
1583
1827
  $.cookie(this.cookieId + "-select", this.selectedKeyList.join(","), this.cookieOpts);
1584
1828
  }
1585
1829
  },
1586
1830
  isReloading: function() {
1587
- return this.cookiesFound == true;
1831
+ return this.cookiesFound === true;
1588
1832
  },
1589
1833
  toDict: function() {
1590
1834
  return {
@@ -1599,7 +1843,8 @@ DynaTreeStatus.prototype = {
1599
1843
  lastentry: undefined
1600
1844
  };
1601
1845
 
1602
- /*
1846
+
1847
+ /*************************************************************************
1603
1848
  * class DynaTree
1604
1849
  */
1605
1850
 
@@ -1607,7 +1852,7 @@ var DynaTree = Class.create();
1607
1852
 
1608
1853
  // --- Static members ----------------------------------------------------------
1609
1854
 
1610
- DynaTree.version = "$Version:$";
1855
+ DynaTree.version = "$Version:$";
1611
1856
  /*
1612
1857
  DynaTree._initTree = function() {
1613
1858
  };
@@ -1629,7 +1874,7 @@ DynaTree.prototype = {
1629
1874
  this.timer = null;
1630
1875
  // find container element
1631
1876
  this.divTree = this.$tree.get(0);
1632
- //
1877
+ //
1633
1878
  _initDragAndDrop(this);
1634
1879
  },
1635
1880
 
@@ -1644,39 +1889,43 @@ DynaTree.prototype = {
1644
1889
  this.focusNode = null;
1645
1890
 
1646
1891
  // Some deprecation warnings to help with migration
1647
- if( opts.rootVisible !== undefined )
1892
+ if( opts.rootVisible !== undefined ){
1648
1893
  _log("warn", "Option 'rootVisible' is no longer supported.");
1649
- if( opts.title !== undefined )
1894
+ }
1895
+ if( opts.title !== undefined ){
1650
1896
  _log("warn", "Option 'title' is no longer supported.");
1651
- if( opts.minExpandLevel < 1 ) {
1897
+ }
1898
+ if( opts.minExpandLevel < 1 ) {
1652
1899
  _log("warn", "Option 'minExpandLevel' must be >= 1.");
1653
1900
  opts.minExpandLevel = 1;
1654
1901
  }
1655
-
1656
- // If a 'options.classNames' dictionary was passed, still use defaults
1657
- // for undefined classes:
1658
- if( opts.classNames !== $.ui.dynatree.prototype.options.classNames ) {
1659
- opts.classNames = $.extend({}, $.ui.dynatree.prototype.options.classNames, opts.classNames);
1660
- }
1661
- // Guess skin path, if not specified
1662
- if(!opts.imagePath) {
1663
- $("script").each( function () {
1664
- // Eclipse syntax parser breaks on this expression, so put it at the bottom:
1665
- if( this.src.search(_rexDtLibName) >= 0 ) {
1666
- if( this.src.indexOf("/")>=0 ) // issue #47
1667
- opts.imagePath = this.src.slice(0, this.src.lastIndexOf("/")) + "/skin/";
1668
- else
1669
- opts.imagePath = "skin/";
1670
- // logMsg("Guessing imagePath from '%s': '%s'", this.src, opts.imagePath);
1671
- return false; // first match
1672
- }
1673
- });
1674
- }
1675
-
1902
+
1903
+ // If a 'options.classNames' dictionary was passed, still use defaults
1904
+ // for undefined classes:
1905
+ if( opts.classNames !== $.ui.dynatree.prototype.options.classNames ) {
1906
+ opts.classNames = $.extend({}, $.ui.dynatree.prototype.options.classNames, opts.classNames);
1907
+ }
1908
+ // Guess skin path, if not specified
1909
+ if(!opts.imagePath) {
1910
+ $("script").each( function () {
1911
+ var _rexDtLibName = /.*dynatree[^\/]*\.js$/i;
1912
+ if( this.src.search(_rexDtLibName) >= 0 ) {
1913
+ if( this.src.indexOf("/")>=0 ){ // issue #47
1914
+ opts.imagePath = this.src.slice(0, this.src.lastIndexOf("/")) + "/skin/";
1915
+ }else{
1916
+ opts.imagePath = "skin/";
1917
+ }
1918
+ logMsg("Guessing imagePath from '%s': '%s'", this.src, opts.imagePath);
1919
+ return false; // first match
1920
+ }
1921
+ });
1922
+ }
1923
+
1676
1924
  this.persistence = new DynaTreeStatus(opts.cookieId, opts.cookie);
1677
1925
  if( opts.persist ) {
1678
- if( !$.cookie )
1926
+ if( !$.cookie ){
1679
1927
  _log("warn", "Please include jquery.cookie.js to use persistence.");
1928
+ }
1680
1929
  this.persistence.read();
1681
1930
  }
1682
1931
  this.logDebug("DynaTree.persistence: %o", this.persistence.toDict());
@@ -1692,13 +1941,14 @@ DynaTree.prototype = {
1692
1941
  lastentry: undefined
1693
1942
  };
1694
1943
 
1695
- // Clear container, in case it contained some 'waiting' or 'error' text
1696
- // for clients that don't support JS.
1944
+ // Clear container, in case it contained some 'waiting' or 'error' text
1945
+ // for clients that don't support JS.
1697
1946
  // We don't do this however, if we try to load from an embedded UL element.
1698
- if( opts.children || (opts.initAjax && opts.initAjax.url) || opts.initId )
1699
- $(this.divTree).empty();
1700
- else if( this.divRoot )
1701
- $(this.divRoot).remove();
1947
+ if( opts.children || (opts.initAjax && opts.initAjax.url) || opts.initId ){
1948
+ $(this.divTree).empty();
1949
+ }else if( this.divRoot ){
1950
+ $(this.divRoot).remove();
1951
+ }
1702
1952
  /*
1703
1953
  // create the root element
1704
1954
  this.tnRoot = new DynaTreeNode(null, this, {title: opts.title, key: "root"});
@@ -1706,7 +1956,7 @@ DynaTree.prototype = {
1706
1956
  this.tnRoot.render(false, false);
1707
1957
  this.divRoot = this.tnRoot.div;
1708
1958
  this.divRoot.className = opts.classNames.container;
1709
-
1959
+
1710
1960
  // add root to container
1711
1961
  // TODO: this should be delayed until all children have been created for performance reasons
1712
1962
  this.divTree.appendChild(this.divRoot);
@@ -1717,95 +1967,117 @@ DynaTree.prototype = {
1717
1967
  this.divTree.appendChild(this.tnRoot.ul);
1718
1968
 
1719
1969
  var root = this.tnRoot;
1720
- var isReloading = ( opts.persist && this.persistence.isReloading() );
1721
- var isLazy = false;
1722
- var prevFlag = this.enableUpdate(false);
1723
-
1724
- this.logDebug("Dynatree._load(): read tree structure...");
1725
-
1726
- // Init tree structure
1727
- if( opts.children ) {
1728
- // Read structure from node array
1729
- root.addChild(opts.children);
1730
-
1731
- } else if( opts.initAjax && opts.initAjax.url ) {
1732
- // Init tree from AJAX request
1733
- isLazy = true;
1734
- root.data.isLazy = true;
1735
- this._reloadAjax();
1736
-
1737
- } else if( opts.initId ) {
1738
- // Init tree from another UL element
1739
- this._createFromTag(root, $("#"+opts.initId));
1740
-
1741
- } else {
1742
- // Init tree from the first UL element inside the container <div>
1743
- var $ul = this.$tree.find(">ul:first").hide();
1744
- this._createFromTag(root, $ul);
1745
- $ul.remove();
1746
- }
1747
-
1748
- this._checkConsistency();
1749
- // Render html markup
1750
- this.logDebug("Dynatree._load(): render nodes...");
1751
- this.enableUpdate(prevFlag);
1752
-
1753
- // bind event handlers
1754
- this.logDebug("Dynatree._load(): bind events...");
1755
- this.$widget.bind();
1756
-
1757
- // --- Post-load processing
1758
- this.logDebug("Dynatree._load(): postInit...");
1759
- this.phase = "postInit";
1760
-
1761
- // In persist mode, make sure that cookies are written, even if they are empty
1762
- if( opts.persist ) {
1763
- this.persistence.write();
1764
- }
1765
-
1766
- // Set focus, if possible (this will also fire an event and write a cookie)
1767
- if( this.focusNode && this.focusNode.isVisible() ) {
1768
- this.logDebug("Focus on init: %o", this.focusNode);
1769
- this.focusNode.focus();
1770
- }
1970
+ var isReloading = ( opts.persist && this.persistence.isReloading() );
1971
+ var isLazy = false;
1972
+ var prevFlag = this.enableUpdate(false);
1973
+
1974
+ this.logDebug("Dynatree._load(): read tree structure...");
1771
1975
 
1772
- if( !isLazy && opts.onPostInit ) {
1773
- opts.onPostInit.call(this, isReloading, false);
1774
- }
1976
+ // Init tree structure
1977
+ if( opts.children ) {
1978
+ // Read structure from node array
1979
+ root.addChild(opts.children);
1775
1980
 
1776
- this.phase = "idle";
1981
+ } else if( opts.initAjax && opts.initAjax.url ) {
1982
+ // Init tree from AJAX request
1983
+ isLazy = true;
1984
+ root.data.isLazy = true;
1985
+ this._reloadAjax();
1986
+
1987
+ } else if( opts.initId ) {
1988
+ // Init tree from another UL element
1989
+ this._createFromTag(root, $("#"+opts.initId));
1990
+
1991
+ } else {
1992
+ // Init tree from the first UL element inside the container <div>
1993
+ var $ul = this.$tree.find(">ul:first").hide();
1994
+ this._createFromTag(root, $ul);
1995
+ $ul.remove();
1996
+ }
1997
+
1998
+ this._checkConsistency();
1999
+ // Render html markup
2000
+ this.logDebug("Dynatree._load(): render nodes...");
2001
+ this.enableUpdate(prevFlag);
2002
+
2003
+ // bind event handlers
2004
+ this.logDebug("Dynatree._load(): bind events...");
2005
+ this.$widget.bind();
2006
+
2007
+ // --- Post-load processing
2008
+ this.logDebug("Dynatree._load(): postInit...");
2009
+ this.phase = "postInit";
2010
+
2011
+ // In persist mode, make sure that cookies are written, even if they are empty
2012
+ if( opts.persist ) {
2013
+ this.persistence.write();
2014
+ }
2015
+ // Set focus, if possible (this will also fire an event and write a cookie)
2016
+ if( this.focusNode && this.focusNode.isVisible() ) {
2017
+ this.logDebug("Focus on init: %o", this.focusNode);
2018
+ this.focusNode.focus();
2019
+ }
2020
+ if( !isLazy && opts.onPostInit ) {
2021
+ opts.onPostInit.call(this, isReloading, false);
2022
+ }
2023
+ this.phase = "idle";
1777
2024
  },
1778
-
2025
+
2026
+ _setNoUpdate: function(silent) {
2027
+ // TODO: set options to disable and re-enable updates while loading
2028
+ var opts = this.options;
2029
+ var prev = {
2030
+ fx: opts.fx,
2031
+ autoFocus: opts.autoFocus,
2032
+ autoCollapse: opts.autoCollapse };
2033
+ if(silent === true){
2034
+ opts.autoFocus = false;
2035
+ opts.fx = null;
2036
+ opts.autoCollapse = false;
2037
+ } else {
2038
+ opts.autoFocus = silent.autoFocus;
2039
+ opts.fx = silent.fx;
2040
+ opts.autoCollapse = silent.autoCollapse;
2041
+ }
2042
+ return prev;
2043
+ },
2044
+
1779
2045
  _reloadAjax: function() {
1780
- // Reload
2046
+ // Reload
1781
2047
  var opts = this.options;
1782
- if( ! opts.initAjax || ! opts.initAjax.url )
2048
+ if( ! opts.initAjax || ! opts.initAjax.url ){
1783
2049
  throw "tree.reload() requires 'initAjax' mode.";
2050
+ }
1784
2051
  var pers = this.persistence;
1785
2052
  var ajaxOpts = $.extend({}, opts.initAjax);
1786
2053
  // Append cookie info to the request
1787
2054
  // this.logDebug("reloadAjax: key=%o, an.key:%o", pers.activeKey, this.activeNode?this.activeNode.data.key:"?");
1788
- if( ajaxOpts.addActiveKey )
1789
- ajaxOpts.data.activeKey = pers.activeKey;
1790
- if( ajaxOpts.addFocusedKey )
1791
- ajaxOpts.data.focusedKey = pers.focusedKey;
1792
- if( ajaxOpts.addExpandedKeyList )
1793
- ajaxOpts.data.expandedKeyList = pers.expandedKeyList.join(",");
1794
- if( ajaxOpts.addSelectedKeyList )
1795
- ajaxOpts.data.selectedKeyList = pers.selectedKeyList.join(",");
1796
-
2055
+ if( ajaxOpts.addActiveKey ){
2056
+ ajaxOpts.data.activeKey = pers.activeKey;
2057
+ }
2058
+ if( ajaxOpts.addFocusedKey ){
2059
+ ajaxOpts.data.focusedKey = pers.focusedKey;
2060
+ }
2061
+ if( ajaxOpts.addExpandedKeyList ){
2062
+ ajaxOpts.data.expandedKeyList = pers.expandedKeyList.join(",");
2063
+ }
2064
+ if( ajaxOpts.addSelectedKeyList ){
2065
+ ajaxOpts.data.selectedKeyList = pers.selectedKeyList.join(",");
2066
+ }
1797
2067
  // Set up onPostInit callback to be called when Ajax returns
1798
2068
  if( opts.onPostInit ) {
1799
- if( ajaxOpts.success )
2069
+ if( ajaxOpts.success ){
1800
2070
  this.logWarning("initAjax: success callback is ignored when onPostInit was specified.");
1801
- if( ajaxOpts.error )
2071
+ }
2072
+ if( ajaxOpts.error ){
1802
2073
  this.logWarning("initAjax: error callback is ignored when onPostInit was specified.");
2074
+ }
1803
2075
  var isReloading = pers.isReloading();
1804
- ajaxOpts["success"] = function(dtnode) { opts.onPostInit.call(dtnode.tree, isReloading, false); };
1805
- ajaxOpts["error"] = function(dtnode) { opts.onPostInit.call(dtnode.tree, isReloading, true); };
2076
+ ajaxOpts["success"] = function(dtnode) { opts.onPostInit.call(dtnode.tree, isReloading, false); };
2077
+ ajaxOpts["error"] = function(dtnode) { opts.onPostInit.call(dtnode.tree, isReloading, true); };
1806
2078
  }
1807
- this.logDebug("Dynatree._init(): send Ajax request...");
1808
- this.tnRoot.appendAjax(ajaxOpts);
2079
+ this.logDebug("Dynatree._init(): send Ajax request...");
2080
+ this.tnRoot.appendAjax(ajaxOpts);
1809
2081
  },
1810
2082
 
1811
2083
  toString: function() {
@@ -1816,11 +2088,11 @@ DynaTree.prototype = {
1816
2088
  toDict: function() {
1817
2089
  return this.tnRoot.toDict(true);
1818
2090
  },
1819
-
2091
+
1820
2092
  getPersistData: function() {
1821
2093
  return this.persistence.toDict();
1822
2094
  },
1823
-
2095
+
1824
2096
  logDebug: function(msg) {
1825
2097
  if( this.options.debugLevel >= 2 ) {
1826
2098
  Array.prototype.unshift.apply(arguments, ["debug"]);
@@ -1856,29 +2128,45 @@ DynaTree.prototype = {
1856
2128
  this.logDebug("dynatree.redraw() done.");
1857
2129
  },
1858
2130
 
1859
- reloadAjax: function() {
1860
- this.logWarning("tree.reloadAjax() is deprecated since v0.5.2 (use reload() instead).");
1861
- },
1862
-
1863
2131
  reload: function() {
1864
2132
  this._load();
1865
2133
  },
1866
-
2134
+
1867
2135
  getRoot: function() {
1868
2136
  return this.tnRoot;
1869
2137
  },
1870
2138
 
2139
+ enable: function() {
2140
+ this.$widget.enable();
2141
+ },
2142
+
2143
+ disable: function() {
2144
+ this.$widget.disable();
2145
+ },
2146
+
1871
2147
  getNodeByKey: function(key) {
2148
+ // Search the DOM by element ID (assuming this is faster than traversing all nodes).
1872
2149
  // $("#...") has problems, if the key contains '.', so we use getElementById()
1873
- // return $("#" + this.options.idPrefix + key).attr("dtnode");
1874
2150
  var el = document.getElementById(this.options.idPrefix + key);
1875
- return ( el && el.dtnode ) ? el.dtnode : null;
2151
+ if( el ){
2152
+ return el.dtnode ? el.dtnode : null;
2153
+ }
2154
+ // Not found in the DOM, but still may be in an unrendered part of tree
2155
+ var match = null;
2156
+ this.visit(function(node){
2157
+ // window.console.log("%s", node);
2158
+ if(node.data.key == key) {
2159
+ match = node;
2160
+ return false;
2161
+ }
2162
+ }, true);
2163
+ return match;
1876
2164
  },
1877
2165
 
1878
2166
  getActiveNode: function() {
1879
2167
  return this.activeNode;
1880
2168
  },
1881
-
2169
+
1882
2170
  reactivate: function(setFocus) {
1883
2171
  // Re-fire onQueryActivate and onActivate events.
1884
2172
  var node = this.activeNode;
@@ -1886,18 +2174,20 @@ DynaTree.prototype = {
1886
2174
  if( node ) {
1887
2175
  this.activeNode = null; // Force re-activating
1888
2176
  node.activate();
1889
- if( setFocus )
2177
+ if( setFocus ){
1890
2178
  node.focus();
2179
+ }
1891
2180
  }
1892
2181
  },
1893
2182
 
1894
2183
  getSelectedNodes: function(stopOnParents) {
1895
2184
  var nodeList = [];
1896
- this.tnRoot.visit(function(dtnode){
1897
- if( dtnode.bSelected ) {
1898
- nodeList.push(dtnode);
1899
- if( stopOnParents == true )
1900
- return false; // stop processing this branch
2185
+ this.tnRoot.visit(function(node){
2186
+ if( node.bSelected ) {
2187
+ nodeList.push(node);
2188
+ if( stopOnParents === true ){
2189
+ return "skip"; // stop processing this branch
2190
+ }
1901
2191
  }
1902
2192
  });
1903
2193
  return nodeList;
@@ -1906,8 +2196,9 @@ DynaTree.prototype = {
1906
2196
  activateKey: function(key) {
1907
2197
  var dtnode = (key === null) ? null : this.getNodeByKey(key);
1908
2198
  if( !dtnode ) {
1909
- if( this.activeNode )
2199
+ if( this.activeNode ){
1910
2200
  this.activeNode.deactivate();
2201
+ }
1911
2202
  this.activeNode = null;
1912
2203
  return null;
1913
2204
  }
@@ -1916,25 +2207,43 @@ DynaTree.prototype = {
1916
2207
  return dtnode;
1917
2208
  },
1918
2209
 
2210
+ loadKeyPath: function(keyPath, expand, callback) {
2211
+ var segList = keyPath.split(this.options.keyPathSeparator);
2212
+ // Remove leading '/'
2213
+ if(segList[0] == ""){
2214
+ segList.shift();
2215
+ }
2216
+ // Remove leading system root key
2217
+ if(segList[0] == this.tnRoot.data.key){
2218
+ this.logDebug("Removed leading root key.");
2219
+ segList.shift();
2220
+ }
2221
+ keyPath = segList.join(this.options.keyPathSeparator);
2222
+ return this.tnRoot.loadKeyPath(keyPath, expand, callback);
2223
+ },
2224
+
1919
2225
  selectKey: function(key, select) {
1920
2226
  var dtnode = this.getNodeByKey(key);
1921
- if( !dtnode )
2227
+ if( !dtnode ){
1922
2228
  return null;
2229
+ }
1923
2230
  dtnode.select(select);
1924
2231
  return dtnode;
1925
2232
  },
1926
2233
 
1927
2234
  enableUpdate: function(bEnable) {
1928
- if ( this.bEnableUpdate==bEnable )
2235
+ if ( this.bEnableUpdate==bEnable ){
1929
2236
  return bEnable;
2237
+ }
1930
2238
  this.bEnableUpdate = bEnable;
1931
- if ( bEnable )
2239
+ if ( bEnable ){
1932
2240
  this.redraw();
2241
+ }
1933
2242
  return !bEnable; // return previous value
1934
2243
  },
1935
2244
 
1936
- visit: function(fn, data, includeRoot) {
1937
- return this.tnRoot.visit(fn, data, includeRoot);
2245
+ visit: function(fn, includeRoot) {
2246
+ return this.tnRoot.visit(fn, includeRoot);
1938
2247
  },
1939
2248
 
1940
2249
  _createFromTag: function(parentTreeNode, $ulParent) {
@@ -1956,10 +2265,11 @@ TODO: better?
1956
2265
  // If only a <li> tag is specified, use the trimmed string up to the next child <ul> tag.
1957
2266
  title = $li.html();
1958
2267
  var iPos = title.search(/<ul/i);
1959
- if( iPos>=0 )
2268
+ if( iPos>=0 ){
1960
2269
  title = $.trim(title.substring(0, iPos));
1961
- else
2270
+ }else{
1962
2271
  title = $.trim(title);
2272
+ }
1963
2273
  // self.logDebug("%o", title);
1964
2274
  }
1965
2275
  // Parse node options from ID, title and class attributes
@@ -1970,18 +2280,22 @@ TODO: better?
1970
2280
  expand: $li.hasClass("expanded"),
1971
2281
  select: $li.hasClass("selected"),
1972
2282
  activate: $li.hasClass("active"),
1973
- focus: $li.hasClass("focused")
2283
+ focus: $li.hasClass("focused"),
2284
+ noLink: $li.hasClass("noLink")
1974
2285
  };
1975
- if( $li.attr("title") )
2286
+ if( $li.attr("title") ){
1976
2287
  data.tooltip = $li.attr("title");
1977
- if( $li.attr("id") )
2288
+ }
2289
+ if( $li.attr("id") ){
1978
2290
  data.key = $li.attr("id");
2291
+ }
1979
2292
  // If a data attribute is present, evaluate as a JavaScript object
1980
2293
  if( $li.attr("data") ) {
1981
2294
  var dataAttr = $.trim($li.attr("data"));
1982
2295
  if( dataAttr ) {
1983
- if( dataAttr.charAt(0) != "{" )
2296
+ if( dataAttr.charAt(0) != "{" ){
1984
2297
  dataAttr = "{" + dataAttr + "}"
2298
+ }
1985
2299
  try {
1986
2300
  $.extend(data, eval("(" + dataAttr + ")"));
1987
2301
  } catch(e) {
@@ -2007,7 +2321,7 @@ TODO: better?
2007
2321
  var $source = sourceNode ? $(sourceNode.span) : null;
2008
2322
  var $target = $(targetNode.span);
2009
2323
  if( !this.$dndMarker ) {
2010
- this.$dndMarker = $("<div id='dynatree_drop_marker'></div>")
2324
+ this.$dndMarker = $("<div id='dynatree-drop-marker'></div>")
2011
2325
  .hide()
2012
2326
  .prependTo("body");
2013
2327
  logMsg("Creating marker: %o", this.$dndMarker);
@@ -2017,18 +2331,25 @@ TODO: better?
2017
2331
  if(hitMode === "stop"){
2018
2332
  // sourceNode.removeClass("dynatree-drop-target");
2019
2333
  }
2334
+ // this.$dndMarker.attr("class", hitMode);
2020
2335
  if(hitMode === "after" || hitMode === "before" || hitMode === "over"){
2021
2336
  // $source && $source.addClass("dynatree-drag-source");
2022
- $target.addClass("dynatree-drop-target");
2023
2337
  var pos = $target.position();
2024
2338
  switch(hitMode){
2025
2339
  case "before":
2340
+ this.$dndMarker.removeClass("dynatree-drop-after dynatree-drop-over");
2341
+ this.$dndMarker.addClass("dynatree-drop-before");
2026
2342
  pos.top -= 8;
2027
2343
  break;
2028
2344
  case "after":
2345
+ this.$dndMarker.removeClass("dynatree-drop-before dynatree-drop-over");
2346
+ this.$dndMarker.addClass("dynatree-drop-after");
2029
2347
  pos.top += 8;
2030
2348
  break;
2031
2349
  default:
2350
+ this.$dndMarker.removeClass("dynatree-drop-after dynatree-drop-before");
2351
+ this.$dndMarker.addClass("dynatree-drop-over");
2352
+ $target.addClass("dynatree-drop-target");
2032
2353
  pos.left += 8;
2033
2354
  }
2034
2355
  this.$dndMarker.css({"left": (pos.left) + "px", "top": (pos.top) + "px" })
@@ -2069,29 +2390,42 @@ TODO: better?
2069
2390
  helper.removeClass("dynatree-drop-reject");
2070
2391
  }
2071
2392
  },
2072
-
2393
+
2073
2394
  _onDragEvent: function(eventName, node, otherNode, event, ui, draggable) {
2074
- /*
2395
+ /**
2075
2396
  * Handles drag'n'drop functionality.
2397
+ *
2398
+ * A standard jQuery drag-and-drop process may generate these calls:
2399
+ *
2400
+ * draggable helper():
2401
+ * _onDragEvent("helper", sourceNode, null, event, null, null);
2402
+ * start:
2403
+ * _onDragEvent("start", sourceNode, null, event, ui, draggable);
2404
+ * drag:
2405
+ * _onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
2406
+ * _onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
2407
+ * _onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
2408
+ * stop:
2409
+ * _onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
2410
+ * _onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
2411
+ * _onDragEvent("stop", sourceNode, null, event, ui, draggable);
2076
2412
  */
2077
- var _calcHitMode = function() {
2078
-
2079
- }
2080
- if(eventName !== "over")
2413
+ if(eventName !== "over"){
2081
2414
  this.logDebug("tree._onDragEvent(%s, %o, %o) - %o", eventName, node, otherNode, this);
2415
+ }
2082
2416
  var opts = this.options;
2083
2417
  var dnd = this.options.dnd;
2084
2418
  var res = null;
2085
2419
  var nodeTag = $(node.span);
2086
2420
  switch (eventName) {
2087
2421
  case "helper":
2088
- // Only event and node argument is available
2089
- var helper = $("<div class='dynatree-drag-helper'><span class='dynatree-drag-helper-img' /></div>")
2090
- .append($(event.target).closest('a').clone());
2091
- // Attach node reference to helper object
2092
- helper.data("dtSourceNode", node);
2093
- logMsg("helper.sourceNode=%o", helper.data("dtSourceNode"));
2094
- res = helper;
2422
+ // Only event and node argument is available
2423
+ var helper = $("<div class='dynatree-drag-helper'><span class='dynatree-drag-helper-img' /></div>")
2424
+ .append($(event.target).closest('a').clone());
2425
+ // Attach node reference to helper object
2426
+ helper.data("dtSourceNode", node);
2427
+ logMsg("helper.sourceNode=%o", helper.data("dtSourceNode"));
2428
+ res = helper;
2095
2429
  break;
2096
2430
  case "start":
2097
2431
  if(node.isStatusNode()) {
@@ -2101,54 +2435,77 @@ TODO: better?
2101
2435
  }
2102
2436
  if(res === false) {
2103
2437
  this.logDebug("tree.onDragStart() cancelled");
2104
- draggable._clear();
2438
+ //draggable._clear();
2439
+ // NOTE: the return value seems to be ignored (drag is not canceled, when false is returned)
2440
+ ui.helper.trigger("mouseup");
2441
+ ui.helper.hide();
2105
2442
  } else {
2106
2443
  nodeTag.addClass("dynatree-drag-source");
2107
2444
  }
2108
2445
  break;
2109
2446
  case "enter":
2110
2447
  res = dnd.onDragEnter ? dnd.onDragEnter(node, otherNode) : null;
2111
- // logMsg("helper %o", ui.helper);
2112
- ui.helper.data("enterResponse", res);
2448
+ res = {
2449
+ over: (res !== false) && ((res === true) || (res === "over") || $.inArray("over", res) >= 0),
2450
+ before: (res !== false) && ((res === true) || (res === "before") || $.inArray("before", res) >= 0),
2451
+ after: (res !== false) && ((res === true) || (res === "after") || $.inArray("after", res) >= 0)
2452
+ };
2453
+ ui.helper.data("enterResponse", res);
2113
2454
  this.logDebug("helper.enterResponse: %o", res);
2114
- // this._setDndStatus(otherNode, node, ui.helper, "over", res!==false);
2115
2455
  break;
2116
2456
  case "over":
2117
- // Auto-expand node
2118
- if(dnd.autoExpandMS && node.hasChildren() && !node.bExpanded) {
2119
- node.scheduleAction("expand", dnd.autoExpandMS);
2120
- }
2121
- var enterResponse = ui.helper.data("enterResponse");
2457
+ var enterResponse = ui.helper.data("enterResponse");
2122
2458
  var hitMode = null;
2123
- if(enterResponse === false){
2124
- // Don't call onDragOver if onEnter returned false.
2125
- break;
2126
- } else if(typeof enterResponse === "string") {
2127
- // Use hitMode from onEnter if provided.
2128
- hitMode = enterResponse;
2129
- } else {
2130
- // Calculate hitMode from relative cursor position.
2131
- var nodeOfs = nodeTag.position();
2132
- var relPos = { x: event.clientX - nodeOfs.left,
2133
- y: event.clientY - nodeOfs.top };
2134
- var relPos2 = { x: relPos.x / nodeTag.width(),
2135
- y: relPos.y / nodeTag.height() };
2136
- if( (relPos2.y > 0.25 && relPos2.y < 0.75)
2137
- // || (relPos2.x > 0.8 )
2138
- ) {
2139
- hitMode = "over";
2140
- } else if(relPos2.y <= 0.25) {
2141
- hitMode = "before";
2142
- } else {
2143
- hitMode = "after";
2144
- }
2145
- ui.helper.data("hitMode", hitMode);
2459
+ if(enterResponse === false){
2460
+ // Don't call onDragOver if onEnter returned false.
2461
+ break;
2462
+ } else if(typeof enterResponse === "string") {
2463
+ // Use hitMode from onEnter if provided.
2464
+ hitMode = enterResponse;
2465
+ } else {
2466
+ // Calculate hitMode from relative cursor position.
2467
+ var nodeOfs = nodeTag.position();
2468
+ var relPos = { x: event.clientX - nodeOfs.left,
2469
+ y: event.clientY - nodeOfs.top };
2470
+ var relPos2 = { x: relPos.x / nodeTag.width(),
2471
+ y: relPos.y / nodeTag.height() };
2472
+ if( enterResponse.after && relPos2.y > 0.75 ){
2473
+ hitMode = "after";
2474
+ } else if(!enterResponse.over && enterResponse.after && relPos2.y > 0.5 ){
2475
+ hitMode = "after";
2476
+ } else if(enterResponse.before && relPos2.y <= 0.25) {
2477
+ hitMode = "before";
2478
+ } else if(!enterResponse.over && enterResponse.before && relPos2.y <= 0.5) {
2479
+ hitMode = "before";
2480
+ } else if(enterResponse.over) {
2481
+ hitMode = "over";
2482
+ }
2483
+ // Prevent no-ops like 'before source node'
2484
+ // TODO: these are no-ops when moving nodes, but not in copy mode
2485
+ if( dnd.preventVoidMoves ){
2486
+ if(node === otherNode){
2487
+ logMsg(" drop over source node prevented");
2488
+ hitMode = null;
2489
+ }else if(hitMode === "before" && otherNode && node === otherNode.getNextSibling()){
2490
+ logMsg(" drop after source node prevented");
2491
+ hitMode = null;
2492
+ }else if(hitMode === "after" && otherNode && node === otherNode.getPrevSibling()){
2493
+ logMsg(" drop before source node prevented");
2494
+ hitMode = null;
2495
+ }else if(hitMode === "over" && otherNode
2496
+ && otherNode.parent === node && otherNode.isLastSibling() ){
2497
+ logMsg(" drop last child over own parent prevented");
2498
+ hitMode = null;
2499
+ }
2500
+ }
2501
+ logMsg("hitMode: %s - %s - %s", hitMode, (node.parent === otherNode), node.isLastSibling());
2502
+ ui.helper.data("hitMode", hitMode);
2146
2503
  // logMsg(" clientPos: %s/%s", event.clientX, event.clientY);
2147
2504
  // logMsg(" nodeOfs: %s/%s", nodeOfs.left, nodeOfs.top);
2148
2505
  // logMsg(" relPos: %s/%s", relPos.x, relPos.y);
2149
2506
  // logMsg(" relPos2: %s/%s: %s", relPos2.x, relPos2.y, hitMode);
2150
2507
  // logMsg(" e:%o", event);
2151
- }
2508
+ }
2152
2509
  /* var checkPos = function(node, pos) {
2153
2510
  var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
2154
2511
  var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
@@ -2158,80 +2515,91 @@ TODO: better?
2158
2515
  return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
2159
2516
  };
2160
2517
  var relPos = event.()*/
2161
- if(dnd.onDragOver)
2162
- res = dnd.onDragOver(node, otherNode, hitMode)
2163
- this._setDndStatus(otherNode, node, ui.helper, hitMode, res!==false)
2518
+ // Auto-expand node (only when 'over' the node, not 'before', or 'after')
2519
+ if(hitMode === "over"
2520
+ && dnd.autoExpandMS && node.hasChildren() !== false && !node.bExpanded) {
2521
+ node.scheduleAction("expand", dnd.autoExpandMS);
2522
+ }
2523
+ if(hitMode && dnd.onDragOver){
2524
+ res = dnd.onDragOver(node, otherNode, hitMode);
2525
+ }
2526
+ this._setDndStatus(otherNode, node, ui.helper, hitMode, res!==false);
2164
2527
  break;
2165
2528
  case "drop":
2166
- var enterResponse = ui.helper.data("enterResponse");
2167
- var hitMode = ui.helper.data("hitMode");
2168
- if(dnd.onDrop && enterResponse !== false)
2169
- dnd.onDrop(node, otherNode, hitMode)
2529
+ // var enterResponse = ui.helper.data("enterResponse");
2530
+ var hitMode = ui.helper.data("hitMode");
2531
+ // if(dnd.onDrop && enterResponse !== false)
2532
+ // dnd.onDrop(node, otherNode, hitMode)
2533
+ if(hitMode && dnd.onDrop){
2534
+ dnd.onDrop(node, otherNode, hitMode, ui, draggable);
2535
+ }
2170
2536
  break;
2171
2537
  case "leave":
2172
2538
  // Cancel pending expand request
2173
2539
  node.scheduleAction("cancel");
2174
- ui.helper.data("enterResponse", null);
2175
- ui.helper.data("hitMode", null);
2540
+ ui.helper.data("enterResponse", null);
2541
+ ui.helper.data("hitMode", null);
2176
2542
  // nodeTag.removeClass("dynatree-drop-hover dynatree-drop-accept dynatree-drop-reject");
2177
- this._setDndStatus(otherNode, node, ui.helper, "out", undefined)
2178
- if(dnd.onDragLeave)
2179
- dnd.onDragLeave(node, otherNode)
2543
+ this._setDndStatus(otherNode, node, ui.helper, "out", undefined);
2544
+ if(dnd.onDragLeave){
2545
+ dnd.onDragLeave(node, otherNode);
2546
+ }
2180
2547
  break;
2181
2548
  case "stop":
2182
2549
  nodeTag.removeClass("dynatree-drag-source");
2183
- if(dnd.onDragStop)
2184
- dnd.onDragStop(node)
2550
+ if(dnd.onDragStop){
2551
+ dnd.onDragStop(node);
2552
+ }
2185
2553
  break;
2186
2554
  default:
2187
2555
  throw "Unsupported drag event: " + eventName;
2188
2556
  }
2189
2557
  return res;
2190
2558
  },
2191
-
2559
+
2192
2560
  // --- end of class
2193
2561
  lastentry: undefined
2194
2562
  };
2195
2563
 
2196
- /*
2564
+ /*************************************************************************
2197
2565
  * Widget $(..).dynatree
2198
2566
  */
2199
2567
 
2200
2568
  $.widget("ui.dynatree", {
2201
2569
  /*
2202
2570
  init: function() {
2203
- // ui.core 1.6 renamed init() to _init(): this stub assures backward compatibility
2204
- _log("warn", "ui.dynatree.init() was called; you should upgrade to jquery.ui.core.js v1.8 or higher.");
2205
- return this._init();
2206
- },
2571
+ // ui.core 1.6 renamed init() to _init(): this stub assures backward compatibility
2572
+ _log("warn", "ui.dynatree.init() was called; you should upgrade to jquery.ui.core.js v1.8 or higher.");
2573
+ return this._init();
2574
+ },
2207
2575
  */
2208
2576
  _init: function() {
2209
2577
  if( parseFloat($.ui.version) < 1.8 ) {
2210
- // jquery.ui.core 1.8 renamed _init() to _create(): this stub assures backward compatibility
2211
- _log("warn", "ui.dynatree._init() was called; you should upgrade to jquery.ui.core.js v1.8 or higher.");
2578
+ // jquery.ui.core 1.8 renamed _init() to _create(): this stub assures backward compatibility
2579
+ _log("warn", "ui.dynatree._init() was called; you should upgrade to jquery.ui.core.js v1.8 or higher.");
2212
2580
  return this._create();
2213
2581
  }
2214
- // jquery.ui.core 1.8 still uses _init() to perform "default functionality"
2215
- _log("debug", "ui.dynatree._init() was called; no current default functionality.");
2216
- },
2217
-
2218
- _create: function() {
2219
- logMsg("Dynatree._create(): version='%s', debugLevel=%o.", DynaTree.version, this.options.debugLevel);
2582
+ // jquery.ui.core 1.8 still uses _init() to perform "default functionality"
2583
+ _log("debug", "ui.dynatree._init() was called; no current default functionality.");
2584
+ },
2220
2585
 
2221
- var opts = this.options;
2222
- // The widget framework supplies this.element and this.options.
2223
- this.options.event += ".dynatree"; // namespace event
2586
+ _create: function() {
2587
+ logMsg("Dynatree._create(): version='%s', debugLevel=%o.", DynaTree.version, this.options.debugLevel);
2224
2588
 
2225
- var divTree = this.element.get(0);
2226
- /* // Clear container, in case it contained some 'waiting' or 'error' text
2227
- // for clients that don't support JS
2228
- if( opts.children || (opts.initAjax && opts.initAjax.url) || opts.initId )
2229
- $(divTree).empty();
2589
+ var opts = this.options;
2590
+ // The widget framework supplies this.element and this.options.
2591
+ this.options.event += ".dynatree"; // namespace event
2592
+
2593
+ var divTree = this.element.get(0);
2594
+ /* // Clear container, in case it contained some 'waiting' or 'error' text
2595
+ // for clients that don't support JS
2596
+ if( opts.children || (opts.initAjax && opts.initAjax.url) || opts.initId )
2597
+ $(divTree).empty();
2230
2598
  */
2231
- // Create the DynaTree object
2232
- this.tree = new DynaTree(this);
2233
- this.tree._load();
2234
- this.tree.logDebug("Dynatree._init(): done.");
2599
+ // Create the DynaTree object
2600
+ this.tree = new DynaTree(this);
2601
+ this.tree._load();
2602
+ this.tree.logDebug("Dynatree._init(): done.");
2235
2603
  },
2236
2604
 
2237
2605
  bind: function() {
@@ -2240,14 +2608,17 @@ $.widget("ui.dynatree", {
2240
2608
 
2241
2609
  // Prevent duplicate binding
2242
2610
  this.unbind();
2243
-
2611
+
2244
2612
  var eventNames = "click.dynatree dblclick.dynatree";
2245
- if( o.keyboard ) // Note: leading ' '!
2613
+ if( o.keyboard ){
2614
+ // Note: leading ' '!
2246
2615
  eventNames += " keypress.dynatree keydown.dynatree";
2616
+ }
2247
2617
  $this.bind(eventNames, function(event){
2248
2618
  var dtnode = getDtNodeFromElement(event.target);
2249
- if( !dtnode )
2619
+ if( !dtnode ){
2250
2620
  return true; // Allow bubbling of other events
2621
+ }
2251
2622
  var prevPhase = dtnode.tree.phase;
2252
2623
  dtnode.tree.phase = "userEvent";
2253
2624
  try {
@@ -2262,7 +2633,7 @@ $.widget("ui.dynatree", {
2262
2633
  return ( o.onKeydown && o.onKeydown(dtnode, event)===false ) ? false : dtnode.onKeydown(event);
2263
2634
  case "keypress":
2264
2635
  return ( o.onKeypress && o.onKeypress(dtnode, event)===false ) ? false : dtnode.onKeypress(event);
2265
- };
2636
+ }
2266
2637
  } catch(e) {
2267
2638
  var _ = null; // issue 117
2268
2639
  dtnode.tree.logWarning("bind(%o): dtnode: %o, error: %o", event, dtnode, e);
@@ -2270,7 +2641,7 @@ $.widget("ui.dynatree", {
2270
2641
  dtnode.tree.phase = prevPhase;
2271
2642
  }
2272
2643
  });
2273
-
2644
+
2274
2645
  // focus/blur don't bubble, i.e. are not delegated to parent <div> tags,
2275
2646
  // so we use the addEventListener capturing phase.
2276
2647
  // See http://www.howtocreate.co.uk/tutorials/javascript/domevents
@@ -2292,30 +2663,30 @@ $.widget("ui.dynatree", {
2292
2663
  // disable click if event is configured to something else
2293
2664
  // if (!(/^click/).test(o.event))
2294
2665
  // this.$tabs.bind("click.tabs", function() { return false; });
2295
-
2666
+
2296
2667
  },
2297
-
2668
+
2298
2669
  unbind: function() {
2299
2670
  this.element.unbind(".dynatree");
2300
2671
  },
2301
-
2672
+
2302
2673
  /* TODO: we could handle option changes during runtime here (maybe to re-render, ...)
2303
2674
  setData: function(key, value) {
2304
2675
  this.tree.logDebug("dynatree.setData('" + key + "', '" + value + "')");
2305
2676
  },
2306
- */
2677
+ */
2307
2678
  enable: function() {
2308
2679
  this.bind();
2309
- // Call default disable(): remove -disabled from css:
2680
+ // Call default disable(): remove -disabled from css:
2310
2681
  $.Widget.prototype.enable.apply(this, arguments);
2311
2682
  },
2312
-
2683
+
2313
2684
  disable: function() {
2314
2685
  this.unbind();
2315
- // Call default disable(): add -disabled to css:
2686
+ // Call default disable(): add -disabled to css:
2316
2687
  $.Widget.prototype.disable.apply(this, arguments);
2317
2688
  },
2318
-
2689
+
2319
2690
  // --- getter methods (i.e. NOT returning a reference to $)
2320
2691
  getTree: function() {
2321
2692
  return this.tree;
@@ -2344,28 +2715,27 @@ $.widget("ui.dynatree", {
2344
2715
  //$.ui.dynatree.getter = "getTree getRoot getActiveNode getSelectedNodes";
2345
2716
 
2346
2717
 
2347
- /*
2718
+ /*******************************************************************************
2348
2719
  * Plugin default options:
2349
2720
  */
2350
2721
  //$.ui.dynatree.defaults = { @@ 1.8
2351
2722
  $.ui.dynatree.prototype.options = {
2352
2723
  title: "Dynatree", // Tree's name (only used for debug outpu)
2353
- minExpandLevel: 1, // 1: root node is not collapsible
2724
+ minExpandLevel: 1, // 1: root node is not collapsible
2354
2725
  imagePath: null, // Path to a folder containing icons. Defaults to 'skin/' subdirectory.
2355
2726
  children: null, // Init tree structure from this object array.
2356
2727
  initId: null, // Init tree structure from a <ul> element with this ID.
2357
2728
  initAjax: null, // Ajax options used to initialize the tree strucuture.
2358
2729
  autoFocus: true, // Set focus to first child, when expanding or lazy-loading.
2359
2730
  keyboard: true, // Support keyboard navigation.
2360
- persist: false, // Persist expand-status to a cookie
2731
+ persist: false, // Persist expand-status to a cookie
2361
2732
  autoCollapse: false, // Automatically collapse all siblings, when a node is expanded.
2362
2733
  clickFolderMode: 3, // 1:activate, 2:expand, 3:activate and expand
2363
2734
  activeVisible: true, // Make sure, active nodes are visible (expanded).
2364
2735
  checkbox: false, // Show checkboxes.
2365
2736
  selectMode: 2, // 1:single, 2:multi, 3:multi-hier
2366
2737
  fx: null, // Animations, e.g. null or { height: "toggle", duration: 200 }
2367
- enableDrag: false,
2368
- enableDrop: false,
2738
+ noLink: false, // Use <span> instead of <a> tags for all nodes
2369
2739
  // Low level event handlers: onEvent(dtnode, event): return false, to stop default processing
2370
2740
  onClick: null, // null: generate focus, expand, activate, select events.
2371
2741
  onDblClick: null, // (No default actions.)
@@ -2378,7 +2748,7 @@ $.ui.dynatree.prototype.options = {
2378
2748
  onQueryActivate: null, // Callback(flag, dtnode) before a node is (de)activated.
2379
2749
  onQuerySelect: null, // Callback(flag, dtnode) before a node is (de)selected.
2380
2750
  onQueryExpand: null, // Callback(flag, dtnode) before a node is expanded/collpsed.
2381
-
2751
+
2382
2752
  // High level event handlers
2383
2753
  onPostInit: null, // Callback(isReloading, isError) when tree was (re)loaded.
2384
2754
  onActivate: null, // Callback(dtnode) when a node is activated.
@@ -2386,15 +2756,16 @@ $.ui.dynatree.prototype.options = {
2386
2756
  onSelect: null, // Callback(flag, dtnode) when a node is (de)selected.
2387
2757
  onExpand: null, // Callback(dtnode) when a node is expanded/collapsed.
2388
2758
  onLazyRead: null, // Callback(dtnode) when a lazy node is expanded for the first time.
2389
-
2759
+
2390
2760
  // Drag'n'drop support
2391
2761
  dnd: {
2392
2762
  // Make tree nodes draggable:
2393
2763
  onDragStart: null, // Callback(sourceNode), return true, to enable dnd
2394
2764
  onDragStop: null, // Callback(sourceNode)
2395
- helper: null,
2765
+ // helper: null,
2396
2766
  // Make tree nodes accept draggables
2397
- autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering.
2767
+ autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering.
2768
+ preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
2398
2769
  onDragEnter: null, // Callback(targetNode, sourceNode)
2399
2770
  onDragOver: null, // Callback(targetNode, sourceNode, hitMode)
2400
2771
  onDrop: null, // Callback(targetNode, sourceNode, hitMode)
@@ -2408,25 +2779,26 @@ $.ui.dynatree.prototype.options = {
2408
2779
  loading: "Loading&#8230;",
2409
2780
  loadError: "Load error!"
2410
2781
  },
2411
- generateIds: false,
2782
+ generateIds: false, // Generate id attributes like <span id='dynatree-id-KEY'>
2412
2783
  idPrefix: "dynatree-id-", // Used to generate node id's like <span id="dynatree-id-<key>">.
2784
+ keyPathSeparator: "/", // Used by node.getKeyPath() and tree.loadKeyPath().
2413
2785
  // cookieId: "dynatree-cookie", // Choose a more unique name, to allow multiple trees.
2414
- cookieId: "dynatree", // Choose a more unique name, to allow multiple trees.
2786
+ cookieId: "dynatree", // Choose a more unique name, to allow multiple trees.
2415
2787
  cookie: {
2416
2788
  expires: null //7, // Days or Date; null: session cookie
2417
2789
  // path: "/", // Defaults to current page
2418
2790
  // domain: "jquery.com",
2419
2791
  // secure: true
2420
2792
  },
2421
- // Class names used, when rendering the HTML markup.
2422
- // Note: if only single entries are passed for options.classNames, all other
2423
- // values are still set to default.
2793
+ // Class names used, when rendering the HTML markup.
2794
+ // Note: if only single entries are passed for options.classNames, all other
2795
+ // values are still set to default.
2424
2796
  classNames: {
2425
2797
  container: "dynatree-container",
2426
2798
  node: "dynatree-node",
2427
2799
  folder: "dynatree-folder",
2428
2800
  // document: "dynatree-document",
2429
-
2801
+
2430
2802
  empty: "dynatree-empty",
2431
2803
  vline: "dynatree-vline",
2432
2804
  expander: "dynatree-expander",
@@ -2435,7 +2807,7 @@ $.ui.dynatree.prototype.options = {
2435
2807
  nodeIcon: "dynatree-icon",
2436
2808
  title: "dynatree-title",
2437
2809
  noConnector: "dynatree-no-connector",
2438
-
2810
+
2439
2811
  nodeError: "dynatree-statusnode-error",
2440
2812
  nodeWait: "dynatree-statusnode-wait",
2441
2813
  hidden: "dynatree-hidden",
@@ -2451,13 +2823,13 @@ $.ui.dynatree.prototype.options = {
2451
2823
  partsel: "dynatree-partsel",
2452
2824
  lastsib: "dynatree-lastsib"
2453
2825
  },
2454
- debugLevel: 0, // 0:quiet, 1:normal, 2:debug $REPLACE: debugLevel: 1,
2826
+ debugLevel: 2, // 0:quiet, 1:normal, 2:debug $REPLACE: debugLevel: 1,
2455
2827
 
2456
2828
  // ------------------------------------------------------------------------
2457
2829
  lastentry: undefined
2458
2830
  };
2459
2831
 
2460
- /*
2832
+ /*******************************************************************************
2461
2833
  * Reserved data attributes for a tree node.
2462
2834
  */
2463
2835
  $.ui.dynatree.nodedatadefaults = {
@@ -2467,14 +2839,15 @@ $.ui.dynatree.nodedatadefaults = {
2467
2839
  isLazy: false, // Call onLazyRead(), when the node is expanded for the first time to allow for delayed creation of children.
2468
2840
  tooltip: null, // Show this popup text.
2469
2841
  icon: null, // Use a custom image (filename relative to tree.options.imagePath). 'null' for default icon, 'false' for no icon.
2470
- addClass: null, // Class name added to the node's span tag.
2842
+ addClass: null, // Class name added to the node's span tag.
2843
+ noLink: false, // Use <span> instead of <a> tag for this node
2471
2844
  activate: false, // Initial active status.
2472
2845
  focus: false, // Initial focused status.
2473
2846
  expand: false, // Initial expanded status.
2474
2847
  select: false, // Initial selected status.
2475
2848
  hideCheckbox: false, // Suppress checkbox display for this node.
2476
2849
  unselectable: false, // Prevent selection.
2477
- // disabled: false,
2850
+ // disabled: false,
2478
2851
  // The following attributes are only valid if passed to some functions:
2479
2852
  children: null, // Array of child nodes.
2480
2853
  // NOTE: we can also add custom attributes here.
@@ -2483,7 +2856,7 @@ $.ui.dynatree.nodedatadefaults = {
2483
2856
  lastentry: undefined
2484
2857
  };
2485
2858
 
2486
- /*
2859
+ /*******************************************************************************
2487
2860
  * Drag and drop support
2488
2861
  */
2489
2862
  function _initDragAndDrop(tree) {
@@ -2494,122 +2867,135 @@ function _initDragAndDrop(tree) {
2494
2867
  }
2495
2868
  // Attach ui.draggable to this Dynatree instance
2496
2869
  if(dnd && dnd.onDragStart ) {
2497
- tree.$tree.draggable({
2498
- addClasses: false,
2499
- appendTo: "body",
2500
- containment: false,
2501
- delay: 0,
2502
- distance: 4,
2503
- revert: false,
2504
- // Delegate draggable.start, drag, and stop events to our handler
2505
- connectToDynatree: true,
2506
- // Let source tree create the helper element
2507
- helper: function(event) {
2508
- var sourceNode = getDtNodeFromElement(event.target);
2509
- return sourceNode.tree._onDragEvent("helper", sourceNode, null, event, null, null);
2510
- },
2511
- _last: null
2512
- });
2870
+ tree.$tree.draggable({
2871
+ addClasses: false,
2872
+ appendTo: "body",
2873
+ containment: false,
2874
+ delay: 0,
2875
+ distance: 4,
2876
+ revert: false,
2877
+ // Delegate draggable.start, drag, and stop events to our handler
2878
+ connectToDynatree: true,
2879
+ // Let source tree create the helper element
2880
+ helper: function(event) {
2881
+ var sourceNode = getDtNodeFromElement(event.target);
2882
+ return sourceNode.tree._onDragEvent("helper", sourceNode, null, event, null, null);
2883
+ },
2884
+ _last: null
2885
+ });
2513
2886
  }
2514
2887
  // Attach ui.droppable to this Dynatree instance
2515
2888
  if(dnd && dnd.onDrop) {
2516
- tree.$tree.droppable({
2517
- addClasses: false,
2518
- //tolerance: "intersect",
2519
- tolerance: "touch",
2520
- greedy: false,
2521
- _last: null
2522
- });
2889
+ tree.$tree.droppable({
2890
+ addClasses: false,
2891
+ tolerance: "intersect",
2892
+ greedy: false,
2893
+ _last: null
2894
+ });
2523
2895
  }
2524
2896
  }
2525
2897
 
2526
2898
  //--- Extend ui.draggable event handling --------------------------------------
2527
- var didRegisterDnd = false;
2899
+ var didRegisterDnd = false;
2528
2900
  var _registerDnd = function() {
2529
- if(didRegisterDnd)
2901
+ if(didRegisterDnd){
2530
2902
  return;
2903
+ }
2531
2904
  $.ui.plugin.add("draggable", "connectToDynatree", {
2532
- start: function(event, ui) {
2533
- var draggable = $(this).data("draggable");
2534
- var sourceNode = ui.helper.data("dtSourceNode") || null;
2535
- logMsg("draggable-connectToDynatree.start, %o", sourceNode);
2536
- logMsg(" this: %o", this);
2537
- logMsg(" event: %o", event);
2538
- logMsg(" draggable: %o", draggable);
2539
- logMsg(" ui: %o", ui);
2540
- if(sourceNode) {
2541
- // Adjust helper offset for tree nodes
2905
+ start: function(event, ui) {
2906
+ var draggable = $(this).data("draggable");
2907
+ var sourceNode = ui.helper.data("dtSourceNode") || null;
2908
+ logMsg("draggable-connectToDynatree.start, %s", sourceNode);
2909
+ logMsg(" this: %o", this);
2910
+ logMsg(" event: %o", event);
2911
+ logMsg(" draggable: %o", draggable);
2912
+ logMsg(" ui: %o", ui);
2913
+ if(sourceNode) {
2914
+ // Adjust helper offset for tree nodes
2542
2915
  /*
2543
- var sourcePosition = $(sourceNode.span).position();
2544
- var cssPosition = $(ui.helper).position();
2545
- logMsg(" draggable.offset.click: %s/%s", draggable.offset.click.left, draggable.offset.click.top);
2546
- logMsg(" sourceNode.position: %s/%s", sourcePosition.left, sourcePosition.top);
2547
- logMsg(" helper.position: %s/%s", cssPosition.left, cssPosition.top);
2548
- logMsg(" event.target.offset: %s/%s, %sx%s", event.target.offsetLeft, event.target.offsetTop, event.target.offsetWidth, event.target.offsetHeight);
2549
- logMsg(" draggable.positionAbs: %s/%s", draggable.positionAbs.left, draggable.positionAbs.top);
2916
+ var sourcePosition = $(sourceNode.span).position();
2917
+ var cssPosition = $(ui.helper).position();
2918
+ logMsg(" draggable.offset.click: %s/%s", draggable.offset.click.left, draggable.offset.click.top);
2919
+ logMsg(" sourceNode.position: %s/%s", sourcePosition.left, sourcePosition.top);
2920
+ logMsg(" helper.position: %s/%s", cssPosition.left, cssPosition.top);
2921
+ logMsg(" event.target.offset: %s/%s, %sx%s", event.target.offsetLeft, event.target.offsetTop, event.target.offsetWidth, event.target.offsetHeight);
2922
+ logMsg(" draggable.positionAbs: %s/%s", draggable.positionAbs.left, draggable.positionAbs.top);
2550
2923
  */
2551
- // Adjust helper offset, so cursor is slightly outside top/left corner
2924
+ // Adjust helper offset, so cursor is slightly outside top/left corner
2552
2925
  // draggable.offset.click.top -= event.target.offsetTop;
2553
2926
  // draggable.offset.click.left -= event.target.offsetLeft;
2554
- draggable.offset.click.top = -2;
2555
- draggable.offset.click.left = + 16;
2556
- logMsg(" draggable.offset.click FIXED: %s/%s", draggable.offset.click.left, draggable.offset.click.top);
2557
- // Trigger onDragStart event
2558
- // TODO: when called as connectTo..., the return value is ignored(?)
2559
- return sourceNode.tree._onDragEvent("start", sourceNode, null, event, ui, draggable);
2560
- }
2561
- },
2562
- drag: function(event, ui) {
2563
- var draggable = $(this).data("draggable");
2564
- var sourceNode = ui.helper.data("dtSourceNode") || null;
2927
+ draggable.offset.click.top = -2;
2928
+ draggable.offset.click.left = + 16;
2929
+ logMsg(" draggable.offset.click FIXED: %s/%s", draggable.offset.click.left, draggable.offset.click.top);
2930
+ // Trigger onDragStart event
2931
+ // TODO: when called as connectTo..., the return value is ignored(?)
2932
+ return sourceNode.tree._onDragEvent("start", sourceNode, null, event, ui, draggable);
2933
+ }
2934
+ },
2935
+ drag: function(event, ui) {
2936
+ var draggable = $(this).data("draggable");
2937
+ var sourceNode = ui.helper.data("dtSourceNode") || null;
2565
2938
  var prevTargetNode = ui.helper.data("dtTargetNode") || null;
2566
- var targetNode = getDtNodeFromElement(event.target);
2567
- ui.helper.data("dtTargetNode", targetNode);
2568
- // Leaving a tree node
2569
- if(prevTargetNode && prevTargetNode !== targetNode ) {
2570
- prevTargetNode.tree._onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
2571
- }
2572
- if(targetNode){
2573
- if(!targetNode.tree.options.dnd.onDrop) {
2574
- // not enabled as drop target
2575
- } else if(targetNode === prevTargetNode) {
2576
- // Moving over same node
2577
- targetNode.tree._onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
2578
- }else{
2579
- // Entering this node first time
2580
- targetNode.tree._onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
2581
- }
2582
- }
2583
- // else go ahead with standard event handling
2584
- },
2585
- stop: function(event, ui) {
2586
- var draggable = $(this).data("draggable");
2587
- var sourceNode = ui.helper.data("dtSourceNode") || null;
2588
- var targetNode = getDtNodeFromElement(event.target);
2939
+ var targetNode = getDtNodeFromElement(event.target);
2940
+ if(event.target && !targetNode){
2941
+ // We got a drag event, but the targetNode could not be found
2942
+ // at the event location. This may happen, if the mouse
2943
+ // jumped over the drag helper, in which case we ignore it:
2944
+ var isHelper = $(event.target).closest("div.dynatree-drag-helper,#dynatree-drop-marker").length > 0;
2945
+ if(isHelper){
2946
+ logMsg("Drag event over helper: ignored.");
2947
+ return;
2948
+ }
2949
+ }
2950
+ // logMsg("draggable-connectToDynatree.drag: targetNode(from event): %s, dtTargetNode: %s", targetNode, ui.helper.data("dtTargetNode"));
2951
+ ui.helper.data("dtTargetNode", targetNode);
2952
+ // Leaving a tree node
2953
+ if(prevTargetNode && prevTargetNode !== targetNode ) {
2954
+ prevTargetNode.tree._onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
2955
+ }
2956
+ if(targetNode){
2957
+ if(!targetNode.tree.options.dnd.onDrop) {
2958
+ // not enabled as drop target
2959
+ } else if(targetNode === prevTargetNode) {
2960
+ // Moving over same node
2961
+ targetNode.tree._onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
2962
+ }else{
2963
+ // Entering this node first time
2964
+ targetNode.tree._onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
2965
+ }
2966
+ }
2967
+ // else go ahead with standard event handling
2968
+ },
2969
+ stop: function(event, ui) {
2970
+ var draggable = $(this).data("draggable");
2971
+ var sourceNode = ui.helper.data("dtSourceNode") || null;
2972
+ // var targetNode = getDtNodeFromElement(event.target);
2973
+ var targetNode = ui.helper.data("dtTargetNode") || null;
2974
+ logMsg("draggable-connectToDynatree.stop: targetNode(from event): %s, dtTargetNode: %s", targetNode, ui.helper.data("dtTargetNode"));
2589
2975
  // var targetTree = targetNode ? targetNode.tree : null;
2590
2976
  // if(dtnode && dtnode.tree.
2591
- logMsg("draggable-connectToDynatree.stop, %o", sourceNode);
2592
- var mouseDownEvent = draggable._mouseDownEvent;
2593
- var eventType = event.type;
2594
- logMsg(" type: %o, downEvent: %o, upEvent: %o", eventType, mouseDownEvent, event);
2595
- var dropped = (eventType == "mouseup" && event.which == 1);
2596
- if(!dropped)
2597
- logMsg("Drag was cancelled");
2598
- if(targetNode) {
2599
- if(dropped)
2600
- targetNode.tree._onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
2601
- targetNode.tree._onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
2602
- }
2603
- if(sourceNode)
2604
- sourceNode.tree._onDragEvent("stop", sourceNode, null, event, ui, draggable);
2605
- }
2977
+ logMsg("draggable-connectToDynatree.stop, %s", sourceNode);
2978
+ var mouseDownEvent = draggable._mouseDownEvent;
2979
+ var eventType = event.type;
2980
+ logMsg(" type: %o, downEvent: %o, upEvent: %o", eventType, mouseDownEvent, event);
2981
+ logMsg(" targetNode: %o", targetNode);
2982
+ var dropped = (eventType == "mouseup" && event.which == 1);
2983
+ if(!dropped){
2984
+ logMsg("Drag was cancelled");
2985
+ }
2986
+ if(targetNode) {
2987
+ if(dropped){
2988
+ targetNode.tree._onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
2989
+ }
2990
+ targetNode.tree._onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
2991
+ }
2992
+ if(sourceNode){
2993
+ sourceNode.tree._onDragEvent("stop", sourceNode, null, event, ui, draggable);
2994
+ }
2995
+ }
2606
2996
  });
2607
2997
  didRegisterDnd = true;
2608
2998
  };
2609
2999
 
2610
-
2611
3000
  // ---------------------------------------------------------------------------
2612
3001
  })(jQuery);
2613
-
2614
- // Eclipse syntax parser breaks on this expression, so we put it at the bottom.
2615
- var _rexDtLibName = /.*dynatree[^/]*\.js$/i;