sequenceserver 2.0.0.rc8 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sequenceserver might be problematic. Click here for more details.

Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/bin/sequenceserver +22 -30
  3. data/lib/sequenceserver/api_errors.rb +5 -1
  4. data/lib/sequenceserver/blast/constants.rb +1 -1
  5. data/lib/sequenceserver/blast/hit.rb +5 -16
  6. data/lib/sequenceserver/blast/job.rb +9 -18
  7. data/lib/sequenceserver/blast/report.rb +5 -3
  8. data/lib/sequenceserver/config.rb +4 -1
  9. data/lib/sequenceserver/database.rb +69 -9
  10. data/lib/sequenceserver/job.rb +1 -1
  11. data/lib/sequenceserver/makeblastdb.rb +40 -45
  12. data/lib/sequenceserver/routes.rb +4 -0
  13. data/lib/sequenceserver/version.rb +1 -1
  14. data/lib/sequenceserver.rb +15 -11
  15. data/public/config.js +143 -142
  16. data/public/css/fonts.css +23 -22
  17. data/public/css/grapher.css +598 -594
  18. data/public/css/sequenceserver.css +86 -24
  19. data/public/css/sequenceserver.min.css +2 -2
  20. data/public/js/alignment_exporter.js +14 -14
  21. data/public/js/databases_tree.js +215 -0
  22. data/public/js/download_fasta.js +1 -1
  23. data/public/js/hit.js +6 -2
  24. data/public/js/hits_overview.js +1 -1
  25. data/public/js/length_distribution.js +5 -5
  26. data/public/js/query.js +4 -7
  27. data/public/js/report.js +12 -24
  28. data/public/js/search.js +21 -2
  29. data/public/js/sidebar.js +4 -4
  30. data/public/js/svgExporter.js +12 -12
  31. data/public/js/visualisation_helpers.js +4 -5
  32. data/public/sequenceserver-report.min.js +11 -11
  33. data/public/sequenceserver-search.min.js +15 -11
  34. data/public/vendor/github/vakata/jstree@3.3.8/LICENSE-MIT +22 -0
  35. data/public/vendor/github/vakata/jstree@3.3.8/README.md +663 -0
  36. data/public/vendor/github/vakata/jstree@3.3.8/bower.json +33 -0
  37. data/public/vendor/github/vakata/jstree@3.3.8/component.json +28 -0
  38. data/public/vendor/github/vakata/jstree@3.3.8/composer.json +46 -0
  39. data/public/vendor/github/vakata/jstree@3.3.8/demo/README.md +2 -0
  40. data/public/vendor/github/vakata/jstree@3.3.8/demo/basic/index.html +146 -0
  41. data/public/vendor/github/vakata/jstree@3.3.8/demo/basic/root.json +1 -0
  42. data/public/vendor/github/vakata/jstree@3.3.8/dist/jstree.js +8612 -0
  43. data/public/vendor/github/vakata/jstree@3.3.8/dist/jstree.min.js +6 -0
  44. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/32px.png +0 -0
  45. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/40px.png +0 -0
  46. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/style.css +1102 -0
  47. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/style.min.css +1 -0
  48. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/throbber.gif +0 -0
  49. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/32px.png +0 -0
  50. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/40px.png +0 -0
  51. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/style.css +1146 -0
  52. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/style.min.css +1 -0
  53. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/throbber.gif +0 -0
  54. data/public/vendor/github/vakata/jstree@3.3.8/gruntfile.js +242 -0
  55. data/public/vendor/github/vakata/jstree@3.3.8/jstree.jquery.json +28 -0
  56. data/public/vendor/github/vakata/jstree@3.3.8/package.json +58 -0
  57. data/public/vendor/github/vakata/jstree@3.3.8/src/intro.js +14 -0
  58. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.changed.js +69 -0
  59. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.checkbox.js +976 -0
  60. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.conditionalselect.js +38 -0
  61. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.contextmenu.js +661 -0
  62. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.dnd.js +669 -0
  63. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.js +4931 -0
  64. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.massload.js +137 -0
  65. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.search.js +421 -0
  66. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.sort.js +74 -0
  67. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.state.js +138 -0
  68. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.types.js +372 -0
  69. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.unique.js +164 -0
  70. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.wholerow.js +122 -0
  71. data/public/vendor/github/vakata/jstree@3.3.8/src/misc.js +656 -0
  72. data/public/vendor/github/vakata/jstree@3.3.8/src/outro.js +1 -0
  73. data/public/vendor/github/vakata/jstree@3.3.8/src/sample.js +93 -0
  74. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/base.less +93 -0
  75. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/32px.png +0 -0
  76. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/40px.png +0 -0
  77. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/style.css +1102 -0
  78. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/style.less +22 -0
  79. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/throbber.gif +0 -0
  80. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/32px.png +0 -0
  81. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/40px.png +0 -0
  82. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/style.css +1146 -0
  83. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/style.less +50 -0
  84. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/throbber.gif +0 -0
  85. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/main.less +77 -0
  86. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/mixins.less +104 -0
  87. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/responsive.less +67 -0
  88. data/public/vendor/github/vakata/jstree@3.3.8/src/vakata-jstree.js +38 -0
  89. data/public/vendor/github/vakata/jstree@3.3.8/test/unit/index.html +16 -0
  90. data/public/vendor/github/vakata/jstree@3.3.8/test/unit/libs/qunit.css +244 -0
  91. data/public/vendor/github/vakata/jstree@3.3.8/test/unit/libs/qunit.js +2212 -0
  92. data/public/vendor/github/vakata/jstree@3.3.8/test/unit/test.js +11 -0
  93. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/desktop/index.html +44 -0
  94. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/mobile/index.html +42 -0
  95. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/desktop/desktop.png +0 -0
  96. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/desktop/home.png +0 -0
  97. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/mobile/home.png +0 -0
  98. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/mobile/mobile.png +0 -0
  99. data/public/vendor/github/vakata/jstree@3.3.8.js +3 -0
  100. data/public/vendor/system-csp-production.js +3 -3
  101. data/public/vendor/system-csp-production.js.map +1 -1
  102. data/public/vendor/system-csp-production.src.js +146 -140
  103. data/public/vendor/system-polyfills.js.map +1 -1
  104. data/public/vendor/system-polyfills.src.js +1 -0
  105. data/public/vendor/system.js +3 -3
  106. data/public/vendor/system.js.map +1 -1
  107. data/public/vendor/system.src.js +4771 -2383
  108. data/views/_options.erb +21 -0
  109. data/views/layout.erb +17 -18
  110. metadata +102 -43
  111. data/bin/chromedriver +0 -0
  112. data/bin/geckodriver +0 -0
  113. data/public/shims/form-core.js +0 -3
  114. data/public/shims/form-validation.js +0 -3
  115. data/public/shims/plugins/jquery.ui.position.js +0 -13
  116. data/public/shims/styles/shim.css +0 -1
