django-fast-treenode 3.0.6__py3-none-any.whl → 3.0.8__py3-none-any.whl

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 (37) hide show
  1. {django_fast_treenode-3.0.6.dist-info → django_fast_treenode-3.0.8.dist-info}/METADATA +1 -1
  2. {django_fast_treenode-3.0.6.dist-info → django_fast_treenode-3.0.8.dist-info}/RECORD +37 -37
  3. {django_fast_treenode-3.0.6.dist-info → django_fast_treenode-3.0.8.dist-info}/WHEEL +1 -1
  4. treenode/__init__.py +1 -0
  5. treenode/admin/admin.py +105 -109
  6. treenode/admin/mixin.py +1 -1
  7. treenode/managers/queries.py +18 -6
  8. treenode/managers/tasks.py +1 -1
  9. treenode/models/models.py +2 -2
  10. treenode/static/css/treenode_admin.css +21 -0
  11. treenode/static/js/treenode_admin.js +130 -339
  12. treenode/static/vendors/jquery-ui/AUTHORS.txt +384 -384
  13. treenode/static/vendors/jquery-ui/LICENSE.txt +43 -43
  14. treenode/static/vendors/jquery-ui/external/jquery/jquery.js +10716 -10716
  15. treenode/static/vendors/jquery-ui/index.html +297 -297
  16. treenode/static/vendors/jquery-ui/jquery-ui.css +438 -438
  17. treenode/static/vendors/jquery-ui/jquery-ui.js +5222 -5222
  18. treenode/static/vendors/jquery-ui/jquery-ui.min.css +6 -6
  19. treenode/static/vendors/jquery-ui/jquery-ui.min.js +5 -5
  20. treenode/static/vendors/jquery-ui/jquery-ui.structure.css +16 -16
  21. treenode/static/vendors/jquery-ui/jquery-ui.structure.min.css +4 -4
  22. treenode/static/vendors/jquery-ui/jquery-ui.theme.css +439 -439
  23. treenode/static/vendors/jquery-ui/jquery-ui.theme.min.css +4 -4
  24. treenode/static/vendors/jquery-ui/package.json +82 -82
  25. treenode/templates/treenode/admin/treenode_changelist.html +61 -15
  26. treenode/templates/treenode/admin/treenode_rows.html +37 -40
  27. treenode/templatetags/treenode_admin.py +57 -14
  28. treenode/utils/db/sqlcompat.py +1 -33
  29. treenode/utils/db/sqlquery.py +0 -24
  30. treenode/version.py +2 -2
  31. treenode/views/autoapi.py +91 -91
  32. treenode/views/autocomplete.py +52 -52
  33. treenode/views/children.py +41 -41
  34. treenode/views/common.py +23 -23
  35. treenode/widgets.py +0 -2
  36. {django_fast_treenode-3.0.6.dist-info → django_fast_treenode-3.0.8.dist-info}/licenses/LICENSE +0 -0
  37. {django_fast_treenode-3.0.6.dist-info → django_fast_treenode-3.0.8.dist-info}/top_level.txt +0 -0
@@ -1,40 +1,23 @@
1
1
  /**
2
2
  * treenode_admin.js
3
3
  *
4
- * Advanced TreeNode Admin extension for Django Admin.
5
- * Adds dynamic drag-and-drop sorting, AJAX-based subtree loading,
6
- * real-time visual feedback, and persistent tree state.
4
+ * Cleaned version 3.1.0 — TreeNode Admin extension for Django Admin.
5
+ * - No AJAX loading of children
6
+ * - No persistence in localStorage
7
+ * - Local-only expand/collapse logic
8
+ * - Compatible with pre-rendered full tree
7
9
  *
8
- * Features:
9
- * - Drag-and-drop node movement with Shift for child placement
10
- * - Visual animations for feedback (insert flash, drag highlight)
11
- * - Inline AJAX expansion and collapse of subtrees
12
- * - Server-side re-rendering and recovery after node movement
13
- * - Lightweight localStorage persistence using compressed HTML
14
- *
15
- * Version: 3.0.0
10
+ * Version: 3.1.0
16
11
  * Author: Timur Kady
17
12
  * Email: timurkady@yandex.com
18
13
  */
19
14
 
