PageSourceSearch

https://masterakrasoti.ru/nassets/3e6171b4/js/file-dialog.js?v=1790428180

js masterakrasoti.ru collected 2026-10-08 11:04:06 UTC 29,132 bytes, 780 lines download raw bytes

1window.gcSelectFiles = function( options ) {
2    var type = ('type' in options) ? options.type : 'image';
3    var fileDialogLabel = ('fileDialogLabel' in options) ? options.fileDialogLabel : null;
4    window.canDelete = options.canDelete || false
5    if (fileDialogLabel !== null) {
6        type = fileDialogLabel;
7    }
8    if (!window.gcFileSelectEl) {
9        window.gcFileSelectEl = {};
10    }
11    if (!(type in window.gcFileSelectEl)) {
12        window.gcFileSelectEl[type] = $('<div class="gc-file-dialog"></div>');
13        window.gcFileSelectEl[type].appendTo(window.body);
14        window.gcFileSelectEl[type].gcFileSelector(options);
15    }
16    //window.gcFileSelectEl.gcFileSelector( 'setIsMulti', isMulti )
17    window.gcFileSelectEl[type].gcFileSelector('selectFile', options);
18};
19
20jQuery.widget( 'gc.gcFileSelector', {
21	TYPE_IMAGE: 'image',
22	TYPE_VIDEO: 'video',
23    TYPE_AUDIO: 'audio',
24    options: {
25        isMulti: null,
26		callback: null,
27		type: this.TYPE_IMAGE,
28        overrideDefaultFolder: '',
29		defaultFolder: "recent",
30		accept: '',
31        isShowHint: false,
32        fileDialogLabel: null,
33        extensions: null,
34        forceFileType: null
35    },
36    settingItems: ['frames', 'subtitles', 'grids', 'statistics'],
37	currentFolder: null,
38    currentFolderWidget: null,
39	folders: null,
40    actions: null,
41    directories: {},
42    modal: null,
43	previousModal: null,
44    _create: function () {
45        this.options.type = !this.options.type || this.options.type === undefined
46            ? this.TYPE_IMAGE
47            : this.options.type;
48
49		this.modal = this.createModal();
50		this.modal.getModalEl().addClass('file-dialog-modal')
51        this.modal.getModalEl().css('overflow-y', 'auto')
52        this.modal.setContent("")
53        this.element.appendTo( this.modal.getContentEl() )
54
55		this.createFolders();
56
57        this.createActions();
58        this.createMainStructure();
59        this.loadDirectories();
60
61        //his.addAccordionEventListeners();
62
63        //this.modal.setTitle("Выбор файла")
64        this.modal.getBodyEl().addClass("file-dialog-modal-content")
65
66        if(this.options.overrideDefaultFolder !== '') {
67            this.options.defaultFolder = this.options.overrideDefaultFolder;
68        }
69		this.selectFolder(this.options.defaultFolder, false);
70    },
71	createModal: function() {
72		this.detectPreviousActiveModal();
73		// Тут уже срабатывает установка активной модалки, потому до этого имеет смысл получить текущую активную
74		return window.gcModalFactory.create();
75	},
76	createFolders: function() {
77		if (!this.folders) {
78		    var mainLabel = '';
79		    var mainIcon = '';
80
81		    if (this.options.type === this.TYPE_VIDEO) {
82                mainLabel = window.tt('common', 'Video');
83                mainIcon = 'glyphicon glyphicon-facetime-video';
84            } else if (this.options.type === this.TYPE_AUDIO) {
85                mainLabel = window.tt('common', 'Audio');
86                mainIcon = 'glyphicon glyphicon-volume-up';
87            } else {
88                mainLabel = window.tt('common', 'Images');
89                mainIcon = 'glyphicon glyphicon-camera';
90            }
91
92			this.folders = {
93				/*my: {
94					label: mainLabel,
95					icon: mainIcon,
96					widget: 'gcFileSelectorFolder'
97				},*/
98				recent: {
99					label: window.tt('common', 'Recent'),
100					icon: "glyphicon glyphicon-time",
101					widget: 'gcFileSelectorFolder'
102				},
103				favorites: {
104					label: window.tt('common', 'Favorites'),
105					icon: "glyphicon glyphicon-star",
106					widget: 'gcFileSelectorFolder'
107				}
108			};
109
110			if (this.options.type !== this.TYPE_VIDEO && this.options.type !== this.TYPE_AUDIO) {
111				this.folders = Object.assign({}, this.folders, {
112					cover: {
113						label: window.tt('common', 'Covers'),
114						icon: "glyphicon glyphicon-picture",
115						widget: 'gcFileSelectorFolder'
116					},
117					// pixabay: {
118					// 	label: window.tt('common', 'Photobank'),
119					// 	icon: "glyphicon glyphicon-globe",
120					// 	widget: 'gcFilePixabayFolder'
121					// }
122				});
123			}
124
125			if ( this.options.withIcons ) {
126				this.folders = Object.assign({}, {
127					icons: {
128						label: window.tt('common', 'Icons'),
129						icon: "fa fa-check",
130						widget: 'gcIconForImageSelector'
131					},
132					emoji: {
133						label: "Emoji",
134						icon: "fa fa-smile",
135						widget: 'gcEmojiForImageSelector'
136					}
137				}, this.folders )
138			}
139		}
140	},
141    createActions: function() {
142        if (!this.actions) {
143            var mainLabel = '';
144
145            if (this.options.fileDialogLabel) {
146                mainLabel = window.tt('common', this.options.fileDialogLabel);
147            } else {
148                if (this.options.type === this.TYPE_VIDEO) {
149                    mainLabel = window.tt('common', 'video');
150                } else if (this.options.type === this.TYPE_AUDIO) {
151                    mainLabel = window.tt('common', 'audio');
152                } else if (this.options.type === this.TYPE_RECORD) {
153                    mainLabel = window.tt('common', 'audio');
154                } else {
155                    mainLabel = window.tt('common', 'image');
156                }
157            }
158
159            this.actions = {
160                upload: {
161                    label: "+ " + window.tt('common', 'Add') + " " + mainLabel,
162                    icon: "glyphicon glyphicon-file",
163                    widget: 'gcFileUploader'
164                },
165            };
166
167            // В конструкторе уроков/страниц и т.п. в блоках "видео", и блок "слайдер видео" вывести надпись:
168            if (this.options.type === this.TYPE_VIDEO && this.options.isS
168howHint) {
169                this.actions.upload.hint = window.tt('common', 'Видео будет модифицировано для просмотра на разных устройствах');
170            }
171
172            if (this.options.type === this.TYPE_VIDEO && window.videoLinkFeatureUsed === 1) {
173                this.actions.uploadLinks = {
174                    label: "+ " + window.tt('common', 'Add link') + " " + mainLabel,
175                    icon: "glyphicon glyphicon-file",
176                    widget: 'gcFileUploader'
177                };
178            }
179
180            this.actions.addById = {
181                label: window.tt('common', 'Add by id'),
182                icon: "glyphicon glyphicon-file",
183                widget: 'gcFileUploader'
184            }
185        }
186    },
187    selectFile: function( options ) {
188	    if (this.currentFolder && this.currentFolder.widgetEl) {
189			var folder = this.currentFolder;
190		    if( options.iconParams ) {
191			    folder.widgetEl.data( 'iconParams', options.iconParams )
192		    }
193			folder.widgetEl[folder.widget]('checkNeedToRefresh');
194		}
195
196        this.options = options;
197
198        if ( options.isMulti ) {
199            this.element.addClass( "multi-select-mode" );
200        }
201        else {
202            this.element.removeClass( "multi-select-mode" );
203        }
204        this.showMultiStat();
205
206        var active = window.gcModalActive();
207        if (active && !active.isActive()) {
208            active = null;
209        }
210        this.previousModal = active;
211        this.modal.show();
212
213        this.selectedFilesEl.empty();
214
215        if ( this.options.selectedHash && this.folders['recent'].widgetEl ) {
216            this.folders['recent'].widgetEl.gcFileSelectorFolder( 'setSelectedHash', this.options.selectedHash );
217        }
218	    //if ( this.options.selectedHash && this.folders['my'].widgetEl ) {
219		//    this.folders['my'].widgetEl.gcFileSelectorFolder( 'setSelectedHash', this.options.selectedHash );
220	    //}
221
222        if ( this.options.isMulti && this.options.selected ) {
223            for ( key in this.options.selected ) {
224                var item = this.options.selected[key]
225                if ( item.hash ) {
226                    this.addSelectedFileEl( item.hash, item.caption );
227                }
228            }
229        }
230    },
231	detectPreviousActiveModal: function() {
232		var active = window.gcModalActive();
233		if (active && !active.isActive()) {
234			active = null;
235		}
236		// При создании модалки она уже установилась активной, на этот случай сохраняем предыдущее значение,
237		// кторое записали как раз перед созданием
238		if (!active || !this.modal || active.getId() !== this.modal.getId()) {
239			this.previousModal = active;
240		}
241
242		return this.previousModal;
243	},
244    showMultiStat: function() {
245        var self = this;
246
247        if ( ! this.options.isMulti ) {
248            return false;
249        }
250
251        var selectedFiles = self.selectedFilesEl.find('.selected-file-item')
252
253		self.detailEl.find('.selected-info').html(
254			window.tt('common', 'images selected')
255			+ ": <b>" + selectedFiles.length + "</b>"
256		);
257    },
258
259
260    createMainStructure: function() {
261        var self = this;
262
263        var storageUsagePercent = parseInt(window.storage_usage_percent)
264        var usedStorageSize = self.formatBytes(window.used_storage_size ? parseInt(window.used_storage_size) : 0)
265        var maxStorageSize = self.formatBytes(window.max_storage_size ? parseInt(window.max_storage_size) : 0)
266
267        $layout = $('<div class="file-dialog-layout">' +
268            '<div class="file-dialog-menu">' +
269                '<div class="file-dialog-action-selector"></div>' +
270                '<div class="file-dialog-delimiter"><hr></div>' +
271                '<div class="file-dialog-folder-selector"></div>' +
272			(window.file_upload_blocking_for_admin
273			? ('<div class="file-info-over" style="font-size: smaller;margin:2px;padding-right:11px;padding-left:11px;text-align:center">' +
274			window.tt('common', 'Хранилище заполнено на') + ' ' + window.storage_usage_percent + '%\n' +
275			window.tt('common', 'Чтобы загружать файлы нужно') +
276			' <a href="/saas/account/show?files=1" class="rd-link" target="_blank">' +
277			window.tt('common', 'увеличить объем хранилища') +
278			'</a>'
279			+'</div>') : '')
280			+
281                '<div class="file-dialog-size-progress">' +
282                    '<div class="progress">' +
283                        '<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="' +
284                            storageUsagePercent+'" ' + 'aria-valuemin="0" aria-valuemax="100" style="width:' +
285                            storageUsagePercent+ '%">' +
286                        '</div>' +
287                    '</div>' +
288                    '<div class="progress-text">' + window.tt('common', 'Used') + '<br>' +
289						usedStorageSize + ' ' + window.tt('common', 'from2') + ' ' +
290                        maxStorageSize + '</div>' +
291                '</div>' +
292            '</div>' +
293            '<div class="file-dialog-content"></div></div>')
294        $layout.appendTo( this.element )
295
296        self.actionSelectorEl = $actions = $layout.find('.file-dialog-action-selector')
297        self.folderSelectorEl = $folders = $layout.find('.file-dialog-folder-selector')
298
299        self.contentEl = $layout.find('.file-dialog-content')
300
301		self.detailEl = $('<div class="file-dialog-detail"> <div class="info-div"><button class="btn-confirm btn btn-success">'
302			+ window.tt('common', 'Confirm selection')
303			+ '</button> <span class="selected-info"></span></div> <div class="selected-files-list"></div></div>'
304		);
305        self.detailEl.prependTo( this.element )
306
307        self.selectedFilesEl = self.detailEl.find( '.selected-files-list' );
308
309        self.btnConfirm = self.detailEl.find('.btn-confirm')
310        self.btnConfirm.click( function() {
311            var selectedFiles = []
312            self.selectedFilesEl.find('.selected-file-item').each( function() {
313                selectedFiles.push( {
314                    hash: $(this).data('hash'),
315                    caption: $(this).find('input').val()
316                })
317            })
318
319            self.options.callback( selectedFiles );
320            self.modal.hide();
321        })
322
323        if( self.isMobile() ) {
324          self.folderSelectorEl.css('display', 'none')
325          self.contentEl.css('margin-left', '0%')
326        }
327
328        for (key in this.actions) {
329            var action = this.actions[key]
330            $wrapper = $('<div></div>')
331            if (key === 'upload') {
332                $actionEl = $('<div class="folder-action"> ' + action.label + '</div>')
333				let colorGray = 'rgb(222, 222, 222)';
334                $actionEl.addClass('folder-action-' + key)
335                $actionEl.addClass('btn')
336                $actionEl.addClass(window.file_upload_blocking_for_admin ? 'btn-default' : 'btn-success')
337
338                $actionEl.mouseenter(function () {
339                    $(this).css('background-color', window.file_upload_blocking_for_admin ? colorGray : '#0cc57c');
340                });
341
342                $actionEl.mouseleave(function () {
343                    $(this).css('background-color',  window.file_upload_blocking_for_admin ? colorGray : '#199c68');
344                });
345
346                $actionEl.css('border', '1px solid')
347                if (self.options.type === self.TYPE_AUDIO || self.options.type === self.TYPE_VIDEO) {
348                    $actionEl.css('font-size', '12px')
349                } else {
350                    $actionEl.css('font-size', '9px')
351                }
352            } else if (key === 'uploadLinks') {
353                $actionEl = $('<div class="folder-action"> ' + action.label + '</div>')
354
355                $actionEl.addClass('folder-action-' + key);
356                $actionEl.addClass('btn');
357                $actionEl.addClass('btn-success');
358
359                $actionEl.mouseenter(function () {
360                    $(this).css('background-color', '#0cc57c');
361                });
362
363                $actionEl.mouseleave(function () {
364                    $(this).css('background-color', '#199c68');
365                });
366
367                $actionEl.css('border', '1px solid');
368                if (self.options.type === self.TYPE_AUDIO || self.options.type === self.TYPE_VIDEO) {
369                    $actionEl.css('font-size', '12px');
370                } else {
371                    $actionEl.css('font-size', '9px');
372                }
373            } else {
374                $actionEl = $('<div class="folder-action" style="text-align: center"><a href="#">' + action.label + '</a></div>')
375            }
376
377            $actionEl.data('action', key);
378            $actionEl.appendTo($wrapper);
379
380            if (action.hasOwnProperty('hint') && action.hint !== '') {
381                $('<div style="color: #7B6A6A; font-size: 10px; margin: 10px 0">' + action.hint + '</div>').appendTo($wrapper);
382            }
383
384            if (!this.settingItems.includes(this.options.overrideDefaultFolder)) {
385                $wrapper.appendTo($actions);
386            }
387
388            action.pickerEl = $actionEl;
389
390            $actionEl.click(function (e) {
391                self.selectAction($(this).data('action'), $(this), e);
392            })
393        }
394
395        for (key in this.folders) {
396            var folder = this.folders[key]
397
398            $folderEl = $('<div class="folder-directory-picker" title="' +
399                folder.label + '"> <span class="icon ' + folder.icon + '"></span>' + folder.label + '</div>')
400            $folderEl.addClass('folder-picker-' + key)
401            $folderEl.data('folder', key)
402            $folderEl.appendTo($folders)
403
404            folder.pickerEl = $folderEl;
405
406            $folderEl.click( function() {
407                self.selectFolder($(this).data('folder'), false)
408            })
409        }
410
411
412        if (!this.settingItems.includes(this.options.overrideDefaultFolder)) {
413            var $createFolderEl = $('<div class="folder-directory-picker" title="'+window.tt('common', 'Create folder')+'">' +
414                '<span class="icon glyphicon glyphicon-plus-sign"></span>'+window.tt('common', 'Create folder')+'</div>');
415
416            $createFolderEl.addClass('folder-picker-' + key)
417            $createFolderEl.data('folder', 'create-folder')
418            $createFolderEl.appendTo($folders)
419
420            $createFolderEl.click(function(e) {
421                self.selectAction('directory', $(this), e);
422            })
423        }
424    },
425    formatBytes: function (bytes, decimals = 2) {
426        if (bytes === 0) return ('0 ' + window.tt('common', 'Byte'));
427
428        const k = 1000;
429        const dm = decimals < 0 ? 0 : decimals;
430		const sizes = [
431			window.tt('common', 'Byte'),
432			window.tt('common', 'KB'),
433			window.tt('common', 'MB'),
434			window.tt('common', 'GB'),
435			window.tt('common', 'TB')
436		];
437
438        const i = Math.floor(Math.log(bytes) / Math.log(k));
439
440        return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
441    },
442    addAccordionEventListeners: function () {
443        var acc = document.getElementsByClassName("menu-accordion");
444        var i;
445
446        for (i = 0; i < acc.length; i++) {
447            acc[i].addEventListener("click", function() {
448                this.classList.toggle("dialogue-active");
449                var panel = this.parentNode.querySelector('.menu-panel');
450                if (panel.style.maxHeight) {
451                    panel.style.maxHeight = null;
452                    panel.style.padding = "0px";
453                } else {
454                    panel.style.maxHeight = "72%";
455                }
456            });
457        }
458    },
459    selectFolder: function(folderName, fromDirectories = false) {
460        var folder = fromDirectories ? this.directories[folderName] : this.folders[folderName]
461        var self = this;
462
463        folder.name = folderName;
464        self.currentFolder = folder;
465        if( !folder.widgetEl ) {
466            var widgetEl = $('<div class="folder-content"></div>')
467			var folderOptions = {
468				owner: this,
469				folder: folderName,
470                label: folder.label,
471				fileType: this.options.type,
472                type: this.options.type,
473				accept: this.options.accept,
474                folderType: folder.type,
475                directoryId: folder.directoryId,
476                filesNumber: 0,
477                contentEl: self.contentEl,
478                directories: self.folderSelectorEl,
479                directoriesList: self.directories,
480                extensions: self.options.extensions,
481                fileDialogLabel: self.options.fileDialogLabel,
482                forceFileType: self.options.forceFileType
483			};
484			if ('options' in folder) {
485				folderOptions = Object.assign({}, folderOptions, folder.options);
486			}
487            widgetEl[folder.widget](folderOptions);
488            widgetEl.appendTo( self.contentEl );
489
490            widgetEl.addClass("folder-" + folderName + "-content")
491
492            folder.widgetEl = widgetEl;
493        }
494
495        if (!folder.pickerEl && fromDirectories) {
496            folder.pickerEl = self.folderSelectorEl.find('.folder-directory-picker-' + folderName);
497        }
498
499        self.contentEl.find('.folder-content').hide();
500        self.folderSelectorEl.find('.selected').removeClass("selected");
501
502        folder.pickerEl.addClass("selected");
503        folder.widgetEl.show();
504        folder.widgetEl[folder.widget]('init', this.options.selectedHash, this.options.iconParams);
505    },
506    selectAction: function(actionName, $actionEl, event) {
507        var action = this.actions[actionName]
508        var self = this;
509        var folder = self.currentFolder;
510        var type = self.options.type || self.TYPE_IMAGE;
511        var forceFileType = self.options.forceFileType;
512
513        const input = $actionEl
514            .parents('.file-dialog-layout')
515            .find('.folder-' + self.currentFolder.name + '-content')
516            .find('input[type=file]')
517
518        self.currentAction = action;
519
520        if (actionName === 'addById') {
521            if (!input.length) {
522                $(document).find('.file-dialog-layout').find('.folder-picker-recent').click();
523                setTimeout(()=> {
524                    $(document).find('.file-dialog-layout').find('.file-dialog-action-selector a').click();
525                })
526            } else {
527                event.preventDefault();
528                let fileId = prompt(window.tt('common', 'Enter file id'), '');
529
530                if (!fileId) {
531                    return;
532                }
533
534                fileId = fileId.replace(/[^0-9]/g,'');
535
536                if (!fileId) {
537                    $.toast(window.tt('common', 'Incorrect id'), {type: "danger"});
538                } else {
539                    folder.widgetEl[folder.widget]('markFileById', fileId, folder.name, true, null, type, forceFileType);
540                }
541            }
542        }
543
544        if (actionName === 'uploadLinks') {
545            event.preventDefault();
546            let fileLink = prompt(window.tt('common', 'Enter video link'), '');
547
548            if (!fileLink) {
549                return;
550            }
551
552            //проверять гугл \ яндекс?
553            var urlPattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
554                '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
555                '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
556                '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
557                '(\\?[;&a-z\\d\\!%_.~+=-]*)?'+ // query string
558                '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
559            if (!urlPattern.test(fileLink)) {
560                $.toast(window.tt('common', 'Указана ссылка не верного формата'), {type: "danger"});
561                return;
562            }
563
564            ajaxCall('/pl/fileservice/video/save-video-link', {'link': fileLink}, {}, function (response) {
565                if (response.success) {
566                    folder.widgetEl[folder.widget]('fileUploaded', response.hash);
567                }
568            }, function(response) {
569                console.log('ccc', response)
570            }, function(response) {
571                console.log('eee', response)
572            });
573            return
574        }
575
576        if (actionName === 'upload') {
577			if (window.file_upload_blocking_for_admin) {
578				return;
579			}
580            if (input.length) {
581                input.last().click();
582            } else {
583                $(document).find('.file-dialog-layout').find('.folder-picker-recent').click();
584                $(document).find('.folder-recent-content').find('input[type=file]').last().click();
585            }
586        }
587
588        if (actionName === 'directory') {
589            var directoryName = prompt(window.tt('common', 'Enter folder name'), window.tt('common', 'New folder'));
590
591            if (directoryName === null) {
592                return;
593            }
594
595            directoryName = directoryName.trim().replace(/[`!#$%&*()|+\-=?:'<>\{\}\[\]\\\/]/gi, '');
596
597            directoryName = directoryName.trim() === '' ? window.tt('common', 'New folder') : directoryName.trim();
598            self.createDirectory(directoryName);
599        }
600    },
601    fileSelected: function( hash, folderCallback ) {
602
603        var self = this;
604
605        if ( this.options.isMulti ) {
606            this.addSelectedFileEl( hash );
607            this.showMultiStat();
608        }
609        else {
610            this.valueSelected({ hash: hash } )
611        }
612    },
613	valueSelected: function( value ) {
614		if ( this.options.callback ) {
615			if ( this.options.withIcons ) {
616				this.options.callback(value)
617			} else {
618				this.options.callback(value.hash)
619			}
620		}
621		this.modal.hide();
622	},
623    addSelectedFileEl: function( hash, caption ) {
624        var self = this;
625
626        var $el = $('<div class="selected-file-item"></div>')
627        $el.appendTo( self.selectedFilesEl )
628
629        self.selectedFilesEl.sortable({ axis: "x" })
630
631        $el.data('hash', hash )
632
633        $el.addClass('selected-file-' + hash.replace("\.", ""))
634
635		var $img = $('<img>');
636		var src = self.getSrcByHash(hash);
637		$img.attr("src", src);
638        $img.appendTo( $el )
639
640        $unselectBtn = $("<span class='fa fa-trash btn-unselect'></span>")
641        $unselectBtn.appendTo( $el )
642
643
644        $unselectBtn.click( function() {
645            $el.remove();
646            self.showMultiStat();
647        })
648
649        var $descriptionBlock = $("<div class='description-block'> <a href='javascript:void(0)' class='set-description-link'>"
650			+ window.tt('common', 'description')
651			+ "</a> <input type='text' placeholder='" + window.tt('common','description') + "'></div>"
652		);
653        $descriptionBlock.appendTo( $el )
654
655        $descriptionBlock.find( '.set-description-link' ).click( function() {
656            $descriptionBlock.addClass('active')
657            $descriptionBlock.find('input').focus();
658        })
659
660        $descriptionBlock.addClass( 'active' )
661        if ( caption ) {
662            $descriptionBlock.find( 'input' ).val( caption )
663        }
664
665
666        //$unselectBtn.click( function)( {})
667
668    },
669	getSrcByHash: function(hash) {
670		return this.options.type === this.TYPE_VIDEO
671			? getVideoThumbnailUrl(hash, 200, 200)
672			: getThumbnailUrl(hash, 200, 200);
673	},
674    isMobile: function () {
675        if( navigator.userAgent.match(/Android/i)
676          || navigator.userAgent.match(/webOS/i)
677          || navigator.userAgent.match(/iPhone/i)
678          || navigator.userAgent.match(/iPad/i)
679          || navigator.userAgent.match(/iPod/i)
680          || navigator.userAgent.match(/BlackBerry/i)
681          || navigator.userAgent.match(/Windows Phone/i)
682        ){
683          return true;
684        }
685        else {
686          return false;
687        }
688    },
689    createDirectory: function (directoryName) {
690	    var self = this
691
692        ajaxCall('/pl/fileservice/directory/create', {
693            'name': directoryName,
694            'type': self.options.type || self.TYPE_IMAGE,
695        }, {}, function (response) {
696            var key = 'folder_' + response.id;
697            var $folders = self.folderSelectorEl
698
699            self.directories[key] = {
700                label: directoryName,
701                icon: "glyphicon glyphicon-folder-open",
702                widget: 'gcFileSelectorFolder',
703                type: 'custom',
704                directoryId: response.id
705            }
706            var folder = self.directories[key]
707
708            var $folderEl = $('<div data-id="' +
709                response.id + '" data-folder-id="' +
710                key + '" class="folder-directory-picker custom-directory" title="' +
711                folder.label + '"><span class="icon ' +
712                folder.icon + '"></span><span class="custom-directory" data-id="' +
713                response.id + '" id="folder-text-' +
714                response.id + '">' +
715                folder.label + '</span></div>')
716
717            $folderEl.addClass('folder-directory-picker-' + key)
718            $folderEl.data('folder', key)
719
720            $folderEl.appendTo($folders)
721
722            folder.pickerEl = $folderEl;
723
724            $folderEl.click(function() {
725                self.selectFolder($(this).data('folder'), true)
726            })
727
728            self.selectFolder($folderEl.data('folder'), true)
729        });
730    },
731    loadDirectories: function () {
732        var self = this
733
734        ajaxCall('/pl/fileservice/directory/list', { type: self.options.type || self.TYPE_IMAGE },
735            {async: false}, function (response) {
736            if (response.success && response.directories.length > 0) {
737                response.directories.forEach(element => self.directories['folder_' + element.id] = {
738                    label: element.name,
739                    icon: "glyphicon glyphicon-folder-open",
740                    widget: 'gcFileSelectorFolder',
741                    type: 'custom',
742                    category: element.type,
743                    directoryId: element.id
744                });
745            }
746
747            self.fillDirectories();
748        });
749    },
750    fillDirectories: function () {
751	    var self = this;
752	    var i = 0;
753
754        if (!this.settingItems.includes(this.options.overrideDefaultFolder)) {
755            for (dirKey in this.directories) {
756                var directory = this.directories[dirKey]
757                if (directory.category !== self.options.type) {
758                    continue;
759                }
760
761                var $directoryEl = $('<div data-id="' + directory.directoryId + '" data-folder-id="' + dirKey + '" class="folder-directory-picker custom-directory" title="' +
762                    directory.label + '"><span class="icon ' +
763                    directory.icon + '"></span><span class="custom-directory" data-id="' + directory.directoryId + '" id="folder-text-' +
764                    directory.directoryId + '">' +
765                    directory.label + '</span></div>')
766
767                $directoryEl.data('folder', dirKey)
768                $directoryEl.css('display', 'none')
769                $directoryEl.appendTo(self.folderSelectorEl)
770                $directoryEl.delay((i++) * 100).fadeTo(1000, 1)
771                directory.pickerEl = $directoryEl;
772                $directoryEl.click(function () {
773                    self.selectFolder($(this).data('folder'), true)
774                })
775
776                i++;
777            }
778        }
779    }
780} );

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.