corrade-nucleus-nucleons – Blame information for rev 24
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
20 | office | 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) > 50 || Math.abs(ey - e.originalEvent.changedTouches[0].clientY) > 50)) { |
||
213 | clearTimeout(cto); |
||
214 | } |
||
215 | }) |
||
216 | .on('touchend.vakata.jstree', function (e) { |
||
217 | if(cto) { |
||
218 | clearTimeout(cto); |
||
219 | } |
||
220 | }); |
||
221 | |||
222 | /*! |
||
223 | if(!('oncontextmenu' in document.body) && ('ontouchstart' in document.body)) { |
||
224 | var el = null, tm = null; |
||
225 | this.element |
||
226 | .on("touchstart", ".jstree-anchor", function (e) { |
||
227 | el = e.currentTarget; |
||
228 | tm = +new Date(); |
||
229 | $(document).one("touchend", function (e) { |
||
230 | e.target = document.elementFromPoint(e.originalEvent.targetTouches[0].pageX - window.pageXOffset, e.originalEvent.targetTouches[0].pageY - window.pageYOffset); |
||
231 | e.currentTarget = e.target; |
||
232 | tm = ((+(new Date())) - tm); |
||
233 | if(e.target === el && tm > 600 && tm < 1000) { |
||
234 | e.preventDefault(); |
||
235 | $(el).trigger('contextmenu', e); |
||
236 | } |
||
237 | el = null; |
||
238 | tm = null; |
||
239 | }); |
||
240 | }); |
||
241 | } |
||
242 | */ |
||
243 | $(document).on("context_hide.vakata.jstree", $.proxy(function (e, data) { |
||
244 | this._data.contextmenu.visible = false; |
||
245 | $(data.reference).removeClass('jstree-context'); |
||
246 | }, this)); |
||
247 | }; |
||
248 | this.teardown = function () { |
||
249 | if(this._data.contextmenu.visible) { |
||
250 | $.vakata.context.hide(); |
||
251 | } |
||
252 | parent.teardown.call(this); |
||
253 | }; |
||
254 | |||
255 | /** |
||
256 | * prepare and show the context menu for a node |
||
257 | * @name show_contextmenu(obj [, x, y]) |
||
258 | * @param {mixed} obj the node |
||
259 | * @param {Number} x the x-coordinate relative to the document to show the menu at |
||
260 | * @param {Number} y the y-coordinate relative to the document to show the menu at |
||
261 | * @param {Object} e the event if available that triggered the contextmenu |
||
262 | * @plugin contextmenu |
||
263 | * @trigger show_contextmenu.jstree |
||
264 | */ |
||
265 | this.show_contextmenu = function (obj, x, y, e) { |
||
266 | obj = this.get_node(obj); |
||
267 | if(!obj || obj.id === $.jstree.root) { return false; } |
||
268 | var s = this.settings.contextmenu, |
||
269 | d = this.get_node(obj, true), |
||
270 | a = d.children(".jstree-anchor"), |
||
271 | o = false, |
||
272 | i = false; |
||
273 | if(s.show_at_node || x === undefined || y === undefined) { |
||
274 | o = a.offset(); |
||
275 | x = o.left; |
||
276 | y = o.top + this._data.core.li_height; |
||
277 | } |
||
278 | if(this.settings.contextmenu.select_node && !this.is_selected(obj)) { |
||
279 | this.activate_node(obj, e); |
||
280 | } |
||
281 | |||
282 | i = s.items; |
||
283 | if($.isFunction(i)) { |
||
284 | i = i.call(this, obj, $.proxy(function (i) { |
||
285 | this._show_contextmenu(obj, x, y, i); |
||
286 | }, this)); |
||
287 | } |
||
288 | if($.isPlainObject(i)) { |
||
289 | this._show_contextmenu(obj, x, y, i); |
||
290 | } |
||
291 | }; |
||
292 | /** |
||
293 | * show the prepared context menu for a node |
||
294 | * @name _show_contextmenu(obj, x, y, i) |
||
295 | * @param {mixed} obj the node |
||
296 | * @param {Number} x the x-coordinate relative to the document to show the menu at |
||
297 | * @param {Number} y the y-coordinate relative to the document to show the menu at |
||
298 | * @param {Number} i the object of items to show |
||
299 | * @plugin contextmenu |
||
300 | * @trigger show_contextmenu.jstree |
||
301 | * @private |
||
302 | */ |
||
303 | this._show_contextmenu = function (obj, x, y, i) { |
||
304 | var d = this.get_node(obj, true), |
||
305 | a = d.children(".jstree-anchor"); |
||
306 | $(document).one("context_show.vakata.jstree", $.proxy(function (e, data) { |
||
307 | var cls = 'jstree-contextmenu jstree-' + this.get_theme() + '-contextmenu'; |
||
308 | $(data.element).addClass(cls); |
||
309 | a.addClass('jstree-context'); |
||
310 | }, this)); |
||
311 | this._data.contextmenu.visible = true; |
||
312 | $.vakata.context.show(a, { 'x' : x, 'y' : y }, i); |
||
313 | /** |
||
314 | * triggered when the contextmenu is shown for a node |
||
315 | * @event |
||
316 | * @name show_contextmenu.jstree |
||
317 | * @param {Object} node the node |
||
318 | * @param {Number} x the x-coordinate of the menu relative to the document |
||
319 | * @param {Number} y the y-coordinate of the menu relative to the document |
||
320 | * @plugin contextmenu |
||
321 | */ |
||
322 | this.trigger('show_contextmenu', { "node" : obj, "x" : x, "y" : y }); |
||
323 | }; |
||
324 | }; |
||
325 | |||
326 | // contextmenu helper |
||
327 | (function ($) { |
||
328 | var right_to_left = false, |
||
329 | vakata_context = { |
||
330 | element : false, |
||
331 | reference : false, |
||
332 | position_x : 0, |
||
333 | position_y : 0, |
||
334 | items : [], |
||
335 | html : "", |
||
336 | is_visible : false |
||
337 | }; |
||
338 | |||
339 | $.vakata.context = { |
||
340 | settings : { |
||
341 | hide_onmouseleave : 0, |
||
342 | icons : true |
||
343 | }, |
||
344 | _trigger : function (event_name) { |
||
345 | $(document).triggerHandler("context_" + event_name + ".vakata", { |
||
346 | "reference" : vakata_context.reference, |
||
347 | "element" : vakata_context.element, |
||
348 | "position" : { |
||
349 | "x" : vakata_context.position_x, |
||
350 | "y" : vakata_context.position_y |
||
351 | } |
||
352 | }); |
||
353 | }, |
||
354 | _execute : function (i) { |
||
355 | i = vakata_context.items[i]; |
||
356 | 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, { |
||
357 | "item" : i, |
||
358 | "reference" : vakata_context.reference, |
||
359 | "element" : vakata_context.element, |
||
360 | "position" : { |
||
361 | "x" : vakata_context.position_x, |
||
362 | "y" : vakata_context.position_y |
||
363 | } |
||
364 | }) : false; |
||
365 | }, |
||
366 | _parse : function (o, is_callback) { |
||
367 | if(!o) { return false; } |
||
368 | if(!is_callback) { |
||
369 | vakata_context.html = ""; |
||
370 | vakata_context.items = []; |
||
371 | } |
||
372 | var str = "", |
||
373 | sep = false, |
||
374 | tmp; |
||
375 | |||
376 | if(is_callback) { str += "<"+"ul>"; } |
||
377 | $.each(o, function (i, val) { |
||
378 | if(!val) { return true; } |
||
379 | vakata_context.items.push(val); |
||
380 | if(!sep && val.separator_before) { |
||
381 | str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> <"+"/a><"+"/li>"; |
||
382 | } |
||
383 | sep = false; |
||
384 | 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+"' ":'')+">"; |
||
385 | str += "<"+"a href='#' rel='" + (vakata_context.items.length - 1) + "' " + (val.title ? "title='" + val.title + "'" : "") + ">"; |
||
386 | if($.vakata.context.settings.icons) { |
||
387 | str += "<"+"i "; |
||
388 | if(val.icon) { |
||
389 | if(val.icon.indexOf("/") !== -1 || val.icon.indexOf(".") !== -1) { str += " style='background:url(\"" + val.icon + "\") center center no-repeat' "; } |
||
390 | else { str += " class='" + val.icon + "' "; } |
||
391 | } |
||
392 | str += "><"+"/i><"+"span class='vakata-contextmenu-sep'> <"+"/span>"; |
||
393 | } |
||
394 | 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>"; |
||
395 | if(val.submenu) { |
||
396 | tmp = $.vakata.context._parse(val.submenu, true); |
||
397 | if(tmp) { str += tmp; } |
||
398 | } |
||
399 | str += "<"+"/li>"; |
||
400 | if(val.separator_after) { |
||
401 | str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> <"+"/a><"+"/li>"; |
||
402 | sep = true; |
||
403 | } |
||
404 | }); |
||
405 | str = str.replace(/ |
||
406 |
|
||
407 |
|
||
408 |
|
||
409 |
|
||
410 |
|
||
411 |
|
||
412 |
|
||
413 |
|
||
414 |
|
||
415 |
|
||
416 |
|
||
417 |
|
||
418 |
|
||
419 |
|
||
420 |
|
||
421 |
|
||
422 |
|
||
423 |
|
||
424 |
|
||
425 |
|
||
426 |
|
||
427 |
|
||
428 |
|
||
429 |
|
||
430 |
|
||
431 |
|
||
432 |
|
||
433 |
|
||
434 |
|
||
435 |
|
||
436 |
|
||
437 |
|
||
438 |
|
||
439 |
|
||
440 | |||
441 |
|
||
442 |
|
||
443 |
|
||
444 |
|
||
445 |
|
||
446 |
|
||
447 |
|
||
448 |
|
||
449 |
|
||
450 |
|
||
451 | |||
452 |
|
||
453 |
|
||
454 |
|
||
455 |
|
||
456 |
|
||
457 |
|
||
458 |
|
||
459 |
|
||
460 |
|
||
461 |
|
||
462 |
|
||
463 |
|
||
464 |
|
||
465 |
|
||
466 |
|
||
467 |
|
||
468 |
|
||
469 |
|
||
470 |
|
||
471 |
|
||
472 |
|
||
473 |
|
||
474 |
|
||
475 |
|
||
476 |
|
||
477 |
|
||
478 |
|
||
479 |
|
||
480 |
|
||
481 |
|
||
482 |
|
||
483 |
|
||
484 |
|
||
485 |
|
||
486 |
|
||
487 |
|
||
488 |
|
||
489 |
|
||
490 |
|
||
491 |
|
||
492 |
|
||
493 |
|
||
494 |
|
||
495 |
|
||
496 |
|
||
497 |
|
||
498 |
|
||
499 |
|
||
500 |
|
||
501 |
|
||
502 |
|
||
503 |
|
||
504 |
|
||
505 | |||
506 |
|
||
507 |
|
||
508 |
|
||
509 |
|
||
510 |
|
||
511 |
|
||
512 |
|
||
513 |
|
||
514 |
|
||
515 |
|
||
516 |
|
||
517 |
|
||
518 |
|
||
519 |
|
||
520 |
|
||
521 |
|
||
522 |
|
||
523 |
|
||
524 |
|
||
525 |
|
||
526 |
|
||
527 |
|
||
528 |
|
||
529 |
|
||
530 |
|
||
531 |
|
||
532 |
|
||
533 |
|
||
534 |
|
||
535 |
|
||
536 |
|
||
537 |
|
||
538 |
|
||
539 |
|
||
540 |
|
||
541 |
|
||
542 |
|
||
543 | |||
544 |
|
||
545 |
|
||
546 |
|
||
547 |
|
||
548 | |||
549 |
|
||
550 |
|
||
551 |
|
||
552 |
|
||
553 |
|
||
554 | |||
555 |
|
||
556 |
|
||
557 | |||
558 |
|
||
559 |
|
||
560 |
|
||
561 |
|
||
562 |
|
||
563 |
|
||
564 |
|
||
565 |
|
||
566 |
|
||
567 |
|
||
568 |
|
||
569 |
|
||
570 |
|
||
571 |
|
||
572 |
|
||
573 |
|
||
574 |
|
||
575 |
|
||
576 |
|
||
577 |
|
||
578 |
|
||
579 |
|
||
580 |
|
||
581 |
|
||
582 |
|
||
583 |
|
||
584 |
|
||
585 |
|
||
586 |
|
||
587 |
|
||
588 |
|
||
589 |
|
||
590 |
|
||
591 |
|
||
592 |
|
||
593 |
|
||
594 |
|
||
595 |
|
||
596 |
|
||
597 |
|
||
598 |
|
||
599 |
|
||
600 |
|
||
601 |
|
||
602 |
|
||
603 |
|
||
604 |
|
||
605 |
|
||
606 |
|
||
607 |
|
||
608 |
|
||
609 |
|
||
610 |
|
||
611 |
|
||
612 |
|
||
613 |
|
||
614 |
|
||
615 |
|
||
616 |
|
||
617 |
|
||
618 |
|
||
619 |
|
||
620 |
|
||
621 |
|
||
622 |
|
||
623 |
|
||
624 |
|
||
625 |
|
||
626 |
|
||
627 |
|
||
628 |
|
||
629 |
|
||
630 |
|
||
631 |
|
||
632 |
|
||
633 |
|
||
634 |
|
||
635 |
|
||
636 |
|
||
637 |
|
||
638 |
|
||
639 |
|
||
640 |
|
||
641 |
|
||
642 | |||
643 |
|
||
644 |
|
||
645 |
|
||
646 |
|
||
647 |
|
||
648 |
|
||
649 |
|
||
650 |
|
||
651 |
|
||
652 |
|
||
653 |
|
||
654 |
|
||
655 |
|
||
656 |
|
||
657 |
|
||
658 |
|
||
659 |
|
||
660 |
|