@@ -0,0 +1,38 @@
1
+ /**
2
+ * ### Conditionalselect plugin
3
+ *
4
+ * This plugin allows defining a callback to allow or deny node selection by user input (activate node method).
5
+ */
6
+ /*globals jQuery, define, exports, require, document */
7
+ (function (factory) {
8
+ "use strict";
9
+ if (typeof define === 'function' && define.amd) {
10
+ define('jstree.conditionalselect', ['jquery','jstree'], factory);
11
+ }
12
+ else if(typeof exports === 'object') {
13
+ factory(require('jquery'), require('jstree'));
14
+ }
15
+ else {
16
+ factory(jQuery, jQuery.jstree);
17
+ }
18
+ }(function ($, jstree, undefined) {
19
+ "use strict";
20
+
21
+ if($.jstree.plugins.conditionalselect) { return; }
22
+
23
+ /**
24
+ * a callback (function) which is invoked in the instance's scope and receives two arguments - the node and the event that triggered the `activate_node` call. Returning false prevents working with the node, returning true allows invoking activate_node. Defaults to returning `true`.
25
+ * @name $.jstree.defaults.checkbox.visible
26
+ * @plugin checkbox
27
+ */
28
+ $.jstree.defaults.conditionalselect = function () { return true; };
29
+ $.jstree.plugins.conditionalselect = function (options, parent) {
30
+ // own function
31
+ this.activate_node = function (obj, e) {
32
+ if(this.settings.conditionalselect.call(this, this.get_node(obj), e)) {
33
+ return parent.activate_node.call(this, obj, e);
34
+ }
35
+ };
36
+ };
37
+
38
+ }));
@@ -0,0 +1,661 @@
1
+ /**
2
+ * ### Contextmenu plugin
3
+ *
4
+ * Shows a context menu when a node is right-clicked.
5
+ */
6
+ /*globals jQuery, define, exports, require, document */
7
+ (function (factory) {
8
+ "use strict";
9
+ if (typeof define === 'function' && define.amd) {
10
+ define('jstree.contextmenu', ['jquery','jstree'], factory);
11
+ }
12
+ else if(typeof exports === 'object') {
13
+ factory(require('jquery'), require('jstree'));
14
+ }
15
+ else {
16
+ factory(jQuery, jQuery.jstree);
17
+ }
18
+ }(function ($, jstree, undefined) {
19
+ "use strict";
20
+
21
+ if($.jstree.plugins.contextmenu) { return; }
22
+
23
+ /**
24
+ * stores all defaults for the contextmenu plugin
25
+ * @name $.jstree.defaults.contextmenu
26
+ * @plugin contextmenu
27
+ */
28
+ $.jstree.defaults.contextmenu = {
29
+ /**
30
+ * a boolean indicating if the node should be selected when the context menu is invoked on it. Defaults to `true`.
31
+ * @name $.jstree.defaults.contextmenu.select_node
32
+ * @plugin contextmenu
33
+ */
34
+ select_node : true,
35
+ /**
36
+ * a boolean indicating if the menu should be shown aligned with the node. Defaults to `true`, otherwise the mouse coordinates are used.
37
+ * @name $.jstree.defaults.contextmenu.show_at_node
38
+ * @plugin contextmenu
39
+ */
40
+ show_at_node : true,
41
+ /**
42
+ * an object of actions, or a function that accepts a node and a callback function and calls the callback function with an object of actions available for that node (you can also return the items too).
43
+ *
44
+ * Each action consists of a key (a unique name) and a value which is an object with the following properties (only label and action are required). Once a menu item is activated the `action` function will be invoked with an object containing the following keys: item - the contextmenu item definition as seen below, reference - the DOM node that was used (the tree node), element - the contextmenu DOM element, position - an object with x/y properties indicating the position of the menu.
45
+ *
46
+ * * `separator_before` - a boolean indicating if there should be a separator before this item
47
+ * * `separator_after` - a boolean indicating if there should be a separator after this item
48
+ * * `_disabled` - a boolean indicating if this action should be disabled
49
+ * * `label` - a string - the name of the action (could be a function returning a string)
50
+ * * `title` - a string - an optional tooltip for the item
51
+ * * `action` - a function to be executed if this item is chosen, the function will receive
52
+ * * `icon` - a string, can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class
53
+ * * `shortcut` - keyCode which will trigger the action if the menu is open (for example `113` for rename, which equals F2)
54
+ * * `shortcut_label` - shortcut label (like for example `F2` for rename)
55
+ * * `submenu` - an object with the same structure as $.jstree.defaults.contextmenu.items which can be used to create a submenu - each key will be rendered as a separate option in a submenu that will appear once the current item is hovered
56
+ *
57
+ * @name $.jstree.defaults.contextmenu.items
58
+ * @plugin contextmenu
59
+ */
60
+ items : function (o, cb) { // Could be an object directly
61
+ return {
62
+ "create" : {
63
+ "separator_before" : false,
64
+ "separator_after" : true,
65
+ "_disabled" : false, //(this.check("create_node", data.reference, {}, "last")),
66
+ "label" : "Create",
67
+ "action" : function (data) {
68
+ var inst = $.jstree.reference(data.reference),
69
+ obj = inst.get_node(data.reference);
70
+ inst.create_node(obj, {}, "last", function (new_node) {
71
+ try {
72
+ inst.edit(new_node);
73
+ } catch (ex) {
74
+ setTimeout(function () { inst.edit(new_node); },0);
75
+ }
76
+ });
77
+ }
78
+ },
79
+ "rename" : {
80
+ "separator_before" : false,
81
+ "separator_after" : false,
82
+ "_disabled" : false, //(this.check("rename_node", data.reference, this.get_parent(data.reference), "")),
83
+ "label" : "Rename",
84
+ /*!
85
+ "shortcut" : 113,
86
+ "shortcut_label" : 'F2',
87
+ "icon" : "glyphicon glyphicon-leaf",
88
+ */
89
+ "action" : function (data) {
90
+ var inst = $.jstree.reference(data.reference),
91
+ obj = inst.get_node(data.reference);
92
+ inst.edit(obj);
93
+ }
94
+ },
95
+ "remove" : {
96
+ "separator_before" : false,
97
+ "icon" : false,
98
+ "separator_after" : false,
99
+ "_disabled" : false, //(this.check("delete_node", data.reference, this.get_parent(data.reference), "")),
100
+ "label" : "Delete",
101
+ "action" : function (data) {
102
+ var inst = $.jstree.reference(data.reference),
103
+ obj = inst.get_node(data.reference);
104
+ if(inst.is_selected(obj)) {
105
+ inst.delete_node(inst.get_selected());
106
+ }
107
+ else {
108
+ inst.delete_node(obj);
109
+ }
110
+ }
111
+ },
112
+ "ccp" : {
113
+ "separator_before" : true,
114
+ "icon" : false,
115
+ "separator_after" : false,
116
+ "label" : "Edit",
117
+ "action" : false,
118
+ "submenu" : {
119
+ "cut" : {
120
+ "separator_before" : false,
121
+ "separator_after" : false,
122
+ "label" : "Cut",
123
+ "action" : function (data) {
124
+ var inst = $.jstree.reference(data.reference),
125
+ obj = inst.get_node(data.reference);
126
+ if(inst.is_selected(obj)) {
127
+ inst.cut(inst.get_top_selected());
128
+ }
129
+ else {
130
+ inst.cut(obj);
131
+ }
132
+ }
133
+ },
134
+ "copy" : {
135
+ "separator_before" : false,
136
+ "icon" : false,
137
+ "separator_after" : false,
138
+ "label" : "Copy",
139
+ "action" : function (data) {
140
+ var inst = $.jstree.reference(data.reference),
141
+ obj = inst.get_node(data.reference);
142
+ if(inst.is_selected(obj)) {
143
+ inst.copy(inst.get_top_selected());
144
+ }
145
+ else {
146
+ inst.copy(obj);
147
+ }
148
+ }
149
+ },
150
+ "paste" : {
151
+ "separator_before" : false,
152
+ "icon" : false,
153
+ "_disabled" : function (data) {
154
+ return !$.jstree.reference(data.reference).can_paste();
155
+ },
156
+ "separator_after" : false,
157
+ "label" : "Paste",
158
+ "action" : function (data) {
159
+ var inst = $.jstree.reference(data.reference),
160
+ obj = inst.get_node(data.reference);
161
+ inst.paste(obj);
162
+ }
163
+ }
164
+ }
165
+ }
166
+ };
167
+ }
168
+ };
169
+
170
+ $.jstree.plugins.contextmenu = function (options, parent) {
171
+ this.bind = function () {
172
+ parent.bind.call(this);
173
+
174
+ var last_ts = 0, cto = null, ex, ey;
175
+ this.element
176
+ .on("init.jstree loading.jstree ready.jstree", $.proxy(function () {
177
+ this.get_container_ul().addClass('jstree-contextmenu');
178
+ }, this))
179
+ .on("contextmenu.jstree", ".jstree-anchor", $.proxy(function (e, data) {
180
+ if (e.target.tagName.toLowerCase() === 'input') {
181
+ return;
182
+ }
183
+ e.preventDefault();
184
+ last_ts = e.ctrlKey ? +new Date() : 0;
185
+ if(data || cto) {
186
+ last_ts = (+new Date()) + 10000;
187
+ }
188
+ if(cto) {
189
+ clearTimeout(cto);
190
+ }
191
+ if(!this.is_loading(e.currentTarget)) {
192
+ this.show_contextmenu(e.currentTarget, e.pageX, e.pageY, e);
193
+ }
194
+ }, this))
195
+ .on("click.jstree", ".jstree-anchor", $.proxy(function (e) {
196
+ if(this._data.contextmenu.visible && (!last_ts || (+new Date()) - last_ts > 250)) { // work around safari & macOS ctrl+click
197
+ $.vakata.context.hide();
198
+ }
199
+ last_ts = 0;
200
+ }, this))
201
+ .on("touchstart.jstree", ".jstree-anchor", function (e) {
202
+ if(!e.originalEvent || !e.originalEvent.changedTouches || !e.originalEvent.changedTouches[0]) {
203
+ return;
204
+ }
205
+ ex = e.originalEvent.changedTouches[0].clientX;
206
+ ey = e.originalEvent.changedTouches[0].clientY;
207
+ cto = setTimeout(function () {
208
+ $(e.currentTarget).trigger('contextmenu', true);
209
+ }, 750);
210
+ })
211
+ .on('touchmove.vakata.jstree', function (e) {
212
+ if(cto && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0] && (Math.abs(ex - e.originalEvent.changedTouches[0].clientX) > 10 || Math.abs(ey - e.originalEvent.changedTouches[0].clientY) > 10)) {
213
+ clearTimeout(cto);
214
+ $.vakata.context.hide();
215
+ }
216
+ })
217
+ .on('touchend.vakata.jstree', function (e) {
218
+ if(cto) {
219
+ clearTimeout(cto);
220
+ }
221
+ });
222
+
223
+ /*!
224
+ if(!('oncontextmenu' in document.body) && ('ontouchstart' in document.body)) {
225
+ var el = null, tm = null;
226
+ this.element
227
+ .on("touchstart", ".jstree-anchor", function (e) {
228
+ el = e.currentTarget;
229
+ tm = +new Date();
230
+ $(document).one("touchend", function (e) {
231
+ e.target = document.elementFromPoint(e.originalEvent.targetTouches[0].pageX - window.pageXOffset, e.originalEvent.targetTouches[0].pageY - window.pageYOffset);
232
+ e.currentTarget = e.target;
233
+ tm = ((+(new Date())) - tm);
234
+ if(e.target === el && tm > 600 && tm < 1000) {
235
+ e.preventDefault();
236
+ $(el).trigger('contextmenu', e);
237
+ }
238
+ el = null;
239
+ tm = null;
240
+ });
241
+ });
242
+ }
243
+ */
244
+ $(document).on("context_hide.vakata.jstree", $.proxy(function (e, data) {
245
+ this._data.contextmenu.visible = false;
246
+ $(data.reference).removeClass('jstree-context');
247
+ }, this));
248
+ };
249
+ this.teardown = function () {
250
+ if(this._data.contextmenu.visible) {
251
+ $.vakata.context.hide();
252
+ }
253
+ parent.teardown.call(this);
254
+ };
255
+
256
+ /**
257
+ * prepare and show the context menu for a node
258
+ * @name show_contextmenu(obj [, x, y])
259
+ * @param {mixed} obj the node
260
+ * @param {Number} x the x-coordinate relative to the document to show the menu at
261
+ * @param {Number} y the y-coordinate relative to the document to show the menu at
262
+ * @param {Object} e the event if available that triggered the contextmenu
263
+ * @plugin contextmenu
264
+ * @trigger show_contextmenu.jstree
265
+ */
266
+ this.show_contextmenu = function (obj, x, y, e) {
267
+ obj = this.get_node(obj);
268
+ if(!obj || obj.id === $.jstree.root) { return false; }
269
+ var s = this.settings.contextmenu,
270
+ d = this.get_node(obj, true),
271
+ a = d.children(".jstree-anchor"),
272
+ o = false,
273
+ i = false;
274
+ if(s.show_at_node || x === undefined || y === undefined) {
275
+ o = a.offset();
276
+ x = o.left;
277
+ y = o.top + this._data.core.li_height;
278
+ }
279
+ if(this.settings.contextmenu.select_node && !this.is_selected(obj)) {
280
+ this.activate_node(obj, e);
281
+ }
282
+
283
+ i = s.items;
284
+ if($.isFunction(i)) {
285
+ i = i.call(this, obj, $.proxy(function (i) {
286
+ this._show_contextmenu(obj, x, y, i);
287
+ }, this));
288
+ }
289
+ if($.isPlainObject(i)) {
290
+ this._show_contextmenu(obj, x, y, i);
291
+ }
292
+ };
293
+ /**
294
+ * show the prepared context menu for a node
295
+ * @name _show_contextmenu(obj, x, y, i)
296
+ * @param {mixed} obj the node
297
+ * @param {Number} x the x-coordinate relative to the document to show the menu at
298
+ * @param {Number} y the y-coordinate relative to the document to show the menu at
299
+ * @param {Number} i the object of items to show
300
+ * @plugin contextmenu
301
+ * @trigger show_contextmenu.jstree
302
+ * @private
303
+ */
304
+ this._show_contextmenu = function (obj, x, y, i) {
305
+ var d = this.get_node(obj, true),
306
+ a = d.children(".jstree-anchor");
307
+ $(document).one("context_show.vakata.jstree", $.proxy(function (e, data) {
308
+ var cls = 'jstree-contextmenu jstree-' + this.get_theme() + '-contextmenu';
309
+ $(data.element).addClass(cls);
310
+ a.addClass('jstree-context');
311
+ }, this));
312
+ this._data.contextmenu.visible = true;
313
+ $.vakata.context.show(a, { 'x' : x, 'y' : y }, i);
314
+ /**
315
+ * triggered when the contextmenu is shown for a node
316
+ * @event
317
+ * @name show_contextmenu.jstree
318
+ * @param {Object} node the node
319
+ * @param {Number} x the x-coordinate of the menu relative to the document
320
+ * @param {Number} y the y-coordinate of the menu relative to the document
321
+ * @plugin contextmenu
322
+ */
323
+ this.trigger('show_contextmenu', { "node" : obj, "x" : x, "y" : y });
324
+ };
325
+ };
326
+
327
+ // contextmenu helper
328
+ (function ($) {
329
+ var right_to_left = false,
330
+ vakata_context = {
331
+ element : false,
332
+ reference : false,
333
+ position_x : 0,
334
+ position_y : 0,
335
+ items : [],
336
+ html : "",
337
+ is_visible : false
338
+ };
339
+
340
+ $.vakata.context = {
341
+ settings : {
342
+ hide_onmouseleave : 0,
343
+ icons : true
344
+ },
345
+ _trigger : function (event_name) {
346
+ $(document).triggerHandler("context_" + event_name + ".vakata", {
347
+ "reference" : vakata_context.reference,
348
+ "element" : vakata_context.element,
349
+ "position" : {
350
+ "x" : vakata_context.position_x,
351
+ "y" : vakata_context.position_y
352
+ }
353
+ });
354
+ },
355
+ _execute : function (i) {
356
+ i = vakata_context.items[i];
357
+ return i && (!i._disabled || ($.isFunction(i._disabled) && !i._disabled({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }))) && i.action ? i.action.call(null, {
358
+ "item" : i,
359
+ "reference" : vakata_context.reference,
360
+ "element" : vakata_context.element,
361
+ "position" : {
362
+ "x" : vakata_context.position_x,
363
+ "y" : vakata_context.position_y
364
+ }
365
+ }) : false;
366
+ },
367
+ _parse : function (o, is_callback) {
368
+ if(!o) { return false; }
369
+ if(!is_callback) {
370
+ vakata_context.html = "";
371
+ vakata_context.items = [];
372
+ }
373
+ var str = "",
374
+ sep = false,
375
+ tmp;
376
+
377
+ if(is_callback) { str += "<"+"ul>"; }
378
+ $.each(o, function (i, val) {
379
+ if(!val) { return true; }
380
+ vakata_context.items.push(val);
381
+ if(!sep && val.separator_before) {
382
+ str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + ">&#160;<"+"/a><"+"/li>";
383
+ }
384
+ sep = false;
385
+ str += "<"+"li class='" + (val._class || "") + (val._disabled === true || ($.isFunction(val._disabled) && val._disabled({ "item" : val, "reference" : vakata_context.reference, "element" : vakata_context.element })) ? " vakata-contextmenu-disabled " : "") + "' "+(val.shortcut?" data-shortcut='"+val.shortcut+"' ":'')+">";
386
+ str += "<"+"a href='#' rel='" + (vakata_context.items.length - 1) + "' " + (val.title ? "title='" + val.title + "'" : "") + ">";
387
+ if($.vakata.context.settings.icons) {
388
+ str += "<"+"i ";
389
+ if(val.icon) {
390
+ if(val.icon.indexOf("/") !== -1 || val.icon.indexOf(".") !== -1) { str += " style='background:url(\"" + val.icon + "\") center center no-repeat' "; }
391
+ else { str += " class='" + val.icon + "' "; }
392
+ }
393
+ str += "><"+"/i><"+"span class='vakata-contextmenu-sep'>&#160;<"+"/span>";
394
+ }
395
+ str += ($.isFunction(val.label) ? val.label({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }) : val.label) + (val.shortcut?' <span class="vakata-contextmenu-shortcut vakata-contextmenu-shortcut-'+val.shortcut+'">'+ (val.shortcut_label || '') +'</span>':'') + "<"+"/a>";
396
+ if(val.submenu) {
397
+ tmp = $.vakata.context._parse(val.submenu, true);
398
+ if(tmp) { str += tmp; }
399
+ }
400
+ str += "<"+"/li>";
401
+ if(val.separator_after) {
402
+ str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + ">&#160;<"+"/a><"+"/li>";
403
+ sep = true;
404
+ }
405
+ });
406
+ str = str.replace(/<li class\='vakata-context-separator'\><\/li\>$/,"");
407
+ if(is_callback) { str += "</ul>"; }
408
+ /**
409
+ * triggered on the document when the contextmenu is parsed (HTML is built)
410
+ * @event
411
+ * @plugin contextmenu
412
+ * @name context_parse.vakata
413
+ * @param {jQuery} reference the element that was right clicked
414
+ * @param {jQuery} element the DOM element of the menu itself
415
+ * @param {Object} position the x & y coordinates of the menu
416
+ */
417
+ if(!is_callback) { vakata_context.html = str; $.vakata.context._trigger("parse"); }
418
+ return str.length > 10 ? str : false;
419
+ },
420
+ _show_submenu : function (o) {
421
+ o = $(o);
422
+ if(!o.length || !o.children("ul").length) { return; }
423
+ var e = o.children("ul"),
424
+ xl = o.offset().left,
425
+ x = xl + o.outerWidth(),
426
+ y = o.offset().top,
427
+ w = e.width(),
428
+ h = e.height(),
429
+ dw = $(window).width() + $(window).scrollLeft(),
430
+ dh = $(window).height() + $(window).scrollTop();
431
+ // може да се спести е една проверка - дали няма някой от класовете вече нагоре
432
+ if(right_to_left) {
433
+ o[x - (w + 10 + o.outerWidth()) < 0 ? "addClass" : "removeClass"]("vakata-context-left");
434
+ }
435
+ else {
436
+ o[x + w > dw && xl > dw - x ? "addClass" : "removeClass"]("vakata-context-right");
437
+ }
438
+ if(y + h + 10 > dh) {
439
+ e.css("bottom","-1px");
440
+ }
441
+
442
+ //if does not fit - stick it to the side
443
+ if (o.hasClass('vakata-context-right')) {
444
+ if (xl < w) {
445
+ e.css("margin-right", xl - w);
446
+ }
447
+ } else {
448
+ if (dw - x < w) {
449
+ e.css("margin-left", dw - x - w);
450
+ }
451
+ }
452
+
453
+ e.show();
454
+ },
455
+ show : function (reference, position, data) {
456
+ var o, e, x, y, w, h, dw, dh, cond = true;
457
+ if(vakata_context.element && vakata_context.element.length) {
458
+ vakata_context.element.width('');
459
+ }
460
+ switch(cond) {
461
+ case (!position && !reference):
462
+ return false;
463
+ case (!!position && !!reference):
464
+ vakata_context.reference = reference;
465
+ vakata_context.position_x = position.x;
466
+ vakata_context.position_y = position.y;
467
+ break;
468
+ case (!position && !!reference):
469
+ vakata_context.reference = reference;
470
+ o = reference.offset();
471
+ vakata_context.position_x = o.left + reference.outerHeight();
472
+ vakata_context.position_y = o.top;
473
+ break;
474
+ case (!!position && !reference):
475
+ vakata_context.position_x = position.x;
476
+ vakata_context.position_y = position.y;
477
+ break;
478
+ }
479
+ if(!!reference && !data && $(reference).data('vakata_contextmenu')) {
480
+ data = $(reference).data('vakata_contextmenu');
481
+ }
482
+ if($.vakata.context._parse(data)) {
483
+ vakata_context.element.html(vakata_context.html);
484
+ }
485
+ if(vakata_context.items.length) {
486
+ vakata_context.element.appendTo(document.body);
487
+ e = vakata_context.element;
488
+ x = vakata_context.position_x;
489
+ y = vakata_context.position_y;
490
+ w = e.width();
491
+ h = e.height();
492
+ dw = $(window).width() + $(window).scrollLeft();
493
+ dh = $(window).height() + $(window).scrollTop();
494
+ if(right_to_left) {
495
+ x -= (e.outerWidth() - $(reference).outerWidth());
496
+ if(x < $(window).scrollLeft() + 20) {
497
+ x = $(window).scrollLeft() + 20;
498
+ }
499
+ }
500
+ if(x + w + 20 > dw) {
501
+ x = dw - (w + 20);
502
+ }
503
+ if(y + h + 20 > dh) {
504
+ y = dh - (h + 20);
505
+ }
506
+
507
+ vakata_context.element
508
+ .css({ "left" : x, "top" : y })
509
+ .show()
510
+ .find('a').first().focus().parent().addClass("vakata-context-hover");
511
+ vakata_context.is_visible = true;
512
+ /**
513
+ * triggered on the document when the contextmenu is shown
514
+ * @event
515
+ * @plugin contextmenu
516
+ * @name context_show.vakata
517
+ * @param {jQuery} reference the element that was right clicked
518
+ * @param {jQuery} element the DOM element of the menu itself
519
+ * @param {Object} position the x & y coordinates of the menu
520
+ */
521
+ $.vakata.context._trigger("show");
522
+ }
523
+ },
524
+ hide : function () {
525
+ if(vakata_context.is_visible) {
526
+ vakata_context.element.hide().find("ul").hide().end().find(':focus').blur().end().detach();
527
+ vakata_context.is_visible = false;
528
+ /**
529
+ * triggered on the document when the contextmenu is hidden
530
+ * @event
531
+ * @plugin contextmenu
532
+ * @name context_hide.vakata
533
+ * @param {jQuery} reference the element that was right clicked
534
+ * @param {jQuery} element the DOM element of the menu itself
535
+ * @param {Object} position the x & y coordinates of the menu
536
+ */
537
+ $.vakata.context._trigger("hide");
538
+ }
539
+ }
540
+ };
541
+ $(function () {
542
+ right_to_left = $(document.body).css("direction") === "rtl";
543
+ var to = false;
544
+
545
+ vakata_context.element = $("<ul class='vakata-context'></ul>");
546
+ vakata_context.element
547
+ .on("mouseenter", "li", function (e) {
548
+ e.stopImmediatePropagation();
549
+
550
+ if($.contains(this, e.relatedTarget)) {
551
+ // премахнато заради delegate mouseleave по-долу
552
+ // $(this).find(".vakata-context-hover").removeClass("vakata-context-hover");
553
+ return;
554
+ }
555
+
556
+ if(to) { clearTimeout(to); }
557
+ vakata_context.element.find(".vakata-context-hover").removeClass("vakata-context-hover").end();
558
+
559
+ $(this)
560
+ .siblings().find("ul").hide().end().end()
561
+ .parentsUntil(".vakata-context", "li").addBack().addClass("vakata-context-hover");
562
+ $.vakata.context._show_submenu(this);
563
+ })
564
+ // тестово - дали не натоварва?
565
+ .on("mouseleave", "li", function (e) {
566
+ if($.contains(this, e.relatedTarget)) { return; }
567
+ $(this).find(".vakata-context-hover").addBack().removeClass("vakata-context-hover");
568
+ })
569
+ .on("mouseleave", function (e) {
570
+ $(this).find(".vakata-context-hover").removeClass("vakata-context-hover");
571
+ if($.vakata.context.settings.hide_onmouseleave) {
572
+ to = setTimeout(
573
+ (function (t) {
574
+ return function () { $.vakata.context.hide(); };
575
+ }(this)), $.vakata.context.settings.hide_onmouseleave);
576
+ }
577
+ })
578
+ .on("click", "a", function (e) {
579
+ e.preventDefault();
580
+ //})
581
+ //.on("mouseup", "a", function (e) {
582
+ if(!$(this).blur().parent().hasClass("vakata-context-disabled") && $.vakata.context._execute($(this).attr("rel")) !== false) {
583
+ $.vakata.context.hide();
584
+ }
585
+ })
586
+ .on('keydown', 'a', function (e) {
587
+ var o = null;
588
+ switch(e.which) {
589
+ case 13:
590
+ case 32:
591
+ e.type = "click";
592
+ e.preventDefault();
593
+ $(e.currentTarget).trigger(e);
594
+ break;
595
+ case 37:
596
+ if(vakata_context.is_visible) {
597
+ vakata_context.element.find(".vakata-context-hover").last().closest("li").first().find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover").end().end().children('a').focus();
598
+ e.stopImmediatePropagation();
599
+ e.preventDefault();
600
+ }
601
+ break;
602
+ case 38:
603
+ if(vakata_context.is_visible) {
604
+ o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").prevAll("li:not(.vakata-context-separator)").first();
605
+ if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").last(); }
606
+ o.addClass("vakata-context-hover").children('a').focus();
607
+ e.stopImmediatePropagation();
608
+ e.preventDefault();
609
+ }
610
+ break;
611
+ case 39:
612
+ if(vakata_context.is_visible) {
613
+ vakata_context.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover").children('a').focus();
614
+ e.stopImmediatePropagation();
615
+ e.preventDefault();
616
+ }
617
+ break;
618
+ case 40:
619
+ if(vakata_context.is_visible) {
620
+ o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").nextAll("li:not(.vakata-context-separator)").first();
621
+ if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").first(); }
622
+ o.addClass("vakata-context-hover").children('a').focus();
623
+ e.stopImmediatePropagation();
624
+ e.preventDefault();
625
+ }
626
+ break;
627
+ case 27:
628
+ $.vakata.context.hide();
629
+ e.preventDefault();
630
+ break;
631
+ default:
632
+ //console.log(e.which);
633
+ break;
634
+ }
635
+ })
636
+ .on('keydown', function (e) {
637
+ e.preventDefault();
638
+ var a = vakata_context.element.find('.vakata-contextmenu-shortcut-' + e.which).parent();
639
+ if(a.parent().not('.vakata-context-disabled')) {
640
+ a.click();
641
+ }
642
+ });
643
+
644
+ $(document)
645
+ .on("mousedown.vakata.jstree", function (e) {
646
+ if(vakata_context.is_visible && vakata_context.element[0] !== e.target && !$.contains(vakata_context.element[0], e.target)) {
647
+ $.vakata.context.hide();
648
+ }
649
+ })
650
+ .on("context_show.vakata.jstree", function (e, data) {
651
+ vakata_context.element.find("li:has(ul)").children("a").addClass("vakata-context-parent");
652
+ if(right_to_left) {
653
+ vakata_context.element.addClass("vakata-context-rtl").css("direction", "rtl");
654
+ }
655
+ // also apply a RTL class?
656
+ vakata_context.element.find("ul").hide().end();
657
+ });
658
+ });
659
+ }($));
660
+ // $.jstree.defaults.plugins.push("contextmenu");
661
+ }));