From dde0980decee1172805d1fcd98eb5bfc3657b763 Mon Sep 17 00:00:00 2001 From: taggon Date: Thu, 4 Nov 2010 04:42:14 +0000 Subject: [PATCH] =?UTF-8?q?#19239406=20=EC=97=85=EB=A1=9C=EB=8D=94=20?= =?UTF-8?q?=ED=94=8C=EB=9F=AC=EA=B7=B8=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://xe-core.googlecode.com/svn/sandbox@7786 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- common/js/plugins/uploader/plugin.load | 1 + common/js/plugins/uploader/uploader.js | 773 ++++++++++++++++++++++++ common/js/plugins/uploader/uploader.swf | Bin 0 -> 3573 bytes 3 files changed, 774 insertions(+) create mode 100644 common/js/plugins/uploader/plugin.load create mode 100644 common/js/plugins/uploader/uploader.js create mode 100644 common/js/plugins/uploader/uploader.swf diff --git a/common/js/plugins/uploader/plugin.load b/common/js/plugins/uploader/plugin.load new file mode 100644 index 000000000..c24671bf6 --- /dev/null +++ b/common/js/plugins/uploader/plugin.load @@ -0,0 +1 @@ +uploader.js diff --git a/common/js/plugins/uploader/uploader.js b/common/js/plugins/uploader/uploader.js new file mode 100644 index 000000000..2eac29527 --- /dev/null +++ b/common/js/plugins/uploader/uploader.js @@ -0,0 +1,773 @@ +/** + * Uploader + */ +(function($){ + +var runtime; + +var Uploader = xe.createApp('Uploader', { + settings : {}, + files : [], + init : function(browseButton, opts) { + if (!runtime) { + $.each(runtimes, function(key,obj) { + if (obj.check()) { runtime = key; return false; } + }); + } + + this.queue = []; + this.settings = $.extend({ + filters : {}, + params : {} + }, opts); + this.settings.browse = $(browseButton); + + if (!this.settings.browse.length) throw 'The parameter browseButton is not valid object or selector.'; + + var s = this.settings; + + if (s.dropzone) s.dropzone = $(s.dropzone); + if (s.upload) s.upload = $(s.upload); + + runtimes[runtime].create(this, this.settings); + }, + API_ON_START : function(sender, params) { + if ($.isFunction(this.settings.onstart)) { + this.settings.onstart.apply(this, params); + } + }, + API_ON_FINISH : function(sender, params) { + if ($.isFunction(this.settings.onfinish)) { + this.settings.onfinish.apply(this, params); + } + }, + API_ON_SELECT : function(sender, params) { + if ($.isFunction(this.settings.onselect)) { + this.settings.onselect.apply(this, params); + } + }, + API_ON_STARTONE : function(sender, params) { + if ($.isFunction(this.settings.onstartone)) { + this.settings.onstartone.apply(this, params); + } + }, + API_ON_FINISHONE : function(sender, params) { + if ($.isFunction(this.settings.onfinishone)) { + this.settings.onfinishone.apply(this, params); + } + }, + API_ON_PROGRESS : function(sender, params) { + if ($.isFunction(this.settings.onprogress)) { + this.settings.onprogress.apply(this, params); + } + }, + API_START : function(sender, params) { + var files = $.grep(this.files, function(file){ return (file.status != 'DONE') }); + + runtimes[runtime].upload(this, this.settings, files); + }, + API_STOP : function(sender, params) { + runtimes[runtime].stop(this, this.settings); + }, + API_SET_PARAM : function(sender, params) { + this.settings.params[params[0]] = params[1]; + }, + API_DEL_PARAM : function(sender, params) { + try { + delete this.settings.params[params[0]]; + } catch(e){} + } +}); + +// Shortcut function in jQuery +$.fn.uploader = function(opts) { + var u = new Uploader(this.eq(0), opts); + if (u) xe.registerApp(u); + + return u; +}; + +// Shortcut function in XE +xe.createUploader = function(browseButton, opts) { + var u = new Uploader(browseButton, opts); + if (u) xe.registerApp(u); + + return u; +}; + +// {{{ runtimes +var runtimes = {}; + +// Google Gears +runtimes.gears = { + _desktop : null, + create : function(uploader, settings) { + var self = this; + var opt = {filter:[]}; + + if (!window.google || google.gears || !google.gears.factory) this.createFactory(); + if (!this._desktop && google.gears.factory) this._desktop = google.gears.factory.create('beta.desktop'); + if (!this._desktop) return false; + + // browse button + settings.browse.click(function(){ + self._desktop.openFiles(onselect, opt); + return false; + }); + + // file filters + $.each(settings.filters, function(k,v){ opt.filter=$.merge(opt.filter,v.split(' ')) }); + opt.filter = $.map(opt.filter, function(ext){ return '.'+ext }); + + // select file callback + function onselect(files) { + var old_length = uploader.files.length; + + $.each(files, function() { + uploader.files.push(new File(this, this.blob.length)) + }); + + uploader.cast('ON_SELECT', [uploader.files, old_length]); + } + + // drag and drop + if (settings.dropzone) { + settings.dropzone + .bind('dragover', function(){ return false; }) + .bind('drop', function(event) { + var data = self._desktop.getDragData(event.originalEvent, 'application/x-gears-files'); + var files = $.grep(data.files, function(file) { + var ext = file.name.match(/\.[a-z0-9]+$/)[0] || ''; + return ($.inArray(ext, opt.filter)!=-1); + }); + + onselect(files); + + return false; + }); + } + + // upload + if (settings.upload) { + settings.upload.click(function(){ + uploader.cast('START'); + return false; + }); + } + }, + createFactory : function() { + var f, m; + + if (!window.google) window.google = {}; + if (!google.gears) { + google.gears = {}; + + if (typeof(GearsFactory)!='undefined'){f = new GearsFactory()} // Firefox + else { + try{ // IE + f = new ActiveXObject('Gears.Factory'); + }catch(e){ // Safari + if ((typeof(m=navigator.mimeTypes)!='undefined')&&(m['application/x-googlegears'])) { + f = $('').appendTo(document.documentElement); + } + } + } + if(f) google.gears.factory = f; + } + }, + check : function() { + if ((window.google && google.gears && google.gears.factory) || (typeof(GearsFactory) != 'undefined')) return true; + + try { + this.factory = new ActiveXObject('Gears.factory'); + return true; + } catch(e) { + var m = navigator.mimeTypes; + if (m && m['application/x-googlegears']) return true; + } + }, + upload : function(uploader, settings, files) { + if (uploader.request || !files.length) return false; + + uploader.cast('ON_START'); + + (function uploadNext() { + var file = files.shift(); + var req = google.gears.factory.create('beta.httprequest'); + var blob = google.gears.factory.create('beta.blobbuilder'); + var bndr = '--------------xe-boundary'+random(); + var data, gap; + + $.each(settings.params, function(key, val) { + blob.append( + '--'+bndr+'\r\n'+ + 'Content-Disposition: form-data; name="'+key+'"\r\n\r\n'+ + val+'\r\n' + ); + }); + + blob.append( + '--'+bndr+'\r\n'+ + 'Content-Disposition: form-data; name="Filedata"; filename="'+file.name+'"\r\n'+ + 'Content-Type: application/octet-stream\r\n\r\n' + ); + + blob.append(file.object.blob); + blob.append('\r\n--'+bndr+'--\r\n'); + + data = blob.getAsBlob(); + gap = data.length - file.size; + + uploader.cast('ON_STARTONE', [file]); + + req.open('POST', settings.url); + req.setRequestHeader('Content-Type', 'multipart/form-data; boundary='+bndr); + req.onreadystatechange = function() { + if (req.readyState == 1) { + file.status = 'UPLOADING'; + return; + } + if (req.readyState != 4) return; + + uploader.request = null; + + if (req.status == 200) { + file.status = 'DONE'; + } else { + file.status = 'FAILED'; + } + + if (files.length) { + uploadNext(); + } else { + setTimeout(function(){ uploader.cast('ON_FINISH') }, 0); + } + + uploader.cast('ON_FINISHONE', [file]); + }; + req.upload.onprogress = function(event) { + if (event.lengthComputable) { + file.loaded = Math.max(event.loaded - gap, 0); + uploader.cast('ON_PROGRESS', [file]); + } + }; + req.send(data); + })(); + }, + stop : function(uploader, settings) { + if (uploader.request) { + uploader.request.abort(); + uploader.request = null; + } + + uploader.cast('ON_STOP'); + } +}; + +// HTML5 +runtimes.html5 = { + create : function(uploader, settings) { + var self = this; + var filter = []; + + // filter by extension + $.each(settings.filters, function(k,v){ filter=$.merge(filter,v.split(' ')) }); + + // when file is selected + function onselect() { + + var files = $.grep(this.files, function(file) { + var ext = (file.fileName.match(/\.([^\.]+)$/)[1] || '').toLowerCase(); + return ($.inArray(ext,filter) != -1); + }); + + if (files.length) { + var old_length = uploader.files.length; + + $.each(files, function(idx, file){ + uploader.files.push(new File(file, file.size||file.fileSize)); + }); + uploader.cast('ON_SELECT', [uploader.files, old_length]); + } + + this.value = ''; + } + + function make_button(event) { + var op = this.offsetParent; + var ow = this.offsetWidth; + var oh = this.offsetHeight; + var ot = this.offsetTop; + var ol = this.offsetLeft; + + if (!uploader.browseButton) { + uploader.browseButton = $('
').appendTo(op); + uploader.browseButton.find('>input').css({cursor:'pointer',opacity:0}).change(onselect); + } + + uploader.browseButton.css({width:ow+'px', height:oh+'px', left:ol+'px', top:ot+'px', margin:0, padding:0}); + + if (event.type == 'focus') uploader.browseButton.find('>input').focus(); + } + + // browse button + settings.browse.bind({mouseover:make_button,focus:make_button}); + + // drag and drop (available only Firefox) + if (settings.dropzone) { + settings.dropzone + .bind('dragover', function(){ return false; }) + .bind('drop', function(event){ + var data = event.originalEvent.dataTransfer; + var obj = {files:data.files||[]}; + + onselect.apply(obj); + + return false; + }); + } + + // upload + if (settings.upload) { + settings.upload.click(function(){ + uploader.cast('START'); + return false; + }); + } + }, + check : function() { + if (window.XMLHttpRequest) { + var xhr = new XMLHttpRequest(); + if (!!xhr.sendAsBinary || !!xhr.upload) return true; + } + + return false; + }, + upload : function(uploader, settings, files) { + if (uploader.request || !files.length) return false; + + uploader.cast('ON_START'); + + (function uploadNext() { + var file = files.shift(); + var req = uploader.request = new XMLHttpRequest(); + var data = ''; + var bndr = '--------------xe-boundary'+random(); + var bin = file.object.getAsBinary(); + var gap = 0; + + $.each(settings.params, function(key, val) { + data += '--'+bndr+'\r\n'; + data += 'Content-Disposition: form-data; name="'+key+'"\r\n\r\n'; + data += val+'\r\n'; + }); + + data += '--'+bndr+'\r\n'; + data += 'Content-Disposition: form-data; name="Filedata"; filename="'+file.name+'"\r\n'; + data += 'Content-Type: application/octet-stream\r\n\r\n'; + data += bin; + data += '\r\n'; + data += '--'+bndr+'--\r\n'; + + bin = null; + gap = data.length - file.object.fileSize; + + uploader.cast('ON_STARTONE', [file]); + + function nextOrFinish() { + if (files.length) { + uploadNext(); + } else { + setTimeout(function(){ uploader.cast('ON_FINISH') }, 0); + } + + uploader.cast('ON_FINISHONE', [file]); + } + + req.onreadystatechange = function() { + if (req.readyState == 1) { + file.status = 'UPLOADING'; + return; + } + if (req.readyState != 4) return; + + uploader.request = null; + + if (req.status == 200) { + file.loaded = file.size; + file.status = 'DONE'; + } else { + file.status = 'FAILED'; + } + nextOrFinish(); + }; + req.onerror = function(event) { + file.status = 'FAILED'; + nextOrFinish(); + }; + + if (req.upload) { + req.upload.onprogress = + req.upload.onload = + function(event){ + if (event.lengthComputable) { + file.loaded = Math.max(event.loaded - gap, 0); + uploader.cast('ON_PROGRESS', [file]); + } + }; + } + + req.open('POST', settings.url); + req.setRequestHeader('Content-Type', 'multipart/form-data; boundary='+bndr); + + if (req.sendAsBinary) req.sendAsBinary(data); + else req.send(data); + })(); + }, + stop : function(uploader, settings) { + if (uploader.request) { + uploader.request.abort(); + uploader.request = null; + } + + uploader.cast('ON_STOP'); + } +}; + +// Adobe Flash +runtimes.flash = { + version : 0, + object : null, + uploaders : [], + create : function(uploader, settings) { + var self = this; + var rand = random(); + var name = 'xe_flashuploader_object'+rand; + var swf = '/common/swf/uploader.swf'; + + if (!window.xe_flashuploaders) window.xe_flashuploaders = []; + + function make_button(event) { + var b = settings.browse.get(0); + var op = b.offsetParent; + var ow = b.offsetWidth; + var oh = b.offsetHeight; + var ot = b.offsetTop; + var ol = b.offsetLeft; + + if (typeof uploader.flashindex == 'undefined') { + uploader.flashindex = xe_flashuploaders.length; + + xe_flashuploaders.push({ + uploader : uploader, + settings : settings, + onselect : function(files) { + var old_length = uploader.files.length; + + $.each(files, function() { + uploader.files.push(new File(this, this.fileSize)) + }); + + uploader.cast('ON_SELECT', [uploader.files, old_length]); + }, + onprogress : function(fileInfo) {}, + oncomplete : function(fileInfo) {}, + onerror : function(fileInfo) {}, + oncancel : function(fileInfo) {} + }); + } + + var flash = $.browser.msie?window[name]:document[name]; + var css = {position:'absolute',width:ow+'px',height:oh+'px',left:ol+'px',top:ot+'px',margin:0,padding:0,overflow:'hidden'}; + + if (!flash) { + var div = $('
').css(css).appendTo(op); + div[0].innerHTML = '' + + '' + + '' + + '' + + '' + + '' + + ''; + + flash = $.browser.msie?window[name]:document[name]; + } + + if (!uploader.flash) { + try { + var _settings = {}; + var pass_keys = ['filters','params','url']; + + $.each(settings, function(key,val){ + if ($.inArray(key, pass_keys) < 0) return true; + _settings[key] = val; + }); + + flash.setConfig(uploader.flashindex, _settings); + + uploader.flash = flash; + uploader.flash_box = $(flash).parents('div:first'); + } catch(e) { + return setTimeout(arguments.callee, 10); + } + } + if (uploader.flash) { + uploader.flash_box.css(css); + uploader.flash.setIndex(uploader.flashindex); + } + } + + // browse button + settings.browse.bind({mouseover:make_button,focus:make_button}); + + // upload + if (settings.upload) { + settings.upload.click(function(){ + uploader.cast('START'); + return false; + }); + } + + }, + check : function() { + var p = navigator.plugins, v; + + if (p && (v=p['Shockwave Flash'])) { + v = v.description; + } else { + try { + v = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); + } catch(e) { + v = "0.0"; + } + } + + v = v.match(/\d+/g); + v = parseFloat(v[0]+'.'+v[1]); + + if (!isNaN(v)) this.version = v; + + return (this.version >= 9); + }, + upload : function(uploader, settings, files) { + if (typeof uploader.flashindex == 'undefined') return false; + if (uploader.request || !files.length) return false; + + var g_uploader = xe_flashuploaders[uploader.flashindex]; + + uploader.cast('ON_START'); + + (function uploadNext(){ + var file = files.shift(); + uploader.flash.startUpload(file.object.index); + + uploader.cast('ON_STARTONE', [file]); + + function nextOrFinish() { + if (files.length) { + uploadNext(); + } else { + setTimeout(function(){ uploader.cast('ON_FINISH') }, 0); + } + + uploader.cast('ON_FINISHONE', [file]); + } + + file.status = 'UPLOADING'; + + g_uploader.onprogress = function(fileInfo){ + file.loaded = fileInfo.loaded; + uploader.cast('ON_PROGRESS', [file]); + }; + + g_uploader.oncomplete = function(fileInfo) { + file.loaded = fileInfo.loaded; + file.status = 'DONE'; + + nextOrFinish(); + }; + + g_uploader.onerror = function() { + file.status = 'FAILED'; + nextOrFinish(); + }; + })(); + }, + stop : function(uploader, settings) { + if (typeof uploader.flashindex == 'undefined') return false; + } +}; + +// HTML4 +runtimes.html4 = { + create : function(uploader, settings) { + var self = this; + var filter = []; + + // filter by extension + $.each(settings.filters, function(k,v){ filter=$.merge(filter,v.split(' ')) }); + + // when file is selected + function onselect() { + var ext = (this.value.match(/\.([^\.]+)$/)[1] || '').toLowerCase(); + + if ($.inArray(ext, filter) != -1) { + uploader.files.push(new File(this, -1)); + uploader.cast('ON_SELECT', [uploader.files, uploader.files.length - 1]); + } + + uploader.browseButton = null; + $(this).parent().remove(); + } + + function make_button(event) { + var op = this.offsetParent; + var ow = this.offsetWidth; + var oh = this.offsetHeight; + var ot = this.offsetTop; + var ol = this.offsetLeft; + + if (!uploader.browseButton) { + uploader.browseButton = $('
') + .appendTo(op) + .change(onselect); + uploader.browseButton.find('>input').css({cursor:'pointer',opacity:0}); + } + + uploader.browseButton.css({width:ow+'px', height:oh+'px', left:ol+'px', top:ot+'px', margin:0, padding:0}); + + if (event.type == 'focus') uploader.browseButton.find('>input').focus(); + } + + // browse button + settings.browse.bind({mouseover:make_button,focus:make_button}); + + // upload + if (settings.upload) { + settings.upload.click(function(){ + uploader.cast('START'); + return false; + }); + } + }, + check : function() { + return true; + }, + upload : function(uploader, settings, files) { + if (uploader.request || !files.length) return false; + + var css = {position:'absolute',width:'1px',height:'1px',left:'-100px',top:'-100px',overflow:'hidden'}; + + // callback + if (!window.callbacks) window.callbacks = {}; + + uploader.cast('ON_START'); + + (function uploadNext(){ + var file = files.shift(); + var id = 'tmp_upload_'+random(); + var iframe = $('').css(css).appendTo(document.documentElement); + var form = $('
').css(css).appendTo(document.documentElement); + + form.attr('action', settings.url); + + uploader.request = {iframe:iframe, form:form}; + + // set parameters + settings.params._callback = 'callbacks.'+id; // callback + $.each(settings.params, function(k,v) { + $('').val(v).appendTo(form); + }); + + // set status of a file + file.status = 'UPLOADING'; + + callbacks[id] = function(fileInfo) { + file.status = 'DONE'; + file.size = fileInfo.size; + file.loaded = fileInfo.size; + + form.find('>input[type=file]').remove(); + + uploader.cast('ON_FINISHONE', [file]); + + if (files.length) { + setTimeout(uploadNext, 0); + } else { + uploader.request = null; + uploader.cast('ON_FINISH'); + } + + setTimeout(function(){ + form.remove(); + iframe.remove(); + + delete callbacks[id]; + }, 0); + }; + + form.append(file.object).submit(); + })(); + }, + stop : function(uploader, settings) { + if (uploader.request) { + uploader.request.iframe.attr('src', 'about:blank').remove(); + uploader.request.form.remove(); + uploader.request = null; + } + } +}; + +// }}} runtimes + +var mimetypes = { + 'application/java-archive' : 'jar', + 'application/java-vm' : 'class', + 'application/javascript' : 'js', + 'application/msword' : 'doc dot', + 'application/pdf' : 'pdf', + 'application/octet-stream' : 'bin lha lzh iso dmg dist pkg exe', + 'application/postscript' : 'ai eps ps', + 'application/rtf' : 'rtf', + 'application/smil' : 'smi smil', + 'application/vnd.ms-excel' : 'xls xlm xla xlc xlt xlw', + 'application/vnd.openxmlformats': 'docx pptx xlsx', + 'application/vnd.ms-powerpoint' : 'ppt pps pot', + 'application/zip' : 'zip', + 'application/x-shockwave-flash' : 'swf swfl', + 'audio/mpeg' : 'mpga mpega mp2 mp3', + 'audio/x-wav' : 'wav', + 'image/bmp' : 'bmp', + 'image/gif' : 'gif', + 'image/jpeg' : 'jpeg jpg jpe', + 'image/png' : 'png', + 'image/svg+xml' : 'svg svgz', + 'image/tiff' : 'tiff tif', + 'text/html' : 'htm html xhtml', + 'text/plain' : 'asc txt text diff log', + 'video/mpeg' : 'mpeg mpg mpe', + 'video/quicktime' : 'qt mov', + 'video/x-flv' : 'flv', + 'video/x-ms-asf' : 'asf', + 'video/x-ms-wmv' : 'wmv', + 'video/x-msvideo' : 'avi' +}; + +function File(obj, filesize) { + if (runtime == 'html4') { + this.name = obj.value.match(/[^\\\/]+$/)[0]; + } else { + this.name = obj.name || obj.fileName; + } + + this.size = filesize; + this.loaded = 0; + this.status = 'QUEUED'; // QUEUED, UPLOADING, FAILED, DONE + this.object = obj; +}; + +function random() { + return Math.floor(Math.random()*80000+10000); +} + +})(jQuery); diff --git a/common/js/plugins/uploader/uploader.swf b/common/js/plugins/uploader/uploader.swf new file mode 100644 index 0000000000000000000000000000000000000000..bcc4946dffe845381a49f18e310f99a9364968db GIT binary patch literal 3573 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 literal 0 HcmV?d00001