20
-
21
15
  (function($) {
22
16
 
23
17
  // ------------------------------- //
24
- // Service and auxiliary functions //
18
+ // Helpers //
25
19
  // ------------------------------- //
26
20
 
27
- function debounce(func, wait) {
28
- var timeout;
29
- return function() {
30
- var context = this, args = arguments;
31
- clearTimeout(timeout);
32
- timeout = setTimeout(function() {
33
- func.apply(context, args);
34
- }, wait);
35
- };
36
- }
37
-
38
21
  function getCookie(name) {
39
22
  let cookieValue = null;
40
23
  if (document.cookie && document.cookie !== '') {
@@ -49,120 +32,9 @@
49
32
  }
50
33
  return cookieValue;
51
34
  }
52
-
53
- function showAdminMessage(text, level = "info", duration = 6000) {
54
- const $ = django.jQuery || window.jQuery;
55
-
56
- // Make sure the block exists
57
- let msgList = $(".messagelist");
58
- if (!msgList.length) {
59
- msgList = $('<ul class="messagelist"></ul>');
60
- $("#content").before(msgList);
61
- }
62
-
63
- // Create a message
64
- const msg = $(`<li class="${level}">${text}</li>`);
65
-
66
- msgList.append(msg);
67
-
68
- // Auto disappear after 6 seconds (default)
69
- setTimeout(() => {
70
- msg.fadeOut(500, () => msg.remove());
71
- }, duration);
72
- }
73
-
74
- function hangleAjaxSuccess(data) {
75
- const msg = data.message || "The request was successfully completed.";
76
- showAdminMessage(msg, "success");
77
- ChangeList.saveTree()
78
- ChangeList.restoreTree(ChangeList.expandedNodes);
79
- }
80
-
81
- function handleAjaxError(xhr, status, error) {
82
- ChangeList.restoreTree(ChangeList.expandedNodes);
83
-
84
- const fallbackMessage = "An unknown error occurred while executing the request.";
85
- const $ = django.jQuery || window.jQuery;
86
- let message = "";
87
-
88
- // Try to extract the JSON error
89
- try {
90
- const contentType = xhr.getResponseHeader("Content-Type") || "";
91
- if (contentType.includes("application/json")) {
92
- const data = xhr.responseJSON || JSON.parse(xhr.responseText);
93
- if (data?.error) {
94
- message = data.error;
95
- } else if (typeof data?.detail === "string") {
96
- message = data.detail;
97
- } else if (typeof data === "string") {
98
- message = data;
99
- }
100
- }
101
- } catch (e) {
102
- // Not JSON – silently continue
103
- }
104
-
105
- // Try to parse plain HTML Django error and extract exception summary
106
- if (!message && xhr.responseText) {
107
- try {
108
- // Try to extract main exception message from Django debug HTML
109
- const match = xhr.responseText.match(/<pre class="exception_value">([^<]+)<\/pre>/);
110
- if (match && match[1]) {
111
- message = match[1].trim();
112
- } else {
113
- // As fallback, extract first lines of cleaned HTML
114
- const plain = xhr.responseText.replace(/<\/?[^>]+(>|$)/g, "").trim();
115
- const lines = plain.split("\n").map(line => line.trim()).filter(Boolean);
116
- if (lines.length) {
117
- message = lines.slice(0, 3).join(" — "); // keep it brief
118
- }
119
- }
120
- } catch (e) {
121
- // Parsing failed, do nothing
122
- }
123
- }
124
-
125
- // If there is still nothing, build a generic fallback
126
- if (!message) {
127
- if (xhr.status) {
128
- message = `${xhr.status}: ${error || status}`;
129
- } else {
130
- message = fallbackMessage;
131
- }
132
- }
133
-
134
- showAdminMessage(message, "error");
135
- }
136
-
137
- function isDarkTheme() {
138
- return document.documentElement.getAttribute("data-theme") === "dark";
139
- }
140
-
141
- function applyTheme() {
142
- var dark = isDarkTheme();
143
- var $container = $(".tree-widget");
144
- var $dropdown = $(".tree-widget-dropdown");
145
-
146
- if (dark) {
147
- $dropdown.addClass("dark-theme");
148
- $container.addClass("dark-theme");
149
- } else {
150
- $dropdown.removeClass("dark-theme");
151
- $container.removeClass("dark-theme");
152
- }
153
- }
154
-
155
- let ajaxCounter = 0;
156
-
157
- function clearCursor() {
158
- ajaxCounter--;
159
- if (ajaxCounter === 0) {
160
- $('body').css('cursor', 'default');
161
- }
162
- }
163
35
 
164
36
  // ------------------------------- //
165
- // AJAX Setup //
37
+ // AJAX Setup //
166
38
  // ------------------------------- //
167
39
 
168
40
  const csrftoken = getCookie('csrftoken');
@@ -172,18 +44,19 @@
172
44
  if (!/^https?:.*/.test(settings.url)) {
173
45
  xhr.setRequestHeader("X-CSRFToken", csrftoken);
174
46
  }
175
- ajaxCounter++;
176
47
  $('body').css('cursor', 'wait');
177
48
  },
49
+ complete: function() {
50
+ $('body').css('cursor', 'default');
51
+ },
178
52
  cache: false
179
53
  });
