parlement 0.1

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