PageSourceSearch

https://nextcloud.naturfreunde-koeln.de/apps/files_rightclick/js/script.js?v=a3ac0fb4-1

js naturfreunde-koeln.de collected 2026-10-05 03:43:01 UTC 14,871 bytes, 492 lines download raw bytes

1var RightClick = RightClick || {};
2
3(function(window, $, exports, undefined) {
4    'use strict';
5
6    exports.appName = 'files_rightclick';
7    exports.selectors = {
8        containerId: 'rightClickMenus',
9        detectorId: 'rightClickDetector',
10        menuId: 'rightClickMenu',
11        menuClass: 'rightClickMenu',
12        subMenuClass: 'rightClickSubMenu',
13        openedClass: 'rightClickOpened',
14        arrowClass: 'rightClickArrow',
15    };
16    exports.handableKeys = [
17        'ctrl', 'shift', 'alt'
18    ];
19
20    // Object where all options are listed for one (sub)menu
21    exports.Options = function (options) {
22        this.options = [];
23
24        this.getIndexFromOptionName = function (name) {
25            return this.getNbrOfOptions(); // TODO
26        };
27
28        // Add one or more options
29        this.add = function (options, index) {
30            if (!(typeof index === 'number'))
31                index = this.getIndexFromOptionName(index);
32
33            if (index === undefined)
34                index = this.getNbrOfOptions();
35
36            if (typeof options === 'string' || typeof options === 'number')
37                options = new exports.Option(options);
38
39            if (options instanceof exports.Option)
40                this.options.splice(index, 0, options);
41            else if (options !== undefined && Array.isArray(options)) {
42                for (var name in options) {
43                    var option = options[name];
44
45                    if (typeof option !== 'function') {
46                        if (typeof option === 'string' || typeof option === 'number')
47                            option = new exports.Option(option);
48                    }
49
50                    if (option instanceof exports.Option)
51                        this.options.splice(index, 0, option);
52                }
53            }
54
55            return this;
56        };
57
58        this.prepend = function (options) {
59            return this.add(options, 0);
60        };
61
62        this.append = function (options) {
63            return this.add(options, this.getNbrOfOptions());
64        };
65
66        // Generate all html options
67        this.generate = function () {
68            var ul = $('<ul>');
69
70            for (var name in this.options) {
71                var li = this.options[name].generate();
72
73                if (li) {
74                    li.addClass('action-' + name);
75                    ul.append(li);
76                }
77            }
78
79            return ul;
80        };
81
82        this.getNbrOfOptions = function () {
83            return this.options.length;
84        };
85
86        this.isDisabled = function () {
87            for (var name in this.options) {
88                if (!this.options[name].isDisabled())
89                    return false;
90            }
91
92            return true;
93        };
94
95        this.isFirstDisabled = function () {
96            if (this.getNbrOfOptions() === 0)
97                return true;
98            else
99                return this.options[Object.keys(this.options)[0]].isDisabled();
100        };
101
102        this.add(options);
103    };
104
105    exports.Option = function (name, text, icon, onClick, subOptions) {
106        this.name = name;
107        this.text = text;
108        this.icon = icon;
109        this.onClick = onClick;
110        this.subOptions = subOptions;
111        var option = this;
112
113        this.printIfAppEnabled = function (appName) {
114            this.appName = appName;
115            this.printIfNoApp = false;
116        }
117
118        this.enableIfAppEnabled = function (appName) {
119            this.appName = appName;
120            this.printIfNoApp = true;
121        }
122
123        this.generate = function () {
124            var a = $('<a>', {
125                'class': 'menu-option option-' + this.name.toLowerCase()
126            }).css('width', '100%');
127            var iconSpan = $('<span>', {
128                'class': 'icon ' + this.icon
129            });
130            var textSpan = $('<span>', {
131                'text': this.text,
132            });
133
134            if (this.appName && !this.printIfNoApp && !exports.isAppAvailable(this.appName))
135                return;
136
137            if (this.isDisabled()) {
138                a.attr('disabled', true).css({
139                    'cursor': 'default',
140                    'background-color': '#AAA'
141                });
142
143                iconSpan.css('cursor', 'default');
144                textSpan.css('cursor', 'default');
145            }
146
147            if (typeof this.onClick === 'string') {
148                a.on('click', function (event) {
149                    event.stopPropagation();
150                    event.preventDefault();
151
152                    var $temp = $("<input>");
153                    $("body").append($temp);
154                    $temp.val(option.onClick).select();
155                    document.execCommand("copy");
156                    $temp.remove();
157
158                    var html = textSpan.html();
159                    textSpan.html(t('files_rightclick', 'Copied !'));
160
161                    setTimeout(function () {
162                        textSpan.html(html);
163                    }, 1000);
164                });
165            }
166            else {
167                a.on('click', function (event) {
168                    event.stopPropagation();
169                    event.preventDefault();
170
171                    exports.closeAllMenus();
172
173                    onClick(event, option);
174                });
175            }
176
177
178            var li = $('<li>').append(a.append(iconSpan).append(textSpan));
179
180            if (this.subOptions instanceof exports.Options && this.subOptions.getNbrOfOptions() > 0) {
181                var sub = $('<a>').append($('<span>').text('▶')
182                    .css('padding-right', '10px')).addClass(exports.selectors.arrowClass)
183                    .attr('style', 'width: auto; padding-right: 0px !important');
184
185                new exports.Menu(sub, this.subOptions, li).setAsSubMenu().setAlsoOnHover().setAlsoOnLeftClick();
186                li.append(sub);
187            }
188
189            return li;
190        };
191
192        this.isDisabled = function () {
193            if (this.appName && !exports.isAppAvailable(this.appName))
194                return true;
195
196            return this.onClick === undefined;
197        };
198    };
199
200    exports.menus = [];
201    exports.Menu = function (delimiter, options, context, onClose, handledKeys) {
202        this.delimiter = $(delimiter);
203        this.context = context;
204        this.currentContext = undefined;
205        this.options = options || new exports.Options();
206        this.onClose = onClose;
207
208        this.isSubMenu = false;
209
210        if (delimiter === undefined)
211            return undefined;
212
213        // Allow onClick function to access to menu data
214        var menu = this;
215
216        this.setContext = function (context) {
217            this.context = context;
218
219            return this;
220        };
221
222        this.isOpened = function () {
223            return this.element !== undefined;
224        }
225
226        this.handleKeys = function (handledKeys) {
227            this.handledKeys = {};
228            handledKeys = handledKeys || {};
229
230            for (var key in exports.handableKeys) {
231                var keyName = exports.handableKeys[key];
232
233                this.handledKeys[keyName] = handledKeys[keyName] || false;
234            }
235        };
236        this.handleKeys(handledKeys);
237
238        var onClick = function (event, originalEvent) {
239            for (var key in exports.handableKeys) {
240                var keyName = exports.handableKeys[key];
241                var targetedEvent = originalEvent || event;
242
243                if (targetedEvent[keyName + 'Key'] && !menu.handledKeys[keyName]) {
244                    return true;
245                }
246            }
247
248            event.stopPropagation();
249            event.preventDefault();
250
251            if (originalEvent) {
252                event.clientX = originalEvent.clientX;
253                event.clientY = originalEvent.clientY;
254            }
255
256            var delimiter = $(this);
257            var context = menu.context;
258            var options = menu.options;
259            var params = menu.params;
260
261            if (menu.isSubMenu) {
262                if (!exports.closeAllSubMenus()) {
263                    return !exports.clean();
264                }
265            }
266            else if (!exports.closeAllMenus()) {
267                return !exports.clean();
268            }
269
270            if (menu.isOpened()) {
271                return !exports.clean();
272            }
273
274            exports.prepare();
275
276            menu.attachedEvent = event;
277
278            if (typeof context === "function")
279                context = context(event);
280
281            context = (context === undefined) ? delimiter : $(context[0]);
282            menu.currentContext = context;
283
284            if (typeof options === "function")
285                options = options(event, context, delimiter);
286
287            if (options.getNbrOfOptions() === 0) {
288                return !exports.clean();
289            }
290
291            var className = exports.selectors.menuClass + ' bubble open';
292
293            menu.element = $('<div>', menu.isSubMenu ? {
294                'class': exports.selectord.subMenuClass +  ' ' + className
295            } : {
296                'id': exports.selectors.menuId,
297                'class': className
298            }).append(options.generate());
299
300            menu.element.appendTo(exports.container);
301
302            if (menu.isSubMenu) {
303                var menuPosition = context.parents('.rightClick').first().position();
304                var contextPosition = context.position();
305                var top = menuPosition.top - contextPosition.top;
306                var left = menuPosition.left + context.width() + 2;
307            }
308            else {
309                var top = event.clientY - parseInt(menu.element.css("marginTop").replace('px', ''));
310                var left = event.clientX - parseInt(menu.element.css("marginLeft").replace('px', ''));
311            }
312
313            var height = menu.element.outerHeight();
314            var width = menu.element.outerWidth();
315
316            if (left + width >= $(window).width()) {
317                left -= width;
318            }
319            if (top + height >= $(window).height()) {
320                top -= height;
321            }
322
323            if (top < 0) {
324                top = 0;
325            }
326            if (left < 0) {
327                left = 0;
328            }
329
330            menu.element.css({
331                'top': top,
332                'left': left,
333                'right': 'auto',
334            });
335
336            var optionsDisabled = options.isDisabled();
337
338            if (optionsDisabled)
339                menu.element.css('background-color', '#AAA');
340
341            menu.element.on('contextmenu', function () {
342                return false;
343            });
344            menu.element.on('mouseleave', function (event) {
345                if (menu.isOpenedOnHover)
346                    menu.close();
347            });
348
349            return false;
350        };
351
352        this.close = function () {
353            if (!this.isOpened())
354                return true;
355
356            if (this.element) {
357                if (this.onClose) {
358                    if (this.onClose(this.attachedEvent, this.currentContext, this.delimiter) === false)
359                        return false;
360                }
361
362                this.element.remove();
363                delete this.element;
364
365                exports.clean();
366            }
367
368            return true;
369        };
370
371        this.setAlsoOnLeftClick = function () {
372            this.delimiter.on('click', function (event) {
373                if (menu.isOpened() && !menu.isOpenedOnHover) {
374                    menu.close();
375
376                    return false;
377                }
378
379                menu.isOpenedOnHover = false;
380            }).on('click', onClick);
381
382            return this;
383        };
384
385        this.setAlsoOnHover = function () {
386            this.delimiter.on('mouseenter', function (event) {
387                menu.isOpenedOnHover = true;
388            }).on('mouseenter', onClick);
389
390            return this;
391        };
392
393        this.setAsSubMenu = function (isSubMenu) {
394            this.isSubMenu = isSubMenu || true;
395
396            return this;
397        };
398
399        this.delimiter.contextmenu(onClick);
400        exports.menus.push(this);
401    };
402
403    exports.closeAllMenus = function () {
404        for (var key in exports.menus) {
405            if (exports.menus.hasOwnProperty(key)) {
406                if (exports.menus[key].close() === false)
407                    return false;
408            }
409        }
410
411        return true;
412    };
413
414    exports.closeAllSubMenus = function () {
415        for (var key in exports.menus) {
416            if (exports.menus.hasOwnProperty(key)) {
417                if (exports.menus[key].isSubMenu) {
418                    if (exports.menus[key].close() === false)
419                        return false;
420                }
421            }
422        }
423
424        return true;
425    };
426
427    exports.isAMenuOpened = function () {
428        for (var key = 0; key < exports.menus.length; key++) {
429            if (exports.menus[key].isOpened()) {
430                return true;
431            }
432        }
433
434        return false;
435    };
436
437    exports.prepare = function () {
438        if (!exports.isAMenuOpened()) {
439            $(window).on('resize', exports.closeAllMenus);
440            $('body').addClass(exports.selectors.openedClass);
441        }
442
443        $('#' + exports.selectors.detectorId).css('display', 'block');
444    }
445
446    exports.onKeyUp = function (event) {
447        event = event || window.event;
448        var isEscape = false;
449
450        if ("key" in event) {
451            isEscape = (event.key == "Escape" || event.key == "Esc");
452        } else {
453            isEscape = (event.keyCode === 27);
454        }
455
456        if (isEscape) {
457            if (exports.isAMenuOpened()) {
458                exports.closeAllMenus();
459
460                event.stopPropagation();
461            }
462        }
463    };
464
465    exports.clean = function () {
466        if (!exports.isAMenuOpened()) {
467            $(window).off('resize', exports.closeAllMenus);
468            $('body').removeClass(exports.selectors.openedClass);
469            $('#' + exports.selectors.detectorId).css('display', 'none');
470
471            return true;
472        }
473
474        return false;
475    };
476
477    exports.propagateRightClick = function (event) {
478        exports.closeAllMenus();
479        event.preventDefault();
480        event.stopPropagation();
481
482        $(document.elementFromPoint(event.clientX, event.clientY)).trigger('contextmenu', event);
483    }
484
485    exports.container = $('<div id="' + exports.selectors.containerId + '"></div>').appendTo('body');
486    exports.detector = $('<div id="' + exports.selectors.detectorId + '"></div>').appendTo('body');
487
488    exports.detector.on('click resize', exports.closeAllMenus);
489    exports.detector.on('contextmenu', exports.propagateRightClick);
490
491    document.onkeyup = exports.onKeyUp;
492})(window, jQuery, RightClick);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.