parlement 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. data/CHANGES +709 -0
  2. data/COPYING +223 -0
  3. data/README +20 -0
  4. data/Rakefile +136 -0
  5. data/app/controllers/account_controller.rb +181 -0
  6. data/app/controllers/application.rb +30 -0
  7. data/app/controllers/elt_controller.rb +83 -0
  8. data/app/helpers/account_helper.rb +2 -0
  9. data/app/helpers/application_helper.rb +4 -0
  10. data/app/helpers/elt_helper.rb +37 -0
  11. data/app/helpers/live_tree.rb +238 -0
  12. data/app/helpers/mailman.rb +96 -0
  13. data/app/models/attachment.rb +4 -0
  14. data/app/models/elt.rb +17 -0
  15. data/app/models/mail.rb +4 -0
  16. data/app/models/notifier.rb +13 -0
  17. data/app/models/person.rb +9 -0
  18. data/app/models/user.rb +7 -0
  19. data/app/models/user_notify.rb +75 -0
  20. data/app/views/account/_help.rhtml +23 -0
  21. data/app/views/account/_login.rhtml +57 -0
  22. data/app/views/account/_show.rhtml +31 -0
  23. data/app/views/account/logout.rhtml +10 -0
  24. data/app/views/account/signup.rhtml +17 -0
  25. data/app/views/account/welcome.rhtml +13 -0
  26. data/app/views/elt/_elt.rhtml +105 -0
  27. data/app/views/elt/_form.rhtml +31 -0
  28. data/app/views/elt/_list.rhtml +28 -0
  29. data/app/views/elt/new.rhtml +102 -0
  30. data/app/views/elt/rss.rxml +31 -0
  31. data/app/views/elt/show.rhtml +46 -0
  32. data/app/views/elt/show_tree.rhtml +8 -0
  33. data/app/views/layouts/scaffold.rhtml +13 -0
  34. data/app/views/layouts/top.rhtml +45 -0
  35. data/app/views/notifier/changeEmail.rhtml +10 -0
  36. data/config/boot.rb +17 -0
  37. data/config/database.yml +82 -0
  38. data/config/environment.rb +92 -0
  39. data/config/environments/development.rb +17 -0
  40. data/config/environments/production.rb +17 -0
  41. data/config/environments/test.rb +17 -0
  42. data/config/environments/user_environment.rb +1 -0
  43. data/config/routes.rb +28 -0
  44. data/db/ROOT/CV.txt +166 -0
  45. data/db/ROOT/IP.txt +3 -0
  46. data/db/ROOT/parleR.txt +3 -0
  47. data/db/ROOT/parlement/security.txt +34 -0
  48. data/db/ROOT/parlement/test.txt +4 -0
  49. data/db/ROOT/parlement.txt +51 -0
  50. data/db/ROOT/perso.txt +215 -0
  51. data/db/schema.sql +127 -0
  52. data/lib/data_import.rb +54 -0
  53. data/lib/file_column.rb +263 -0
  54. data/lib/file_column_helper.rb +45 -0
  55. data/lib/localization.rb +88 -0
  56. data/lib/localizer.rb +88 -0
  57. data/lib/login_system.rb +87 -0
  58. data/lib/rails_file_column.rb +19 -0
  59. data/lib/user_system.rb +101 -0
  60. data/public/404.html +8 -0
  61. data/public/500.html +8 -0
  62. data/public/dispatch.cgi +10 -0
  63. data/public/dispatch.fcgi +24 -0
  64. data/public/dispatch.rb +10 -0
  65. data/public/engine_files/README +5 -0
  66. data/public/engine_files/login_engine/stylesheets/login_engine.css +81 -0
  67. data/public/favicon.ico +0 -0
  68. data/public/favicon.png +0 -0
  69. data/public/images/live_tree_branch_collapsed_icon.gif +0 -0
  70. data/public/images/live_tree_branch_expanded_icon.gif +0 -0
  71. data/public/images/live_tree_leaf_icon.gif +0 -0
  72. data/public/images/live_tree_loading_spinner.gif +0 -0
  73. data/public/images/webfeed.gif +0 -0
  74. data/public/javascripts/controls.js +721 -0
  75. data/public/javascripts/dragdrop.js +519 -0
  76. data/public/javascripts/effects.js +992 -0
  77. data/public/javascripts/live_tree.js +749 -0
  78. data/public/javascripts/prototype.js +1726 -0
  79. data/public/javascripts/scriptaculous.js +47 -0
  80. data/public/javascripts/slider.js +258 -0
  81. data/public/oldREADME +190 -0
  82. data/public/oldindex.html +78 -0
  83. data/public/robots.txt +1 -0
  84. data/public/stylesheets/default.css +238 -0
  85. data/public/stylesheets/live_tree.css +62 -0
  86. data/public/stylesheets/scaffold.css +74 -0
  87. data/script/about +3 -0
  88. data/script/benchmarker +19 -0
  89. data/script/breakpointer +3 -0
  90. data/script/console +3 -0
  91. data/script/create_db +7 -0
  92. data/script/destroy +3 -0
  93. data/script/generate +3 -0
  94. data/script/performance/benchmarker +3 -0
  95. data/script/performance/profiler +3 -0
  96. data/script/plugin +3 -0
  97. data/script/process/reaper +3 -0
  98. data/script/process/spawner +3 -0
  99. data/script/process/spinner +3 -0
  100. data/script/profiler +34 -0
  101. data/script/runner +3 -0
  102. data/script/server +3 -0
  103. data/test/fixtures/attachments.yml +10 -0
  104. data/test/fixtures/elts.yml +15 -0
  105. data/test/fixtures/mails.yml +7 -0
  106. data/test/fixtures/people.yml +49 -0
  107. data/test/fixtures/users.yml +41 -0
  108. data/test/functional/account_controller_test.rb +239 -0
  109. data/test/functional/elt_controller_test.rb +18 -0
  110. data/test/mocks/test/time.rb +17 -0
  111. data/test/mocks/test/user_notify.rb +16 -0
  112. data/test/test_helper.rb +28 -0
  113. data/test/unit/attachment_test.rb +14 -0
  114. data/test/unit/elt_test.rb +14 -0
  115. data/test/unit/mail_test.rb +14 -0
  116. data/test/unit/notifier_test.rb +31 -0
  117. data/test/unit/person_test.rb +24 -0
  118. data/test/unit/user_test.rb +94 -0
  119. data/vendor/plugins/engines/CHANGELOG +7 -0
  120. data/vendor/plugins/engines/README +128 -0
  121. data/vendor/plugins/engines/init.rb +33 -0
  122. data/vendor/plugins/engines/lib/action_mailer_extensions.rb +160 -0
  123. data/vendor/plugins/engines/lib/action_view_extensions.rb +130 -0
  124. data/vendor/plugins/engines/lib/dependencies_extensions.rb +56 -0
  125. data/vendor/plugins/engines/lib/engines.rb +292 -0
  126. data/vendor/plugins/engines/lib/ruby_extensions.rb +127 -0
  127. data/vendor/plugins/engines/lib/testing_extensions.rb +33 -0
  128. data/vendor/plugins/engines/test/ruby_extensions_test.rb +94 -0
  129. data/vendor/plugins/login_engine/README +258 -0
  130. data/vendor/plugins/login_engine/app/controllers/user_controller.rb +248 -0
  131. data/vendor/plugins/login_engine/app/helpers/user_helper.rb +88 -0
  132. data/vendor/plugins/login_engine/app/models/user.rb +7 -0
  133. data/vendor/plugins/login_engine/app/models/user_notify.rb +75 -0
  134. data/vendor/plugins/login_engine/app/views/user/_edit.rhtml +11 -0
  135. data/vendor/plugins/login_engine/app/views/user/_password.rhtml +9 -0
  136. data/vendor/plugins/login_engine/app/views/user/change_password.rhtml +17 -0
  137. data/vendor/plugins/login_engine/app/views/user/edit.rhtml +23 -0
  138. data/vendor/plugins/login_engine/app/views/user/forgot_password.rhtml +18 -0
  139. data/vendor/plugins/login_engine/app/views/user/home.rhtml +7 -0
  140. data/vendor/plugins/login_engine/app/views/user/login.rhtml +17 -0
  141. data/vendor/plugins/login_engine/app/views/user/logout.rhtml +8 -0
  142. data/vendor/plugins/login_engine/app/views/user/signup.rhtml +17 -0
  143. data/vendor/plugins/login_engine/app/views/user_notify/change_password.rhtml +10 -0
  144. data/vendor/plugins/login_engine/app/views/user_notify/delete.rhtml +5 -0
  145. data/vendor/plugins/login_engine/app/views/user_notify/forgot_password.rhtml +11 -0
  146. data/vendor/plugins/login_engine/app/views/user_notify/pending_delete.rhtml +9 -0
  147. data/vendor/plugins/login_engine/app/views/user_notify/signup.rhtml +12 -0
  148. data/vendor/plugins/login_engine/db/schema.rb +25 -0
  149. data/vendor/plugins/login_engine/init_engine.rb +10 -0
  150. data/vendor/plugins/login_engine/lib/login_engine/authenticated_system.rb +107 -0
  151. data/vendor/plugins/login_engine/lib/login_engine/authenticated_user.rb +149 -0
  152. data/vendor/plugins/login_engine/lib/login_engine.rb +58 -0
  153. data/vendor/plugins/login_engine/public/stylesheets/login_engine.css +81 -0
  154. data/vendor/plugins/login_engine/tasks/tasks.rake +4 -0
  155. data/vendor/plugins/login_engine/test/fixtures/templates/users.yml +41 -0
  156. data/vendor/plugins/login_engine/test/fixtures/users.yml +41 -0
  157. data/vendor/plugins/login_engine/test/functional/user_controller_test.rb +533 -0
  158. data/vendor/plugins/login_engine/test/mocks/mail.rb +14 -0
  159. data/vendor/plugins/login_engine/test/mocks/time.rb +19 -0
  160. data/vendor/plugins/login_engine/test/test_helper.rb +15 -0
  161. data/vendor/plugins/login_engine/test/unit/user_test.rb +94 -0
  162. metadata +276 -0
