sharkey-web 3.3.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 (96) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.md +19 -0
  5. data/README.md +188 -0
  6. data/Rakefile +8 -0
  7. data/bin/sharkey-web +9 -0
  8. data/config.ru +3 -0
  9. data/lib/sharkey.rb +12 -0
  10. data/lib/sharkey/app.rb +526 -0
  11. data/lib/sharkey/importerexporter.rb +79 -0
  12. data/lib/sharkey/models.rb +295 -0
  13. data/lib/sharkey/public/css/loading.gif +0 -0
  14. data/lib/sharkey/public/css/magicsuggest.css +232 -0
  15. data/lib/sharkey/public/css/nprogress.css +74 -0
  16. data/lib/sharkey/public/css/styles.css +263 -0
  17. data/lib/sharkey/public/css/ui.fancytree.css +545 -0
  18. data/lib/sharkey/public/data/sentences.txt +5 -0
  19. data/lib/sharkey/public/fonts/Quadrata.eot +0 -0
  20. data/lib/sharkey/public/fonts/Quadrata.svg +613 -0
  21. data/lib/sharkey/public/fonts/Quadrata.ttf +0 -0
  22. data/lib/sharkey/public/fonts/Quadrata.woff +0 -0
  23. data/lib/sharkey/public/fonts/Quadrata.zip +0 -0
  24. data/lib/sharkey/public/images/loader.gif +0 -0
  25. data/lib/sharkey/public/images/sharkey-logo.png +0 -0
  26. data/lib/sharkey/public/images/sharkey.png +0 -0
  27. data/lib/sharkey/public/js/ajaxmanager.js +67 -0
  28. data/lib/sharkey/public/js/keybindings.js +92 -0
  29. data/lib/sharkey/public/js/lib/bootstrap.min.js +6 -0
  30. data/lib/sharkey/public/js/lib/jquery-1.9.1.min.js +5 -0
  31. data/lib/sharkey/public/js/lib/jquery-ui.js +16150 -0
  32. data/lib/sharkey/public/js/lib/jquery.bootstrap-autohidingnavbar.js +213 -0
  33. data/lib/sharkey/public/js/lib/jquery.fancytree-all.js +6424 -0
  34. data/lib/sharkey/public/js/lib/jquery.tagcloud.js +92 -0
  35. data/lib/sharkey/public/js/lib/magicsuggest.js +1468 -0
  36. data/lib/sharkey/public/js/lib/mousetrap.min.js +9 -0
  37. data/lib/sharkey/public/js/lib/nprogress.js +476 -0
  38. data/lib/sharkey/public/js/page-add-link-autofill.js +102 -0
  39. data/lib/sharkey/public/js/page-add-link.js +156 -0
  40. data/lib/sharkey/public/js/page-categories.js +348 -0
  41. data/lib/sharkey/public/js/page-edit-link.js +103 -0
  42. data/lib/sharkey/public/js/page-links.js +54 -0
  43. data/lib/sharkey/public/js/page-settings.js +93 -0
  44. data/lib/sharkey/public/js/page-tagcloud.js +35 -0
  45. data/lib/sharkey/public/js/page-tags.js +287 -0
  46. data/lib/sharkey/public/js/scripts.js +147 -0
  47. data/lib/sharkey/public/themes/amelia/style.css +7 -0
  48. data/lib/sharkey/public/themes/bootstrap/style.css +5785 -0
  49. data/lib/sharkey/public/themes/cerulean/style.css +7 -0
  50. data/lib/sharkey/public/themes/cosmo/style.css +7 -0
  51. data/lib/sharkey/public/themes/cyborg/style.css +7 -0
  52. data/lib/sharkey/public/themes/darkly/style.css +7 -0
  53. data/lib/sharkey/public/themes/facebook-like/README.md +6 -0
  54. data/lib/sharkey/public/themes/facebook-like/style.css +6085 -0
  55. data/lib/sharkey/public/themes/flatly/style.css +7 -0
  56. data/lib/sharkey/public/themes/fonts/glyphicons-halflings-regular.eot +0 -0
  57. data/lib/sharkey/public/themes/fonts/glyphicons-halflings-regular.svg +229 -0
  58. data/lib/sharkey/public/themes/fonts/glyphicons-halflings-regular.ttf +0 -0
  59. data/lib/sharkey/public/themes/fonts/glyphicons-halflings-regular.woff +0 -0
  60. data/lib/sharkey/public/themes/holo-like/README.md +5 -0
  61. data/lib/sharkey/public/themes/holo-like/style.css +5997 -0
  62. data/lib/sharkey/public/themes/journal/style.css +7 -0
  63. data/lib/sharkey/public/themes/lumen/style.css +7 -0
  64. data/lib/sharkey/public/themes/readable/style.css +7 -0
  65. data/lib/sharkey/public/themes/simplex/style.css +7 -0
  66. data/lib/sharkey/public/themes/slate/style.css +7 -0
  67. data/lib/sharkey/public/themes/spacelab/style.css +7 -0
  68. data/lib/sharkey/public/themes/superhero/style.css +7 -0
  69. data/lib/sharkey/public/themes/united/style.css +7 -0
  70. data/lib/sharkey/public/themes/yeti/style.css +7 -0
  71. data/lib/sharkey/setting.rb +74 -0
  72. data/lib/sharkey/version.rb +5 -0
  73. data/lib/sharkey/views/404.slim +4 -0
  74. data/lib/sharkey/views/about.slim +7 -0
  75. data/lib/sharkey/views/add_link.slim +157 -0
  76. data/lib/sharkey/views/categories.slim +101 -0
  77. data/lib/sharkey/views/category.slim +22 -0
  78. data/lib/sharkey/views/centered.slim +49 -0
  79. data/lib/sharkey/views/dashboard.slim +107 -0
  80. data/lib/sharkey/views/dashboard_index.slim +26 -0
  81. data/lib/sharkey/views/edit_link.slim +121 -0
  82. data/lib/sharkey/views/help.slim +74 -0
  83. data/lib/sharkey/views/keybindings.slim +58 -0
  84. data/lib/sharkey/views/link.slim +30 -0
  85. data/lib/sharkey/views/links.slim +22 -0
  86. data/lib/sharkey/views/navbar.slim +68 -0
  87. data/lib/sharkey/views/settings.slim +74 -0
  88. data/lib/sharkey/views/settings_index.slim +220 -0
  89. data/lib/sharkey/views/single_category.slim +37 -0
  90. data/lib/sharkey/views/single_link.slim +95 -0
  91. data/lib/sharkey/views/single_tag.slim +33 -0
  92. data/lib/sharkey/views/tag.slim +22 -0
  93. data/lib/sharkey/views/tagcloud.slim +54 -0
  94. data/lib/sharkey/views/tags.slim +99 -0
  95. data/sharkey-web.gemspec +44 -0
  96. metadata +324 -0