180
54
 
181
55
  // ------------------------------- //
182
- // Animations and visual feedback //
56
+ // Visual feedback //
183
57
  // ------------------------------- //
184
58
 
185
59
  const TreeFx = {
186
- // Highlight the line where the element was moved
187
60
  flashInsert(nodeId) {
188
61
  const $row = $(`tr[data-node-id="${nodeId}"]`);
189
62
  if (!$row.length) return;
@@ -192,235 +65,167 @@
192
65
  setTimeout(() => $row.removeClass("flash-insert"), 1000);
193
66
  },
194
67
 
195
- // Fading in a new tbody (e.g. after reloadTree)
196
- fadeInTbody(newHTML, callback) {
197
- const $tbody = $('table#result_list tbody');
198
- $tbody.stop(true, true).fadeOut(100, () => {
199
- $tbody.html(newHTML).fadeIn(150, callback);
200
- });
201
- },
202
-
203
- // Visual cue when drag starts and ends
204
68
  markDragging($item, enable) {
205
69
  $item.toggleClass('dragging', enable);
206
- },
70
+ }
207
71
  };
208
72
 
209
-
210
73
  // ------------------------------- //
211
- // Main Class //
74
+ // Tree logic //
212
75
  // ------------------------------- //
213
76
 
214
-
215
77
  var ChangeList = {
216
78
  $tableBody: null,
217
79
  isShiftPressed: false,
218
80
  activeTargetRow: null,
219
81
  isMoving: false,
220
- expandedNodes: [],
221
- label: '',
222
82
 
223
83
  init: function() {
224
84
  this.$tableBody = $('table#result_list tbody');
225
85
  this.bindEvents();
226
- this.restoreTree();
227
86
  this.enableDragAndDrop();
228
87
  },
229
-
88
+
89
+ // Save expanded nodes to localStorage
230
90
  saveTree: function() {
231
91
  if (!this.$tableBody) return;
232
-
233
- this.expandedNodes = [];
234
- this.$tableBody.find(".treenode-toggle").each(function () {
235
- $btn = $(this)
236
- if ($btn.data('expanded')) {
237
- ChangeList.expandedNodes.push($btn.data('node-id'));
238
- }
239
- });
240
- if (!(this.expandedNodes ) || (this.expandedNodes.length === 0)) {
241
- localStorage.removeItem("saved_tbody");
92
+
93
+ // Сохраняем ТОЛЬКО те node_id, которые раскрыты
94
+ this.expandedNodes = this.$tableBody.find(".treenode-toggle").map(function() {
95
+ const $btn = $(this);
96
+ return $btn.data("expanded") ? $btn.data("node-id") : null;
97
+ }).get().filter(Boolean);
98
+
99
+ if (this.expandedNodes.length === 0) {
100
+ localStorage.removeItem("treenode_expanded");
242
101
  } else {
243
- localStorage.setItem("saved_tbody", JSON.stringify(this.expandedNodes));
102
+ localStorage.setItem("treenode_expanded", JSON.stringify(this.expandedNodes));
244
103
  }
104
+
245
105
  const count = $("#result_list tbody tr").length;
246
106
  if (count > 0) {
247
107
  $("p.paginator").first().text(`${count} ${ChangeList.label}`);
248
108
  localStorage.setItem("label", ChangeList.label);
249
109
  }
250
-
251
110
  },
252
111
 
253
- restoreTree: function(expandedList = null) {
254
- const expanded = expandedList || JSON.parse(localStorage.getItem("saved_tbody") || "[]");
255
- ChangeList.label = localStorage.getItem("label") || "";
256
- if (!expanded.length) return;
257
112
 
258
- const params = { expanded: JSON.stringify(expanded) };
259
-
260
- $.ajax({
261
- url: 'change_list/',
262
- method: 'GET',
263
- data: params,
264
- dataType: 'json',
265
- success: function(data) {
266
- ChangeList.$tableBody.html(data.html);
267
- ChangeList.expandedNodes = expanded;
268
-
269
- ChangeList.$tableBody.find(".treenode-toggle").each(function () {
270
- const $btn = $(this);
271
- const nodeId = $btn.data('node-id');
272
- if (ChangeList.expandedNodes.includes(nodeId)) {
273
- $btn.data("expanded", true);
274
- $btn.text("▼");
275
- }
276
- });
277
-
278
- if (data.label) ChangeList.label = data.label;
279
- const count = $("#result_list tbody tr").length;
280
- $("p.paginator").first().text(`${count} ${ChangeList.label}`);
281
- },
282
- error: function(xhr, status, error) {
283
- handleAjaxError(xhr, status, error);
284
- // console.error("Restore error:", status, error);
285
- },
286
- complete: function() {
287
- clearCursor();
288
- }
289
- });
113
+ // Restore expanded nodes from localStorage
114
+ restoreTreeState: function() {
115
+ const expanded = JSON.parse(localStorage.getItem("treenode_expanded") || "[]");
116
+ for (const nodeId of expanded) {
117
+ ChangeList.expandNode(nodeId);
118
+ }
290
119
  },
291
-
292
- searchRows: function(searchQuery) {
293
- var params = { q: searchQuery };
294
120
 
295
- $.ajax({
296
- url: 'change_list/',
297
- method: 'GET',
298
- data: params,
299
- dataType: 'json',
300
- success: function(data) {
301
- ChangeList.$tableBody.html(data.html);
302
- },
303
- error: function(xhr, status, error) {
304
- handleAjaxError(xhr, status, error);
305
- // console.error("Search error:", status, error);
306
- },
307
- complete: function() {
308
- clearCursor();
309
- }
310
- });
121
+ expandNode: function(nodeId) {
122
+ const $row = this.$tableBody.find(`tr[data-node-id="${nodeId}"]`);
123
+ const $btn = $row.find(".treenode-toggle");
124
+ $btn.text("▼").data("expanded", true);
125
+ this.showChildren(nodeId);
126
+ this.saveTree();
311
127
  },
312
128
 
313
- insertRows: function($parentRow, parentId) {
314
- var parent_id = parentId
315
- var params = {parent_id: parent_id};
129
+ collapseNode: function(nodeId) {
130
+ const $row = this.$tableBody.find(`tr[data-node-id="${nodeId}"]`);
131
+ const $btn = $row.find(".treenode-toggle");
132
+ $btn.text("►").data("expanded", false); // <-- ВАЖНО!
133
+ this.hideChildrenRecursive(nodeId);
134
+ this.saveTree();
135
+ },
316
136
 
317
- $.ajax({
318
- url: 'change_list/',
319
- method: 'GET',
320
- data: params,
321
- dataType: 'json',
322
- success: function(data) {
323
- $parentRow.after(data.html);
324
- if (data.label) ChangeList.label = data.label;
325
- },
326
- error: function(xhr, status, error) {
327
- handleAjaxError(xhr, status, error);
328
- // console.error("Insert rows error:", status, error);
329
- },
330
- complete: function() {
331
- ChangeList.saveTree();
332
- clearCursor();
137
+ toggleNode: function($btn) {
138
+ const nodeId = $btn.data("node-id");
139
+ const isExpanded = $btn.data("expanded");
140
+ if (isExpanded) {
141
+ this.collapseNode(nodeId);
142
+ } else {
143
+ this.expandNode(nodeId);
144
+ }
145
+ },
146
+
147
+ showChildren: function(parentId) {
148
+ const $children = this.$tableBody.find(`tr[data-parent-id="${parentId}"]`);
149
+ $children.removeClass("treenode-hidden");
150
+
151
+ $children.each((_, child) => {
152
+ const $child = $(child);
153
+ const childId = $child.data("node-id");
154
+ const $toggle = $child.find(".treenode-toggle");
155
+ if ($toggle.data("expanded")) {
156
+ this.showChildren(childId);
333
157
  }
334
158
  });
335
159
  },
336
160
 
337
- removeRows: function(parentId) {
338
- var $children = this.$tableBody.find(`tr[data-parent-of="${parentId}"]`);
339
- $children.each(function () {
340
- var childId = $(this).data('node-id');
341
- ChangeList.removeRows(childId);
161
+ hideChildrenRecursive: function(parentId) {
162
+ const $children = this.$tableBody.find(`tr[data-parent-id="${parentId}"]`);
163
+ $children.addClass("treenode-hidden");
164
+
165
+ $children.each((_, child) => {
166
+ const childId = $(child).data("node-id");
167
+ this.hideChildrenRecursive(childId);
342
168
  });
343
- $children.remove();
344
- this.saveTree();
345
169
  },
346
170
 
347
- toggleNode: function($btn) {
348
- var expanded = $btn.data('expanded');
349
- var $parentRow = $btn.closest('tr');
350
- var parentId = $btn.data('node-id');
171
+ expandAll: function() {
172
+ const self = this;
173
+ this.$tableBody.find("button.treenode-toggle").each(function() {
174
+ self.expandNode($(this).data("node-id"));
175
+ });
176
+ },
351
177
 
352
- if (expanded) {
353
- $btn.html('►').data('expanded', false);
354
- this.removeRows(parentId);
355
- } else {
356
- $btn.html('▼').data('expanded', true);
357
- this.insertRows($parentRow, parentId);
358
- }
178
+ collapseAll: function() {
179
+ const self = this;
180
+ this.$tableBody.find("button.treenode-toggle").each(function() {
181
+ self.collapseNode($(this).data("node-id"));
182
+ });
359
183
  },
360
184
 
361
185
  bindEvents: function() {
362
- var self = this;
363
-
364
- // Search listener
365
- $('input[name="q"]')
366
- .on("focus", function() {
367
- self.saveTree();
368
- })
369
- .on("keyup", debounce(function() {
370
- var query = $.trim($(this).val());
371
- if (query === '') {
372
- self.restoreTree(ChangeList.expandedNodes);
373
- } else {
374
- self.searchRows(query);
375
- }
376
- }, 300));
186
+ const self = this;
377
187
 
378
- // Toggle buttons listener
379
188
  $(document).on("click", "button.treenode-toggle", function(e) {
380
189
  e.preventDefault();
381
- var $btn = $(this);
382
- self.toggleNode($btn);
190
+ self.toggleNode($(this));
191
+ });
192
+
193
+ $(document).on("click", ".treenode-expand-all", function() {
194
+ self.expandAll();
383
195
  });
384
-
385
- // Shift key hold listener
196
+
197
+ $(document).on("click", ".treenode-collapse-all", function() {
198
+ self.collapseAll();
199
+ });
200
+
386
201
  $(document).on("keydown", function(e) {
387
202
  if (e.key === "Shift") {
388
- ChangeList.isShiftPressed = true;
389
- ChangeList.updateDndHighlight();
203
+ self.isShiftPressed = true;
204
+ self.updateDndHighlight();
390
205
  }
391
- })
392
- .on("keyup", function(e) {
206
+ }).on("keyup", function(e) {
393
207
  if (e.key === "Shift") {
394
- ChangeList.isShiftPressed = false;
395
- ChangeList.updateDndHighlight();
208
+ self.isShiftPressed = false;
209
+ self.updateDndHighlight();
396
210
  }
397
211
  });
398
-
399
- // Listener for admin panel theme change button
400
- $(document).on("click", "button.theme-toggle", function() {
401
- applyTheme();
402
- });
403
-
404
- // Fix action selets
212
+
405
213
  $('#result_list').on('change', '#action-toggle', function() {
406
214
  $('input.action-select').prop('checked', this.checked);
407
215
  });
408
216
  },
409
-
217
+
410
218
  enableDragAndDrop: function() {
411
219
  const self = this;
412
-
220
+
413
221
  this.$tableBody.sortable({
414
222
  items: "tr",
415
223
  handle: ".treenode-drag-handle",
416
224
  placeholder: "treenode-placeholder",
417
- activeTargetRow: null,
418
225
  helper: function(e, tr) {
419
226
  const $originals = tr.children();
420
227
  const $helper = tr.clone();
421
- $helper.find('[id]').each(function() {
422
- $(this).removeAttr('id');
423
- });
228
+ $helper.find('[id]').removeAttr('id');
424
229
  $helper.children().each(function(index) {
425
230
  $(this).width($originals.eq(index).width());
426
231
  });
@@ -428,45 +233,38 @@
428
233
  },
429
234
  start: function(e, ui) {
430
235
  TreeFx.markDragging(ui.item, true);
431
- // ChangeList.updateDndHighlight();
432
- // console.log("Drag started:", ui.item.data("node-id"));
433
236
  },
434
237
  over: function(e, ui) {
435
- ChangeList.updateDndHighlight();
436
- // console.log("over")
238
+ self.updateDndHighlight();
437
239
  },
438
240
  stop: function(e, ui) {
439
241
  TreeFx.markDragging(ui.item, false);
440
-
441
242
  const $item = ui.item;
442
243
  const nodeId = $item.data("node-id");
443
244
  const prevId = $item.prev().data("node-id") || null;
444
- const nextId = $item.next().data("node-id") || null;
445
- const isChild = ChangeList.isShiftPressed;
245
+ const mode = self.isShiftPressed ? 'child' : 'after';
446
246
 
447
- if (ChangeList.activeTargetRow) {
448
- ChangeList.activeTargetRow.removeClass("target-as-child");
449
- ChangeList.activeTargetRow = null;
247
+ if (self.activeTargetRow) {
248
+ self.activeTargetRow.removeClass("target-as-child");
249
+ self.activeTargetRow = null;
450
250
  }
451
251
 
452
- mode = isChild ? 'child' : 'after';
453
- ChangeList.applyMove(nodeId, prevId, mode)
454
-
252
+ self.applyMove(nodeId, prevId, mode);
455
253
  TreeFx.flashInsert(nodeId);
456
254
  },
457
255
  });
458
256
  },
459
-
257
+
460
258
  updateDndHighlight: function() {
461
259
  const $placeholder = this.$tableBody.find("tr.treenode-placeholder");
462
260
  const $target = $placeholder.prev();
463
-
464
- if (!($target && $target.length && $target.data("node-id"))) {
261
+
262
+ if (!$target.length || !$target.data("node-id")) {
465
263
  this.$tableBody.find("tr.target-as-child").removeClass("target-as-child");
466
264
  this.activeTargetRow = null;
467
265
  return;
468
266
  }
469
-
267
+
470
268
  if (this.isShiftPressed) {
471
269
  if (!this.activeTargetRow || !this.activeTargetRow.is($target)) {
472
270
  this.$tableBody.find("tr.target-as-child").removeClass("target-as-child");
@@ -480,52 +278,45 @@
480
278
  }
481
279
  }
482
280
  },
483
-
281
+
484
282
  applyMove: function(nodeId, targetId, mode) {
485
283
  if (this.isMoving) return;
486
-
284
+
487
285
  this.isMoving = true;
488
286
  this.activeTargetRow = null;
489
-
287
+
490
288
  const params = {
491
289
  node_id: nodeId,
492
290
  target_id: targetId,
493
- mode: mode,
494
- expanded: JSON.stringify(this.expandedNodes)
291
+ mode: mode
495
292
  };
496
-
497
- // console.log(params);
498
-
293
+
499
294
  $.ajax({
500
295
  url: 'move/',
501
296
  method: 'POST',
502
297
  data: params,
503
298
  dataType: 'json',
504
299
  success: function(data) {
505
- hangleAjaxSuccess(data);
300
+ const msg = data.message || "Node moved successfully.";
301
+ $("<li class='success'>" + msg + "</li>").appendTo(".messagelist");
506
302
  },
507
303
  error: function(xhr, status, error) {
508
- handleAjaxError(xhr, status, error);
304
+ const fallback = "Error moving node.";
305
+ $("<li class='error'>" + (xhr.responseText || fallback) + "</li>").appendTo(".messagelist");
509
306
  },
510
307
  complete: function() {
511
308
  ChangeList.isMoving = false;
512
- clearCursor();
309
+ location.reload();
513
310
  }
514
311
  });
515
312
  }
516
- }
517
-
518
- // ------------------------------- //
519
- // Init //
520
- // ------------------------------- //
313
+ };
521
314
 
522
315
  $(document).ready(function () {
523
- document.body.style.cursor = '';
524
- applyTheme();
525
- if ($("table#result_list").length) {
526
- ChangeList.init();
527
- }
316
+ if ($("table#result_list").length) {
317
+ ChangeList.init();
318
+ ChangeList.restoreTreeState();
319
+ }
528
320
  });
529
321
 
530
- })(django.jQuery || window.jQuery);
531
-
322
+ })(django.jQuery || window.jQuery);