Index: branches/5.2.x/core/admin_templates/js/uploader/uploader.js =================================================================== --- branches/5.2.x/core/admin_templates/js/uploader/uploader.js (revision 16557) +++ branches/5.2.x/core/admin_templates/js/uploader/uploader.js (revision 16558) @@ -1,688 +1,688 @@ function Uploader(id, params) { this.id = id; this.instance = null; // normalize params if (isNaN(parseInt(params.multiple))) { // ensure that maximal file number is greater then zero params.multiple = 1; } params.allowedFilesize = this._normalizeFilesize(params.allowedFilesize); // set params to uploader this.ready = false; this.params = params; this._ensureDefaultValues(); this.files = []; this.files_count = 0; this.deleted = []; // because used outside this class this.deleteURL = params.deleteURL; this.enableUploadButton(); this._fixFileExtensions(); this._attachEventHandler(); var $me = this; if ( this.params.ajax ) { $(document).bind('FormManager.WindowManager.Ready', function ($e) { $me.init(); }); } else { $(document).ready(function() { $me.init(); }); } } /* ==== Private methods ==== */ Uploader.prototype._fixFileExtensions = function() { this.params.allowedFiletypes = this.params.allowedFiletypes.replace(/\*\./g, '').replace(/;/g, ','); }; Uploader.prototype._attachEventHandler = function() { var $me = this; $(document).bind('UploadsManager.Uploader.' + crc32(this.id), function ($e, $method) { $me[$method].apply($me, Array.prototype.slice.call(arguments, 2)); }); }; Uploader.prototype._ensureDefaultValues = function() { // Upload backend settings var $me = this, $defaults = { baseUrl : '', uploadURL : '', deleteURL : '', previewURL : '', allowedFiletypes : '*.*', allowedFiletypesDescription : 'All Files', allowedFilesize : 0, // Default zero means "unlimited" multiple : 0, field : '', thumb_format: '', urls : '', names : '', sizes : '', ajax: false }; $.each($defaults, function ($param_name, $param_value) { if ($me.params[$param_name] == null) { // console.log('setting default value [', $param_value, '] for missing parameter [', $param_name, '] instead of [', $me.params[$param_name], ']'); $me.params[$param_name] = $param_value; } }); }; Uploader.prototype._normalizeFilesize = function($file_size) { var $normalize_size = parseInt($file_size); if (isNaN($normalize_size)) { return $file_size; } // in kilobytes (flash doesn't recognize numbers, that are longer, then 9 digits) return $normalize_size / 1024; }; Uploader.prototype._prepareFiles = function() { var ids = '', names = ''; // process uploaded files for (var f = 0; f < this.files.length; f++) { if (isset(this.files[f].uploaded) && !isset(this.files[f].temp)) { continue; } ids += this.files[f].id + '|'; names += this.files[f].name + '|'; } ids = ids.replace(/\|$/, ''); names = names.replace(/\|$/, ''); document.getElementById(this.id+'[tmp_ids]').value = ids; document.getElementById(this.id+'[tmp_names]').value = names; document.getElementById(this.id+'[tmp_deleted]').value = this.deleted.join('|'); }; Uploader.prototype._formatSize = function (bytes) { var kb = Math.round(bytes / 1024); if (kb < 1024) { return kb + ' KB'; } var mb = Math.round(kb / 1024 * 100) / 100; return mb + ' MB'; }; /* ==== Public methods ==== */ Uploader.prototype.init = function() { var $me = this, $uploader_options = { - runtimes : 'flash,html4', // html5 + runtimes : 'html5,flash,html4', chunk_size: '1mb', browse_button : this.id + '_browse_button', container: this.id + '_container', url : this.params.uploadURL, flash_swf_url : this.params.baseUrl + '/Moxie.swf', multi_selection: this.params.multiple > 1, filters : {}, init: {} }; if ( this.params.allowedFilesize > 0 ) { $uploader_options.filters.max_file_size = this.params.allowedFilesize + 'kb'; } if ( this.params.allowedFiletypes != '*' ) { $uploader_options.filters.mime_types = [ {title : this.params.allowedFiletypesDescription, extensions : this.params.allowedFiletypes} ]; } this.IconPath = this.params.IconPath ? this.params.IconPath : '../admin_templates/img/browser/icons'; $uploader_options.init['Init'] = function(uploader) { $me.onReady(); }; $uploader_options.init['FilesAdded'] = function(uploader, files) { $.each(files, function (index, file) { $me.onFileQueued(file); }); $me.startUpload(); }; $uploader_options.init['FilesRemoved'] = function(uploader, files) { $.each(files, function (index, file) { if ( file.status != plupload.QUEUED ) { uploader.stop(); uploader.start(); } }); }; $uploader_options.init['Error'] = function(uploader, error) { $me.onError(error); }; $uploader_options.init['BeforeUpload'] = function(uploader, file) { return $me.onUploadFileStart(uploader, file); }; $uploader_options.init['UploadProgress'] = function(uploader, file) { $me.onUploadProgress(file); }; $uploader_options.init['FileUploaded'] = function(uploader, file, response) { $me.onUploadFinished(file, response); }; this.instance = new plupload.Uploader($uploader_options); Application.setHook( 'm:OnAfterFormInit', function () { $me.renderBrowseButton(); } ); this.refreshQueue(); }; Uploader.prototype.refreshQueue = function($params) { if ( $params !== undefined ) { $.extend(true, this.params, $params); document.getElementById(this.id+'[upload]').value = this.params.names; document.getElementById(this.id+'[order]').value = this.params.names; } // 1. remove queue DIVs for files, that doesn't exist after upload was made var $new_file_ids = this.getFileIds(this.params.names); for (var $i = 0; $i < this.files.length; $i++) { if ( !in_array(this.files[$i].id, $new_file_ids) ) { this.updateQueueFile($i, true); } } this.files = []; this.files_count = 0; this.deleted = []; if (this.params.urls != '') { var urls = this.params.urls.split('|'), names = this.params.names.split('|'), sizes = this.params.sizes.split('|'); for (var i = 0; i < urls.length; i++) { var a_file = { // original properties from Uploader id : this.getUploadedFileId(names[i]), name : names[i], size: sizes[i], percent: 100, // custom properties url : urls[i], uploaded : 1 }; this.files_count++; this.files.push(a_file); } this.updateInfo(); } }; Uploader.prototype.getFileIds = function($file_names) { var $ret = []; if ( !$file_names.length ) { return $ret; } if ( !$.isArray($file_names) ) { $file_names = $file_names.split('|'); } for (var i = 0; i < $file_names.length; i++) { $ret.push(this.getUploadedFileId($file_names[i])) } return $ret; }; Uploader.prototype.getUploadedFileId = function($file_name) { return 'uploaded_' + crc32($file_name); }; Uploader.prototype.enableUploadButton = function() { // enable upload button, when plupload runtime is fully loaded $('#' + jq(this.id + '_browse_button')).prop('disabled', false).removeClass('button-disabled'); }; Uploader.prototype.renderBrowseButton = function() { this.instance.init(); }; Uploader.prototype.remove = function() { this.instance.destroy(); }; Uploader.prototype.isImage = function($filename) { this.removeTempExtension($filename).match(/\.([^.]*)$/); var $ext = RegExp.$1.toLowerCase(); return $ext.match(/^(bmp|gif|jpg|jpeg|png)$/); }; Uploader.prototype.getFileIcon = function($filename) { this.removeTempExtension($filename).match(/\.([^.]*)$/); var $ext = RegExp.$1.toLowerCase(), $ext_overrides = { 'doc': '^(docx|dotx|docm|dotm)$', 'xls': '^(xlsx|xltx|xlsm|xltm|xlam|xlsb)$', 'ppt': '^(pptx|potx|ppsx|ppam|pptm|potm|ppsm)$' }; $.each($ext_overrides, function ($new_ext, $expression) { var $regexp = new RegExp($expression); if ( $ext.match($regexp) ) { $ext = $new_ext; return false; } return true; }); var $icon = $ext.match(/^(ai|avi|bmp|cs|dll|doc|dot|exe|fla|gif|htm|html|jpg|js|mdb|mp3|pdf|ppt|rdp|swf|swt|txt|vsd|xls|xml|zip)$/) ? $ext : 'default.icon'; return this.IconPath + '/' + $icon + '.gif'; }; Uploader.prototype.removeTempExtension = function ($file) { return $file.replace(/(_[\d]+)?\.tmp$/, ''); }; Uploader.prototype.getQueueElement = function($file) { var $me = this, $ret = '', $icon_image = this.getFileIcon($file.name), $file_label = this.removeTempExtension($file.name) + ' (' + this._formatSize($file.size) + ')', $need_preview = false; if (isset($file.uploaded)) { // add deletion checkbox $need_preview = (this.params.thumb_format.length > 0) && this.isImage($file.name); $ret += '
'; // add icon based on file type $ret += '
'; if ($need_preview) { $ret += ''; } else { $ret += ''; } $ret += '
'; // add filename + preview link $ret += '
' + $file_label + '
'; } else { // add icon based on file type $ret += '
'; // add filename $ret += '
' + $file_label + '
'; // add empty progress bar $ret += '
'; // add cancel upload link $ret += '
Cancel
'; } $ret += '
'; $ret = $('
' + $ret + '
'); // set click events $('.delete-file-btn', $ret).click(function ($e) { $(this).prop('checked', !$me.deleteFile($file)); }); $('.cancel-upload-btn', $ret).click(function ($e) { $me.removeFile($file); $e.preventDefault(); }); // prepare auto-loading preview var $image = $('img.thumbnail-image', $ret); if ($image.length > 0) { var $tmp_image = new Image(); $tmp_image.src = $image.attr('large_src'); $($tmp_image).load ( function ($e) { $image.attr('src', $tmp_image.src).addClass('thumbnail'); } ); } return $ret; }; Uploader.prototype.getSortedFiles = function($ordered_queue) { var $me = this; var $ret = $.map($me.files, function ($elem, $index) { var $file_id = $ordered_queue[$index].replace(/_queue_row$/, ''), $file_index = $me.getFileIndex({id: $file_id}); return $me.files[$file_index].name; }); return $ret; }; Uploader.prototype.updateQueueFile = function($file_index, $delete_file) { var $queue_container = $( jq('#' + this.id + '_queueinfo') ); if ($delete_file !== undefined && $delete_file) { $( jq('#' + this.files[$file_index].id + '_queue_row') ).remove(); if (this.files.length == 1) { $queue_container.css('margin-top', '0px'); } return ; } var $ret = this.getQueueElement(this.files[$file_index]), $row = $(jq('#' + this.files[$file_index].id + '_queue_row')); if ($row.length > 0) { // file round -> replace $row.replaceWith($ret); } else { // file not found - add $( jq('#' + this.id + '_queueinfo') ).append($ret); $queue_container.css('margin-top', '8px'); } }; Uploader.prototype.updateInfo = function($file_index, $prepare_only) { if ($prepare_only === undefined || !$prepare_only) { if ($file_index === undefined) { for (var f = 0; f < this.files.length; f++) { this.updateQueueFile(f); } } else { this.updateQueueFile($file_index); } } this._prepareFiles(); }; Uploader.prototype.updateProgressOnly = function ($file_index) { var $progress_code = '
'; $('#' + this.files[$file_index].id + '_progress').html($progress_code); }; Uploader.prototype.removeFile = function (file) { var count = 0, n_files = [], $to_delete = []; if (!isset(file.uploaded)) { this.instance.removeFile(file); } $.each(this.files, function (f, current_file) { if ( current_file.id == file.id || current_file.name == file.name ) { $to_delete.push(f); } else { n_files.push(current_file); count++; } }); for (var $i = 0; $i < $to_delete.length; $i++) { this.updateQueueFile($to_delete[$i], true); } this.files = n_files; this.files_count = count; this.updateInfo(undefined, true); }; Uploader.prototype.hasQueue = function() { for (var f = 0; f < this.files.length; f++) { if (isset(this.files[f].uploaded)) { continue; } return true; } return false; }; Uploader.prototype.startUpload = function() { if ( this.hasQueue() ) { this.instance.start(); } }; Uploader.prototype.deleteFile = function(file, confirmed) { if (!confirmed && !confirm('Are you sure you want to delete "' + file.name + '" file?')) { return false; } var $me = this; $.get( this.getDeleteUrl(file), function ($data) { $me.removeFile(file); $me.deleted.push(file.name); $me.updateInfo(undefined, true); } ); return true; }; Uploader.prototype.onUploadFileStart = function(uploader, file) { var $upload_url = this.params.uploadURL, $file_index = this.getFileIndex(file), $extra_params = { field: this.params.field, id: file.id, flashsid: this.params.flashsid }; this.files[$file_index].percent = file.percent; this.updateProgressOnly($file_index); $upload_url += ($upload_url.indexOf('?') ? '&' : '?'); $.each($extra_params, function ($param_name, $param_value) { $upload_url += $param_name + '=' + encodeURIComponent($param_value) + '&'; }); uploader.settings.url = $upload_url; return true; }; Uploader.prototype.onUploadProgress = function(file) { var $file_index = this.getFileIndex(file); this.files[$file_index].percent = file.percent; this.updateProgressOnly($file_index); }; Uploader.prototype.onFileQueued = function(file) { if (this.files_count >= this.params.multiple) { // new file can exceed allowed file number if (this.params.multiple > 1) { // it definitely exceed it var $error = { 'file': file, 'code': 'ERROR_1', 'message': 'Files count exceeds allowed limit.' }; this.instance.trigger('Error', $error); } else { // delete file added this.files_count++; this.files.push(file); if (this.files[0].uploaded) { this.deleteFile(this.files[0], true); } else { this.instance.removeFile(file); } } } else { // new file will not exceed allowed file number this.files_count++; this.files.push(file); } this.updateInfo(this.files.length - 1); }; Uploader.prototype.onError = function(error) { this.removeFile(error.file); if ( error.code == plupload.FILE_SIZE_ERROR ) { error.message = 'File size exceeds allowed limit.'; } else if ( error.code == plupload.FILE_EXTENSION_ERROR ) { error.message = 'File is not an allowed file type.'; } setTimeout(function () { alert('Error: ' + error.message + "\n" + 'Occurred on file ' + error.file.name); }, 0); }; Uploader.prototype.onUploadFinished = function(file, response) { var $json_response = eval('(' + response.response + ')'); if (response.status != 200) { return ; } if ( $json_response.status == 'error' ) { var $error = { 'file': file, 'code': $json_response.error.code, 'message': $json_response.error.message }; this.instance.trigger('Error', $error); return ; } // new uploaded file name returned by OnUploadFile event file.name = $json_response.result; this.onUploadFileComplete(file); }; Uploader.prototype.onUploadFileComplete = function(file) { // file was uploaded OR file upload was cancelled var $file_index = this.getFileIndex(file); if ($file_index !== false) { // in case if file upload was cancelled, then no info here this.files[$file_index].name = file.name; this.files[$file_index].percent = file.percent; this.files[$file_index].temp = 1; this.files[$file_index].uploaded = 1; this.files[$file_index].url = this.getPreviewUrl(this.files[$file_index]); this.updateInfo($file_index); } }; Uploader.prototype.getPreviewUrl = function($file, $preview) { var $url = this.getUrl(this.params.previewURL, $file); if ( $preview !== undefined && $preview === true ) { $url += '&thumb=1'; } return $url; }; Uploader.prototype.getDeleteUrl = function($file) { return this.getUrl(this.params.deleteURL, $file); }; Uploader.prototype.getUrl = function($base_url, $file) { var $replacements = { '#FILE#': $file.name, '#FIELD#': this.params.field, '#FIELD_ID#': this.id }; var $url = $base_url; $.each($replacements, function ($replace_from, $replace_to) { $url = $url.replace($replace_from, encodeURIComponent($replace_to)); }); if ( $file.temp !== undefined && $file.temp ) { $url += '&tmp=1&id=' + $file.id; } return $url; }; Uploader.prototype.getFileIndex = function(file) { for (var f = 0; f < this.files.length; f++) { if (this.files[f].id == file.id) { return f; } } return false; }; Uploader.prototype.onReady = function() { this.ready = true; UploadsManager.onReady(); -}; \ No newline at end of file +};