@@ -0,0 +1,749 @@
1
+ // LiveTree, version: 0.1
2
+ //
3
+ // Home page: http://www.epiphyte.ca/code/live_tree.html
4
+ //
5
+ // Copyright (c) 2005 Emanuel Borsboom
6
+ //
7
+ // Permission is hereby granted, free of charge, to any person obtaining a
8
+ // copy of this software and associated documentation files (the
9
+ // "Software"), to deal in the Software without restriction, including
10
+ // without limitation the rights to use, copy, modify, merge, publish,
11
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
12
+ // persons to whom the Software is furnished to do so, subject to the
13
+ // following conditions:
14
+ //
15
+ // The above copyright notice and this permission notice shall be included
16
+ // in all copies or substantial portions of the Software.
17
+ //
18
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
21
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ function LiveTree(id, options) {
27
+ this.id = id;
28
+
29
+ if (options == null) {
30
+ options = {};
31
+ }
32
+
33
+ this.dataUrl = options.dataUrl;
34
+ this.cssClass = options.cssClass;
35
+ this.cssStyle = options.cssStyle;
36
+ this.expandRootItem = (options.expandRootItem == null ? true : options.expandRootItem);
37
+ this.hideRootItem = (options.hideRootItem == null ? false : options.hideRootItem);
38
+ this.rootItemId = options.rootItemId;
39
+ this.expandItemOnClick = (options.expandItemOnClick == null ? true : options.expandItemOnClick);
40
+ this.initialData = options.initialData;
41
+ this.scroll = (options.scroll == null ? true : options.scroll);
42
+ this.preloadItems = (options.preloadItems == null ? true : options.preloadItems);
43
+
44
+ this.collapsedItemIconHtml = options.collapsedItemIconHtml;
45
+ this.expandedItemIconHtml = options.expandedItemIconHtml;
46
+ this.leafIconHtml = options.leafIconHtml;
47
+ this.loadingIconHtml = options.loadingIconHtml;
48
+ this.loadingTreeHtml = options.loadingTreeHtml;
49
+ this.searchingHtml = options.searchingHtml;
50
+
51
+ this.onClickItem = options.onClickItem;
52
+ this.allowClickBranch = (options.allowClickBranch == null ? true : options.allowClickBranch);
53
+ this.allowClickLeaf = (options.allowClickLeaf == null ? true : options.allowClickLeaf);
54
+ this.onExpandItem = options.onExpandItem;
55
+ this.onCollapseItem = options.onCollapseItem;
56
+ this.onLoadItem = options.onLoadItem;
57
+
58
+ this._root = {};
59
+ this._itemsIndex = {};
60
+ this._activeItemId = null;
61
+ this._scrollToItemIdOnLoad = null;
62
+ this._scrollToItemMustBeExpanded = false;
63
+ this._searchCount = 0;
64
+ this._preloadCount = 0;
65
+ this._updateItemDisplay = null;
66
+ }
67
+
68
+ LiveTree.prototype._markItemForUpdateDisplay = function (item) {
69
+ var tree = this;
70
+ // This is not very intelligent yet... basically if only one item needs to be updated, that's fine, otherwise the whole tree is updated.
71
+ if (tree._updateItemDisplay == null) {
72
+ tree._updateItemDisplay = item;
73
+ } else if (tree._updateItemDisplay != item) {
74
+ tree._updateItemDisplay = tree._root;
75
+ }
76
+ }
77
+
78
+ LiveTree.prototype._getClass = function (suffix) {
79
+ if (suffix != "") {
80
+ suffix = "_" + suffix;
81
+ }
82
+ result = 'live_tree' + suffix;
83
+ if (this.cssClass != null) {
84
+ result += ' ' + this.cssClass + suffix;
85
+ }
86
+ return result;
87
+ }
88
+
89
+ LiveTree.prototype._getCollapsedItemIconHtml = function () {
90
+ if (this.collapsedItemIconHtml != null) {
91
+ return this.collapsedItemIconHtml;
92
+ } else {
93
+ return '<img src="/images/live_tree_branch_collapsed_icon.gif" alt="&gt;" width="9" height="9" class="' + this._getClass("item_icon") + '" />';
94
+ }
95
+ }
96
+
97
+ LiveTree.prototype._getExpandedItemIconHtml = function () {
98
+ if (this.expandedItemIconHtml != null) {
99
+ return this.expandedItemIconHtml;
100
+ } else {
101
+ return '<img src="/images/live_tree_branch_expanded_icon.gif" alt="v" width="9" height="9" class="' + this._getClass("item_icon") + '" />';
102
+ }
103
+ }
104
+
105
+ LiveTree.prototype._getLeafIconHtml = function () {
106
+ if (this.leafIconHtml != null) {
107
+ return this.leafIconHtml;
108
+ } else {
109
+ return '<img src="/images/live_tree_leaf_icon.gif" alt=" " width="9" height="9" class="' + this._getClass("item_icon") + '" />';
110
+ }
111
+ }
112
+
113
+ LiveTree.prototype._getLoadingIconHtml = function () {
114
+ if (this.loadingIconHtml != null) {
115
+ return this.loadingIconHtml;
116
+ } else {
117
+ return '<img src="/images/live_tree_loading_spinner.gif" alt="[loading]" width="10" height="10" class="' + this._getClass("loading_icon") + '" />';
118
+ }
119
+ }
120
+
121
+ LiveTree.prototype._getLoadingTreeHtml = function () {
122
+ if (this.loadingTreeHtml != null) {
123
+ return this.loadingTreeHtml;
124
+ } else {
125
+ return '<span class="' + this._getClass("loading_tree") + '">' + this._getLoadingIconHtml() + 'Loading tree data&hellip;</span>';
126
+ }
127
+ }
128
+
129
+ LiveTree.prototype._getSearchingHtml = function () {
130
+ if (this.searchingHtml != null) {
131
+ return this.searchingHtml;
132
+ } else {
133
+ return '<div class="' + this._getClass("searching") + '">' + this._getLoadingIconHtml() + 'Searching for item&hellip;</div>';
134
+ }
135
+ }
136
+
137
+ LiveTree.prototype._addItem = function (item, parent) {
138
+ // If this item ID was already loaded, copy its status from the old data
139
+ var oldItem = this._itemsIndex[item.id];
140
+ if (oldItem != null) {
141
+ item.isLoading = oldItem.isLoading;
142
+ item.isLoadingBackground = oldItem.isLoadingBackground;
143
+ item.isExpanded = oldItem.isExpanded;
144
+ }
145
+ this._itemsIndex[item.id] = item;
146
+
147
+ // Add some extra properties
148
+ item.isLeaf = !(item.children == null || item.children.length > 0);
149
+ item.isLoaded = item.children != null;
150
+ item.parent = parent;
151
+
152
+ // Replace or add this item in the parent's list of children
153
+ if (parent.children == null) {
154
+ parent.children = [item];
155
+ } else {
156
+ var found = false;
157
+ for (var i = 0; i < parent.children.length; i++) {
158
+ if (parent.children[i].id == item.id) {
159
+ parent.children[i] = item;
160
+ found = true;
161
+ break;
162
+ }
163
+ }
164
+ if (!found) {
165
+ parent.children[parent.children.length] = item;
166
+ }
167
+ }
168
+
169
+ // Now add the item's children as well
170
+ if (item.children != null) {
171
+ for (var i = 0; i < item.children.length; i++) {
172
+ this._addItem(item.children[i], item);
173
+ }
174
+ }
175
+ }
176
+
177
+ LiveTree.prototype._startPreloads = function (item) {
178
+ var tree = this;
179
+ if (!tree.preloadItems || tree._preloadCount > 0) {
180
+ return false;
181
+ }
182
+ if (item == null) {
183
+ item = tree._root;
184
+ }
185
+ //alert("startPreloads " + item.id);
186
+ if (!item.isExpanded || item.isLoading) {
187
+ return false;
188
+ }
189
+ var tailBranch = true;
190
+ for (var i = 0; i < item.children.length; i++) {
191
+ var child = item.children[i];
192
+ if (!child.isLeaf && ( child.isLoaded || child.isLoading )) {
193
+ tailBranch = false;
194
+ }
195
+ }
196
+ var doLoad = false;
197
+ if (tailBranch) {
198
+ for (var i = 0; i < item.children.length; i++) {
199
+ var child = item.children[i];
200
+ if (!child.isLeaf) {
201
+ if (!child.isLoaded && !child.isLoading) {
202
+ //alert("setting loading for " + child.id);
203
+ doLoad = true;
204
+ child.isLoading = true;
205
+ child.isLoadingBackground = true;
206
+ }
207
+ }
208
+ }
209
+ }
210
+ var didLoad = false;
211
+ if (doLoad) {
212
+ //alert("preloading children of " + item.id);
213
+ tree._preloadCount++;
214
+ tree._requestItem(item.id, 3, tree._onPreloadItemReceived.bind(tree));
215
+ tree._markItemForUpdateDisplay(item);
216
+ didLoad = true;
217
+ } else {
218
+ for (var i = 0; i < item.children.length; i++) {
219
+ var child = item.children[i];
220
+ if (!child.isLeaf && child.isLoaded) {
221
+ if (tree._startPreloads(child)) {
222
+ didLoad = true;
223
+ }
224
+ }
225
+ }
226
+ }
227
+
228
+ return didLoad;
229
+ }
230
+
231
+ LiveTree.prototype._handleReceivedItem = function (item, requestOptions) {
232
+ var tree = this;
233
+
234
+ // Find item's parent
235
+ var parent = null;
236
+ if (requestOptions.includeParents) {
237
+ // The response includes the desired item's parents, but we don't want to over-write
238
+ // data that is already there (since it may include other children deeper down), so
239
+ // go down the tree until we find an item that hasn't been loaded before (or we get to the
240
+ // requested item)
241
+ var newParent = tree._getItem(item.id).parent;
242
+ while (true) {
243
+ // since we included parents, there should only be a single child with children, so find that one
244
+ var child = null;
245
+ for (var i = 0; i < item.children.length; i++) {
246
+ if (item.children[i].children != null && item.children[i].children.length > 0) {
247
+ if (child != null) {
248
+ alert("LiveTree error: didn't expect multiple children with children while iterating through parents");
249
+ return;
250
+ }
251
+ child = item.children[i];
252
+ }
253
+ }
254
+ if (child == null || tree._getItem(child.id) == null) {
255
+ break;
256
+ }
257
+ newParent = item;
258
+ item = child;
259
+ }
260
+ parent = tree._getItem(newParent.id);
261
+ } else {
262
+ // First, check if root is the parent
263
+ if (tree._root.children == null) {
264
+ // ... which is always the case if the root has no children, since that means nothing has been loaded yet
265
+ parent = tree._root;
266
+ } else {
267
+ for (var i = 0; i < tree._root.children.length; i++) {
268
+ if (item.id == tree._root.children[i].id) {
269
+ parent = tree._root;
270
+ break;
271
+ }
272
+ }
273
+ }
274
+ // Otherwise, it must have been loaded before, so get the old parent
275
+ if (parent == null) {
276
+ var oldItem = tree._itemsIndex[item.id];
277
+ if (oldItem == null) {
278
+ alert("LiveTree error: attempt to load item of unknown parentage");
279
+ return false;
280
+ }
281
+ parent = oldItem.parent;
282
+ }
283
+ }
284
+
285
+ // Now add the item to its parent
286
+ tree._addItem(item, parent);
287
+ //alert(ekb_inspect(tree._root));
288
+ tree._markItemForUpdateDisplay(parent);
289
+
290
+ if (tree.onLoadItem != null) {
291
+ tree.onLoadItem(item);
292
+ }
293
+ return true;
294
+ }
295
+
296
+ LiveTree.prototype._onItemResponse = function (request, onItemCallback, requestOptions) {
297
+ var tree = this;
298
+ if (requestOptions.includeParents) {
299
+ tree._searchCount--;
300
+ }
301
+ var item;
302
+ try {
303
+ eval("item = " + request.responseText);
304
+ } catch (e) {
305
+ alert("LiveTree error: bad items data from server: " + e);
306
+ return;
307
+ }
308
+ var handled = tree._handleReceivedItem(item, requestOptions);
309
+ if (handled) {
310
+ onItemCallback(item, requestOptions);
311
+ }
312
+ }
313
+
314
+ LiveTree.prototype._requestItem = function (itemId, depth, onItemCallback, options) {
315
+ var tree = this;
316
+ if (options == null) {
317
+ options = {};
318
+ }
319
+ var url = tree.dataUrl;
320
+ if (url == null) {
321
+ alert("LiveTree error: no data URL provided");
322
+ return false;
323
+ }
324
+ var requestOptions = new Object();
325
+ var delim = "?";
326
+ if (itemId != null) {
327
+ requestOptions.itemId = itemId;
328
+ url += delim + "item_id=" + itemId;
329
+ delim = "&";
330
+ }
331
+ if (depth != null) {
332
+ requestOptions.depth = depth;
333
+ url += delim + "depth=" + depth;
334
+ delim = "&";
335
+ }
336
+ if (options.includeParents) {
337
+ requestOptions.includeParents = true;
338
+ requestOptions.rootItemId = tree.rootItemId;
339
+ url += delim + "include_parents=1&root_item_id=" + tree.rootItemId;
340
+ tree._searchCount++;
341
+ }
342
+ new Ajax.Request(url, {onComplete:function (request) { tree._onItemResponse(request, onItemCallback, requestOptions) }, evalScripts:true, asynchronous:true});
343
+ return true;
344
+ }
345
+
346
+ LiveTree.prototype._onExpandItemReceived = function (item, requestOptions) {
347
+ var tree = this;
348
+ item.isLoading = false;
349
+ tree._startPreloads();
350
+ tree._updateDisplay();
351
+ }
352
+
353
+ LiveTree.prototype._onPreloadItemReceived = function (item, requestOptions) {
354
+ var tree = this;
355
+ tree._preloadCount--;
356
+ for (var i = 0; i < item.children.length; i++) {
357
+ item.children[i].isLoading = false;
358
+ }
359
+ tree._markItemForUpdateDisplay(item);
360
+ tree._startPreloads();
361
+ tree._updateDisplay();
362
+ }
363
+
364
+ LiveTree.prototype._onClickExpand = function (item) {
365
+ var tree = this;
366
+ var expanded = tree._expandItem(item);
367
+ tree._updateDisplay();
368
+ if (expanded) {
369
+ tree.scrollToItem(item.id);
370
+ if (item.isLoading) {
371
+ tree._scrollToItemIdOnLoad = item.id;
372
+ tree._scrollToItemMustBeExpanded = true;
373
+ }
374
+ if (tree.onExpandItem != null) {
375
+ tree.onExpandItem(item);
376
+ }
377
+ }
378
+ }
379
+
380
+ LiveTree.prototype._onClickCollapse = function (item) {
381
+ var tree = this;
382
+ if (!item.isExpanded) {
383
+ return;
384
+ }
385
+ item.isExpanded = false;
386
+ tree._markItemForUpdateDisplay(item);
387
+ tree._updateDisplay();
388
+ if (tree.onCollapseItem != null) {
389
+ tree.onCollapseItem(item);
390
+ }
391
+ }
392
+
393
+ LiveTree.prototype._onClickItem = function (item) {
394
+ var tree = this;
395
+ if (tree.expandItemOnClick && !item.isExpanded && !item.isLeaf) {
396
+ tree._onClickExpand(item);
397
+ }
398
+ if (tree.onClickItem != null && ((tree.allowClickLeaf && item.isLeaf) || (tree.allowClickBranch && !item.isLeaf))) {
399
+ tree.onClickItem(item);
400
+ }
401
+ tree._updateDisplay();
402
+ }
403
+
404
+ LiveTree.prototype._getItem = function (itemId) {
405
+ return this._itemsIndex[itemId];
406
+ }
407
+
408
+ LiveTree.prototype._getItemElement = function (itemId) {
409
+ return $(this.id + "_item_" + itemId);
410
+ }
411
+
412
+ LiveTree.prototype._displayItem = function (item, isRoot) {
413
+ var tree = this;
414
+ var elem;
415
+ if (isRoot) {
416
+ elem = $(tree.id + "_root");
417
+ } else {
418
+ elem = tree._getItemElement(item.id);
419
+ }
420
+ var html = '';
421
+ if (!isRoot) {
422
+ if (!item.isLeaf) {
423
+ if (item.isExpanded) {
424
+ html += '<a href="#" id="' + tree.id + '_branch_collapse_link_' + item.id + '" class="' + this._getClass("branch_collapse_link") + '">'; {
425
+ html += tree._getExpandedItemIconHtml();
426
+ } html += '</a>';
427
+ } else {
428
+ html += '<a href="#" id="' + tree.id + '_branch_expand_link_' + item.id + '" class="' + this._getClass("branch_expand_link") + '">'; {
429
+ html += tree._getCollapsedItemIconHtml();
430
+ } html += '</a>';
431
+ }
432
+ if (item.isLoading && !item.isLoadingBackground) {
433
+ html += tree._getLoadingIconHtml();
434
+ }
435
+ } else {
436
+ html += tree._getLeafIconHtml();
437
+ }
438
+ var item_link_exists = false;
439
+ var extraNameClass = "";
440
+ if (item.id == tree._activeItemId) {
441
+ extraNameClass = " " + this._getClass("active_item_name");
442
+ }
443
+ var name_html = '<span id="' + tree.id + '_item_name_' + item.id + '" class="' + this._getClass("item_name") + extraNameClass + '">' + item.name + '</span>';
444
+ if ((tree.onClickItem != null && ((tree.allowClickLeaf && item.isLeaf) || (tree.allowClickBranch && !item.isLeaf))) ||
445
+ (tree.expandItemOnClick && !item.isLeaf && !item.isExpanded)) {
446
+ name_html = '<a href="#" id="' + tree.id + '_item_link_' + item.id + '" class="' + this._getClass("item_link") + '">' + name_html + '</a>';
447
+ item_link_exists = true;
448
+ }
449
+ //name_html = "(" + item.id + ") " + name_html;
450
+ html += name_html;
451
+ //if (item.isLoading && item.isLoadingBackground) {
452
+ // html += " " + tree._getLoadingIconHtml();
453
+ //}
454
+ }
455
+ if (item.isExpanded && item.children != null) {
456
+ var childrenListId;
457
+ if (isRoot) {
458
+ childrenListId = tree.id + '_children_list_root';
459
+ } else {
460
+ childrenListId = tree.id + '_children_list_' + item.id;
461
+ }
462
+ if (!isRoot) {
463
+ html += '<ul id="' + childrenListId + '" class="' + this._getClass("branch") + '">';
464
+ }
465
+ for (var i = 0; i < item.children.length; i++) {
466
+ var child = item.children[i];
467
+ html += '<li id="' + tree.id + '_item_' + child.id + '" class="' + this._getClass("item") + '"></li>';
468
+ }
469
+ if (!isRoot) {
470
+ html += '</ul>';
471
+ }
472
+ }
473
+ elem.innerHTML = html;
474
+ if (!isRoot) {
475
+ if (!item.isLeaf) {
476
+ if (item.isExpanded) {
477
+ $(tree.id + '_branch_collapse_link_' + item.id).onclick = function () { tree._onClickCollapse(item); return false }
478
+ } else {
479
+ $(tree.id + '_branch_expand_link_' + item.id).onclick = function () { tree._onClickExpand(item); return false }
480
+ }
481
+ }
482
+ if (item_link_exists) {
483
+ $(tree.id + '_item_link_' + item.id).onclick = function() { tree._onClickItem(item); return false }
484
+ }
485
+ }
486
+ if (item.isExpanded && item.children != null) {
487
+ for (var i = 0; i < item.children.length; i++) {
488
+ tree._displayItem(item.children[i], false);
489
+ }
490
+ }
491
+ }
492
+
493
+ LiveTree.prototype._checkScrollOnLoad = function () {
494
+ var tree = this;
495
+ if (tree._scrollToItemIdOnLoad == null) {
496
+ return;
497
+ }
498
+ var item = tree._itemsIndex[tree._scrollToItemIdOnLoad];
499
+ if (item == null) {
500
+ return;
501
+ }
502
+ if (tree._scrollToItemMustBeExpanded) {
503
+ if (item.isLoaded) {
504
+ // The user may have collapsed the item while it was loading, so only scroll to it if it's still expanded.
505
+ if (item.isExpanded) {
506
+ tree.scrollToItem(item.id);
507
+ }
508
+ tree._scrollToItemIdOnLoad = null;
509
+ }
510
+ } else {
511
+ tree.scrollToItem(item.id);
512
+ tree._scrollToItemIdOnLoad = null;
513
+ }
514
+ }
515
+
516
+ LiveTree.prototype._updateDisplay = function () {
517
+ var tree = this;
518
+ if (tree._searchCount > 0) {
519
+ Element.show(tree.id + "_searching");
520
+ } else {
521
+ Element.hide(tree.id + "_searching");
522
+ }
523
+ var updateItem = tree._updateItemDisplay;
524
+ if (updateItem != null) {
525
+ tree._updateItemDisplay = null;
526
+ var html = "";
527
+ var isRoot = false;
528
+ if (updateItem == tree._root || (tree.hideRootItem && updateItem == tree._root.children[0])) {
529
+ if (tree.hideRootItem) {
530
+ updateItem = tree._root.children[0];
531
+ }
532
+ isRoot = true;
533
+ }
534
+ tree._displayItem(updateItem, isRoot);
535
+ }
536
+ tree._checkScrollOnLoad();
537
+ }
538
+
539
+ LiveTree.prototype._onInitialItemReceived = function () {
540
+ var tree = this;
541
+ this.rootItemId = tree._root.children[0].id;
542
+ if (tree.hideRootItem) {
543
+ //tree._root = tree._root.children[0];
544
+ tree._expandItem(tree._root.children[0]);
545
+ } else if (tree.expandRootItem) {
546
+ tree._expandItem(tree._root.children[0]);
547
+ }
548
+ tree._root.isExpanded = true;
549
+ tree._markItemForUpdateDisplay(tree._root);
550
+ tree._startPreloads();
551
+ }
552
+
553
+ LiveTree.prototype._getElementPosition = function (destinationLink) {
554
+ // borrowed from http://www.sitepoint.com/print/scroll-smoothly-javascript
555
+ var destx = destinationLink.offsetLeft;
556
+ var desty = destinationLink.offsetTop;
557
+ var thisNode = destinationLink;
558
+ while (thisNode.offsetParent &&
559
+ (thisNode.offsetParent != document.body)) {
560
+ thisNode = thisNode.offsetParent;
561
+ destx += thisNode.offsetLeft;
562
+ desty += thisNode.offsetTop;
563
+ }
564
+ return { x: destx, y: desty }
565
+ }
566
+
567
+ LiveTree.prototype._scrollTo = function (top) {
568
+ var tree = this;
569
+ if (!tree.scroll) {
570
+ return;
571
+ }
572
+ var containerElem = $(tree.id);
573
+ containerElem.scrollTop = top;
574
+ }
575
+
576
+ LiveTree.prototype.scrollToItem = function (itemId) {
577
+ var tree = this;
578
+ if (!tree.scroll) {
579
+ return;
580
+ }
581
+ var itemElem = tree._getItemElement(itemId);
582
+ if (itemElem == null) {
583
+ return;
584
+ }
585
+ var containerElem = $(tree.id);
586
+ var itemPos = tree._getElementPosition(itemElem);
587
+ var containerPos = tree._getElementPosition(containerElem);
588
+ var itemTop = itemPos.y - containerPos.y;
589
+ var containerHeight = containerElem.offsetHeight - 35; //HACK: adjust for space used by scrollbars and other decoration
590
+ if (itemTop + itemElem.offsetHeight > containerElem.scrollTop + containerHeight ||
591
+ itemTop < containerElem.scrollTop) {
592
+ // item is currently not entirely visible
593
+ if (itemElem.offsetHeight > containerHeight) {
594
+ // item is too big to fit, so scroll to the top
595
+ tree._scrollTo(itemTop);
596
+ } else {
597
+ if (itemTop < containerElem.scrollTop + containerHeight) {
598
+ // item is partially onscreen (the top is showing), so put whole item at bottom
599
+ tree._scrollTo(itemTop + itemElem.offsetHeight - containerHeight);
600
+ } else {
601
+ // item is entirely offscreen, so center it
602
+ tree._scrollTo(itemTop - containerHeight/2 + itemElem.offsetHeight/2);
603
+ }
604
+ }
605
+ }
606
+ tree._scrollToItemOnLoad = null;
607
+ }
608
+
609
+ LiveTree.prototype._expandItem = function (item) {
610
+ var tree = this;
611
+
612
+ // Make sure all item's parents are expanded as well
613
+ var didExpand = false;
614
+ var parent = item.parent;
615
+ while (parent != tree._root && parent != null) {
616
+ if (!parent.isExpanded) {
617
+ parent.isExpanded = true;
618
+ tree._markItemForUpdateDisplay(parent);
619
+ didExpand = true;
620
+ }
621
+ parent = parent.parent;
622
+ }
623
+
624
+ // Expand the selected item
625
+ var needToLoad = false;
626
+ if (!item.isExpanded) {
627
+ needToLoad = (item.children == null && !item.isLoading);
628
+ if (needToLoad) {
629
+ item.isLoading = true;
630
+ }
631
+ item.isLoadingBackground = false;
632
+ item.isExpanded = true;
633
+ tree._markItemForUpdateDisplay(item);
634
+ didExpand = true;
635
+ }
636
+
637
+ // If the item has not loaded, load it now
638
+ if (needToLoad) {
639
+ tree._requestItem(item.id, 2, tree._onExpandItemReceived.bind(tree));
640
+ }
641
+
642
+ tree._startPreloads();
643
+ return didExpand;
644
+ }
645
+
646
+ LiveTree.prototype._onExpandItemParentsReceived = function (item, requestOptions) {
647
+ var tree = this;
648
+ var requestedItem = tree._getItem(requestOptions.itemId);
649
+ this._expandItem(requestedItem);
650
+ tree._startPreloads();
651
+ tree._updateDisplay();
652
+ }
653
+
654
+ LiveTree.prototype.expandItem = function (itemId) {
655
+ var tree = this;
656
+ var item = tree._getItem(itemId);
657
+ var search = false;
658
+ if (item == null) {
659
+ tree._requestItem(itemId, 2, tree._onExpandItemParentsReceived.bind(tree), { includeParents: true });
660
+ search = true;
661
+ } else {
662
+ this._expandItem(this._itemsIndex[itemId]);
663
+ }
664
+ tree._updateDisplay();
665
+ if (search) {
666
+ tree._scrollTo(0);
667
+ tree._scrollToItemIdOnLoad = itemId;
668
+ tree._scrollToItemMustBeExpanded = false;
669
+ } else {
670
+ tree.scrollToItem(itemId);
671
+ }
672
+ }
673
+
674
+ LiveTree.prototype._onExpandParentsOfItemReceived = function (item, requestOptions) {
675
+ var tree = this;
676
+ var requestedItem = tree._getItem(requestOptions.itemId);
677
+ tree._expandItem(requestedItem.parent);
678
+ tree._startPreloads();
679
+ tree._updateDisplay();
680
+ }
681
+
682
+ LiveTree.prototype.expandParentsOfItem = function (itemId) {
683
+ var tree = this;
684
+ var item = tree._getItem(itemId);
685
+ var search = false;
686
+ if (item == null) {
687
+ tree._requestItem(itemId, 1, tree._onExpandParentsOfItemReceived.bind(tree), { includeParents: true });
688
+ search = true;
689
+ } else {
690
+ tree._expandItem(item.parent);
691
+ }
692
+ tree._updateDisplay();
693
+ if (search) {
694
+ tree._scrollTo(0);
695
+ tree._scrollToItemIdOnLoad = itemId;
696
+ tree._scrollToItemMustBeExpanded = false;
697
+ } else {
698
+ tree.scrollToItem(itemId);
699
+ }
700
+ }
701
+
702
+ LiveTree.prototype.activateItem = function (itemId) {
703
+ var tree = this;
704
+ // un-highlight the old active item
705
+ var oldElem = $(tree.id + '_item_name_' + tree._activeItemId);
706
+ if (oldElem != null) {
707
+ oldElem.className = tree._getClass("item_name");
708
+ }
709
+ // highlight the new active item
710
+ var elem = $(tree.id + '_item_name_' + itemId);
711
+ if (elem != null) {
712
+ elem.className = tree._getClass("item_name") + " " + tree._getClass("active_item_name");
713
+ }
714
+ tree._activeItemId = itemId;
715
+ tree.scrollToItem(itemId);
716
+ }
717
+
718
+ LiveTree.prototype.getHtml = function() {
719
+ var tree = this;
720
+ var html = '';
721
+ html += '<div id="' + tree.id + '" class="' + tree._getClass("") + '"';
722
+ if (tree.cssStyle != null) {
723
+ html += ' style="' + tree.cssStyle + '"';
724
+ }
725
+ html += '>';
726
+ html += '<div id="' + tree.id + '_searching" style="display:none">' + tree._getSearchingHtml() + '</div>';
727
+ html += '<ul id="' + tree.id + '_root" class="' + tree._getClass("root") + '">' + tree._getLoadingTreeHtml() + '</ul>'
728
+ html += '</div>';
729
+ return html;
730
+ }
731
+
732
+ LiveTree.prototype.start = function() {
733
+ var tree = this;
734
+ if (tree.initialData != null) {
735
+ var handled = tree._handleReceivedItem(tree.initialData, {});
736
+ if (handled) {
737
+ tree._onInitialItemReceived(tree.initialData);
738
+ }
739
+ tree._updateDisplay();
740
+ } else {
741
+ tree._requestItem(tree.rootItemId, tree.expandRootItem || tree.hideRootItem ? 2 : 1, tree._onInitialItemReceived.bind(tree));
742
+ }
743
+ }
744
+
745
+ LiveTree.prototype.render = function () {
746
+ var tree = this;
747
+ document.write(tree.getHtml());
748
+ tree.start();
749
+ }