diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8f2f28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.py[cdo] +*~ + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..20f65e7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2012, Cuker Interactive +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..9c2c806 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +recursive-include directupload/templates * diff --git a/directupload/__init__.py b/directupload/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/directupload/admin.py b/directupload/admin.py new file mode 100644 index 0000000..b957c3c --- /dev/null +++ b/directupload/admin.py @@ -0,0 +1,17 @@ +from django.db import models +from django.contrib.admin import ModelAdmin + +from widgets import UploadifyClearableFileInput + +class UploadifyAdminMixin(object): + def formfield_for_dbfield(self, db_field, **kwargs): + if isinstance(db_field, models.FileField): + return self.formfield_for_file_field(db_field, kwargs.pop('request', None), **kwargs) + return ModelAdmin.formfield_for_dbfield(self, db_field, **kwargs) + + def formfield_for_file_field(self, db_field, request=None, **kwargs): + """ + Get a form Field that is prepared for uploadify + """ + kwargs['widget'] = UploadifyClearableFileInput(db_field=db_field) + return db_field.formfield(**kwargs) diff --git a/directupload/app_settings.py b/directupload/app_settings.py new file mode 100644 index 0000000..90a234e --- /dev/null +++ b/directupload/app_settings.py @@ -0,0 +1,5 @@ +from django.conf import settings + +UPLOADIFY_BACKEND = getattr(settings, 'UPLOADIFY_BACKEND', 'directupload.backends.djangoview.DjangoViewBackend') +#UPLOADIFY_BACKEND = getattr(settings, 'UPLOADIFY_BACKEND', 'directupload.backends.s3.S3UploadifyBackend') + diff --git a/directupload/backends/__init__.py b/directupload/backends/__init__.py new file mode 100644 index 0000000..68ee5f5 --- /dev/null +++ b/directupload/backends/__init__.py @@ -0,0 +1,11 @@ +try: + import importlib +except ImportError: + from django.utils import importlib + +def get_uploadify_backend(): + from directupload.app_settings import UPLOADIFY_BACKEND + module_name, class_name = UPLOADIFY_BACKEND.rsplit('.', 1) + module = importlib.import_module(module_name) + return getattr(module, class_name) + diff --git a/directupload/backends/base.py b/directupload/backends/base.py new file mode 100644 index 0000000..660a25e --- /dev/null +++ b/directupload/backends/base.py @@ -0,0 +1,61 @@ +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.core.urlresolvers import reverse + +from django.utils import simplejson as json + +from common import UPLOADIFY_OPTIONS, UPLOADIFY_METHODS, DEFAULT_CANCELIMG, DEFAULT_UPLOADER, BUTTON_TEXT + +class BaseUploadifyBackend(object): + def __init__(self, request, uploadify_options={}, post_data={}): + self.request = request + self.options = getattr(settings, 'UPLOADIFY_DEFAULT_OPTIONS', {}) + self.options.update(uploadify_options) + + if any(True for key in self.options if key not in UPLOADIFY_OPTIONS + UPLOADIFY_METHODS): + raise ImproperlyConfigured("Attempted to initialize with unrecognized option '%s'." % key) + + _set_default_if_none(self.options, 'cancelImage', DEFAULT_CANCELIMG) + _set_default_if_none(self.options, 'swf', DEFAULT_UPLOADER) + _set_default_if_none(self.options, 'uploader', self.get_uploader()) + _set_default_if_none(self.options, 'buttonText', BUTTON_TEXT) + _set_default_if_none(self.options, 'checkExisting', self.get_check_existing()) + _set_default_if_none(self.options, 'determineName', self.get_determine_name()) + + self.post_data = post_data + self.build_post_data() + + def get_check_existing(self): + return False + + def get_determine_name(self): + return reverse('uploadify-determine-name') + + def get_uploader(self): + pass + + def build_post_data(self): + pass + + def update_post_params(self, params): + pass + + def get_options_json(self): + self.options['postData'] = self.post_data + subs = [] + for key in self.options: + if key in UPLOADIFY_METHODS: + subs.append(('"%%%s%%"' % key, self.options[key])) + self.options[key] = "%%%s%%" % key + + out = json.dumps(self.options) + + for search, replace in subs: + out = out.replace(search, replace) + + return out + +def _set_default_if_none(dict, key, default=None): + if key not in dict: + dict[key] = default + diff --git a/directupload/backends/common.py b/directupload/backends/common.py new file mode 100644 index 0000000..5010b55 --- /dev/null +++ b/directupload/backends/common.py @@ -0,0 +1,11 @@ +from django.conf import settings + +UPLOADIFY_OPTIONS = ('auto', 'buttonImg', 'buttonText', 'cancelImg', 'checkScript', 'displayData', 'expressInstall', 'fileDataName', 'fileDesc', 'fileExt', 'folder', 'height', 'hideButton', 'method', 'multi', 'queueID', 'queueSizeLimit', 'removeCompleted', 'rollover', 'script','scriptAccess', 'scriptData', 'simUploadLimit', 'sizeLimit', 'uploader', 'width', 'wmode') + +UPLOADIFY_METHODS = ('onAllComplete', 'onCancel', 'onCheck', 'onClearQueue', 'onComplete', 'onError', 'onInit', 'onOpen', 'onProgress', 'onQueueFull', 'onSelect', 'onSelectOnce', 'onSWFReady') + +BUTTON_TEXT = 'Select File' + +# Defaults for required Uploadify options +DEFAULT_CANCELIMG = settings.STATIC_URL + "uploadify/uploadify-cancel.png" +DEFAULT_UPLOADER = settings.STATIC_URL + "uploadify/uploadify.swf" diff --git a/directupload/backends/djangoview.py b/directupload/backends/djangoview.py new file mode 100644 index 0000000..33b970c --- /dev/null +++ b/directupload/backends/djangoview.py @@ -0,0 +1,31 @@ +from base import BaseUploadifyBackend + +import datetime +from urllib import urlencode + +from django.middleware.csrf import get_token +from django.core.urlresolvers import reverse + +from utils import Signer +signer = Signer() + +def sign(value): + return signer.sign(value) + +def unsign(value): + return signer.unsign(value) + +class DjangoViewBackend(BaseUploadifyBackend): + """Uploadify for using the builtin django view""" + + def get_uploader(self): + return reverse('uploadify-upload-file') + + def build_post_data(self): + data = {'upload_to': self.options['folder'], + 'request_time': datetime.datetime.now().isoformat(), + '_request_id': 'foo',} #TODO salt} + signed_data = sign(urlencode(data)) + self.post_data['payload'] = signed_data + self.post_data['csrfmiddlewaretoken'] = get_token(self.request) + diff --git a/directupload/backends/s3.py b/directupload/backends/s3.py new file mode 100644 index 0000000..0df4db3 --- /dev/null +++ b/directupload/backends/s3.py @@ -0,0 +1,99 @@ +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from urllib import quote_plus +from datetime import datetime +from datetime import timedelta +import base64 +import hmac +import hashlib +import os + +from base import BaseUploadifyBackend, _set_default_if_none, json + +# AWS Options +ACCESS_KEY_ID = getattr(settings, 'AWS_ACCESS_KEY_ID', None) +SECRET_ACCESS_KEY = getattr(settings, 'AWS_SECRET_ACCESS_KEY', None) +BUCKET_NAME = getattr(settings, 'AWS_BUCKET_NAME', None) +SECURE_URLS = getattr(settings, 'AWS_S3_SECURE_URLS', False) +BUCKET_URL = getattr(settings, 'AWS_BUCKET_URL', ('https://' if SECURE_URLS else 'http://') + BUCKET_NAME + '.s3.amazonaws.com') +DEFAULT_ACL = getattr(settings, 'AWS_DEFAULT_ACL', 'public-read') +DEFAULT_KEY_PATTERN = getattr(settings, 'AWS_DEFAULT_KEY_PATTERN', '${targetname}') +DEFAULT_FORM_TIME = getattr(settings, 'AWS_DEFAULT_FORM_LIFETIME', 36000) # 10 HOURS + + +class S3UploadifyBackend(BaseUploadifyBackend): + """Uploadify for Amazon S3""" + + def __init__(self, request, uploadify_options={}, post_data={}, conditions={}): + self.conditions = conditions + super(S3UploadifyBackend, self).__init__(request, uploadify_options, post_data) + + def get_uploader(self): + return BUCKET_URL + + def build_post_data(self): + self.options['fileObjName'] = 'file' #S3 requires this be the field name + + if 'folder' in self.options: + key = os.path.join(self.options['folder'], DEFAULT_KEY_PATTERN) + else: + key = DEFAULT_KEY_PATTERN + #_set_default_if_none(self.post_data, 'key', key) #this is set by update_post_params + _set_default_if_none(self.post_data, 'acl', DEFAULT_ACL) + + try: + _set_default_if_none(self.post_data, 'bucket', BUCKET_NAME) + except ValueError: + raise ImproperlyConfigured("Bucket name is a required property.") + + try: + _set_default_if_none(self.post_data, 'AWSAccessKeyId', ACCESS_KEY_ID) + except ValueError: + raise ImproperlyConfigured("AWS Access Key ID is a required property.") + + self.conditions = self.build_conditions() + + if not SECRET_ACCESS_KEY: + raise ImproperlyConfigured("AWS Secret Access Key is a required property.") + + expiration_time = datetime.utcnow() + timedelta(seconds=DEFAULT_FORM_TIME) + self.policy_string = self.build_post_policy(expiration_time) + self.policy = base64.b64encode(self.policy_string) + + self.signature = base64.encodestring(hmac.new(SECRET_ACCESS_KEY, self.policy, hashlib.sha1).digest()).strip() + + self.post_data['policy'] = self.policy + self.post_data['signature'] = self.signature + + def build_conditions(self): + conditions = list() + + #make s3 happy with uploadify + #conditions.append(['starts-with', '$folder', '']) #no longer passed by uploadify + conditions.append(['starts-with', '$filename', '']) + conditions.append(['starts-with', '$targetname', '']) #variable introduced by this package + conditions.append(['starts-with', '$targetpath', self.options['folder']]) + #conditions.append({'success_action_status': '200'}) + + #real conditions + conditions.append(['starts-with', '$key', self.options['folder']]) + conditions.append({'bucket': self.post_data['bucket']}) + conditions.append({'acl': self.post_data['acl']}) + return conditions + + def build_post_policy(self, expiration_time): + policy = {'expiration': expiration_time.strftime("%Y-%m-%dT%H:%M:%SZ"), + 'conditions': self.conditions,} + return json.dumps(policy) + + def update_post_params(self, params): + #instruct s3 that our key is the targetpath + params['key'] = params['targetpath'] + +def _uri_encode(str): + try: + # The Uploadify flash component apparently decodes the scriptData once, so we need to encode twice here. + return quote_plus(quote_plus(str, safe='~'), safe='~') + except: + raise ValueError + diff --git a/directupload/backends/utils.py b/directupload/backends/utils.py new file mode 100644 index 0000000..82409cd --- /dev/null +++ b/directupload/backends/utils.py @@ -0,0 +1,44 @@ +from django.conf import settings +from django.utils.crypto import constant_time_compare, salted_hmac + +import base64 + +def b64_encode(s): + return base64.urlsafe_b64encode(s).strip('=') + +def b64_decode(s): + pad = '=' * (-len(s) % 4) + return base64.urlsafe_b64decode(s + pad) + +def base64_hmac(salt, value, key): + return b64_encode(salted_hmac(salt, value, key).digest()) + +class LegacySigner(object): + ''' + Limited functionality signer + ''' + def __init__(self, key=None, sep=':', salt=None): + self.sep = sep + self.key = key or settings.SECRET_KEY + self.salt = salt or ('%s.%s' % + (self.__class__.__module__, self.__class__.__name__)) + + def signature(self, value): + return base64_hmac(self.salt + 'signer', value, self.key) + + def sign(self, value): + return '%s%s%s' % (value, self.sep, self.signature(value)) + + def unsign(self, signed_value): + if not self.sep in signed_value: + raise ValueError('No "%s" found in value' % self.sep) + value, sig = signed_value.rsplit(self.sep, 1) + if constant_time_compare(sig, self.signature(value)): + return value + raise ValueError('Signature "%s" does not match' % sig) + +try: + from django.core.signing import Signer +except ImportError: + Signer = LegacySigner + diff --git a/directupload/models.py b/directupload/models.py new file mode 100644 index 0000000..37528e3 --- /dev/null +++ b/directupload/models.py @@ -0,0 +1,11 @@ +from django.db import models + +from widgets import UploadifyClearableFileInput + +def patch_admin(): + from django.contrib.admin.options import FORMFIELD_FOR_DBFIELD_DEFAULTS + FORMFIELD_FOR_DBFIELD_DEFAULTS[models.ImageField] = {'widget': UploadifyClearableFileInput} + FORMFIELD_FOR_DBFIELD_DEFAULTS[models.FileField] = {'widget': UploadifyClearableFileInput} + +patch_admin() + diff --git a/directupload/static/uploadify/jquery.uploadify.js b/directupload/static/uploadify/jquery.uploadify.js new file mode 100644 index 0000000..f4d790f --- /dev/null +++ b/directupload/static/uploadify/jquery.uploadify.js @@ -0,0 +1,677 @@ +/* +SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com + +mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/ + +SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License: +http://www.opensource.org/licenses/mit-license.php + +SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License: +http://www.opensource.org/licenses/mit-license.php +*/ + +var SWFUpload;if(SWFUpload==undefined){SWFUpload=function(a){this.initSWFUpload(a)}}SWFUpload.prototype.initSWFUpload=function(b){try{this.customSettings={};this.settings=b;this.eventQueue=[];this.movieName="SWFUpload_"+SWFUpload.movieCount++;this.movieElement=null;SWFUpload.instances[this.movieName]=this;this.initSettings();this.loadFlash();this.displayDebugInfo()}catch(a){delete SWFUpload.instances[this.movieName];throw a}};SWFUpload.instances={};SWFUpload.movieCount=0;SWFUpload.version="2.2.0 2009-03-25";SWFUpload.QUEUE_ERROR={QUEUE_LIMIT_EXCEEDED:-100,FILE_EXCEEDS_SIZE_LIMIT:-110,ZERO_BYTE_FILE:-120,INVALID_FILETYPE:-130};SWFUpload.UPLOAD_ERROR={HTTP_ERROR:-200,MISSING_UPLOAD_URL:-210,IO_ERROR:-220,SECURITY_ERROR:-230,UPLOAD_LIMIT_EXCEEDED:-240,UPLOAD_FAILED:-250,SPECIFIED_FILE_ID_NOT_FOUND:-260,FILE_VALIDATION_FAILED:-270,FILE_CANCELLED:-280,UPLOAD_STOPPED:-290};SWFUpload.FILE_STATUS={QUEUED:-1,IN_PROGRESS:-2,ERROR:-3,COMPLETE:-4,CANCELLED:-5};SWFUpload.BUTTON_ACTION={SELECT_FILE:-100,SELECT_FILES:-110,START_UPLOAD:-120};SWFUpload.CURSOR={ARROW:-1,HAND:-2};SWFUpload.WINDOW_MODE={WINDOW:"window",TRANSPARENT:"transparent",OPAQUE:"opaque"};SWFUpload.completeURL=function(a){if(typeof(a)!=="string"||a.match(/^https?:\/\//i)||a.match(/^\//)){return a}var c=window.location.protocol+"//"+window.location.hostname+(window.location.port?":"+window.location.port:"");var b=window.location.pathname.lastIndexOf("/");if(b<=0){path="/"}else{path=window.location.pathname.substr(0,b)+"/"}return path+a};SWFUpload.prototype.initSettings=function(){this.ensureDefault=function(b,a){this.settings[b]=(this.settings[b]==undefined)?a:this.settings[b]};this.ensureDefault("upload_url","");this.ensureDefault("preserve_relative_urls",false);this.ensureDefault("file_post_name","Filedata");this.ensureDefault("post_params",{});this.ensureDefault("use_query_string",false);this.ensureDefault("requeue_on_error",false);this.ensureDefault("http_success",[]);this.ensureDefault("assume_success_timeout",0);this.ensureDefault("file_types","*.*");this.ensureDefault("file_types_description","All Files");this.ensureDefault("file_size_limit",0);this.ensureDefault("file_upload_limit",0);this.ensureDefault("file_queue_limit",0);this.ensureDefault("flash_url","swfupload.swf");this.ensureDefault("prevent_swf_caching",true);this.ensureDefault("button_image_url","");this.ensureDefault("button_width",1);this.ensureDefault("button_height",1);this.ensureDefault("button_text","");this.ensureDefault("button_text_style","color: #000000; font-size: 16pt;");this.ensureDefault("button_text_top_padding",0);this.ensureDefault("button_text_left_padding",0);this.ensureDefault("button_action",SWFUpload.BUTTON_ACTION.SELECT_FILES);this.ensureDefault("button_disabled",false);this.ensureDefault("button_placeholder_id","");this.ensureDefault("button_placeholder",null);this.ensureDefault("button_cursor",SWFUpload.CURSOR.ARROW);this.ensureDefault("button_window_mode",SWFUpload.WINDOW_MODE.WINDOW);this.ensureDefault("debug",false);this.settings.debug_enabled=this.settings.debug;this.settings.return_upload_start_handler=this.returnUploadStart;this.ensureDefault("swfupload_loaded_handler",null);this.ensureDefault("file_dialog_start_handler",null);this.ensureDefault("file_queued_handler",null);this.ensureDefault("file_queue_error_handler",null);this.ensureDefault("file_dialog_complete_handler",null);this.ensureDefault("upload_start_handler",null);this.ensureDefault("upload_progress_handler",null);this.ensureDefault("upload_error_handler",null);this.ensureDefault("upload_success_handler",null);this.ensureDefault("upload_complete_handler",null);this.ensureDefault("debug_handler",this.debugMessage);this.ensureDefault("custom_settings",{});this.customSettings=this.settings.custom_settings;if(!!this.settings.prevent_swf_caching){this.settings.flash_url=this.settings.flash_url+(this.settings.flash_url.indexOf("?")<0?"?":"&")+"preventswfcaching="+new Date().getTime()}if(!this.settings.preserve_relative_urls){this.settings.upload_url=SWFUpload.completeURL(this.settings.upload_url);this.settings.button_image_url=SWFUpload.completeURL(this.settings.button_image_url)}delete this.ensureDefault};SWFUpload.prototype.loadFlash=function(){var a,b;if(document.getElementById(this.movieName)!==null){throw"ID "+this.movieName+" is already in use. The Flash Object could not be added"}a=document.getElementById(this.settings.button_placeholder_id)||this.settings.button_placeholder;if(a==undefined){throw"Could not find the placeholder element: "+this.settings.button_placeholder_id}b=document.createElement("div");b.innerHTML=this.getFlashHTML();a.parentNode.replaceChild(b.firstChild,a);if(window[this.movieName]==undefined){window[this.movieName]=this.getMovieElement()}};SWFUpload.prototype.getFlashHTML=function(){return['','','','','','','',""].join("")};SWFUpload.prototype.getFlashVars=function(){var b=this.buildParamString();var a=this.settings.http_success.join(",");return["movieName=",encodeURIComponent(this.movieName),"&uploadURL=",encodeURIComponent(this.settings.upload_url),"&useQueryString=",encodeURIComponent(this.settings.use_query_string),"&requeueOnError=",encodeURIComponent(this.settings.requeue_on_error),"&httpSuccess=",encodeURIComponent(a),"&assumeSuccessTimeout=",encodeURIComponent(this.settings.assume_success_timeout),"&params=",encodeURIComponent(b),"&filePostName=",encodeURIComponent(this.settings.file_post_name),"&fileTypes=",encodeURIComponent(this.settings.file_types),"&fileTypesDescription=",encodeURIComponent(this.settings.file_types_description),"&fileSizeLimit=",encodeURIComponent(this.settings.file_size_limit),"&fileUploadLimit=",encodeURIComponent(this.settings.file_upload_limit),"&fileQueueLimit=",encodeURIComponent(this.settings.file_queue_limit),"&debugEnabled=",encodeURIComponent(this.settings.debug_enabled),"&buttonImageURL=",encodeURIComponent(this.settings.button_image_url),"&buttonWidth=",encodeURIComponent(this.settings.button_width),"&buttonHeight=",encodeURIComponent(this.settings.button_height),"&buttonText=",encodeURIComponent(this.settings.button_text),"&buttonTextTopPadding=",encodeURIComponent(this.settings.button_text_top_padding),"&buttonTextLeftPadding=",encodeURIComponent(this.settings.button_text_left_padding),"&buttonTextStyle=",encodeURIComponent(this.settings.button_text_style),"&buttonAction=",encodeURIComponent(this.settings.button_action),"&buttonDisabled=",encodeURIComponent(this.settings.button_disabled),"&buttonCursor=",encodeURIComponent(this.settings.button_cursor)].join("")};SWFUpload.prototype.getMovieElement=function(){if(this.movieElement==undefined){this.movieElement=document.getElementById(this.movieName)}if(this.movieElement===null){throw"Could not find Flash element"}return this.movieElement};SWFUpload.prototype.buildParamString=function(){var c=this.settings.post_params;var b=[];if(typeof(c)==="object"){for(var a in c){if(c.hasOwnProperty(a)){b.push(encodeURIComponent(a.toString())+"="+encodeURIComponent(c[a].toString()))}}}return b.join("&")};SWFUpload.prototype.destroy=function(){try{this.cancelUpload(null,false);var a=null;a=this.getMovieElement();if(a&&typeof(a.CallFunction)==="unknown"){for(var c in a){try{if(typeof(a[c])==="function"){a[c]=null}}catch(e){}}try{a.parentNode.removeChild(a)}catch(b){}}window[this.movieName]=null;SWFUpload.instances[this.movieName]=null;delete SWFUpload.instances[this.movieName];this.movieElement=null;this.settings=null;this.customSettings=null;this.eventQueue=null;this.movieName=null;return true}catch(d){return false}};SWFUpload.prototype.displayDebugInfo=function(){this.debug(["---SWFUpload Instance Info---\n","Version: ",SWFUpload.version,"\n","Movie Name: ",this.movieName,"\n","Settings:\n","\t","upload_url: ",this.settings.upload_url,"\n","\t","flash_url: ",this.settings.flash_url,"\n","\t","use_query_string: ",this.settings.use_query_string.toString(),"\n","\t","requeue_on_error: ",this.settings.requeue_on_error.toString(),"\n","\t","http_success: ",this.settings.http_success.join(", "),"\n","\t","assume_success_timeout: ",this.settings.assume_success_timeout,"\n","\t","file_post_name: ",this.settings.file_post_name,"\n","\t","post_params: ",this.settings.post_params.toString(),"\n","\t","file_types: ",this.settings.file_types,"\n","\t","file_types_description: ",this.settings.file_types_description,"\n","\t","file_size_limit: ",this.settings.file_size_limit,"\n","\t","file_upload_limit: ",this.settings.file_upload_limit,"\n","\t","file_queue_limit: ",this.settings.file_queue_limit,"\n","\t","debug: ",this.settings.debug.toString(),"\n","\t","prevent_swf_caching: ",this.settings.prevent_swf_caching.toString(),"\n","\t","button_placeholder_id: ",this.settings.button_placeholder_id.toString(),"\n","\t","button_placeholder: ",(this.settings.button_placeholder?"Set":"Not Set"),"\n","\t","button_image_url: ",this.settings.button_image_url.toString(),"\n","\t","button_width: ",this.settings.button_width.toString(),"\n","\t","button_height: ",this.settings.button_height.toString(),"\n","\t","button_text: ",this.settings.button_text.toString(),"\n","\t","button_text_style: ",this.settings.button_text_style.toString(),"\n","\t","button_text_top_padding: ",this.settings.button_text_top_padding.toString(),"\n","\t","button_text_left_padding: ",this.settings.button_text_left_padding.toString(),"\n","\t","button_action: ",this.settings.button_action.toString(),"\n","\t","button_disabled: ",this.settings.button_disabled.toString(),"\n","\t","custom_settings: ",this.settings.custom_settings.toString(),"\n","Event Handlers:\n","\t","swfupload_loaded_handler assigned: ",(typeof this.settings.swfupload_loaded_handler==="function").toString(),"\n","\t","file_dialog_start_handler assigned: ",(typeof this.settings.file_dialog_start_handler==="function").toString(),"\n","\t","file_queued_handler assigned: ",(typeof this.settings.file_queued_handler==="function").toString(),"\n","\t","file_queue_error_handler assigned: ",(typeof this.settings.file_queue_error_handler==="function").toString(),"\n","\t","upload_start_handler assigned: ",(typeof this.settings.upload_start_handler==="function").toString(),"\n","\t","upload_progress_handler assigned: ",(typeof this.settings.upload_progress_handler==="function").toString(),"\n","\t","upload_error_handler assigned: ",(typeof this.settings.upload_error_handler==="function").toString(),"\n","\t","upload_success_handler assigned: ",(typeof this.settings.upload_success_handler==="function").toString(),"\n","\t","upload_complete_handler assigned: ",(typeof this.settings.upload_complete_handler==="function").toString(),"\n","\t","debug_handler assigned: ",(typeof this.settings.debug_handler==="function").toString(),"\n"].join(""))};SWFUpload.prototype.addSetting=function(b,c,a){if(c==undefined){return(this.settings[b]=a)}else{return(this.settings[b]=c)}};SWFUpload.prototype.getSetting=function(a){if(this.settings[a]!=undefined){return this.settings[a]}return""};SWFUpload.prototype.callFlash=function(functionName,argumentArray){argumentArray=argumentArray||[];var movieElement=this.getMovieElement();var returnValue,returnString;try{returnString=movieElement.CallFunction(''+__flash__argumentsToXML(argumentArray,0)+"");returnValue=eval(returnString)}catch(ex){throw"Call to "+functionName+" failed"}if(returnValue!=undefined&&typeof returnValue.post==="object"){returnValue=this.unescapeFilePostParams(returnValue)}return returnValue};SWFUpload.prototype.selectFile=function(){this.callFlash("SelectFile")};SWFUpload.prototype.selectFiles=function(){this.callFlash("SelectFiles")};SWFUpload.prototype.startUpload=function(a){this.callFlash("StartUpload",[a])};SWFUpload.prototype.cancelUpload=function(a,b){if(b!==false){b=true}this.callFlash("CancelUpload",[a,b])};SWFUpload.prototype.stopUpload=function(){this.callFlash("StopUpload")};SWFUpload.prototype.getStats=function(){return this.callFlash("GetStats")};SWFUpload.prototype.setStats=function(a){this.callFlash("SetStats",[a])};SWFUpload.prototype.getFile=function(a){if(typeof(a)==="number"){return this.callFlash("GetFileByIndex",[a])}else{return this.callFlash("GetFile",[a])}};SWFUpload.prototype.addFileParam=function(a,b,c){return this.callFlash("AddFileParam",[a,b,c])};SWFUpload.prototype.removeFileParam=function(a,b){this.callFlash("RemoveFileParam",[a,b])};SWFUpload.prototype.setUploadURL=function(a){this.settings.upload_url=a.toString();this.callFlash("SetUploadURL",[a])};SWFUpload.prototype.setPostParams=function(a){this.settings.post_params=a;this.callFlash("SetPostParams",[a])};SWFUpload.prototype.addPostParam=function(a,b){this.settings.post_params[a]=b;this.callFlash("SetPostParams",[this.settings.post_params])};SWFUpload.prototype.removePostParam=function(a){delete this.settings.post_params[a];this.callFlash("SetPostParams",[this.settings.post_params])};SWFUpload.prototype.setFileTypes=function(a,b){this.settings.file_types=a;this.settings.file_types_description=b;this.callFlash("SetFileTypes",[a,b])};SWFUpload.prototype.setFileSizeLimit=function(a){this.settings.file_size_limit=a;this.callFlash("SetFileSizeLimit",[a])};SWFUpload.prototype.setFileUploadLimit=function(a){this.settings.file_upload_limit=a;this.callFlash("SetFileUploadLimit",[a])};SWFUpload.prototype.setFileQueueLimit=function(a){this.settings.file_queue_limit=a;this.callFlash("SetFileQueueLimit",[a])};SWFUpload.prototype.setFilePostName=function(a){this.settings.file_post_name=a;this.callFlash("SetFilePostName",[a])};SWFUpload.prototype.setUseQueryString=function(a){this.settings.use_query_string=a;this.callFlash("SetUseQueryString",[a])};SWFUpload.prototype.setRequeueOnError=function(a){this.settings.requeue_on_error=a;this.callFlash("SetRequeueOnError",[a])};SWFUpload.prototype.setHTTPSuccess=function(a){if(typeof a==="string"){a=a.replace(" ","").split(",")}this.settings.http_success=a;this.callFlash("SetHTTPSuccess",[a])};SWFUpload.prototype.setAssumeSuccessTimeout=function(a){this.settings.assume_success_timeout=a;this.callFlash("SetAssumeSuccessTimeout",[a])};SWFUpload.prototype.setDebugEnabled=function(a){this.settings.debug_enabled=a;this.callFlash("SetDebugEnabled",[a])};SWFUpload.prototype.setButtonImageURL=function(a){if(a==undefined){a=""}this.settings.button_image_url=a;this.callFlash("SetButtonImageURL",[a])};SWFUpload.prototype.setButtonDimensions=function(c,a){this.settings.button_width=c;this.settings.button_height=a;var b=this.getMovieElement();if(b!=undefined){b.style.width=c+"px";b.style.height=a+"px"}this.callFlash("SetButtonDimensions",[c,a])};SWFUpload.prototype.setButtonText=function(a){this.settings.button_text=a;this.callFlash("SetButtonText",[a])};SWFUpload.prototype.setButtonTextPadding=function(b,a){this.settings.button_text_top_padding=a;this.settings.button_text_left_padding=b;this.callFlash("SetButtonTextPadding",[b,a])};SWFUpload.prototype.setButtonTextStyle=function(a){this.settings.button_text_style=a;this.callFlash("SetButtonTextStyle",[a])};SWFUpload.prototype.setButtonDisabled=function(a){this.settings.button_disabled=a;this.callFlash("SetButtonDisabled",[a])};SWFUpload.prototype.setButtonAction=function(a){this.settings.button_action=a;this.callFlash("SetButtonAction",[a])};SWFUpload.prototype.setButtonCursor=function(a){this.settings.button_cursor=a;this.callFlash("SetButtonCursor",[a])};SWFUpload.prototype.queueEvent=function(b,c){if(c==undefined){c=[]}else{if(!(c instanceof Array)){c=[c]}}var a=this;if(typeof this.settings[b]==="function"){this.eventQueue.push(function(){this.settings[b].apply(this,c)});setTimeout(function(){a.executeNextEvent()},0)}else{if(this.settings[b]!==null){throw"Event handler "+b+" is unknown or is not a function"}}};SWFUpload.prototype.executeNextEvent=function(){var a=this.eventQueue?this.eventQueue.shift():null;if(typeof(a)==="function"){a.apply(this)}};SWFUpload.prototype.unescapeFilePostParams=function(c){var e=/[$]([0-9a-f]{4})/i;var f={};var d;if(c!=undefined){for(var a in c.post){if(c.post.hasOwnProperty(a)){d=a;var b;while((b=e.exec(d))!==null){d=d.replace(b[0],String.fromCharCode(parseInt("0x"+b[1],16)))}f[d]=c.post[a]}}c.post=f}return c};SWFUpload.prototype.testExternalInterface=function(){try{return this.callFlash("TestExternalInterface")}catch(a){return false}};SWFUpload.prototype.flashReady=function(){var a=this.getMovieElement();if(!a){this.debug("Flash called back ready but the flash movie can't be found.");return}this.cleanUp(a);this.queueEvent("swfupload_loaded_handler")};SWFUpload.prototype.cleanUp=function(a){try{if(this.movieElement&&typeof(a.CallFunction)==="unknown"){this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");for(var c in a){try{if(typeof(a[c])==="function"){a[c]=null}}catch(b){}}}}catch(d){}window.__flash__removeCallback=function(e,f){try{if(e){e[f]=null}}catch(g){}}};SWFUpload.prototype.fileDialogStart=function(){this.queueEvent("file_dialog_start_handler")};SWFUpload.prototype.fileQueued=function(a){a=this.unescapeFilePostParams(a);this.queueEvent("file_queued_handler",a)};SWFUpload.prototype.fileQueueError=function(a,c,b){a=this.unescapeFilePostParams(a);this.queueEvent("file_queue_error_handler",[a,c,b])};SWFUpload.prototype.fileDialogComplete=function(b,c,a){this.queueEvent("file_dialog_complete_handler",[b,c,a])};SWFUpload.prototype.uploadStart=function(a){a=this.unescapeFilePostParams(a);this.queueEvent("return_upload_start_handler",a)};SWFUpload.prototype.returnUploadStart=function(a){var b;if(typeof this.settings.upload_start_handler==="function"){a=this.unescapeFilePostParams(a);b=this.settings.upload_start_handler.call(this,a)}else{if(this.settings.upload_start_handler!=undefined){throw"upload_start_handler must be a function"}}if(b===undefined){b=true}b=!!b;this.callFlash("ReturnUploadStart",[b])};SWFUpload.prototype.uploadProgress=function(a,c,b){a=this.unescapeFilePostParams(a);this.queueEvent("upload_progress_handler",[a,c,b])};SWFUpload.prototype.uploadError=function(a,c,b){a=this.unescapeFilePostParams(a);this.queueEvent("upload_error_handler",[a,c,b])};SWFUpload.prototype.uploadSuccess=function(b,a,c){b=this.unescapeFilePostParams(b);this.queueEvent("upload_success_handler",[b,a,c])};SWFUpload.prototype.uploadComplete=function(a){a=this.unescapeFilePostParams(a);this.queueEvent("upload_complete_handler",a)};SWFUpload.prototype.debug=function(a){this.queueEvent("debug_handler",a)};SWFUpload.prototype.debugMessage=function(c){if(this.settings.debug){var a,d=[];if(typeof c==="object"&&typeof c.name==="string"&&typeof c.message==="string"){for(var b in c){if(c.hasOwnProperty(b)){d.push(b+": "+c[b])}}a=d.join("\n")||"";d=a.split("\n");a="EXCEPTION: "+d.join("\nEXCEPTION: ");SWFUpload.Console.writeLine(a)}else{SWFUpload.Console.writeLine(c)}}};SWFUpload.Console={};SWFUpload.Console.writeLine=function(d){var b,a;try{b=document.getElementById("SWFUpload_Console");if(!b){a=document.createElement("form");document.getElementsByTagName("body")[0].appendChild(a);b=document.createElement("textarea");b.id="SWFUpload_Console";b.style.fontFamily="monospace";b.setAttribute("wrap","off");b.wrap="off";b.style.overflow="auto";b.style.width="700px";b.style.height="350px";b.style.margin="5px";a.appendChild(b)}b.value+=d+"\n";b.scrollTop=b.scrollHeight-b.clientHeight}catch(c){alert("Exception: "+c.name+" Message: "+c.message)}}; + +/* +Uploadify v3.0.0 +Copyright (c) 2010 Ronnie Garcia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +if(jQuery)( + function(jQuery){ + jQuery.extend(jQuery.fn,{ + uploadify:function(options,swfUploadOptions) { + jQuery(this).each(function() { + var clone = jQuery(this).clone(); + var settings = jQuery.extend({ + // Required Settings + id : jQuery(this).attr('id'), + swf : 'uploadify.swf', + uploader : 'uploadify.php', + + // Options + auto : false, + buttonClass : '', + buttonCursor : 'hand', + buttonImage : false, + buttonText : 'SELECT FILES', + cancelImage : 'uploadify-cancel.png', + checkExisting : 'uploadify-check-existing.php', + debug : false, + fileObjName : 'Filedata', + fileSizeLimit : 0, + fileTypeDesc : 'All Files (*.*)', + fileTypeExts : '*.*', + height : 30, + method : 'post', + multi : false, + queueID : false, + queueSizeLimit : 999, + removeCompleted : true, + removeTimeout : 3, + requeueErrors : false, + postData : {}, + preventCaching : true, + progressData : 'percentage', + // simUploadLimit : 1, // Not possible with swfUpload + successTimeout : 30, + transparent : true, + uploadLimit : 999, + uploaderType : 'html5', // the other option is 'flash' + width : 120, + + // Events + skipDefault : [], + onClearQueue : function() {}, + onDialogOpen : function() {}, + onDialogClose : function() {}, + onInit : function() {}, + onQueueComplete : function() {}, + onSelectError : function() {}, + onSelect : function() {}, + onSWFReady : function() {}, + onUploadCancel : function() {}, + onUploadComplete : function() {}, + onUploadError : function() {}, + onUploadProgress : function() {}, + onUploadStart : function() {} + }, options); + + var swfUploadSettings = { + assume_success_timeout : settings.successTimeout, + button_placeholder_id : settings.id, + button_image_url : settings.buttonImage, + button_width : settings.width, + button_height : settings.height, + button_text : null, + button_text_style : null, + button_text_top_padding : 0, + button_text_left_padding : 0, + button_action : (settings.multi ? SWFUpload.BUTTON_ACTION.SELECT_FILES : SWFUpload.BUTTON_ACTION.SELECT_FILE), + button_disabled : false, + button_cursor : (settings.buttonCursor == 'arrow' ? SWFUpload.CURSOR.ARROW : SWFUpload.CURSOR.HAND), + button_window_mode : (settings.transparent && !settings.buttonImage ? SWFUpload.WINDOW_MODE.TRANSPARENT : SWFUpload.WINDOW_MODE.OPAQUE), + debug : settings.debug, + requeue_on_error : settings.requeueErrors, + file_post_name : settings.fileObjName, + file_size_limit : settings.fileSizeLimit, + file_types : settings.fileTypeExts, + file_types_description : settings.fileTypeDesc, + file_queue_limit : settings.queueSizeLimit, + file_upload_limit : settings.uploadLimit, + flash_url : settings.swf, + prevent_swf_caching : settings.preventCaching, + post_params : settings.postData, + upload_url : settings.uploader, + use_query_string : (settings.method == 'get'), + + // Event Handlers + file_dialog_complete_handler : onDialogClose, + file_dialog_start_handler : onDialogOpen, + file_queued_handler : onSelect, + file_queue_error_handler : onSelectError, + flash_ready_handler : settings.onSWFReady, + upload_complete_handler : onUploadComplete, + upload_error_handler : onUploadError, + upload_progress_handler : onUploadProgress, + upload_start_handler : onUploadStart, + upload_success_handler : onUploadSuccess + } + if (swfUploadOptions) { + swfUploadSettings = jQuery.extend(swfUploadSettings,swfUploadOptions); + } + swfUploadSettings = jQuery.extend(swfUploadSettings,settings); + + // Create the swfUpload instance + window['uploadify_' + settings.id] = new SWFUpload(swfUploadSettings); + var swfuploadify = window['uploadify_' + settings.id]; + swfuploadify.original = clone; + + // Wrap the uploadify instance + var wrapper = jQuery('
',{ + id : settings.id, + 'class' : 'uploadify', + css : { + 'height' : settings.height + 'px', + 'position' : 'relative', + 'width' : settings.width + 'px' + } + }); + jQuery('#' + swfuploadify.movieName).wrap(wrapper); + + // Create the file queue + if (!settings.queueID) { + var queue = jQuery('
', { + id : settings.id + '_queue', + 'class' : 'uploadifyQueue' + }); + jQuery('#' + settings.id).after(queue); + swfuploadify.settings.queueID = settings.queueID = settings.id + '_queue'; + } + + // Create some queue related objects and variables + swfuploadify.queue = { + files : {}, // The files in the queue + filesSelected : 0, // The number of files selected in the last select operation + filesQueued : 0, // The number of files added to the queue in the last select operation + filesReplaced : 0, // The number of files replaced in the last select operation + filesCancelled : 0, // The number of files that were cancelled instead of replaced + filesErrored : 0, // The number of files that caused error in the last select operation + averageSpeed : 0, // The average speed of the uploads in KB + queueLength : 0, // The number of files in the queue + queueSize : 0, // The size in bytes of the entire queue + uploadSize : 0, // The size in bytes of the upload queue + queueBytesUploaded : 0, // The size in bytes that have been uploaded for the current upload queue + uploadQueue : [], // The files currently to be uploaded + errorMsg : 'Some files were not added to the queue:' + }; + + // Create the button + if (!settings.buttonImage) { + var button = jQuery('
', { + id : settings.id + '_button', + 'class' : 'uploadifyButton ' + settings.buttonClass, + html : '' + settings.buttonText + '' + }); + jQuery('#' + settings.id).append(button); + jQuery('#' + swfuploadify.movieName).css({position: 'absolute', 'z-index': 1}); + } else { + jQuery('#' + swfuploadify.movieName).addClass(settings.buttonClass); + } + + // ----------------------------- + // Begin Event Handler Functions + // ----------------------------- + + // Triggered once when file dialog is closed + function onDialogClose(filesSelected,filesQueued,queueLength) { + var stats = swfuploadify.getStats(); + swfuploadify.queue.filesErrored = filesSelected - filesQueued; + swfuploadify.queue.filesSelected = filesSelected; + swfuploadify.queue.filesQueued = filesQueued - swfuploadify.queue.filesCancelled; + swfuploadify.queue.queueLength = queueLength; + if (jQuery.inArray('onDialogClose',swfuploadify.settings.skipDefault) < 0) { + if (swfuploadify.queue.filesErrored > 0) { + alert(swfuploadify.queue.errorMsg); + } + } + if (swfuploadify.settings.onDialogClose) swfuploadify.settings.onDialogClose(swfuploadify.queue); + if (swfuploadify.settings.auto) jQuery('#' + swfuploadify.settings.id).uploadifyUpload('*'); + } + + function onDialogOpen() { + // Reset some queue info + swfuploadify.queue.errorMsg = 'Some files were not added to the queue:'; + swfuploadify.queue.filesReplaced = 0; + swfuploadify.queue.filesCancelled = 0; + if (swfuploadify.settings.onDialogOpen) swfuploadify.settings.onDialogOpen(); + } + + // Triggered once for each file added to the queue + function onSelect(file) { + if (jQuery.inArray('onSelect',swfuploadify.settings.skipDefault) < 0) { + // Check if a file with the same name exists in the queue + var queuedFile = {}; + for (var n in swfuploadify.queue.files) { + queuedFile = swfuploadify.queue.files[n]; + if (queuedFile.name == file.name) { + var replaceQueueItem = confirm('The file named "' + file.name + '" is already in the queue.\nDo you want to replace the existing item in the queue?'); + if (!replaceQueueItem) { + swfuploadify.cancelUpload(file.id); + swfuploadify.queue.filesCancelled++; + return false; + } else { + jQuery('#' + queuedFile.id).remove(); + swfuploadify.cancelUpload(queuedFile.id); + swfuploadify.queue.filesReplaced++; + } + } + } + + // Get the size of the file + var fileSize = Math.round(file.size / 1024); + var suffix = 'KB'; + if (fileSize > 1000) { + fileSize = Math.round(fileSize / 1000); + suffix = 'MB'; + } + var fileSizeParts = fileSize.toString().split('.'); + fileSize = fileSizeParts[0]; + if (fileSizeParts.length > 1) { + fileSize += '.' + fileSizeParts[1].substr(0,2); + } + fileSize += suffix; + + // Truncate the filename if it's too long + var fileName = file.name; + if (fileName.length > 25) { + fileName = fileName.substr(0,25) + '...'; + } + + // Add the file item to the queue + jQuery('#' + swfuploadify.settings.queueID).append('
\ +
\ + \ +
\ + ' + fileName + ' (' + fileSize + ')\ +
\ +
\ +
\ +
'); + swfuploadify.queue.queueSize += file.size; + } + swfuploadify.queue.files[file.id] = file; + if (swfuploadify.settings.onSelect) swfuploadify.settings.onSelect(file); + } + + // Triggered when a file is not added to the queue + function onSelectError(file,errorCode,errorMsg) { + if (jQuery.inArray('onSelectError',swfuploadify.settings.skipDefault) < 0) { + switch(errorCode) { + case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED: + if (swfuploadify.settings.queueSizeLimit > errorMsg) { + swfuploadify.queue.errorMsg += '\nThe number of files selected exceeds the remaining upload limit (' + errorMsg + ').'; + } else { + swfuploadify.queue.errorMsg += '\nThe number of files selected exceeds the queue size limit (' + swfuploadify.settings.queueSizeLimit + ').'; + } + break; + case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT: + swfuploadify.queue.errorMsg += '\nThe file "' + file.name + '" exceeds the size limit (' + swfuploadify.settings.fileSizeLimit + ').'; + break; + case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: + swfuploadify.queue.errorMsg += '\nThe file "' + file.name + '" is empty.'; + break; + case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT: + swfuploadify.queue.errorMsg += '\nThe file "' + file.name + '" is not an accepted file type (' + swfuploadify.settings.fileTypeDesc + ').'; + break; + } + } + if (errorCode != SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED) { + delete swfuploadify.queue.files[file.id]; + } + if (swfuploadify.settings.onSelectError) swfuploadify.settings.onSelectError(file,errorCode,errorMsg); + } + + // Triggered when all the files in the queue have been processed + function onQueueComplete() { + var stats = swfuploadify.getStats(); + if (swfuploadify.settings.onQueueComplete) swfuploadify.settings.onQueueComplete(stats); + } + + // Triggered when a file upload successfully completes + function onUploadComplete(file) { + var stats = swfuploadify.getStats(); + swfuploadify.queue.queueLength = stats.files_queued; + if (swfuploadify.queue.uploadQueue[0] == '*') { + if (swfuploadify.queue.queueLength > 0) { + swfuploadify.startUpload(); + } else { + swfuploadify.queue.uploadQueue = []; + if (swfuploadify.settings.onQueueComplete) swfuploadify.settings.onQueueComplete(stats); + } + } else { + if (swfuploadify.queue.uploadQueue.length > 0) { + swfuploadify.startUpload(swfuploadify.queue.uploadQueue.shift()); + } else { + swfuploadify.queue.uploadQueue = []; + if (swfuploadify.settings.onQueueComplete) setting.onQueueComplete(stats); + } + } + if (jQuery.inArray('onUploadComplete',swfuploadify.settings.skipDefault) < 0) { + if (swfuploadify.settings.removeCompleted) { + switch (file.filestatus) { + case SWFUpload.FILE_STATUS.COMPLETE: + setTimeout(function() { + if (jQuery('#' + file.id)) { + swfuploadify.queue.queueSize -= file.size; + delete swfuploadify.queue.files[file.id] + jQuery('#' + file.id).fadeOut(500,function() { + jQuery(this).remove(); + }); + } + },swfuploadify.settings.removeTimeout * 1000); + break; + case SWFUpload.FILE_STATUS.ERROR: + if (!swfuploadify.settings.requeueErrors) { + setTimeout(function() { + if (jQuery('#' + file.id)) { + swfuploadify.queue.queueSize -= file.size; + delete swfuploadify.queue.files[file.id]; + jQuery('#' + file.id).fadeOut(500,function() { + jQuery(this).remove(); + }); + } + },swfuploadify.settings.removeTimeout * 1000); + } + break; + } + } + } + if (swfuploadify.settings.onUploadComplete) swfuploadify.settings.onUploadComplete(file,swfuploadify.queue); + } + + // Triggered when a file upload returns an error + function onUploadError(file,errorCode,errorMsg) { + var errorString = 'Error'; + if (errorCode != SWFUpload.UPLOAD_ERROR.FILE_CANCELLED && errorCode != SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED) { + jQuery('#' + file.id).addClass('uploadifyError'); + } + jQuery('#' + file.id).find('.uploadifyProgressBar').css('width','1px'); + switch(errorCode) { + case SWFUpload.UPLOAD_ERROR.HTTP_ERROR: + errorString = 'HTTP Error (' + errorMsg + ')'; + break; + case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL: + errorString = 'Missing Upload URL'; + break; + case SWFUpload.UPLOAD_ERROR.IO_ERROR: + errorString = 'IO Error'; + break; + case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR: + errorString = 'Security Error'; + break; + case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED: + alert('The upload limit has been reached (' + errorMsg + ').'); + errorString = 'Exceeds Upload Limit'; + break; + case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED: + errorString = 'Failed'; + break; + case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND: + break; + case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED: + errorString = 'Validation Error'; + break; + case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED: + errorString = 'Cancelled'; + swfuploadify.queue.queueSize -= file.size; + if (file.status == SWFUpload.FILE_STATUS.IN_PROGRESS || jQuery.inArray(file.id,swfuploadify.queue.uploadQueue) >= 0) { + swfuploadify.queue.uploadSize -= file.size; + } + delete swfuploadify.queue.files[file.id]; + break; + case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED: + errorString = 'Stopped'; + break; + } + if (errorCode != SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND && file.status != SWFUpload.FILE_STATUS.COMPLETE) { + jQuery('#' + file.id).find('.data').html(' - ' + errorString); + } + if (swfuploadify.settings.onUploadError) swfuploadify.settings.onUploadError(file,errorCode,errorMsg,errorString,swfuploadify.queue); + } + + // Triggered periodically during a file upload + function onUploadProgress(file,fileBytesLoaded,fileTotalBytes) { + var timer = new Date(); + var newTime = timer.getTime(); + var lapsedTime = newTime - swfuploadify.timer; + swfuploadify.timer = newTime; + var lapsedBytes = fileBytesLoaded - swfuploadify.bytesLoaded; + swfuploadify.bytesLoaded = fileBytesLoaded; + var queueBytesLoaded = swfuploadify.queue.queueBytesUploaded + fileBytesLoaded; + var percentage = Math.round(fileBytesLoaded / fileTotalBytes * 100); + + // Calculate the average speed + var mbs = 0; + var kbs = (lapsedBytes / 1024) / (lapsedTime / 1000); + kbs = Math.floor(kbs * 10) / 10; + if (swfuploadify.queue.averageSpeed > 0) { + swfuploadify.queue.averageSpeed = (swfuploadify.queue.averageSpeed + kbs) / 2; + } else { + swfuploadify.queue.averageSpeed = kbs; + } + if (kbs > 1000) { + mbs = (kbs * .001); + swfuploadify.queue.averageSpeed = mbs; + } + var suffix = 'KB/s'; + if (mbs > 0) { + suffix = 'MB/s'; + } + + if (jQuery.inArray('onUploadProgress',swfuploadify.settings.skipDefault) < 0) { + if (swfuploadify.settings.progressData == 'percentage') { + jQuery('#' + file.id).find('.data').html(' - ' + percentage + '%'); + } else if (swfuploadify.settings.progressData == 'speed') { + jQuery('#' + file.id).find('.data').html(' - ' + percentage + suffix); + } + jQuery('#' + file.id).find('.uploadifyProgressBar').css('width',percentage + '%'); + } + if (swfuploadify.settings.onUploadProgress) swfuploadify.settings.onUploadProgress(file,fileBytesLoaded,fileTotalBytes,queueBytesLoaded,swfuploadify.queue.uploadSize); + } + + // Triggered right before a file is uploaded + function onUploadStart(file) { + var timer = new Date(); + swfuploadify.timer = timer.getTime(); + swfuploadify.bytesLoaded = 0; + if (swfuploadify.queue.uploadQueue.length == 0) { + swfuploadify.queue.uploadSize = file.size; + } + if (swfuploadify.settings.checkExisting !== false) { + jQuery.ajax({ + type : 'POST', + async : false, + url : swfuploadify.settings.checkExisting, + data : {filename: file.name}, + success : function(data) { + if (data == 1) { + var overwrite = confirm('A file with the name "' + file.name + '" already exists on the server.\nWould you like to replace the existing file?'); + if (!overwrite) { + swfuploadify.cancelUpload(file.id); + jQuery('#' + file.id).remove(); + if (swfuploadify.queue.uploadQueue.length > 0 && swfuploadify.queue.queueLength > 0) { + if (swfuploadify.queue.uploadQueue[0] == '*') { + swfuploadify.startUpload(); + } else { + swfuploadify.startUpload(swfuploadify.queue.uploadQueue.shift()); + } + } + } + } + } + }); + } + if (swfuploadify.settings.onUploadStart) swfuploadify.settings.onUploadStart(file); + } + + // Triggered when a file upload returns a successful code + function onUploadSuccess(file,data,response) { + swfuploadify.queue.queueBytesUploaded += file.size; + jQuery('#' + file.id).find('.data').html(' - Complete'); + if (swfuploadify.settings.onUploadSuccess) swfuploadify.settings.onUploadSuccess(file,data,response); + } + + // --------------------------- + // End Event Handler Functions + // --------------------------- + }); + }, + + // Cancel a file upload and remove it from the queue + uploadifyCancel:function(fileID) { + var id = jQuery(this).selector.replace('#',''); + var swfuploadify = window['uploadify_' + id]; + var delay = -1; + if (arguments[0]) { + if (arguments[0] == '*') { + jQuery('#' + swfuploadify.settings.queueID).find('.uploadifyQueueItem').each(function() { + delay++; + swfuploadify.cancelUpload(jQuery(this).attr('id')); + jQuery(this).delay(100 * delay).fadeOut(500,function() { + jQuery(this).remove(); + + }); + }); + swfuploadify.queue.queueSize = 0; + } else { + for (var n = 0; n < arguments.length; n++) { + swfuploadify.cancelUpload(arguments[n]); + jQuery('#' + arguments[n]).delay(100 * n).fadeOut(500,function() { + jQuery(this).remove(); + }); + } + } + } else { + jQuery('#' + swfuploadify.settings.queueID).find('.uploadifyQueueItem').get(0).fadeOut(500,function() { + jQuery(this).remove(); + swfuploadify.cancelUpload(jQuery(this).attr('id')); + }); + } + }, + + // Get rid of the instance of Uploadify + uploadifyDestroy:function() { + var id = jQuery(this).selector.replace('#',''); + var swfuploadify = window['uploadify_' + id]; + swfuploadify.destroy(); + jQuery('#' + id + '_queue').remove(); + jQuery('#' + id).replaceWith(swfuploadify.original); + delete window['uploadify_' + id]; + }, + + // Disable the select button + uploadifyDisable:function(isDisabled) { + var id = jQuery(this).selector.replace('#',''); + var swfuploadify = window['uploadify_' + id]; + swfuploadify.setButtonDisabled(isDisabled); + }, + + // Update or retrieve a setting + uploadifySettings:function(name,value,resetObjects) { + var id = jQuery(this).selector.replace('#',''); + var swfuploadify = window['uploadify_' + id]; + if (typeof(arguments[0]) == 'object') { + for (var n in value) { + setData(n,value[n]); + } + } + if (arguments.length == 1) { + return swfuploadify.settings[name]; + } else { + setData(name,value,resetObjects); + } + + function setData(settingName,settingValue,resetObjects) { + switch (settingName) { + case 'uploader': + swfuploadify.setUploadURL(settingValue); + break; + case 'postData': + if (!resetObjects) { + value = jQuery.extend(swfuploadify.settings.postData,settingValue); + } + swfuploadify.setPostParams(settingValue); + break; + case 'method': + if (settingValue == 'get') { + swfuploadify.setUseQueryString(true); + } else { + swfuploadify.setUseQueryString(false); + } + break; + case 'fileObjName': + swfuploadify.setFilePostName(settingValue); + break; + case 'fileTypeExts': + swfuploadify.setFileTypes(settingValue,swfuploadify.settings.fileTypeDesc); + break; + case 'fileTypeDesc': + swfuploadify.setFileTypes(swfuploadify.settings.fileTypeExts,settingValue); + break; + case 'fileSizeLimit': + swfuploadify.setFileSizeLimit(settingValue); + break; + case 'uploadLimit': + swfuploadify.setFileUploadLimit(settingValue); + break; + case 'queueSizeLimit': + swfuploadify.setFileQueueLimit(settingValue); + break; + case 'buttonImage': + jQuery('#' + swfuploadify.settings.id + '_button').remove(); + swfuploadify.setButtonImageURL(settingValue); + break; + case 'buttonCursor': + if (settingValue == 'arrow') { + swfuploadify.setButtonCursor(SWFUpload.CURSOR.ARROW); + } else { + swfuploadify.setButtonCursor(SWFUpload.CURSOR.HAND); + } + break; + case 'buttonText': + jQuery('#' + swfuploadify.settings.id + '_button').find('.uploadifyButtonText').html(settingValue); + break; + case 'width': + swfuploadify.setButtonDimensions(settingValue,swfuploadify.settings.height); + break; + case 'height': + swfuploadify.setButtonDimensions(swfuploadify.settings.width,settingValue); + break; + case 'multi': + if (settingValue) { + swfuploadify.setButtonAction(SWFUpload.BUTTON_ACTION.SELECT_FILES); + } else { + swfuploadify.setButtonAction(SWFUpload.BUTTON_ACTION.SELECT_FILE); + } + break; + } + swfuploadify.settings[settingName] = value; + } + }, + + // Stop the current upload and requeue what is in progress + uploadifyStop:function() { + var id = jQuery(this).selector.replace('#',''); + var swfuploadify = window['uploadify_' + id]; + swfuploadify.stopUpload(); + }, + + // Upload the first file, a select number of files, or all the files in the queue + uploadifyUpload:function() { + var id = jQuery(this).selector.replace('#',''); + var swfuploadify = window['uploadify_' + id]; + + // Reset the queue information + swfuploadify.queue.averageSpeed = 0; + swfuploadify.queue.uploadSize = 0; + swfuploadify.queue.bytesUploaded = 0; + swfuploadify.queue.uploadQueue = []; + + if (arguments[0]) { + if (arguments[0] == '*') { + swfuploadify.queue.uploadSize = swfuploadify.queue.queueSize; + swfuploadify.queue.uploadQueue.push('*'); + swfuploadify.startUpload(); + } else { + for (var n = 0; n < arguments.length; n++) { + swfuploadify.queue.uploadSize += swfuploadify.queue.files[arguments[n]].size; + swfuploadify.queue.uploadQueue.push(arguments[n]); + } + swfuploadify.startUpload(swfuploadify.queue.uploadQueue.shift()); + } + } else { + swfuploadify.startUpload(); + } + } + }) + } +)(jQuery); \ No newline at end of file diff --git a/directupload/static/uploadify/jquery.uploadify.min.js b/directupload/static/uploadify/jquery.uploadify.min.js new file mode 100644 index 0000000..568637e --- /dev/null +++ b/directupload/static/uploadify/jquery.uploadify.min.js @@ -0,0 +1,38 @@ +/* +SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com + +mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/ + +SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License: +http://www.opensource.org/licenses/mit-license.php + +SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License: +http://www.opensource.org/licenses/mit-license.php +*/ + +var SWFUpload;if(SWFUpload==undefined){SWFUpload=function(a){this.initSWFUpload(a)}}SWFUpload.prototype.initSWFUpload=function(b){try{this.customSettings={};this.settings=b;this.eventQueue=[];this.movieName="SWFUpload_"+SWFUpload.movieCount++;this.movieElement=null;SWFUpload.instances[this.movieName]=this;this.initSettings();this.loadFlash();this.displayDebugInfo()}catch(a){delete SWFUpload.instances[this.movieName];throw a}};SWFUpload.instances={};SWFUpload.movieCount=0;SWFUpload.version="2.2.0 2009-03-25";SWFUpload.QUEUE_ERROR={QUEUE_LIMIT_EXCEEDED:-100,FILE_EXCEEDS_SIZE_LIMIT:-110,ZERO_BYTE_FILE:-120,INVALID_FILETYPE:-130};SWFUpload.UPLOAD_ERROR={HTTP_ERROR:-200,MISSING_UPLOAD_URL:-210,IO_ERROR:-220,SECURITY_ERROR:-230,UPLOAD_LIMIT_EXCEEDED:-240,UPLOAD_FAILED:-250,SPECIFIED_FILE_ID_NOT_FOUND:-260,FILE_VALIDATION_FAILED:-270,FILE_CANCELLED:-280,UPLOAD_STOPPED:-290};SWFUpload.FILE_STATUS={QUEUED:-1,IN_PROGRESS:-2,ERROR:-3,COMPLETE:-4,CANCELLED:-5};SWFUpload.BUTTON_ACTION={SELECT_FILE:-100,SELECT_FILES:-110,START_UPLOAD:-120};SWFUpload.CURSOR={ARROW:-1,HAND:-2};SWFUpload.WINDOW_MODE={WINDOW:"window",TRANSPARENT:"transparent",OPAQUE:"opaque"};SWFUpload.completeURL=function(a){if(typeof(a)!=="string"||a.match(/^https?:\/\//i)||a.match(/^\//)){return a}var c=window.location.protocol+"//"+window.location.hostname+(window.location.port?":"+window.location.port:"");var b=window.location.pathname.lastIndexOf("/");if(b<=0){path="/"}else{path=window.location.pathname.substr(0,b)+"/"}return path+a};SWFUpload.prototype.initSettings=function(){this.ensureDefault=function(b,a){this.settings[b]=(this.settings[b]==undefined)?a:this.settings[b]};this.ensureDefault("upload_url","");this.ensureDefault("preserve_relative_urls",false);this.ensureDefault("file_post_name","Filedata");this.ensureDefault("post_params",{});this.ensureDefault("use_query_string",false);this.ensureDefault("requeue_on_error",false);this.ensureDefault("http_success",[]);this.ensureDefault("assume_success_timeout",0);this.ensureDefault("file_types","*.*");this.ensureDefault("file_types_description","All Files");this.ensureDefault("file_size_limit",0);this.ensureDefault("file_upload_limit",0);this.ensureDefault("file_queue_limit",0);this.ensureDefault("flash_url","swfupload.swf");this.ensureDefault("prevent_swf_caching",true);this.ensureDefault("button_image_url","");this.ensureDefault("button_width",1);this.ensureDefault("button_height",1);this.ensureDefault("button_text","");this.ensureDefault("button_text_style","color: #000000; font-size: 16pt;");this.ensureDefault("button_text_top_padding",0);this.ensureDefault("button_text_left_padding",0);this.ensureDefault("button_action",SWFUpload.BUTTON_ACTION.SELECT_FILES);this.ensureDefault("button_disabled",false);this.ensureDefault("button_placeholder_id","");this.ensureDefault("button_placeholder",null);this.ensureDefault("button_cursor",SWFUpload.CURSOR.ARROW);this.ensureDefault("button_window_mode",SWFUpload.WINDOW_MODE.WINDOW);this.ensureDefault("debug",false);this.settings.debug_enabled=this.settings.debug;this.settings.return_upload_start_handler=this.returnUploadStart;this.ensureDefault("swfupload_loaded_handler",null);this.ensureDefault("file_dialog_start_handler",null);this.ensureDefault("file_queued_handler",null);this.ensureDefault("file_queue_error_handler",null);this.ensureDefault("file_dialog_complete_handler",null);this.ensureDefault("upload_start_handler",null);this.ensureDefault("upload_progress_handler",null);this.ensureDefault("upload_error_handler",null);this.ensureDefault("upload_success_handler",null);this.ensureDefault("upload_complete_handler",null);this.ensureDefault("debug_handler",this.debugMessage);this.ensureDefault("custom_settings",{});this.customSettings=this.settings.custom_settings;if(!!this.settings.prevent_swf_caching){this.settings.flash_url=this.settings.flash_url+(this.settings.flash_url.indexOf("?")<0?"?":"&")+"preventswfcaching="+new Date().getTime()}if(!this.settings.preserve_relative_urls){this.settings.upload_url=SWFUpload.completeURL(this.settings.upload_url);this.settings.button_image_url=SWFUpload.completeURL(this.settings.button_image_url)}delete this.ensureDefault};SWFUpload.prototype.loadFlash=function(){var a,b;if(document.getElementById(this.movieName)!==null){throw"ID "+this.movieName+" is already in use. The Flash Object could not be added"}a=document.getElementById(this.settings.button_placeholder_id)||this.settings.button_placeholder;if(a==undefined){throw"Could not find the placeholder element: "+this.settings.button_placeholder_id}b=document.createElement("div");b.innerHTML=this.getFlashHTML();a.parentNode.replaceChild(b.firstChild,a);if(window[this.movieName]==undefined){window[this.movieName]=this.getMovieElement()}};SWFUpload.prototype.getFlashHTML=function(){return['','','','','','','',""].join("")};SWFUpload.prototype.getFlashVars=function(){var b=this.buildParamString();var a=this.settings.http_success.join(",");return["movieName=",encodeURIComponent(this.movieName),"&uploadURL=",encodeURIComponent(this.settings.upload_url),"&useQueryString=",encodeURIComponent(this.settings.use_query_string),"&requeueOnError=",encodeURIComponent(this.settings.requeue_on_error),"&httpSuccess=",encodeURIComponent(a),"&assumeSuccessTimeout=",encodeURIComponent(this.settings.assume_success_timeout),"&params=",encodeURIComponent(b),"&filePostName=",encodeURIComponent(this.settings.file_post_name),"&fileTypes=",encodeURIComponent(this.settings.file_types),"&fileTypesDescription=",encodeURIComponent(this.settings.file_types_description),"&fileSizeLimit=",encodeURIComponent(this.settings.file_size_limit),"&fileUploadLimit=",encodeURIComponent(this.settings.file_upload_limit),"&fileQueueLimit=",encodeURIComponent(this.settings.file_queue_limit),"&debugEnabled=",encodeURIComponent(this.settings.debug_enabled),"&buttonImageURL=",encodeURIComponent(this.settings.button_image_url),"&buttonWidth=",encodeURIComponent(this.settings.button_width),"&buttonHeight=",encodeURIComponent(this.settings.button_height),"&buttonText=",encodeURIComponent(this.settings.button_text),"&buttonTextTopPadding=",encodeURIComponent(this.settings.button_text_top_padding),"&buttonTextLeftPadding=",encodeURIComponent(this.settings.button_text_left_padding),"&buttonTextStyle=",encodeURIComponent(this.settings.button_text_style),"&buttonAction=",encodeURIComponent(this.settings.button_action),"&buttonDisabled=",encodeURIComponent(this.settings.button_disabled),"&buttonCursor=",encodeURIComponent(this.settings.button_cursor)].join("")};SWFUpload.prototype.getMovieElement=function(){if(this.movieElement==undefined){this.movieElement=document.getElementById(this.movieName)}if(this.movieElement===null){throw"Could not find Flash element"}return this.movieElement};SWFUpload.prototype.buildParamString=function(){var c=this.settings.post_params;var b=[];if(typeof(c)==="object"){for(var a in c){if(c.hasOwnProperty(a)){b.push(encodeURIComponent(a.toString())+"="+encodeURIComponent(c[a].toString()))}}}return b.join("&")};SWFUpload.prototype.destroy=function(){try{this.cancelUpload(null,false);var a=null;a=this.getMovieElement();if(a&&typeof(a.CallFunction)==="unknown"){for(var c in a){try{if(typeof(a[c])==="function"){a[c]=null}}catch(e){}}try{a.parentNode.removeChild(a)}catch(b){}}window[this.movieName]=null;SWFUpload.instances[this.movieName]=null;delete SWFUpload.instances[this.movieName];this.movieElement=null;this.settings=null;this.customSettings=null;this.eventQueue=null;this.movieName=null;return true}catch(d){return false}};SWFUpload.prototype.displayDebugInfo=function(){this.debug(["---SWFUpload Instance Info---\n","Version: ",SWFUpload.version,"\n","Movie Name: ",this.movieName,"\n","Settings:\n","\t","upload_url: ",this.settings.upload_url,"\n","\t","flash_url: ",this.settings.flash_url,"\n","\t","use_query_string: ",this.settings.use_query_string.toString(),"\n","\t","requeue_on_error: ",this.settings.requeue_on_error.toString(),"\n","\t","http_success: ",this.settings.http_success.join(", "),"\n","\t","assume_success_timeout: ",this.settings.assume_success_timeout,"\n","\t","file_post_name: ",this.settings.file_post_name,"\n","\t","post_params: ",this.settings.post_params.toString(),"\n","\t","file_types: ",this.settings.file_types,"\n","\t","file_types_description: ",this.settings.file_types_description,"\n","\t","file_size_limit: ",this.settings.file_size_limit,"\n","\t","file_upload_limit: ",this.settings.file_upload_limit,"\n","\t","file_queue_limit: ",this.settings.file_queue_limit,"\n","\t","debug: ",this.settings.debug.toString(),"\n","\t","prevent_swf_caching: ",this.settings.prevent_swf_caching.toString(),"\n","\t","button_placeholder_id: ",this.settings.button_placeholder_id.toString(),"\n","\t","button_placeholder: ",(this.settings.button_placeholder?"Set":"Not Set"),"\n","\t","button_image_url: ",this.settings.button_image_url.toString(),"\n","\t","button_width: ",this.settings.button_width.toString(),"\n","\t","button_height: ",this.settings.button_height.toString(),"\n","\t","button_text: ",this.settings.button_text.toString(),"\n","\t","button_text_style: ",this.settings.button_text_style.toString(),"\n","\t","button_text_top_padding: ",this.settings.button_text_top_padding.toString(),"\n","\t","button_text_left_padding: ",this.settings.button_text_left_padding.toString(),"\n","\t","button_action: ",this.settings.button_action.toString(),"\n","\t","button_disabled: ",this.settings.button_disabled.toString(),"\n","\t","custom_settings: ",this.settings.custom_settings.toString(),"\n","Event Handlers:\n","\t","swfupload_loaded_handler assigned: ",(typeof this.settings.swfupload_loaded_handler==="function").toString(),"\n","\t","file_dialog_start_handler assigned: ",(typeof this.settings.file_dialog_start_handler==="function").toString(),"\n","\t","file_queued_handler assigned: ",(typeof this.settings.file_queued_handler==="function").toString(),"\n","\t","file_queue_error_handler assigned: ",(typeof this.settings.file_queue_error_handler==="function").toString(),"\n","\t","upload_start_handler assigned: ",(typeof this.settings.upload_start_handler==="function").toString(),"\n","\t","upload_progress_handler assigned: ",(typeof this.settings.upload_progress_handler==="function").toString(),"\n","\t","upload_error_handler assigned: ",(typeof this.settings.upload_error_handler==="function").toString(),"\n","\t","upload_success_handler assigned: ",(typeof this.settings.upload_success_handler==="function").toString(),"\n","\t","upload_complete_handler assigned: ",(typeof this.settings.upload_complete_handler==="function").toString(),"\n","\t","debug_handler assigned: ",(typeof this.settings.debug_handler==="function").toString(),"\n"].join(""))};SWFUpload.prototype.addSetting=function(b,c,a){if(c==undefined){return(this.settings[b]=a)}else{return(this.settings[b]=c)}};SWFUpload.prototype.getSetting=function(a){if(this.settings[a]!=undefined){return this.settings[a]}return""};SWFUpload.prototype.callFlash=function(functionName,argumentArray){argumentArray=argumentArray||[];var movieElement=this.getMovieElement();var returnValue,returnString;try{returnString=movieElement.CallFunction(''+__flash__argumentsToXML(argumentArray,0)+"");returnValue=eval(returnString)}catch(ex){throw"Call to "+functionName+" failed"}if(returnValue!=undefined&&typeof returnValue.post==="object"){returnValue=this.unescapeFilePostParams(returnValue)}return returnValue};SWFUpload.prototype.selectFile=function(){this.callFlash("SelectFile")};SWFUpload.prototype.selectFiles=function(){this.callFlash("SelectFiles")};SWFUpload.prototype.startUpload=function(a){this.callFlash("StartUpload",[a])};SWFUpload.prototype.cancelUpload=function(a,b){if(b!==false){b=true}this.callFlash("CancelUpload",[a,b])};SWFUpload.prototype.stopUpload=function(){this.callFlash("StopUpload")};SWFUpload.prototype.getStats=function(){return this.callFlash("GetStats")};SWFUpload.prototype.setStats=function(a){this.callFlash("SetStats",[a])};SWFUpload.prototype.getFile=function(a){if(typeof(a)==="number"){return this.callFlash("GetFileByIndex",[a])}else{return this.callFlash("GetFile",[a])}};SWFUpload.prototype.addFileParam=function(a,b,c){return this.callFlash("AddFileParam",[a,b,c])};SWFUpload.prototype.removeFileParam=function(a,b){this.callFlash("RemoveFileParam",[a,b])};SWFUpload.prototype.setUploadURL=function(a){this.settings.upload_url=a.toString();this.callFlash("SetUploadURL",[a])};SWFUpload.prototype.setPostParams=function(a){this.settings.post_params=a;this.callFlash("SetPostParams",[a])};SWFUpload.prototype.addPostParam=function(a,b){this.settings.post_params[a]=b;this.callFlash("SetPostParams",[this.settings.post_params])};SWFUpload.prototype.removePostParam=function(a){delete this.settings.post_params[a];this.callFlash("SetPostParams",[this.settings.post_params])};SWFUpload.prototype.setFileTypes=function(a,b){this.settings.file_types=a;this.settings.file_types_description=b;this.callFlash("SetFileTypes",[a,b])};SWFUpload.prototype.setFileSizeLimit=function(a){this.settings.file_size_limit=a;this.callFlash("SetFileSizeLimit",[a])};SWFUpload.prototype.setFileUploadLimit=function(a){this.settings.file_upload_limit=a;this.callFlash("SetFileUploadLimit",[a])};SWFUpload.prototype.setFileQueueLimit=function(a){this.settings.file_queue_limit=a;this.callFlash("SetFileQueueLimit",[a])};SWFUpload.prototype.setFilePostName=function(a){this.settings.file_post_name=a;this.callFlash("SetFilePostName",[a])};SWFUpload.prototype.setUseQueryString=function(a){this.settings.use_query_string=a;this.callFlash("SetUseQueryString",[a])};SWFUpload.prototype.setRequeueOnError=function(a){this.settings.requeue_on_error=a;this.callFlash("SetRequeueOnError",[a])};SWFUpload.prototype.setHTTPSuccess=function(a){if(typeof a==="string"){a=a.replace(" ","").split(",")}this.settings.http_success=a;this.callFlash("SetHTTPSuccess",[a])};SWFUpload.prototype.setAssumeSuccessTimeout=function(a){this.settings.assume_success_timeout=a;this.callFlash("SetAssumeSuccessTimeout",[a])};SWFUpload.prototype.setDebugEnabled=function(a){this.settings.debug_enabled=a;this.callFlash("SetDebugEnabled",[a])};SWFUpload.prototype.setButtonImageURL=function(a){if(a==undefined){a=""}this.settings.button_image_url=a;this.callFlash("SetButtonImageURL",[a])};SWFUpload.prototype.setButtonDimensions=function(c,a){this.settings.button_width=c;this.settings.button_height=a;var b=this.getMovieElement();if(b!=undefined){b.style.width=c+"px";b.style.height=a+"px"}this.callFlash("SetButtonDimensions",[c,a])};SWFUpload.prototype.setButtonText=function(a){this.settings.button_text=a;this.callFlash("SetButtonText",[a])};SWFUpload.prototype.setButtonTextPadding=function(b,a){this.settings.button_text_top_padding=a;this.settings.button_text_left_padding=b;this.callFlash("SetButtonTextPadding",[b,a])};SWFUpload.prototype.setButtonTextStyle=function(a){this.settings.button_text_style=a;this.callFlash("SetButtonTextStyle",[a])};SWFUpload.prototype.setButtonDisabled=function(a){this.settings.button_disabled=a;this.callFlash("SetButtonDisabled",[a])};SWFUpload.prototype.setButtonAction=function(a){this.settings.button_action=a;this.callFlash("SetButtonAction",[a])};SWFUpload.prototype.setButtonCursor=function(a){this.settings.button_cursor=a;this.callFlash("SetButtonCursor",[a])};SWFUpload.prototype.queueEvent=function(b,c){if(c==undefined){c=[]}else{if(!(c instanceof Array)){c=[c]}}var a=this;if(typeof this.settings[b]==="function"){this.eventQueue.push(function(){this.settings[b].apply(this,c)});setTimeout(function(){a.executeNextEvent()},0)}else{if(this.settings[b]!==null){throw"Event handler "+b+" is unknown or is not a function"}}};SWFUpload.prototype.executeNextEvent=function(){var a=this.eventQueue?this.eventQueue.shift():null;if(typeof(a)==="function"){a.apply(this)}};SWFUpload.prototype.unescapeFilePostParams=function(c){var e=/[$]([0-9a-f]{4})/i;var f={};var d;if(c!=undefined){for(var a in c.post){if(c.post.hasOwnProperty(a)){d=a;var b;while((b=e.exec(d))!==null){d=d.replace(b[0],String.fromCharCode(parseInt("0x"+b[1],16)))}f[d]=c.post[a]}}c.post=f}return c};SWFUpload.prototype.testExternalInterface=function(){try{return this.callFlash("TestExternalInterface")}catch(a){return false}};SWFUpload.prototype.flashReady=function(){var a=this.getMovieElement();if(!a){this.debug("Flash called back ready but the flash movie can't be found.");return}this.cleanUp(a);this.queueEvent("swfupload_loaded_handler")};SWFUpload.prototype.cleanUp=function(a){try{if(this.movieElement&&typeof(a.CallFunction)==="unknown"){this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");for(var c in a){try{if(typeof(a[c])==="function"){a[c]=null}}catch(b){}}}}catch(d){}window.__flash__removeCallback=function(e,f){try{if(e){e[f]=null}}catch(g){}}};SWFUpload.prototype.fileDialogStart=function(){this.queueEvent("file_dialog_start_handler")};SWFUpload.prototype.fileQueued=function(a){a=this.unescapeFilePostParams(a);this.queueEvent("file_queued_handler",a)};SWFUpload.prototype.fileQueueError=function(a,c,b){a=this.unescapeFilePostParams(a);this.queueEvent("file_queue_error_handler",[a,c,b])};SWFUpload.prototype.fileDialogComplete=function(b,c,a){this.queueEvent("file_dialog_complete_handler",[b,c,a])};SWFUpload.prototype.uploadStart=function(a){a=this.unescapeFilePostParams(a);this.queueEvent("return_upload_start_handler",a)};SWFUpload.prototype.returnUploadStart=function(a){var b;if(typeof this.settings.upload_start_handler==="function"){a=this.unescapeFilePostParams(a);b=this.settings.upload_start_handler.call(this,a)}else{if(this.settings.upload_start_handler!=undefined){throw"upload_start_handler must be a function"}}if(b===undefined){b=true}b=!!b;this.callFlash("ReturnUploadStart",[b])};SWFUpload.prototype.uploadProgress=function(a,c,b){a=this.unescapeFilePostParams(a);this.queueEvent("upload_progress_handler",[a,c,b])};SWFUpload.prototype.uploadError=function(a,c,b){a=this.unescapeFilePostParams(a);this.queueEvent("upload_error_handler",[a,c,b])};SWFUpload.prototype.uploadSuccess=function(b,a,c){b=this.unescapeFilePostParams(b);this.queueEvent("upload_success_handler",[b,a,c])};SWFUpload.prototype.uploadComplete=function(a){a=this.unescapeFilePostParams(a);this.queueEvent("upload_complete_handler",a)};SWFUpload.prototype.debug=function(a){this.queueEvent("debug_handler",a)};SWFUpload.prototype.debugMessage=function(c){if(this.settings.debug){var a,d=[];if(typeof c==="object"&&typeof c.name==="string"&&typeof c.message==="string"){for(var b in c){if(c.hasOwnProperty(b)){d.push(b+": "+c[b])}}a=d.join("\n")||"";d=a.split("\n");a="EXCEPTION: "+d.join("\nEXCEPTION: ");SWFUpload.Console.writeLine(a)}else{SWFUpload.Console.writeLine(c)}}};SWFUpload.Console={};SWFUpload.Console.writeLine=function(d){var b,a;try{b=document.getElementById("SWFUpload_Console");if(!b){a=document.createElement("form");document.getElementsByTagName("body")[0].appendChild(a);b=document.createElement("textarea");b.id="SWFUpload_Console";b.style.fontFamily="monospace";b.setAttribute("wrap","off");b.wrap="off";b.style.overflow="auto";b.style.width="700px";b.style.height="350px";b.style.margin="5px";a.appendChild(b)}b.value+=d+"\n";b.scrollTop=b.scrollHeight-b.clientHeight}catch(c){alert("Exception: "+c.name+" Message: "+c.message)}}; + +/* +Uploadify v3.0.0 +Copyright (c) 2010 Ronnie Garcia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +if(jQuery){(function(a){a.extend(a.fn,{uploadify:function(b,c){a(this).each(function(){var r=a(this).clone();var k=a.extend({id:a(this).attr("id"),swf:"uploadify.swf",uploader:"uploadify.php",auto:false,buttonClass:"",buttonCursor:"hand",buttonImage:false,buttonText:"SELECT FILES",cancelImage:"uploadify-cancel.png",checkExisting:"uploadify-check-existing.php",debug:false,fileObjName:"Filedata",fileSizeLimit:0,fileTypeDesc:"All Files (*.*)",fileTypeExts:"*.*",height:30,method:"post",multi:false,queueID:false,queueSizeLimit:999,removeCompleted:true,removeTimeout:3,requeueErrors:true,postData:{},preventCaching:true,progressData:"percentage",successTimeout:30,transparent:true,uploadLimit:999,uploaderType:"html5",width:120,skipDefault:[],onClearQueue:function(){},onDialogOpen:function(){},onDialogClose:function(){},onInit:function(){},onQueueComplete:function(){},onSelectError:function(){},onSelect:function(){},onSWFReady:function(){},onUploadCancel:function(){},onUploadComplete:function(){},onUploadError:function(){},onUploadProgress:function(){},onUploadStart:function(){}},b);var d={assume_success_timeout:k.successTimeout,button_placeholder_id:k.id,button_image_url:k.buttonImage,button_width:k.width,button_height:k.height,button_text:null,button_text_style:null,button_text_top_padding:0,button_text_left_padding:0,button_action:(k.multi?SWFUpload.BUTTON_ACTION.SELECT_FILES:SWFUpload.BUTTON_ACTION.SELECT_FILE),button_disabled:false,button_cursor:(k.buttonCursor=="arrow"?SWFUpload.CURSOR.ARROW:SWFUpload.CURSOR.HAND),button_window_mode:(k.transparent&&!k.buttonImage?SWFUpload.WINDOW_MODE.TRANSPARENT:SWFUpload.WINDOW_MODE.OPAQUE),debug:k.debug,requeue_on_error:k.requeueErrors,file_post_name:k.fileObjName,file_size_limit:k.fileSizeLimit,file_types:k.fileTypeExts,file_types_description:k.fileTypeDesc,file_queue_limit:k.queueSizeLimit,file_upload_limit:k.uploadLimit,flash_url:k.swf,prevent_swf_caching:k.preventCaching,post_params:k.postData,upload_url:k.uploader,use_query_string:(k.method=="get"),file_dialog_complete_handler:e,file_dialog_start_handler:t,file_queued_handler:p,file_queue_error_handler:q,flash_ready_handler:k.onSWFReady,upload_complete_handler:i,upload_error_handler:s,upload_progress_handler:g,upload_start_handler:h,upload_success_handler:n};if(c){d=a.extend(d,c)}d=a.extend(d,k);window["uploadify_"+k.id]=new SWFUpload(d);var j=window["uploadify_"+k.id];j.original=r;var f=a("
",{id:k.id,"class":"uploadify",css:{height:k.height+"px",position:"relative",width:k.width+"px"}});a("#"+j.movieName).wrap(f);if(!k.queueID){var m=a("
",{id:k.id+"_queue","class":"uploadifyQueue"});a("#"+k.id).after(m);j.settings.queueID=k.queueID=k.id+"_queue"}j.queue={files:{},filesSelected:0,filesQueued:0,filesReplaced:0,filesCancelled:0,filesErrored:0,averageSpeed:0,queueLength:0,queueSize:0,uploadSize:0,queueBytesUploaded:0,uploadQueue:[],errorMsg:"Some files were not added to the queue:"};if(!k.buttonImage){var l=a("
",{id:k.id+"_button","class":"uploadifyButton "+k.buttonClass,html:''+k.buttonText+""});a("#"+k.id).append(l);a("#"+j.movieName).css({position:"absolute","z-index":1})}else{a("#"+j.movieName).addClass(k.buttonClass)}function e(u,w,x){var v=j.getStats();j.queue.filesErrored=u-w;j.queue.filesSelected=u;j.queue.filesQueued=w-j.queue.filesCancelled;j.queue.queueLength=x;if(a.inArray("onDialogClose",j.settings.skipDefault)<0){if(j.queue.filesErrored>0){alert(j.queue.errorMsg)}}if(j.settings.onDialogClose){j.settings.onDialogClose(j.queue)}if(j.settings.auto){a("#"+j.settings.id).uploadifyUpload("*")}}function t(){j.queue.errorMsg="Some files were not added to the queue:";j.queue.filesReplaced=0;j.queue.filesCancelled=0;if(j.settings.onDialogOpen){j.settings.onDialogOpen()}}function p(w){if(a.inArray("onSelect",j.settings.skipDefault)<0){var v={};for(var B in j.queue.files){v=j.queue.files[B];if(v.name==w.name){var x=confirm('The file named "'+w.name+'" is already in the queue.\nDo you want to replace the existing item in the queue?');if(!x){j.cancelUpload(w.id);j.queue.filesCancelled++;return false}else{a("#"+v.id).remove();j.cancelUpload(v.id);j.queue.filesReplaced++}}}var u=Math.round(w.size/1024);var z="KB";if(u>1000){u=Math.round(u/1000);z="MB"}var y=u.toString().split(".");u=y[0];if(y.length>1){u+="."+y[1].substr(0,2)}u+=z;var A=w.name;if(A.length>25){A=A.substr(0,25)+"..."}a("#"+j.settings.queueID).append('
'+A+" ("+u+')
');j.queue.queueSize+=w.size}j.queue.files[w.id]=w;if(j.settings.onSelect){j.settings.onSelect(w)}}function q(u,w,v){if(a.inArray("onSelectError",j.settings.skipDefault)<0){switch(w){case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:if(j.settings.queueSizeLimit>v){j.queue.errorMsg+="\nThe number of files selected exceeds the remaining upload limit ("+v+")."}else{j.queue.errorMsg+="\nThe number of files selected exceeds the queue size limit ("+j.settings.queueSizeLimit+")."}break;case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:j.queue.errorMsg+='\nThe file "'+u.name+'" exceeds the size limit ('+j.settings.fileSizeLimit+").";break;case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:j.queue.errorMsg+='\nThe file "'+u.name+'" is empty.';break;case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:j.queue.errorMsg+='\nThe file "'+u.name+'" is not an accepted file type ('+j.settings.fileTypeDesc+").";break}}if(w!=SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED){delete j.queue.files[u.id]}if(j.settings.onSelectError){j.settings.onSelectError(u,w,v)}}function o(){var u=j.getStats();if(j.settings.onQueueComplete){j.settings.onQueueComplete(u)}}function i(v){var u=j.getStats();j.queue.queueLength=u.files_queued;if(j.queue.uploadQueue[0]=="*"){if(j.queue.queueLength>0){j.startUpload()}else{j.queue.uploadQueue=[];if(j.settings.onQueueComplete){j.settings.onQueueComplete(u)}}}else{if(j.queue.uploadQueue.length>0){j.startUpload(j.queue.uploadQueue.shift())}else{j.queue.uploadQueue=[];if(j.settings.onQueueComplete){setting.onQueueComplete(u)}}}if(a.inArray("onUploadComplete",j.settings.skipDefault)<0){if(j.settings.removeCompleted){switch(v.filestatus){case SWFUpload.FILE_STATUS.COMPLETE:setTimeout(function(){if(a("#"+v.id)){j.queue.queueSize-=v.size;delete j.queue.files[v.id];a("#"+v.id).fadeOut(500,function(){a(this).remove()})}},j.settings.removeTimeout*1000);break;case SWFUpload.FILE_STATUS.ERROR:if(!j.settings.requeueErrors){setTimeout(function(){if(a("#"+v.id)){j.queue.queueSize-=v.size;delete j.queue.files[v.id];a("#"+v.id).fadeOut(500,function(){a(this).remove()})}},j.settings.removeTimeout*1000)}break}}}if(j.settings.onUploadComplete){j.settings.onUploadComplete(v,j.queue)}}function s(u,x,w){var v="Error";if(x!=SWFUpload.UPLOAD_ERROR.FILE_CANCELLED&&x!=SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED){a("#"+u.id).addClass("uploadifyError")}a("#"+u.id).find(".uploadifyProgressBar").css("width","1px");switch(x){case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:v="HTTP Error ("+w+")";break;case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:v="Missing Upload URL";break;case SWFUpload.UPLOAD_ERROR.IO_ERROR:v="IO Error";break;case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:v="Security Error";break;case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:alert("The upload limit has been reached ("+w+").");v="Exceeds Upload Limit";break;case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:v="Failed";break;case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND:break;case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:v="Validation Error";break;case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:v="Cancelled";j.queue.queueSize-=u.size;if(u.status==SWFUpload.FILE_STATUS.IN_PROGRESS||a.inArray(u.id,j.queue.uploadQueue)>=0){j.queue.uploadSize-=u.size}delete j.queue.files[u.id];break;case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:v="Stopped";break}if(x!=SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND&&u.status!=SWFUpload.FILE_STATUS.COMPLETE){a("#"+u.id).find(".data").html(" - "+v)}if(j.settings.onUploadError){j.settings.onUploadError(u,x,w,v,j.queue)}}function g(x,C,z){var v=new Date();var D=v.getTime();var A=D-j.timer;j.timer=D;var y=C-j.bytesLoaded;j.bytesLoaded=C;var u=j.queue.queueBytesUploaded+C;var F=Math.round(C/z*100);var B=0;var w=(y/1024)/(A/1000);w=Math.floor(w*10)/10;if(j.queue.averageSpeed>0){j.queue.averageSpeed=(j.queue.averageSpeed+w)/2}else{j.queue.averageSpeed=w}if(w>1000){B=(w*0.001);j.queue.averageSpeed=B}var E="KB/s";if(B>0){E="MB/s"}if(a.inArray("onUploadProgress",j.settings.skipDefault)<0){if(j.settings.progressData=="percentage"){a("#"+x.id).find(".data").html(" - "+F+"%")}else{if(j.settings.progressData=="speed"){a("#"+x.id).find(".data").html(" - "+F+E)}}a("#"+x.id).find(".uploadifyProgressBar").css("width",F+"%")}if(j.settings.onUploadProgress){j.settings.onUploadProgress(x,C,z,u,j.queue.uploadSize)}}function h(u){var v=new Date();j.timer=v.getTime();j.bytesLoaded=0;if(j.queue.uploadQueue.length==0){j.queue.uploadSize=u.size}if(j.settings.checkExisting!==false){a.ajax({type:"POST",async:false,url:j.settings.checkExisting,data:{filename:u.name},success:function(x){if(x==1){var w=confirm('A file with the name "'+u.name+'" already exists on the server.\nWould you like to replace the existing file?');if(!w){j.cancelUpload(u.id);a("#"+u.id).remove();if(j.queue.uploadQueue.length>0&&j.queue.queueLength>0){if(j.queue.uploadQueue[0]=="*"){j.startUpload()}else{j.startUpload(j.queue.uploadQueue.shift())}}}}}})}if(j.settings.onUploadStart){j.settings.onUploadStart(u)}}function n(v,w,u){j.queue.queueBytesUploaded+=v.size;a("#"+v.id).find(".data").html(" - Complete");if(j.settings.onUploadSuccess){j.settings.onUploadSuccess(v,w,u)}}})},uploadifyCancel:function(b){var f=a(this).selector.replace("#","");var d=window["uploadify_"+f];var c=-1;if(arguments[0]){if(arguments[0]=="*"){a("#"+d.settings.queueID).find(".uploadifyQueueItem").each(function(){c++;d.cancelUpload(a(this).attr("id"));a(this).delay(100*c).fadeOut(500,function(){a(this).remove()})});d.queue.queueSize=0}else{for(var e=0;e'; + } + }); + return true; + } + form.data('submit', true); + return false; + }); + form.data('uploadify_init', true); + } + + function on_upload_success(file, data, response) { + delete form.data('pending_uploads')[this.id]; + if (file.targetpath) { + $('#'+this.id).data('path', file.targetpath); + } else { + $('#'+this.id).data('path', data); + } + if ($.isEmptyObject(form.data('pending_uploads')) && form.data('submit')) { + form.submit(); + } + } + + function on_select(file) { + if (!form.data('uploadify_init')) { //hack around + init_form() + } + form.data('pending_uploads')[this.id] = true; + + //determine the target path and update post data if our backend requires + var swfuploadify = window['uploadify_' + this.id]; + if (swfuploadify.settings.determineName) { + jQuery.ajax({ + type : 'POST', + async : false, + dataType: 'json', + url : swfuploadify.settings.determineName, + beforeSend : add_csrf, + data : {filename: file.name, + upload_to: upload_to}, + success : function(data) { + for (key in data) { + swfuploadify.addFileParam(file.id, key, data[key]); + } + file.targetpath = data['targetpath']; + } + }); + } else { + //swfuploadify.addFileParam(file.id, 'targetname', file.name); + } + } + + function on_upload_error(file,errorCode,errorMsg,errorString, queue) { + delete form.data('pending_uploads')[this.id]; + } + + function on_upload_cancel() { + delete form.data('pending_uploads')[this.id]; + } + + options['onUploadSuccess'] = on_upload_success; + options['onSelect'] = on_select; + //options['onUploadStart'] = on_upload_start; + options['onUploadError'] = on_upload_error; + options['onUploadCancel'] = on_upload_cancel; + options['onSWFReady'] = init_form; //this may not work + /* Uploadify Setup */ + options['auto'] = true; + options['multi'] = false; + options['removeCompleted'] = false; + options['uploadLimit'] = 1; + $this.uploadify(options); + } + }); + }); +} + + diff --git a/directupload/templates/admin/includes/fieldset.html b/directupload/templates/admin/includes/fieldset.html new file mode 100644 index 0000000..7a03f5c --- /dev/null +++ b/directupload/templates/admin/includes/fieldset.html @@ -0,0 +1,36 @@ +{% load uploadify_tags %} +
+ {% if fieldset.name %}

{{ fieldset.name }}

{% endif %} + {% if fieldset.description %} +
{{ fieldset.description|safe }}
+ {% endif %} + {% for line in fieldset %} +
+ {% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %} + {% for field in line %} + + {% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.errors }}{% endif %} + {% if field.is_checkbox %} + {{ field.field }}{{ field.label_tag }} + {% else %} + {{ field.label_tag }} + {% if field.is_readonly %} +

{{ field.contents }}

+ {% else %} + {# begin custom uploadify snippet #} + {% if field.field|is_file_field:line.model_admin.model %} + {% render_uploadify_field field.field model=line.model_admin.model %} + {% else %} + {{ field.field }} + {% endif %} + {# end snippet #} + {% endif %} + {% endif %} + {% if field.field.help_text %} +

{{ field.field.help_text|safe }}

+ {% endif %} +
+ {% endfor %} +
+ {% endfor %} + diff --git a/directupload/templates/uploadify/templatetags/head.html b/directupload/templates/uploadify/templatetags/head.html new file mode 100644 index 0000000..9ba8545 --- /dev/null +++ b/directupload/templates/uploadify/templatetags/head.html @@ -0,0 +1,9 @@ + +{{media}} + diff --git a/directupload/templates/uploadify/templatetags/render_uploadify_widget.html b/directupload/templates/uploadify/templatetags/render_uploadify_widget.html new file mode 100644 index 0000000..5d2879c --- /dev/null +++ b/directupload/templates/uploadify/templatetags/render_uploadify_widget.html @@ -0,0 +1 @@ +{{field}} diff --git a/directupload/templatetags/__init__.py b/directupload/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/directupload/templatetags/uploadify_tags.py b/directupload/templatetags/uploadify_tags.py new file mode 100644 index 0000000..ad066c6 --- /dev/null +++ b/directupload/templatetags/uploadify_tags.py @@ -0,0 +1,49 @@ +from django import template +from django.db import models + +import copy + +register = template.Library() + +from classytags.core import Options +from classytags.helpers import InclusionTag +from classytags.arguments import Argument, KeywordArgument + +from directupload.widgets import UploadifyClearableFileInput + +@register.inclusion_tag('uploadify/templatetags/head.html') +def uploadify_head(): + return { + 'media': UploadifyClearableFileInput().media, + } + +class RenderUploadifyField(InclusionTag): + name = 'render_uploadify_field' + template = 'uploadify/templatetags/render_uploadify_widget.html' + options = Options( + Argument('field', resolve=True), + KeywordArgument('model', resolve=True, required=False), + KeywordArgument('model_field', resolve=True, required=False), + ) + + def get_context(self, context, field, model, model_field): + model = model.get('model', None) + model_field = model_field.get('model_field', None) + if not model_field and model: + model_field = model._meta.get_field(field.name) + if not model_field: + pass + widget = UploadifyClearableFileInput(db_field=model_field) + field.field = copy.copy(field.field) #looks weird but field is actually a bound field + field.field.widget = widget + return {'widget': widget, 'field':field} + +register.tag(RenderUploadifyField) + +def is_file_field(field, model): + #field|is_file_field:line.model_admin.model + model_field = model._meta.get_field(field.name) + return isinstance(model_field, models.FileField) + +register.filter('is_file_field', is_file_field) + diff --git a/directupload/urls.py b/directupload/urls.py new file mode 100644 index 0000000..2051fb1 --- /dev/null +++ b/directupload/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls.defaults import patterns, url + +urlpatterns = patterns('directupload.views', + url(r'^uploadify-options/$', 'uploadify_options_view', name='uploadify-options'), + url(r'^upload/$', 'upload_file', name='uploadify-upload-file'), + url(r'^exists/$', 'determine_name', name='uploadify-determine-name'), +) + diff --git a/directupload/views.py b/directupload/views.py new file mode 100644 index 0000000..2f7d509 --- /dev/null +++ b/directupload/views.py @@ -0,0 +1,44 @@ +from django.http import HttpResponse, HttpResponseBadRequest +from django.core.files.storage import default_storage +from django.views.decorators.csrf import csrf_exempt +from django.utils import simplejson as json + +from directupload.backends import get_uploadify_backend + +from urlparse import parse_qsl +import os + +def uploadify_options_view(request): + if not request.POST: + return HttpResponseBadRequest() + uploadify_options = {} + if 'upload_to' in request.POST: + uploadify_options['folder'] = request.POST['upload_to'] + backend = get_uploadify_backend() + data = backend(request=request, + uploadify_options=uploadify_options).get_options_json() + return HttpResponse(data) + +@csrf_exempt +def upload_file(request): + #this is handled by a different session then the user's browser, hence csrf exempt + if not request.POST: + return HttpResponseBadRequest() + from directupload.djangoview import unsign + data = dict(parse_qsl(unsign(request.POST['payload']))) + assert data['request_time'] #TODO respect some expiration + path = request.POST.get('targetpath', os.path.join(data['upload_to'], request.POST['Filename'])) + file_path = default_storage.save(path, request.FILES['Filedata']) #TODO how to tell the storage engine not to rename? + return HttpResponse(file_path) + +def determine_name(request): + if not request.POST: + return HttpResponseBadRequest() + desired_path = os.path.join(request.POST['upload_to'], request.POST['filename']) + path = default_storage.get_available_name(desired_path) + data = {'targetpath':path, + 'targetname':os.path.split(path)[-1],} + backend = get_uploadify_backend() + backend(request=request, uploadify_options={'folder':request.POST['upload_to']}).update_post_params(data) + return HttpResponse(json.dumps(data)) + diff --git a/directupload/widgets.py b/directupload/widgets.py new file mode 100644 index 0000000..78c4150 --- /dev/null +++ b/directupload/widgets.py @@ -0,0 +1,69 @@ +from django.forms.widgets import FileInput, ClearableFileInput +from django.core.files.storage import default_storage +from django.db.models.fields.files import FileField +from django.conf import settings + +class UploadifyInputMixin(object): + db_field = None + + class Media: #this does not work for the admin as django ignores it [WTF] + css = {'all': ('uploadify/uploadify.css',)} + if settings.DEBUG: + js = ('uploadify/jquery.uploadify.js', 'uploadify/widget.js') + else: + js = ('uploadify/jquery.uploadify.min.js', 'uploadify/widget.js') + + def get_file_field(self): + if self.db_field: + return self.db_field + return FileField(upload_to='', storage=default_storage) + + def value_from_datadict(self, data, files, name): + "File widgets take data from FILES, not POST" + if name in data: + file_path = data[name] + file_field = self.get_file_field() + file_obj = file_field.storage.open(file_path) + file_copy = file_field.attr_class(None, file_field, file_path) + file_copy.file = file_obj + file_copy._committed = True + return file_copy + return None + + def prepare_attrs(self, attrs): + attrs = attrs or {} + file_field = self.get_file_field() + attrs['class'] = 'uploadifyinput' + attrs['data-upload-to'] = file_field.upload_to + return attrs + +class UploadifyFileInput(UploadifyInputMixin, FileInput): + def __init__(self, *args, **kwargs): + self.db_field = kwargs.pop('db_field', None) + FileInput.__init__(self, *args, **kwargs) + + def value_from_datadict(self, data, files, name): + file_obj = UploadifyInputMixin.value_from_datadict(self, data, files, name) + if file_obj: + return file_obj + return super(UploadifyFileInput, self).value_from_datadict(data, files, name) + + def render(self, name, value, attrs=None): + attrs = self.prepare_attrs(attrs) + return super(UploadifyFileInput, self).render(name, value, attrs) + +class UploadifyClearableFileInput(UploadifyInputMixin, ClearableFileInput): + def __init__(self, *args, **kwargs): + self.db_field = kwargs.pop('db_field', None) + ClearableFileInput.__init__(self, *args, **kwargs) + + def value_from_datadict(self, data, files, name): + file_obj = UploadifyInputMixin.value_from_datadict(self, data, files, name) + if file_obj: + return file_obj + return super(UploadifyClearableFileInput, self).value_from_datadict(data, files, name) + + def render(self, name, value, attrs=None): + attrs = self.prepare_attrs(attrs) + return super(UploadifyClearableFileInput, self).render(name, value, attrs) + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..819dd3b --- /dev/null +++ b/setup.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +try: + from setuptools import setup, find_packages +except ImportError: + from distutils.core import setup, find_packages + +version = '0.0.1' + +setup(name='django-directupload', + version=version, + description='A Django application that offers direct uploading of files from your forms using Uploadify.', + author='Jason Kraus', + author_email='jasonk@cukerinteractive.com', + url='https://github.com/cuker/django-directupload', + packages=find_packages(exclude=['test_environment']), + include_package_data = True, + classifiers=['Development Status :: 4 - Beta', + 'Environment :: Web Environment', + 'Framework :: Django', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: BSD License', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Utilities'], + ) +