/** *>*************************************************************************< * Name : uploadConstruct * Author : Ed Cradock * Date : 4 May 2006 * * Method : __construct * * @param object simplejax - Simplejax object for callback script * @return none * * Description: * Upload construct object to handle an uploaded file *>**************************************************************************< */ var _this; function uploadConstruct(simplejax, statusurl) { //Setup vital properties this.curWidth = 0; // Current width of loadbar this.destWidth = 0; // Destination width of loadbar this.speed = 5; // Loadbar speed this.startTime = 0; // Upload started this.checkUpdate = 4; // Refresh rate //Setup timers this.timer = ''; this.loadbarTimer = ''; // Error thresholds this.curFail = 0; // Current failures this.failMax = 5; // Maximum failures this.fail = false; // Generic failure this.errorPass = 2; // Concurrent errors before verified this.maxPasses = 2; // Maximum passes this.errorPasses = 1; // Current error passes // Processed signal messages this.signals = new Array ( /*0*/ 'The server could not process your request.', null, /*2*/ 'Your session has expired or cookies are not enabled, please refresh.', /*3*/ 'Filesize is invalid, please check the front page for the acceptable filesize.', /*4*/ 'Invalid filetype. Please only upload .rar files.', /*5*/ 'Filename contains illegal characters, please ensure no foreign characters or white space are present (spaces etc).', /*6*/ 'The captcha text entered does not match the image. Try again' ); //Assign the simplejax object simplejax.set('URL', statusurl); simplejax.set('CALLBACK', this.status); this.simplejax = simplejax; // Extract the instance (6 characters) var len = statusurl.length; this.instance = statusurl.substr((len -6), len-1); _this = this; } /** *>***************************************************************< * Method : status * Access : PUBLIC * * @param string dataRecv - Data received from simplejax connection * * @return boolean * * Description: * The main processing for the upload bar *>***************************************************************< */ uploadConstruct.prototype.status = function(dataRecv) { if(!dataRecv) _this.fail = true; var loadbar = eval(dataRecv); var error = loadbar.error; var signal = loadbar.signal; var skip = (typeof(loadbar.skip) != 'undefined') ? true : false; var context = loadbar.context; var failed = false; //Check for error if(_this.fail === true || (error == true && _this.errorPasses == _this.maxPasses) || (_this.curFail >= _this.failMax) || (skip == true)) { //Reset error passes _this.errorPasses = 1; /* Translate error signals */ var errStr; switch(signal) { case 0: errStr = _this.signals[0]; break; case 2: errStr = _this.signals[2]; break; case 3: errStr = _this.signals[3]; break; case 4: errStr = _this.signals[4]; break; case 5: errStr = _this.signals[5]; break; case 6: errStr = _this.signals[6]; break; default: errStr = 'Unknown error.'; } _this.getElem('hiddenFrame').src = ''; _this.getElem('uploadbox3').style.display = 'none'; //Set contextual error & change step _this.getElem('contextualError').innerHTML = errStr; _this.changeStep(6); _this.destruct(); return false; }else if(error === true && (_this.errorPasses < _this.maxPasses)){ _this.errorPasses++; return false; } var totalBytes = loadbar.bytesTotal; // File size in bytes var loadedBytes = loadbar.bytesLoaded; // Bytes loaded var percentage = (loadedBytes / totalBytes) * 100; percentage = Math.round(percentage); // Percentage complete /* Evil hack for ridiculously small rar files */ if(percentage == '98') percentage = '100'; var failed = false; if(isNaN(percentage) || typeof(percentage) == 'undefined') failed = true; //Calculate speed var dateObj = new Date(); var Curtime = dateObj.getTime() / 1000; Curtime = Math.round(Curtime); var elapsed = Curtime - _this.startTime; if(elapsed != 0) { var Speed = loadedBytes / elapsed; var KilaBytes = _this.speedInKB(Speed); var remaining = (totalBytes - loadedBytes) / Speed; _this.getElem('stats').innerHTML = remaining + " - "; remaining = Math.round(remaining); var finalOutput = _this.remaining(remaining); if(failed == false) { _this.getElem('stats').innerHTML = finalOutput + ' remaining | ' + KilaBytes + ' kb/s upload speed'; _this.getElem('tab2').innerHTML = percentage + '% .rar completed'; }else{ _this.curFail++; _this.getElem('stats').innerHTML = 'Loading...'; } } _this.destWidth = percentage; } /** *>***************************************************************< * Method : speed * Access : private * * @param int speed - current speed * * @return int * * Description: * Calculates speed in kb *>***************************************************************< */ uploadConstruct.prototype.speedInKB = function(speed) { var bits = speed * 8; var bytes = bits / 1024; var kilabytes = bytes / 8; return Math.round(kilabytes); } /** *>***************************************************************< * Method : remaining * Access : PUBLIC * * @param int remaining - Calculated time remaining * * @return string * * Description: * Creates a human readable time remaining from a second * representation *>***************************************************************< */ uploadConstruct.prototype.remaining = function(remaining) { var units = new Array(1, 60, 3600); units = units.reverse(); var unitNames = new Array('sec', 'min', 'hr'); unitNames = unitNames.reverse(); var output = new Array(); for(unit in units) { if(remaining >= units[unit]) { var quotient = Math.floor(remaining / units[unit]); remaining = remaining % units[unit]; output.push(quotient + ' ' + ((quotient == 1) ? unitNames[unit] : unitNames[unit] + 's')); } } if(output.length > 2) output.pop(); if(output.length > 1) { var last = output.pop(); var finalstr = output.join(', ') + ' and ' + last; }else var finalstr = output.pop(); return finalstr; } /** *>***************************************************************< * Method : update * Access : PUBLIC * * @param void * * @return void * * Description: * Set on a timer will update the upload bar every 100ms *>***************************************************************< */ uploadConstruct.prototype.update = function() { //Date object var dateObj = new Date(); //Set start time this.startTime = dateObj.getTime() / 1000; this.startTime = Math.round(this.startTime); //Invoke first off this.simplejax.invoke() //Set on interval this.timer = setInterval(function(){ _this.simplejax.invoke() }, (this.checkUpdate * 1000)); var _this = this; //Start loadbarTimer this.loadbarTimer = setInterval( function() { _this.curWidth = parseInt(_this.getElem('loadbar').style.width); if(_this.curWidth == 100 || _this.destWidth == 100) { setTimeout(function(){ _this.changeStep(4) }, 2000); _this.getElem('stats').innerHTML = 'Completed'; _this.getElem('loadbar').style.width = '100%'; _this.destruct(); }else if(_this.curWidth < _this.destWidth) { _this.curWidth += 1; _this.getElem('loadbar').style.width = _this.curWidth + '%'; } } , 100); } /** *>***************************************************************< * Method : getElem * Access : PUBLIC * * @param ElementID - Id for the element to return * * @return void * * Description: * Wrapper for returning the gebid for the instructed element *>***************************************************************< */ uploadConstruct.prototype.getElem = function(ElementID) { var element = document.getElementById(ElementID); var exists = eval(element); if(exists) return element; else { alert('Provided element \'' + ElementID + '\' does not exist'); return false; } } /** *>***************************************************************< * Method : changeStep * Access : PUBLIC * * @param int num - The step to switch to * * @return void * * Description: * Hides/shows a layer in numerical order *>***************************************************************< */ uploadConstruct.prototype.changeStep = function(num) { var layerFamily = 'uploadbox'; var previousSibling = this.getElem(layerFamily + (num - 1)); var element = this.getElem(layerFamily + num); if(element && previousSibling) { // Hide current step previousSibling.style.display = 'none'; previousSibling.style.visibility = 'hidden'; // Display next step element.style.display = 'block'; element.style.visibility = 'visible'; } } /** *>***************************************************************< * Method : startDialog * Access : PUBLIC * * @param void * * @return void * * Description: * Display step one and fade out background uploadbox *>***************************************************************< */ uploadConstruct.prototype.startDialog = function() { if(this.getElem('a').value == '') return false; var element = this.getElem('uploadbox1') element.style.display = 'block'; //Fade out all other elements var divs = this.getElem('CenterContainer').getElementsByTagName('div'); var opacValue = 10; var opacStop = 5; changeOpac = setInterval( function(){ for(var i = 0; i <= divs.length-1; i++) { if(divs[i].id.substr(0, 9) != 'uploadbox') { _this.getElem('logo').style.opacity = opacValue / 10; _this.getElem('logo').style.filter = 'alpha(opacity=' + (opacValue * 10) + ')'; divs[i].style.opacity = opacValue / 10; divs[i].style.filter = 'alpha(opacity=' + (opacValue * 10) + ')'; }else continue; } if(opacValue != opacStop) opacValue--; else clearInterval(changeOpac); }, 100); this.getElem('uploadit').disabled = true; } /** *>***************************************************************< * Method : terms * Access : PUBLIC * * @param object element - the element to check * * @return void * * Description: * Validates that the user has agreed to tos *>***************************************************************< */ uploadConstruct.prototype.terms = function(element) { if(element.checked == false) alert('You must agree to the terms of service before uploading.'); else { this.changeStep(2); this.upload(); } } /** *>***************************************************************< * Method : upload * Access : PUBLIC * * @param void * * @return void * * Description: * Triggers the upload to begin (controlled by the user) *>***************************************************************< */ uploadConstruct.prototype.upload = function() { if(this.getElem('checktwo').checked != true) { alert('You must agree to the terms of service before uploading.'); return false; }else this.getElem('agreed').value = '1'; //Set captcha id this.getElem('boxform').action += this.getElem('captcha').value; //Set up previously set values for hidden fields if(this.getElem('filedescription').value.length > 0) this.getElem('description').value = this.getElem('filedescription').value; if(this.getElem('checkone').checked == true) this.getElem('display').value = '1'; else this.getElem('display').value = '0'; document.forms['uploadForm'].submit(); this.changeStep(3); this.update(); } /** *>***************************************************************< * Method : showid * Access : PUBLIC * * @param void * * @return void * * Description: * Displays unique file id *>***************************************************************< */ uploadConstruct.prototype.showid = function() { prompt('Your unique id is located below:', this.instance); } /** *>***************************************************************< * Method : captcha * Access : PUBLIC * * @param void * * @return void * * Description: * Updates captcha id and reloads image *>***************************************************************< */ uploadConstruct.prototype.captcha = function() { //Refresh session var time = new Date(); this.getElem('hiddenFrame').src = 'captcha/set.php?instance=' + this.instance; //Give it some time to load the page setTimeout( function() { _this.getElem('uploadbox6').style.display = 'none'; _this.getElem('uploadbox2').style.display = 'block'; _this.getElem('uploadbox2').style.visibility = 'visible'; _this.getElem('captcha').value = ''; _this.getElem('captchaImg').src = '/captcha/image.php?instance=' + _this.instance + '&' + time.getTime(); }, 500); } /** *>***************************************************************< * Method : destruct * Access : private * * @param void * * @return void * * Description: * Destroys set intervals *>***************************************************************< */ uploadConstruct.prototype.destruct = function() { clearInterval(this.timer); clearInterval(this.loadbarTimer); }