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

Sign up to get free protection for your applications and to get access to all the features.
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;