@@ -0,0 +1,102 @@
1
+ /*global $*/
2
+
3
+ ($(function(){
4
+
5
+ // *****************************************************
6
+ // CODE DUPLICATION
7
+ // (see `scripts.js`)
8
+ /**
9
+ * Returns a new cute spinner GIF for
10
+ * showing indeterminate progress.
11
+ */
12
+ function newSpinner() {
13
+ return $('<img/>').attr("src", "/images/loader.gif");
14
+ }
15
+ /* Here we preload the image so it won't take long
16
+ * when creating it for the first time */
17
+ newSpinner().appendTo('body').hide();
18
+ // *****************************************************
19
+
20
+
21
+
22
+ /* When the user finishes entering a URL, we make an
23
+ * AJAX request to know that URL's title and description.
24
+ *
25
+ * We'll use that to automatically fill the <inputs>
26
+ * on the "Add Link" dialog.
27
+ *
28
+ * But if the user starts typing something on the title
29
+ * input then we abort that request.
30
+ */
31
+
32
+ // This will contain the AJAX request for when we ask
33
+ // for the link info.
34
+ var linkMetadataRequest;
35
+
36
+ // If the user starts typing on the title input
37
+ // we cancel the AJAX request
38
+ //
39
+ $('#input-link-title').keypress(function() {
40
+ if (typeof(linkMetadataRequest) !== 'undefined')
41
+ linkMetadataRequest.abort();
42
+ });
43
+
44
+ // And here we make it so that when the user leaves
45
+ // the URL input, we start making that request.
46
+ //
47
+ // When it starts it'll place a cute spinner to show
48
+ // progress.
49
+ //
50
+ // @note: It will only put things on the input if
51
+ // there's nothing there!
52
+ // In other words, it won't override existing
53
+ // values!
54
+ $('#add-link #input-link-url').focusout(function() {
55
+
56
+ // Don't request title for empty URL
57
+ var text = $(this).val();
58
+ if (text === "")
59
+ return;
60
+
61
+ // Won't do anything if all the fields
62
+ // are already filled
63
+ var title_input = $('#add-link #input-link-title');
64
+ var comment_input = $('#add-link .input-links-comment');
65
+ if ((title_input.val() !== '') && (comment_input.val() !== ''))
66
+ return;
67
+
68
+ var spinner_place = $('#single-link span.spinner-placeholder');
69
+ var spinner = $(newSpinner()).appendTo(spinner_place);
70
+
71
+ linkMetadataRequest = $.ajax({
72
+ url: '/metadata',
73
+ method: 'GET',
74
+ data: {
75
+ url: text
76
+ },
77
+
78
+ success: function(responseData, textStatus, jqXHR) {
79
+ spinner.remove();
80
+
81
+ var response = $.parseJSON(responseData);
82
+
83
+ var title = response.pageTitle;
84
+ var description = response.pageDescription;
85
+
86
+ if (title_input.val() === '')
87
+ title_input.val(title);
88
+
89
+ if (comment_input.val() === '')
90
+ comment_input.val(description);
91
+ },
92
+
93
+ complete: function() {
94
+ spinner.remove();
95
+ }
96
+ });
97
+
98
+ });
99
+
100
+ }));
101
+
102
+
@@ -0,0 +1,156 @@
1
+ /*global $*/
2
+
3
+ /**
4
+ * Scripts for both the "Add Link" dialog and the "Edit Link".
5
+ *
6
+ * They're Bootstrap Modals that initially appear hidden and only
7
+ * get shown when requested.
8
+ */
9
+ ($(function(){
10
+
11
+ // *****************************************************
12
+ // CODE DUPLICATION
13
+ // (see `scripts.js`)
14
+ /**
15
+ * Returns a new cute spinner GIF for
16
+ * showing indeterminate progress.
17
+ */
18
+ function newSpinner() {
19
+ return $('<img/>').attr("src", "/images/loader.gif");
20
+ }
21
+ /* Here we preload the image so it won't take long
22
+ * when creating it for the first time */
23
+ newSpinner().appendTo('body').hide();
24
+ // *****************************************************
25
+
26
+
27
+
28
+ // Prevent user from double-submitting a <form>
29
+ // 1. Make buttons hide when user submits
30
+ // (either by clicking on 'Add Link' or pressing Enter)
31
+ // 2. As soon as a <form> starts being submitted,
32
+ // disable further submissions.
33
+ var submitting = false;
34
+ $('.input-link form').submit(function() {
35
+ // By returning false we prevent further submissions
36
+ if (submitting)
37
+ return false;
38
+
39
+ // <input> validation!
40
+ // Only submit if we have an URL on the <form>
41
+ if ($('.input-link-url').val() !== "") {
42
+
43
+ $('.input-link form button').addClass('disabled');
44
+ submitting = true;
45
+ }
46
+ // Makes the form start submitting
47
+ return true;
48
+ });
49
+
50
+
51
+ /**
52
+ * The awesome new category form.
53
+ * We have a button "New Category" that shows
54
+ * a form when clicked.
55
+ *
56
+ * When that form is filled, we hide it and
57
+ * show the button again.
58
+ */
59
+ $('.new-category-form').hide();
60
+
61
+ $('.new-category').click(function(e) {
62
+ /* otherwise it would trigger the form validation */
63
+ e.preventDefault();
64
+
65
+ $(this).hide();
66
+ $('.new-category-form').show();
67
+ });
68
+
69
+ /* ...and when this form is submitted, we send an AJAX
70
+ * request for a new category.
71
+ *
72
+ * If successful it refreshes both <select> fields on
73
+ * the page.
74
+ */
75
+ $('.new-category-form').submit(function(e) {
76
+ /* Don't refresh the page! */
77
+ e.preventDefault();
78
+
79
+ /* Will replace the button text with a nice
80
+ * progress spinner */
81
+ var form = $(this);
82
+ var button = $('.new-category-button');
83
+
84
+ var buttonText = button.html();
85
+ var spinner = $(newSpinner());
86
+
87
+ button.html(spinner);
88
+
89
+ $.ajax({
90
+ url: form.attr('action'),
91
+ type: 'POST',
92
+ data: {
93
+ name: $('.new-category-name').val(),
94
+ parent: $('.new-category-parent').val()
95
+ },
96
+
97
+ /* Will add the latest Category to the top of the
98
+ * dropdown menu and mark it as selected
99
+ */
100
+ success: function(responseData, textStatus, jqXHR) {
101
+ var dropdown1 = $('.input-link-category-one');
102
+ var dropdown2 = $('.input-link-category-two');
103
+
104
+ var parsedResponse = $.parseJSON(responseData);
105
+ var value = parsedResponse['id'];
106
+ var name = parsedResponse['name'];
107
+
108
+ dropdown1
109
+ .prepend('<option value="' + value + '">' + name + '</option>')
110
+ .val(value);
111
+ dropdown2
112
+ .prepend('<option value="' + value + '">' + name + '</option>')
113
+ .val(value);
114
+ },
115
+ error: function(responseData, textStatus, jqXHR) {
116
+ /* This error-handling function sucks! */
117
+ // form.append(
118
+ // $("<div>Couldn't apply the setting - please reload the page</div>")
119
+ // .attr('class', 'alert alert-danger')
120
+ // .attr('role', 'alert')
121
+ // );
122
+ alert('no!');
123
+ },
124
+ complete: function() {
125
+ /* taking out the spinner image */
126
+ button.html(buttonText);
127
+ spinner.remove();
128
+
129
+ form.hide();
130
+ $('.new-category').show();
131
+ }
132
+ });
133
+ });
134
+
135
+ /* Beautiful tag-handling stuff */
136
+ $('.tagsinput').magicSuggest({
137
+ /* URL to make an AJAX call to get results */
138
+ data: '/tags',
139
+ /* by default it uses POST, what a bummer */
140
+ method: 'get',
141
+ /* how much it waits before triggering the AJAX query */
142
+ typeDelay: 0,
143
+ noSuggestionText: 'No tags like this',
144
+ placeholder: 'Yeah',
145
+ /* use , to add a tag
146
+ * (why does it not work?
147
+ * it keeps accepting tags ending with commas!) */
148
+ useCommaKey: true,
149
+ /* choose how many tags you want */
150
+ maxSelection: null,
151
+ /* show lines with alternated colors */
152
+ useZebraStyle: true
153
+ });
154
+
155
+ }));
156
+
@@ -0,0 +1,348 @@
1
+ /*global $,ajaxManager*/
2
+
3
+ /**
4
+ * Scripts specific to the Categories page
5
+ *
6
+ * Requires FancyTree
7
+ */
8
+ ($(function(){
9
+
10
+
11
+ // When the page loads, focus on the Category Browser
12
+ $('#categories .fancytree-container').focus();
13
+
14
+
15
+ /**
16
+ * Initializing the tree view for all the Categories
17
+ */
18
+ $('#categories').fancytree({
19
+ extensions: ["glyph", "childcounter"],
20
+ glyph: {
21
+ map: {
22
+ doc: "glyphicon glyphicon-link",
23
+ docOpen: "glyphicon glyphicon-link",
24
+ checkbox: "glyphicon glyphicon-unchecked",
25
+ checkboxSelected:"glyphicon glyphicon-check",
26
+ checkboxUnknown: "glyphicon glyphicon-edit",
27
+ expanderClosed: "glyphicon glyphicon-expand",
28
+ expanderLazy: "glyphicon glyphicon-expand",
29
+ expanderOpen: "glyphicon glyphicon-collapse-down",
30
+ folder: "glyphicon glyphicon-book",
31
+ folderOpen: "glyphicon glyphicon-book"
32
+ }
33
+ },
34
+ keyboard: true,
35
+
36
+ /* when an item is clicked (either Tag or Link) */
37
+ click: function(event, data) {
38
+
39
+ // Clicked item on the list
40
+ //var node = data.node;
41
+
42
+ /* Whenever you click on a link, let's make an
43
+ * AJAX request to add it's visit count
44
+ */
45
+ var element = event.toElement;
46
+
47
+ if ((element) && ($(element).attr('class') === 'link-link')) {
48
+
49
+ var link_id = $(element).attr('data-link-id');
50
+
51
+ $.ajax({
52
+ url: '/visit/' + link_id,
53
+ type: 'POST',
54
+
55
+ // Yeah, won't do anything if we succeed
56
+
57
+ success: function(responseData, textStatus, jqXHR) {
58
+ console.log($.parseJSON(responseData).visitCount);
59
+ },
60
+
61
+ error: function(responseData, textStatus, jqXHR) {
62
+ console.log(
63
+ "Error! Couldn't set Link as visited!\n" +
64
+ "responseData: " + responseData + "\n" +
65
+ "textStatus: " + textStatus + "\n" +
66
+ "jqXHR: " + jqXHR
67
+ );
68
+ }
69
+ });
70
+ }
71
+ },
72
+ /* when user presses ENTER or SPACE inside an item */
73
+ link: function(event, data) {
74
+ /* redirect to the internal link
75
+ * (either Category or Link) */
76
+ var href = $(
77
+ $.parseHTML(data.node.title)
78
+ ).attr('href');
79
+
80
+ window.location.href = href;
81
+ }
82
+ });
83
+ /**
84
+ * Helper to ease applying things to every
85
+ * node inside the tree view.
86
+ *
87
+ * @param apply Function to apply to each node.
88
+ */
89
+ var foreachNode = function(apply) {
90
+ $('#categories')
91
+ .fancytree('getTree')
92
+ .visit(function(node) {
93
+ apply(node);
94
+ });
95
+ };
96
+ /* Things using FancyTree's API */
97
+ $('#categories-expand').click(function() {
98
+ foreachNode(function(node) {
99
+ node.setExpanded(true);
100
+ });
101
+ });
102
+
103
+ $('#categories-collapse').click(function() {
104
+ foreachNode(function(node) {
105
+ node.setExpanded(false);
106
+ });
107
+ });
108
+
109
+ /*
110
+ * Now we define some functions that will handle the
111
+ * editing progress of the Categories.
112
+ */
113
+
114
+ // Flag to tell if we're editing the Categories
115
+ var categoryIsEditing = false;
116
+
117
+ // All the buttons for the editing process
118
+ var categoryEditButtons = $(
119
+ '#categories-select-all, #categories-select-none, #categories-select-toggle, #categories-delete, #categories-delete-links'
120
+ );
121
+ // Initially we're not editing
122
+ categoryEditButtons.hide();
123
+
124
+ /* Start editing, baby! */
125
+ $('#categories-edit').click(function() {
126
+ categoryIsEditing = !categoryIsEditing;
127
+
128
+ if (categoryIsEditing) {
129
+ // Change the button's appearance
130
+ $(this).html(
131
+ "<button class='btn btn-default'><span class='glyphicon glyphicon-ban-circle' /> Cancel</button>"
132
+ );
133
+
134
+ /* Reinitializing the tree view, this time
135
+ * enabling checkboxes and multi-selection
136
+ * mode */
137
+ $('#categories').fancytree({
138
+ checkbox: true,
139
+ selectMode: 2,
140
+
141
+ // When double-clicking, toggle!
142
+ dblclick: function(event, data) {
143
+ data.node.toggleSelected();
144
+ }
145
+ });
146
+ categoryEditButtons.show();
147
+
148
+ // Here we only let the user select CATEGORIES,
149
+ // not LINKS!
150
+ // Categories are considered folders, because they
151
+ foreachNode(function(node) {
152
+ if (! node.isFolder())
153
+ node.unselectable = true;
154
+ });
155
+
156
+ }
157
+ else {
158
+ // Change the button's appearance AGAIN
159
+ $(this).html(
160
+ "<button class='btn btn-default'><span class='glyphicon glyphicon-pencil' /> Edit</button>"
161
+ );
162
+ $('#categories').fancytree({
163
+ checkbox:false
164
+ });
165
+ categoryEditButtons.hide();
166
+ }
167
+ });
168
+
169
+ // And now, what happens when you click
170
+ // on each of those fancy buttons
171
+
172
+ $('#categories-select-all').click(function() {
173
+ foreachNode(function(node) {
174
+ node.setSelected(true);
175
+ });
176
+ });
177
+ $('#categories-select-none').click(function() {
178
+ foreachNode(function(node) {
179
+ node.setSelected(false);
180
+ });
181
+ });
182
+ $('#categories-select-toggle').click(function() {
183
+ foreachNode(function(node) {
184
+ node.toggleSelected();
185
+ });
186
+ });
187
+
188
+ // Now, when you click to delete categories, we musc
189
+ // communicate with the server
190
+ $('#categories-delete').click(function() {
191
+
192
+ // Will also destroy links that has these categories
193
+ var destroyLinks = $('#categories-delete-links input').is(':checked');
194
+
195
+ // We will send several DELETE requests
196
+ // to the server, each with a selected
197
+ // category's ID
198
+ var maxSize = $('#categories')
199
+ .fancytree('getTree')
200
+ .getSelectedNodes()
201
+ .length;
202
+
203
+ // And we place a beautiful progress bar,
204
+ // to make the user not think we crashed
205
+ var progressbarParent = $(
206
+ "<div class='progress progress-striped active'></div>"
207
+ );
208
+ var progressbarText = $("<span>0%</span>");
209
+ var progressbar = $(
210
+ "<div class='progress-bar' " +
211
+ "role='progressbar' " +
212
+ "aria-valuenow='0' " +
213
+ "aria-valuemin='0' " +
214
+ "aria-valuemax='" + maxSize + "'></div>"
215
+ );
216
+
217
+ // Replace the buttons by the progress bar
218
+ $('#categories-buttons').html('');
219
+ progressbarParent.appendTo($('#categories-buttons'));
220
+ progressbar.appendTo(progressbarParent);
221
+ progressbarText.appendTo(progressbar);
222
+
223
+ var deletedCount = 0;
224
+
225
+ foreachNode(function(node) {
226
+
227
+ if (!node.selected)
228
+ return;
229
+
230
+ // Each node has a `title` element,
231
+ // with an href like '/category/(ID)'
232
+ var href = $(
233
+ $.parseHTML(node.title)
234
+ ).attr('href');
235
+
236
+ // Now, time for the AJAX request...!
237
+ ajaxManager.add({
238
+ url: href,
239
+ type: 'DELETE',
240
+ data: {
241
+ destroy_links: destroyLinks
242
+ },
243
+ /* Showing a red background on deleted categories */
244
+ success: function(responseData, textStatus, jqXHR) {
245
+
246
+ // Updating the progress bar
247
+ deletedCount += 1;
248
+ progressbar
249
+ .attr('style', 'width:' + (deletedCount/maxSize)*100 + '%')
250
+ .attr('aria-valuenow', deletedCount);
251
+ progressbarText
252
+ .text(Math.round( ((deletedCount/maxSize)*100) * 100)/100+ '%');
253
+
254
+ // This animation requires jQueryUI
255
+ $(node.span).animate({
256
+ backgroundColor: '#FFDFDF'
257
+ }, 1000);
258
+
259
+ // Removing the element on the raw list
260
+ // generated by sinatra
261
+ $('#categories')
262
+ .find("li span a[href='" + href + "']")
263
+ .each(function() {
264
+ $(this).parent('li').remove();
265
+ });
266
+ },
267
+ error: function(responseData, textStatus, jqXHR) {
268
+ /* This error-handling function sucks! */
269
+ alert("Couldn't remove category! " + responseData + ', ' + textStatus);
270
+ }
271
+ });
272
+ });
273
+ // When everything's done...
274
+ ajaxManager.complete = function() {
275
+
276
+ // Now the progress bar is shown as completed
277
+ // and the user is advised to refresh the page
278
+ progressbarParent.removeClass('active');
279
+ progressbarParent.removeClass('progress-striped');
280
+ progressbar.addClass('progress-bar-success');
281
+ progressbarText.text("Done! Refresh page to see the changes");
282
+ };
283
+
284
+ // Now, do perform those requests for me!
285
+ ajaxManager.run();
286
+ });
287
+
288
+
289
+
290
+
291
+ // // When the page loads, focus on the categories browser
292
+ // $('#categories .fancytree-container').focus();
293
+
294
+ // /**
295
+ // * FancyTree makes easy to show a tree view, just like
296
+ // * a file browser on a file system.
297
+ // *
298
+ // * We use it on the Categories page.
299
+ // */
300
+ // $('#categories').fancytree({
301
+ // extensions: ["glyph", "childcounter"],
302
+ // glyph: {
303
+ // map: {
304
+ // doc: "glyphicon glyphicon-link",
305
+ // folder: "glyphicon glyphicon-book",
306
+ // expanderClosed: "glyphicon glyphicon-expand",
307
+ // expanderLazy: "glyphicon glyphicon-expand",
308
+ // expanderOpen: "glyphicon glyphicon-collapse-down"
309
+ // }
310
+ // },
311
+ // keyboard: true,
312
+
313
+ // /* when an item is clicked (either Category or Link) */
314
+ // activate: function(event, data) {
315
+ // /* Nothing for now... */
316
+ // //var node = data.node;
317
+ // //console.log(data);
318
+ // },
319
+ // /* when user presses ENTER or SPACE inside an item */
320
+ // link: function(event, data) {
321
+ // /* redirect to the internal link
322
+ // * (either Category or Link) */
323
+ // var href = $(
324
+ // $.parseHTML(data.node.title)
325
+ // ).attr('href');
326
+
327
+ // window.location.href = href;
328
+ // }
329
+ // });
330
+ // /* Things using FancyTree's API */
331
+ // $('#categories-expand').click(function() {
332
+ // // For each node, expand it!
333
+ // $('#categories')
334
+ // .fancytree('getTree')
335
+ // .visit(function(node) {
336
+ // node.setExpanded(true);
337
+ // });
338
+ // });
339
+ // $('#categories-collapse').click(function() {
340
+ // // TODO: Remove this code repetition!
341
+ // $('#categories')
342
+ // .fancytree('getTree')
343
+ // .visit(function(node) {
344
+ // node.setExpanded(false);
345
+ // });
346
+ // });
347
+ }));
348
+