1jQuery.widget( 'gc.gcFileSelectorFolder', { 2 TYPE_IMAGE: 'image', 3 TYPE_VIDEO: 'video', 4 TYPE_VIDEO_NOTE: 'video_note', 5 TYPE_AUDIO: 'audio', 6 FOLDER_TYPE_CUSTOM: 'custom', 7 ORDER_TYPE_FILENAME: 'filename', 8 ORDER_TYPE_DATE: 'date', 9 options: { 10 owner: null, 11 folder: null, 12 selectedHash: null, 13 fileSizeLimit: '6GB', 14 fileSizeLimitWarning: (typeof Yii != 'undefined') ? Yii.t('common', 'Max size {n} GB', 6) : 'Max size 6 GB', 15 fileType: this.TYPE_IMAGE, 16 accept: '', 17 onUploadComplete: null, 18 folderType: null, 19 directoryId: null, 20 label: '', 21 directories: null, 22 directoriesSelectEl: null, 23 currentSearch: null, 24 fromWebinar: false, 25 extensions: null, 26 fileDialogLabel: null, 27 forceFileType: null 28 }, 29 30 _create: function() { 31 var self = this; 32 33 var isFromWebinar = this.options.fromWebinar; 34 35 this.contentEl = this.options.contentEl 36 this.options.orderBy = self.ORDER_TYPE_DATE 37 38 this.element.addClass("folder") 39 var $folderHeader = $('<div class="folder-header"></div>') 40 this.folderHeaderEl = $folderHeader 41 42 $folderHeader.appendTo(this.element) 43 44 var $title = $('<div class="folder-title" contenteditable="false" data-filename="' + 45 this.options.label + '">' + this.options.label + '</div>'); 46 47 if (self.options.folderType === self.FOLDER_TYPE_CUSTOM) { 48 $title.click(function () { 49 $(this).attr('contenteditable', 'true').attr("tabindex", -1).focus() 50 $(this).css('background-color', '#d2d2d2') 51 }) 52 53 $title.on('keypress', function (e) { 54 if (e.keyCode === 13) { 55 e.preventDefault(e) 56 self.renameDirectory($(this)) 57 } 58 }) 59 60 $title.on('focusout', function () { 61 self.renameDirectory($(this)) 62 }) 63 } 64 65 $title.appendTo(isFromWebinar ? '' : $folderHeader) 66 67 var $line = $('<div></div>'); 68 $line.css('display', isFromWebinar ? 'block' : 'none'); 69 70 var typeLabel; 71 if (self.options.fileDialogLabel !== null) { 72 typeLabel = self.options.fileDialogLabel; 73 } else { 74 switch (self.options.fileType) { 75 case self.TYPE_VIDEO: 76 case self.TYPE_AUDIO: 77 typeLabel = self.options.fileType 78 break; 79 case self.TYPE_IMAGE: 80 typeLabel = 'image|images' 81 break; 82 } 83 } 84 85 var $searchFileInput = $('<div class="search-file-input">' 86 + '<input class="files-search-input" placeholder="' + window.tt('common', 'Search by name') + '">' 87 + '</div>' 88 ); 89 var $searchZoomer = $('<div class="search-zoomer glyphicon glyphicon-search"></div>') 90 var $filesNumber = $('<div class="files-number">0 ' + window.tt('common', typeLabel, 0) + '</div>') 91 var $sortForm = $('<div class="sort-form"><select id="order-by">' 92 + '<option value="date">' + window.tt('common', 'Date added') + '</option>' 93 + '<option value="filename">' + window.tt('common', 'name') + '</option>' 94 + '</select></div>' 95 ); 96 var $deleteFolder = $('<div class="delete-folder-btn btn btn-secondary">' 97 + window.tt('common', 'Delete folder') 98 + '</div>' 99 ); 100 101 self.filesNumber = $filesNumber 102 103 if (self.options.folderType === self.FOLDER_TYPE_CUSTOM) { 104 $deleteFolder.appendTo(isFromWebinar ? '' : $folderHeader) 105 } 106 107 $('<br>').appendTo(isFromWebinar ? '' : $folderHeader) 108 $filesNumber.appendTo(isFromWebinar ? '' : $folderHeader) 109 $sortForm.appendTo(isFromWebinar ? '' : $folderHeader) 110 $sortForm.change(function () { 111 self.changeOrder($(this)) 112 }) 113 114 $searchFileInput.appendTo(isFromWebinar ? '' : $folderHeader) 115 $searchZoomer.appendTo(isFromWebinar ? '' : $folderHeader) 116 117 $searchZoomer.click(function () { 118 if ($searchFileInput.css('display') === 'none') { 119 $searchFileInput.fadeIn(1500); 120 $searchFileInput.css('display', 'inline-block') 121 $searchFileInput.find('.files-search-input').focus() 122 } 123 }) 124 125 $deleteFolder.click(function () { 126 var isAgreed = confirm(window.tt('common', 'The folder and all files in it will be deleted.')); 127 128 if (isAgreed) { 129 self.deleteFolder() 130 } 131 }) 132 133 $searchFileInput.focusout(function (e) { 134 self.searchFiles(e, $searchFileInput) 135 }) 136 137 $searchFileInput.on("keypress", function (e) { 138 self.searchFiles(e, $searchFileInput) 139 }) 140 141 // Left part of line
142 var $leftPartWrapper = $('<div></div>'); 143 $leftPartWrapper.css('display', 'inline-block'); 144 $leftPartWrapper.appendTo($line); 145 var $uploader = $('<div class="uploader"></div>'); 146 $uploader.appendTo($leftPartWrapper); 147 148 var $rightPartWrapper = $('<div></div>'); 149 $rightPartWrapper.css('display', 'inline-block').css('vertical-align', 'top').css('padding', '4px 0 0 20px'); 150 $rightPartWrapper.appendTo($line); 151 152 var $clear = $("<span class='clear-link'>" + window.tt('common', 'Reset') + "</span>") 153 .appendTo( $rightPartWrapper ) 154 .click(function() { 155 self.selectFile( null ); 156 }); 157 158 159 // Right part of line 160 if (self.options.fileType === self.TYPE_VIDEO) { 161 var $rightPart = self.buildUploadByLink(); 162 $rightPart.appendTo($rightPartWrapper); 163 } 164 165 $line.appendTo($folderHeader); 166 167 var queueId = "queue" + this.options.folder; 168 var $queue = $("<div id='" + queueId + "' class='queues'></div>") 169 $queue.css('display', 'contents') 170 $queue.appendTo($folderHeader) 171 if (self.options.fileType === self.TYPE_VIDEO || self.options.fileType === self.TYPE_AUDIO) { 172 $queue.css('height', '5px') 173 } 174 175 this.filesEl = $('<div class="files-list"></div>') 176 this.filesEl.appendTo(this.element) 177 178 if (window.fileserviceTusFeatureEnabled && tus.isSupported) { 179 $('<div class="tus-uploader" />').appendTo($uploader).tusUploader({ 180 'accept': self.options.accept, 181 'progressContainer': $queue, 182 'onSuccess': function (url, file) { 183 $.ajax({ 184 url: url, 185 method: 'PUT', 186 success: function (data) { 187 self.fileUploaded(data.hash, data.filename); 188 $queue.text('') 189 if (self.options.onUploadComplete) { 190 self.options.onUploadComplete(data.hash); 191 } 192 }, 193 }); 194 }, 195 }); 196 197 if ( self.options.fileSizeLimit && self.options.fileSizeLimitWarning ) { 198 $("<p class='text-muted'>" + self.options.fileSizeLimitWarning + "</p>") 199 .appendTo($uploader); 200 } 201 202 return; 203 } 204 205 var uploadifiveParams = { 206 auto: true, 207 buttonText: window.tt('common', 'Upload'), 208 width: 120, 209 id: "folderUpload" + self.options.folder, 210 queueID: queueId, 211 dnd: false, 212 removeCompleted: true, 213 multi: true, 214 fileSizeLimit: self.options.fileSizeLimit, 215 uploadScript: '/fileservice/widget/upload?deprecated=12' 216 + '&secure=' + window.isEnabledSecureUpload 217 + '&host=' + window.fileserviceUploadHost, 218 formData: {fullAnswer: true}, 219 onUploadError: function(file, errorCode, errorMsg) { 220 alert("ERROR"); 221 }, 222 onUploadComplete: function(e, res) { 223 res = JSON.parse(res); 224 self.fileUploaded(res.hash, res.filename); 225 $queue.text('') 226 227 if (self.options.onUploadComplete) { 228 self.options.onUploadComplete(res.hash); 229 } 230 } 231 }; 232 233 234 if (window.isEnabledSecureUpload && window.fileserviceUploadHost) { 235 uploadifiveParams.onUpload = getUploadifySecretLink; 236 } 237 238 if (this.options.accept) { 239 // ÐоÑÐ¾Ð¼Ñ ÑÑо fileType паÑамеÑÑ uploadifive как-Ñо не Ñак ÑабоÑаеÑ. 240 // ÐÑи Ñказании video/* кÑÑÑ Ð²Ð¸Ð´ÐµÐ¾ ÑоÑмаÑов не позволÑÐµÑ Ð²ÑбÑаÑÑ 241 // ÐÑли пеÑеÑиÑлиÑÑ ÐºÐ¾Ð½ÐºÑеÑнÑе ÑаÑÑиÑÐµÐ½Ð¸Ñ Ñайлов (или mime-type'Ñ), Ñо Ñоже не вÑе Ð¸Ñ Ð²Ð¾ÑпÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ 242 uploadifiveParams.onInit = function() { 243 var $fileInput = $('input[type=file]', self.element); 244 $fileInput.attr('accept', self.options.accept); 245 }; 246 // ÐÑи добавлении оÑеÑедного Ñайла ÑоздаÑÑÑÑ ÐµÑе input'Ñ Ð¸ по ÑÑÐ¾Ð¼Ñ ÑобÑÑÐ¸Ñ Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ обÑабоÑаÑÑ 247 uploadifiveParams.onUpload = function(filesToUpload, settings) { 248 var $fileInput = $('input[type=file]', self.element); 249 $fileInput.attr('accept', self.options.accept); 250 251 var secureDirectUploadUri = '/fileservice/widget/secure-direct-upload'; 252 try { 253 var session = localStorage.getItem('session'); 254 var requestParams = {"fs_ref": window.location.href}; 255 256 if (session !== undefined && session != null){ 257 var objSession = jQuery.parseJSON(session); 258 259 if (objSession.hasOwnProperty('user_id') && objSession.user_id != null) {
260 requestParams.fs_u = objSession.user_id; 261 } else { 262 requestParams.fs_u = -1; 263 } 264 } 265 266 secureDirectUploadUri += '?' + jQuery.param(requestParams); 267 } catch (err) { 268 } 269 270 $.ajax({ 271 url: '/fileservice/widget/create-secret-link', 272 method: 'GET', 273 data: { 274 host: window.fileserviceUploadHost, 275 uri: secureDirectUploadUri, 276 expires: 600, 277 is_video: 1 278 }, 279 success: function (data) { 280 if (data.link) { 281 settings.uploadScript = data.link; 282 } 283 }, 284 error: function (http, message, exc) {sendCreateLinkError(http, message, exc);}, 285 async: false 286 }); 287 }; 288 } 289 290 setTimeout( function() { 291 $uploader.uploadifive(uploadifiveParams); 292 293 if ( self.options.fileSizeLimit && self.options.fileSizeLimitWarning ) { 294 var warning = $("<p class='text-muted'>" + self.options.fileSizeLimitWarning + "</p>"); 295 $uploader.parent().after( warning ); 296 } 297 298 }, 100 ) 299 300 }, 301 deleteFolder: function() { 302 var self = this 303 var dirId = self.options.directoryId 304 305 ajaxCall("/pl/fileservice/directory/delete", 306 {directory_id: dirId}, {}, function() { 307 var $menuFolder = self.options.directories.find('.custom-directory[data-id=' + dirId + ']') 308 var $recentFolder = self.options.directories.find('.folder-picker-recent') 309 $menuFolder.remove() 310 $recentFolder.click() 311 }) 312 }, 313 searchFiles: function(e, el) { 314 var input = el.find('.files-search-input')[0].value.replace(/[`!#$%&*()|+\-=?:'<>\{\}\[\]\\\/]/gi, ''); 315 var self = this 316 317 self.currentSearch = input 318 319 if (e.type === 'keypress' && e.keyCode !== 13) { 320 return 321 } 322 323 if ((e.type === 'focusout' || (e.type === 'keypress' && e.keyCode === 13)) && input.trim() === '') { 324 self.loadFiles(this.options.folder, this.filesEl, null, '') 325 326 el.fadeOut() 327 return 328 } 329 330 self.loadFiles(this.options.folder, this.filesEl, null, input) 331 }, 332 changeOrder: function(orderEl) { 333 var self = this 334 var orderBy = orderEl.find('#order-by')[0].value 335 336 self.options.orderBy = orderBy 337 338 self.loadFiles(this.options.folder, this.filesEl, null, this.currentSearch) 339 }, 340 renameDirectory: function($title) { 341 var text = $title.text().trim().replace(/[`!#$%&*()|+\-=?:'<>\{\}\[\]\\\/]/gi, ''); 342 var self = this 343 344 if (!text) { 345 $title.text($title.data('filename')); 346 $.toast(window.tt('common', 'Incorrect folder name'), {type: "danger"}); 347 } else { 348 ajaxCall("/pl/fileservice/directory/rename", 349 {directory_id: self.options.directoryId, name: text}, {}, function() { 350 var $menuFolder = self.options.directories.find('#folder-text-' + self.options.directoryId) 351 352 $menuFolder.text(text) 353 $menuFolder.attr('title', text) 354 355 $title.attr('contenteditable', 'false') 356 $title.css('background-color', '') 357 $title.text(text) 358 }) 359 } 360 }, 361 buildUploadByLink: function() { 362 var self = this; 363 364 var $content = $('<div></div>'); 365 366 if (window.file_upload_blocking) { 367 return $content; 368 } 369 370 var $uploadByLink = $('<a href="javascript:void(0);">' + window.tt('common', 'Upload file by link') + '</a>'); 371 $uploadByLink.appendTo($content); 372 373 var $input = $('<input placeholder="' + window.tt('common', 'Link from file storage') + '" type="url"/>'); 374 $input.css('min-width', '300px'); 375 $input.hide(); 376 $input.appendTo($content); 377 378 var $btn = $('<a href="javascript:void(0);">' + window.tt('common', 'Upload') + '</a>'); 379 $btn.css('padding-left', '10px'); 380 $btn.hide(); 381 $btn.appendTo($content); 382 383 var $loading = $('<img src="/public/img/loading.gif">'); 384 $loading.hide(); 385 $loading.appendTo($content); 386 387 $uploadByLink.click(function() { 388 $uploadByLink.hide(); 389 $input.show(); 390 $btn.show(); 391 }); 392 393 $btn.click(function() { 394 var url = $input.val(); 395 if (url.length === 0) { 396 $.toast(window.tt('common', 'Enter a link'), {type: "danger"}); 397 return; 398 } 399
400 var hashRegExp = /(?:AB\.)?[a-f\d]{32}\.[\w\d]+/gi; 401 var entries = url.match(hashRegExp); 402 if (!entries || entries.length === 0) { 403 $.toast(Yii.t('common', 'Only links from file storage can be inserted'), {type: "danger"}); 404 return; 405 } 406 407 408 var hash = entries[entries.length - 1].toLowerCase(); 409 var hashParts = hash.split('.'); 410 var ext = hashParts[hashParts.length-1].toLowerCase(); 411 412 var $existFileEl = self.getFileElByHash(hash); 413 if ($existFileEl.length > 0) { 414 $.toast(window.tt('common', 'This file is already in the current folder'), {type: "danger"}); 415 return; 416 } 417 418 if (self.options.accept) { 419 var acceptExts = self.options.accept.toLowerCase().match(/[\w\d]+/g); 420 if (acceptExts && acceptExts.length > 0) { 421 if (!acceptExts.includes(ext)) { 422 $.toast(window.tt('common', 'The following formats are allowed') + ': ' + self.options.accept, {type: "danger"}); 423 return; 424 } 425 } 426 } 427 428 $loading.show(); 429 $btn.hide(); 430 ajaxCall('/pl/fileservice/video/exists', { 431 'file-hash': hash 432 }, {}, function (response) { 433 if (response.exists) { 434 self.fileUploaded(hash, hash); 435 $input.val(''); 436 $.toast(window.tt('common', 'File uploaded successfully'), {type: "success"}); 437 438 if (self.options.onUploadComplete) { 439 self.options.onUploadComplete(hash); 440 } 441 } else { 442 $.toast(window.tt('common', 'File not found'), {type: "danger"}); 443 } 444 }, function() { 445 $loading.hide(); 446 $btn.show(); 447 }); 448 }); 449 450 return $content; 451 }, 452 fileUploaded: function( hash, filename ) { 453 var self = this; 454 var date = new Date().toISOString().split('T')[0] + ' ' + new Date().toISOString().split('T')[1].slice(0, 8) 455 var $fileEl = this.createFileEl( hash, false, filename, date, true) 456 457 // ÐÑли Ñакой Ñже бÑл, ÑдалÑем его пеÑед добавлением Ñакого же 458 var $existFileEl = self.getFileElByHash(hash); 459 $existFileEl.remove(); 460 461 $fileEl.prependTo( this.filesEl ); 462 463 self.markFile( hash, this.options.folder, true ); 464 465 self.numberOfFiles = ++self.numberOfFiles 466 self.filesNumber.text(self.numberOfFiles + ' ' + self.getTypeLabel(self.numberOfFiles)) 467 468 if ( this.options.owner.options.isMulti ) { 469 self.selectFile( hash ) 470 } 471 }, 472 getFileElByHash: function(hash) { 473 return $('.' + this.getFileClass(hash), this.filesEl); 474 }, 475 getFileKey: function(hash) { 476 return hash.replace("\.", ""); 477 }, 478 getFileClass: function(hash) { 479 return 'file-' + this.getFileKey(hash); 480 }, 481 initFileActionTooltip: function($el, title) { 482 $el.attr('data-toggle', 'tooltip'); 483 $el.attr('title', title); 484 $el.tooltip({ 485 container: '.files-list', 486 placement: 'auto', 487 }); 488 }, 489 createFileEl: function( hash, inFavorites, filename, datetime, can ) { 490 if (can === undefined) { 491 can = true; 492 } 493 var $el = $('<div class="file-item"></div>') 494 var self = this; 495 self.hash = hash; 496 filename = filename || hash 497 $el.draggable({ 498 cursor: "move", 499 cursorAt: { top: -12, left: -20 }, 500 helper: function(e) { 501 return $("<div class='ui-widget-header'>" + filename + "</div>"); 502 }, 503 start: function(e) { 504 }, 505 drag: function(e) { 506 var dragger = $(this) 507 var $hoverEl = $(e.toElement) 508 509 if ($hoverEl.attr('class')) { 510 var classes = $hoverEl.attr('class') 511 var parentClasses = $($hoverEl.parentElement).attr('class') 512 513 if (classes.includes('custom-directory') && self.options.directoryId !== $hoverEl.data('id')) { 514 } 515 } 516 }, 517 stop: function(e) { 518 var dragger = $(this) 519 var $hoverEl = $(e.toElement) 520 521 if ($hoverEl.attr('class')) { 522 var classes = $hoverEl.attr('class') 523 524 if (classes.includes('custom-directory') && self.options.directoryId !== $hoverEl.data('id')) { 525 self.moveFile(hash, $hoverEl.data('id'), $el) 526 } 527 } 528 } 529 }); 530 531 var fileKey = self.getFileKey(hash); 532 var fileClass = self.getFileClass(hash); 533 $el.css('position', 'relative'); 534 $el.data('key', fileKey); 535 $el.data('hash', hash) 536 537 $el.addClass(fileClass); 538 if (self.options.fileType === self.TYPE_VIDEO) { 539 $el.addClass('video-preview'); 540 } 541 /*if ( this.options.owner.isFileSelected( fileKey ) ) { 542 $el.addClass("selected") 543 }*/ 544 545 var $img = $('<img>') 546 547 var src = self.isVideo(this.options.fileType) 548 ? getVideoThumbnailUrl(hash, 200, 150) 549 : getThumbnailUrl(hash, 200, 200); 550 $img.attr("src", src); 551 $img.data('hash', hash); 552 $img.appendTo($el) 553 var $titles = $('<div data-filename="' + filename + '" contenteditable="false" class="titles-text" id="' + 554 hash + '">' + filename + '</div>'); 555 556 $titles.appendTo($el); 557 558 var $createDate = $('<div class="file-create-data">' + datetime + '</div>') 559 $createDate.appendTo($el) 560 561 var $bottomPanel = $('<div class="bottom-panel" style="display: flex; align-items: center;"></div>') 562 $bottomPanel.appendTo($el) 563 //$selectBtn = $('<button class="btn btn-select btn-primary">ÐÑбÑаÑÑ</button>') 564 //$selectBtn.appendTo( $el ) 565 566 var $hideBtn = $('<button class="btn btn-cancel text-left btn-sm btn-link file-action"><span class="glyphicon glyphicon-eye-close"></span></button>') 567 $hideBtn.appendTo($bottomPanel) 568 self.initFileActionTooltip($hideBtn, window.tt('common', 'СкÑÑÑÑ')); 569 570 let $textFileRemove = window.tt('common', 'Удаление ÑеÑез Ñайловое Ñ ÑанилиÑе недоÑÑÑпно без пÑав доÑÑÑпа'); 571 let $colorFileRemove = 'gray'; 572 if (window && window.canFileStorage === true) { 573 $textFileRemove = window.tt('common', 'УдалиÑÑ Ð² Ñайловом Ñ ÑанилиÑе'); 574 $colorFileRemove = 'red'; 575 } 576 if (can === true) { 577 var $cancelBtn = $('<a class="btn btn-remove text-left btn-sm btn-link file-action"><span style="color: ' + $colorFileRemove + ' " class="glyphicon glyphicon-trash"></span></a>') 578 $cancelBtn.appendTo($bottomPanel); 579 self.initFileActionTooltip($cancelBtn, window.tt('common', $textFileRemove)); 580 } 581 582 var $downloadBtn = $('<button class="btn btn-link btn-download file-action"><span class="from-favorites glyphicon glyphicon-download-alt"></span></button>') 583 $downloadBtn.appendTo($bottomPanel) 584 self.initFileActionTooltip($downloadBtn, window.tt('common', 'СкаÑаÑÑ')); 585 self.downloadBtn = $downloadBtn 586 587 var $cropBtn = $('<button class="btn btn-link btn-crop file-action"><span class="to-favorites glyphicon glyphicon-scissors"></span></button>'); 588 $cropBtn.appendTo($bottomPanel); 589 self.initFileActionTooltip($cropBtn, window.tt('common', 'ÐбÑезаÑÑ')); 590 self.cropBtn = $cropBtn; 591 592 var $changeVideoPreviewBtn = ''; 593 if (this.options.fileType === this.TYPE_VIDEO) { 594 $cropBtn.hide(); 595 596 $changeVideoPreviewBtn = $('<button class="btn btn-link btn-change-video-preview file-action"><span class="to-favorites glyphicon glyphicon-edit"></span></button>'); 597 $changeVideoPreviewBtn.appendTo($bottomPanel); 598 self.initFileActionTooltip($changeVideoPreviewBtn, window.tt('common', 'СмениÑÑ Ð¾Ð±Ð»Ð¾Ð¶ÐºÑ')); 599 self.setVideoPreviewBtn = $changeVideoPreviewBtn; 600 } 601 602 603 var $allowRenameBtn = $('<button class="btn btn-sm btn-link btn-allow-rename file-action"><span class="glyphicon glyphicon-pencil"></span></button>') 604 $allowRenameBtn.appendTo($bottomPanel) 605 self.initFileActionTooltip($allowRenameBtn, window.tt('common', 'ÐеÑеименоваÑÑ')); 606 self.allowRename = $allowRenameBtn 607 608 609 var $applyRenameBtn = $('<button class="btn btn-sm btn-success-outline btn-apply-rename file-action"><span class="glyphicon glyphicon-ok"></span></button>') 610 $applyRenameBtn.css('display', 'none') 611 $applyRenameBtn.appendTo($bottomPanel) 612 self.initFileActionTooltip($applyRenameBtn, window.tt('common', 'ÐÑимениÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ')); 613 self.applyRenameBtn = $applyRenameBtn 614 615 var $moveFileBtn = $('<button class="btn btn-sm btn-link btn-move-file file-action"><span class="glyphicon glyphicon-copy"></span></button>') 616 $moveFileBtn.appendTo($bottomPanel) 617 self.initFileActionTooltip($moveFileBtn, window.tt('common', 'ÐеÑемеÑÑиÑÑ')); 618 619 var $favBtn = $('<button class="btn btn-link btn-favorites file-action"><span class="to-favorites glyphicon glyphicon-star-empty"></span><span class="from-favorites glyphicon glyphicon-star"></span></button>') 620 $favBtn.appendTo($bottomPanel) 621 self.initFileActionTooltip($favBtn, window.tt('common', 'ÐобавиÑÑ Ð² избÑанное')); 622 self.favBtn = $favBtn 623 624 //$coverBtn = $('<button class="btn btn-link btn-cover hidden"><span class="glyphicon glyphicon-picture"></span></button>') 625 //$coverBtn.appendTo( $el ) 626 627 $titles.on("keypress", function (e) { 628 if (e.keyCode === 13) { 629 e.preventDefault(e) 630 var text = $titles.text().trim().replace(/[`!#$%&*()|+\-=?:'<>\{\}\[\]\\\/]/gi, ''); 631 if (!text) { 632 $(this).text($(this).data('filename')); 633 $.toast(window.tt('common', 'Incorrect file name'), {type: "danger"}); 634 } else { 635 self.renameFile(hash, text) 636 $titles.attr('contenteditable', 'false'); 637 $titles.text(text); 638 $.toast(window.tt('common', 'File name updated'), {type: "success"}); 639 $applyRenameBtn.hide() 640 $allowRenameBtn.show() 641 } 642 } 643 }) 644 645 $titles.focusout(function () { 646 var text = $titles.text().trim().replace(/[`!#$%&*()|+\-=?:'<>\{\}\[\]\\\/]/gi, ''); 647 if (!text) { 648 $(this).text($(this).data('filename')); 649 $.toast(window.tt('common', 'Incorrect file name'), {type: "danger"}); 650 } else { 651 self.renameFile(hash, text) 652 $titles.attr('contenteditable', 'false'); 653 $titles.text(text); 654 $.toast(window.tt('common', 'File name updated'), {type: "success"}); 655 $applyRenameBtn.hide() 656 $allowRenameBtn.show() 657 } 658 }) 659 660 if ( inFavorites ) { 661 self.favBtn.addClass('in-favorites'); 662 } 663 664 var handleButtons = function( hash, $el, filename, $titles, self ) { 665 $favBtn = $el.find('.btn-favorites') 666 $cancelBtn = $el.find('.btn-cancel') 667 let $removeBtn = $el.find('.btn-remove') 668 //$coverBtn = $el.find('.btn-cover') 669 $allowRenameBtn = $el.find('.btn-allow-rename') 670 $applyRenameBtn = $el.find('.btn-apply-rename') 671 $moveFileBtn = $el.find('.btn-move-file') 672 673 var $btnSelect = $el.find('img') 674 675 $btnSelect.click( function() { 676 self.selectFile( hash ) 677 }) 678 679 function addBtnHandler( btn, handler ) { 680 btn.click( handler ) 681 } 682 if (window && window.canFileStorage === true) { 683 $removeBtn.attr('href', '/pl/fileindex/file/view?hash=' + hash).attr('target', '_blank'); 684 } 685 686 addBtnHandler( $favBtn, function() { 687 $favBtn = $(this) 688 var needPositive = ! $favBtn.hasClass("in-favorites"); 689 self.markFile( hash, "favorites", needPositive, function( needPositive ) { 690 if ( needPositive ) { 691 $favBtn.addClass('in-favorites') 692 } 693 else { 694 $favBtn.removeClass('in-favorites') 695 } 696 }) 697 }); 698 699 addBtnHandler($cancelBtn, function() { 700 if (confirm(window.tt('common', 'Are you sure?'))) { 701 self.markFile( hash, self.options.folder, false ); 702 $(this).parents('.file-item').remove() 703 } 704 }) 705 706 addBtnHandler($downloadBtn, function() { 707 window.open( getDownloadUrl( hash ) ); 708 }) 709 710 addBtnHandler($allowRenameBtn, function() { 711 $allowRenameBtn = $(this) 712 $allowRenameBtn.hide() 713 $applyRenameBtn.show() 714 715 $titles.attr('contenteditable', 'true').attr("tabindex",-1).focus(); 716 }) 717 718 addBtnHandler($applyRenameBtn, function() { 719 $applyRenameBtn = $(this) 720 var text = $titles.text().trim().replace(/[`!#$%&*()|+\-=?:'<>\{\}\[\]\\\/]/gi, ''); 721 if (!text) { 722 $(this).text($(this).data('filename')); 723 $.toast(window.tt('common', 'Incorrect file name'), {type: "danger"}); 724 } else { 725 self.renameFile(hash, text) 726 $titles.attr('contenteditable', 'false'); 727 $titles.text(text); 728 $.toast(window.tt('common', 'File name updated'), {type: "success"}); 729 $applyRenameBtn.hide() 730 $allowRenameBtn.show() 731 } 732 }) 733 734 addBtnHandler($cropBtn, function () { 735 var jcrop, data = {}; 736 737 var active = window.gcModalActive(); 738 active && active.hide(); 739 var modal = window.gcModalFactory.create({ 740 onHide: function () { 741 jcrop.destroy(); 742 active && active.show(); 743 } 744 }); 745 746 var fixCrop = function(c) 747 { 748 // console.log('x = '+c.x); 749 // console.log('y = '+c.y); 750 // console.log('x2 = '+c.x2); 751 // console.log('y2 = '+c.y2); 752 // console.log('w = '+c.w); 753 // console.log('h = '+c.h); 754 data.crop = c; 755 data.image = { 756 w : modal.getContentEl().find('img').width(), 757 h : modal.getContentEl().find('img').height() 758 }; 759 var $btn = modal.getModalEl().find('.btn-success'); 760 if (c.w && c.h) { 761 $btn.removeAttr('disabled'); 762 } 763 else { 764 $btn.attr('disabled', 'disabled'); 765 } 766 // console.log(data); 767 }; 768 769 770 var $imgToEdit = $('<img>'); 771 $imgToEdit.attr("src", getThumbnailUrl(hash, 550, '')); 772 773 var $editContent = $('<div style="width: 550px;margin: 0 auto;">'); 774 $editContent.append($imgToEdit); 775 var $saveEditImageBtn = $('<button class="btn btn-success" style="margin: 5px;" disabled>' 776 + window.tt('common', 'Save') 777 + '</button>' 778 ); 779 var $cancelEditImageBtn = $('<button class="btn" style="margin: 5px;">'+window.tt('common', 'Cancel')+'</button>'); 780 781 $saveEditImageBtn.click(function () { 782 ajaxCall('/pl/fileservice/widget/user-crop', { 783 hash : hash, 784 data : data 785 }, {btn : $saveEditImageBtn}, function(response) { 786 modal.hide(); 787 self.fileUploaded(response.hash, response.filename); 788 }); 789 }); 790 791 $cancelEditImageBtn.click(function () { 792 modal.hide(); 793 }); 794 var $editButtons = $('<div style="text-align: center">'); 795 $editButtons.append($saveEditImageBtn).append($cancelEditImageBtn); 796 $editContent.append($editButtons); 797
798 modal.getModalEl().find('.modal-dialog').css('max-width', '600px'); 799 modal.getContentEl().addClass("row-container"); 800 modal.setTitle(window.tt('common', 'Crop image')); 801 modal.setContent($editContent); 802 modal.getContentEl().find('img').Jcrop({ 803 onChange: fixCrop, 804 onSelect: fixCrop 805 }, function() {jcrop = this;}); 806 807 modal.show(); 808 }); 809 810 addBtnHandler($moveFileBtn, function (e) { 811 var $existedIcon = $($moveFileBtn[0].parentElement).find('.move-directories') 812 813 if ($existedIcon.length > 0) { 814 $existedIcon.remove() 815 return 816 } 817 818 var directoriesFilteredByType = $(this).parents('.file-dialog-layout').find('span.custom-directory') 819 820 var $directoriesSelectEl = $('<div class="move-directories"><select class="dir-select">' 821 + '<option value="0">'+window.tt('common', 'Select folder')+'</option>' 822 + '</select></div>' 823 ); 824 var $selectEl = $directoriesSelectEl.find('.dir-select') 825 826 $.each(directoriesFilteredByType, function (i, element) { 827 $selectEl.append('<option value="' + 828 $(element).data('id') + '">' + 829 $(element).text() + '</option>') 830 }) 831 832 833 $directoriesSelectEl.css('display', 'none') 834 $directoriesSelectEl.css('z-index', '1') 835 $directoriesSelectEl.css('max-height', '100px') 836 $directoriesSelectEl.css('overflow-y', 'auto') 837 838 self.directoriesSelectEl = $directoriesSelectEl 839 840 $selectEl.change(function () { 841 var selectedOption = $(this).val() 842 var hash = $($directoriesSelectEl[0].parentNode.parentNode).data('hash') 843 var fileEl = $($directoriesSelectEl[0].parentNode.parentNode) 844 845 self.moveFile(hash, selectedOption, fileEl) 846 847 $directoriesSelectEl.remove() 848 }) 849 850 var $directoriesSelect = self.directoriesSelectEl 851 852 $directoriesSelect.appendTo($($moveFileBtn[0].parentElement)) 853 854 $directoriesSelect.css({ 855 'left': '170px', 856 'display': 'block', 857 'position': 'absolute' 858 }) 859 860 $directoriesSelect.find('.dir-select').val(0) 861 862 $directoriesSelect.focusout(function () { 863 $directoriesSelectEl.remove() 864 }) 865 866 }) 867 868 if ($changeVideoPreviewBtn) { 869 $changeVideoPreviewBtn.click(function() { 870 window.gcSelectVideoFrame({ 871 hash: hash, 872 callback: function (hash) { 873 self.fileUploaded(hash); 874 }, 875 overrideDefaultFolder: 'frames' 876 }); 877 }); 878 } 879 880 /*addBtnHandler($coverBtn, function() { 881 if (confirm("ÐÑ ÑвеÑенÑ?")) { 882 self.markFile( hash, "cover", true ); 883 } 884 })*/ 885 } 886 887 handleButtons( hash, $el, filename, $titles, self ) 888 889 $titles.click(function () { 890 $allowRenameBtn.hide() 891 $applyRenameBtn.show() 892 893 $(this).attr('contenteditable', 'true').attr("tabindex", -1).focus(); 894 }) 895 896 return $el; 897 }, 898 markFile: function( hash, mark, positive, callback ) { 899 var self = this 900 var data = { 901 hash: hash, 902 mark: mark, 903 positive: positive ? 1 : 0, 904 fileType: self.options.fileType, 905 forceFileType: self.options.forceFileType 906 } 907 908 if (mark !== 'favorites' && this.options.folderType === 'custom') { 909 data.directory_id = this.options.directoryId; 910 data.mark = 'custom'; 911 } 912 913 if (!positive) { 914 var newFileNumber = self.numberOfFiles - 1 915 self.filesNumber.text(newFileNumber + ' ' + self.getTypeLabel(newFileNumber)) 916 } 917 918 ajaxCall( "/pl/fileservice/widget/mark", data, {}, function() { 919 if ( callback ) { 920 callback( positive ); 921 } 922 } ) 923 }, 924 renameFile: function(hash, filename, callback) { 925 var data = { 926 hash: hash, 927 filename: filename, 928 positive: 1, 929 } 930 931 ajaxCall("/pl/fileservice/widget/rename", data, {}, function() { 932 if (callback) { 933 callback(); 934 } 935 }) 936 }, 937 setSelectedHash: function( selectedHash ) { 938 this.loadFiles( this.options.folder, this.filesEl, selectedHash ) 939 }, 940 loadFiles: function(mark, $toElement, selectedHash, substring) { 941 let key = mark + selectedHash; 942 if ( this.loading && this.loading == key ) { 943 return; 944 } 945 var self = this; 946 $toElement.empty(); 947
948 if ( this.options.folder != "recent" ) { 949 selectedHash = null; 950 } 951 952 if (this.options.folderType === 'custom') { 953 mark = this.options.folderType; 954 } 955 956 this.loading = key; 957 958 var params = { 959 mark: mark, 960 selectedHash: selectedHash, 961 fileType: this.options.fileType ? this.options.fileType : this.TYPE_IMAGE, 962 directoryId: self.options.directoryId, 963 orderBy: self.options.orderBy, 964 extensions: self.options.extensions 965 }; 966 967 ajaxCall( '/pl/fileservice/widget/get-by-mark', params, {}, function( response ) { 968 var filesNumber = 0; 969 970 for ( key in response.data.files ) { 971 var file = response.data.files[key]; 972 973 if (substring && !file.filename.toLowerCase().includes(substring.toLowerCase())) { 974 continue 975 } 976 977 if (!file.created_at) { 978 file.created_at = new Date().toISOString().split('T')[0] + ' ' + 979 new Date().toISOString().split('T')[1].slice(0, 8) 980 } 981 982 var $fileEl = self.createFileEl(file.hash, file.inFavorites, file.filename, file.created_at, file.can) 983 $fileEl.appendTo( $toElement ) 984 filesNumber++ 985 } 986 987 self.numberOfFiles = filesNumber 988 self.filesNumber.text(filesNumber + ' ' + self.getTypeLabel(filesNumber)) 989 self.loading = null; 990 } ) 991 }, 992 getTypeLabel: function(filesNumber) { 993 var self = this 994 var typeLabel; 995 if (self.options.fileDialogLabel !== null) { 996 typeLabel = self.options.fileDialogLabel; 997 } else { 998 switch (self.options.fileType) { 999 case self.TYPE_VIDEO: 1000 typeLabel = window.tt('common', 'video') 1001 break; 1002 case self.TYPE_AUDIO: 1003 typeLabel = window.tt('common', 'audio') 1004 break; 1005 case self.TYPE_IMAGE: 1006 typeLabel = window.tt('common', 'image|images', filesNumber) 1007 break; 1008 } 1009 } 1010 1011 return typeLabel 1012 }, 1013 selectFile: function( hash ) { 1014 this.options.owner.fileSelected( hash ) 1015 }, 1016 init: function( selectedHash ) { 1017 this.loadFiles(this.options.folder, this.filesEl, selectedHash, '') 1018 }, 1019 checkNeedToRefresh: function() { 1020 var self = this; 1021 $('.file-item img', this.filesEl).each(function() { 1022 var $img = $(this); 1023 var hash = $img.data('hash'); 1024 var src = self.isVideo(self.options.fileType) 1025 ? getVideoThumbnailUrl(hash, 200, 150) 1026 : getThumbnailUrl(hash, 200, 200); 1027 if ($img.attr('src') !== src) { 1028 $img.attr('src', src); 1029 } 1030 }); 1031 }, 1032 numberCases: function(number, one, two, five) { 1033 const cases = [2, 0, 1, 1, 1, 2]; 1034 const titles = [one, two, five]; 1035 return titles[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]]; 1036 }, 1037 moveFile: function (hash, newDirectoryId, $el) { 1038 var self = this 1039 1040 ajaxCall("/pl/fileservice/widget/move-file", 1041 {hash: hash, directory_id: newDirectoryId}, {}, function() { 1042 if (self.options.folderType === 'custom' && response.success) { 1043 $el.fadeOut() 1044 var newFileNumber = self.numberOfFiles - 1 1045 self.filesNumber.text(newFileNumber + ' ' + self.getTypeLabel(newFileNumber)) 1046 } 1047 }) 1048 }, 1049 markFileById: function(id, mark, positive, callback, type) { 1050 var self = this 1051 var data = { 1052 id: id, 1053 mark: mark, 1054 positive: positive ? 1 : 0, 1055 type: type, 1056 forceFileType: self.options.forceFileType 1057 } 1058 1059 if (mark !== 'favorites' && this.options.folderType === 'custom') { 1060 data.directory_id = this.options.directoryId; 1061 data.mark = 'custom'; 1062 } 1063 1064 if (!positive) { 1065 var newFileNumber = self.numberOfFiles - 1 1066 self.filesNumber.text(newFileNumber + ' ' + self.getTypeLabel(newFileNumber)) 1067 } 1068 1069 ajaxCall( "/pl/fileservice/widget/mark-by-id", data, {}, function(response) { 1070 if (response.success) { 1071 var hash = response.hash; 1072 var filename = response.filename; 1073 1074 var date = new Date().toISOString().split('T')[0] + ' ' + new Date().toISOString().split('T')[1].slice(0, 8) 1075 var $fileEl = self.createFileEl(hash, false, filename, date) 1076 1077 // ÐÑли Ñакой Ñже бÑл, ÑдалÑем его пеÑед добавлением Ñакого же 1078 var $existFileEl = self.getFileElByHash(hash); 1079 $existFileEl.remove(); 1080 1081 $fileEl.prependTo(self.filesEl); 1082 1083 self.numberOfFiles = ++self.numberOfFiles 1084 self.filesNumber.text(self.numberOfFiles + ' ' + self.getTypeLabel(self.numberOfFiles)) 1085 1086 } 1087 } ) 1088 }, 1089 isVideo: function(type) { 1090 return type === this.TYPE_VIDEO || type === this.TYPE_VIDEO_NOTE; 1091 } 1092 /* 1093 showFileSelected: function( fileKey, isSelected ) { 1094 var $files = this.filesEl.find( '.file-' + fileKey ) 1095 if ( isSelected ) { 1096 $files.addClass( "selected" ) 1097 } 1098 else { 1099 $files.removeClass( "selected" ) 1100 } 1101 }*/ 1102 1103} );
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.