/* * Copyright 2007-2011 Charles du Jeu * This file is part of AjaXplorer. * * AjaXplorer is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * AjaXplorer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with AjaXplorer. If not, see . * * The latest code can be found at . * Description : Class for simple XHR multiple upload, HTML5 only */ Class.create("XHRUploader", { _globalConfigs:null, initialize : function( formObject, mask ){ formObject = $(formObject); // Main form this.mainForm = formObject; // Where to write the list this.listTarget = formObject.select('div.uploadFilesList')[0]; // How many elements? this.count = 0; // Current index this.id = 0; var confs = ajaxplorer.getPluginConfigs("uploader"); if(confs) this._globalConfigs = confs; else this._globalConfigs = $H(); this.max = parseInt(this._globalConfigs.get("UPLOAD_MAX_NUMBER")) || 0; this.maxUploadSize = this._globalConfigs.get("UPLOAD_MAX_SIZE") || 0; this.namesMaxLength = ajaxplorer.getPluginConfigs("ajaxplorer").get("NODENAME_MAX_LENGTH"); this.mask = false; mask = this._globalConfigs.get("ALLOWED_EXTENSIONS"); if(mask && mask.trim() != ""){ this.mask = $A(mask.split(",")); this.maskLabel = this._globalConfigs.get("ALLOWED_EXTENSIONS_READABLE"); } this.crtContext = ajaxplorer.getUserSelection(); this.clearList(); // INITIALIZE GUI, IF NOT ALREADY! this.sendButton = formObject.select('div[id="uploadSendButton"]')[0]; this.sendButton.addClassName("disabled"); if(this.sendButton.observerSet){ this.totalProgressBar = this.mainForm.PROGRESSBAR; this.totalStrings = $('totalStrings'); this.uploadedString = $('uploadedString'); this.optionPane = this.mainForm.down('#uploader_options_pane'); this.optionPane.loadData(); this.updateTotalData(); if(window.UploaderDroppedFiles){ var files = window.UploaderDroppedFiles; for(var i=0;i\ '+MessageHash[258]+' : 0 '+MessageHash[259]+' : 0Kb\
\
\ '+MessageHash[256]+' : 0%\
'); var options = { animate : false, // Animate the progress? - default: true showText : false, // show text with percentage in next to the progressbar? - default : true width : 154, // Width of the progressbar - don't forget to adjust your image too!!! boxImage : ajxpResourcesFolder+'/images/progress_box.gif', // boxImage : image around the progress bar barImage : ajxpResourcesFolder+'/images/progress_bar.gif', // Image to use in the progressbar. Can be an array of images too. height : 4 // Height of the progressbar - don't forget to adjust your image too!!! }; $('clear_list_button').observe("click", function(e){ ajaxplorer.actionBar.multi_selector.clearList(); ajaxplorer.actionBar.multi_selector.updateTotalData(); }); this.optionPane = this.createOptionsPane(); this.optionPane.loadData(); this.totalProgressBar = new JS_BRAMUS.jsProgressBar($('pgBar_total'), 0, options); this.mainForm.PROGRESSBAR = this.totalProgressBar; this.totalStrings = $('totalStrings'); this.uploadedString = $('uploadedString'); if(window.UploaderDroppedFiles){ var files = window.UploaderDroppedFiles; for(var i=0;i'); optionPane.insert('
\ '+MessageHash[339]+' '+MessageHash[263]+' \ '+MessageHash[6]+' \ '+MessageHash[340]+'
\ Options '+MessageHash[337]+'    \ '+MessageHash[338]+'\
'); optionPane.hide(); optionPane.autoSendCheck = optionPane.down('#uploader_auto_send'); optionPane.autoCloseCheck = optionPane.down('#uploader_auto_close'); optionPane.optionsStrings = optionPane.down('#uploader_options_strings'); optionPane.existingRadio = optionPane.select('input[name="uploader_existing"]'); var totalPane = this.mainForm.down('#total_files_list'); totalPane.insert({after:optionPane}); optionPane.showPane = function(){ totalPane.hide();optionPane.show(); modal.refreshDialogAppearance(); } optionPane.hidePane = function(){ totalPane.show();optionPane.hide(); modal.refreshDialogAppearance(); } optionPane.autoSendCheck.observe("click", function(e){ var autoSendOpt = optionPane.autoSendCheck.checked; if(ajaxplorer.user){ ajaxplorer.user.setPreference('upload_auto_send', (autoSendOpt?'true':'false')); ajaxplorer.user.savePreference('upload_auto_send'); }else{ setAjxpCookie('upload_auto_send', (autoSendOpt?'true':'false')); } }); optionPane.autoCloseCheck.observe("click", function(e){ var autoCloseOpt = optionPane.autoCloseCheck.checked; if(ajaxplorer.user){ ajaxplorer.user.setPreference('upload_auto_close', (autoCloseOpt?'true':'false')); ajaxplorer.user.savePreference('upload_auto_close'); }else{ setAjxpCookie('upload_auto_close', (autoCloseOpt?'true':'false')); } }); optionPane.existingRadio.each(function(el){ el.observe("click", function(e){ var value = el.value; if(ajaxplorer.user){ ajaxplorer.user.setPreference('upload_existing', value); ajaxplorer.user.savePreference('upload_existing'); }else{ setAjxpCookie('upload_existing', value); } }); }); optionPane.getExistingBehaviour = function(){ var value; optionPane.existingRadio.each(function(el){ if(el.checked) value = el.value; }); return value; }; optionPane.loadData = function(){ var message = '' + MessageHash[281] + ' '; message += '  '+ MessageHash[282] + ':' + roundSize(this.maxUploadSize, ''); message += '  '+ MessageHash[284] + ':' + this.max; optionPane.optionsStrings.update(message); var autoSendValue = false; if(ajaxplorer.user && ajaxplorer.user.getPreference('upload_auto_send')){ autoSendValue = ajaxplorer.user.getPreference('upload_auto_send'); autoSendValue = (autoSendValue =="true" ? true:false); }else if(this._globalConfigs.get('DEFAULT_AUTO_START')){ autoSendValue = this._globalConfigs.get('DEFAULT_AUTO_START'); }else{ var value = getAjxpCookie('upload_auto_send'); autoSendValue = ((value && value == "true")?true:false); } optionPane.autoSendCheck.checked = autoSendValue; var autoCloseValue = false; if(ajaxplorer.user && ajaxplorer.user.getPreference('upload_auto_close')){ autoCloseValue = ajaxplorer.user.getPreference('upload_auto_close'); autoCloseValue = (autoCloseValue =="true" ? true:false); }else if(this._globalConfigs.get('DEFAULT_AUTO_CLOSE')){ autoCloseValue = this._globalConfigs.get('DEFAULT_AUTO_CLOSE'); }else{ var value = getAjxpCookie('upload_auto_close'); autoCloseValue = ((value && value == "true")?true:false); } optionPane.autoCloseCheck.checked = autoCloseValue; var existingValue = 'overwrite'; if(ajaxplorer.user && ajaxplorer.user.getPreference('upload_existing')){ existingValue = ajaxplorer.user.getPreference('upload_existing'); }else if(this._globalConfigs.get('DEFAULT_EXISTING')){ existingValue = this._globalConfigs.get('DEFAULT_EXISTING'); }else if(getAjxpCookie('upload_existing')){ var value = getAjxpCookie('upload_existing'); } optionPane.down('#uploader_existing_' + existingValue).checked = true; }.bind(this); return optionPane; }, /** * Add a new file input element */ initElement : function( ){ var element = this.mainForm.down('.dialogFocus'); element.setAttribute("multiple", "true"); if(Prototype.Browser.Gecko) element.setStyle({left:'-100px'}); element.observe("change", function(event){ var files = element.files; for(var i=0;i this.maxUploadSize){ alert(MessageHash[211]); return; } if(this.max && this.listTarget.childNodes.length == this.max){ alert(MessageHash[365].replace("%s", this.max)); return; } var basename = getBaseName(file.name); if(basename.length > this.namesMaxLength){ alert(MessageHash[393].replace("%s", this.namesMaxLength)); } if(this.mask){ var ext = getFileExtension(file.name); if(!this.mask.include(ext)){ alert(MessageHash[367] + this.mask.join(', ') + (this.maskLabel? " ("+ this.maskLabel +")":"" ) ); return; } } // GET VALUE FROM FILE OBJECT var label = file.name; var maxLength = 63; if(label.length > maxLength){ label = label.substr(0,20) + '[...]' + label.substr(label.length-(maxLength-20), label.length); } var item = new Element( 'div' ); // Delete button var delButton = new Element( 'img', { src:ajxpResourcesFolder+'/images/actions/16/editdelete.png', className : 'fakeUploadButton', align : 'absmiddle', style : '-moz-border-radius:3px;border-radius:3px;float:left;margin:1px 7px 2px 0px;padding:3px;width:16px;background-position:center top;', title : MessageHash[257] }); delButton.observe("click", function(e){ if(item.xhr){ try{ item.xhr.abort(); }catch(e){} } item.remove(); this.updateTotalData(); }.bind(this)); // Add button & text item.insert( delButton ); item.insert( label ); // Add it to the list this.listTarget.insert( item ); var id = 'pgBar_' + (this.listTarget.childNodes.length + 1); this.createProgressBar(item, id); item.file = file; item.updateStatus('new'); this.updateTotalData(); this.sendButton.removeClassName("disabled"); }, createProgressBar : function(item, id){ var div = new Element('div', {id:id, style:'-moz-border-radius:2px;border-radius:2px;'}); div.setStyle({ border:'1px solid #ccc', backgroundColor: 'white', marginTop: '7px', height:'4px', padding:0, width:'154px' }); var percentText = new Element('span', {style:"float:right;display:block;width:30px;text-align:center;"}); var statusText = new Element('span', {style:"float:right;display:block;width:66px;overflow:hidden;text-align:right;"}); var container = new Element('div', {style:'border:none;padding:0;padding-right:5px;color: #777;'}); container.insert(statusText); container.insert(percentText); container.insert(div); item.insert(container); item.percentText = percentText; var options = { animate : false, showText : false, width : 154, boxImage : ajxpResourcesFolder+'/images/progress_box.gif', barImage : ajxpResourcesFolder+'/images/progress_bar.gif', height : 4 }; item.pgBar = new JS_BRAMUS.jsProgressBar(div, 0, options); item.statusText = statusText; item.updateProgress = function(computableEvent, percentage){ if(percentage == null){ percentage = Math.round((computableEvent.loaded * 100) / computableEvent.total); this.bytesLoaded = computableEvent.loaded; } if(!this.percentValue || this.percentValue != percentage){ this.percentText.innerHTML = percentage + '%'; this.pgBar.setPercentage(percentage); } this.percentValue = percentage; }.bind(item); item.updateStatus = function(status){ this.status = status; var messageIds = { "new" : 433, "loading":434, "loaded":435, "error":436 }; try{ status = window.MessageHash[messageIds[status]]; }catch(e){}; this.statusText.innerHTML = "["+status+"]"; }.bind(item); }, updateTotalData : function(){ var count = 0; var size = 0; var uploaded = 0; var percentage = 0; if(this.listTarget.childNodes.length){ $A(this.listTarget.childNodes).each(function(item){ if(item.status == 'new'){ size += item.file.size; count ++; }else if(item.status == 'loading'){ size += item.file.size; count ++; uploaded += item.bytesLoaded; }else if(item.status == 'loaded'){ size += item.file.size; count ++; uploaded += item.file.size; } }); }else{ if(this.sendButton) this.sendButton.addClassName("disabled"); } if(size){ var percentage = Math.round(100*uploaded/size); } this.totalProgressBar.setPercentage(percentage, true); this.totalStrings.update(MessageHash[258]+' ' + count + ' '+MessageHash[259]+' ' +roundSize(size, 'b')); this.uploadedString.update(MessageHash[256]+' : ' + percentage + '%'); }, submit : function(){ this.submitNext(); }, submitNext : function(){ if(item = this.getNextItem()){ document.fire("ajaxplorer:longtask_starting"); this.sendFileMultipart(item); }else{ if(this.hasLoadingItem()) return; ajaxplorer.fireContextRefresh(); if(this.optionPane.autoCloseCheck.checked){ hideLightBox(true); } document.fire("ajaxplorer:longtask_finished"); } }, getNextItem : function(){ for(var i=0;i this.fileSize){ chunkLength = this.fileSize - this.cursor + 1; } var blob = this.item.file.slice(this.cursor, chunkLength); this.cursor += chunkLength; var filename = this.fileName+"_part_"+this.fIndex; this.fIndex ++; reader.onloadend = function(evt){ if (evt.target.readyState == FileReader.DONE) { item.statusText.update('[building query]'); this.fileData = evt.target.result; this.xhrSendAsBinary( filename, evt.target.result, evt.target.result.length, this.item, this.sendNextBlob.bind(this) ); } }.bind(this); reader.onprogress = function(evt){ if (evt.lengthComputable) { var percentLoaded = Math.round((evt.loaded / evt.total) * 100); this.item.statusText.update('[reading '+percentLoaded+'%]'); } }.bind(this); this.item.statusText.update('[reading data]'); reader.readAsBinaryString(blob); }else{ this.sendUnifyQuery(this.fileName, this.fIndex); delete this.item; } }, sendUnifyQuery : function(fileName, lastIndex){ var conn = new Connexion(); conn.setParameters({ "get_action" : "upload_chunks_unify", "file_name" : fileName, "dir" : this.crtContext.getContextNode().getPath() }); for(var i=0;i