From f7e11bbd1266029f86dbd4a5eef1191fbb19925e Mon Sep 17 00:00:00 2001 From: Wenyuan Wu Date: Thu, 28 Sep 2017 12:29:13 +0800 Subject: [PATCH] init project --- .idea/django-qiniu-fields.iml | 20 + .../inspectionProfiles/profiles_settings.xml | 7 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/workspace.xml | 535 + demo/__init__.py | 0 demo/adminx.py | 42 + demo/apps.py | 5 + demo/migrations/0001_initial.py | 31 + demo/migrations/__init__.py | 0 demo/models.py | 24 + demo/qiniu_utils.py | 47 + demo/views.py | 10 + manage.py | 22 + qiniu_fields/__init__.py | 3 + qiniu_fields/fields.py | 39 + qiniu_fields/forms.py | 14 + .../static/qiniu_fields/plupload/Moxie.swf | Bin 0 -> 29910 bytes .../static/qiniu_fields/plupload/Moxie.xap | Bin 0 -> 63118 bytes .../static/qiniu_fields/plupload/i18n/en.js | 2 + .../qiniu_fields/plupload/i18n/zh_CN.js | 2 + .../static/qiniu_fields/plupload/moxie.js | 11158 ++++++++++++++++ .../static/qiniu_fields/plupload/moxie.min.js | 16 + .../qiniu_fields/plupload/plupload.dev.js | 2347 ++++ .../plupload/plupload.full.min.js | 29 + .../qiniu_fields/plupload/plupload.min.js | 13 + .../static/qiniu_fields/qiniu/loading.gif | Bin 0 -> 913 bytes .../static/qiniu_fields/qiniu/qiniu.js | 1630 +++ .../static/qiniu_fields/qiniu/qiniu.min.js | 3 + .../static/qiniu_fields/qiniu/qiniu.min.map | 1 + qiniu_fields/static/qiniu_fields/qiniu/ui.js | 233 + .../static/qiniu_fields/qiniu/ui.min.js | 2 + qiniu_fields/templates/file.html | 103 + qiniu_fields/templates/file_list.html | 107 + qiniu_fields/widgets.py | 55 + qiniu_fields_demo/__init__.py | 2 + qiniu_fields_demo/settings.py | 141 + qiniu_fields_demo/urls.py | 37 + qiniu_fields_demo/wsgi.py | 16 + requirements.txt | 5 + 41 files changed, 16719 insertions(+) create mode 100644 .idea/django-qiniu-fields.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 demo/__init__.py create mode 100644 demo/adminx.py create mode 100644 demo/apps.py create mode 100644 demo/migrations/0001_initial.py create mode 100644 demo/migrations/__init__.py create mode 100644 demo/models.py create mode 100644 demo/qiniu_utils.py create mode 100644 demo/views.py create mode 100755 manage.py create mode 100644 qiniu_fields/__init__.py create mode 100644 qiniu_fields/fields.py create mode 100644 qiniu_fields/forms.py create mode 100644 qiniu_fields/static/qiniu_fields/plupload/Moxie.swf create mode 100644 qiniu_fields/static/qiniu_fields/plupload/Moxie.xap create mode 100644 qiniu_fields/static/qiniu_fields/plupload/i18n/en.js create mode 100644 qiniu_fields/static/qiniu_fields/plupload/i18n/zh_CN.js create mode 100644 qiniu_fields/static/qiniu_fields/plupload/moxie.js create mode 100644 qiniu_fields/static/qiniu_fields/plupload/moxie.min.js create mode 100644 qiniu_fields/static/qiniu_fields/plupload/plupload.dev.js create mode 100644 qiniu_fields/static/qiniu_fields/plupload/plupload.full.min.js create mode 100644 qiniu_fields/static/qiniu_fields/plupload/plupload.min.js create mode 100644 qiniu_fields/static/qiniu_fields/qiniu/loading.gif create mode 100755 qiniu_fields/static/qiniu_fields/qiniu/qiniu.js create mode 100755 qiniu_fields/static/qiniu_fields/qiniu/qiniu.min.js create mode 100755 qiniu_fields/static/qiniu_fields/qiniu/qiniu.min.map create mode 100644 qiniu_fields/static/qiniu_fields/qiniu/ui.js create mode 100644 qiniu_fields/static/qiniu_fields/qiniu/ui.min.js create mode 100644 qiniu_fields/templates/file.html create mode 100644 qiniu_fields/templates/file_list.html create mode 100644 qiniu_fields/widgets.py create mode 100644 qiniu_fields_demo/__init__.py create mode 100644 qiniu_fields_demo/settings.py create mode 100644 qiniu_fields_demo/urls.py create mode 100644 qiniu_fields_demo/wsgi.py create mode 100644 requirements.txt diff --git a/.idea/django-qiniu-fields.iml b/.idea/django-qiniu-fields.iml new file mode 100644 index 0000000..7823e3b --- /dev/null +++ b/.idea/django-qiniu-fields.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..c23ecac --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..609d0ab --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..920fb38 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..6789543 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,535 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1506571539244 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/__init__.py b/demo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/demo/adminx.py b/demo/adminx.py new file mode 100644 index 0000000..48c2f99 --- /dev/null +++ b/demo/adminx.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +import xadmin +import xadmin.views as xviews +from xadmin.layout import Main, Fieldset, Side + +from .models import Banner + + +class BaseSetting(object): + enable_themes = True + use_bootswatch = True + +xadmin.site.register(xviews.BaseAdminView, BaseSetting) + + +class AdminSettings(object): + global_search_models = [Banner] + site_title = 'QiniuFields' + site_footer = 'QiniuFields Inc. 2017' + menu_style = 'default' # accordion + + def get_site_menu(self): + return ( + {'title': '内容管理', 'menus': ( + {'title': 'Banner', 'icon': 'fa fa-gift', 'url': self.get_model_url(Banner, 'changelist')}, + )}, + ) + +xadmin.site.register(xviews.CommAdminView, AdminSettings) + + +class BannerAdmin(object): + list_display = ('title', 'banner_img', 'created_time') + search_fields = ['title'] + form_layout = ( + Main(Fieldset(u'基本信息', 'title', 'img_url')), + Side(Fieldset(u'其他信息', 'created_time', 'updated_time')) + ) + readonly_fields = ('created_time', 'updated_time') + + +xadmin.site.register(Banner, BannerAdmin) diff --git a/demo/apps.py b/demo/apps.py new file mode 100644 index 0000000..57920c3 --- /dev/null +++ b/demo/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class DemoConfig(AppConfig): + name = 'demo' diff --git a/demo/migrations/0001_initial.py b/demo/migrations/0001_initial.py new file mode 100644 index 0000000..8307914 --- /dev/null +++ b/demo/migrations/0001_initial.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.5 on 2017-09-28 12:23 +from __future__ import unicode_literals + +from django.db import migrations, models +import qiniu_fields.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Banner', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=100, verbose_name='标题')), + ('img_url', qiniu_fields.fields.QiniuFileField(max_length=500, verbose_name='图片')), + ('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ], + options={ + 'verbose_name_plural': 'Banner', + 'verbose_name': 'Banner', + }, + ), + ] diff --git a/demo/migrations/__init__.py b/demo/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/demo/models.py b/demo/models.py new file mode 100644 index 0000000..d1731c0 --- /dev/null +++ b/demo/models.py @@ -0,0 +1,24 @@ +from django.db import models +from django.utils.html import format_html + +from qiniu_fields import QiniuFileField + + +class Banner(models.Model): + title = models.CharField(max_length=100, verbose_name='标题') + img_url = QiniuFileField(prefix='banner', file_type='image', verbose_name='图片') + created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') + updated_time = models.DateTimeField(auto_now=True, verbose_name='更新时间') + + def __str__(self): + return self.title + + def banner_img(self): + return format_html('', self.img_url) + banner_img.short_description = u'图片' + banner_img.allow_tags = True + + class Meta: + app_label = 'demo' + verbose_name = 'Banner' + verbose_name_plural = 'Banner' diff --git a/demo/qiniu_utils.py b/demo/qiniu_utils.py new file mode 100644 index 0000000..caf3caf --- /dev/null +++ b/demo/qiniu_utils.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +import hashlib + +from django.conf import settings + +from qiniu import Auth, BucketManager, put_file, build_batch_delete + + +EXPIRE_TIME = 24 * 3600 # 1 day + +Q = Auth(settings.QINIU_ACCESS_KEY, settings.QINIU_SECRET_KEY) + + +def get_token(): + token = Q.upload_token(settings.QINIU_BUCKET, expires=EXPIRE_TIME) + return token + + +def delete_data(urls, key_prefix=''): + keys = [] + for url in urls: + if not url.endswith('/'): + url += '/' + key = url.split('/')[-2] + if key_prefix: + key = '%s/%s' % (key_prefix, key) + keys.append(key) + + ops = build_batch_delete(settings.QINIU_BUCKET, keys) + b = BucketManager(Q) + ret, info = b.batch(ops) + print(ret, info) + + +def upload_file(file_data, key_prefix=''): + file_ext = file_data.name.split('.')[-1] + file_name = '.'.join([hashlib.md5(file_data.read()).hexdigest(), file_ext]) + if key_prefix and not key_prefix.endswith('/'): + key_prefix += '/' + key = '%s%s' % (key_prefix, file_name) + token = get_token() + + ret, info = put_file(token, key, file_data.temporary_file_path(), check_crc=False) + if not ret or ret.get('key') != key: + print('fail to upload image to qiniu, info: %s' % info) + + return settings.QINIU_DOMAIN + key diff --git a/demo/views.py b/demo/views.py new file mode 100644 index 0000000..8d54976 --- /dev/null +++ b/demo/views.py @@ -0,0 +1,10 @@ +#! -*- coding: utf-8 -*- +from django.contrib.auth.decorators import login_required +from django.http import JsonResponse + +from . import qiniu_utils + + +@login_required +def get_qiniu_token(request): + return JsonResponse({'uptoken': qiniu_utils.get_token()}) diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..d9827d9 --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "qiniu_fields_demo.settings") + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff --git a/qiniu_fields/__init__.py b/qiniu_fields/__init__.py new file mode 100644 index 0000000..07bdb59 --- /dev/null +++ b/qiniu_fields/__init__.py @@ -0,0 +1,3 @@ +from .fields import QiniuFileField, QiniuFileListField + +__all__ = ["QiniuFileField", "QiniuFileListField"] diff --git a/qiniu_fields/fields.py b/qiniu_fields/fields.py new file mode 100644 index 0000000..1b25db7 --- /dev/null +++ b/qiniu_fields/fields.py @@ -0,0 +1,39 @@ +#! -*- coding: utf-8 -*- +from django.db import models + +from .widgets import QiniuFileWidget, QiniuFileListWidget +from .forms import QiniuFileFormField + + +class QiniuFileField(models.URLField): + widget_clz = QiniuFileWidget + form_field_clz = QiniuFileFormField + + def __init__(self, verbose_name=None, name=None, prefix='', file_type='all', **kwargs): + self.prefix = prefix + self.file_type = file_type + kwargs['max_length'] = 500 + super(QiniuFileField, self).__init__(verbose_name, name, **kwargs) + + def formfield(self, **kwargs): + self.form_field_clz.prefix = self.prefix + self.form_field_clz.file_type = self.file_type + kwargs.update({ + 'form_class': self.form_field_clz, + 'widget': self.widget_clz(attrs={'prefix': self.prefix, 'file_type': self.file_type}) + }) + return super(QiniuFileField, self).formfield(**kwargs) + + +class QiniuFileListField(models.TextField): + + def __init__(self, *args, prefix='', file_type='all', **kwargs): + self.prefix = prefix + self.file_type = file_type + super(QiniuFileListField, self).__init__(*args, **kwargs) + + def formfield(self, **kwargs): + kwargs.update({ + 'widget': QiniuFileListWidget(attrs={'prefix': self.prefix, 'file_type': self.file_type}), + }) + return super(QiniuFileListField, self).formfield(**kwargs) diff --git a/qiniu_fields/forms.py b/qiniu_fields/forms.py new file mode 100644 index 0000000..00058db --- /dev/null +++ b/qiniu_fields/forms.py @@ -0,0 +1,14 @@ +#! -*- coding: utf-8 -*- +from django import forms + +from .widgets import QiniuFileWidget, QiniuFileListWidget + + +class QiniuFileFormField(forms.URLField): + prefix = '' + file_type = 'all' + widget = QiniuFileWidget + + def __init__(self, *args, **kwargs): + kwargs["widget"] = QiniuFileWidget(attrs={'prefix': self.prefix, 'file_type': self.file_type}) + super(QiniuFileFormField, self).__init__(*args, **kwargs) diff --git a/qiniu_fields/static/qiniu_fields/plupload/Moxie.swf b/qiniu_fields/static/qiniu_fields/plupload/Moxie.swf new file mode 100644 index 0000000000000000000000000000000000000000..e477cf9326ec212859ed21cc1ba4e19296dc5270 GIT binary patch literal 29910 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 ZF&Cr9`@lK>`p4g%AD9NA{{-b?AHb^|E{^~J literal 0 HcmV?d00001 diff --git a/qiniu_fields/static/qiniu_fields/plupload/Moxie.xap b/qiniu_fields/static/qiniu_fields/plupload/Moxie.xap new file mode 100644 index 0000000000000000000000000000000000000000..fc7fbfe4b24cfbb901d5f05f760b0996493207a5 GIT binary patch literal 63118 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

ohC;)+F&1(P3t&|kXtQOoB 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 Ug!->zP~VIFcmE literal 0 HcmV?d00001 diff --git a/qiniu_fields/static/qiniu_fields/plupload/i18n/en.js b/qiniu_fields/static/qiniu_fields/plupload/i18n/en.js new file mode 100644 index 0000000..6ab3e2e --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/plupload/i18n/en.js @@ -0,0 +1,2 @@ +// English (en) +plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Size","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Add files to the upload queue and click the start button.","Filename":"Filename","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","mb":"mb","kb":"kb","Duplicate file error.":"Duplicate file error.","File size error.":"File size error.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Select files","%s already present in the queue.":"%s already present in the queue.","File: %s":"File: %s","b":"b","Uploaded %d/%d files":"Uploaded %d/%d files","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"File: %s, size: %d, max file size: %d","Drag files here.":"Drag files here.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"}); \ No newline at end of file diff --git a/qiniu_fields/static/qiniu_fields/plupload/i18n/zh_CN.js b/qiniu_fields/static/qiniu_fields/plupload/i18n/zh_CN.js new file mode 100644 index 0000000..f48e0c4 --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/plupload/i18n/zh_CN.js @@ -0,0 +1,2 @@ +// Chinese (China) (zh_CN) +plupload.addI18n({"Stop Upload":"停止上传","Upload URL might be wrong or doesn't exist.":"上传的URL可能是错误的或不存在。","tb":"tb","Size":"大小","Close":"关闭","Init error.":"初始化错误。","Add files to the upload queue and click the start button.":"将文件添加到上传队列,然后点击”开始上传“按钮。","Filename":"文件名","Image format either wrong or not supported.":"图片格式错误或者不支持。","Status":"状态","HTTP Error.":"HTTP 错误。","Start Upload":"开始上传","mb":"mb","kb":"kb","Duplicate file error.":"重复文件错误。","File size error.":"文件大小错误。","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"错误:无效的文件扩展名:","Select files":"选择文件","%s already present in the queue.":"%s 已经在当前队列里。","File: %s":"文件: %s","b":"b","Uploaded %d/%d files":"已上传 %d/%d 个文件","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"每次只接受同时上传 %d 个文件,多余的文件将会被删除。","%d files queued":"%d 个文件加入到队列","File: %s, size: %d, max file size: %d":"文件: %s, 大小: %d, 最大文件大小: %d","Drag files here.":"把文件拖到这里。","Runtime ran out of available memory.":"运行时已消耗所有可用内存。","File count error.":"文件数量错误。","File extension error.":"文件扩展名错误。","Error: File too large:":"错误: 文件太大:","Add Files":"增加文件"}); \ No newline at end of file diff --git a/qiniu_fields/static/qiniu_fields/plupload/moxie.js b/qiniu_fields/static/qiniu_fields/plupload/moxie.js new file mode 100644 index 0000000..c7624ff --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/plupload/moxie.js @@ -0,0 +1,11158 @@ +;var MXI_DEBUG = true; +/** + * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill + * v1.3.4 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2015-07-18 + */ +/** + * Compiled inline version. (Library mode) + */ + +/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */ +/*globals $code */ + +(function(exports, undefined) { + "use strict"; + + var modules = {}; + + function require(ids, callback) { + var module, defs = []; + + for (var i = 0; i < ids.length; ++i) { + module = modules[ids[i]] || resolve(ids[i]); + if (!module) { + throw 'module definition dependecy not found: ' + ids[i]; + } + + defs.push(module); + } + + callback.apply(null, defs); + } + + function define(id, dependencies, definition) { + if (typeof id !== 'string') { + throw 'invalid module definition, module id must be defined and be a string'; + } + + if (dependencies === undefined) { + throw 'invalid module definition, dependencies must be specified'; + } + + if (definition === undefined) { + throw 'invalid module definition, definition function must be specified'; + } + + require(dependencies, function() { + modules[id] = definition.apply(null, arguments); + }); + } + + function defined(id) { + return !!modules[id]; + } + + function resolve(id) { + var target = exports; + var fragments = id.split(/[.\/]/); + + for (var fi = 0; fi < fragments.length; ++fi) { + if (!target[fragments[fi]]) { + return; + } + + target = target[fragments[fi]]; + } + + return target; + } + + function expose(ids) { + for (var i = 0; i < ids.length; i++) { + var target = exports; + var id = ids[i]; + var fragments = id.split(/[.\/]/); + + for (var fi = 0; fi < fragments.length - 1; ++fi) { + if (target[fragments[fi]] === undefined) { + target[fragments[fi]] = {}; + } + + target = target[fragments[fi]]; + } + + target[fragments[fragments.length - 1]] = modules[id]; + } + } + +// Included from: src/javascript/core/utils/Basic.js + +/** + * Basic.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/utils/Basic', [], function() { + /** + Gets the true type of the built-in object (better version of typeof). + @author Angus Croll (http://javascriptweblog.wordpress.com/) + + @method typeOf + @for Utils + @static + @param {Object} o Object to check. + @return {String} Object [[Class]] + */ + var typeOf = function(o) { + var undef; + + if (o === undef) { + return 'undefined'; + } else if (o === null) { + return 'null'; + } else if (o.nodeType) { + return 'node'; + } + + // the snippet below is awesome, however it fails to detect null, undefined and arguments types in IE lte 8 + return ({}).toString.call(o).match(/\s([a-z|A-Z]+)/)[1].toLowerCase(); + }; + + /** + Extends the specified object with another object. + + @method extend + @static + @param {Object} target Object to extend. + @param {Object} [obj]* Multiple objects to extend with. + @return {Object} Same as target, the extended object. + */ + var extend = function(target) { + var undef; + + each(arguments, function(arg, i) { + if (i > 0) { + each(arg, function(value, key) { + if (value !== undef) { + if (typeOf(target[key]) === typeOf(value) && !!~inArray(typeOf(value), ['array', 'object'])) { + extend(target[key], value); + } else { + target[key] = value; + } + } + }); + } + }); + return target; + }; + + /** + Executes the callback function for each item in array/object. If you return false in the + callback it will break the loop. + + @method each + @static + @param {Object} obj Object to iterate. + @param {function} callback Callback function to execute for each item. + */ + var each = function(obj, callback) { + var length, key, i, undef; + + if (obj) { + if (typeOf(obj.length) === 'number') { // it might be Array, FileList or even arguments object + // Loop array items + for (i = 0, length = obj.length; i < length; i++) { + if (callback(obj[i], i) === false) { + return; + } + } + } else if (typeOf(obj) === 'object') { + // Loop object items + for (key in obj) { + if (obj.hasOwnProperty(key)) { + if (callback(obj[key], key) === false) { + return; + } + } + } + } + } + }; + + /** + Checks if object is empty. + + @method isEmptyObj + @static + @param {Object} o Object to check. + @return {Boolean} + */ + var isEmptyObj = function(obj) { + var prop; + + if (!obj || typeOf(obj) !== 'object') { + return true; + } + + for (prop in obj) { + return false; + } + + return true; + }; + + /** + Recieve an array of functions (usually async) to call in sequence, each function + receives a callback as first argument that it should call, when it completes. Finally, + after everything is complete, main callback is called. Passing truthy value to the + callback as a first argument will interrupt the sequence and invoke main callback + immediately. + + @method inSeries + @static + @param {Array} queue Array of functions to call in sequence + @param {Function} cb Main callback that is called in the end, or in case of error + */ + var inSeries = function(queue, cb) { + var i = 0, length = queue.length; + + if (typeOf(cb) !== 'function') { + cb = function() {}; + } + + if (!queue || !queue.length) { + cb(); + } + + function callNext(i) { + if (typeOf(queue[i]) === 'function') { + queue[i](function(error) { + /*jshint expr:true */ + ++i < length && !error ? callNext(i) : cb(error); + }); + } + } + callNext(i); + }; + + + /** + Recieve an array of functions (usually async) to call in parallel, each function + receives a callback as first argument that it should call, when it completes. After + everything is complete, main callback is called. Passing truthy value to the + callback as a first argument will interrupt the process and invoke main callback + immediately. + + @method inParallel + @static + @param {Array} queue Array of functions to call in sequence + @param {Function} cb Main callback that is called in the end, or in case of error + */ + var inParallel = function(queue, cb) { + var count = 0, num = queue.length, cbArgs = new Array(num); + + each(queue, function(fn, i) { + fn(function(error) { + if (error) { + return cb(error); + } + + var args = [].slice.call(arguments); + args.shift(); // strip error - undefined or not + + cbArgs[i] = args; + count++; + + if (count === num) { + cbArgs.unshift(null); + cb.apply(this, cbArgs); + } + }); + }); + }; + + + /** + Find an element in array and return it's index if present, otherwise return -1. + + @method inArray + @static + @param {Mixed} needle Element to find + @param {Array} array + @return {Int} Index of the element, or -1 if not found + */ + var inArray = function(needle, array) { + if (array) { + if (Array.prototype.indexOf) { + return Array.prototype.indexOf.call(array, needle); + } + + for (var i = 0, length = array.length; i < length; i++) { + if (array[i] === needle) { + return i; + } + } + } + return -1; + }; + + + /** + Returns elements of first array if they are not present in second. And false - otherwise. + + @private + @method arrayDiff + @param {Array} needles + @param {Array} array + @return {Array|Boolean} + */ + var arrayDiff = function(needles, array) { + var diff = []; + + if (typeOf(needles) !== 'array') { + needles = [needles]; + } + + if (typeOf(array) !== 'array') { + array = [array]; + } + + for (var i in needles) { + if (inArray(needles[i], array) === -1) { + diff.push(needles[i]); + } + } + return diff.length ? diff : false; + }; + + + /** + Find intersection of two arrays. + + @private + @method arrayIntersect + @param {Array} array1 + @param {Array} array2 + @return {Array} Intersection of two arrays or null if there is none + */ + var arrayIntersect = function(array1, array2) { + var result = []; + each(array1, function(item) { + if (inArray(item, array2) !== -1) { + result.push(item); + } + }); + return result.length ? result : null; + }; + + + /** + Forces anything into an array. + + @method toArray + @static + @param {Object} obj Object with length field. + @return {Array} Array object containing all items. + */ + var toArray = function(obj) { + var i, arr = []; + + for (i = 0; i < obj.length; i++) { + arr[i] = obj[i]; + } + + return arr; + }; + + + /** + Generates an unique ID. The only way a user would be able to get the same ID is if the two persons + at the same exact millisecond manage to get the same 5 random numbers between 0-65535; it also uses + a counter so each ID is guaranteed to be unique for the given page. It is more probable for the earth + to be hit with an asteroid. + + @method guid + @static + @param {String} prefix to prepend (by default 'o' will be prepended). + @method guid + @return {String} Virtually unique id. + */ + var guid = (function() { + var counter = 0; + + return function(prefix) { + var guid = new Date().getTime().toString(32), i; + + for (i = 0; i < 5; i++) { + guid += Math.floor(Math.random() * 65535).toString(32); + } + + return (prefix || 'o_') + guid + (counter++).toString(32); + }; + }()); + + + /** + Trims white spaces around the string + + @method trim + @static + @param {String} str + @return {String} + */ + var trim = function(str) { + if (!str) { + return str; + } + return String.prototype.trim ? String.prototype.trim.call(str) : str.toString().replace(/^\s*/, '').replace(/\s*$/, ''); + }; + + + /** + Parses the specified size string into a byte value. For example 10kb becomes 10240. + + @method parseSizeStr + @static + @param {String/Number} size String to parse or number to just pass through. + @return {Number} Size in bytes. + */ + var parseSizeStr = function(size) { + if (typeof(size) !== 'string') { + return size; + } + + var muls = { + t: 1099511627776, + g: 1073741824, + m: 1048576, + k: 1024 + }, + mul; + + + size = /^([0-9\.]+)([tmgk]?)$/.exec(size.toLowerCase().replace(/[^0-9\.tmkg]/g, '')); + mul = size[2]; + size = +size[1]; + + if (muls.hasOwnProperty(mul)) { + size *= muls[mul]; + } + return Math.floor(size); + }; + + + /** + * Pseudo sprintf implementation - simple way to replace tokens with specified values. + * + * @param {String} str String with tokens + * @return {String} String with replaced tokens + */ + var sprintf = function(str) { + var args = [].slice.call(arguments, 1); + + return str.replace(/%[a-z]/g, function() { + var value = args.shift(); + return typeOf(value) !== 'undefined' ? value : ''; + }); + }; + + + return { + guid: guid, + typeOf: typeOf, + extend: extend, + each: each, + isEmptyObj: isEmptyObj, + inSeries: inSeries, + inParallel: inParallel, + inArray: inArray, + arrayDiff: arrayDiff, + arrayIntersect: arrayIntersect, + toArray: toArray, + trim: trim, + sprintf: sprintf, + parseSizeStr: parseSizeStr + }; +}); + +// Included from: src/javascript/core/utils/Env.js + +/** + * Env.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/core/utils/Env", [ + "moxie/core/utils/Basic" +], function(Basic) { + + /** + * UAParser.js v0.7.7 + * Lightweight JavaScript-based User-Agent string parser + * https://github.com/faisalman/ua-parser-js + * + * Copyright © 2012-2015 Faisal Salman + * Dual licensed under GPLv2 & MIT + */ + var UAParser = (function (undefined) { + + ////////////// + // Constants + ///////////// + + + var EMPTY = '', + UNKNOWN = '?', + FUNC_TYPE = 'function', + UNDEF_TYPE = 'undefined', + OBJ_TYPE = 'object', + MAJOR = 'major', + MODEL = 'model', + NAME = 'name', + TYPE = 'type', + VENDOR = 'vendor', + VERSION = 'version', + ARCHITECTURE= 'architecture', + CONSOLE = 'console', + MOBILE = 'mobile', + TABLET = 'tablet'; + + + /////////// + // Helper + ////////// + + + var util = { + has : function (str1, str2) { + return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; + }, + lowerize : function (str) { + return str.toLowerCase(); + } + }; + + + /////////////// + // Map helper + ////////////// + + + var mapper = { + + rgx : function () { + + // loop through all regexes maps + for (var result, i = 0, j, k, p, q, matches, match, args = arguments; i < args.length; i += 2) { + + var regex = args[i], // even sequence (0,2,4,..) + props = args[i + 1]; // odd sequence (1,3,5,..) + + // construct object barebones + if (typeof(result) === UNDEF_TYPE) { + result = {}; + for (p in props) { + q = props[p]; + if (typeof(q) === OBJ_TYPE) { + result[q[0]] = undefined; + } else { + result[q] = undefined; + } + } + } + + // try matching uastring with regexes + for (j = k = 0; j < regex.length; j++) { + matches = regex[j].exec(this.getUA()); + if (!!matches) { + for (p = 0; p < props.length; p++) { + match = matches[++k]; + q = props[p]; + // check if given property is actually array + if (typeof(q) === OBJ_TYPE && q.length > 0) { + if (q.length == 2) { + if (typeof(q[1]) == FUNC_TYPE) { + // assign modified match + result[q[0]] = q[1].call(this, match); + } else { + // assign given value, ignore regex match + result[q[0]] = q[1]; + } + } else if (q.length == 3) { + // check whether function or regex + if (typeof(q[1]) === FUNC_TYPE && !(q[1].exec && q[1].test)) { + // call function (usually string mapper) + result[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; + } else { + // sanitize match using given regex + result[q[0]] = match ? match.replace(q[1], q[2]) : undefined; + } + } else if (q.length == 4) { + result[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; + } + } else { + result[q] = match ? match : undefined; + } + } + break; + } + } + + if(!!matches) break; // break the loop immediately if match found + } + return result; + }, + + str : function (str, map) { + + for (var i in map) { + // check if array + if (typeof(map[i]) === OBJ_TYPE && map[i].length > 0) { + for (var j = 0; j < map[i].length; j++) { + if (util.has(map[i][j], str)) { + return (i === UNKNOWN) ? undefined : i; + } + } + } else if (util.has(map[i], str)) { + return (i === UNKNOWN) ? undefined : i; + } + } + return str; + } + }; + + + /////////////// + // String map + ////////////// + + + var maps = { + + browser : { + oldsafari : { + major : { + '1' : ['/8', '/1', '/3'], + '2' : '/4', + '?' : '/' + }, + version : { + '1.0' : '/8', + '1.2' : '/1', + '1.3' : '/3', + '2.0' : '/412', + '2.0.2' : '/416', + '2.0.3' : '/417', + '2.0.4' : '/419', + '?' : '/' + } + } + }, + + device : { + sprint : { + model : { + 'Evo Shift 4G' : '7373KT' + }, + vendor : { + 'HTC' : 'APA', + 'Sprint' : 'Sprint' + } + } + }, + + os : { + windows : { + version : { + 'ME' : '4.90', + 'NT 3.11' : 'NT3.51', + 'NT 4.0' : 'NT4.0', + '2000' : 'NT 5.0', + 'XP' : ['NT 5.1', 'NT 5.2'], + 'Vista' : 'NT 6.0', + '7' : 'NT 6.1', + '8' : 'NT 6.2', + '8.1' : 'NT 6.3', + 'RT' : 'ARM' + } + } + } + }; + + + ////////////// + // Regex map + ///////////// + + + var regexes = { + + browser : [[ + + // Presto based + /(opera\smini)\/([\w\.-]+)/i, // Opera Mini + /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i, // Opera Mobi/Tablet + /(opera).+version\/([\w\.]+)/i, // Opera > 9.80 + /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80 + + ], [NAME, VERSION], [ + + /\s(opr)\/([\w\.]+)/i // Opera Webkit + ], [[NAME, 'Opera'], VERSION], [ + + // Mixed + /(kindle)\/([\w\.]+)/i, // Kindle + /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i, + // Lunascape/Maxthon/Netfront/Jasmine/Blazer + + // Trident based + /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i, + // Avant/IEMobile/SlimBrowser/Baidu + /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer + + // Webkit/KHTML based + /(rekonq)\/([\w\.]+)*/i, // Rekonq + /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi)\/([\w\.-]+)/i + // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron + ], [NAME, VERSION], [ + + /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i // IE11 + ], [[NAME, 'IE'], VERSION], [ + + /(edge)\/((\d+)?[\w\.]+)/i // Microsoft Edge + ], [NAME, VERSION], [ + + /(yabrowser)\/([\w\.]+)/i // Yandex + ], [[NAME, 'Yandex'], VERSION], [ + + /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon + ], [[NAME, /_/g, ' '], VERSION], [ + + /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i, + // Chrome/OmniWeb/Arora/Tizen/Nokia + /(uc\s?browser|qqbrowser)[\/\s]?([\w\.]+)/i + // UCBrowser/QQBrowser + ], [NAME, VERSION], [ + + /(dolfin)\/([\w\.]+)/i // Dolphin + ], [[NAME, 'Dolphin'], VERSION], [ + + /((?:android.+)crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS + ], [[NAME, 'Chrome'], VERSION], [ + + /XiaoMi\/MiuiBrowser\/([\w\.]+)/i // MIUI Browser + ], [VERSION, [NAME, 'MIUI Browser']], [ + + /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)/i // Android Browser + ], [VERSION, [NAME, 'Android Browser']], [ + + /FBAV\/([\w\.]+);/i // Facebook App for iOS + ], [VERSION, [NAME, 'Facebook']], [ + + /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari + ], [VERSION, [NAME, 'Mobile Safari']], [ + + /version\/([\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile + ], [VERSION, NAME], [ + + /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0 + ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [ + + /(konqueror)\/([\w\.]+)/i, // Konqueror + /(webkit|khtml)\/([\w\.]+)/i + ], [NAME, VERSION], [ + + // Gecko based + /(navigator|netscape)\/([\w\.-]+)/i // Netscape + ], [[NAME, 'Netscape'], VERSION], [ + /(swiftfox)/i, // Swiftfox + /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i, + // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror + /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i, + // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix + /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla + + // Other + /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf)[\/\s]?([\w\.]+)/i, + // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf + /(links)\s\(([\w\.]+)/i, // Links + /(gobrowser)\/?([\w\.]+)*/i, // GoBrowser + /(ice\s?browser)\/v?([\w\._]+)/i, // ICE Browser + /(mosaic)[\/\s]([\w\.]+)/i // Mosaic + ], [NAME, VERSION] + ], + + engine : [[ + + /windows.+\sedge\/([\w\.]+)/i // EdgeHTML + ], [VERSION, [NAME, 'EdgeHTML']], [ + + /(presto)\/([\w\.]+)/i, // Presto + /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m + /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links + /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab + ], [NAME, VERSION], [ + + /rv\:([\w\.]+).*(gecko)/i // Gecko + ], [VERSION, NAME] + ], + + os : [[ + + // Windows based + /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes) + ], [NAME, VERSION], [ + /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT + /(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i + ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [ + /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i + ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ + + // Mobile/Embedded OS + /\((bb)(10);/i // BlackBerry 10 + ], [[NAME, 'BlackBerry'], VERSION], [ + /(blackberry)\w*\/?([\w\.]+)*/i, // Blackberry + /(tizen)[\/\s]([\w\.]+)/i, // Tizen + /(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i, + // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki + /linux;.+(sailfish);/i // Sailfish OS + ], [NAME, VERSION], [ + /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i // Symbian + ], [[NAME, 'Symbian'], VERSION], [ + /\((series40);/i // Series 40 + ], [NAME], [ + /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS + ], [[NAME, 'Firefox OS'], VERSION], [ + + // Console + /(nintendo|playstation)\s([wids3portablevu]+)/i, // Nintendo/Playstation + + // GNU/Linux based + /(mint)[\/\s\(]?(\w+)*/i, // Mint + /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux + /(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?([\w\.-]+)*/i, + // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware + // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus + /(hurd|linux)\s?([\w\.]+)*/i, // Hurd/Linux + /(gnu)\s?([\w\.]+)*/i // GNU + ], [NAME, VERSION], [ + + /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS + ], [[NAME, 'Chromium OS'], VERSION],[ + + // Solaris + /(sunos)\s?([\w\.]+\d)*/i // Solaris + ], [[NAME, 'Solaris'], VERSION], [ + + // BSD based + /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly + ], [NAME, VERSION],[ + + /(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i // iOS + ], [[NAME, 'iOS'], [VERSION, /_/g, '.']], [ + + /(mac\sos\sx)\s?([\w\s\.]+\w)*/i, + /(macintosh|mac(?=_powerpc)\s)/i // Mac OS + ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [ + + // Other + /((?:open)?solaris)[\/\s-]?([\w\.]+)*/i, // Solaris + /(haiku)\s(\w+)/i, // Haiku + /(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i, // AIX + /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i, + // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS + /(unix)\s?([\w\.]+)*/i // UNIX + ], [NAME, VERSION] + ] + }; + + + ///////////////// + // Constructor + //////////////// + + + var UAParser = function (uastring) { + + var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); + + this.getBrowser = function () { + return mapper.rgx.apply(this, regexes.browser); + }; + this.getEngine = function () { + return mapper.rgx.apply(this, regexes.engine); + }; + this.getOS = function () { + return mapper.rgx.apply(this, regexes.os); + }; + this.getResult = function() { + return { + ua : this.getUA(), + browser : this.getBrowser(), + engine : this.getEngine(), + os : this.getOS() + }; + }; + this.getUA = function () { + return ua; + }; + this.setUA = function (uastring) { + ua = uastring; + return this; + }; + this.setUA(ua); + }; + + return UAParser; + })(); + + + function version_compare(v1, v2, operator) { + // From: http://phpjs.org/functions + // + original by: Philippe Jausions (http://pear.php.net/user/jausions) + // + original by: Aidan Lister (http://aidanlister.com/) + // + reimplemented by: Kankrelune (http://www.webfaktory.info/) + // + improved by: Brett Zamir (http://brett-zamir.me) + // + improved by: Scott Baker + // + improved by: Theriault + // * example 1: version_compare('8.2.5rc', '8.2.5a'); + // * returns 1: 1 + // * example 2: version_compare('8.2.50', '8.2.52', '<'); + // * returns 2: true + // * example 3: version_compare('5.3.0-dev', '5.3.0'); + // * returns 3: -1 + // * example 4: version_compare('4.1.0.52','4.01.0.51'); + // * returns 4: 1 + + // Important: compare must be initialized at 0. + var i = 0, + x = 0, + compare = 0, + // vm maps textual PHP versions to negatives so they're less than 0. + // PHP currently defines these as CASE-SENSITIVE. It is important to + // leave these as negatives so that they can come before numerical versions + // and as if no letters were there to begin with. + // (1alpha is < 1 and < 1.1 but > 1dev1) + // If a non-numerical value can't be mapped to this table, it receives + // -7 as its value. + vm = { + 'dev': -6, + 'alpha': -5, + 'a': -5, + 'beta': -4, + 'b': -4, + 'RC': -3, + 'rc': -3, + '#': -2, + 'p': 1, + 'pl': 1 + }, + // This function will be called to prepare each version argument. + // It replaces every _, -, and + with a dot. + // It surrounds any nonsequence of numbers/dots with dots. + // It replaces sequences of dots with a single dot. + // version_compare('4..0', '4.0') == 0 + // Important: A string of 0 length needs to be converted into a value + // even less than an unexisting value in vm (-7), hence [-8]. + // It's also important to not strip spaces because of this. + // version_compare('', ' ') == 1 + prepVersion = function (v) { + v = ('' + v).replace(/[_\-+]/g, '.'); + v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); + return (!v.length ? [-8] : v.split('.')); + }, + // This converts a version component to a number. + // Empty component becomes 0. + // Non-numerical component becomes a negative number. + // Numerical component becomes itself as an integer. + numVersion = function (v) { + return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); + }; + + v1 = prepVersion(v1); + v2 = prepVersion(v2); + x = Math.max(v1.length, v2.length); + for (i = 0; i < x; i++) { + if (v1[i] == v2[i]) { + continue; + } + v1[i] = numVersion(v1[i]); + v2[i] = numVersion(v2[i]); + if (v1[i] < v2[i]) { + compare = -1; + break; + } else if (v1[i] > v2[i]) { + compare = 1; + break; + } + } + if (!operator) { + return compare; + } + + // Important: operator is CASE-SENSITIVE. + // "No operator" seems to be treated as "<." + // Any other values seem to make the function return null. + switch (operator) { + case '>': + case 'gt': + return (compare > 0); + case '>=': + case 'ge': + return (compare >= 0); + case '<=': + case 'le': + return (compare <= 0); + case '==': + case '=': + case 'eq': + return (compare === 0); + case '<>': + case '!=': + case 'ne': + return (compare !== 0); + case '': + case '<': + case 'lt': + return (compare < 0); + default: + return null; + } + } + + + var can = (function() { + var caps = { + define_property: (function() { + /* // currently too much extra code required, not exactly worth it + try { // as of IE8, getters/setters are supported only on DOM elements + var obj = {}; + if (Object.defineProperty) { + Object.defineProperty(obj, 'prop', { + enumerable: true, + configurable: true + }); + return true; + } + } catch(ex) {} + + if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { + return true; + }*/ + return false; + }()), + + create_canvas: (function() { + // On the S60 and BB Storm, getContext exists, but always returns undefined + // so we actually have to call getContext() to verify + // github.com/Modernizr/Modernizr/issues/issue/97/ + var el = document.createElement('canvas'); + return !!(el.getContext && el.getContext('2d')); + }()), + + return_response_type: function(responseType) { + try { + if (Basic.inArray(responseType, ['', 'text', 'document']) !== -1) { + return true; + } else if (window.XMLHttpRequest) { + var xhr = new XMLHttpRequest(); + xhr.open('get', '/'); // otherwise Gecko throws an exception + if ('responseType' in xhr) { + xhr.responseType = responseType; + // as of 23.0.1271.64, Chrome switched from throwing exception to merely logging it to the console (why? o why?) + if (xhr.responseType !== responseType) { + return false; + } + return true; + } + } + } catch (ex) {} + return false; + }, + + // ideas for this heavily come from Modernizr (http://modernizr.com/) + use_data_uri: (function() { + var du = new Image(); + + du.onload = function() { + caps.use_data_uri = (du.width === 1 && du.height === 1); + }; + + setTimeout(function() { + du.src = "data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="; + }, 1); + return false; + }()), + + use_data_uri_over32kb: function() { // IE8 + return caps.use_data_uri && (Env.browser !== 'IE' || Env.version >= 9); + }, + + use_data_uri_of: function(bytes) { + return (caps.use_data_uri && bytes < 33000 || caps.use_data_uri_over32kb()); + }, + + use_fileinput: function() { + if (navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/)) { + return false; + } + + var el = document.createElement('input'); + el.setAttribute('type', 'file'); + return !el.disabled; + } + }; + + return function(cap) { + var args = [].slice.call(arguments); + args.shift(); // shift of cap + return Basic.typeOf(caps[cap]) === 'function' ? caps[cap].apply(this, args) : !!caps[cap]; + }; + }()); + + + var uaResult = new UAParser().getResult(); + + + var Env = { + can: can, + + uaParser: UAParser, + + browser: uaResult.browser.name, + version: uaResult.browser.version, + os: uaResult.os.name, // everybody intuitively types it in a lowercase for some reason + osVersion: uaResult.os.version, + + verComp: version_compare, + + swf_url: "../flash/Moxie.swf", + xap_url: "../silverlight/Moxie.xap", + global_event_dispatcher: "moxie.core.EventTarget.instance.dispatchEvent" + }; + + // for backward compatibility + // @deprecated Use `Env.os` instead + Env.OS = Env.os; + + if (MXI_DEBUG) { + Env.debug = { + runtime: true, + events: false + }; + + Env.log = function() { + + function logObj(data) { + // TODO: this should recursively print out the object in a pretty way + console.appendChild(document.createTextNode(data + "\n")); + } + + var data = arguments[0]; + + if (Basic.typeOf(data) === 'string') { + data = Basic.sprintf.apply(this, arguments); + } + + if (window && window.console && window.console.log) { + window.console.log(data); + } else if (document) { + var console = document.getElementById('moxie-console'); + if (!console) { + console = document.createElement('pre'); + console.id = 'moxie-console'; + //console.style.display = 'none'; + document.body.appendChild(console); + } + + if (Basic.inArray(Basic.typeOf(data), ['object', 'array']) !== -1) { + logObj(data); + } else { + console.appendChild(document.createTextNode(data + "\n")); + } + } + }; + } + + return Env; +}); + +// Included from: src/javascript/core/I18n.js + +/** + * I18n.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/core/I18n", [ + "moxie/core/utils/Basic" +], function(Basic) { + var i18n = {}; + + return { + /** + * Extends the language pack object with new items. + * + * @param {Object} pack Language pack items to add. + * @return {Object} Extended language pack object. + */ + addI18n: function(pack) { + return Basic.extend(i18n, pack); + }, + + /** + * Translates the specified string by checking for the english string in the language pack lookup. + * + * @param {String} str String to look for. + * @return {String} Translated string or the input string if it wasn't found. + */ + translate: function(str) { + return i18n[str] || str; + }, + + /** + * Shortcut for translate function + * + * @param {String} str String to look for. + * @return {String} Translated string or the input string if it wasn't found. + */ + _: function(str) { + return this.translate(str); + }, + + /** + * Pseudo sprintf implementation - simple way to replace tokens with specified values. + * + * @param {String} str String with tokens + * @return {String} String with replaced tokens + */ + sprintf: function(str) { + var args = [].slice.call(arguments, 1); + + return str.replace(/%[a-z]/g, function() { + var value = args.shift(); + return Basic.typeOf(value) !== 'undefined' ? value : ''; + }); + } + }; +}); + +// Included from: src/javascript/core/utils/Mime.js + +/** + * Mime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/core/utils/Mime", [ + "moxie/core/utils/Basic", + "moxie/core/I18n" +], function(Basic, I18n) { + + var mimeData = "" + + "application/msword,doc dot," + + "application/pdf,pdf," + + "application/pgp-signature,pgp," + + "application/postscript,ps ai eps," + + "application/rtf,rtf," + + "application/vnd.ms-excel,xls xlb," + + "application/vnd.ms-powerpoint,ppt pps pot," + + "application/zip,zip," + + "application/x-shockwave-flash,swf swfl," + + "application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx," + + "application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx," + + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx," + + "application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx," + + "application/vnd.openxmlformats-officedocument.presentationml.template,potx," + + "application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx," + + "application/x-javascript,js," + + "application/json,json," + + "audio/mpeg,mp3 mpga mpega mp2," + + "audio/x-wav,wav," + + "audio/x-m4a,m4a," + + "audio/ogg,oga ogg," + + "audio/aiff,aiff aif," + + "audio/flac,flac," + + "audio/aac,aac," + + "audio/ac3,ac3," + + "audio/x-ms-wma,wma," + + "image/bmp,bmp," + + "image/gif,gif," + + "image/jpeg,jpg jpeg jpe," + + "image/photoshop,psd," + + "image/png,png," + + "image/svg+xml,svg svgz," + + "image/tiff,tiff tif," + + "text/plain,asc txt text diff log," + + "text/html,htm html xhtml," + + "text/css,css," + + "text/csv,csv," + + "text/rtf,rtf," + + "video/mpeg,mpeg mpg mpe m2v," + + "video/quicktime,qt mov," + + "video/mp4,mp4," + + "video/x-m4v,m4v," + + "video/x-flv,flv," + + "video/x-ms-wmv,wmv," + + "video/avi,avi," + + "video/webm,webm," + + "video/3gpp,3gpp 3gp," + + "video/3gpp2,3g2," + + "video/vnd.rn-realvideo,rv," + + "video/ogg,ogv," + + "video/x-matroska,mkv," + + "application/vnd.oasis.opendocument.formula-template,otf," + + "application/octet-stream,exe"; + + + var Mime = { + + mimes: {}, + + extensions: {}, + + // Parses the default mime types string into a mimes and extensions lookup maps + addMimeType: function (mimeData) { + var items = mimeData.split(/,/), i, ii, ext; + + for (i = 0; i < items.length; i += 2) { + ext = items[i + 1].split(/ /); + + // extension to mime lookup + for (ii = 0; ii < ext.length; ii++) { + this.mimes[ext[ii]] = items[i]; + } + // mime to extension lookup + this.extensions[items[i]] = ext; + } + }, + + + extList2mimes: function (filters, addMissingExtensions) { + var self = this, ext, i, ii, type, mimes = []; + + // convert extensions to mime types list + for (i = 0; i < filters.length; i++) { + ext = filters[i].extensions.split(/\s*,\s*/); + + for (ii = 0; ii < ext.length; ii++) { + + // if there's an asterisk in the list, then accept attribute is not required + if (ext[ii] === '*') { + return []; + } + + type = self.mimes[ext[ii]]; + if (type && Basic.inArray(type, mimes) === -1) { + mimes.push(type); + } + + // future browsers should filter by extension, finally + if (addMissingExtensions && /^\w+$/.test(ext[ii])) { + mimes.push('.' + ext[ii]); + } else if (!type) { + // if we have no type in our map, then accept all + return []; + } + } + } + return mimes; + }, + + + mimes2exts: function(mimes) { + var self = this, exts = []; + + Basic.each(mimes, function(mime) { + if (mime === '*') { + exts = []; + return false; + } + + // check if this thing looks like mime type + var m = mime.match(/^(\w+)\/(\*|\w+)$/); + if (m) { + if (m[2] === '*') { + // wildcard mime type detected + Basic.each(self.extensions, function(arr, mime) { + if ((new RegExp('^' + m[1] + '/')).test(mime)) { + [].push.apply(exts, self.extensions[mime]); + } + }); + } else if (self.extensions[mime]) { + [].push.apply(exts, self.extensions[mime]); + } + } + }); + return exts; + }, + + + mimes2extList: function(mimes) { + var accept = [], exts = []; + + if (Basic.typeOf(mimes) === 'string') { + mimes = Basic.trim(mimes).split(/\s*,\s*/); + } + + exts = this.mimes2exts(mimes); + + accept.push({ + title: I18n.translate('Files'), + extensions: exts.length ? exts.join(',') : '*' + }); + + // save original mimes string + accept.mimes = mimes; + + return accept; + }, + + + getFileExtension: function(fileName) { + var matches = fileName && fileName.match(/\.([^.]+)$/); + if (matches) { + return matches[1].toLowerCase(); + } + return ''; + }, + + getFileMime: function(fileName) { + return this.mimes[this.getFileExtension(fileName)] || ''; + } + }; + + Mime.addMimeType(mimeData); + + return Mime; +}); + +// Included from: src/javascript/core/utils/Dom.js + +/** + * Dom.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/utils/Dom', ['moxie/core/utils/Env'], function(Env) { + + /** + Get DOM Element by it's id. + + @method get + @for Utils + @param {String} id Identifier of the DOM Element + @return {DOMElement} + */ + var get = function(id) { + if (typeof id !== 'string') { + return id; + } + return document.getElementById(id); + }; + + /** + Checks if specified DOM element has specified class. + + @method hasClass + @static + @param {Object} obj DOM element like object to add handler to. + @param {String} name Class name + */ + var hasClass = function(obj, name) { + if (!obj.className) { + return false; + } + + var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)"); + return regExp.test(obj.className); + }; + + /** + Adds specified className to specified DOM element. + + @method addClass + @static + @param {Object} obj DOM element like object to add handler to. + @param {String} name Class name + */ + var addClass = function(obj, name) { + if (!hasClass(obj, name)) { + obj.className = !obj.className ? name : obj.className.replace(/\s+$/, '') + ' ' + name; + } + }; + + /** + Removes specified className from specified DOM element. + + @method removeClass + @static + @param {Object} obj DOM element like object to add handler to. + @param {String} name Class name + */ + var removeClass = function(obj, name) { + if (obj.className) { + var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)"); + obj.className = obj.className.replace(regExp, function($0, $1, $2) { + return $1 === ' ' && $2 === ' ' ? ' ' : ''; + }); + } + }; + + /** + Returns a given computed style of a DOM element. + + @method getStyle + @static + @param {Object} obj DOM element like object. + @param {String} name Style you want to get from the DOM element + */ + var getStyle = function(obj, name) { + if (obj.currentStyle) { + return obj.currentStyle[name]; + } else if (window.getComputedStyle) { + return window.getComputedStyle(obj, null)[name]; + } + }; + + + /** + Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields. + + @method getPos + @static + @param {Element} node HTML element or element id to get x, y position from. + @param {Element} root Optional root element to stop calculations at. + @return {object} Absolute position of the specified element object with x, y fields. + */ + var getPos = function(node, root) { + var x = 0, y = 0, parent, doc = document, nodeRect, rootRect; + + node = node; + root = root || doc.body; + + // Returns the x, y cordinate for an element on IE 6 and IE 7 + function getIEPos(node) { + var bodyElm, rect, x = 0, y = 0; + + if (node) { + rect = node.getBoundingClientRect(); + bodyElm = doc.compatMode === "CSS1Compat" ? doc.documentElement : doc.body; + x = rect.left + bodyElm.scrollLeft; + y = rect.top + bodyElm.scrollTop; + } + + return { + x : x, + y : y + }; + } + + // Use getBoundingClientRect on IE 6 and IE 7 but not on IE 8 in standards mode + if (node && node.getBoundingClientRect && Env.browser === 'IE' && (!doc.documentMode || doc.documentMode < 8)) { + nodeRect = getIEPos(node); + rootRect = getIEPos(root); + + return { + x : nodeRect.x - rootRect.x, + y : nodeRect.y - rootRect.y + }; + } + + parent = node; + while (parent && parent != root && parent.nodeType) { + x += parent.offsetLeft || 0; + y += parent.offsetTop || 0; + parent = parent.offsetParent; + } + + parent = node.parentNode; + while (parent && parent != root && parent.nodeType) { + x -= parent.scrollLeft || 0; + y -= parent.scrollTop || 0; + parent = parent.parentNode; + } + + return { + x : x, + y : y + }; + }; + + /** + Returns the size of the specified node in pixels. + + @method getSize + @static + @param {Node} node Node to get the size of. + @return {Object} Object with a w and h property. + */ + var getSize = function(node) { + return { + w : node.offsetWidth || node.clientWidth, + h : node.offsetHeight || node.clientHeight + }; + }; + + return { + get: get, + hasClass: hasClass, + addClass: addClass, + removeClass: removeClass, + getStyle: getStyle, + getPos: getPos, + getSize: getSize + }; +}); + +// Included from: src/javascript/core/Exceptions.js + +/** + * Exceptions.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/Exceptions', [ + 'moxie/core/utils/Basic' +], function(Basic) { + function _findKey(obj, value) { + var key; + for (key in obj) { + if (obj[key] === value) { + return key; + } + } + return null; + } + + return { + RuntimeError: (function() { + var namecodes = { + NOT_INIT_ERR: 1, + NOT_SUPPORTED_ERR: 9, + JS_ERR: 4 + }; + + function RuntimeError(code) { + this.code = code; + this.name = _findKey(namecodes, code); + this.message = this.name + ": RuntimeError " + this.code; + } + + Basic.extend(RuntimeError, namecodes); + RuntimeError.prototype = Error.prototype; + return RuntimeError; + }()), + + OperationNotAllowedException: (function() { + + function OperationNotAllowedException(code) { + this.code = code; + this.name = 'OperationNotAllowedException'; + } + + Basic.extend(OperationNotAllowedException, { + NOT_ALLOWED_ERR: 1 + }); + + OperationNotAllowedException.prototype = Error.prototype; + + return OperationNotAllowedException; + }()), + + ImageError: (function() { + var namecodes = { + WRONG_FORMAT: 1, + MAX_RESOLUTION_ERR: 2, + INVALID_META_ERR: 3 + }; + + function ImageError(code) { + this.code = code; + this.name = _findKey(namecodes, code); + this.message = this.name + ": ImageError " + this.code; + } + + Basic.extend(ImageError, namecodes); + ImageError.prototype = Error.prototype; + + return ImageError; + }()), + + FileException: (function() { + var namecodes = { + NOT_FOUND_ERR: 1, + SECURITY_ERR: 2, + ABORT_ERR: 3, + NOT_READABLE_ERR: 4, + ENCODING_ERR: 5, + NO_MODIFICATION_ALLOWED_ERR: 6, + INVALID_STATE_ERR: 7, + SYNTAX_ERR: 8 + }; + + function FileException(code) { + this.code = code; + this.name = _findKey(namecodes, code); + this.message = this.name + ": FileException " + this.code; + } + + Basic.extend(FileException, namecodes); + FileException.prototype = Error.prototype; + return FileException; + }()), + + DOMException: (function() { + var namecodes = { + INDEX_SIZE_ERR: 1, + DOMSTRING_SIZE_ERR: 2, + HIERARCHY_REQUEST_ERR: 3, + WRONG_DOCUMENT_ERR: 4, + INVALID_CHARACTER_ERR: 5, + NO_DATA_ALLOWED_ERR: 6, + NO_MODIFICATION_ALLOWED_ERR: 7, + NOT_FOUND_ERR: 8, + NOT_SUPPORTED_ERR: 9, + INUSE_ATTRIBUTE_ERR: 10, + INVALID_STATE_ERR: 11, + SYNTAX_ERR: 12, + INVALID_MODIFICATION_ERR: 13, + NAMESPACE_ERR: 14, + INVALID_ACCESS_ERR: 15, + VALIDATION_ERR: 16, + TYPE_MISMATCH_ERR: 17, + SECURITY_ERR: 18, + NETWORK_ERR: 19, + ABORT_ERR: 20, + URL_MISMATCH_ERR: 21, + QUOTA_EXCEEDED_ERR: 22, + TIMEOUT_ERR: 23, + INVALID_NODE_TYPE_ERR: 24, + DATA_CLONE_ERR: 25 + }; + + function DOMException(code) { + this.code = code; + this.name = _findKey(namecodes, code); + this.message = this.name + ": DOMException " + this.code; + } + + Basic.extend(DOMException, namecodes); + DOMException.prototype = Error.prototype; + return DOMException; + }()), + + EventException: (function() { + function EventException(code) { + this.code = code; + this.name = 'EventException'; + } + + Basic.extend(EventException, { + UNSPECIFIED_EVENT_TYPE_ERR: 0 + }); + + EventException.prototype = Error.prototype; + + return EventException; + }()) + }; +}); + +// Included from: src/javascript/core/EventTarget.js + +/** + * EventTarget.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/EventTarget', [ + 'moxie/core/utils/Env', + 'moxie/core/Exceptions', + 'moxie/core/utils/Basic' +], function(Env, x, Basic) { + /** + Parent object for all event dispatching components and objects + + @class EventTarget + @constructor EventTarget + */ + function EventTarget() { + // hash of event listeners by object uid + var eventpool = {}; + + Basic.extend(this, { + + /** + Unique id of the event dispatcher, usually overriden by children + + @property uid + @type String + */ + uid: null, + + /** + Can be called from within a child in order to acquire uniqie id in automated manner + + @method init + */ + init: function() { + if (!this.uid) { + this.uid = Basic.guid('uid_'); + } + }, + + /** + Register a handler to a specific event dispatched by the object + + @method addEventListener + @param {String} type Type or basically a name of the event to subscribe to + @param {Function} fn Callback function that will be called when event happens + @param {Number} [priority=0] Priority of the event handler - handlers with higher priorities will be called first + @param {Object} [scope=this] A scope to invoke event handler in + */ + addEventListener: function(type, fn, priority, scope) { + var self = this, list; + + // without uid no event handlers can be added, so make sure we got one + if (!this.hasOwnProperty('uid')) { + this.uid = Basic.guid('uid_'); + } + + type = Basic.trim(type); + + if (/\s/.test(type)) { + // multiple event types were passed for one handler + Basic.each(type.split(/\s+/), function(type) { + self.addEventListener(type, fn, priority, scope); + }); + return; + } + + type = type.toLowerCase(); + priority = parseInt(priority, 10) || 0; + + list = eventpool[this.uid] && eventpool[this.uid][type] || []; + list.push({fn : fn, priority : priority, scope : scope || this}); + + if (!eventpool[this.uid]) { + eventpool[this.uid] = {}; + } + eventpool[this.uid][type] = list; + }, + + /** + Check if any handlers were registered to the specified event + + @method hasEventListener + @param {String} type Type or basically a name of the event to check + @return {Mixed} Returns a handler if it was found and false, if - not + */ + hasEventListener: function(type) { + var list = type ? eventpool[this.uid] && eventpool[this.uid][type] : eventpool[this.uid]; + return list ? list : false; + }, + + /** + Unregister the handler from the event, or if former was not specified - unregister all handlers + + @method removeEventListener + @param {String} type Type or basically a name of the event + @param {Function} [fn] Handler to unregister + */ + removeEventListener: function(type, fn) { + type = type.toLowerCase(); + + var list = eventpool[this.uid] && eventpool[this.uid][type], i; + + if (list) { + if (fn) { + for (i = list.length - 1; i >= 0; i--) { + if (list[i].fn === fn) { + list.splice(i, 1); + break; + } + } + } else { + list = []; + } + + // delete event list if it has become empty + if (!list.length) { + delete eventpool[this.uid][type]; + + // and object specific entry in a hash if it has no more listeners attached + if (Basic.isEmptyObj(eventpool[this.uid])) { + delete eventpool[this.uid]; + } + } + } + }, + + /** + Remove all event handlers from the object + + @method removeAllEventListeners + */ + removeAllEventListeners: function() { + if (eventpool[this.uid]) { + delete eventpool[this.uid]; + } + }, + + /** + Dispatch the event + + @method dispatchEvent + @param {String/Object} Type of event or event object to dispatch + @param {Mixed} [...] Variable number of arguments to be passed to a handlers + @return {Boolean} true by default and false if any handler returned false + */ + dispatchEvent: function(type) { + var uid, list, args, tmpEvt, evt = {}, result = true, undef; + + if (Basic.typeOf(type) !== 'string') { + // we can't use original object directly (because of Silverlight) + tmpEvt = type; + + if (Basic.typeOf(tmpEvt.type) === 'string') { + type = tmpEvt.type; + + if (tmpEvt.total !== undef && tmpEvt.loaded !== undef) { // progress event + evt.total = tmpEvt.total; + evt.loaded = tmpEvt.loaded; + } + evt.async = tmpEvt.async || false; + } else { + throw new x.EventException(x.EventException.UNSPECIFIED_EVENT_TYPE_ERR); + } + } + + // check if event is meant to be dispatched on an object having specific uid + if (type.indexOf('::') !== -1) { + (function(arr) { + uid = arr[0]; + type = arr[1]; + }(type.split('::'))); + } else { + uid = this.uid; + } + + type = type.toLowerCase(); + + list = eventpool[uid] && eventpool[uid][type]; + + if (list) { + // sort event list by prority + list.sort(function(a, b) { return b.priority - a.priority; }); + + args = [].slice.call(arguments); + + // first argument will be pseudo-event object + args.shift(); + evt.type = type; + args.unshift(evt); + + if (MXI_DEBUG && Env.debug.events) { + Env.log("Event '%s' fired on %u", evt.type, uid); + } + + // Dispatch event to all listeners + var queue = []; + Basic.each(list, function(handler) { + // explicitly set the target, otherwise events fired from shims do not get it + args[0].target = handler.scope; + // if event is marked as async, detach the handler + if (evt.async) { + queue.push(function(cb) { + setTimeout(function() { + cb(handler.fn.apply(handler.scope, args) === false); + }, 1); + }); + } else { + queue.push(function(cb) { + cb(handler.fn.apply(handler.scope, args) === false); // if handler returns false stop propagation + }); + } + }); + if (queue.length) { + Basic.inSeries(queue, function(err) { + result = !err; + }); + } + } + return result; + }, + + /** + Alias for addEventListener + + @method bind + @protected + */ + bind: function() { + this.addEventListener.apply(this, arguments); + }, + + /** + Alias for removeEventListener + + @method unbind + @protected + */ + unbind: function() { + this.removeEventListener.apply(this, arguments); + }, + + /** + Alias for removeAllEventListeners + + @method unbindAll + @protected + */ + unbindAll: function() { + this.removeAllEventListeners.apply(this, arguments); + }, + + /** + Alias for dispatchEvent + + @method trigger + @protected + */ + trigger: function() { + return this.dispatchEvent.apply(this, arguments); + }, + + + /** + Handle properties of on[event] type. + + @method handleEventProps + @private + */ + handleEventProps: function(dispatches) { + var self = this; + + this.bind(dispatches.join(' '), function(e) { + var prop = 'on' + e.type.toLowerCase(); + if (Basic.typeOf(this[prop]) === 'function') { + this[prop].apply(this, arguments); + } + }); + + // object must have defined event properties, even if it doesn't make use of them + Basic.each(dispatches, function(prop) { + prop = 'on' + prop.toLowerCase(prop); + if (Basic.typeOf(self[prop]) === 'undefined') { + self[prop] = null; + } + }); + } + + }); + } + + EventTarget.instance = new EventTarget(); + + return EventTarget; +}); + +// Included from: src/javascript/runtime/Runtime.js + +/** + * Runtime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/runtime/Runtime', [ + "moxie/core/utils/Env", + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/EventTarget" +], function(Env, Basic, Dom, EventTarget) { + var runtimeConstructors = {}, runtimes = {}; + + /** + Common set of methods and properties for every runtime instance + + @class Runtime + + @param {Object} options + @param {String} type Sanitized name of the runtime + @param {Object} [caps] Set of capabilities that differentiate specified runtime + @param {Object} [modeCaps] Set of capabilities that do require specific operational mode + @param {String} [preferredMode='browser'] Preferred operational mode to choose if no required capabilities were requested + */ + function Runtime(options, type, caps, modeCaps, preferredMode) { + /** + Dispatched when runtime is initialized and ready. + Results in RuntimeInit on a connected component. + + @event Init + */ + + /** + Dispatched when runtime fails to initialize. + Results in RuntimeError on a connected component. + + @event Error + */ + + var self = this + , _shim + , _uid = Basic.guid(type + '_') + , defaultMode = preferredMode || 'browser' + ; + + options = options || {}; + + // register runtime in private hash + runtimes[_uid] = this; + + /** + Default set of capabilities, which can be redifined later by specific runtime + + @private + @property caps + @type Object + */ + caps = Basic.extend({ + // Runtime can: + // provide access to raw binary data of the file + access_binary: false, + // provide access to raw binary data of the image (image extension is optional) + access_image_binary: false, + // display binary data as thumbs for example + display_media: false, + // make cross-domain requests + do_cors: false, + // accept files dragged and dropped from the desktop + drag_and_drop: false, + // filter files in selection dialog by their extensions + filter_by_extension: true, + // resize image (and manipulate it raw data of any file in general) + resize_image: false, + // periodically report how many bytes of total in the file were uploaded (loaded) + report_upload_progress: false, + // provide access to the headers of http response + return_response_headers: false, + // support response of specific type, which should be passed as an argument + // e.g. runtime.can('return_response_type', 'blob') + return_response_type: false, + // return http status code of the response + return_status_code: true, + // send custom http header with the request + send_custom_headers: false, + // pick up the files from a dialog + select_file: false, + // select whole folder in file browse dialog + select_folder: false, + // select multiple files at once in file browse dialog + select_multiple: true, + // send raw binary data, that is generated after image resizing or manipulation of other kind + send_binary_string: false, + // send cookies with http request and therefore retain session + send_browser_cookies: true, + // send data formatted as multipart/form-data + send_multipart: true, + // slice the file or blob to smaller parts + slice_blob: false, + // upload file without preloading it to memory, stream it out directly from disk + stream_upload: false, + // programmatically trigger file browse dialog + summon_file_dialog: false, + // upload file of specific size, size should be passed as argument + // e.g. runtime.can('upload_filesize', '500mb') + upload_filesize: true, + // initiate http request with specific http method, method should be passed as argument + // e.g. runtime.can('use_http_method', 'put') + use_http_method: true + }, caps); + + + // default to the mode that is compatible with preferred caps + if (options.preferred_caps) { + defaultMode = Runtime.getMode(modeCaps, options.preferred_caps, defaultMode); + } + + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("\tdefault mode: %s", defaultMode); + } + + // small extension factory here (is meant to be extended with actual extensions constructors) + _shim = (function() { + var objpool = {}; + return { + exec: function(uid, comp, fn, args) { + if (_shim[comp]) { + if (!objpool[uid]) { + objpool[uid] = { + context: this, + instance: new _shim[comp]() + }; + } + if (objpool[uid].instance[fn]) { + return objpool[uid].instance[fn].apply(this, args); + } + } + }, + + removeInstance: function(uid) { + delete objpool[uid]; + }, + + removeAllInstances: function() { + var self = this; + Basic.each(objpool, function(obj, uid) { + if (Basic.typeOf(obj.instance.destroy) === 'function') { + obj.instance.destroy.call(obj.context); + } + self.removeInstance(uid); + }); + } + }; + }()); + + + // public methods + Basic.extend(this, { + /** + Specifies whether runtime instance was initialized or not + + @property initialized + @type {Boolean} + @default false + */ + initialized: false, // shims require this flag to stop initialization retries + + /** + Unique ID of the runtime + + @property uid + @type {String} + */ + uid: _uid, + + /** + Runtime type (e.g. flash, html5, etc) + + @property type + @type {String} + */ + type: type, + + /** + Runtime (not native one) may operate in browser or client mode. + + @property mode + @private + @type {String|Boolean} current mode or false, if none possible + */ + mode: Runtime.getMode(modeCaps, (options.required_caps), defaultMode), + + /** + id of the DOM container for the runtime (if available) + + @property shimid + @type {String} + */ + shimid: _uid + '_container', + + /** + Number of connected clients. If equal to zero, runtime can be destroyed + + @property clients + @type {Number} + */ + clients: 0, + + /** + Runtime initialization options + + @property options + @type {Object} + */ + options: options, + + /** + Checks if the runtime has specific capability + + @method can + @param {String} cap Name of capability to check + @param {Mixed} [value] If passed, capability should somehow correlate to the value + @param {Object} [refCaps] Set of capabilities to check the specified cap against (defaults to internal set) + @return {Boolean} true if runtime has such capability and false, if - not + */ + can: function(cap, value) { + var refCaps = arguments[2] || caps; + + // if cap var is a comma-separated list of caps, convert it to object (key/value) + if (Basic.typeOf(cap) === 'string' && Basic.typeOf(value) === 'undefined') { + cap = Runtime.parseCaps(cap); + } + + if (Basic.typeOf(cap) === 'object') { + for (var key in cap) { + if (!this.can(key, cap[key], refCaps)) { + return false; + } + } + return true; + } + + // check the individual cap + if (Basic.typeOf(refCaps[cap]) === 'function') { + return refCaps[cap].call(this, value); + } else { + return (value === refCaps[cap]); + } + }, + + /** + Returns container for the runtime as DOM element + + @method getShimContainer + @return {DOMElement} + */ + getShimContainer: function() { + var container, shimContainer = Dom.get(this.shimid); + + // if no container for shim, create one + if (!shimContainer) { + container = this.options.container ? Dom.get(this.options.container) : document.body; + + // create shim container and insert it at an absolute position into the outer container + shimContainer = document.createElement('div'); + shimContainer.id = this.shimid; + shimContainer.className = 'moxie-shim moxie-shim-' + this.type; + + Basic.extend(shimContainer.style, { + position: 'absolute', + top: '0px', + left: '0px', + width: '1px', + height: '1px', + overflow: 'hidden' + }); + + container.appendChild(shimContainer); + container = null; + } + + return shimContainer; + }, + + /** + Returns runtime as DOM element (if appropriate) + + @method getShim + @return {DOMElement} + */ + getShim: function() { + return _shim; + }, + + /** + Invokes a method within the runtime itself (might differ across the runtimes) + + @method shimExec + @param {Mixed} [] + @protected + @return {Mixed} Depends on the action and component + */ + shimExec: function(component, action) { + var args = [].slice.call(arguments, 2); + return self.getShim().exec.call(this, this.uid, component, action, args); + }, + + /** + Operaional interface that is used by components to invoke specific actions on the runtime + (is invoked in the scope of component) + + @method exec + @param {Mixed} []* + @protected + @return {Mixed} Depends on the action and component + */ + exec: function(component, action) { // this is called in the context of component, not runtime + var args = [].slice.call(arguments, 2); + + if (self[component] && self[component][action]) { + return self[component][action].apply(this, args); + } + return self.shimExec.apply(this, arguments); + }, + + /** + Destroys the runtime (removes all events and deletes DOM structures) + + @method destroy + */ + destroy: function() { + if (!self) { + return; // obviously already destroyed + } + + var shimContainer = Dom.get(this.shimid); + if (shimContainer) { + shimContainer.parentNode.removeChild(shimContainer); + } + + if (_shim) { + _shim.removeAllInstances(); + } + + this.unbindAll(); + delete runtimes[this.uid]; + this.uid = null; // mark this runtime as destroyed + _uid = self = _shim = shimContainer = null; + } + }); + + // once we got the mode, test against all caps + if (this.mode && options.required_caps && !this.can(options.required_caps)) { + this.mode = false; + } + } + + + /** + Default order to try different runtime types + + @property order + @type String + @static + */ + Runtime.order = 'html5,flash,silverlight,html4'; + + + /** + Retrieves runtime from private hash by it's uid + + @method getRuntime + @private + @static + @param {String} uid Unique identifier of the runtime + @return {Runtime|Boolean} Returns runtime, if it exists and false, if - not + */ + Runtime.getRuntime = function(uid) { + return runtimes[uid] ? runtimes[uid] : false; + }; + + + /** + Register constructor for the Runtime of new (or perhaps modified) type + + @method addConstructor + @static + @param {String} type Runtime type (e.g. flash, html5, etc) + @param {Function} construct Constructor for the Runtime type + */ + Runtime.addConstructor = function(type, constructor) { + constructor.prototype = EventTarget.instance; + runtimeConstructors[type] = constructor; + }; + + + /** + Get the constructor for the specified type. + + method getConstructor + @static + @param {String} type Runtime type (e.g. flash, html5, etc) + @return {Function} Constructor for the Runtime type + */ + Runtime.getConstructor = function(type) { + return runtimeConstructors[type] || null; + }; + + + /** + Get info about the runtime (uid, type, capabilities) + + @method getInfo + @static + @param {String} uid Unique identifier of the runtime + @return {Mixed} Info object or null if runtime doesn't exist + */ + Runtime.getInfo = function(uid) { + var runtime = Runtime.getRuntime(uid); + + if (runtime) { + return { + uid: runtime.uid, + type: runtime.type, + mode: runtime.mode, + can: function() { + return runtime.can.apply(runtime, arguments); + } + }; + } + return null; + }; + + + /** + Convert caps represented by a comma-separated string to the object representation. + + @method parseCaps + @static + @param {String} capStr Comma-separated list of capabilities + @return {Object} + */ + Runtime.parseCaps = function(capStr) { + var capObj = {}; + + if (Basic.typeOf(capStr) !== 'string') { + return capStr || {}; + } + + Basic.each(capStr.split(','), function(key) { + capObj[key] = true; // we assume it to be - true + }); + + return capObj; + }; + + /** + Test the specified runtime for specific capabilities. + + @method can + @static + @param {String} type Runtime type (e.g. flash, html5, etc) + @param {String|Object} caps Set of capabilities to check + @return {Boolean} Result of the test + */ + Runtime.can = function(type, caps) { + var runtime + , constructor = Runtime.getConstructor(type) + , mode + ; + if (constructor) { + runtime = new constructor({ + required_caps: caps + }); + mode = runtime.mode; + runtime.destroy(); + return !!mode; + } + return false; + }; + + + /** + Figure out a runtime that supports specified capabilities. + + @method thatCan + @static + @param {String|Object} caps Set of capabilities to check + @param {String} [runtimeOrder] Comma-separated list of runtimes to check against + @return {String} Usable runtime identifier or null + */ + Runtime.thatCan = function(caps, runtimeOrder) { + var types = (runtimeOrder || Runtime.order).split(/\s*,\s*/); + for (var i in types) { + if (Runtime.can(types[i], caps)) { + return types[i]; + } + } + return null; + }; + + + /** + Figure out an operational mode for the specified set of capabilities. + + @method getMode + @static + @param {Object} modeCaps Set of capabilities that depend on particular runtime mode + @param {Object} [requiredCaps] Supplied set of capabilities to find operational mode for + @param {String|Boolean} [defaultMode='browser'] Default mode to use + @return {String|Boolean} Compatible operational mode + */ + Runtime.getMode = function(modeCaps, requiredCaps, defaultMode) { + var mode = null; + + if (Basic.typeOf(defaultMode) === 'undefined') { // only if not specified + defaultMode = 'browser'; + } + + if (requiredCaps && !Basic.isEmptyObj(modeCaps)) { + // loop over required caps and check if they do require the same mode + Basic.each(requiredCaps, function(value, cap) { + if (modeCaps.hasOwnProperty(cap)) { + var capMode = modeCaps[cap](value); + + // make sure we always have an array + if (typeof(capMode) === 'string') { + capMode = [capMode]; + } + + if (!mode) { + mode = capMode; + } else if (!(mode = Basic.arrayIntersect(mode, capMode))) { + // if cap requires conflicting mode - runtime cannot fulfill required caps + + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("\t\t%c: %v (conflicting mode requested: %s)", cap, value, capMode); + } + + return (mode = false); + } + } + + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("\t\t%c: %v (compatible modes: %s)", cap, value, mode); + } + }); + + if (mode) { + return Basic.inArray(defaultMode, mode) !== -1 ? defaultMode : mode[0]; + } else if (mode === false) { + return false; + } + } + return defaultMode; + }; + + + /** + Capability check that always returns true + + @private + @static + @return {True} + */ + Runtime.capTrue = function() { + return true; + }; + + /** + Capability check that always returns false + + @private + @static + @return {False} + */ + Runtime.capFalse = function() { + return false; + }; + + /** + Evaluate the expression to boolean value and create a function that always returns it. + + @private + @static + @param {Mixed} expr Expression to evaluate + @return {Function} Function returning the result of evaluation + */ + Runtime.capTest = function(expr) { + return function() { + return !!expr; + }; + }; + + return Runtime; +}); + +// Included from: src/javascript/runtime/RuntimeClient.js + +/** + * RuntimeClient.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/runtime/RuntimeClient', [ + 'moxie/core/utils/Env', + 'moxie/core/Exceptions', + 'moxie/core/utils/Basic', + 'moxie/runtime/Runtime' +], function(Env, x, Basic, Runtime) { + /** + Set of methods and properties, required by a component to acquire ability to connect to a runtime + + @class RuntimeClient + */ + return function RuntimeClient() { + var runtime; + + Basic.extend(this, { + /** + Connects to the runtime specified by the options. Will either connect to existing runtime or create a new one. + Increments number of clients connected to the specified runtime. + + @private + @method connectRuntime + @param {Mixed} options Can be a runtme uid or a set of key-value pairs defining requirements and pre-requisites + */ + connectRuntime: function(options) { + var comp = this, ruid; + + function initialize(items) { + var type, constructor; + + // if we ran out of runtimes + if (!items.length) { + comp.trigger('RuntimeError', new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR)); + runtime = null; + return; + } + + type = items.shift().toLowerCase(); + constructor = Runtime.getConstructor(type); + if (!constructor) { + initialize(items); + return; + } + + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("Trying runtime: %s", type); + Env.log(options); + } + + // try initializing the runtime + runtime = new constructor(options); + + runtime.bind('Init', function() { + // mark runtime as initialized + runtime.initialized = true; + + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("Runtime '%s' initialized", runtime.type); + } + + // jailbreak ... + setTimeout(function() { + runtime.clients++; + // this will be triggered on component + comp.trigger('RuntimeInit', runtime); + }, 1); + }); + + runtime.bind('Error', function() { + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("Runtime '%s' failed to initialize", runtime.type); + } + + runtime.destroy(); // runtime cannot destroy itself from inside at a right moment, thus we do it here + initialize(items); + }); + + /*runtime.bind('Exception', function() { });*/ + + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("\tselected mode: %s", runtime.mode); + } + + // check if runtime managed to pick-up operational mode + if (!runtime.mode) { + runtime.trigger('Error'); + return; + } + + runtime.init(); + } + + // check if a particular runtime was requested + if (Basic.typeOf(options) === 'string') { + ruid = options; + } else if (Basic.typeOf(options.ruid) === 'string') { + ruid = options.ruid; + } + + if (ruid) { + runtime = Runtime.getRuntime(ruid); + if (runtime) { + runtime.clients++; + return runtime; + } else { + // there should be a runtime and there's none - weird case + throw new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR); + } + } + + // initialize a fresh one, that fits runtime list and required features best + initialize((options.runtime_order || Runtime.order).split(/\s*,\s*/)); + }, + + + /** + Disconnects from the runtime. Decrements number of clients connected to the specified runtime. + + @private + @method disconnectRuntime + */ + disconnectRuntime: function() { + if (runtime && --runtime.clients <= 0) { + runtime.destroy(); + } + + // once the component is disconnected, it shouldn't have access to the runtime + runtime = null; + }, + + + /** + Returns the runtime to which the client is currently connected. + + @method getRuntime + @return {Runtime} Runtime or null if client is not connected + */ + getRuntime: function() { + if (runtime && runtime.uid) { + return runtime; + } + return runtime = null; // make sure we do not leave zombies rambling around + }, + + + /** + Handy shortcut to safely invoke runtime extension methods. + + @private + @method exec + @return {Mixed} Whatever runtime extension method returns + */ + exec: function() { + if (runtime) { + return runtime.exec.apply(this, arguments); + } + return null; + } + + }); + }; + + +}); + +// Included from: src/javascript/file/FileInput.js + +/** + * FileInput.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/FileInput', [ + 'moxie/core/utils/Basic', + 'moxie/core/utils/Env', + 'moxie/core/utils/Mime', + 'moxie/core/utils/Dom', + 'moxie/core/Exceptions', + 'moxie/core/EventTarget', + 'moxie/core/I18n', + 'moxie/runtime/Runtime', + 'moxie/runtime/RuntimeClient' +], function(Basic, Env, Mime, Dom, x, EventTarget, I18n, Runtime, RuntimeClient) { + /** + Provides a convenient way to create cross-browser file-picker. Generates file selection dialog on click, + converts selected files to _File_ objects, to be used in conjunction with _Image_, preloaded in memory + with _FileReader_ or uploaded to a server through _XMLHttpRequest_. + + @class FileInput + @constructor + @extends EventTarget + @uses RuntimeClient + @param {Object|String|DOMElement} options If options is string or node, argument is considered as _browse\_button_. + @param {String|DOMElement} options.browse_button DOM Element to turn into file picker. + @param {Array} [options.accept] Array of mime types to accept. By default accepts all. + @param {String} [options.file='file'] Name of the file field (not the filename). + @param {Boolean} [options.multiple=false] Enable selection of multiple files. + @param {Boolean} [options.directory=false] Turn file input into the folder input (cannot be both at the same time). + @param {String|DOMElement} [options.container] DOM Element to use as a container for file-picker. Defaults to parentNode + for _browse\_button_. + @param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support. + + @example +

+ + + */ + var dispatches = [ + /** + Dispatched when runtime is connected and file-picker is ready to be used. + + @event ready + @param {Object} event + */ + 'ready', + + /** + Dispatched right after [ready](#event_ready) event, and whenever [refresh()](#method_refresh) is invoked. + Check [corresponding documentation entry](#method_refresh) for more info. + + @event refresh + @param {Object} event + */ + + /** + Dispatched when selection of files in the dialog is complete. + + @event change + @param {Object} event + */ + 'change', + + 'cancel', // TODO: might be useful + + /** + Dispatched when mouse cursor enters file-picker area. Can be used to style element + accordingly. + + @event mouseenter + @param {Object} event + */ + 'mouseenter', + + /** + Dispatched when mouse cursor leaves file-picker area. Can be used to style element + accordingly. + + @event mouseleave + @param {Object} event + */ + 'mouseleave', + + /** + Dispatched when functional mouse button is pressed on top of file-picker area. + + @event mousedown + @param {Object} event + */ + 'mousedown', + + /** + Dispatched when functional mouse button is released on top of file-picker area. + + @event mouseup + @param {Object} event + */ + 'mouseup' + ]; + + function FileInput(options) { + if (MXI_DEBUG) { + Env.log("Instantiating FileInput..."); + } + + var self = this, + container, browseButton, defaults; + + // if flat argument passed it should be browse_button id + if (Basic.inArray(Basic.typeOf(options), ['string', 'node']) !== -1) { + options = { browse_button : options }; + } + + // this will help us to find proper default container + browseButton = Dom.get(options.browse_button); + if (!browseButton) { + // browse button is required + throw new x.DOMException(x.DOMException.NOT_FOUND_ERR); + } + + // figure out the options + defaults = { + accept: [{ + title: I18n.translate('All Files'), + extensions: '*' + }], + name: 'file', + multiple: false, + required_caps: false, + container: browseButton.parentNode || document.body + }; + + options = Basic.extend({}, defaults, options); + + // convert to object representation + if (typeof(options.required_caps) === 'string') { + options.required_caps = Runtime.parseCaps(options.required_caps); + } + + // normalize accept option (could be list of mime types or array of title/extensions pairs) + if (typeof(options.accept) === 'string') { + options.accept = Mime.mimes2extList(options.accept); + } + + container = Dom.get(options.container); + // make sure we have container + if (!container) { + container = document.body; + } + + // make container relative, if it's not + if (Dom.getStyle(container, 'position') === 'static') { + container.style.position = 'relative'; + } + + container = browseButton = null; // IE + + RuntimeClient.call(self); + + Basic.extend(self, { + /** + Unique id of the component + + @property uid + @protected + @readOnly + @type {String} + @default UID + */ + uid: Basic.guid('uid_'), + + /** + Unique id of the connected runtime, if any. + + @property ruid + @protected + @type {String} + */ + ruid: null, + + /** + Unique id of the runtime container. Useful to get hold of it for various manipulations. + + @property shimid + @protected + @type {String} + */ + shimid: null, + + /** + Array of selected mOxie.File objects + + @property files + @type {Array} + @default null + */ + files: null, + + /** + Initializes the file-picker, connects it to runtime and dispatches event ready when done. + + @method init + */ + init: function() { + self.bind('RuntimeInit', function(e, runtime) { + self.ruid = runtime.uid; + self.shimid = runtime.shimid; + + self.bind("Ready", function() { + self.trigger("Refresh"); + }, 999); + + // re-position and resize shim container + self.bind('Refresh', function() { + var pos, size, browseButton, shimContainer; + + browseButton = Dom.get(options.browse_button); + shimContainer = Dom.get(runtime.shimid); // do not use runtime.getShimContainer(), since it will create container if it doesn't exist + + if (browseButton) { + pos = Dom.getPos(browseButton, Dom.get(options.container)); + size = Dom.getSize(browseButton); + + if (shimContainer) { + Basic.extend(shimContainer.style, { + top : pos.y + 'px', + left : pos.x + 'px', + width : size.w + 'px', + height : size.h + 'px' + }); + } + } + shimContainer = browseButton = null; + }); + + runtime.exec.call(self, 'FileInput', 'init', options); + }); + + // runtime needs: options.required_features, options.runtime_order and options.container + self.connectRuntime(Basic.extend({}, options, { + required_caps: { + select_file: true + } + })); + }, + + /** + Disables file-picker element, so that it doesn't react to mouse clicks. + + @method disable + @param {Boolean} [state=true] Disable component if - true, enable if - false + */ + disable: function(state) { + var runtime = this.getRuntime(); + if (runtime) { + runtime.exec.call(this, 'FileInput', 'disable', Basic.typeOf(state) === 'undefined' ? true : state); + } + }, + + + /** + Reposition and resize dialog trigger to match the position and size of browse_button element. + + @method refresh + */ + refresh: function() { + self.trigger("Refresh"); + }, + + + /** + Destroy component. + + @method destroy + */ + destroy: function() { + var runtime = this.getRuntime(); + if (runtime) { + runtime.exec.call(this, 'FileInput', 'destroy'); + this.disconnectRuntime(); + } + + if (Basic.typeOf(this.files) === 'array') { + // no sense in leaving associated files behind + Basic.each(this.files, function(file) { + file.destroy(); + }); + } + this.files = null; + + this.unbindAll(); + } + }); + + this.handleEventProps(dispatches); + } + + FileInput.prototype = EventTarget.instance; + + return FileInput; +}); + +// Included from: src/javascript/core/utils/Encode.js + +/** + * Encode.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/utils/Encode', [], function() { + + /** + Encode string with UTF-8 + + @method utf8_encode + @for Utils + @static + @param {String} str String to encode + @return {String} UTF-8 encoded string + */ + var utf8_encode = function(str) { + return unescape(encodeURIComponent(str)); + }; + + /** + Decode UTF-8 encoded string + + @method utf8_decode + @static + @param {String} str String to decode + @return {String} Decoded string + */ + var utf8_decode = function(str_data) { + return decodeURIComponent(escape(str_data)); + }; + + /** + Decode Base64 encoded string (uses browser's default method if available), + from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_decode.js + + @method atob + @static + @param {String} data String to decode + @return {String} Decoded string + */ + var atob = function(data, utf8) { + if (typeof(window.atob) === 'function') { + return utf8 ? utf8_decode(window.atob(data)) : window.atob(data); + } + + // http://kevin.vanzonneveld.net + // + original by: Tyler Akins (http://rumkin.com) + // + improved by: Thunder.m + // + input by: Aman Gupta + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + bugfixed by: Onno Marsman + // + bugfixed by: Pellentesque Malesuada + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + input by: Brett Zamir (http://brett-zamir.me) + // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA=='); + // * returns 1: 'Kevin van Zonneveld' + // mozilla has this native + // - but breaks in 2.0.0.12! + //if (typeof this.window.atob == 'function') { + // return atob(data); + //} + var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, + ac = 0, + dec = "", + tmp_arr = []; + + if (!data) { + return data; + } + + data += ''; + + do { // unpack four hexets into three octets using index points in b64 + h1 = b64.indexOf(data.charAt(i++)); + h2 = b64.indexOf(data.charAt(i++)); + h3 = b64.indexOf(data.charAt(i++)); + h4 = b64.indexOf(data.charAt(i++)); + + bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; + + o1 = bits >> 16 & 0xff; + o2 = bits >> 8 & 0xff; + o3 = bits & 0xff; + + if (h3 == 64) { + tmp_arr[ac++] = String.fromCharCode(o1); + } else if (h4 == 64) { + tmp_arr[ac++] = String.fromCharCode(o1, o2); + } else { + tmp_arr[ac++] = String.fromCharCode(o1, o2, o3); + } + } while (i < data.length); + + dec = tmp_arr.join(''); + + return utf8 ? utf8_decode(dec) : dec; + }; + + /** + Base64 encode string (uses browser's default method if available), + from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_encode.js + + @method btoa + @static + @param {String} data String to encode + @return {String} Base64 encoded string + */ + var btoa = function(data, utf8) { + if (utf8) { + data = utf8_encode(data); + } + + if (typeof(window.btoa) === 'function') { + return window.btoa(data); + } + + // http://kevin.vanzonneveld.net + // + original by: Tyler Akins (http://rumkin.com) + // + improved by: Bayron Guevara + // + improved by: Thunder.m + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + bugfixed by: Pellentesque Malesuada + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + improved by: Rafał Kukawski (http://kukawski.pl) + // * example 1: base64_encode('Kevin van Zonneveld'); + // * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' + // mozilla has this native + // - but breaks in 2.0.0.12! + var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, + ac = 0, + enc = "", + tmp_arr = []; + + if (!data) { + return data; + } + + do { // pack three octets into four hexets + o1 = data.charCodeAt(i++); + o2 = data.charCodeAt(i++); + o3 = data.charCodeAt(i++); + + bits = o1 << 16 | o2 << 8 | o3; + + h1 = bits >> 18 & 0x3f; + h2 = bits >> 12 & 0x3f; + h3 = bits >> 6 & 0x3f; + h4 = bits & 0x3f; + + // use hexets to index into b64, and append result to encoded string + tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); + } while (i < data.length); + + enc = tmp_arr.join(''); + + var r = data.length % 3; + + return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3); + }; + + + return { + utf8_encode: utf8_encode, + utf8_decode: utf8_decode, + atob: atob, + btoa: btoa + }; +}); + +// Included from: src/javascript/file/Blob.js + +/** + * Blob.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/Blob', [ + 'moxie/core/utils/Basic', + 'moxie/core/utils/Encode', + 'moxie/runtime/RuntimeClient' +], function(Basic, Encode, RuntimeClient) { + + var blobpool = {}; + + /** + @class Blob + @constructor + @param {String} ruid Unique id of the runtime, to which this blob belongs to + @param {Object} blob Object "Native" blob object, as it is represented in the runtime + */ + function Blob(ruid, blob) { + + function _sliceDetached(start, end, type) { + var blob, data = blobpool[this.uid]; + + if (Basic.typeOf(data) !== 'string' || !data.length) { + return null; // or throw exception + } + + blob = new Blob(null, { + type: type, + size: end - start + }); + blob.detach(data.substr(start, blob.size)); + + return blob; + } + + RuntimeClient.call(this); + + if (ruid) { + this.connectRuntime(ruid); + } + + if (!blob) { + blob = {}; + } else if (Basic.typeOf(blob) === 'string') { // dataUrl or binary string + blob = { data: blob }; + } + + Basic.extend(this, { + + /** + Unique id of the component + + @property uid + @type {String} + */ + uid: blob.uid || Basic.guid('uid_'), + + /** + Unique id of the connected runtime, if falsy, then runtime will have to be initialized + before this Blob can be used, modified or sent + + @property ruid + @type {String} + */ + ruid: ruid, + + /** + Size of blob + + @property size + @type {Number} + @default 0 + */ + size: blob.size || 0, + + /** + Mime type of blob + + @property type + @type {String} + @default '' + */ + type: blob.type || '', + + /** + @method slice + @param {Number} [start=0] + */ + slice: function(start, end, type) { + if (this.isDetached()) { + return _sliceDetached.apply(this, arguments); + } + return this.getRuntime().exec.call(this, 'Blob', 'slice', this.getSource(), start, end, type); + }, + + /** + Returns "native" blob object (as it is represented in connected runtime) or null if not found + + @method getSource + @return {Blob} Returns "native" blob object or null if not found + */ + getSource: function() { + if (!blobpool[this.uid]) { + return null; + } + return blobpool[this.uid]; + }, + + /** + Detaches blob from any runtime that it depends on and initialize with standalone value + + @method detach + @protected + @param {DOMString} [data=''] Standalone value + */ + detach: function(data) { + if (this.ruid) { + this.getRuntime().exec.call(this, 'Blob', 'destroy'); + this.disconnectRuntime(); + this.ruid = null; + } + + data = data || ''; + + // if dataUrl, convert to binary string + if (data.substr(0, 5) == 'data:') { + var base64Offset = data.indexOf(';base64,'); + this.type = data.substring(5, base64Offset); + data = Encode.atob(data.substring(base64Offset + 8)); + } + + this.size = data.length; + + blobpool[this.uid] = data; + }, + + /** + Checks if blob is standalone (detached of any runtime) + + @method isDetached + @protected + @return {Boolean} + */ + isDetached: function() { + return !this.ruid && Basic.typeOf(blobpool[this.uid]) === 'string'; + }, + + /** + Destroy Blob and free any resources it was using + + @method destroy + */ + destroy: function() { + this.detach(); + delete blobpool[this.uid]; + } + }); + + + if (blob.data) { + this.detach(blob.data); // auto-detach if payload has been passed + } else { + blobpool[this.uid] = blob; + } + } + + return Blob; +}); + +// Included from: src/javascript/file/File.js + +/** + * File.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/File', [ + 'moxie/core/utils/Basic', + 'moxie/core/utils/Mime', + 'moxie/file/Blob' +], function(Basic, Mime, Blob) { + /** + @class File + @extends Blob + @constructor + @param {String} ruid Unique id of the runtime, to which this blob belongs to + @param {Object} file Object "Native" file object, as it is represented in the runtime + */ + function File(ruid, file) { + if (!file) { // avoid extra errors in case we overlooked something + file = {}; + } + + Blob.apply(this, arguments); + + if (!this.type) { + this.type = Mime.getFileMime(file.name); + } + + // sanitize file name or generate new one + var name; + if (file.name) { + name = file.name.replace(/\\/g, '/'); + name = name.substr(name.lastIndexOf('/') + 1); + } else if (this.type) { + var prefix = this.type.split('/')[0]; + name = Basic.guid((prefix !== '' ? prefix : 'file') + '_'); + + if (Mime.extensions[this.type]) { + name += '.' + Mime.extensions[this.type][0]; // append proper extension if possible + } + } + + + Basic.extend(this, { + /** + File name + + @property name + @type {String} + @default UID + */ + name: name || Basic.guid('file_'), + + /** + Relative path to the file inside a directory + + @property relativePath + @type {String} + @default '' + */ + relativePath: '', + + /** + Date of last modification + + @property lastModifiedDate + @type {String} + @default now + */ + lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString() // Thu Aug 23 2012 19:40:00 GMT+0400 (GET) + }); + } + + File.prototype = Blob.prototype; + + return File; +}); + +// Included from: src/javascript/file/FileDrop.js + +/** + * FileDrop.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/FileDrop', [ + 'moxie/core/I18n', + 'moxie/core/utils/Dom', + 'moxie/core/Exceptions', + 'moxie/core/utils/Basic', + 'moxie/core/utils/Env', + 'moxie/file/File', + 'moxie/runtime/RuntimeClient', + 'moxie/core/EventTarget', + 'moxie/core/utils/Mime' +], function(I18n, Dom, x, Basic, Env, File, RuntimeClient, EventTarget, Mime) { + /** + Turn arbitrary DOM element to a drop zone accepting files. Converts selected files to _File_ objects, to be used + in conjunction with _Image_, preloaded in memory with _FileReader_ or uploaded to a server through + _XMLHttpRequest_. + + @example +
+ Drop files here +
+
+
+ + + + @class FileDrop + @constructor + @extends EventTarget + @uses RuntimeClient + @param {Object|String} options If options has typeof string, argument is considered as options.drop_zone + @param {String|DOMElement} options.drop_zone DOM Element to turn into a drop zone + @param {Array} [options.accept] Array of mime types to accept. By default accepts all + @param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support + */ + var dispatches = [ + /** + Dispatched when runtime is connected and drop zone is ready to accept files. + + @event ready + @param {Object} event + */ + 'ready', + + /** + Dispatched when dragging cursor enters the drop zone. + + @event dragenter + @param {Object} event + */ + 'dragenter', + + /** + Dispatched when dragging cursor leaves the drop zone. + + @event dragleave + @param {Object} event + */ + 'dragleave', + + /** + Dispatched when file is dropped onto the drop zone. + + @event drop + @param {Object} event + */ + 'drop', + + /** + Dispatched if error occurs. + + @event error + @param {Object} event + */ + 'error' + ]; + + function FileDrop(options) { + if (MXI_DEBUG) { + Env.log("Instantiating FileDrop..."); + } + + var self = this, defaults; + + // if flat argument passed it should be drop_zone id + if (typeof(options) === 'string') { + options = { drop_zone : options }; + } + + // figure out the options + defaults = { + accept: [{ + title: I18n.translate('All Files'), + extensions: '*' + }], + required_caps: { + drag_and_drop: true + } + }; + + options = typeof(options) === 'object' ? Basic.extend({}, defaults, options) : defaults; + + // this will help us to find proper default container + options.container = Dom.get(options.drop_zone) || document.body; + + // make container relative, if it is not + if (Dom.getStyle(options.container, 'position') === 'static') { + options.container.style.position = 'relative'; + } + + // normalize accept option (could be list of mime types or array of title/extensions pairs) + if (typeof(options.accept) === 'string') { + options.accept = Mime.mimes2extList(options.accept); + } + + RuntimeClient.call(self); + + Basic.extend(self, { + uid: Basic.guid('uid_'), + + ruid: null, + + files: null, + + init: function() { + self.bind('RuntimeInit', function(e, runtime) { + self.ruid = runtime.uid; + runtime.exec.call(self, 'FileDrop', 'init', options); + self.dispatchEvent('ready'); + }); + + // runtime needs: options.required_features, options.runtime_order and options.container + self.connectRuntime(options); // throws RuntimeError + }, + + destroy: function() { + var runtime = this.getRuntime(); + if (runtime) { + runtime.exec.call(this, 'FileDrop', 'destroy'); + this.disconnectRuntime(); + } + this.files = null; + + this.unbindAll(); + } + }); + + this.handleEventProps(dispatches); + } + + FileDrop.prototype = EventTarget.instance; + + return FileDrop; +}); + +// Included from: src/javascript/file/FileReader.js + +/** + * FileReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/FileReader', [ + 'moxie/core/utils/Basic', + 'moxie/core/utils/Encode', + 'moxie/core/Exceptions', + 'moxie/core/EventTarget', + 'moxie/file/Blob', + 'moxie/runtime/RuntimeClient' +], function(Basic, Encode, x, EventTarget, Blob, RuntimeClient) { + /** + Utility for preloading o.Blob/o.File objects in memory. By design closely follows [W3C FileReader](http://www.w3.org/TR/FileAPI/#dfn-filereader) + interface. Where possible uses native FileReader, where - not falls back to shims. + + @class FileReader + @constructor FileReader + @extends EventTarget + @uses RuntimeClient + */ + var dispatches = [ + + /** + Dispatched when the read starts. + + @event loadstart + @param {Object} event + */ + 'loadstart', + + /** + Dispatched while reading (and decoding) blob, and reporting partial Blob data (progess.loaded/progress.total). + + @event progress + @param {Object} event + */ + 'progress', + + /** + Dispatched when the read has successfully completed. + + @event load + @param {Object} event + */ + 'load', + + /** + Dispatched when the read has been aborted. For instance, by invoking the abort() method. + + @event abort + @param {Object} event + */ + 'abort', + + /** + Dispatched when the read has failed. + + @event error + @param {Object} event + */ + 'error', + + /** + Dispatched when the request has completed (either in success or failure). + + @event loadend + @param {Object} event + */ + 'loadend' + ]; + + function FileReader() { + + RuntimeClient.call(this); + + Basic.extend(this, { + /** + UID of the component instance. + + @property uid + @type {String} + */ + uid: Basic.guid('uid_'), + + /** + Contains current state of FileReader object. Can take values of FileReader.EMPTY, FileReader.LOADING + and FileReader.DONE. + + @property readyState + @type {Number} + @default FileReader.EMPTY + */ + readyState: FileReader.EMPTY, + + /** + Result of the successful read operation. + + @property result + @type {String} + */ + result: null, + + /** + Stores the error of failed asynchronous read operation. + + @property error + @type {DOMError} + */ + error: null, + + /** + Initiates reading of File/Blob object contents to binary string. + + @method readAsBinaryString + @param {Blob|File} blob Object to preload + */ + readAsBinaryString: function(blob) { + _read.call(this, 'readAsBinaryString', blob); + }, + + /** + Initiates reading of File/Blob object contents to dataURL string. + + @method readAsDataURL + @param {Blob|File} blob Object to preload + */ + readAsDataURL: function(blob) { + _read.call(this, 'readAsDataURL', blob); + }, + + /** + Initiates reading of File/Blob object contents to string. + + @method readAsText + @param {Blob|File} blob Object to preload + */ + readAsText: function(blob) { + _read.call(this, 'readAsText', blob); + }, + + /** + Aborts preloading process. + + @method abort + */ + abort: function() { + this.result = null; + + if (Basic.inArray(this.readyState, [FileReader.EMPTY, FileReader.DONE]) !== -1) { + return; + } else if (this.readyState === FileReader.LOADING) { + this.readyState = FileReader.DONE; + } + + this.exec('FileReader', 'abort'); + + this.trigger('abort'); + this.trigger('loadend'); + }, + + /** + Destroy component and release resources. + + @method destroy + */ + destroy: function() { + this.abort(); + this.exec('FileReader', 'destroy'); + this.disconnectRuntime(); + this.unbindAll(); + } + }); + + // uid must already be assigned + this.handleEventProps(dispatches); + + this.bind('Error', function(e, err) { + this.readyState = FileReader.DONE; + this.error = err; + }, 999); + + this.bind('Load', function(e) { + this.readyState = FileReader.DONE; + }, 999); + + + function _read(op, blob) { + var self = this; + + this.trigger('loadstart'); + + if (this.readyState === FileReader.LOADING) { + this.trigger('error', new x.DOMException(x.DOMException.INVALID_STATE_ERR)); + this.trigger('loadend'); + return; + } + + // if source is not o.Blob/o.File + if (!(blob instanceof Blob)) { + this.trigger('error', new x.DOMException(x.DOMException.NOT_FOUND_ERR)); + this.trigger('loadend'); + return; + } + + this.result = null; + this.readyState = FileReader.LOADING; + + if (blob.isDetached()) { + var src = blob.getSource(); + switch (op) { + case 'readAsText': + case 'readAsBinaryString': + this.result = src; + break; + case 'readAsDataURL': + this.result = 'data:' + blob.type + ';base64,' + Encode.btoa(src); + break; + } + this.readyState = FileReader.DONE; + this.trigger('load'); + this.trigger('loadend'); + } else { + this.connectRuntime(blob.ruid); + this.exec('FileReader', 'read', op, blob); + } + } + } + + /** + Initial FileReader state + + @property EMPTY + @type {Number} + @final + @static + @default 0 + */ + FileReader.EMPTY = 0; + + /** + FileReader switches to this state when it is preloading the source + + @property LOADING + @type {Number} + @final + @static + @default 1 + */ + FileReader.LOADING = 1; + + /** + Preloading is complete, this is a final state + + @property DONE + @type {Number} + @final + @static + @default 2 + */ + FileReader.DONE = 2; + + FileReader.prototype = EventTarget.instance; + + return FileReader; +}); + +// Included from: src/javascript/core/utils/Url.js + +/** + * Url.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/utils/Url', [], function() { + /** + Parse url into separate components and fill in absent parts with parts from current url, + based on https://raw.github.com/kvz/phpjs/master/functions/url/parse_url.js + + @method parseUrl + @for Utils + @static + @param {String} url Url to parse (defaults to empty string if undefined) + @return {Object} Hash containing extracted uri components + */ + var parseUrl = function(url, currentUrl) { + var key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment'] + , i = key.length + , ports = { + http: 80, + https: 443 + } + , uri = {} + , regex = /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/ + , m = regex.exec(url || '') + ; + + while (i--) { + if (m[i]) { + uri[key[i]] = m[i]; + } + } + + // when url is relative, we set the origin and the path ourselves + if (!uri.scheme) { + // come up with defaults + if (!currentUrl || typeof(currentUrl) === 'string') { + currentUrl = parseUrl(currentUrl || document.location.href); + } + + uri.scheme = currentUrl.scheme; + uri.host = currentUrl.host; + uri.port = currentUrl.port; + + var path = ''; + // for urls without trailing slash we need to figure out the path + if (/^[^\/]/.test(uri.path)) { + path = currentUrl.path; + // if path ends with a filename, strip it + if (/\/[^\/]*\.[^\/]*$/.test(path)) { + path = path.replace(/\/[^\/]+$/, '/'); + } else { + // avoid double slash at the end (see #127) + path = path.replace(/\/?$/, '/'); + } + } + uri.path = path + (uri.path || ''); // site may reside at domain.com or domain.com/subdir + } + + if (!uri.port) { + uri.port = ports[uri.scheme] || 80; + } + + uri.port = parseInt(uri.port, 10); + + if (!uri.path) { + uri.path = "/"; + } + + delete uri.source; + + return uri; + }; + + /** + Resolve url - among other things will turn relative url to absolute + + @method resolveUrl + @static + @param {String|Object} url Either absolute or relative, or a result of parseUrl call + @return {String} Resolved, absolute url + */ + var resolveUrl = function(url) { + var ports = { // we ignore default ports + http: 80, + https: 443 + } + , urlp = typeof(url) === 'object' ? url : parseUrl(url); + ; + + return urlp.scheme + '://' + urlp.host + (urlp.port !== ports[urlp.scheme] ? ':' + urlp.port : '') + urlp.path + (urlp.query ? urlp.query : ''); + }; + + /** + Check if specified url has the same origin as the current document + + @method hasSameOrigin + @param {String|Object} url + @return {Boolean} + */ + var hasSameOrigin = function(url) { + function origin(url) { + return [url.scheme, url.host, url.port].join('/'); + } + + if (typeof url === 'string') { + url = parseUrl(url); + } + + return origin(parseUrl()) === origin(url); + }; + + return { + parseUrl: parseUrl, + resolveUrl: resolveUrl, + hasSameOrigin: hasSameOrigin + }; +}); + +// Included from: src/javascript/runtime/RuntimeTarget.js + +/** + * RuntimeTarget.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/runtime/RuntimeTarget', [ + 'moxie/core/utils/Basic', + 'moxie/runtime/RuntimeClient', + "moxie/core/EventTarget" +], function(Basic, RuntimeClient, EventTarget) { + /** + Instance of this class can be used as a target for the events dispatched by shims, + when allowing them onto components is for either reason inappropriate + + @class RuntimeTarget + @constructor + @protected + @extends EventTarget + */ + function RuntimeTarget() { + this.uid = Basic.guid('uid_'); + + RuntimeClient.call(this); + + this.destroy = function() { + this.disconnectRuntime(); + this.unbindAll(); + }; + } + + RuntimeTarget.prototype = EventTarget.instance; + + return RuntimeTarget; +}); + +// Included from: src/javascript/file/FileReaderSync.js + +/** + * FileReaderSync.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/file/FileReaderSync', [ + 'moxie/core/utils/Basic', + 'moxie/runtime/RuntimeClient', + 'moxie/core/utils/Encode' +], function(Basic, RuntimeClient, Encode) { + /** + Synchronous FileReader implementation. Something like this is available in WebWorkers environment, here + it can be used to read only preloaded blobs/files and only below certain size (not yet sure what that'd be, + but probably < 1mb). Not meant to be used directly by user. + + @class FileReaderSync + @private + @constructor + */ + return function() { + RuntimeClient.call(this); + + Basic.extend(this, { + uid: Basic.guid('uid_'), + + readAsBinaryString: function(blob) { + return _read.call(this, 'readAsBinaryString', blob); + }, + + readAsDataURL: function(blob) { + return _read.call(this, 'readAsDataURL', blob); + }, + + /*readAsArrayBuffer: function(blob) { + return _read.call(this, 'readAsArrayBuffer', blob); + },*/ + + readAsText: function(blob) { + return _read.call(this, 'readAsText', blob); + } + }); + + function _read(op, blob) { + if (blob.isDetached()) { + var src = blob.getSource(); + switch (op) { + case 'readAsBinaryString': + return src; + case 'readAsDataURL': + return 'data:' + blob.type + ';base64,' + Encode.btoa(src); + case 'readAsText': + var txt = ''; + for (var i = 0, length = src.length; i < length; i++) { + txt += String.fromCharCode(src[i]); + } + return txt; + } + } else { + var result = this.connectRuntime(blob.ruid).exec.call(this, 'FileReaderSync', 'read', op, blob); + this.disconnectRuntime(); + return result; + } + } + }; +}); + +// Included from: src/javascript/xhr/FormData.js + +/** + * FormData.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/xhr/FormData", [ + "moxie/core/Exceptions", + "moxie/core/utils/Basic", + "moxie/file/Blob" +], function(x, Basic, Blob) { + /** + FormData + + @class FormData + @constructor + */ + function FormData() { + var _blob, _fields = []; + + Basic.extend(this, { + /** + Append another key-value pair to the FormData object + + @method append + @param {String} name Name for the new field + @param {String|Blob|Array|Object} value Value for the field + */ + append: function(name, value) { + var self = this, valueType = Basic.typeOf(value); + + // according to specs value might be either Blob or String + if (value instanceof Blob) { + _blob = { + name: name, + value: value // unfortunately we can only send single Blob in one FormData + }; + } else if ('array' === valueType) { + name += '[]'; + + Basic.each(value, function(value) { + self.append(name, value); + }); + } else if ('object' === valueType) { + Basic.each(value, function(value, key) { + self.append(name + '[' + key + ']', value); + }); + } else if ('null' === valueType || 'undefined' === valueType || 'number' === valueType && isNaN(value)) { + self.append(name, "false"); + } else { + _fields.push({ + name: name, + value: value.toString() + }); + } + }, + + /** + Checks if FormData contains Blob. + + @method hasBlob + @return {Boolean} + */ + hasBlob: function() { + return !!this.getBlob(); + }, + + /** + Retrieves blob. + + @method getBlob + @return {Object} Either Blob if found or null + */ + getBlob: function() { + return _blob && _blob.value || null; + }, + + /** + Retrieves blob field name. + + @method getBlobName + @return {String} Either Blob field name or null + */ + getBlobName: function() { + return _blob && _blob.name || null; + }, + + /** + Loop over the fields in FormData and invoke the callback for each of them. + + @method each + @param {Function} cb Callback to call for each field + */ + each: function(cb) { + Basic.each(_fields, function(field) { + cb(field.value, field.name); + }); + + if (_blob) { + cb(_blob.value, _blob.name); + } + }, + + destroy: function() { + _blob = null; + _fields = []; + } + }); + } + + return FormData; +}); + +// Included from: src/javascript/xhr/XMLHttpRequest.js + +/** + * XMLHttpRequest.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/xhr/XMLHttpRequest", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/core/EventTarget", + "moxie/core/utils/Encode", + "moxie/core/utils/Url", + "moxie/runtime/Runtime", + "moxie/runtime/RuntimeTarget", + "moxie/file/Blob", + "moxie/file/FileReaderSync", + "moxie/xhr/FormData", + "moxie/core/utils/Env", + "moxie/core/utils/Mime" +], function(Basic, x, EventTarget, Encode, Url, Runtime, RuntimeTarget, Blob, FileReaderSync, FormData, Env, Mime) { + + var httpCode = { + 100: 'Continue', + 101: 'Switching Protocols', + 102: 'Processing', + + 200: 'OK', + 201: 'Created', + 202: 'Accepted', + 203: 'Non-Authoritative Information', + 204: 'No Content', + 205: 'Reset Content', + 206: 'Partial Content', + 207: 'Multi-Status', + 226: 'IM Used', + + 300: 'Multiple Choices', + 301: 'Moved Permanently', + 302: 'Found', + 303: 'See Other', + 304: 'Not Modified', + 305: 'Use Proxy', + 306: 'Reserved', + 307: 'Temporary Redirect', + + 400: 'Bad Request', + 401: 'Unauthorized', + 402: 'Payment Required', + 403: 'Forbidden', + 404: 'Not Found', + 405: 'Method Not Allowed', + 406: 'Not Acceptable', + 407: 'Proxy Authentication Required', + 408: 'Request Timeout', + 409: 'Conflict', + 410: 'Gone', + 411: 'Length Required', + 412: 'Precondition Failed', + 413: 'Request Entity Too Large', + 414: 'Request-URI Too Long', + 415: 'Unsupported Media Type', + 416: 'Requested Range Not Satisfiable', + 417: 'Expectation Failed', + 422: 'Unprocessable Entity', + 423: 'Locked', + 424: 'Failed Dependency', + 426: 'Upgrade Required', + + 500: 'Internal Server Error', + 501: 'Not Implemented', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + 504: 'Gateway Timeout', + 505: 'HTTP Version Not Supported', + 506: 'Variant Also Negotiates', + 507: 'Insufficient Storage', + 510: 'Not Extended' + }; + + function XMLHttpRequestUpload() { + this.uid = Basic.guid('uid_'); + } + + XMLHttpRequestUpload.prototype = EventTarget.instance; + + /** + Implementation of XMLHttpRequest + + @class XMLHttpRequest + @constructor + @uses RuntimeClient + @extends EventTarget + */ + var dispatches = [ + 'loadstart', + + 'progress', + + 'abort', + + 'error', + + 'load', + + 'timeout', + + 'loadend' + + // readystatechange (for historical reasons) + ]; + + var NATIVE = 1, RUNTIME = 2; + + function XMLHttpRequest() { + var self = this, + // this (together with _p() @see below) is here to gracefully upgrade to setter/getter syntax where possible + props = { + /** + The amount of milliseconds a request can take before being terminated. Initially zero. Zero means there is no timeout. + + @property timeout + @type Number + @default 0 + */ + timeout: 0, + + /** + Current state, can take following values: + UNSENT (numeric value 0) + The object has been constructed. + + OPENED (numeric value 1) + The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the request can be made using the send() method. + + HEADERS_RECEIVED (numeric value 2) + All redirects (if any) have been followed and all HTTP headers of the final response have been received. Several response members of the object are now available. + + LOADING (numeric value 3) + The response entity body is being received. + + DONE (numeric value 4) + + @property readyState + @type Number + @default 0 (UNSENT) + */ + readyState: XMLHttpRequest.UNSENT, + + /** + True when user credentials are to be included in a cross-origin request. False when they are to be excluded + in a cross-origin request and when cookies are to be ignored in its response. Initially false. + + @property withCredentials + @type Boolean + @default false + */ + withCredentials: false, + + /** + Returns the HTTP status code. + + @property status + @type Number + @default 0 + */ + status: 0, + + /** + Returns the HTTP status text. + + @property statusText + @type String + */ + statusText: "", + + /** + Returns the response type. Can be set to change the response type. Values are: + the empty string (default), "arraybuffer", "blob", "document", "json", and "text". + + @property responseType + @type String + */ + responseType: "", + + /** + Returns the document response entity body. + + Throws an "InvalidStateError" exception if responseType is not the empty string or "document". + + @property responseXML + @type Document + */ + responseXML: null, + + /** + Returns the text response entity body. + + Throws an "InvalidStateError" exception if responseType is not the empty string or "text". + + @property responseText + @type String + */ + responseText: null, + + /** + Returns the response entity body (http://www.w3.org/TR/XMLHttpRequest/#response-entity-body). + Can become: ArrayBuffer, Blob, Document, JSON, Text + + @property response + @type Mixed + */ + response: null + }, + + _async = true, + _url, + _method, + _headers = {}, + _user, + _password, + _encoding = null, + _mimeType = null, + + // flags + _sync_flag = false, + _send_flag = false, + _upload_events_flag = false, + _upload_complete_flag = false, + _error_flag = false, + _same_origin_flag = false, + + // times + _start_time, + _timeoutset_time, + + _finalMime = null, + _finalCharset = null, + + _options = {}, + _xhr, + _responseHeaders = '', + _responseHeadersBag + ; + + + Basic.extend(this, props, { + /** + Unique id of the component + + @property uid + @type String + */ + uid: Basic.guid('uid_'), + + /** + Target for Upload events + + @property upload + @type XMLHttpRequestUpload + */ + upload: new XMLHttpRequestUpload(), + + + /** + Sets the request method, request URL, synchronous flag, request username, and request password. + + Throws a "SyntaxError" exception if one of the following is true: + + method is not a valid HTTP method. + url cannot be resolved. + url contains the "user:password" format in the userinfo production. + Throws a "SecurityError" exception if method is a case-insensitive match for CONNECT, TRACE or TRACK. + + Throws an "InvalidAccessError" exception if one of the following is true: + + Either user or password is passed as argument and the origin of url does not match the XMLHttpRequest origin. + There is an associated XMLHttpRequest document and either the timeout attribute is not zero, + the withCredentials attribute is true, or the responseType attribute is not the empty string. + + + @method open + @param {String} method HTTP method to use on request + @param {String} url URL to request + @param {Boolean} [async=true] If false request will be done in synchronous manner. Asynchronous by default. + @param {String} [user] Username to use in HTTP authentication process on server-side + @param {String} [password] Password to use in HTTP authentication process on server-side + */ + open: function(method, url, async, user, password) { + var urlp; + + // first two arguments are required + if (!method || !url) { + throw new x.DOMException(x.DOMException.SYNTAX_ERR); + } + + // 2 - check if any code point in method is higher than U+00FF or after deflating method it does not match the method + if (/[\u0100-\uffff]/.test(method) || Encode.utf8_encode(method) !== method) { + throw new x.DOMException(x.DOMException.SYNTAX_ERR); + } + + // 3 + if (!!~Basic.inArray(method.toUpperCase(), ['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'TRACE', 'TRACK'])) { + _method = method.toUpperCase(); + } + + + // 4 - allowing these methods poses a security risk + if (!!~Basic.inArray(_method, ['CONNECT', 'TRACE', 'TRACK'])) { + throw new x.DOMException(x.DOMException.SECURITY_ERR); + } + + // 5 + url = Encode.utf8_encode(url); + + // 6 - Resolve url relative to the XMLHttpRequest base URL. If the algorithm returns an error, throw a "SyntaxError". + urlp = Url.parseUrl(url); + + _same_origin_flag = Url.hasSameOrigin(urlp); + + // 7 - manually build up absolute url + _url = Url.resolveUrl(url); + + // 9-10, 12-13 + if ((user || password) && !_same_origin_flag) { + throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); + } + + _user = user || urlp.user; + _password = password || urlp.pass; + + // 11 + _async = async || true; + + if (_async === false && (_p('timeout') || _p('withCredentials') || _p('responseType') !== "")) { + throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); + } + + // 14 - terminate abort() + + // 15 - terminate send() + + // 18 + _sync_flag = !_async; + _send_flag = false; + _headers = {}; + _reset.call(this); + + // 19 + _p('readyState', XMLHttpRequest.OPENED); + + // 20 + this.dispatchEvent('readystatechange'); + }, + + /** + Appends an header to the list of author request headers, or if header is already + in the list of author request headers, combines its value with value. + + Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set. + Throws a "SyntaxError" exception if header is not a valid HTTP header field name or if value + is not a valid HTTP header field value. + + @method setRequestHeader + @param {String} header + @param {String|Number} value + */ + setRequestHeader: function(header, value) { + var uaHeaders = [ // these headers are controlled by the user agent + "accept-charset", + "accept-encoding", + "access-control-request-headers", + "access-control-request-method", + "connection", + "content-length", + "cookie", + "cookie2", + "content-transfer-encoding", + "date", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "user-agent", + "via" + ]; + + // 1-2 + if (_p('readyState') !== XMLHttpRequest.OPENED || _send_flag) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 3 + if (/[\u0100-\uffff]/.test(header) || Encode.utf8_encode(header) !== header) { + throw new x.DOMException(x.DOMException.SYNTAX_ERR); + } + + // 4 + /* this step is seemingly bypassed in browsers, probably to allow various unicode characters in header values + if (/[\u0100-\uffff]/.test(value) || Encode.utf8_encode(value) !== value) { + throw new x.DOMException(x.DOMException.SYNTAX_ERR); + }*/ + + header = Basic.trim(header).toLowerCase(); + + // setting of proxy-* and sec-* headers is prohibited by spec + if (!!~Basic.inArray(header, uaHeaders) || /^(proxy\-|sec\-)/.test(header)) { + return false; + } + + // camelize + // browsers lowercase header names (at least for custom ones) + // header = header.replace(/\b\w/g, function($1) { return $1.toUpperCase(); }); + + if (!_headers[header]) { + _headers[header] = value; + } else { + // http://tools.ietf.org/html/rfc2616#section-4.2 (last paragraph) + _headers[header] += ', ' + value; + } + return true; + }, + + /** + Returns all headers from the response, with the exception of those whose field name is Set-Cookie or Set-Cookie2. + + @method getAllResponseHeaders + @return {String} reponse headers or empty string + */ + getAllResponseHeaders: function() { + return _responseHeaders || ''; + }, + + /** + Returns the header field value from the response of which the field name matches header, + unless the field name is Set-Cookie or Set-Cookie2. + + @method getResponseHeader + @param {String} header + @return {String} value(s) for the specified header or null + */ + getResponseHeader: function(header) { + header = header.toLowerCase(); + + if (_error_flag || !!~Basic.inArray(header, ['set-cookie', 'set-cookie2'])) { + return null; + } + + if (_responseHeaders && _responseHeaders !== '') { + // if we didn't parse response headers until now, do it and keep for later + if (!_responseHeadersBag) { + _responseHeadersBag = {}; + Basic.each(_responseHeaders.split(/\r\n/), function(line) { + var pair = line.split(/:\s+/); + if (pair.length === 2) { // last line might be empty, omit + pair[0] = Basic.trim(pair[0]); // just in case + _responseHeadersBag[pair[0].toLowerCase()] = { // simply to retain header name in original form + header: pair[0], + value: Basic.trim(pair[1]) + }; + } + }); + } + if (_responseHeadersBag.hasOwnProperty(header)) { + return _responseHeadersBag[header].header + ': ' + _responseHeadersBag[header].value; + } + } + return null; + }, + + /** + Sets the Content-Type header for the response to mime. + Throws an "InvalidStateError" exception if the state is LOADING or DONE. + Throws a "SyntaxError" exception if mime is not a valid media type. + + @method overrideMimeType + @param String mime Mime type to set + */ + overrideMimeType: function(mime) { + var matches, charset; + + // 1 + if (!!~Basic.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 2 + mime = Basic.trim(mime.toLowerCase()); + + if (/;/.test(mime) && (matches = mime.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))) { + mime = matches[1]; + if (matches[2]) { + charset = matches[2]; + } + } + + if (!Mime.mimes[mime]) { + throw new x.DOMException(x.DOMException.SYNTAX_ERR); + } + + // 3-4 + _finalMime = mime; + _finalCharset = charset; + }, + + /** + Initiates the request. The optional argument provides the request entity body. + The argument is ignored if request method is GET or HEAD. + + Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set. + + @method send + @param {Blob|Document|String|FormData} [data] Request entity body + @param {Object} [options] Set of requirements and pre-requisities for runtime initialization + */ + send: function(data, options) { + if (Basic.typeOf(options) === 'string') { + _options = { ruid: options }; + } else if (!options) { + _options = {}; + } else { + _options = options; + } + + // 1-2 + if (this.readyState !== XMLHttpRequest.OPENED || _send_flag) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 3 + // sending Blob + if (data instanceof Blob) { + _options.ruid = data.ruid; + _mimeType = data.type || 'application/octet-stream'; + } + + // FormData + else if (data instanceof FormData) { + if (data.hasBlob()) { + var blob = data.getBlob(); + _options.ruid = blob.ruid; + _mimeType = blob.type || 'application/octet-stream'; + } + } + + // DOMString + else if (typeof data === 'string') { + _encoding = 'UTF-8'; + _mimeType = 'text/plain;charset=UTF-8'; + + // data should be converted to Unicode and encoded as UTF-8 + data = Encode.utf8_encode(data); + } + + // if withCredentials not set, but requested, set it automatically + if (!this.withCredentials) { + this.withCredentials = (_options.required_caps && _options.required_caps.send_browser_cookies) && !_same_origin_flag; + } + + // 4 - storage mutex + // 5 + _upload_events_flag = (!_sync_flag && this.upload.hasEventListener()); // DSAP + // 6 + _error_flag = false; + // 7 + _upload_complete_flag = !data; + // 8 - Asynchronous steps + if (!_sync_flag) { + // 8.1 + _send_flag = true; + // 8.2 + // this.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr + // 8.3 + //if (!_upload_complete_flag) { + // this.upload.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr + //} + } + // 8.5 - Return the send() method call, but continue running the steps in this algorithm. + _doXHR.call(this, data); + }, + + /** + Cancels any network activity. + + @method abort + */ + abort: function() { + _error_flag = true; + _sync_flag = false; + + if (!~Basic.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED, XMLHttpRequest.DONE])) { + _p('readyState', XMLHttpRequest.DONE); + _send_flag = false; + + if (_xhr) { + _xhr.getRuntime().exec.call(_xhr, 'XMLHttpRequest', 'abort', _upload_complete_flag); + } else { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + _upload_complete_flag = true; + } else { + _p('readyState', XMLHttpRequest.UNSENT); + } + }, + + destroy: function() { + if (_xhr) { + if (Basic.typeOf(_xhr.destroy) === 'function') { + _xhr.destroy(); + } + _xhr = null; + } + + this.unbindAll(); + + if (this.upload) { + this.upload.unbindAll(); + this.upload = null; + } + } + }); + + this.handleEventProps(dispatches.concat(['readystatechange'])); // for historical reasons + this.upload.handleEventProps(dispatches); + + /* this is nice, but maybe too lengthy + + // if supported by JS version, set getters/setters for specific properties + o.defineProperty(this, 'readyState', { + configurable: false, + + get: function() { + return _p('readyState'); + } + }); + + o.defineProperty(this, 'timeout', { + configurable: false, + + get: function() { + return _p('timeout'); + }, + + set: function(value) { + + if (_sync_flag) { + throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); + } + + // timeout still should be measured relative to the start time of request + _timeoutset_time = (new Date).getTime(); + + _p('timeout', value); + } + }); + + // the withCredentials attribute has no effect when fetching same-origin resources + o.defineProperty(this, 'withCredentials', { + configurable: false, + + get: function() { + return _p('withCredentials'); + }, + + set: function(value) { + // 1-2 + if (!~o.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED]) || _send_flag) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 3-4 + if (_anonymous_flag || _sync_flag) { + throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); + } + + // 5 + _p('withCredentials', value); + } + }); + + o.defineProperty(this, 'status', { + configurable: false, + + get: function() { + return _p('status'); + } + }); + + o.defineProperty(this, 'statusText', { + configurable: false, + + get: function() { + return _p('statusText'); + } + }); + + o.defineProperty(this, 'responseType', { + configurable: false, + + get: function() { + return _p('responseType'); + }, + + set: function(value) { + // 1 + if (!!~o.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 2 + if (_sync_flag) { + throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); + } + + // 3 + _p('responseType', value.toLowerCase()); + } + }); + + o.defineProperty(this, 'responseText', { + configurable: false, + + get: function() { + // 1 + if (!~o.inArray(_p('responseType'), ['', 'text'])) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 2-3 + if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + return _p('responseText'); + } + }); + + o.defineProperty(this, 'responseXML', { + configurable: false, + + get: function() { + // 1 + if (!~o.inArray(_p('responseType'), ['', 'document'])) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // 2-3 + if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + return _p('responseXML'); + } + }); + + o.defineProperty(this, 'response', { + configurable: false, + + get: function() { + if (!!~o.inArray(_p('responseType'), ['', 'text'])) { + if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) { + return ''; + } + } + + if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) { + return null; + } + + return _p('response'); + } + }); + + */ + + function _p(prop, value) { + if (!props.hasOwnProperty(prop)) { + return; + } + if (arguments.length === 1) { // get + return Env.can('define_property') ? props[prop] : self[prop]; + } else { // set + if (Env.can('define_property')) { + props[prop] = value; + } else { + self[prop] = value; + } + } + } + + /* + function _toASCII(str, AllowUnassigned, UseSTD3ASCIIRules) { + // TODO: http://tools.ietf.org/html/rfc3490#section-4.1 + return str.toLowerCase(); + } + */ + + + function _doXHR(data) { + var self = this; + + _start_time = new Date().getTime(); + + _xhr = new RuntimeTarget(); + + function loadEnd() { + if (_xhr) { // it could have been destroyed by now + _xhr.destroy(); + _xhr = null; + } + self.dispatchEvent('loadend'); + self = null; + } + + function exec(runtime) { + _xhr.bind('LoadStart', function(e) { + _p('readyState', XMLHttpRequest.LOADING); + self.dispatchEvent('readystatechange'); + + self.dispatchEvent(e); + + if (_upload_events_flag) { + self.upload.dispatchEvent(e); + } + }); + + _xhr.bind('Progress', function(e) { + if (_p('readyState') !== XMLHttpRequest.LOADING) { + _p('readyState', XMLHttpRequest.LOADING); // LoadStart unreliable (in Flash for example) + self.dispatchEvent('readystatechange'); + } + self.dispatchEvent(e); + }); + + _xhr.bind('UploadProgress', function(e) { + if (_upload_events_flag) { + self.upload.dispatchEvent({ + type: 'progress', + lengthComputable: false, + total: e.total, + loaded: e.loaded + }); + } + }); + + _xhr.bind('Load', function(e) { + _p('readyState', XMLHttpRequest.DONE); + _p('status', Number(runtime.exec.call(_xhr, 'XMLHttpRequest', 'getStatus') || 0)); + _p('statusText', httpCode[_p('status')] || ""); + + _p('response', runtime.exec.call(_xhr, 'XMLHttpRequest', 'getResponse', _p('responseType'))); + + if (!!~Basic.inArray(_p('responseType'), ['text', ''])) { + _p('responseText', _p('response')); + } else if (_p('responseType') === 'document') { + _p('responseXML', _p('response')); + } + + _responseHeaders = runtime.exec.call(_xhr, 'XMLHttpRequest', 'getAllResponseHeaders'); + + self.dispatchEvent('readystatechange'); + + if (_p('status') > 0) { // status 0 usually means that server is unreachable + if (_upload_events_flag) { + self.upload.dispatchEvent(e); + } + self.dispatchEvent(e); + } else { + _error_flag = true; + self.dispatchEvent('error'); + } + loadEnd(); + }); + + _xhr.bind('Abort', function(e) { + self.dispatchEvent(e); + loadEnd(); + }); + + _xhr.bind('Error', function(e) { + _error_flag = true; + _p('readyState', XMLHttpRequest.DONE); + self.dispatchEvent('readystatechange'); + _upload_complete_flag = true; + self.dispatchEvent(e); + loadEnd(); + }); + + runtime.exec.call(_xhr, 'XMLHttpRequest', 'send', { + url: _url, + method: _method, + async: _async, + user: _user, + password: _password, + headers: _headers, + mimeType: _mimeType, + encoding: _encoding, + responseType: self.responseType, + withCredentials: self.withCredentials, + options: _options + }, data); + } + + // clarify our requirements + if (typeof(_options.required_caps) === 'string') { + _options.required_caps = Runtime.parseCaps(_options.required_caps); + } + + _options.required_caps = Basic.extend({}, _options.required_caps, { + return_response_type: self.responseType + }); + + if (data instanceof FormData) { + _options.required_caps.send_multipart = true; + } + + if (!Basic.isEmptyObj(_headers)) { + _options.required_caps.send_custom_headers = true; + } + + if (!_same_origin_flag) { + _options.required_caps.do_cors = true; + } + + + if (_options.ruid) { // we do not need to wait if we can connect directly + exec(_xhr.connectRuntime(_options)); + } else { + _xhr.bind('RuntimeInit', function(e, runtime) { + exec(runtime); + }); + _xhr.bind('RuntimeError', function(e, err) { + self.dispatchEvent('RuntimeError', err); + }); + _xhr.connectRuntime(_options); + } + } + + + function _reset() { + _p('responseText', ""); + _p('responseXML', null); + _p('response', null); + _p('status', 0); + _p('statusText', ""); + _start_time = _timeoutset_time = null; + } + } + + XMLHttpRequest.UNSENT = 0; + XMLHttpRequest.OPENED = 1; + XMLHttpRequest.HEADERS_RECEIVED = 2; + XMLHttpRequest.LOADING = 3; + XMLHttpRequest.DONE = 4; + + XMLHttpRequest.prototype = EventTarget.instance; + + return XMLHttpRequest; +}); + +// Included from: src/javascript/runtime/Transporter.js + +/** + * Transporter.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/runtime/Transporter", [ + "moxie/core/utils/Basic", + "moxie/core/utils/Encode", + "moxie/runtime/RuntimeClient", + "moxie/core/EventTarget" +], function(Basic, Encode, RuntimeClient, EventTarget) { + function Transporter() { + var mod, _runtime, _data, _size, _pos, _chunk_size; + + RuntimeClient.call(this); + + Basic.extend(this, { + uid: Basic.guid('uid_'), + + state: Transporter.IDLE, + + result: null, + + transport: function(data, type, options) { + var self = this; + + options = Basic.extend({ + chunk_size: 204798 + }, options); + + // should divide by three, base64 requires this + if ((mod = options.chunk_size % 3)) { + options.chunk_size += 3 - mod; + } + + _chunk_size = options.chunk_size; + + _reset.call(this); + _data = data; + _size = data.length; + + if (Basic.typeOf(options) === 'string' || options.ruid) { + _run.call(self, type, this.connectRuntime(options)); + } else { + // we require this to run only once + var cb = function(e, runtime) { + self.unbind("RuntimeInit", cb); + _run.call(self, type, runtime); + }; + this.bind("RuntimeInit", cb); + this.connectRuntime(options); + } + }, + + abort: function() { + var self = this; + + self.state = Transporter.IDLE; + if (_runtime) { + _runtime.exec.call(self, 'Transporter', 'clear'); + self.trigger("TransportingAborted"); + } + + _reset.call(self); + }, + + + destroy: function() { + this.unbindAll(); + _runtime = null; + this.disconnectRuntime(); + _reset.call(this); + } + }); + + function _reset() { + _size = _pos = 0; + _data = this.result = null; + } + + function _run(type, runtime) { + var self = this; + + _runtime = runtime; + + //self.unbind("RuntimeInit"); + + self.bind("TransportingProgress", function(e) { + _pos = e.loaded; + + if (_pos < _size && Basic.inArray(self.state, [Transporter.IDLE, Transporter.DONE]) === -1) { + _transport.call(self); + } + }, 999); + + self.bind("TransportingComplete", function() { + _pos = _size; + self.state = Transporter.DONE; + _data = null; // clean a bit + self.result = _runtime.exec.call(self, 'Transporter', 'getAsBlob', type || ''); + }, 999); + + self.state = Transporter.BUSY; + self.trigger("TransportingStarted"); + _transport.call(self); + } + + function _transport() { + var self = this, + chunk, + bytesLeft = _size - _pos; + + if (_chunk_size > bytesLeft) { + _chunk_size = bytesLeft; + } + + chunk = Encode.btoa(_data.substr(_pos, _chunk_size)); + _runtime.exec.call(self, 'Transporter', 'receive', chunk, _size); + } + } + + Transporter.IDLE = 0; + Transporter.BUSY = 1; + Transporter.DONE = 2; + + Transporter.prototype = EventTarget.instance; + + return Transporter; +}); + +// Included from: src/javascript/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define("moxie/image/Image", [ + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/Exceptions", + "moxie/file/FileReaderSync", + "moxie/xhr/XMLHttpRequest", + "moxie/runtime/Runtime", + "moxie/runtime/RuntimeClient", + "moxie/runtime/Transporter", + "moxie/core/utils/Env", + "moxie/core/EventTarget", + "moxie/file/Blob", + "moxie/file/File", + "moxie/core/utils/Encode" +], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) { + /** + Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data. + + @class Image + @constructor + @extends EventTarget + */ + var dispatches = [ + 'progress', + + /** + Dispatched when loading is complete. + + @event load + @param {Object} event + */ + 'load', + + 'error', + + /** + Dispatched when resize operation is complete. + + @event resize + @param {Object} event + */ + 'resize', + + /** + Dispatched when visual representation of the image is successfully embedded + into the corresponsing container. + + @event embedded + @param {Object} event + */ + 'embedded' + ]; + + function Image() { + + RuntimeClient.call(this); + + Basic.extend(this, { + /** + Unique id of the component + + @property uid + @type {String} + */ + uid: Basic.guid('uid_'), + + /** + Unique id of the connected runtime, if any. + + @property ruid + @type {String} + */ + ruid: null, + + /** + Name of the file, that was used to create an image, if available. If not equals to empty string. + + @property name + @type {String} + @default "" + */ + name: "", + + /** + Size of the image in bytes. Actual value is set only after image is preloaded. + + @property size + @type {Number} + @default 0 + */ + size: 0, + + /** + Width of the image. Actual value is set only after image is preloaded. + + @property width + @type {Number} + @default 0 + */ + width: 0, + + /** + Height of the image. Actual value is set only after image is preloaded. + + @property height + @type {Number} + @default 0 + */ + height: 0, + + /** + Mime type of the image. Currently only image/jpeg and image/png are supported. Actual value is set only after image is preloaded. + + @property type + @type {String} + @default "" + */ + type: "", + + /** + Holds meta info (Exif, GPS). Is populated only for image/jpeg. Actual value is set only after image is preloaded. + + @property meta + @type {Object} + @default {} + */ + meta: {}, + + /** + Alias for load method, that takes another mOxie.Image object as a source (see load). + + @method clone + @param {Image} src Source for the image + @param {Boolean} [exact=false] Whether to activate in-depth clone mode + */ + clone: function() { + this.load.apply(this, arguments); + }, + + /** + Loads image from various sources. Currently the source for new image can be: mOxie.Image, mOxie.Blob/mOxie.File, + native Blob/File, dataUrl or URL. Depending on the type of the source, arguments - differ. When source is URL, + Image will be downloaded from remote destination and loaded in memory. + + @example + var img = new mOxie.Image(); + img.onload = function() { + var blob = img.getAsBlob(); + + var formData = new mOxie.FormData(); + formData.append('file', blob); + + var xhr = new mOxie.XMLHttpRequest(); + xhr.onload = function() { + // upload complete + }; + xhr.open('post', 'upload.php'); + xhr.send(formData); + }; + img.load("http://www.moxiecode.com/images/mox-logo.jpg"); // notice file extension (.jpg) + + + @method load + @param {Image|Blob|File|String} src Source for the image + @param {Boolean|Object} [mixed] + */ + load: function() { + _load.apply(this, arguments); + }, + + /** + Downsizes the image to fit the specified width/height. If crop is supplied, image will be cropped to exact dimensions. + + @method downsize + @param {Object} opts + @param {Number} opts.width Resulting width + @param {Number} [opts.height=width] Resulting height (optional, if not supplied will default to width) + @param {Boolean} [opts.crop=false] Whether to crop the image to exact dimensions + @param {Boolean} [opts.preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize) + @param {String} [opts.resample=false] Resampling algorithm to use for resizing + */ + downsize: function(opts) { + var defaults = { + width: this.width, + height: this.height, + type: this.type || 'image/jpeg', + quality: 90, + crop: false, + preserveHeaders: true, + resample: false + }; + + if (typeof(opts) === 'object') { + opts = Basic.extend(defaults, opts); + } else { + // for backward compatibility + opts = Basic.extend(defaults, { + width: arguments[0], + height: arguments[1], + crop: arguments[2], + preserveHeaders: arguments[3] + }); + } + + try { + if (!this.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // no way to reliably intercept the crash due to high resolution, so we simply avoid it + if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) { + throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR); + } + + this.exec('Image', 'downsize', opts.width, opts.height, opts.crop, opts.preserveHeaders); + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + }, + + /** + Alias for downsize(width, height, true). (see downsize) + + @method crop + @param {Number} width Resulting width + @param {Number} [height=width] Resulting height (optional, if not supplied will default to width) + @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize) + */ + crop: function(width, height, preserveHeaders) { + this.downsize(width, height, true, preserveHeaders); + }, + + getAsCanvas: function() { + if (!Env.can('create_canvas')) { + throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); + } + + var runtime = this.connectRuntime(this.ruid); + return runtime.exec.call(this, 'Image', 'getAsCanvas'); + }, + + /** + Retrieves image in it's current state as mOxie.Blob object. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsBlob + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {Blob} Image as Blob + */ + getAsBlob: function(type, quality) { + if (!this.size) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + return this.exec('Image', 'getAsBlob', type || 'image/jpeg', quality || 90); + }, + + /** + Retrieves image in it's current state as dataURL string. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsDataURL + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {String} Image as dataURL string + */ + getAsDataURL: function(type, quality) { + if (!this.size) { + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + return this.exec('Image', 'getAsDataURL', type || 'image/jpeg', quality || 90); + }, + + /** + Retrieves image in it's current state as binary string. Cannot be run on empty or image in progress (throws + DOMException.INVALID_STATE_ERR). + + @method getAsBinaryString + @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png + @param {Number} [quality=90] Applicable only together with mime type image/jpeg + @return {String} Image as binary string + */ + getAsBinaryString: function(type, quality) { + var dataUrl = this.getAsDataURL(type, quality); + return Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)); + }, + + /** + Embeds a visual representation of the image into the specified node. Depending on the runtime, + it might be a canvas, an img node or a thrid party shim object (Flash or SilverLight - very rare, + can be used in legacy browsers that do not have canvas or proper dataURI support). + + @method embed + @param {DOMElement} el DOM element to insert the image object into + @param {Object} [opts] + @param {Number} [opts.width] The width of an embed (defaults to the image width) + @param {Number} [opts.height] The height of an embed (defaults to the image height) + @param {String} [type="image/jpeg"] Mime type + @param {Number} [quality=90] Quality of an embed, if mime type is image/jpeg + @param {Boolean} [crop=false] Whether to crop an embed to the specified dimensions + */ + embed: function(el, opts) { + var self = this + , runtime // this has to be outside of all the closures to contain proper runtime + ; + + opts = Basic.extend({ + width: this.width, + height: this.height, + type: this.type || 'image/jpeg', + quality: 90 + }, opts || {}); + + + function render(type, quality) { + var img = this; + + // if possible, embed a canvas element directly + if (Env.can('create_canvas')) { + var canvas = img.getAsCanvas(); + if (canvas) { + el.appendChild(canvas); + canvas = null; + img.destroy(); + self.trigger('embedded'); + return; + } + } + + var dataUrl = img.getAsDataURL(type, quality); + if (!dataUrl) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + + if (Env.can('use_data_uri_of', dataUrl.length)) { + el.innerHTML = ''; + img.destroy(); + self.trigger('embedded'); + } else { + var tr = new Transporter(); + + tr.bind("TransportingComplete", function() { + runtime = self.connectRuntime(this.result.ruid); + + self.bind("Embedded", function() { + // position and size properly + Basic.extend(runtime.getShimContainer().style, { + //position: 'relative', + top: '0px', + left: '0px', + width: img.width + 'px', + height: img.height + 'px' + }); + + // some shims (Flash/SilverLight) reinitialize, if parent element is hidden, reordered or it's + // position type changes (in Gecko), but since we basically need this only in IEs 6/7 and + // sometimes 8 and they do not have this problem, we can comment this for now + /*tr.bind("RuntimeInit", function(e, runtime) { + tr.destroy(); + runtime.destroy(); + onResize.call(self); // re-feed our image data + });*/ + + runtime = null; // release + }, 999); + + runtime.exec.call(self, "ImageView", "display", this.result.uid, width, height); + img.destroy(); + }); + + tr.transport(Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)), type, { + required_caps: { + display_media: true + }, + runtime_order: 'flash,silverlight', + container: el + }); + } + } + + try { + if (!(el = Dom.get(el))) { + throw new x.DOMException(x.DOMException.INVALID_NODE_TYPE_ERR); + } + + if (!this.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + + // high-resolution images cannot be consistently handled across the runtimes + if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) { + //throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR); + } + + var imgCopy = new Image(); + + imgCopy.bind("Resize", function() { + render.call(this, opts.type, opts.quality); + }); + + imgCopy.bind("Load", function() { + imgCopy.downsize(opts); + }); + + // if embedded thumb data is available and dimensions are big enough, use it + if (this.meta.thumb && this.meta.thumb.width >= opts.width && this.meta.thumb.height >= opts.height) { + imgCopy.load(this.meta.thumb.data); + } else { + imgCopy.clone(this, false); + } + + return imgCopy; + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + }, + + /** + Properly destroys the image and frees resources in use. If any. Recommended way to dispose mOxie.Image object. + + @method destroy + */ + destroy: function() { + if (this.ruid) { + this.getRuntime().exec.call(this, 'Image', 'destroy'); + this.disconnectRuntime(); + } + this.unbindAll(); + } + }); + + + // this is here, because in order to bind properly, we need uid, which is created above + this.handleEventProps(dispatches); + + this.bind('Load Resize', function() { + _updateInfo.call(this); + }, 999); + + + function _updateInfo(info) { + if (!info) { + info = this.exec('Image', 'getInfo'); + } + + this.size = info.size; + this.width = info.width; + this.height = info.height; + this.type = info.type; + this.meta = info.meta; + + // update file name, only if empty + if (this.name === '') { + this.name = info.name; + } + } + + + function _load(src) { + var srcType = Basic.typeOf(src); + + try { + // if source is Image + if (src instanceof Image) { + if (!src.size) { // only preloaded image objects can be used as source + throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); + } + _loadFromImage.apply(this, arguments); + } + // if source is o.Blob/o.File + else if (src instanceof Blob) { + if (!~Basic.inArray(src.type, ['image/jpeg', 'image/png'])) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + _loadFromBlob.apply(this, arguments); + } + // if native blob/file + else if (Basic.inArray(srcType, ['blob', 'file']) !== -1) { + _load.call(this, new File(null, src), arguments[1]); + } + // if String + else if (srcType === 'string') { + // if dataUrl String + if (src.substr(0, 5) === 'data:') { + _load.call(this, new Blob(null, { data: src }), arguments[1]); + } + // else assume Url, either relative or absolute + else { + _loadFromUrl.apply(this, arguments); + } + } + // if source seems to be an img node + else if (srcType === 'node' && src.nodeName.toLowerCase() === 'img') { + _load.call(this, src.src, arguments[1]); + } + else { + throw new x.DOMException(x.DOMException.TYPE_MISMATCH_ERR); + } + } catch(ex) { + // for now simply trigger error event + this.trigger('error', ex.code); + } + } + + + function _loadFromImage(img, exact) { + var runtime = this.connectRuntime(img.ruid); + this.ruid = runtime.uid; + runtime.exec.call(this, 'Image', 'loadFromImage', img, (Basic.typeOf(exact) === 'undefined' ? true : exact)); + } + + + function _loadFromBlob(blob, options) { + var self = this; + + self.name = blob.name || ''; + + function exec(runtime) { + self.ruid = runtime.uid; + runtime.exec.call(self, 'Image', 'loadFromBlob', blob); + } + + if (blob.isDetached()) { + this.bind('RuntimeInit', function(e, runtime) { + exec(runtime); + }); + + // convert to object representation + if (options && typeof(options.required_caps) === 'string') { + options.required_caps = Runtime.parseCaps(options.required_caps); + } + + this.connectRuntime(Basic.extend({ + required_caps: { + access_image_binary: true, + resize_image: true + } + }, options)); + } else { + exec(this.connectRuntime(blob.ruid)); + } + } + + + function _loadFromUrl(url, options) { + var self = this, xhr; + + xhr = new XMLHttpRequest(); + + xhr.open('get', url); + xhr.responseType = 'blob'; + + xhr.onprogress = function(e) { + self.trigger(e); + }; + + xhr.onload = function() { + _loadFromBlob.call(self, xhr.response, true); + }; + + xhr.onerror = function(e) { + self.trigger(e); + }; + + xhr.onloadend = function() { + xhr.destroy(); + }; + + xhr.bind('RuntimeError', function(e, err) { + self.trigger('RuntimeError', err); + }); + + xhr.send(null, options); + } + } + + // virtual world will crash on you if image has a resolution higher than this: + Image.MAX_RESIZE_WIDTH = 8192; + Image.MAX_RESIZE_HEIGHT = 8192; + + Image.prototype = EventTarget.instance; + + return Image; +}); + +// Included from: src/javascript/runtime/html5/Runtime.js + +/** + * Runtime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global File:true */ + +/** +Defines constructor for HTML5 runtime. + +@class moxie/runtime/html5/Runtime +@private +*/ +define("moxie/runtime/html5/Runtime", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/runtime/Runtime", + "moxie/core/utils/Env" +], function(Basic, x, Runtime, Env) { + + var type = "html5", extensions = {}; + + function Html5Runtime(options) { + var I = this + , Test = Runtime.capTest + , True = Runtime.capTrue + ; + + var caps = Basic.extend({ + access_binary: Test(window.FileReader || window.File && window.File.getAsDataURL), + access_image_binary: function() { + return I.can('access_binary') && !!extensions.Image; + }, + display_media: Test(Env.can('create_canvas') || Env.can('use_data_uri_over32kb')), + do_cors: Test(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()), + drag_and_drop: Test(function() { + // this comes directly from Modernizr: http://www.modernizr.com/ + var div = document.createElement('div'); + // IE has support for drag and drop since version 5, but doesn't support dropping files from desktop + return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && + (Env.browser !== 'IE' || Env.verComp(Env.version, 9, '>')); + }()), + filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest + return (Env.browser === 'Chrome' && Env.verComp(Env.version, 28, '>=')) || + (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) || + (Env.browser === 'Safari' && Env.verComp(Env.version, 7, '>=')); + }()), + return_response_headers: True, + return_response_type: function(responseType) { + if (responseType === 'json' && !!window.JSON) { // we can fake this one even if it's not supported + return true; + } + return Env.can('return_response_type', responseType); + }, + return_status_code: True, + report_upload_progress: Test(window.XMLHttpRequest && new XMLHttpRequest().upload), + resize_image: function() { + return I.can('access_binary') && Env.can('create_canvas'); + }, + select_file: function() { + return Env.can('use_fileinput') && window.File; + }, + select_folder: function() { + return I.can('select_file') && Env.browser === 'Chrome' && Env.verComp(Env.version, 21, '>='); + }, + select_multiple: function() { + // it is buggy on Safari Windows and iOS + return I.can('select_file') && + !(Env.browser === 'Safari' && Env.os === 'Windows') && + !(Env.os === 'iOS' && Env.verComp(Env.osVersion, "7.0.0", '>') && Env.verComp(Env.osVersion, "8.0.0", '<')); + }, + send_binary_string: Test(window.XMLHttpRequest && (new XMLHttpRequest().sendAsBinary || (window.Uint8Array && window.ArrayBuffer))), + send_custom_headers: Test(window.XMLHttpRequest), + send_multipart: function() { + return !!(window.XMLHttpRequest && new XMLHttpRequest().upload && window.FormData) || I.can('send_binary_string'); + }, + slice_blob: Test(window.File && (File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice)), + stream_upload: function(){ + return I.can('slice_blob') && I.can('send_multipart'); + }, + summon_file_dialog: function() { // yeah... some dirty sniffing here... + return I.can('select_file') && ( + (Env.browser === 'Firefox' && Env.verComp(Env.version, 4, '>=')) || + (Env.browser === 'Opera' && Env.verComp(Env.version, 12, '>=')) || + (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) || + !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']) + ); + }, + upload_filesize: True + }, + arguments[2] + ); + + Runtime.call(this, options, (arguments[1] || type), caps); + + + Basic.extend(this, { + + init : function() { + this.trigger("Init"); + }, + + destroy: (function(destroy) { // extend default destroy method + return function() { + destroy.call(I); + destroy = I = null; + }; + }(this.destroy)) + }); + + Basic.extend(this.getShim(), extensions); + } + + Runtime.addConstructor(type, Html5Runtime); + + return extensions; +}); + +// Included from: src/javascript/core/utils/Events.js + +/** + * Events.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +define('moxie/core/utils/Events', [ + 'moxie/core/utils/Basic' +], function(Basic) { + var eventhash = {}, uid = 'moxie_' + Basic.guid(); + + // IE W3C like event funcs + function preventDefault() { + this.returnValue = false; + } + + function stopPropagation() { + this.cancelBubble = true; + } + + /** + Adds an event handler to the specified object and store reference to the handler + in objects internal Plupload registry (@see removeEvent). + + @method addEvent + @for Utils + @static + @param {Object} obj DOM element like object to add handler to. + @param {String} name Name to add event listener to. + @param {Function} callback Function to call when event occurs. + @param {String} [key] that might be used to add specifity to the event record. + */ + var addEvent = function(obj, name, callback, key) { + var func, events; + + name = name.toLowerCase(); + + // Add event listener + if (obj.addEventListener) { + func = callback; + + obj.addEventListener(name, func, false); + } else if (obj.attachEvent) { + func = function() { + var evt = window.event; + + if (!evt.target) { + evt.target = evt.srcElement; + } + + evt.preventDefault = preventDefault; + evt.stopPropagation = stopPropagation; + + callback(evt); + }; + + obj.attachEvent('on' + name, func); + } + + // Log event handler to objects internal mOxie registry + if (!obj[uid]) { + obj[uid] = Basic.guid(); + } + + if (!eventhash.hasOwnProperty(obj[uid])) { + eventhash[obj[uid]] = {}; + } + + events = eventhash[obj[uid]]; + + if (!events.hasOwnProperty(name)) { + events[name] = []; + } + + events[name].push({ + func: func, + orig: callback, // store original callback for IE + key: key + }); + }; + + + /** + Remove event handler from the specified object. If third argument (callback) + is not specified remove all events with the specified name. + + @method removeEvent + @static + @param {Object} obj DOM element to remove event listener(s) from. + @param {String} name Name of event listener to remove. + @param {Function|String} [callback] might be a callback or unique key to match. + */ + var removeEvent = function(obj, name, callback) { + var type, undef; + + name = name.toLowerCase(); + + if (obj[uid] && eventhash[obj[uid]] && eventhash[obj[uid]][name]) { + type = eventhash[obj[uid]][name]; + } else { + return; + } + + for (var i = type.length - 1; i >= 0; i--) { + // undefined or not, key should match + if (type[i].orig === callback || type[i].key === callback) { + if (obj.removeEventListener) { + obj.removeEventListener(name, type[i].func, false); + } else if (obj.detachEvent) { + obj.detachEvent('on'+name, type[i].func); + } + + type[i].orig = null; + type[i].func = null; + type.splice(i, 1); + + // If callback was passed we are done here, otherwise proceed + if (callback !== undef) { + break; + } + } + } + + // If event array got empty, remove it + if (!type.length) { + delete eventhash[obj[uid]][name]; + } + + // If mOxie registry has become empty, remove it + if (Basic.isEmptyObj(eventhash[obj[uid]])) { + delete eventhash[obj[uid]]; + + // IE doesn't let you remove DOM object property with - delete + try { + delete obj[uid]; + } catch(e) { + obj[uid] = undef; + } + } + }; + + + /** + Remove all kind of events from the specified object + + @method removeAllEvents + @static + @param {Object} obj DOM element to remove event listeners from. + @param {String} [key] unique key to match, when removing events. + */ + var removeAllEvents = function(obj, key) { + if (!obj || !obj[uid]) { + return; + } + + Basic.each(eventhash[obj[uid]], function(events, name) { + removeEvent(obj, name, key); + }); + }; + + return { + addEvent: addEvent, + removeEvent: removeEvent, + removeAllEvents: removeAllEvents + }; +}); + +// Included from: src/javascript/runtime/html5/file/FileInput.js + +/** + * FileInput.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/file/FileInput +@private +*/ +define("moxie/runtime/html5/file/FileInput", [ + "moxie/runtime/html5/Runtime", + "moxie/file/File", + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/utils/Events", + "moxie/core/utils/Mime", + "moxie/core/utils/Env" +], function(extensions, File, Basic, Dom, Events, Mime, Env) { + + function FileInput() { + var _options; + + Basic.extend(this, { + init: function(options) { + var comp = this, I = comp.getRuntime(), input, shimContainer, mimes, browseButton, zIndex, top; + + _options = options; + + // figure out accept string + mimes = _options.accept.mimes || Mime.extList2mimes(_options.accept, I.can('filter_by_extension')); + + shimContainer = I.getShimContainer(); + + shimContainer.innerHTML = ''; + + input = Dom.get(I.uid); + + // prepare file input to be placed underneath the browse_button element + Basic.extend(input.style, { + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%' + }); + + + browseButton = Dom.get(_options.browse_button); + + // Route click event to the input[type=file] element for browsers that support such behavior + if (I.can('summon_file_dialog')) { + if (Dom.getStyle(browseButton, 'position') === 'static') { + browseButton.style.position = 'relative'; + } + + zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1; + + browseButton.style.zIndex = zIndex; + shimContainer.style.zIndex = zIndex - 1; + + Events.addEvent(browseButton, 'click', function(e) { + var input = Dom.get(I.uid); + if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file] + input.click(); + } + e.preventDefault(); + }, comp.uid); + } + + /* Since we have to place input[type=file] on top of the browse_button for some browsers, + browse_button loses interactivity, so we restore it here */ + top = I.can('summon_file_dialog') ? browseButton : shimContainer; + + Events.addEvent(top, 'mouseover', function() { + comp.trigger('mouseenter'); + }, comp.uid); + + Events.addEvent(top, 'mouseout', function() { + comp.trigger('mouseleave'); + }, comp.uid); + + Events.addEvent(top, 'mousedown', function() { + comp.trigger('mousedown'); + }, comp.uid); + + Events.addEvent(Dom.get(_options.container), 'mouseup', function() { + comp.trigger('mouseup'); + }, comp.uid); + + + input.onchange = function onChange(e) { // there should be only one handler for this + comp.files = []; + + Basic.each(this.files, function(file) { + var relativePath = ''; + + if (_options.directory) { + // folders are represented by dots, filter them out (Chrome 11+) + if (file.name == ".") { + // if it looks like a folder... + return true; + } + } + + if (file.webkitRelativePath) { + relativePath = '/' + file.webkitRelativePath.replace(/^\//, ''); + } + + file = new File(I.uid, file); + file.relativePath = relativePath; + + comp.files.push(file); + }); + + // clearing the value enables the user to select the same file again if they want to + if (Env.browser !== 'IE' && Env.browser !== 'IEMobile') { + this.value = ''; + } else { + // in IE input[type="file"] is read-only so the only way to reset it is to re-insert it + var clone = this.cloneNode(true); + this.parentNode.replaceChild(clone, this); + clone.onchange = onChange; + } + + if (comp.files.length) { + comp.trigger('change'); + } + }; + + // ready event is perfectly asynchronous + comp.trigger({ + type: 'ready', + async: true + }); + + shimContainer = null; + }, + + + disable: function(state) { + var I = this.getRuntime(), input; + + if ((input = Dom.get(I.uid))) { + input.disabled = !!state; + } + }, + + destroy: function() { + var I = this.getRuntime() + , shim = I.getShim() + , shimContainer = I.getShimContainer() + ; + + Events.removeAllEvents(shimContainer, this.uid); + Events.removeAllEvents(_options && Dom.get(_options.container), this.uid); + Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid); + + if (shimContainer) { + shimContainer.innerHTML = ''; + } + + shim.removeInstance(this.uid); + + _options = shimContainer = shim = null; + } + }); + } + + return (extensions.FileInput = FileInput); +}); + +// Included from: src/javascript/runtime/html5/file/Blob.js + +/** + * Blob.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/file/Blob +@private +*/ +define("moxie/runtime/html5/file/Blob", [ + "moxie/runtime/html5/Runtime", + "moxie/file/Blob" +], function(extensions, Blob) { + + function HTML5Blob() { + function w3cBlobSlice(blob, start, end) { + var blobSlice; + + if (window.File.prototype.slice) { + try { + blob.slice(); // depricated version will throw WRONG_ARGUMENTS_ERR exception + return blob.slice(start, end); + } catch (e) { + // depricated slice method + return blob.slice(start, end - start); + } + // slice method got prefixed: https://bugzilla.mozilla.org/show_bug.cgi?id=649672 + } else if ((blobSlice = window.File.prototype.webkitSlice || window.File.prototype.mozSlice)) { + return blobSlice.call(blob, start, end); + } else { + return null; // or throw some exception + } + } + + this.slice = function() { + return new Blob(this.getRuntime().uid, w3cBlobSlice.apply(this, arguments)); + }; + } + + return (extensions.Blob = HTML5Blob); +}); + +// Included from: src/javascript/runtime/html5/file/FileDrop.js + +/** + * FileDrop.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/file/FileDrop +@private +*/ +define("moxie/runtime/html5/file/FileDrop", [ + "moxie/runtime/html5/Runtime", + 'moxie/file/File', + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/utils/Events", + "moxie/core/utils/Mime" +], function(extensions, File, Basic, Dom, Events, Mime) { + + function FileDrop() { + var _files = [], _allowedExts = [], _options, _ruid; + + Basic.extend(this, { + init: function(options) { + var comp = this, dropZone; + + _options = options; + _ruid = comp.ruid; // every dropped-in file should have a reference to the runtime + _allowedExts = _extractExts(_options.accept); + dropZone = _options.container; + + Events.addEvent(dropZone, 'dragover', function(e) { + if (!_hasFiles(e)) { + return; + } + e.preventDefault(); + e.dataTransfer.dropEffect = 'copy'; + }, comp.uid); + + Events.addEvent(dropZone, 'drop', function(e) { + if (!_hasFiles(e)) { + return; + } + e.preventDefault(); + + _files = []; + + // Chrome 21+ accepts folders via Drag'n'Drop + if (e.dataTransfer.items && e.dataTransfer.items[0].webkitGetAsEntry) { + _readItems(e.dataTransfer.items, function() { + comp.files = _files; + comp.trigger("drop"); + }); + } else { + Basic.each(e.dataTransfer.files, function(file) { + _addFile(file); + }); + comp.files = _files; + comp.trigger("drop"); + } + }, comp.uid); + + Events.addEvent(dropZone, 'dragenter', function(e) { + comp.trigger("dragenter"); + }, comp.uid); + + Events.addEvent(dropZone, 'dragleave', function(e) { + comp.trigger("dragleave"); + }, comp.uid); + }, + + destroy: function() { + Events.removeAllEvents(_options && Dom.get(_options.container), this.uid); + _ruid = _files = _allowedExts = _options = null; + } + }); + + + function _hasFiles(e) { + if (!e.dataTransfer || !e.dataTransfer.types) { // e.dataTransfer.files is not available in Gecko during dragover + return false; + } + + var types = Basic.toArray(e.dataTransfer.types || []); + + return Basic.inArray("Files", types) !== -1 || + Basic.inArray("public.file-url", types) !== -1 || // Safari < 5 + Basic.inArray("application/x-moz-file", types) !== -1 // Gecko < 1.9.2 (< Firefox 3.6) + ; + } + + + function _addFile(file, relativePath) { + if (_isAcceptable(file)) { + var fileObj = new File(_ruid, file); + fileObj.relativePath = relativePath || ''; + _files.push(fileObj); + } + } + + + function _extractExts(accept) { + var exts = []; + for (var i = 0; i < accept.length; i++) { + [].push.apply(exts, accept[i].extensions.split(/\s*,\s*/)); + } + return Basic.inArray('*', exts) === -1 ? exts : []; + } + + + function _isAcceptable(file) { + if (!_allowedExts.length) { + return true; + } + var ext = Mime.getFileExtension(file.name); + return !ext || Basic.inArray(ext, _allowedExts) !== -1; + } + + + function _readItems(items, cb) { + var entries = []; + Basic.each(items, function(item) { + var entry = item.webkitGetAsEntry(); + // Address #998 (https://code.google.com/p/chromium/issues/detail?id=332579) + if (entry) { + // file() fails on OSX when the filename contains a special character (e.g. umlaut): see #61 + if (entry.isFile) { + _addFile(item.getAsFile(), entry.fullPath); + } else { + entries.push(entry); + } + } + }); + + if (entries.length) { + _readEntries(entries, cb); + } else { + cb(); + } + } + + + function _readEntries(entries, cb) { + var queue = []; + Basic.each(entries, function(entry) { + queue.push(function(cbcb) { + _readEntry(entry, cbcb); + }); + }); + Basic.inSeries(queue, function() { + cb(); + }); + } + + + function _readEntry(entry, cb) { + if (entry.isFile) { + entry.file(function(file) { + _addFile(file, entry.fullPath); + cb(); + }, function() { + // fire an error event maybe + cb(); + }); + } else if (entry.isDirectory) { + _readDirEntry(entry, cb); + } else { + cb(); // not file, not directory? what then?.. + } + } + + + function _readDirEntry(dirEntry, cb) { + var entries = [], dirReader = dirEntry.createReader(); + + // keep quering recursively till no more entries + function getEntries(cbcb) { + dirReader.readEntries(function(moreEntries) { + if (moreEntries.length) { + [].push.apply(entries, moreEntries); + getEntries(cbcb); + } else { + cbcb(); + } + }, cbcb); + } + + // ...and you thought FileReader was crazy... + getEntries(function() { + _readEntries(entries, cb); + }); + } + } + + return (extensions.FileDrop = FileDrop); +}); + +// Included from: src/javascript/runtime/html5/file/FileReader.js + +/** + * FileReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/file/FileReader +@private +*/ +define("moxie/runtime/html5/file/FileReader", [ + "moxie/runtime/html5/Runtime", + "moxie/core/utils/Encode", + "moxie/core/utils/Basic" +], function(extensions, Encode, Basic) { + + function FileReader() { + var _fr, _convertToBinary = false; + + Basic.extend(this, { + + read: function(op, blob) { + var comp = this; + + comp.result = ''; + + _fr = new window.FileReader(); + + _fr.addEventListener('progress', function(e) { + comp.trigger(e); + }); + + _fr.addEventListener('load', function(e) { + comp.result = _convertToBinary ? _toBinary(_fr.result) : _fr.result; + comp.trigger(e); + }); + + _fr.addEventListener('error', function(e) { + comp.trigger(e, _fr.error); + }); + + _fr.addEventListener('loadend', function(e) { + _fr = null; + comp.trigger(e); + }); + + if (Basic.typeOf(_fr[op]) === 'function') { + _convertToBinary = false; + _fr[op](blob.getSource()); + } else if (op === 'readAsBinaryString') { // readAsBinaryString is depricated in general and never existed in IE10+ + _convertToBinary = true; + _fr.readAsDataURL(blob.getSource()); + } + }, + + abort: function() { + if (_fr) { + _fr.abort(); + } + }, + + destroy: function() { + _fr = null; + } + }); + + function _toBinary(str) { + return Encode.atob(str.substring(str.indexOf('base64,') + 7)); + } + } + + return (extensions.FileReader = FileReader); +}); + +// Included from: src/javascript/runtime/html5/xhr/XMLHttpRequest.js + +/** + * XMLHttpRequest.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global ActiveXObject:true */ + +/** +@class moxie/runtime/html5/xhr/XMLHttpRequest +@private +*/ +define("moxie/runtime/html5/xhr/XMLHttpRequest", [ + "moxie/runtime/html5/Runtime", + "moxie/core/utils/Basic", + "moxie/core/utils/Mime", + "moxie/core/utils/Url", + "moxie/file/File", + "moxie/file/Blob", + "moxie/xhr/FormData", + "moxie/core/Exceptions", + "moxie/core/utils/Env" +], function(extensions, Basic, Mime, Url, File, Blob, FormData, x, Env) { + + function XMLHttpRequest() { + var self = this + , _xhr + , _filename + ; + + Basic.extend(this, { + send: function(meta, data) { + var target = this + , isGecko2_5_6 = (Env.browser === 'Mozilla' && Env.verComp(Env.version, 4, '>=') && Env.verComp(Env.version, 7, '<')) + , isAndroidBrowser = Env.browser === 'Android Browser' + , mustSendAsBinary = false + ; + + // extract file name + _filename = meta.url.replace(/^.+?\/([\w\-\.]+)$/, '$1').toLowerCase(); + + _xhr = _getNativeXHR(); + _xhr.open(meta.method, meta.url, meta.async, meta.user, meta.password); + + + // prepare data to be sent + if (data instanceof Blob) { + if (data.isDetached()) { + mustSendAsBinary = true; + } + data = data.getSource(); + } else if (data instanceof FormData) { + + if (data.hasBlob()) { + if (data.getBlob().isDetached()) { + data = _prepareMultipart.call(target, data); // _xhr must be instantiated and be in OPENED state + mustSendAsBinary = true; + } else if ((isGecko2_5_6 || isAndroidBrowser) && Basic.typeOf(data.getBlob().getSource()) === 'blob' && window.FileReader) { + // Gecko 2/5/6 can't send blob in FormData: https://bugzilla.mozilla.org/show_bug.cgi?id=649150 + // Android browsers (default one and Dolphin) seem to have the same issue, see: #613 + _preloadAndSend.call(target, meta, data); + return; // _preloadAndSend will reinvoke send() with transmutated FormData =%D + } + } + + // transfer fields to real FormData + if (data instanceof FormData) { // if still a FormData, e.g. not mangled by _prepareMultipart() + var fd = new window.FormData(); + data.each(function(value, name) { + if (value instanceof Blob) { + fd.append(name, value.getSource()); + } else { + fd.append(name, value); + } + }); + data = fd; + } + } + + + // if XHR L2 + if (_xhr.upload) { + if (meta.withCredentials) { + _xhr.withCredentials = true; + } + + _xhr.addEventListener('load', function(e) { + target.trigger(e); + }); + + _xhr.addEventListener('error', function(e) { + target.trigger(e); + }); + + // additionally listen to progress events + _xhr.addEventListener('progress', function(e) { + target.trigger(e); + }); + + _xhr.upload.addEventListener('progress', function(e) { + target.trigger({ + type: 'UploadProgress', + loaded: e.loaded, + total: e.total + }); + }); + // ... otherwise simulate XHR L2 + } else { + _xhr.onreadystatechange = function onReadyStateChange() { + + // fake Level 2 events + switch (_xhr.readyState) { + + case 1: // XMLHttpRequest.OPENED + // readystatechanged is fired twice for OPENED state (in IE and Mozilla) - neu + break; + + // looks like HEADERS_RECEIVED (state 2) is not reported in Opera (or it's old versions) - neu + case 2: // XMLHttpRequest.HEADERS_RECEIVED + break; + + case 3: // XMLHttpRequest.LOADING + // try to fire progress event for not XHR L2 + var total, loaded; + + try { + if (Url.hasSameOrigin(meta.url)) { // Content-Length not accessible for cross-domain on some browsers + total = _xhr.getResponseHeader('Content-Length') || 0; // old Safari throws an exception here + } + + if (_xhr.responseText) { // responseText was introduced in IE7 + loaded = _xhr.responseText.length; + } + } catch(ex) { + total = loaded = 0; + } + + target.trigger({ + type: 'progress', + lengthComputable: !!total, + total: parseInt(total, 10), + loaded: loaded + }); + break; + + case 4: // XMLHttpRequest.DONE + // release readystatechange handler (mostly for IE) + _xhr.onreadystatechange = function() {}; + + // usually status 0 is returned when server is unreachable, but FF also fails to status 0 for 408 timeout + if (_xhr.status === 0) { + target.trigger('error'); + } else { + target.trigger('load'); + } + break; + } + }; + } + + + // set request headers + if (!Basic.isEmptyObj(meta.headers)) { + Basic.each(meta.headers, function(value, header) { + _xhr.setRequestHeader(header, value); + }); + } + + // request response type + if ("" !== meta.responseType && 'responseType' in _xhr) { + if ('json' === meta.responseType && !Env.can('return_response_type', 'json')) { // we can fake this one + _xhr.responseType = 'text'; + } else { + _xhr.responseType = meta.responseType; + } + } + + // send ... + if (!mustSendAsBinary) { + _xhr.send(data); + } else { + if (_xhr.sendAsBinary) { // Gecko + _xhr.sendAsBinary(data); + } else { // other browsers having support for typed arrays + (function() { + // mimic Gecko's sendAsBinary + var ui8a = new Uint8Array(data.length); + for (var i = 0; i < data.length; i++) { + ui8a[i] = (data.charCodeAt(i) & 0xff); + } + _xhr.send(ui8a.buffer); + }()); + } + } + + target.trigger('loadstart'); + }, + + getStatus: function() { + // according to W3C spec it should return 0 for readyState < 3, but instead it throws an exception + try { + if (_xhr) { + return _xhr.status; + } + } catch(ex) {} + return 0; + }, + + getResponse: function(responseType) { + var I = this.getRuntime(); + + try { + switch (responseType) { + case 'blob': + var file = new File(I.uid, _xhr.response); + + // try to extract file name from content-disposition if possible (might be - not, if CORS for example) + var disposition = _xhr.getResponseHeader('Content-Disposition'); + if (disposition) { + // extract filename from response header if available + var match = disposition.match(/filename=([\'\"'])([^\1]+)\1/); + if (match) { + _filename = match[2]; + } + } + file.name = _filename; + + // pre-webkit Opera doesn't set type property on the blob response + if (!file.type) { + file.type = Mime.getFileMime(_filename); + } + return file; + + case 'json': + if (!Env.can('return_response_type', 'json')) { + return _xhr.status === 200 && !!window.JSON ? JSON.parse(_xhr.responseText) : null; + } + return _xhr.response; + + case 'document': + return _getDocument(_xhr); + + default: + return _xhr.responseText !== '' ? _xhr.responseText : null; // against the specs, but for consistency across the runtimes + } + } catch(ex) { + return null; + } + }, + + getAllResponseHeaders: function() { + try { + return _xhr.getAllResponseHeaders(); + } catch(ex) {} + return ''; + }, + + abort: function() { + if (_xhr) { + _xhr.abort(); + } + }, + + destroy: function() { + self = _filename = null; + } + }); + + + // here we go... ugly fix for ugly bug + function _preloadAndSend(meta, data) { + var target = this, blob, fr; + + // get original blob + blob = data.getBlob().getSource(); + + // preload blob in memory to be sent as binary string + fr = new window.FileReader(); + fr.onload = function() { + // overwrite original blob + data.append(data.getBlobName(), new Blob(null, { + type: blob.type, + data: fr.result + })); + // invoke send operation again + self.send.call(target, meta, data); + }; + fr.readAsBinaryString(blob); + } + + + function _getNativeXHR() { + if (window.XMLHttpRequest && !(Env.browser === 'IE' && Env.verComp(Env.version, 8, '<'))) { // IE7 has native XHR but it's buggy + return new window.XMLHttpRequest(); + } else { + return (function() { + var progIDs = ['Msxml2.XMLHTTP.6.0', 'Microsoft.XMLHTTP']; // if 6.0 available, use it, otherwise failback to default 3.0 + for (var i = 0; i < progIDs.length; i++) { + try { + return new ActiveXObject(progIDs[i]); + } catch (ex) {} + } + })(); + } + } + + // @credits Sergey Ilinsky (http://www.ilinsky.com/) + function _getDocument(xhr) { + var rXML = xhr.responseXML; + var rText = xhr.responseText; + + // Try parsing responseText (@see: http://www.ilinsky.com/articles/XMLHttpRequest/#bugs-ie-responseXML-content-type) + if (Env.browser === 'IE' && rText && rXML && !rXML.documentElement && /[^\/]+\/[^\+]+\+xml/.test(xhr.getResponseHeader("Content-Type"))) { + rXML = new window.ActiveXObject("Microsoft.XMLDOM"); + rXML.async = false; + rXML.validateOnParse = false; + rXML.loadXML(rText); + } + + // Check if there is no error in document + if (rXML) { + if ((Env.browser === 'IE' && rXML.parseError !== 0) || !rXML.documentElement || rXML.documentElement.tagName === "parsererror") { + return null; + } + } + return rXML; + } + + + function _prepareMultipart(fd) { + var boundary = '----moxieboundary' + new Date().getTime() + , dashdash = '--' + , crlf = '\r\n' + , multipart = '' + , I = this.getRuntime() + ; + + if (!I.can('send_binary_string')) { + throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); + } + + _xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary); + + // append multipart parameters + fd.each(function(value, name) { + // Firefox 3.6 failed to convert multibyte characters to UTF-8 in sendAsBinary(), + // so we try it here ourselves with: unescape(encodeURIComponent(value)) + if (value instanceof Blob) { + // Build RFC2388 blob + multipart += dashdash + boundary + crlf + + 'Content-Disposition: form-data; name="' + name + '"; filename="' + unescape(encodeURIComponent(value.name || 'blob')) + '"' + crlf + + 'Content-Type: ' + (value.type || 'application/octet-stream') + crlf + crlf + + value.getSource() + crlf; + } else { + multipart += dashdash + boundary + crlf + + 'Content-Disposition: form-data; name="' + name + '"' + crlf + crlf + + unescape(encodeURIComponent(value)) + crlf; + } + }); + + multipart += dashdash + boundary + dashdash + crlf; + + return multipart; + } + } + + return (extensions.XMLHttpRequest = XMLHttpRequest); +}); + +// Included from: src/javascript/runtime/html5/utils/BinaryReader.js + +/** + * BinaryReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/utils/BinaryReader +@private +*/ +define("moxie/runtime/html5/utils/BinaryReader", [ + "moxie/core/utils/Basic" +], function(Basic) { + + + function BinaryReader(data) { + if (data instanceof ArrayBuffer) { + ArrayBufferReader.apply(this, arguments); + } else { + UTF16StringReader.apply(this, arguments); + } + } +   + + Basic.extend(BinaryReader.prototype, { + + littleEndian: false, + + + read: function(idx, size) { + var sum, mv, i; + + if (idx + size > this.length()) { + throw new Error("You are trying to read outside the source boundaries."); + } + + mv = this.littleEndian + ? 0 + : -8 * (size - 1) + ; + + for (i = 0, sum = 0; i < size; i++) { + sum |= (this.readByteAt(idx + i) << Math.abs(mv + i*8)); + } + return sum; + }, + + + write: function(idx, num, size) { + var mv, i, str = ''; + + if (idx > this.length()) { + throw new Error("You are trying to write outside the source boundaries."); + } + + mv = this.littleEndian + ? 0 + : -8 * (size - 1) + ; + + for (i = 0; i < size; i++) { + this.writeByteAt(idx + i, (num >> Math.abs(mv + i*8)) & 255); + } + }, + + + BYTE: function(idx) { + return this.read(idx, 1); + }, + + + SHORT: function(idx) { + return this.read(idx, 2); + }, + + + LONG: function(idx) { + return this.read(idx, 4); + }, + + + SLONG: function(idx) { // 2's complement notation + var num = this.read(idx, 4); + return (num > 2147483647 ? num - 4294967296 : num); + }, + + + CHAR: function(idx) { + return String.fromCharCode(this.read(idx, 1)); + }, + + + STRING: function(idx, count) { + return this.asArray('CHAR', idx, count).join(''); + }, + + + asArray: function(type, idx, count) { + var values = []; + + for (var i = 0; i < count; i++) { + values[i] = this[type](idx + i); + } + return values; + } + }); + + + function ArrayBufferReader(data) { + var _dv = new DataView(data); + + Basic.extend(this, { + + readByteAt: function(idx) { + return _dv.getUint8(idx); + }, + + + writeByteAt: function(idx, value) { + _dv.setUint8(idx, value); + }, + + + SEGMENT: function(idx, size, value) { + switch (arguments.length) { + case 2: + return data.slice(idx, idx + size); + + case 1: + return data.slice(idx); + + case 3: + if (value === null) { + value = new ArrayBuffer(); + } + + if (value instanceof ArrayBuffer) { + var arr = new Uint8Array(this.length() - size + value.byteLength); + if (idx > 0) { + arr.set(new Uint8Array(data.slice(0, idx)), 0); + } + arr.set(new Uint8Array(value), idx); + arr.set(new Uint8Array(data.slice(idx + size)), idx + value.byteLength); + + this.clear(); + data = arr.buffer; + _dv = new DataView(data); + break; + } + + default: return data; + } + }, + + + length: function() { + return data ? data.byteLength : 0; + }, + + + clear: function() { + _dv = data = null; + } + }); + } + + + function UTF16StringReader(data) { + Basic.extend(this, { + + readByteAt: function(idx) { + return data.charCodeAt(idx); + }, + + + writeByteAt: function(idx, value) { + putstr(String.fromCharCode(value), idx, 1); + }, + + + SEGMENT: function(idx, length, segment) { + switch (arguments.length) { + case 1: + return data.substr(idx); + case 2: + return data.substr(idx, length); + case 3: + putstr(segment !== null ? segment : '', idx, length); + break; + default: return data; + } + }, + + + length: function() { + return data ? data.length : 0; + }, + + clear: function() { + data = null; + } + }); + + + function putstr(segment, idx, length) { + length = arguments.length === 3 ? length : data.length - idx - 1; + data = data.substr(0, idx) + segment + data.substr(length + idx); + } + } + + + return BinaryReader; +}); + +// Included from: src/javascript/runtime/html5/image/JPEGHeaders.js + +/** + * JPEGHeaders.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/JPEGHeaders +@private +*/ +define("moxie/runtime/html5/image/JPEGHeaders", [ + "moxie/runtime/html5/utils/BinaryReader", + "moxie/core/Exceptions" +], function(BinaryReader, x) { + + return function JPEGHeaders(data) { + var headers = [], _br, idx, marker, length = 0; + + _br = new BinaryReader(data); + + // Check if data is jpeg + if (_br.SHORT(0) !== 0xFFD8) { + _br.clear(); + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + + idx = 2; + + while (idx <= _br.length()) { + marker = _br.SHORT(idx); + + // omit RST (restart) markers + if (marker >= 0xFFD0 && marker <= 0xFFD7) { + idx += 2; + continue; + } + + // no headers allowed after SOS marker + if (marker === 0xFFDA || marker === 0xFFD9) { + break; + } + + length = _br.SHORT(idx + 2) + 2; + + // APPn marker detected + if (marker >= 0xFFE1 && marker <= 0xFFEF) { + headers.push({ + hex: marker, + name: 'APP' + (marker & 0x000F), + start: idx, + length: length, + segment: _br.SEGMENT(idx, length) + }); + } + + idx += length; + } + + _br.clear(); + + return { + headers: headers, + + restore: function(data) { + var max, i, br; + + br = new BinaryReader(data); + + idx = br.SHORT(2) == 0xFFE0 ? 4 + br.SHORT(4) : 2; + + for (i = 0, max = headers.length; i < max; i++) { + br.SEGMENT(idx, 0, headers[i].segment); + idx += headers[i].length; + } + + data = br.SEGMENT(); + br.clear(); + return data; + }, + + strip: function(data) { + var br, headers, jpegHeaders, i; + + jpegHeaders = new JPEGHeaders(data); + headers = jpegHeaders.headers; + jpegHeaders.purge(); + + br = new BinaryReader(data); + + i = headers.length; + while (i--) { + br.SEGMENT(headers[i].start, headers[i].length, ''); + } + + data = br.SEGMENT(); + br.clear(); + return data; + }, + + get: function(name) { + var array = []; + + for (var i = 0, max = headers.length; i < max; i++) { + if (headers[i].name === name.toUpperCase()) { + array.push(headers[i].segment); + } + } + return array; + }, + + set: function(name, segment) { + var array = [], i, ii, max; + + if (typeof(segment) === 'string') { + array.push(segment); + } else { + array = segment; + } + + for (i = ii = 0, max = headers.length; i < max; i++) { + if (headers[i].name === name.toUpperCase()) { + headers[i].segment = array[ii]; + headers[i].length = array[ii].length; + ii++; + } + if (ii >= array.length) { + break; + } + } + }, + + purge: function() { + this.headers = headers = []; + } + }; + }; +}); + +// Included from: src/javascript/runtime/html5/image/ExifParser.js + +/** + * ExifParser.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/ExifParser +@private +*/ +define("moxie/runtime/html5/image/ExifParser", [ + "moxie/core/utils/Basic", + "moxie/runtime/html5/utils/BinaryReader", + "moxie/core/Exceptions" +], function(Basic, BinaryReader, x) { + + function ExifParser(data) { + var __super__, tags, tagDescs, offsets, idx, Tiff; + + BinaryReader.call(this, data); + + tags = { + tiff: { + /* + The image orientation viewed in terms of rows and columns. + + 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side. + 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side. + 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side. + 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side. + 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top. + 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top. + 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom. + 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom. + */ + 0x0112: 'Orientation', + 0x010E: 'ImageDescription', + 0x010F: 'Make', + 0x0110: 'Model', + 0x0131: 'Software', + 0x8769: 'ExifIFDPointer', + 0x8825: 'GPSInfoIFDPointer' + }, + exif: { + 0x9000: 'ExifVersion', + 0xA001: 'ColorSpace', + 0xA002: 'PixelXDimension', + 0xA003: 'PixelYDimension', + 0x9003: 'DateTimeOriginal', + 0x829A: 'ExposureTime', + 0x829D: 'FNumber', + 0x8827: 'ISOSpeedRatings', + 0x9201: 'ShutterSpeedValue', + 0x9202: 'ApertureValue' , + 0x9207: 'MeteringMode', + 0x9208: 'LightSource', + 0x9209: 'Flash', + 0x920A: 'FocalLength', + 0xA402: 'ExposureMode', + 0xA403: 'WhiteBalance', + 0xA406: 'SceneCaptureType', + 0xA404: 'DigitalZoomRatio', + 0xA408: 'Contrast', + 0xA409: 'Saturation', + 0xA40A: 'Sharpness' + }, + gps: { + 0x0000: 'GPSVersionID', + 0x0001: 'GPSLatitudeRef', + 0x0002: 'GPSLatitude', + 0x0003: 'GPSLongitudeRef', + 0x0004: 'GPSLongitude' + }, + + thumb: { + 0x0201: 'JPEGInterchangeFormat', + 0x0202: 'JPEGInterchangeFormatLength' + } + }; + + tagDescs = { + 'ColorSpace': { + 1: 'sRGB', + 0: 'Uncalibrated' + }, + + 'MeteringMode': { + 0: 'Unknown', + 1: 'Average', + 2: 'CenterWeightedAverage', + 3: 'Spot', + 4: 'MultiSpot', + 5: 'Pattern', + 6: 'Partial', + 255: 'Other' + }, + + 'LightSource': { + 1: 'Daylight', + 2: 'Fliorescent', + 3: 'Tungsten', + 4: 'Flash', + 9: 'Fine weather', + 10: 'Cloudy weather', + 11: 'Shade', + 12: 'Daylight fluorescent (D 5700 - 7100K)', + 13: 'Day white fluorescent (N 4600 -5400K)', + 14: 'Cool white fluorescent (W 3900 - 4500K)', + 15: 'White fluorescent (WW 3200 - 3700K)', + 17: 'Standard light A', + 18: 'Standard light B', + 19: 'Standard light C', + 20: 'D55', + 21: 'D65', + 22: 'D75', + 23: 'D50', + 24: 'ISO studio tungsten', + 255: 'Other' + }, + + 'Flash': { + 0x0000: 'Flash did not fire', + 0x0001: 'Flash fired', + 0x0005: 'Strobe return light not detected', + 0x0007: 'Strobe return light detected', + 0x0009: 'Flash fired, compulsory flash mode', + 0x000D: 'Flash fired, compulsory flash mode, return light not detected', + 0x000F: 'Flash fired, compulsory flash mode, return light detected', + 0x0010: 'Flash did not fire, compulsory flash mode', + 0x0018: 'Flash did not fire, auto mode', + 0x0019: 'Flash fired, auto mode', + 0x001D: 'Flash fired, auto mode, return light not detected', + 0x001F: 'Flash fired, auto mode, return light detected', + 0x0020: 'No flash function', + 0x0041: 'Flash fired, red-eye reduction mode', + 0x0045: 'Flash fired, red-eye reduction mode, return light not detected', + 0x0047: 'Flash fired, red-eye reduction mode, return light detected', + 0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode', + 0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected', + 0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected', + 0x0059: 'Flash fired, auto mode, red-eye reduction mode', + 0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode', + 0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode' + }, + + 'ExposureMode': { + 0: 'Auto exposure', + 1: 'Manual exposure', + 2: 'Auto bracket' + }, + + 'WhiteBalance': { + 0: 'Auto white balance', + 1: 'Manual white balance' + }, + + 'SceneCaptureType': { + 0: 'Standard', + 1: 'Landscape', + 2: 'Portrait', + 3: 'Night scene' + }, + + 'Contrast': { + 0: 'Normal', + 1: 'Soft', + 2: 'Hard' + }, + + 'Saturation': { + 0: 'Normal', + 1: 'Low saturation', + 2: 'High saturation' + }, + + 'Sharpness': { + 0: 'Normal', + 1: 'Soft', + 2: 'Hard' + }, + + // GPS related + 'GPSLatitudeRef': { + N: 'North latitude', + S: 'South latitude' + }, + + 'GPSLongitudeRef': { + E: 'East longitude', + W: 'West longitude' + } + }; + + offsets = { + tiffHeader: 10 + }; + + idx = offsets.tiffHeader; + + __super__ = { + clear: this.clear + }; + + // Public functions + Basic.extend(this, { + + read: function() { + try { + return ExifParser.prototype.read.apply(this, arguments); + } catch (ex) { + throw new x.ImageError(x.ImageError.INVALID_META_ERR); + } + }, + + + write: function() { + try { + return ExifParser.prototype.write.apply(this, arguments); + } catch (ex) { + throw new x.ImageError(x.ImageError.INVALID_META_ERR); + } + }, + + + UNDEFINED: function() { + return this.BYTE.apply(this, arguments); + }, + + + RATIONAL: function(idx) { + return this.LONG(idx) / this.LONG(idx + 4) + }, + + + SRATIONAL: function(idx) { + return this.SLONG(idx) / this.SLONG(idx + 4) + }, + + ASCII: function(idx) { + return this.CHAR(idx); + }, + + TIFF: function() { + return Tiff || null; + }, + + + EXIF: function() { + var Exif = null; + + if (offsets.exifIFD) { + try { + Exif = extractTags.call(this, offsets.exifIFD, tags.exif); + } catch(ex) { + return null; + } + + // Fix formatting of some tags + if (Exif.ExifVersion && Basic.typeOf(Exif.ExifVersion) === 'array') { + for (var i = 0, exifVersion = ''; i < Exif.ExifVersion.length; i++) { + exifVersion += String.fromCharCode(Exif.ExifVersion[i]); + } + Exif.ExifVersion = exifVersion; + } + } + + return Exif; + }, + + + GPS: function() { + var GPS = null; + + if (offsets.gpsIFD) { + try { + GPS = extractTags.call(this, offsets.gpsIFD, tags.gps); + } catch (ex) { + return null; + } + + // iOS devices (and probably some others) do not put in GPSVersionID tag (why?..) + if (GPS.GPSVersionID && Basic.typeOf(GPS.GPSVersionID) === 'array') { + GPS.GPSVersionID = GPS.GPSVersionID.join('.'); + } + } + + return GPS; + }, + + + thumb: function() { + if (offsets.IFD1) { + try { + var IFD1Tags = extractTags.call(this, offsets.IFD1, tags.thumb); + + if ('JPEGInterchangeFormat' in IFD1Tags) { + return this.SEGMENT(offsets.tiffHeader + IFD1Tags.JPEGInterchangeFormat, IFD1Tags.JPEGInterchangeFormatLength); + } + } catch (ex) {} + } + return null; + }, + + + setExif: function(tag, value) { + // Right now only setting of width/height is possible + if (tag !== 'PixelXDimension' && tag !== 'PixelYDimension') { return false; } + + return setTag.call(this, 'exif', tag, value); + }, + + + clear: function() { + __super__.clear(); + data = tags = tagDescs = Tiff = offsets = __super__ = null; + } + }); + + + // Check if that's APP1 and that it has EXIF + if (this.SHORT(0) !== 0xFFE1 || this.STRING(4, 5).toUpperCase() !== "EXIF\0") { + throw new x.ImageError(x.ImageError.INVALID_META_ERR); + } + + // Set read order of multi-byte data + this.littleEndian = (this.SHORT(idx) == 0x4949); + + // Check if always present bytes are indeed present + if (this.SHORT(idx+=2) !== 0x002A) { + throw new x.ImageError(x.ImageError.INVALID_META_ERR); + } + + offsets.IFD0 = offsets.tiffHeader + this.LONG(idx += 2); + Tiff = extractTags.call(this, offsets.IFD0, tags.tiff); + + if ('ExifIFDPointer' in Tiff) { + offsets.exifIFD = offsets.tiffHeader + Tiff.ExifIFDPointer; + delete Tiff.ExifIFDPointer; + } + + if ('GPSInfoIFDPointer' in Tiff) { + offsets.gpsIFD = offsets.tiffHeader + Tiff.GPSInfoIFDPointer; + delete Tiff.GPSInfoIFDPointer; + } + + if (Basic.isEmptyObj(Tiff)) { + Tiff = null; + } + + // check if we have a thumb as well + var IFD1Offset = this.LONG(offsets.IFD0 + this.SHORT(offsets.IFD0) * 12 + 2); + if (IFD1Offset) { + offsets.IFD1 = offsets.tiffHeader + IFD1Offset; + } + + + function extractTags(IFD_offset, tags2extract) { + var data = this; + var length, i, tag, type, count, size, offset, value, values = [], hash = {}; + + var types = { + 1 : 'BYTE', + 7 : 'UNDEFINED', + 2 : 'ASCII', + 3 : 'SHORT', + 4 : 'LONG', + 5 : 'RATIONAL', + 9 : 'SLONG', + 10: 'SRATIONAL' + }; + + var sizes = { + 'BYTE' : 1, + 'UNDEFINED' : 1, + 'ASCII' : 1, + 'SHORT' : 2, + 'LONG' : 4, + 'RATIONAL' : 8, + 'SLONG' : 4, + 'SRATIONAL' : 8 + }; + + length = data.SHORT(IFD_offset); + + // The size of APP1 including all these elements shall not exceed the 64 Kbytes specified in the JPEG standard. + + for (i = 0; i < length; i++) { + values = []; + + // Set binary reader pointer to beginning of the next tag + offset = IFD_offset + 2 + i*12; + + tag = tags2extract[data.SHORT(offset)]; + + if (tag === undefined) { + continue; // Not the tag we requested + } + + type = types[data.SHORT(offset+=2)]; + count = data.LONG(offset+=2); + size = sizes[type]; + + if (!size) { + throw new x.ImageError(x.ImageError.INVALID_META_ERR); + } + + offset += 4; + + // tag can only fit 4 bytes of data, if data is larger we should look outside + if (size * count > 4) { + // instead of data tag contains an offset of the data + offset = data.LONG(offset) + offsets.tiffHeader; + } + + // in case we left the boundaries of data throw an early exception + if (offset + size * count >= this.length()) { + throw new x.ImageError(x.ImageError.INVALID_META_ERR); + } + + // special care for the string + if (type === 'ASCII') { + hash[tag] = Basic.trim(data.STRING(offset, count).replace(/\0$/, '')); // strip trailing NULL + continue; + } else { + values = data.asArray(type, offset, count); + value = (count == 1 ? values[0] : values); + + if (tagDescs.hasOwnProperty(tag) && typeof value != 'object') { + hash[tag] = tagDescs[tag][value]; + } else { + hash[tag] = value; + } + } + } + + return hash; + } + + // At the moment only setting of simple (LONG) values, that do not require offset recalculation, is supported + function setTag(ifd, tag, value) { + var offset, length, tagOffset, valueOffset = 0; + + // If tag name passed translate into hex key + if (typeof(tag) === 'string') { + var tmpTags = tags[ifd.toLowerCase()]; + for (var hex in tmpTags) { + if (tmpTags[hex] === tag) { + tag = hex; + break; + } + } + } + offset = offsets[ifd.toLowerCase() + 'IFD']; + length = this.SHORT(offset); + + for (var i = 0; i < length; i++) { + tagOffset = offset + 12 * i + 2; + + if (this.SHORT(tagOffset) == tag) { + valueOffset = tagOffset + 8; + break; + } + } + + if (!valueOffset) { + return false; + } + + try { + this.write(valueOffset, value, 4); + } catch(ex) { + return false; + } + + return true; + } + } + + ExifParser.prototype = BinaryReader.prototype; + + return ExifParser; +}); + +// Included from: src/javascript/runtime/html5/image/JPEG.js + +/** + * JPEG.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/JPEG +@private +*/ +define("moxie/runtime/html5/image/JPEG", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/runtime/html5/image/JPEGHeaders", + "moxie/runtime/html5/utils/BinaryReader", + "moxie/runtime/html5/image/ExifParser" +], function(Basic, x, JPEGHeaders, BinaryReader, ExifParser) { + + function JPEG(data) { + var _br, _hm, _ep, _info; + + _br = new BinaryReader(data); + + // check if it is jpeg + if (_br.SHORT(0) !== 0xFFD8) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + + // backup headers + _hm = new JPEGHeaders(data); + + // extract exif info + try { + _ep = new ExifParser(_hm.get('app1')[0]); + } catch(ex) {} + + // get dimensions + _info = _getDimensions.call(this); + + Basic.extend(this, { + type: 'image/jpeg', + + size: _br.length(), + + width: _info && _info.width || 0, + + height: _info && _info.height || 0, + + setExif: function(tag, value) { + if (!_ep) { + return false; // or throw an exception + } + + if (Basic.typeOf(tag) === 'object') { + Basic.each(tag, function(value, tag) { + _ep.setExif(tag, value); + }); + } else { + _ep.setExif(tag, value); + } + + // update internal headers + _hm.set('app1', _ep.SEGMENT()); + }, + + writeHeaders: function() { + if (!arguments.length) { + // if no arguments passed, update headers internally + return _hm.restore(data); + } + return _hm.restore(arguments[0]); + }, + + stripHeaders: function(data) { + return _hm.strip(data); + }, + + purge: function() { + _purge.call(this); + } + }); + + if (_ep) { + this.meta = { + tiff: _ep.TIFF(), + exif: _ep.EXIF(), + gps: _ep.GPS(), + thumb: _getThumb() + }; + } + + + function _getDimensions(br) { + var idx = 0 + , marker + , length + ; + + if (!br) { + br = _br; + } + + // examine all through the end, since some images might have very large APP segments + while (idx <= br.length()) { + marker = br.SHORT(idx += 2); + + if (marker >= 0xFFC0 && marker <= 0xFFC3) { // SOFn + idx += 5; // marker (2 bytes) + length (2 bytes) + Sample precision (1 byte) + return { + height: br.SHORT(idx), + width: br.SHORT(idx += 2) + }; + } + length = br.SHORT(idx += 2); + idx += length - 2; + } + return null; + } + + + function _getThumb() { + var data = _ep.thumb() + , br + , info + ; + + if (data) { + br = new BinaryReader(data); + info = _getDimensions(br); + br.clear(); + + if (info) { + info.data = data; + return info; + } + } + return null; + } + + + function _purge() { + if (!_ep || !_hm || !_br) { + return; // ignore any repeating purge requests + } + _ep.clear(); + _hm.purge(); + _br.clear(); + _info = _hm = _ep = _br = null; + } + } + + return JPEG; +}); + +// Included from: src/javascript/runtime/html5/image/PNG.js + +/** + * PNG.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/PNG +@private +*/ +define("moxie/runtime/html5/image/PNG", [ + "moxie/core/Exceptions", + "moxie/core/utils/Basic", + "moxie/runtime/html5/utils/BinaryReader" +], function(x, Basic, BinaryReader) { + + function PNG(data) { + var _br, _hm, _ep, _info; + + _br = new BinaryReader(data); + + // check if it's png + (function() { + var idx = 0, i = 0 + , signature = [0x8950, 0x4E47, 0x0D0A, 0x1A0A] + ; + + for (i = 0; i < signature.length; i++, idx += 2) { + if (signature[i] != _br.SHORT(idx)) { + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + } + } + }()); + + function _getDimensions() { + var chunk, idx; + + chunk = _getChunkAt.call(this, 8); + + if (chunk.type == 'IHDR') { + idx = chunk.start; + return { + width: _br.LONG(idx), + height: _br.LONG(idx += 4) + }; + } + return null; + } + + function _purge() { + if (!_br) { + return; // ignore any repeating purge requests + } + _br.clear(); + data = _info = _hm = _ep = _br = null; + } + + _info = _getDimensions.call(this); + + Basic.extend(this, { + type: 'image/png', + + size: _br.length(), + + width: _info.width, + + height: _info.height, + + purge: function() { + _purge.call(this); + } + }); + + // for PNG we can safely trigger purge automatically, as we do not keep any data for later + _purge.call(this); + + function _getChunkAt(idx) { + var length, type, start, CRC; + + length = _br.LONG(idx); + type = _br.STRING(idx += 4, 4); + start = idx += 4; + CRC = _br.LONG(idx + length); + + return { + length: length, + type: type, + start: start, + CRC: CRC + }; + } + } + + return PNG; +}); + +// Included from: src/javascript/runtime/html5/image/ImageInfo.js + +/** + * ImageInfo.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/ImageInfo +@private +*/ +define("moxie/runtime/html5/image/ImageInfo", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/runtime/html5/image/JPEG", + "moxie/runtime/html5/image/PNG" +], function(Basic, x, JPEG, PNG) { + /** + Optional image investigation tool for HTML5 runtime. Provides the following features: + - ability to distinguish image type (JPEG or PNG) by signature + - ability to extract image width/height directly from it's internals, without preloading in memory (fast) + - ability to extract APP headers from JPEGs (Exif, GPS, etc) + - ability to replace width/height tags in extracted JPEG headers + - ability to restore APP headers, that were for example stripped during image manipulation + + @class ImageInfo + @constructor + @param {String} data Image source as binary string + */ + return function(data) { + var _cs = [JPEG, PNG], _img; + + // figure out the format, throw: ImageError.WRONG_FORMAT if not supported + _img = (function() { + for (var i = 0; i < _cs.length; i++) { + try { + return new _cs[i](data); + } catch (ex) { + // console.info(ex); + } + } + throw new x.ImageError(x.ImageError.WRONG_FORMAT); + }()); + + Basic.extend(this, { + /** + Image Mime Type extracted from it's depths + + @property type + @type {String} + @default '' + */ + type: '', + + /** + Image size in bytes + + @property size + @type {Number} + @default 0 + */ + size: 0, + + /** + Image width extracted from image source + + @property width + @type {Number} + @default 0 + */ + width: 0, + + /** + Image height extracted from image source + + @property height + @type {Number} + @default 0 + */ + height: 0, + + /** + Sets Exif tag. Currently applicable only for width and height tags. Obviously works only with JPEGs. + + @method setExif + @param {String} tag Tag to set + @param {Mixed} value Value to assign to the tag + */ + setExif: function() {}, + + /** + Restores headers to the source. + + @method writeHeaders + @param {String} data Image source as binary string + @return {String} Updated binary string + */ + writeHeaders: function(data) { + return data; + }, + + /** + Strip all headers from the source. + + @method stripHeaders + @param {String} data Image source as binary string + @return {String} Updated binary string + */ + stripHeaders: function(data) { + return data; + }, + + /** + Dispose resources. + + @method purge + */ + purge: function() { + data = null; + } + }); + + Basic.extend(this, _img); + + this.purge = function() { + _img.purge(); + _img = null; + }; + }; +}); + +// Included from: src/javascript/runtime/html5/image/MegaPixel.js + +/** +(The MIT License) + +Copyright (c) 2012 Shinichi Tomita ; + +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. +*/ + +/** + * Mega pixel image rendering library for iOS6 Safari + * + * Fixes iOS6 Safari's image file rendering issue for large size image (over mega-pixel), + * which causes unexpected subsampling when drawing it in canvas. + * By using this library, you can safely render the image with proper stretching. + * + * Copyright (c) 2012 Shinichi Tomita + * Released under the MIT license + */ + +/** +@class moxie/runtime/html5/image/MegaPixel +@private +*/ +define("moxie/runtime/html5/image/MegaPixel", [], function() { + + /** + * Rendering image element (with resizing) into the canvas element + */ + function renderImageToCanvas(img, canvas, options) { + var iw = img.naturalWidth, ih = img.naturalHeight; + var width = options.width, height = options.height; + var x = options.x || 0, y = options.y || 0; + var ctx = canvas.getContext('2d'); + if (detectSubsampling(img)) { + iw /= 2; + ih /= 2; + } + var d = 1024; // size of tiling canvas + var tmpCanvas = document.createElement('canvas'); + tmpCanvas.width = tmpCanvas.height = d; + var tmpCtx = tmpCanvas.getContext('2d'); + var vertSquashRatio = detectVerticalSquash(img, iw, ih); + var sy = 0; + while (sy < ih) { + var sh = sy + d > ih ? ih - sy : d; + var sx = 0; + while (sx < iw) { + var sw = sx + d > iw ? iw - sx : d; + tmpCtx.clearRect(0, 0, d, d); + tmpCtx.drawImage(img, -sx, -sy); + var dx = (sx * width / iw + x) << 0; + var dw = Math.ceil(sw * width / iw); + var dy = (sy * height / ih / vertSquashRatio + y) << 0; + var dh = Math.ceil(sh * height / ih / vertSquashRatio); + ctx.drawImage(tmpCanvas, 0, 0, sw, sh, dx, dy, dw, dh); + sx += d; + } + sy += d; + } + tmpCanvas = tmpCtx = null; + } + + /** + * Detect subsampling in loaded image. + * In iOS, larger images than 2M pixels may be subsampled in rendering. + */ + function detectSubsampling(img) { + var iw = img.naturalWidth, ih = img.naturalHeight; + if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = 1; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, -iw + 1, 0); + // subsampled image becomes half smaller in rendering size. + // check alpha channel value to confirm image is covering edge pixel or not. + // if alpha value is 0 image is not covering, hence subsampled. + return ctx.getImageData(0, 0, 1, 1).data[3] === 0; + } else { + return false; + } + } + + + /** + * Detecting vertical squash in loaded image. + * Fixes a bug which squash image vertically while drawing into canvas for some images. + */ + function detectVerticalSquash(img, iw, ih) { + var canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = ih; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + var data = ctx.getImageData(0, 0, 1, ih).data; + // search image edge pixel position in case it is squashed vertically. + var sy = 0; + var ey = ih; + var py = ih; + while (py > sy) { + var alpha = data[(py - 1) * 4 + 3]; + if (alpha === 0) { + ey = py; + } else { + sy = py; + } + py = (ey + sy) >> 1; + } + canvas = null; + var ratio = (py / ih); + return (ratio === 0) ? 1 : ratio; + } + + return { + isSubsampled: detectSubsampling, + renderTo: renderImageToCanvas + }; +}); + +// Included from: src/javascript/runtime/html5/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html5/image/Image +@private +*/ +define("moxie/runtime/html5/image/Image", [ + "moxie/runtime/html5/Runtime", + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/core/utils/Encode", + "moxie/file/Blob", + "moxie/file/File", + "moxie/runtime/html5/image/ImageInfo", + "moxie/runtime/html5/image/MegaPixel", + "moxie/core/utils/Mime", + "moxie/core/utils/Env" +], function(extensions, Basic, x, Encode, Blob, File, ImageInfo, MegaPixel, Mime, Env) { + + function HTML5Image() { + var me = this + , _img, _imgInfo, _canvas, _binStr, _blob + , _modified = false // is set true whenever image is modified + , _preserveHeaders = true + ; + + Basic.extend(this, { + loadFromBlob: function(blob) { + var comp = this, I = comp.getRuntime() + , asBinary = arguments.length > 1 ? arguments[1] : true + ; + + if (!I.can('access_binary')) { + throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); + } + + _blob = blob; + + if (blob.isDetached()) { + _binStr = blob.getSource(); + _preload.call(this, _binStr); + return; + } else { + _readAsDataUrl.call(this, blob.getSource(), function(dataUrl) { + if (asBinary) { + _binStr = _toBinary(dataUrl); + } + _preload.call(comp, dataUrl); + }); + } + }, + + loadFromImage: function(img, exact) { + this.meta = img.meta; + + _blob = new File(null, { + name: img.name, + size: img.size, + type: img.type + }); + + _preload.call(this, exact ? (_binStr = img.getAsBinaryString()) : img.getAsDataURL()); + }, + + getInfo: function() { + var I = this.getRuntime(), info; + + if (!_imgInfo && _binStr && I.can('access_image_binary')) { + _imgInfo = new ImageInfo(_binStr); + } + + info = { + width: _getImg().width || 0, + height: _getImg().height || 0, + type: _blob.type || Mime.getFileMime(_blob.name), + size: _binStr && _binStr.length || _blob.size || 0, + name: _blob.name || '', + meta: _imgInfo && _imgInfo.meta || this.meta || {} + }; + + // store thumbnail data as blob + if (info.meta && info.meta.thumb && !(info.meta.thumb.data instanceof Blob)) { + info.meta.thumb.data = new Blob(null, { + type: 'image/jpeg', + data: info.meta.thumb.data + }); + } + + return info; + }, + + downsize: function() { + _downsize.apply(this, arguments); + }, + + getAsCanvas: function() { + if (_canvas) { + _canvas.id = this.uid + '_canvas'; + } + return _canvas; + }, + + getAsBlob: function(type, quality) { + if (type !== this.type) { + // if different mime type requested prepare image for conversion + _downsize.call(this, this.width, this.height, false); + } + return new File(null, { + name: _blob.name || '', + type: type, + data: me.getAsBinaryString.call(this, type, quality) + }); + }, + + getAsDataURL: function(type) { + var quality = arguments[1] || 90; + + // if image has not been modified, return the source right away + if (!_modified) { + return _img.src; + } + + if ('image/jpeg' !== type) { + return _canvas.toDataURL('image/png'); + } else { + try { + // older Geckos used to result in an exception on quality argument + return _canvas.toDataURL('image/jpeg', quality/100); + } catch (ex) { + return _canvas.toDataURL('image/jpeg'); + } + } + }, + + getAsBinaryString: function(type, quality) { + // if image has not been modified, return the source right away + if (!_modified) { + // if image was not loaded from binary string + if (!_binStr) { + _binStr = _toBinary(me.getAsDataURL(type, quality)); + } + return _binStr; + } + + if ('image/jpeg' !== type) { + _binStr = _toBinary(me.getAsDataURL(type, quality)); + } else { + var dataUrl; + + // if jpeg + if (!quality) { + quality = 90; + } + + try { + // older Geckos used to result in an exception on quality argument + dataUrl = _canvas.toDataURL('image/jpeg', quality/100); + } catch (ex) { + dataUrl = _canvas.toDataURL('image/jpeg'); + } + + _binStr = _toBinary(dataUrl); + + if (_imgInfo) { + _binStr = _imgInfo.stripHeaders(_binStr); + + if (_preserveHeaders) { + // update dimensions info in exif + if (_imgInfo.meta && _imgInfo.meta.exif) { + _imgInfo.setExif({ + PixelXDimension: this.width, + PixelYDimension: this.height + }); + } + + // re-inject the headers + _binStr = _imgInfo.writeHeaders(_binStr); + } + + // will be re-created from fresh on next getInfo call + _imgInfo.purge(); + _imgInfo = null; + } + } + + _modified = false; + + return _binStr; + }, + + destroy: function() { + me = null; + _purge.call(this); + this.getRuntime().getShim().removeInstance(this.uid); + } + }); + + + function _getImg() { + if (!_canvas && !_img) { + throw new x.ImageError(x.DOMException.INVALID_STATE_ERR); + } + return _canvas || _img; + } + + + function _toBinary(str) { + return Encode.atob(str.substring(str.indexOf('base64,') + 7)); + } + + + function _toDataUrl(str, type) { + return 'data:' + (type || '') + ';base64,' + Encode.btoa(str); + } + + + function _preload(str) { + var comp = this; + + _img = new Image(); + _img.onerror = function() { + _purge.call(this); + comp.trigger('error', x.ImageError.WRONG_FORMAT); + }; + _img.onload = function() { + comp.trigger('load'); + }; + + _img.src = str.substr(0, 5) == 'data:' ? str : _toDataUrl(str, _blob.type); + } + + + function _readAsDataUrl(file, callback) { + var comp = this, fr; + + // use FileReader if it's available + if (window.FileReader) { + fr = new FileReader(); + fr.onload = function() { + callback(this.result); + }; + fr.onerror = function() { + comp.trigger('error', x.ImageError.WRONG_FORMAT); + }; + fr.readAsDataURL(file); + } else { + return callback(file.getAsDataURL()); + } + } + + function _downsize(width, height, crop, preserveHeaders) { + var self = this + , scale + , mathFn + , x = 0 + , y = 0 + , img + , destWidth + , destHeight + , orientation + ; + + _preserveHeaders = preserveHeaders; // we will need to check this on export (see getAsBinaryString()) + + // take into account orientation tag + orientation = (this.meta && this.meta.tiff && this.meta.tiff.Orientation) || 1; + + if (Basic.inArray(orientation, [5,6,7,8]) !== -1) { // values that require 90 degree rotation + // swap dimensions + var tmp = width; + width = height; + height = tmp; + } + + img = _getImg(); + + // unify dimensions + if (!crop) { + scale = Math.min(width/img.width, height/img.height); + } else { + // one of the dimensions may exceed the actual image dimensions - we need to take the smallest value + width = Math.min(width, img.width); + height = Math.min(height, img.height); + + scale = Math.max(width/img.width, height/img.height); + } + + // we only downsize here + if (scale > 1 && !crop && preserveHeaders) { + this.trigger('Resize'); + return; + } + + // prepare canvas if necessary + if (!_canvas) { + _canvas = document.createElement("canvas"); + } + + // calculate dimensions of proportionally resized image + destWidth = Math.round(img.width * scale); + destHeight = Math.round(img.height * scale); + + // scale image and canvas + if (crop) { + _canvas.width = width; + _canvas.height = height; + + // if dimensions of the resulting image still larger than canvas, center it + if (destWidth > width) { + x = Math.round((destWidth - width) / 2); + } + + if (destHeight > height) { + y = Math.round((destHeight - height) / 2); + } + } else { + _canvas.width = destWidth; + _canvas.height = destHeight; + } + + // rotate if required, according to orientation tag + if (!_preserveHeaders) { + _rotateToOrientaion(_canvas.width, _canvas.height, orientation); + } + + _drawToCanvas.call(this, img, _canvas, -x, -y, destWidth, destHeight); + + this.width = _canvas.width; + this.height = _canvas.height; + + _modified = true; + self.trigger('Resize'); + } + + + function _drawToCanvas(img, canvas, x, y, w, h) { + if (Env.OS === 'iOS') { + // avoid squish bug in iOS6 + MegaPixel.renderTo(img, canvas, { width: w, height: h, x: x, y: y }); + } else { + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, x, y, w, h); + } + } + + + /** + * Transform canvas coordination according to specified frame size and orientation + * Orientation value is from EXIF tag + * @author Shinichi Tomita + */ + function _rotateToOrientaion(width, height, orientation) { + switch (orientation) { + case 5: + case 6: + case 7: + case 8: + _canvas.width = height; + _canvas.height = width; + break; + default: + _canvas.width = width; + _canvas.height = height; + } + + /** + 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side. + 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side. + 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side. + 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side. + 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top. + 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top. + 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom. + 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom. + */ + + var ctx = _canvas.getContext('2d'); + switch (orientation) { + case 2: + // horizontal flip + ctx.translate(width, 0); + ctx.scale(-1, 1); + break; + case 3: + // 180 rotate left + ctx.translate(width, height); + ctx.rotate(Math.PI); + break; + case 4: + // vertical flip + ctx.translate(0, height); + ctx.scale(1, -1); + break; + case 5: + // vertical flip + 90 rotate right + ctx.rotate(0.5 * Math.PI); + ctx.scale(1, -1); + break; + case 6: + // 90 rotate right + ctx.rotate(0.5 * Math.PI); + ctx.translate(0, -height); + break; + case 7: + // horizontal flip + 90 rotate right + ctx.rotate(0.5 * Math.PI); + ctx.translate(width, -height); + ctx.scale(-1, 1); + break; + case 8: + // 90 rotate left + ctx.rotate(-0.5 * Math.PI); + ctx.translate(-width, 0); + break; + } + } + + + function _purge() { + if (_imgInfo) { + _imgInfo.purge(); + _imgInfo = null; + } + _binStr = _img = _canvas = _blob = null; + _modified = false; + } + } + + return (extensions.Image = HTML5Image); +}); + +// Included from: src/javascript/runtime/flash/Runtime.js + +/** + * Runtime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global ActiveXObject:true */ + +/** +Defines constructor for Flash runtime. + +@class moxie/runtime/flash/Runtime +@private +*/ +define("moxie/runtime/flash/Runtime", [ + "moxie/core/utils/Basic", + "moxie/core/utils/Env", + "moxie/core/utils/Dom", + "moxie/core/Exceptions", + "moxie/runtime/Runtime" +], function(Basic, Env, Dom, x, Runtime) { + + var type = 'flash', extensions = {}; + + /** + Get the version of the Flash Player + + @method getShimVersion + @private + @return {Number} Flash Player version + */ + function getShimVersion() { + var version; + + try { + version = navigator.plugins['Shockwave Flash']; + version = version.description; + } catch (e1) { + try { + version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); + } catch (e2) { + version = '0.0'; + } + } + version = version.match(/\d+/g); + return parseFloat(version[0] + '.' + version[1]); + } + + + /** + Cross-browser SWF removal + - Especially needed to safely and completely remove a SWF in Internet Explorer + + Originated from SWFObject v2.2 + */ + function removeSWF(id) { + var obj = Dom.get(id); + if (obj && obj.nodeName == "OBJECT") { + if (Env.browser === 'IE') { + obj.style.display = "none"; + (function onInit(){ + // http://msdn.microsoft.com/en-us/library/ie/ms534360(v=vs.85).aspx + if (obj.readyState == 4) { + removeObjectInIE(id); + } + else { + setTimeout(onInit, 10); + } + })(); + } + else { + obj.parentNode.removeChild(obj); + } + } + } + + + function removeObjectInIE(id) { + var obj = Dom.get(id); + if (obj) { + for (var i in obj) { + if (typeof obj[i] == "function") { + obj[i] = null; + } + } + obj.parentNode.removeChild(obj); + } + } + + /** + Constructor for the Flash Runtime + + @class FlashRuntime + @extends Runtime + */ + function FlashRuntime(options) { + var I = this, initTimer; + + options = Basic.extend({ swf_url: Env.swf_url }, options); + + Runtime.call(this, options, type, { + access_binary: function(value) { + return value && I.mode === 'browser'; + }, + access_image_binary: function(value) { + return value && I.mode === 'browser'; + }, + display_media: Runtime.capTrue, + do_cors: Runtime.capTrue, + drag_and_drop: false, + report_upload_progress: function() { + return I.mode === 'client'; + }, + resize_image: Runtime.capTrue, + return_response_headers: false, + return_response_type: function(responseType) { + if (responseType === 'json' && !!window.JSON) { + return true; + } + return !Basic.arrayDiff(responseType, ['', 'text', 'document']) || I.mode === 'browser'; + }, + return_status_code: function(code) { + return I.mode === 'browser' || !Basic.arrayDiff(code, [200, 404]); + }, + select_file: Runtime.capTrue, + select_multiple: Runtime.capTrue, + send_binary_string: function(value) { + return value && I.mode === 'browser'; + }, + send_browser_cookies: function(value) { + return value && I.mode === 'browser'; + }, + send_custom_headers: function(value) { + return value && I.mode === 'browser'; + }, + send_multipart: Runtime.capTrue, + slice_blob: function(value) { + return value && I.mode === 'browser'; + }, + stream_upload: function(value) { + return value && I.mode === 'browser'; + }, + summon_file_dialog: false, + upload_filesize: function(size) { + return Basic.parseSizeStr(size) <= 2097152 || I.mode === 'client'; + }, + use_http_method: function(methods) { + return !Basic.arrayDiff(methods, ['GET', 'POST']); + } + }, { + // capabilities that require specific mode + access_binary: function(value) { + return value ? 'browser' : 'client'; + }, + access_image_binary: function(value) { + return value ? 'browser' : 'client'; + }, + report_upload_progress: function(value) { + return value ? 'browser' : 'client'; + }, + return_response_type: function(responseType) { + return Basic.arrayDiff(responseType, ['', 'text', 'json', 'document']) ? 'browser' : ['client', 'browser']; + }, + return_status_code: function(code) { + return Basic.arrayDiff(code, [200, 404]) ? 'browser' : ['client', 'browser']; + }, + send_binary_string: function(value) { + return value ? 'browser' : 'client'; + }, + send_browser_cookies: function(value) { + return value ? 'browser' : 'client'; + }, + send_custom_headers: function(value) { + return value ? 'browser' : 'client'; + }, + stream_upload: function(value) { + return value ? 'client' : 'browser'; + }, + upload_filesize: function(size) { + return Basic.parseSizeStr(size) >= 2097152 ? 'client' : 'browser'; + } + }, 'client'); + + + // minimal requirement for Flash Player version + if (getShimVersion() < 10) { + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("\tFlash didn't meet minimal version requirement (10)."); + } + + this.mode = false; // with falsy mode, runtime won't operable, no matter what the mode was before + } + + + Basic.extend(this, { + + getShim: function() { + return Dom.get(this.uid); + }, + + shimExec: function(component, action) { + var args = [].slice.call(arguments, 2); + return I.getShim().exec(this.uid, component, action, args); + }, + + init: function() { + var html, el, container; + + container = this.getShimContainer(); + + // if not the minimal height, shims are not initialized in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc) + Basic.extend(container.style, { + position: 'absolute', + top: '-8px', + left: '-8px', + width: '9px', + height: '9px', + overflow: 'hidden' + }); + + // insert flash object + html = '' + + '' + + '' + + '' + + ''; + + if (Env.browser === 'IE') { + el = document.createElement('div'); + container.appendChild(el); + el.outerHTML = html; + el = container = null; // just in case + } else { + container.innerHTML = html; + } + + // Init is dispatched by the shim + initTimer = setTimeout(function() { + if (I && !I.initialized) { // runtime might be already destroyed by this moment + I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR)); + + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("\tFlash failed to initialize within a specified period of time (typically 5s)."); + } + } + }, 5000); + }, + + destroy: (function(destroy) { // extend default destroy method + return function() { + removeSWF(I.uid); // SWF removal requires special care in IE + + destroy.call(I); + clearTimeout(initTimer); // initialization check might be still onwait + options = initTimer = destroy = I = null; + }; + }(this.destroy)) + + }, extensions); + } + + Runtime.addConstructor(type, FlashRuntime); + + return extensions; +}); + +// Included from: src/javascript/runtime/flash/file/FileInput.js + +/** + * FileInput.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/file/FileInput +@private +*/ +define("moxie/runtime/flash/file/FileInput", [ + "moxie/runtime/flash/Runtime", + "moxie/file/File", + "moxie/core/utils/Basic" +], function(extensions, File, Basic) { + + var FileInput = { + init: function(options) { + var comp = this, I = this.getRuntime(); + + this.bind("Change", function() { + var files = I.shimExec.call(comp, 'FileInput', 'getFiles'); + comp.files = []; + Basic.each(files, function(file) { + comp.files.push(new File(I.uid, file)); + }); + }, 999); + + this.getRuntime().shimExec.call(this, 'FileInput', 'init', { + name: options.name, + accept: options.accept, + multiple: options.multiple + }); + + this.trigger('ready'); + } + }; + + return (extensions.FileInput = FileInput); +}); + +// Included from: src/javascript/runtime/flash/file/Blob.js + +/** + * Blob.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/file/Blob +@private +*/ +define("moxie/runtime/flash/file/Blob", [ + "moxie/runtime/flash/Runtime", + "moxie/file/Blob" +], function(extensions, Blob) { + + var FlashBlob = { + slice: function(blob, start, end, type) { + var self = this.getRuntime(); + + if (start < 0) { + start = Math.max(blob.size + start, 0); + } else if (start > 0) { + start = Math.min(start, blob.size); + } + + if (end < 0) { + end = Math.max(blob.size + end, 0); + } else if (end > 0) { + end = Math.min(end, blob.size); + } + + blob = self.shimExec.call(this, 'Blob', 'slice', start, end, type || ''); + + if (blob) { + blob = new Blob(self.uid, blob); + } + return blob; + } + }; + + return (extensions.Blob = FlashBlob); +}); + +// Included from: src/javascript/runtime/flash/file/FileReader.js + +/** + * FileReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/file/FileReader +@private +*/ +define("moxie/runtime/flash/file/FileReader", [ + "moxie/runtime/flash/Runtime", + "moxie/core/utils/Encode" +], function(extensions, Encode) { + + function _formatData(data, op) { + switch (op) { + case 'readAsText': + return Encode.atob(data, 'utf8'); + case 'readAsBinaryString': + return Encode.atob(data); + case 'readAsDataURL': + return data; + } + return null; + } + + var FileReader = { + read: function(op, blob) { + var comp = this; + + comp.result = ''; + + // special prefix for DataURL read mode + if (op === 'readAsDataURL') { + comp.result = 'data:' + (blob.type || '') + ';base64,'; + } + + comp.bind('Progress', function(e, data) { + if (data) { + comp.result += _formatData(data, op); + } + }, 999); + + return comp.getRuntime().shimExec.call(this, 'FileReader', 'readAsBase64', blob.uid); + } + }; + + return (extensions.FileReader = FileReader); +}); + +// Included from: src/javascript/runtime/flash/file/FileReaderSync.js + +/** + * FileReaderSync.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/file/FileReaderSync +@private +*/ +define("moxie/runtime/flash/file/FileReaderSync", [ + "moxie/runtime/flash/Runtime", + "moxie/core/utils/Encode" +], function(extensions, Encode) { + + function _formatData(data, op) { + switch (op) { + case 'readAsText': + return Encode.atob(data, 'utf8'); + case 'readAsBinaryString': + return Encode.atob(data); + case 'readAsDataURL': + return data; + } + return null; + } + + var FileReaderSync = { + read: function(op, blob) { + var result, self = this.getRuntime(); + + result = self.shimExec.call(this, 'FileReaderSync', 'readAsBase64', blob.uid); + if (!result) { + return null; // or throw ex + } + + // special prefix for DataURL read mode + if (op === 'readAsDataURL') { + result = 'data:' + (blob.type || '') + ';base64,' + result; + } + + return _formatData(result, op, blob.type); + } + }; + + return (extensions.FileReaderSync = FileReaderSync); +}); + +// Included from: src/javascript/runtime/flash/xhr/XMLHttpRequest.js + +/** + * XMLHttpRequest.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/xhr/XMLHttpRequest +@private +*/ +define("moxie/runtime/flash/xhr/XMLHttpRequest", [ + "moxie/runtime/flash/Runtime", + "moxie/core/utils/Basic", + "moxie/file/Blob", + "moxie/file/File", + "moxie/file/FileReaderSync", + "moxie/xhr/FormData", + "moxie/runtime/Transporter" +], function(extensions, Basic, Blob, File, FileReaderSync, FormData, Transporter) { + + var XMLHttpRequest = { + + send: function(meta, data) { + var target = this, self = target.getRuntime(); + + function send() { + meta.transport = self.mode; + self.shimExec.call(target, 'XMLHttpRequest', 'send', meta, data); + } + + + function appendBlob(name, blob) { + self.shimExec.call(target, 'XMLHttpRequest', 'appendBlob', name, blob.uid); + data = null; + send(); + } + + + function attachBlob(blob, cb) { + var tr = new Transporter(); + + tr.bind("TransportingComplete", function() { + cb(this.result); + }); + + tr.transport(blob.getSource(), blob.type, { + ruid: self.uid + }); + } + + // copy over the headers if any + if (!Basic.isEmptyObj(meta.headers)) { + Basic.each(meta.headers, function(value, header) { + self.shimExec.call(target, 'XMLHttpRequest', 'setRequestHeader', header, value.toString()); // Silverlight doesn't accept integers into the arguments of type object + }); + } + + // transfer over multipart params and blob itself + if (data instanceof FormData) { + var blobField; + data.each(function(value, name) { + if (value instanceof Blob) { + blobField = name; + } else { + self.shimExec.call(target, 'XMLHttpRequest', 'append', name, value); + } + }); + + if (!data.hasBlob()) { + data = null; + send(); + } else { + var blob = data.getBlob(); + if (blob.isDetached()) { + attachBlob(blob, function(attachedBlob) { + blob.destroy(); + appendBlob(blobField, attachedBlob); + }); + } else { + appendBlob(blobField, blob); + } + } + } else if (data instanceof Blob) { + if (data.isDetached()) { + attachBlob(data, function(attachedBlob) { + data.destroy(); + data = attachedBlob.uid; + send(); + }); + } else { + data = data.uid; + send(); + } + } else { + send(); + } + }, + + getResponse: function(responseType) { + var frs, blob, self = this.getRuntime(); + + blob = self.shimExec.call(this, 'XMLHttpRequest', 'getResponseAsBlob'); + + if (blob) { + blob = new File(self.uid, blob); + + if ('blob' === responseType) { + return blob; + } + + try { + frs = new FileReaderSync(); + + if (!!~Basic.inArray(responseType, ["", "text"])) { + return frs.readAsText(blob); + } else if ('json' === responseType && !!window.JSON) { + return JSON.parse(frs.readAsText(blob)); + } + } finally { + blob.destroy(); + } + } + return null; + }, + + abort: function(upload_complete_flag) { + var self = this.getRuntime(); + + self.shimExec.call(this, 'XMLHttpRequest', 'abort'); + + this.dispatchEvent('readystatechange'); + // this.dispatchEvent('progress'); + this.dispatchEvent('abort'); + + //if (!upload_complete_flag) { + // this.dispatchEvent('uploadprogress'); + //} + } + }; + + return (extensions.XMLHttpRequest = XMLHttpRequest); +}); + +// Included from: src/javascript/runtime/flash/runtime/Transporter.js + +/** + * Transporter.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/runtime/Transporter +@private +*/ +define("moxie/runtime/flash/runtime/Transporter", [ + "moxie/runtime/flash/Runtime", + "moxie/file/Blob" +], function(extensions, Blob) { + + var Transporter = { + getAsBlob: function(type) { + var self = this.getRuntime() + , blob = self.shimExec.call(this, 'Transporter', 'getAsBlob', type) + ; + if (blob) { + return new Blob(self.uid, blob); + } + return null; + } + }; + + return (extensions.Transporter = Transporter); +}); + +// Included from: src/javascript/runtime/flash/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/flash/image/Image +@private +*/ +define("moxie/runtime/flash/image/Image", [ + "moxie/runtime/flash/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/Transporter", + "moxie/file/Blob", + "moxie/file/FileReaderSync" +], function(extensions, Basic, Transporter, Blob, FileReaderSync) { + + var Image = { + loadFromBlob: function(blob) { + var comp = this, self = comp.getRuntime(); + + function exec(srcBlob) { + self.shimExec.call(comp, 'Image', 'loadFromBlob', srcBlob.uid); + comp = self = null; + } + + if (blob.isDetached()) { // binary string + var tr = new Transporter(); + tr.bind("TransportingComplete", function() { + exec(tr.result.getSource()); + }); + tr.transport(blob.getSource(), blob.type, { ruid: self.uid }); + } else { + exec(blob.getSource()); + } + }, + + loadFromImage: function(img) { + var self = this.getRuntime(); + return self.shimExec.call(this, 'Image', 'loadFromImage', img.uid); + }, + + getInfo: function() { + var self = this.getRuntime() + , info = self.shimExec.call(this, 'Image', 'getInfo') + ; + + if (info.meta && info.meta.thumb && !(info.meta.thumb.data instanceof Blob)) { + info.meta.thumb.data = new Blob(self.uid, info.meta.thumb.data); + } + return info; + }, + + getAsBlob: function(type, quality) { + var self = this.getRuntime() + , blob = self.shimExec.call(this, 'Image', 'getAsBlob', type, quality) + ; + if (blob) { + return new Blob(self.uid, blob); + } + return null; + }, + + getAsDataURL: function() { + var self = this.getRuntime() + , blob = self.Image.getAsBlob.apply(this, arguments) + , frs + ; + if (!blob) { + return null; + } + frs = new FileReaderSync(); + return frs.readAsDataURL(blob); + } + }; + + return (extensions.Image = Image); +}); + +// Included from: src/javascript/runtime/silverlight/Runtime.js + +/** + * RunTime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global ActiveXObject:true */ + +/** +Defines constructor for Silverlight runtime. + +@class moxie/runtime/silverlight/Runtime +@private +*/ +define("moxie/runtime/silverlight/Runtime", [ + "moxie/core/utils/Basic", + "moxie/core/utils/Env", + "moxie/core/utils/Dom", + "moxie/core/Exceptions", + "moxie/runtime/Runtime" +], function(Basic, Env, Dom, x, Runtime) { + + var type = "silverlight", extensions = {}; + + function isInstalled(version) { + var isVersionSupported = false, control = null, actualVer, + actualVerArray, reqVerArray, requiredVersionPart, actualVersionPart, index = 0; + + try { + try { + control = new ActiveXObject('AgControl.AgControl'); + + if (control.IsVersionSupported(version)) { + isVersionSupported = true; + } + + control = null; + } catch (e) { + var plugin = navigator.plugins["Silverlight Plug-In"]; + + if (plugin) { + actualVer = plugin.description; + + if (actualVer === "1.0.30226.2") { + actualVer = "2.0.30226.2"; + } + + actualVerArray = actualVer.split("."); + + while (actualVerArray.length > 3) { + actualVerArray.pop(); + } + + while ( actualVerArray.length < 4) { + actualVerArray.push(0); + } + + reqVerArray = version.split("."); + + while (reqVerArray.length > 4) { + reqVerArray.pop(); + } + + do { + requiredVersionPart = parseInt(reqVerArray[index], 10); + actualVersionPart = parseInt(actualVerArray[index], 10); + index++; + } while (index < reqVerArray.length && requiredVersionPart === actualVersionPart); + + if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) { + isVersionSupported = true; + } + } + } + } catch (e2) { + isVersionSupported = false; + } + + return isVersionSupported; + } + + /** + Constructor for the Silverlight Runtime + + @class SilverlightRuntime + @extends Runtime + */ + function SilverlightRuntime(options) { + var I = this, initTimer; + + options = Basic.extend({ xap_url: Env.xap_url }, options); + + Runtime.call(this, options, type, { + access_binary: Runtime.capTrue, + access_image_binary: Runtime.capTrue, + display_media: Runtime.capTrue, + do_cors: Runtime.capTrue, + drag_and_drop: false, + report_upload_progress: Runtime.capTrue, + resize_image: Runtime.capTrue, + return_response_headers: function(value) { + return value && I.mode === 'client'; + }, + return_response_type: function(responseType) { + if (responseType !== 'json') { + return true; + } else { + return !!window.JSON; + } + }, + return_status_code: function(code) { + return I.mode === 'client' || !Basic.arrayDiff(code, [200, 404]); + }, + select_file: Runtime.capTrue, + select_multiple: Runtime.capTrue, + send_binary_string: Runtime.capTrue, + send_browser_cookies: function(value) { + return value && I.mode === 'browser'; + }, + send_custom_headers: function(value) { + return value && I.mode === 'client'; + }, + send_multipart: Runtime.capTrue, + slice_blob: Runtime.capTrue, + stream_upload: true, + summon_file_dialog: false, + upload_filesize: Runtime.capTrue, + use_http_method: function(methods) { + return I.mode === 'client' || !Basic.arrayDiff(methods, ['GET', 'POST']); + } + }, { + // capabilities that require specific mode + return_response_headers: function(value) { + return value ? 'client' : 'browser'; + }, + return_status_code: function(code) { + return Basic.arrayDiff(code, [200, 404]) ? 'client' : ['client', 'browser']; + }, + send_browser_cookies: function(value) { + return value ? 'browser' : 'client'; + }, + send_custom_headers: function(value) { + return value ? 'client' : 'browser'; + }, + use_http_method: function(methods) { + return Basic.arrayDiff(methods, ['GET', 'POST']) ? 'client' : ['client', 'browser']; + } + }); + + + // minimal requirement + if (!isInstalled('2.0.31005.0') || Env.browser === 'Opera') { + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("\tSilverlight is not installed or minimal version (2.0.31005.0) requirement not met (not likely)."); + } + + this.mode = false; + } + + + Basic.extend(this, { + getShim: function() { + return Dom.get(this.uid).content.Moxie; + }, + + shimExec: function(component, action) { + var args = [].slice.call(arguments, 2); + return I.getShim().exec(this.uid, component, action, args); + }, + + init : function() { + var container; + + container = this.getShimContainer(); + + container.innerHTML = '' + + '' + + '' + + '' + + '' + + '' + + ''; + + // Init is dispatched by the shim + initTimer = setTimeout(function() { + if (I && !I.initialized) { // runtime might be already destroyed by this moment + I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR)); + + if (MXI_DEBUG && Env.debug.runtime) { + Env.log("\Silverlight failed to initialize within a specified period of time (5-10s)."); + } + } + }, Env.OS !== 'Windows'? 10000 : 5000); // give it more time to initialize in non Windows OS (like Mac) + }, + + destroy: (function(destroy) { // extend default destroy method + return function() { + destroy.call(I); + clearTimeout(initTimer); // initialization check might be still onwait + options = initTimer = destroy = I = null; + }; + }(this.destroy)) + + }, extensions); + } + + Runtime.addConstructor(type, SilverlightRuntime); + + return extensions; +}); + +// Included from: src/javascript/runtime/silverlight/file/FileInput.js + +/** + * FileInput.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/file/FileInput +@private +*/ +define("moxie/runtime/silverlight/file/FileInput", [ + "moxie/runtime/silverlight/Runtime", + "moxie/file/File", + "moxie/core/utils/Basic" +], function(extensions, File, Basic) { + + var FileInput = { + init: function(options) { + var comp = this, I = this.getRuntime(); + + function toFilters(accept) { + var filter = ''; + for (var i = 0; i < accept.length; i++) { + filter += (filter !== '' ? '|' : '') + accept[i].title + " | *." + accept[i].extensions.replace(/,/g, ';*.'); + } + return filter; + } + + this.bind("Change", function() { + var files = I.shimExec.call(comp, 'FileInput', 'getFiles'); + comp.files = []; + Basic.each(files, function(file) { + comp.files.push(new File(I.uid, file)); + }); + }, 999); + + this.getRuntime().shimExec.call(this, 'FileInput', 'init', toFilters(options.accept), options.name, options.multiple); + this.trigger('ready'); + } + }; + + return (extensions.FileInput = FileInput); +}); + +// Included from: src/javascript/runtime/silverlight/file/Blob.js + +/** + * Blob.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/file/Blob +@private +*/ +define("moxie/runtime/silverlight/file/Blob", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/file/Blob" +], function(extensions, Basic, Blob) { + return (extensions.Blob = Basic.extend({}, Blob)); +}); + +// Included from: src/javascript/runtime/silverlight/file/FileDrop.js + +/** + * FileDrop.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/file/FileDrop +@private +*/ +define("moxie/runtime/silverlight/file/FileDrop", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Dom", + "moxie/core/utils/Events" +], function(extensions, Dom, Events) { + + // not exactly useful, since works only in safari (...crickets...) + var FileDrop = { + init: function() { + var comp = this, self = comp.getRuntime(), dropZone; + + dropZone = self.getShimContainer(); + + Events.addEvent(dropZone, 'dragover', function(e) { + e.preventDefault(); + e.stopPropagation(); + e.dataTransfer.dropEffect = 'copy'; + }, comp.uid); + + Events.addEvent(dropZone, 'dragenter', function(e) { + e.preventDefault(); + var flag = Dom.get(self.uid).dragEnter(e); + // If handled, then stop propagation of event in DOM + if (flag) { + e.stopPropagation(); + } + }, comp.uid); + + Events.addEvent(dropZone, 'drop', function(e) { + e.preventDefault(); + var flag = Dom.get(self.uid).dragDrop(e); + // If handled, then stop propagation of event in DOM + if (flag) { + e.stopPropagation(); + } + }, comp.uid); + + return self.shimExec.call(this, 'FileDrop', 'init'); + } + }; + + return (extensions.FileDrop = FileDrop); +}); + +// Included from: src/javascript/runtime/silverlight/file/FileReader.js + +/** + * FileReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/file/FileReader +@private +*/ +define("moxie/runtime/silverlight/file/FileReader", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/file/FileReader" +], function(extensions, Basic, FileReader) { + return (extensions.FileReader = Basic.extend({}, FileReader)); +}); + +// Included from: src/javascript/runtime/silverlight/file/FileReaderSync.js + +/** + * FileReaderSync.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/file/FileReaderSync +@private +*/ +define("moxie/runtime/silverlight/file/FileReaderSync", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/file/FileReaderSync" +], function(extensions, Basic, FileReaderSync) { + return (extensions.FileReaderSync = Basic.extend({}, FileReaderSync)); +}); + +// Included from: src/javascript/runtime/silverlight/xhr/XMLHttpRequest.js + +/** + * XMLHttpRequest.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/xhr/XMLHttpRequest +@private +*/ +define("moxie/runtime/silverlight/xhr/XMLHttpRequest", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/xhr/XMLHttpRequest" +], function(extensions, Basic, XMLHttpRequest) { + return (extensions.XMLHttpRequest = Basic.extend({}, XMLHttpRequest)); +}); + +// Included from: src/javascript/runtime/silverlight/runtime/Transporter.js + +/** + * Transporter.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/runtime/Transporter +@private +*/ +define("moxie/runtime/silverlight/runtime/Transporter", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/runtime/flash/runtime/Transporter" +], function(extensions, Basic, Transporter) { + return (extensions.Transporter = Basic.extend({}, Transporter)); +}); + +// Included from: src/javascript/runtime/silverlight/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/silverlight/image/Image +@private +*/ +define("moxie/runtime/silverlight/image/Image", [ + "moxie/runtime/silverlight/Runtime", + "moxie/core/utils/Basic", + "moxie/file/Blob", + "moxie/runtime/flash/image/Image" +], function(extensions, Basic, Blob, Image) { + return (extensions.Image = Basic.extend({}, Image, { + + getInfo: function() { + var self = this.getRuntime() + , grps = ['tiff', 'exif', 'gps', 'thumb'] + , info = { meta: {} } + , rawInfo = self.shimExec.call(this, 'Image', 'getInfo') + ; + + if (rawInfo.meta) { + Basic.each(grps, function(grp) { + var meta = rawInfo.meta[grp] + , tag + , i + , length + , value + ; + if (meta && meta.keys) { + info.meta[grp] = {}; + for (i = 0, length = meta.keys.length; i < length; i++) { + tag = meta.keys[i]; + value = meta[tag]; + if (value) { + // convert numbers + if (/^(\d|[1-9]\d+)$/.test(value)) { // integer (make sure doesn't start with zero) + value = parseInt(value, 10); + } else if (/^\d*\.\d+$/.test(value)) { // double + value = parseFloat(value); + } + info.meta[grp][tag] = value; + } + } + } + }); + + // save thumb data as blob + if (info.meta && info.meta.thumb && !(info.meta.thumb.data instanceof Blob)) { + info.meta.thumb.data = new Blob(self.uid, info.meta.thumb.data); + } + } + + info.width = parseInt(rawInfo.width, 10); + info.height = parseInt(rawInfo.height, 10); + info.size = parseInt(rawInfo.size, 10); + info.type = rawInfo.type; + info.name = rawInfo.name; + + return info; + } + })); +}); + +// Included from: src/javascript/runtime/html4/Runtime.js + +/** + * Runtime.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global File:true */ + +/** +Defines constructor for HTML4 runtime. + +@class moxie/runtime/html4/Runtime +@private +*/ +define("moxie/runtime/html4/Runtime", [ + "moxie/core/utils/Basic", + "moxie/core/Exceptions", + "moxie/runtime/Runtime", + "moxie/core/utils/Env" +], function(Basic, x, Runtime, Env) { + + var type = 'html4', extensions = {}; + + function Html4Runtime(options) { + var I = this + , Test = Runtime.capTest + , True = Runtime.capTrue + ; + + Runtime.call(this, options, type, { + access_binary: Test(window.FileReader || window.File && File.getAsDataURL), + access_image_binary: false, + display_media: Test(extensions.Image && (Env.can('create_canvas') || Env.can('use_data_uri_over32kb'))), + do_cors: false, + drag_and_drop: false, + filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest + return (Env.browser === 'Chrome' && Env.verComp(Env.version, 28, '>=')) || + (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) || + (Env.browser === 'Safari' && Env.verComp(Env.version, 7, '>=')); + }()), + resize_image: function() { + return extensions.Image && I.can('access_binary') && Env.can('create_canvas'); + }, + report_upload_progress: false, + return_response_headers: false, + return_response_type: function(responseType) { + if (responseType === 'json' && !!window.JSON) { + return true; + } + return !!~Basic.inArray(responseType, ['text', 'document', '']); + }, + return_status_code: function(code) { + return !Basic.arrayDiff(code, [200, 404]); + }, + select_file: function() { + return Env.can('use_fileinput'); + }, + select_multiple: false, + send_binary_string: false, + send_custom_headers: false, + send_multipart: true, + slice_blob: false, + stream_upload: function() { + return I.can('select_file'); + }, + summon_file_dialog: function() { // yeah... some dirty sniffing here... + return I.can('select_file') && ( + (Env.browser === 'Firefox' && Env.verComp(Env.version, 4, '>=')) || + (Env.browser === 'Opera' && Env.verComp(Env.version, 12, '>=')) || + (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) || + !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']) + ); + }, + upload_filesize: True, + use_http_method: function(methods) { + return !Basic.arrayDiff(methods, ['GET', 'POST']); + } + }); + + + Basic.extend(this, { + init : function() { + this.trigger("Init"); + }, + + destroy: (function(destroy) { // extend default destroy method + return function() { + destroy.call(I); + destroy = I = null; + }; + }(this.destroy)) + }); + + Basic.extend(this.getShim(), extensions); + } + + Runtime.addConstructor(type, Html4Runtime); + + return extensions; +}); + +// Included from: src/javascript/runtime/html4/file/FileInput.js + +/** + * FileInput.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html4/file/FileInput +@private +*/ +define("moxie/runtime/html4/file/FileInput", [ + "moxie/runtime/html4/Runtime", + "moxie/file/File", + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/utils/Events", + "moxie/core/utils/Mime", + "moxie/core/utils/Env" +], function(extensions, File, Basic, Dom, Events, Mime, Env) { + + function FileInput() { + var _uid, _mimes = [], _options; + + function addInput() { + var comp = this, I = comp.getRuntime(), shimContainer, browseButton, currForm, form, input, uid; + + uid = Basic.guid('uid_'); + + shimContainer = I.getShimContainer(); // we get new ref everytime to avoid memory leaks in IE + + if (_uid) { // move previous form out of the view + currForm = Dom.get(_uid + '_form'); + if (currForm) { + Basic.extend(currForm.style, { top: '100%' }); + } + } + + // build form in DOM, since innerHTML version not able to submit file for some reason + form = document.createElement('form'); + form.setAttribute('id', uid + '_form'); + form.setAttribute('method', 'post'); + form.setAttribute('enctype', 'multipart/form-data'); + form.setAttribute('encoding', 'multipart/form-data'); + + Basic.extend(form.style, { + overflow: 'hidden', + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%' + }); + + input = document.createElement('input'); + input.setAttribute('id', uid); + input.setAttribute('type', 'file'); + input.setAttribute('name', _options.name || 'Filedata'); + input.setAttribute('accept', _mimes.join(',')); + + Basic.extend(input.style, { + fontSize: '999px', + opacity: 0 + }); + + form.appendChild(input); + shimContainer.appendChild(form); + + // prepare file input to be placed underneath the browse_button element + Basic.extend(input.style, { + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%' + }); + + if (Env.browser === 'IE' && Env.verComp(Env.version, 10, '<')) { + Basic.extend(input.style, { + filter : "progid:DXImageTransform.Microsoft.Alpha(opacity=0)" + }); + } + + input.onchange = function() { // there should be only one handler for this + var file; + + if (!this.value) { + return; + } + + if (this.files) { // check if browser is fresh enough + file = this.files[0]; + + // ignore empty files (IE10 for example hangs if you try to send them via XHR) + if (file.size === 0) { + form.parentNode.removeChild(form); + return; + } + } else { + file = { + name: this.value + }; + } + + file = new File(I.uid, file); + + // clear event handler + this.onchange = function() {}; + addInput.call(comp); + + comp.files = [file]; + + // substitute all ids with file uids (consider file.uid read-only - we cannot do it the other way around) + input.setAttribute('id', file.uid); + form.setAttribute('id', file.uid + '_form'); + + comp.trigger('change'); + + input = form = null; + }; + + + // route click event to the input + if (I.can('summon_file_dialog')) { + browseButton = Dom.get(_options.browse_button); + Events.removeEvent(browseButton, 'click', comp.uid); + Events.addEvent(browseButton, 'click', function(e) { + if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file] + input.click(); + } + e.preventDefault(); + }, comp.uid); + } + + _uid = uid; + + shimContainer = currForm = browseButton = null; + } + + Basic.extend(this, { + init: function(options) { + var comp = this, I = comp.getRuntime(), shimContainer; + + // figure out accept string + _options = options; + _mimes = options.accept.mimes || Mime.extList2mimes(options.accept, I.can('filter_by_extension')); + + shimContainer = I.getShimContainer(); + + (function() { + var browseButton, zIndex, top; + + browseButton = Dom.get(options.browse_button); + + // Route click event to the input[type=file] element for browsers that support such behavior + if (I.can('summon_file_dialog')) { + if (Dom.getStyle(browseButton, 'position') === 'static') { + browseButton.style.position = 'relative'; + } + + zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1; + + browseButton.style.zIndex = zIndex; + shimContainer.style.zIndex = zIndex - 1; + } + + /* Since we have to place input[type=file] on top of the browse_button for some browsers, + browse_button loses interactivity, so we restore it here */ + top = I.can('summon_file_dialog') ? browseButton : shimContainer; + + Events.addEvent(top, 'mouseover', function() { + comp.trigger('mouseenter'); + }, comp.uid); + + Events.addEvent(top, 'mouseout', function() { + comp.trigger('mouseleave'); + }, comp.uid); + + Events.addEvent(top, 'mousedown', function() { + comp.trigger('mousedown'); + }, comp.uid); + + Events.addEvent(Dom.get(options.container), 'mouseup', function() { + comp.trigger('mouseup'); + }, comp.uid); + + browseButton = null; + }()); + + addInput.call(this); + + shimContainer = null; + + // trigger ready event asynchronously + comp.trigger({ + type: 'ready', + async: true + }); + }, + + + disable: function(state) { + var input; + + if ((input = Dom.get(_uid))) { + input.disabled = !!state; + } + }, + + destroy: function() { + var I = this.getRuntime() + , shim = I.getShim() + , shimContainer = I.getShimContainer() + ; + + Events.removeAllEvents(shimContainer, this.uid); + Events.removeAllEvents(_options && Dom.get(_options.container), this.uid); + Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid); + + if (shimContainer) { + shimContainer.innerHTML = ''; + } + + shim.removeInstance(this.uid); + + _uid = _mimes = _options = shimContainer = shim = null; + } + }); + } + + return (extensions.FileInput = FileInput); +}); + +// Included from: src/javascript/runtime/html4/file/FileReader.js + +/** + * FileReader.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html4/file/FileReader +@private +*/ +define("moxie/runtime/html4/file/FileReader", [ + "moxie/runtime/html4/Runtime", + "moxie/runtime/html5/file/FileReader" +], function(extensions, FileReader) { + return (extensions.FileReader = FileReader); +}); + +// Included from: src/javascript/runtime/html4/xhr/XMLHttpRequest.js + +/** + * XMLHttpRequest.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html4/xhr/XMLHttpRequest +@private +*/ +define("moxie/runtime/html4/xhr/XMLHttpRequest", [ + "moxie/runtime/html4/Runtime", + "moxie/core/utils/Basic", + "moxie/core/utils/Dom", + "moxie/core/utils/Url", + "moxie/core/Exceptions", + "moxie/core/utils/Events", + "moxie/file/Blob", + "moxie/xhr/FormData" +], function(extensions, Basic, Dom, Url, x, Events, Blob, FormData) { + + function XMLHttpRequest() { + var _status, _response, _iframe; + + function cleanup(cb) { + var target = this, uid, form, inputs, i, hasFile = false; + + if (!_iframe) { + return; + } + + uid = _iframe.id.replace(/_iframe$/, ''); + + form = Dom.get(uid + '_form'); + if (form) { + inputs = form.getElementsByTagName('input'); + i = inputs.length; + + while (i--) { + switch (inputs[i].getAttribute('type')) { + case 'hidden': + inputs[i].parentNode.removeChild(inputs[i]); + break; + case 'file': + hasFile = true; // flag the case for later + break; + } + } + inputs = []; + + if (!hasFile) { // we need to keep the form for sake of possible retries + form.parentNode.removeChild(form); + } + form = null; + } + + // without timeout, request is marked as canceled (in console) + setTimeout(function() { + Events.removeEvent(_iframe, 'load', target.uid); + if (_iframe.parentNode) { // #382 + _iframe.parentNode.removeChild(_iframe); + } + + // check if shim container has any other children, if - not, remove it as well + var shimContainer = target.getRuntime().getShimContainer(); + if (!shimContainer.children.length) { + shimContainer.parentNode.removeChild(shimContainer); + } + + shimContainer = _iframe = null; + cb(); + }, 1); + } + + Basic.extend(this, { + send: function(meta, data) { + var target = this, I = target.getRuntime(), uid, form, input, blob; + + _status = _response = null; + + function createIframe() { + var container = I.getShimContainer() || document.body + , temp = document.createElement('div') + ; + + // IE 6 won't be able to set the name using setAttribute or iframe.name + temp.innerHTML = ''; + _iframe = temp.firstChild; + container.appendChild(_iframe); + + /* _iframe.onreadystatechange = function() { + console.info(_iframe.readyState); + };*/ + + Events.addEvent(_iframe, 'load', function() { // _iframe.onload doesn't work in IE lte 8 + var el; + + try { + el = _iframe.contentWindow.document || _iframe.contentDocument || window.frames[_iframe.id].document; + + // try to detect some standard error pages + if (/^4(0[0-9]|1[0-7]|2[2346])\s/.test(el.title)) { // test if title starts with 4xx HTTP error + _status = el.title.replace(/^(\d+).*$/, '$1'); + } else { + _status = 200; + // get result + _response = Basic.trim(el.body.innerHTML); + + // we need to fire these at least once + target.trigger({ + type: 'progress', + loaded: _response.length, + total: _response.length + }); + + if (blob) { // if we were uploading a file + target.trigger({ + type: 'uploadprogress', + loaded: blob.size || 1025, + total: blob.size || 1025 + }); + } + } + } catch (ex) { + if (Url.hasSameOrigin(meta.url)) { + // if response is sent with error code, iframe in IE gets redirected to res://ieframe.dll/http_x.htm + // which obviously results to cross domain error (wtf?) + _status = 404; + } else { + cleanup.call(target, function() { + target.trigger('error'); + }); + return; + } + } + + cleanup.call(target, function() { + target.trigger('load'); + }); + }, target.uid); + } // end createIframe + + // prepare data to be sent and convert if required + if (data instanceof FormData && data.hasBlob()) { + blob = data.getBlob(); + uid = blob.uid; + input = Dom.get(uid); + form = Dom.get(uid + '_form'); + if (!form) { + throw new x.DOMException(x.DOMException.NOT_FOUND_ERR); + } + } else { + uid = Basic.guid('uid_'); + + form = document.createElement('form'); + form.setAttribute('id', uid + '_form'); + form.setAttribute('method', meta.method); + form.setAttribute('enctype', 'multipart/form-data'); + form.setAttribute('encoding', 'multipart/form-data'); + + I.getShimContainer().appendChild(form); + } + + // set upload target + form.setAttribute('target', uid + '_iframe'); + + if (data instanceof FormData) { + data.each(function(value, name) { + if (value instanceof Blob) { + if (input) { + input.setAttribute('name', name); + } + } else { + var hidden = document.createElement('input'); + + Basic.extend(hidden, { + type : 'hidden', + name : name, + value : value + }); + + // make sure that input[type="file"], if it's there, comes last + if (input) { + form.insertBefore(hidden, input); + } else { + form.appendChild(hidden); + } + } + }); + } + + // set destination url + form.setAttribute("action", meta.url); + + createIframe(); + form.submit(); + target.trigger('loadstart'); + }, + + getStatus: function() { + return _status; + }, + + getResponse: function(responseType) { + if ('json' === responseType) { + // strip off
..
tags that might be enclosing the response + if (Basic.typeOf(_response) === 'string' && !!window.JSON) { + try { + return JSON.parse(_response.replace(/^\s*]*>/, '').replace(/<\/pre>\s*$/, '')); + } catch (ex) { + return null; + } + } + } else if ('document' === responseType) { + + } + return _response; + }, + + abort: function() { + var target = this; + + if (_iframe && _iframe.contentWindow) { + if (_iframe.contentWindow.stop) { // FireFox/Safari/Chrome + _iframe.contentWindow.stop(); + } else if (_iframe.contentWindow.document.execCommand) { // IE + _iframe.contentWindow.document.execCommand('Stop'); + } else { + _iframe.src = "about:blank"; + } + } + + cleanup.call(this, function() { + // target.dispatchEvent('readystatechange'); + target.dispatchEvent('abort'); + }); + } + }); + } + + return (extensions.XMLHttpRequest = XMLHttpRequest); +}); + +// Included from: src/javascript/runtime/html4/image/Image.js + +/** + * Image.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/** +@class moxie/runtime/html4/image/Image +@private +*/ +define("moxie/runtime/html4/image/Image", [ + "moxie/runtime/html4/Runtime", + "moxie/runtime/html5/image/Image" +], function(extensions, Image) { + return (extensions.Image = Image); +}); + +expose(["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/FileInput","moxie/core/utils/Encode","moxie/file/Blob","moxie/file/File","moxie/file/FileDrop","moxie/file/FileReader","moxie/core/utils/Url","moxie/runtime/RuntimeTarget","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"]); +})(this); +/** + * o.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global moxie:true */ + +/** +Globally exposed namespace with the most frequently used public classes and handy methods. + +@class o +@static +@private +*/ +(function(exports) { + "use strict"; + + var o = {}, inArray = exports.moxie.core.utils.Basic.inArray; + + // directly add some public classes + // (we do it dynamically here, since for custom builds we cannot know beforehand what modules were included) + (function addAlias(ns) { + var name, itemType; + for (name in ns) { + itemType = typeof(ns[name]); + if (itemType === 'object' && !~inArray(name, ['Exceptions', 'Env', 'Mime'])) { + addAlias(ns[name]); + } else if (itemType === 'function') { + o[name] = ns[name]; + } + } + })(exports.moxie); + + // add some manually + o.Env = exports.moxie.core.utils.Env; + o.Mime = exports.moxie.core.utils.Mime; + o.Exceptions = exports.moxie.core.Exceptions; + + // expose globally + exports.mOxie = o; + if (!exports.o) { + exports.o = o; + } + return o; +})(this); diff --git a/qiniu_fields/static/qiniu_fields/plupload/moxie.min.js b/qiniu_fields/static/qiniu_fields/plupload/moxie.min.js new file mode 100644 index 0000000..dfd12b0 --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/plupload/moxie.min.js @@ -0,0 +1,16 @@ +/** + * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill + * v1.3.4 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2015-07-18 + */ +!function(e,t){"use strict";function n(e,t){for(var n,i=[],r=0;r0&&n(o,function(n,o){n!==r&&(e(i[o])===e(n)&&~a(e(n),["array","object"])?t(i[o],n):i[o]=n)})}),i},n=function(t,n){var i,r,o,a;if(t)if("number"===e(t.length)){for(o=0,i=t.length;i>o;o++)if(n(t[o],o)===!1)return}else if("object"===e(t))for(r in t)if(t.hasOwnProperty(r)&&n(t[r],r)===!1)return},i=function(t){var n;if(!t||"object"!==e(t))return!0;for(n in t)return!1;return!0},r=function(t,n){function i(r){"function"===e(t[r])&&t[r](function(e){++rn;n++)if(t[n]===e)return n}return-1},s=function(t,n){var i=[];"array"!==e(t)&&(t=[t]),"array"!==e(n)&&(n=[n]);for(var r in t)-1===a(t[r],n)&&i.push(t[r]);return i.length?i:!1},u=function(e,t){var i=[];return n(e,function(e){-1!==a(e,t)&&i.push(e)}),i.length?i:null},c=function(e){var t,n=[];for(t=0;ti;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}(),d=function(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e},h=function(e){if("string"!=typeof e)return e;var t={t:1099511627776,g:1073741824,m:1048576,k:1024},n;return e=/^([0-9\.]+)([tmgk]?)$/.exec(e.toLowerCase().replace(/[^0-9\.tmkg]/g,"")),n=e[2],e=+e[1],t.hasOwnProperty(n)&&(e*=t[n]),Math.floor(e)},f=function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e(t)?t:""})};return{guid:l,typeOf:e,extend:t,each:n,isEmptyObj:i,inSeries:r,inParallel:o,inArray:a,arrayDiff:s,arrayIntersect:u,toArray:c,trim:d,sprintf:f,parseSizeStr:h}}),i(c,[u],function(e){function t(e,t,n){var i=0,r=0,o=0,a={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},s=function(e){return e=(""+e).replace(/[_\-+]/g,"."),e=e.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,"."),e.length?e.split("."):[-8]},u=function(e){return e?isNaN(e)?a[e]||-7:parseInt(e,10):0};for(e=s(e),t=s(t),r=Math.max(e.length,t.length),i=0;r>i;i++)if(e[i]!=t[i]){if(e[i]=u(e[i]),t[i]=u(t[i]),e[i]t[i]){o=1;break}}if(!n)return o;switch(n){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq":return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",n="?",i="function",r="undefined",o="object",a="major",s="model",u="name",c="type",l="vendor",d="version",h="architecture",f="console",p="mobile",m="tablet",g={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},v={rgx:function(){for(var t,n=0,a,s,u,c,l,d,h=arguments;n0?2==c.length?typeof c[1]==i?t[c[0]]=c[1].call(this,d):t[c[0]]=c[1]:3==c.length?typeof c[1]!==i||c[1].exec&&c[1].test?t[c[0]]=d?d.replace(c[1],c[2]):e:t[c[0]]=d?c[1].call(this,d,c[2]):e:4==c.length&&(t[c[0]]=d?c[3].call(this,d.replace(c[1],c[2])):e):t[c]=d?d:e;break}if(l)break}return t},str:function(t,i){for(var r in i)if(typeof i[r]===o&&i[r].length>0){for(var a=0;a=9)},use_data_uri_of:function(e){return t.use_data_uri&&33e3>e||t.use_data_uri_over32kb()},use_fileinput:function(){if(navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/))return!1;var e=document.createElement("input");return e.setAttribute("type","file"),!e.disabled}};return function(n){var i=[].slice.call(arguments);return i.shift(),"function"===e.typeOf(t[n])?t[n].apply(this,i):!!t[n]}}(),r=(new n).getResult(),o={can:i,uaParser:n,browser:r.browser.name,version:r.browser.version,os:r.os.name,osVersion:r.os.version,verComp:t,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return o.OS=o.os,o}),i(l,[u],function(e){var t={};return{addI18n:function(n){return e.extend(t,n)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),i(d,[u,l],function(e,t){var n="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",i={mimes:{},extensions:{},addMimeType:function(e){var t=e.split(/,/),n,i,r;for(n=0;n=0;o--)if(r[o].fn===i){r.splice(o,1);break}}else r=[];r.length||(delete e[this.uid][t],n.isEmptyObj(e[this.uid])&&delete e[this.uid])}},removeAllEventListeners:function(){e[this.uid]&&delete e[this.uid]},dispatchEvent:function(i){var r,o,a,s,u={},c=!0,l;if("string"!==n.typeOf(i)){if(s=i,"string"!==n.typeOf(s.type))throw new t.EventException(t.EventException.UNSPECIFIED_EVENT_TYPE_ERR);i=s.type,s.total!==l&&s.loaded!==l&&(u.total=s.total,u.loaded=s.loaded),u.async=s.async||!1}if(-1!==i.indexOf("::")?!function(e){r=e[0],i=e[1]}(i.split("::")):r=this.uid,i=i.toLowerCase(),o=e[r]&&e[r][i]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),u.type=i,a.unshift(u);var d=[];n.each(o,function(e){a[0].target=e.scope,d.push(u.async?function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}:function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&n.inSeries(d,function(e){c=!e})}return c},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},handleEventProps:function(e){var t=this;this.bind(e.join(" "),function(e){var t="on"+e.type.toLowerCase();"function"===n.typeOf(this[t])&&this[t].apply(this,arguments)}),n.each(e,function(e){e="on"+e.toLowerCase(e),"undefined"===n.typeOf(t[e])&&(t[e]=null)})}})}return i.instance=new i,i}),i(m,[c,u,h,p],function(e,t,n,i){function r(e,i,o,s,u){var c=this,l,d=t.guid(i+"_"),h=u||"browser";e=e||{},a[d]=this,o=t.extend({access_binary:!1,access_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_file_dialog:!1,upload_filesize:!0,use_http_method:!0},o),e.preferred_caps&&(h=r.getMode(s,e.preferred_caps,h)),l=function(){var e={};return{exec:function(t,n,i,r){return l[n]&&(e[t]||(e[t]={context:this,instance:new l[n]}),e[t].instance[i])?e[t].instance[i].apply(this,r):void 0},removeInstance:function(t){delete e[t]},removeAllInstances:function(){var n=this;t.each(e,function(e,i){"function"===t.typeOf(e.instance.destroy)&&e.instance.destroy.call(e.context),n.removeInstance(i)})}}}(),t.extend(this,{initialized:!1,uid:d,type:i,mode:r.getMode(s,e.required_caps,h),shimid:d+"_container",clients:0,options:e,can:function(e,n){var i=arguments[2]||o;if("string"===t.typeOf(e)&&"undefined"===t.typeOf(n)&&(e=r.parseCaps(e)),"object"===t.typeOf(e)){for(var a in e)if(!this.can(a,e[a],i))return!1;return!0}return"function"===t.typeOf(i[e])?i[e].call(this,n):n===i[e]},getShimContainer:function(){var e,i=n.get(this.shimid);return i||(e=this.options.container?n.get(this.options.container):document.body,i=document.createElement("div"),i.id=this.shimid,i.className="moxie-shim moxie-shim-"+this.type,t.extend(i.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),e.appendChild(i),e=null),i},getShim:function(){return l},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec.call(this,this.uid,e,t,n)},exec:function(e,t){var n=[].slice.call(arguments,2);return c[e]&&c[e][t]?c[e][t].apply(this,n):c.shimExec.apply(this,arguments)},destroy:function(){if(c){var e=n.get(this.shimid);e&&e.parentNode.removeChild(e),l&&l.removeAllInstances(),this.unbindAll(),delete a[this.uid],this.uid=null,d=c=l=e=null}}}),this.mode&&e.required_caps&&!this.can(e.required_caps)&&(this.mode=!1)}var o={},a={};return r.order="html5,flash,silverlight,html4",r.getRuntime=function(e){return a[e]?a[e]:!1},r.addConstructor=function(e,t){t.prototype=i.instance,o[e]=t},r.getConstructor=function(e){return o[e]||null},r.getInfo=function(e){var t=r.getRuntime(e);return t?{uid:t.uid,type:t.type,mode:t.mode,can:function(){return t.can.apply(t,arguments)}}:null},r.parseCaps=function(e){var n={};return"string"!==t.typeOf(e)?e||{}:(t.each(e.split(","),function(e){n[e]=!0}),n)},r.can=function(e,t){var n,i=r.getConstructor(e),o;return i?(n=new i({required_caps:t}),o=n.mode,n.destroy(),!!o):!1},r.thatCan=function(e,t){var n=(t||r.order).split(/\s*,\s*/);for(var i in n)if(r.can(n[i],e))return n[i];return null},r.getMode=function(e,n,i){var r=null;if("undefined"===t.typeOf(i)&&(i="browser"),n&&!t.isEmptyObj(e)){if(t.each(n,function(n,i){if(e.hasOwnProperty(i)){var o=e[i](n);if("string"==typeof o&&(o=[o]),r){if(!(r=t.arrayIntersect(r,o)))return r=!1}else r=o}}),r)return-1!==t.inArray(i,r)?i:r[0];if(r===!1)return!1}return i},r.capTrue=function(){return!0},r.capFalse=function(){return!1},r.capTest=function(e){return function(){return!!e}},r}),i(g,[c,f,u,m],function(e,t,n,i){return function r(){var e;n.extend(this,{connectRuntime:function(r){function o(n){var s,u;return n.length?(s=n.shift().toLowerCase(),(u=i.getConstructor(s))?(e=new u(r),e.bind("Init",function(){e.initialized=!0,setTimeout(function(){e.clients++,a.trigger("RuntimeInit",e)},1)}),e.bind("Error",function(){e.destroy(),o(n)}),e.mode?void e.init():void e.trigger("Error")):void o(n)):(a.trigger("RuntimeError",new t.RuntimeError(t.RuntimeError.NOT_INIT_ERR)),void(e=null))}var a=this,s;if("string"===n.typeOf(r)?s=r:"string"===n.typeOf(r.ruid)&&(s=r.ruid),s){if(e=i.getRuntime(s))return e.clients++,e;throw new t.RuntimeError(t.RuntimeError.NOT_INIT_ERR)}o((r.runtime_order||i.order).split(/\s*,\s*/))},disconnectRuntime:function(){e&&--e.clients<=0&&e.destroy(),e=null},getRuntime:function(){return e&&e.uid?e:e=null},exec:function(){return e?e.exec.apply(this,arguments):null}})}}),i(v,[u,c,d,h,f,p,l,m,g],function(e,t,n,i,r,o,a,s,u){function c(t){var o=this,c,d,h;if(-1!==e.inArray(e.typeOf(t),["string","node"])&&(t={browse_button:t}),d=i.get(t.browse_button),!d)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR);h={accept:[{title:a.translate("All Files"),extensions:"*"}],name:"file",multiple:!1,required_caps:!1,container:d.parentNode||document.body},t=e.extend({},h,t),"string"==typeof t.required_caps&&(t.required_caps=s.parseCaps(t.required_caps)),"string"==typeof t.accept&&(t.accept=n.mimes2extList(t.accept)),c=i.get(t.container),c||(c=document.body),"static"===i.getStyle(c,"position")&&(c.style.position="relative"),c=d=null,u.call(o),e.extend(o,{uid:e.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){o.bind("RuntimeInit",function(n,r){o.ruid=r.uid,o.shimid=r.shimid,o.bind("Ready",function(){o.trigger("Refresh")},999),o.bind("Refresh",function(){var n,o,a,s;a=i.get(t.browse_button),s=i.get(r.shimid),a&&(n=i.getPos(a,i.get(t.container)),o=i.getSize(a),s&&e.extend(s.style,{top:n.y+"px",left:n.x+"px",width:o.w+"px",height:o.h+"px"})),s=a=null}),r.exec.call(o,"FileInput","init",t)}),o.connectRuntime(e.extend({},t,{required_caps:{select_file:!0}}))},disable:function(t){var n=this.getRuntime();n&&n.exec.call(this,"FileInput","disable","undefined"===e.typeOf(t)?!0:t)},refresh:function(){o.trigger("Refresh")},destroy:function(){var t=this.getRuntime();t&&(t.exec.call(this,"FileInput","destroy"),this.disconnectRuntime()),"array"===e.typeOf(this.files)&&e.each(this.files,function(e){e.destroy()}),this.files=null,this.unbindAll()}}),this.handleEventProps(l)}var l=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];return c.prototype=o.instance,c}),i(w,[],function(){var e=function(e){return unescape(encodeURIComponent(e))},t=function(e){return decodeURIComponent(escape(e))},n=function(e,n){if("function"==typeof window.atob)return n?t(window.atob(e)):window.atob(e);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,h=0,f=0,p="",m=[];if(!e)return e;e+="";do s=i.indexOf(e.charAt(h++)),u=i.indexOf(e.charAt(h++)),c=i.indexOf(e.charAt(h++)),l=i.indexOf(e.charAt(h++)),d=s<<18|u<<12|c<<6|l,r=d>>16&255,o=d>>8&255,a=255&d,64==c?m[f++]=String.fromCharCode(r):64==l?m[f++]=String.fromCharCode(r,o):m[f++]=String.fromCharCode(r,o,a);while(h>18&63,u=d>>12&63,c=d>>6&63,l=63&d,m[f++]=i.charAt(s)+i.charAt(u)+i.charAt(c)+i.charAt(l);while(ha;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return i.call(this,"readAsDataURL",e)},readAsText:function(e){return i.call(this,"readAsText",e)}})}}),i(I,[f,u,y],function(e,t,n){function i(){var e,i=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof n?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):i.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(n){t.each(i,function(e){n(e.value,e.name)}),e&&n(e.value,e.name)},destroy:function(){e=null,i=[]}})}return i}),i(T,[u,f,p,w,x,m,R,y,A,I,c,d],function(e,t,n,i,r,o,a,s,u,c,l,d){function h(){this.uid=e.guid("uid_")}function f(){function n(e,t){return w.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?w[e]:v[e]:void(l.can("define_property")?w[e]=t:v[e]=t):void 0}function u(t){function i(){B&&(B.destroy(),B=null),s.dispatchEvent("loadend"),s=null}function r(r){B.bind("LoadStart",function(e){n("readyState",f.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),O&&s.upload.dispatchEvent(e)}),B.bind("Progress",function(e){n("readyState")!==f.LOADING&&(n("readyState",f.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),B.bind("UploadProgress",function(e){O&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),B.bind("Load",function(t){n("readyState",f.DONE),n("status",Number(r.exec.call(B,"XMLHttpRequest","getStatus")||0)),n("statusText",p[n("status")]||""),n("response",r.exec.call(B,"XMLHttpRequest","getResponse",n("responseType"))),~e.inArray(n("responseType"),["text",""])?n("responseText",n("response")):"document"===n("responseType")&&n("responseXML",n("response")),k=r.exec.call(B,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),n("status")>0?(O&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(N=!0,s.dispatchEvent("error")),i()}),B.bind("Abort",function(e){s.dispatchEvent(e),i()}),B.bind("Error",function(e){N=!0,n("readyState",f.DONE),s.dispatchEvent("readystatechange"),D=!0,s.dispatchEvent(e),i()}),r.exec.call(B,"XMLHttpRequest","send",{url:E,method:_,async:y,user:x,password:R,headers:b,mimeType:I,encoding:A,responseType:s.responseType,withCredentials:s.withCredentials,options:H},t)}var s=this;C=(new Date).getTime(),B=new a,"string"==typeof H.required_caps&&(H.required_caps=o.parseCaps(H.required_caps)),H.required_caps=e.extend({},H.required_caps,{return_response_type:s.responseType}),t instanceof c&&(H.required_caps.send_multipart=!0),e.isEmptyObj(b)||(H.required_caps.send_custom_headers=!0),L||(H.required_caps.do_cors=!0),H.ruid?r(B.connectRuntime(H)):(B.bind("RuntimeInit",function(e,t){r(t)}),B.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),B.connectRuntime(H))}function g(){n("responseText",""),n("responseXML",null),n("response",null),n("status",0),n("statusText",""),C=M=null}var v=this,w={timeout:0,readyState:f.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},y=!0,E,_,b={},x,R,A=null,I=null,T=!1,S=!1,O=!1,D=!1,N=!1,L=!1,C,M,F=null,P=null,H={},B,k="",U;e.extend(this,w,{uid:e.guid("uid_"),upload:new h,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||i.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(_=o.toUpperCase()),~e.inArray(_,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=i.utf8_encode(a),l=r.parseUrl(a),L=r.hasSameOrigin(l),E=r.resolveUrl(a),(u||c)&&!L)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(x=u||l.user,R=c||l.pass,y=s||!0,y===!1&&(n("timeout")||n("withCredentials")||""!==n("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);T=!y,S=!1,b={},g.call(this),n("readyState",f.OPENED),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(n("readyState")!==f.OPENED||S)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||i.utf8_encode(r)!==r)throw new t.DOMException(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(b[r]?b[r]+=", "+o:b[r]=o,!0)},getAllResponseHeaders:function(){return k||""},getResponseHeader:function(t){return t=t.toLowerCase(),N||~e.inArray(t,["set-cookie","set-cookie2"])?null:k&&""!==k&&(U||(U={},e.each(k.split(/\r\n/),function(t){var n=t.split(/:\s+/);2===n.length&&(n[0]=e.trim(n[0]),U[n[0].toLowerCase()]={header:n[0],value:e.trim(n[1])})})),U.hasOwnProperty(t))?U[t].header+": "+U[t].value:null},overrideMimeType:function(i){var r,o;if(~e.inArray(n("readyState"),[f.LOADING,f.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i=e.trim(i.toLowerCase()),/;/.test(i)&&(r=i.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(i=r[1],r[2]&&(o=r[2])),!d.mimes[i])throw new t.DOMException(t.DOMException.SYNTAX_ERR);F=i,P=o},send:function(n,r){if(H="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.readyState!==f.OPENED||S)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n instanceof s)H.ruid=n.ruid,I=n.type||"application/octet-stream";else if(n instanceof c){if(n.hasBlob()){var o=n.getBlob();H.ruid=o.ruid,I=o.type||"application/octet-stream"}}else"string"==typeof n&&(A="UTF-8",I="text/plain;charset=UTF-8",n=i.utf8_encode(n));this.withCredentials||(this.withCredentials=H.required_caps&&H.required_caps.send_browser_cookies&&!L),O=!T&&this.upload.hasEventListener(),N=!1,D=!n,T||(S=!0),u.call(this,n)},abort:function(){if(N=!0,T=!1,~e.inArray(n("readyState"),[f.UNSENT,f.OPENED,f.DONE]))n("readyState",f.UNSENT);else{if(n("readyState",f.DONE),S=!1,!B)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);B.getRuntime().exec.call(B,"XMLHttpRequest","abort",D),D=!0}},destroy:function(){B&&("function"===e.typeOf(B.destroy)&&B.destroy(),B=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}}),this.handleEventProps(m.concat(["readystatechange"])),this.upload.handleEventProps(m)}var p={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};h.prototype=n.instance;var m=["loadstart","progress","abort","error","load","timeout","loadend"],g=1,v=2;return f.UNSENT=0,f.OPENED=1,f.HEADERS_RECEIVED=2,f.LOADING=3,f.DONE=4,f.prototype=n.instance,f}),i(S,[u,w,g,p],function(e,t,n,i){function r(){function i(){l=d=0,c=this.result=null}function o(t,n){var i=this;u=n,i.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(i.state,[r.IDLE,r.DONE])&&a.call(i)},999),i.bind("TransportingComplete",function(){d=l,i.state=r.DONE,c=null,i.result=u.exec.call(i,"Transporter","getAsBlob",t||"")},999),i.state=r.BUSY,i.trigger("TransportingStarted"),a.call(i)}function a(){var e=this,n,i=l-d;h>i&&(h=i),n=t.btoa(c.substr(d,h)),u.exec.call(e,"Transporter","receive",n,l)}var s,u,c,l,d,h;n.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,n,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)&&(r.chunk_size+=3-s),h=r.chunk_size,i.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,n,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,n,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),i.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),i.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=i.instance,r}),i(O,[u,h,f,A,T,m,g,S,c,p,y,E,w],function(e,t,n,i,r,o,a,s,u,c,l,d,h){function f(){function i(e){e||(e=this.exec("Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}function c(t){var i=e.typeOf(t);try{if(t instanceof f){if(!t.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);m.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new n.ImageError(n.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(i,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===i)"data:"===t.substr(0,5)?c.call(this,new l(null,{data:t}),arguments[1]):v.apply(this,arguments);else{if("node"!==i||"img"!==t.nodeName.toLowerCase())throw new n.DOMException(n.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r.code)}}function m(t,n){var i=this.connectRuntime(t.ruid);this.ruid=i.uid,i.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(n)?!0:n)}function g(t,n){function i(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){i(t)}),n&&"string"==typeof n.required_caps&&(n.required_caps=o.parseCaps(n.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},n))):i(this.connectRuntime(t.ruid))}function v(e,t){var n=this,i;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){c.apply(this,arguments)},downsize:function(t){var i={width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90,crop:!1,preserveHeaders:!0,resample:!1};t="object"==typeof t?e.extend(i,t):e.extend(i,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]});try{if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>f.MAX_RESIZE_WIDTH||this.height>f.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);this.exec("Image","downsize",t.width,t.height,t.crop,t.preserveHeaders)}catch(r){this.trigger("error",r.code)}},crop:function(e,t,n){this.downsize(e,t,!0,n)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);var e=this.connectRuntime(this.ruid);return e.exec.call(this,"Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsBlob",e||"image/jpeg",t||90)},getAsDataURL:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsDataURL",e||"image/jpeg",t||90)},getAsBinaryString:function(e,t){var n=this.getAsDataURL(e,t);return h.atob(n.substring(n.indexOf("base64,")+7))},embed:function(i,r){function o(t,r){var o=this;if(u.can("create_canvas")){var l=o.getAsCanvas();if(l)return i.appendChild(l),l=null,o.destroy(),void a.trigger("embedded")}var d=o.getAsDataURL(t,r);if(!d)throw new n.ImageError(n.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",d.length))i.innerHTML='',o.destroy(),a.trigger("embedded");else{var f=new s;f.bind("TransportingComplete",function(){c=a.connectRuntime(this.result.ruid),a.bind("Embedded",function(){e.extend(c.getShimContainer().style,{top:"0px",left:"0px",width:o.width+"px",height:o.height+"px"}),c=null},999),c.exec.call(a,"ImageView","display",this.result.uid,width,height),o.destroy()}),f.transport(h.atob(d.substring(d.indexOf("base64,")+7)),t,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:i})}}var a=this,c;r=e.extend({width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90},r||{});try{if(!(i=t.get(i)))throw new n.DOMException(n.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);this.width>f.MAX_RESIZE_WIDTH||this.height>f.MAX_RESIZE_HEIGHT;var l=new f;return l.bind("Resize",function(){o.call(this,r.type,r.quality)}),l.bind("Load",function(){l.downsize(r)}),this.meta.thumb&&this.meta.thumb.width>=r.width&&this.meta.thumb.height>=r.height?l.load(this.meta.thumb.data):l.clone(this,!1),l}catch(d){this.trigger("error",d.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}}),this.handleEventProps(p),this.bind("Load Resize",function(){i.call(this)},999)}var p=["progress","load","error","resize","embedded"];return f.MAX_RESIZE_WIDTH=8192,f.MAX_RESIZE_HEIGHT=8192,f.prototype=c.instance,f}),i(D,[u,f,m,c],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue,c=e.extend({access_binary:s(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return r.can("access_binary")&&!!a.Image},display_media:s(i.can("create_canvas")||i.can("use_data_uri_over32kb")),do_cors:s(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:s(function(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==i.browser||i.verComp(i.version,9,">"))}()),filter_by_extension:s(function(){return"Chrome"===i.browser&&i.verComp(i.version,28,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||"Safari"===i.browser&&i.verComp(i.version,7,">=")}()),return_response_headers:u,return_response_type:function(e){return"json"===e&&window.JSON?!0:i.can("return_response_type",e)},return_status_code:u,report_upload_progress:s(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return r.can("access_binary")&&i.can("create_canvas")},select_file:function(){return i.can("use_fileinput")&&window.File},select_folder:function(){return r.can("select_file")&&"Chrome"===i.browser&&i.verComp(i.version,21,">=")},select_multiple:function(){return!(!r.can("select_file")||"Safari"===i.browser&&"Windows"===i.os||"iOS"===i.os&&i.verComp(i.osVersion,"7.0.0",">")&&i.verComp(i.osVersion,"8.0.0","<"))},send_binary_string:s(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:s(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||r.can("send_binary_string")},slice_blob:s(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return r.can("slice_blob")&&r.can("send_multipart")},summon_file_dialog:function(){return r.can("select_file")&&("Firefox"===i.browser&&i.verComp(i.version,4,">=")||"Opera"===i.browser&&i.verComp(i.version,12,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||!!~e.inArray(i.browser,["Chrome","Safari"]))},upload_filesize:u},arguments[2]);n.call(this,t,arguments[1]||o,c),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html5",a={};return n.addConstructor(o,r),a}),i(N,[u],function(e){function t(){this.returnValue=!1}function n(){this.cancelBubble=!0}var i={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=n,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid()),i.hasOwnProperty(o[r])||(i[o[r]]={}),l=i[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,n,o){var a,s;if(n=n.toLowerCase(),t[r]&&i[t[r]]&&i[t[r]][n]){a=i[t[r]][n];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(n,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+n,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete i[t[r]][n],e.isEmptyObj(i[t[r]])){delete i[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,n){t&&t[r]&&e.each(i[t[r]],function(e,i){a(t,i,n)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),i(L,[D,E,u,h,N,d,c],function(e,t,n,i,r,o,a){function s(){var e;n.extend(this,{init:function(s){var u=this,c=u.getRuntime(),l,d,h,f,p,m;e=s,h=e.accept.mimes||o.extList2mimes(e.accept,c.can("filter_by_extension")),d=c.getShimContainer(),d.innerHTML='",l=i.get(c.uid),n.extend(l.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),f=i.get(e.browse_button),c.can("summon_file_dialog")&&("static"===i.getStyle(f,"position")&&(f.style.position="relative"),p=parseInt(i.getStyle(f,"z-index"),10)||1,f.style.zIndex=p,d.style.zIndex=p-1,r.addEvent(f,"click",function(e){var t=i.get(c.uid);t&&!t.disabled&&t.click(),e.preventDefault()},u.uid)),m=c.can("summon_file_dialog")?f:d,r.addEvent(m,"mouseover",function(){u.trigger("mouseenter")},u.uid),r.addEvent(m,"mouseout",function(){u.trigger("mouseleave")},u.uid),r.addEvent(m,"mousedown",function(){u.trigger("mousedown")},u.uid),r.addEvent(i.get(e.container),"mouseup",function(){u.trigger("mouseup")},u.uid),l.onchange=function g(i){if(u.files=[],n.each(this.files,function(n){var i="";return e.directory&&"."==n.name?!0:(n.webkitRelativePath&&(i="/"+n.webkitRelativePath.replace(/^\//,"")),n=new t(c.uid,n),n.relativePath=i,void u.files.push(n))}),"IE"!==a.browser&&"IEMobile"!==a.browser)this.value="";else{var r=this.cloneNode(!0);this.parentNode.replaceChild(r,this),r.onchange=g}u.files.length&&u.trigger("change")},u.trigger({type:"ready",async:!0}),d=null},disable:function(e){var t=this.getRuntime(),n;(n=i.get(t.uid))&&(n.disabled=!!e)},destroy:function(){var t=this.getRuntime(),n=t.getShim(),o=t.getShimContainer();r.removeAllEvents(o,this.uid),r.removeAllEvents(e&&i.get(e.container),this.uid),r.removeAllEvents(e&&i.get(e.browse_button),this.uid),o&&(o.innerHTML=""),n.removeInstance(this.uid),e=o=n=null}})}return e.FileInput=s}),i(C,[D,y],function(e,t){function n(){function e(e,t,n){var i;if(!window.File.prototype.slice)return(i=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?i.call(e,t,n):null;try{return e.slice(),e.slice(t,n)}catch(r){return e.slice(t,n-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))}}return e.Blob=n}),i(M,[D,E,u,h,N,d],function(e,t,n,i,r,o){function a(){function e(e){if(!e.dataTransfer||!e.dataTransfer.types)return!1;var t=n.toArray(e.dataTransfer.types||[]);return-1!==n.inArray("Files",t)||-1!==n.inArray("public.file-url",t)||-1!==n.inArray("application/x-moz-file",t)}function a(e,n){if(u(e)){var i=new t(g,e);i.relativePath=n||"",f.push(i)}}function s(e){for(var t=[],i=0;i=")&&u.verComp(u.version,7,"<"),h="Android Browser"===u.browser,m=!1;if(p=n.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),f=c(),f.open(n.method,n.url,n.async,n.user,n.password),r instanceof o)r.isDetached()&&(m=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),m=!0;else if((l||h)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return void e.call(s,n,r);if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}f.upload?(n.withCredentials&&(f.withCredentials=!0),f.addEventListener("load",function(e){s.trigger(e)}),f.addEventListener("error",function(e){s.trigger(e)}),f.addEventListener("progress",function(e){s.trigger(e)}),f.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):f.onreadystatechange=function v(){switch(f.readyState){case 1:break;case 2:break;case 3:var e,t;try{i.hasSameOrigin(n.url)&&(e=f.getResponseHeader("Content-Length")||0),f.responseText&&(t=f.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:f.onreadystatechange=function(){},s.trigger(0===f.status?"error":"load")}},t.isEmptyObj(n.headers)||t.each(n.headers,function(e,t){f.setRequestHeader(t,e)}),""!==n.responseType&&"responseType"in f&&("json"!==n.responseType||u.can("return_response_type","json")?f.responseType=n.responseType:f.responseType="text"),m?f.sendAsBinary?f.sendAsBinary(r):!function(){for(var e=new Uint8Array(r.length),t=0;t0&&o.set(new Uint8Array(t.slice(0,e)),0),o.set(new Uint8Array(r),e),o.set(new Uint8Array(t.slice(e+i)),e+r.byteLength),this.clear(),t=o.buffer,n=new DataView(t);break}default:return t}},length:function(){return t?t.byteLength:0},clear:function(){n=t=null}})}function i(t){function n(e,n,i){i=3===arguments.length?i:t.length-n-1,t=t.substr(0,n)+e+t.substr(i+n)}e.extend(this,{readByteAt:function(e){return t.charCodeAt(e)},writeByteAt:function(e,t){n(String.fromCharCode(t),e,1)},SEGMENT:function(e,i,r){switch(arguments.length){case 1:return t.substr(e);case 2:return t.substr(e,i);case 3:n(null!==r?r:"",e,i);break;default:return t}},length:function(){return t?t.length:0},clear:function(){t=null}})}return e.extend(t.prototype,{littleEndian:!1,read:function(e,t){var n,i,r;if(e+t>this.length())throw new Error("You are trying to read outside the source boundaries.");for(i=this.littleEndian?0:-8*(t-1),r=0,n=0;t>r;r++)n|=this.readByteAt(e+r)<this.length())throw new Error("You are trying to write outside the source boundaries.");for(i=this.littleEndian?0:-8*(n-1),r=0;n>r;r++)this.writeByteAt(e+r,t>>Math.abs(i+8*r)&255)},BYTE:function(e){return this.read(e,1)},SHORT:function(e){return this.read(e,2)},LONG:function(e){return this.read(e,4)},SLONG:function(e){var t=this.read(e,4);return t>2147483647?t-4294967296:t},CHAR:function(e){return String.fromCharCode(this.read(e,1))},STRING:function(e,t){return this.asArray("CHAR",e,t).join("")},asArray:function(e,t,n){for(var i=[],r=0;n>r;r++)i[r]=this[e](t+r);return i}}),t}),i(B,[H,f],function(e,t){return function n(i){var r=[],o,a,s,u=0;if(o=new e(i),65496!==o.SHORT(0))throw o.clear(),new t.ImageError(t.ImageError.WRONG_FORMAT);for(a=2;a<=o.length();)if(s=o.SHORT(a),s>=65488&&65495>=s)a+=2;else{if(65498===s||65497===s)break;u=o.SHORT(a+2)+2,s>=65505&&65519>=s&&r.push({hex:s,name:"APP"+(15&s),start:a,length:u,segment:o.SEGMENT(a,u)}),a+=u}return o.clear(),{headers:r,restore:function(t){var n,i,o;for(o=new e(t),a=65504==o.SHORT(2)?4+o.SHORT(4):2,i=0,n=r.length;n>i;i++)o.SEGMENT(a,0,r[i].segment),a+=r[i].length;return t=o.SEGMENT(),o.clear(),t},strip:function(t){var i,r,o,a;for(o=new n(t),r=o.headers,o.purge(),i=new e(t),a=r.length;a--;)i.SEGMENT(r[a].start,r[a].length,"");return t=i.SEGMENT(),i.clear(),t},get:function(e){for(var t=[],n=0,i=r.length;i>n;n++)r[n].name===e.toUpperCase()&&t.push(r[n].segment);return t}, +set:function(e,t){var n=[],i,o,a;for("string"==typeof t?n.push(t):n=t,i=o=0,a=r.length;a>i&&(r[i].name===e.toUpperCase()&&(r[i].segment=n[o],r[i].length=n[o].length,o++),!(o>=n.length));i++);},purge:function(){this.headers=r=[]}}}}),i(k,[u,H,f],function(e,n,i){function r(o){function a(n,r){var o=this,a,s,u,c,h,f,p,m,g=[],v={},w={1:"BYTE",7:"UNDEFINED",2:"ASCII",3:"SHORT",4:"LONG",5:"RATIONAL",9:"SLONG",10:"SRATIONAL"},y={BYTE:1,UNDEFINED:1,ASCII:1,SHORT:2,LONG:4,RATIONAL:8,SLONG:4,SRATIONAL:8};for(a=o.SHORT(n),s=0;a>s;s++)if(g=[],p=n+2+12*s,u=r[o.SHORT(p)],u!==t){if(c=w[o.SHORT(p+=2)],h=o.LONG(p+=2),f=y[c],!f)throw new i.ImageError(i.ImageError.INVALID_META_ERR);if(p+=4,f*h>4&&(p=o.LONG(p)+d.tiffHeader),p+f*h>=this.length())throw new i.ImageError(i.ImageError.INVALID_META_ERR);"ASCII"!==c?(g=o.asArray(c,p,h),m=1==h?g[0]:g,l.hasOwnProperty(u)&&"object"!=typeof m?v[u]=l[u][m]:v[u]=m):v[u]=e.trim(o.STRING(p,h).replace(/\0$/,""))}return v}function s(e,t,n){var i,r,o,a=0;if("string"==typeof t){var s=c[e.toLowerCase()];for(var u in s)if(s[u]===t){t=u;break}}i=d[e.toLowerCase()+"IFD"],r=this.SHORT(i);for(var l=0;r>l;l++)if(o=i+12*l+2,this.SHORT(o)==t){a=o+8;break}if(!a)return!1;try{this.write(a,n,4)}catch(h){return!1}return!0}var u,c,l,d,h,f;if(n.call(this,o),c={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"},thumb:{513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},d={tiffHeader:10},h=d.tiffHeader,u={clear:this.clear},e.extend(this,{read:function(){try{return r.prototype.read.apply(this,arguments)}catch(e){throw new i.ImageError(i.ImageError.INVALID_META_ERR)}},write:function(){try{return r.prototype.write.apply(this,arguments)}catch(e){throw new i.ImageError(i.ImageError.INVALID_META_ERR)}},UNDEFINED:function(){return this.BYTE.apply(this,arguments)},RATIONAL:function(e){return this.LONG(e)/this.LONG(e+4)},SRATIONAL:function(e){return this.SLONG(e)/this.SLONG(e+4)},ASCII:function(e){return this.CHAR(e)},TIFF:function(){return f||null},EXIF:function(){var t=null;if(d.exifIFD){try{t=a.call(this,d.exifIFD,c.exif)}catch(n){return null}if(t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var i=0,r="";i=65472&&65475>=n)return t+=5,{height:e.SHORT(t),width:e.SHORT(t+=2)};i=e.SHORT(t+=2),t+=i-2}return null}function s(){var e=d.thumb(),t,n;return e&&(t=new i(e),n=a(t),t.clear(),n)?(n.data=e,n):null}function u(){d&&l&&c&&(d.clear(),l.purge(),c.clear(),h=l=d=c=null)}var c,l,d,h;if(c=new i(o),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new n(o);try{d=new r(l.get("app1")[0])}catch(f){}h=a.call(this),e.extend(this,{type:"image/jpeg",size:c.length(),width:h&&h.width||0,height:h&&h.height||0,setExif:function(t,n){return d?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,n),void l.set("app1",d.SEGMENT())):!1},writeHeaders:function(){return l.restore(arguments.length?arguments[0]:o)},stripHeaders:function(e){return l.strip(e)},purge:function(){u.call(this)}}),d&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS(),thumb:s()})}return o}),i(G,[f,u,H],function(e,t,n){function i(i){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:s.LONG(t),height:s.LONG(t+=4)}):null}function o(){s&&(s.clear(),i=l=u=c=s=null)}function a(e){var t,n,i,r;return t=s.LONG(e),n=s.STRING(e+=4,4),i=e+=4,r=s.LONG(e+t),{length:t,type:n,start:i,CRC:r}}var s,u,c,l;s=new n(i),function(){var t=0,n=0,i=[35152,20039,3338,6666];for(n=0;ng;){for(var v=g+h>a?a-g:h,w=0;o>w;){var y=w+h>o?o-w:h;p.clearRect(0,0,h,h),p.drawImage(e,-w,-g);var E=w*s/o+c<<0,_=Math.ceil(y*s/o),b=g*u/a/m+l<<0,x=Math.ceil(v*u/a/m);d.drawImage(f,0,0,y,v,E,b,_,x),w+=h}g+=h}f=p=null}function t(e){var t=e.naturalWidth,n=e.naturalHeight;if(t*n>1048576){var i=document.createElement("canvas");i.width=i.height=1;var r=i.getContext("2d");return r.drawImage(e,-t+1,0),0===r.getImageData(0,0,1,1).data[3]}return!1}function n(e,t,n){var i=document.createElement("canvas");i.width=1,i.height=n;var r=i.getContext("2d");r.drawImage(e,0,0);for(var o=r.getImageData(0,0,1,n).data,a=0,s=n,u=n;u>a;){var c=o[4*(u-1)+3];0===c?s=u:a=u,u=s+a>>1}i=null;var l=u/n;return 0===l?1:l}return{isSubsampled:t,renderTo:e}}),i(j,[D,u,f,w,y,E,z,q,d,c],function(e,t,n,i,r,o,a,s,u,c){function l(){function e(){if(!_&&!y)throw new n.ImageError(n.DOMException.INVALID_STATE_ERR);return _||y}function l(e){return i.atob(e.substring(e.indexOf("base64,")+7))}function d(e,t){return"data:"+(t||"")+";base64,"+i.btoa(e)}function h(e){var t=this;y=new Image,y.onerror=function(){v.call(this),t.trigger("error",n.ImageError.WRONG_FORMAT)},y.onload=function(){t.trigger("load")},y.src="data:"==e.substr(0,5)?e:d(e,x.type)}function f(e,t){var i=this,r;return window.FileReader?(r=new FileReader,r.onload=function(){t(this.result)},r.onerror=function(){i.trigger("error",n.ImageError.WRONG_FORMAT)},r.readAsDataURL(e),void 0):t(e.getAsDataURL())}function p(n,i,r,o){var a=this,s,u,c=0,l=0,d,h,f,p;if(A=o,p=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1,-1!==t.inArray(p,[5,6,7,8])){var v=n;n=i,i=v}return d=e(),r?(n=Math.min(n,d.width),i=Math.min(i,d.height),s=Math.max(n/d.width,i/d.height)):s=Math.min(n/d.width,i/d.height),s>1&&!r&&o?void this.trigger("Resize"):(_||(_=document.createElement("canvas")),h=Math.round(d.width*s),f=Math.round(d.height*s),r?(_.width=n,_.height=i,h>n&&(c=Math.round((h-n)/2)),f>i&&(l=Math.round((f-i)/2))):(_.width=h,_.height=f),A||g(_.width,_.height,p),m.call(this,d,_,-c,-l,h,f),this.width=_.width,this.height=_.height,R=!0,void a.trigger("Resize"))}function m(e,t,n,i,r,o){if("iOS"===c.OS)s.renderTo(e,t,{width:r,height:o,x:n,y:i});else{var a=t.getContext("2d");a.drawImage(e,n,i,r,o)}}function g(e,t,n){switch(n){case 5:case 6:case 7:case 8:_.width=t,_.height=e;break;default:_.width=e,_.height=t}var i=_.getContext("2d");switch(n){case 2:i.translate(e,0),i.scale(-1,1);break;case 3:i.translate(e,t),i.rotate(Math.PI);break;case 4:i.translate(0,t),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-t);break;case 7:i.rotate(.5*Math.PI),i.translate(e,-t),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-e,0)}}function v(){E&&(E.purge(),E=null),b=y=_=x=null,R=!1}var w=this,y,E,_,b,x,R=!1,A=!0;t.extend(this,{loadFromBlob:function(e){var t=this,i=t.getRuntime(),r=arguments.length>1?arguments[1]:!0;if(!i.can("access_binary"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);return x=e,e.isDetached()?(b=e.getSource(),void h.call(this,b)):void f.call(this,e.getSource(),function(e){r&&(b=l(e)),h.call(t,e)})},loadFromImage:function(e,t){this.meta=e.meta,x=new o(null,{name:e.name,size:e.size,type:e.type}),h.call(this,t?b=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t=this.getRuntime(),n;return!E&&b&&t.can("access_image_binary")&&(E=new a(b)),n={width:e().width||0,height:e().height||0,type:x.type||u.getFileMime(x.name),size:b&&b.length||x.size||0,name:x.name||"",meta:E&&E.meta||this.meta||{}},!n.meta||!n.meta.thumb||n.meta.thumb.data instanceof r||(n.meta.thumb.data=new r(null,{type:"image/jpeg",data:n.meta.thumb.data})),n},downsize:function(){p.apply(this,arguments)},getAsCanvas:function(){return _&&(_.id=this.uid+"_canvas"),_},getAsBlob:function(e,t){return e!==this.type&&p.call(this,this.width,this.height,!1),new o(null,{name:x.name||"",type:e,data:w.getAsBinaryString.call(this,e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!R)return y.src;if("image/jpeg"!==e)return _.toDataURL("image/png");try{return _.toDataURL("image/jpeg",t/100)}catch(n){return _.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!R)return b||(b=l(w.getAsDataURL(e,t))),b;if("image/jpeg"!==e)b=l(w.getAsDataURL(e,t));else{var n;t||(t=90);try{n=_.toDataURL("image/jpeg",t/100)}catch(i){n=_.toDataURL("image/jpeg")}b=l(n),E&&(b=E.stripHeaders(b),A&&(E.meta&&E.meta.exif&&E.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),b=E.writeHeaders(b)),E.purge(),E=null)}return R=!1,b},destroy:function(){w=null,v.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=l}),i(X,[u,c,h,f,m],function(e,t,n,i,r){function o(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(n){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function a(e){var i=n.get(e);i&&"OBJECT"==i.nodeName&&("IE"===t.browser?(i.style.display="none",function r(){4==i.readyState?s(e):setTimeout(r,10)}()):i.parentNode.removeChild(i))}function s(e){var t=n.get(e);if(t){for(var i in t)"function"==typeof t[i]&&(t[i]=null);t.parentNode.removeChild(t)}}function u(s){var u=this,d;s=e.extend({swf_url:t.swf_url},s),r.call(this,s,c,{access_binary:function(e){return e&&"browser"===u.mode},access_image_binary:function(e){return e&&"browser"===u.mode},display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===u.mode},resize_image:r.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===u.mode},return_status_code:function(t){return"browser"===u.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:function(e){return e&&"browser"===u.mode},send_browser_cookies:function(e){return e&&"browser"===u.mode},send_custom_headers:function(e){return e&&"browser"===u.mode},send_multipart:r.capTrue,slice_blob:function(e){return e&&"browser"===u.mode},stream_upload:function(e){return e&&"browser"===u.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===u.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),o()<10&&(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid)},shimExec:function(e,t){var n=[].slice.call(arguments,2);return u.getShim().exec(this.uid,e,t,n)},init:function(){var n,r,o;o=this.getShimContainer(),e.extend(o.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),n='',"IE"===t.browser?(r=document.createElement("div"),o.appendChild(r),r.outerHTML=n,r=o=null):o.innerHTML=n,d=setTimeout(function(){u&&!u.initialized&&u.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){a(u.uid),e.call(u),clearTimeout(d),s=d=e=u=null}}(this.destroy)},l)}var c="flash",l={};return r.addConstructor(c,u),l}),i(V,[X,E,u],function(e,t,n){var i={init:function(e){var i=this,r=this.getRuntime();this.bind("Change",function(){var e=r.shimExec.call(i,"FileInput","getFiles");i.files=[],n.each(e,function(e){i.files.push(new t(r.uid,e))})},999),this.getRuntime().shimExec.call(this,"FileInput","init",{name:e.name,accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=i}),i(W,[X,y],function(e,t){var n={slice:function(e,n,i,r){var o=this.getRuntime();return 0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),e=o.shimExec.call(this,"Blob","slice",n,i,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=n}),i(Y,[X,w],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i=this;return i.result="","readAsDataURL"===e&&(i.result="data:"+(t.type||"")+";base64,"),i.bind("Progress",function(t,r){r&&(i.result+=n(r,e))},999),i.getRuntime().shimExec.call(this,"FileReader","readAsBase64",t.uid)}};return e.FileReader=i}),i($,[X,w],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i,r=this.getRuntime();return(i=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"+i),n(i,e,t.type)):null}};return e.FileReaderSync=i}),i(J,[X,u,y,E,A,I,S],function(e,t,n,i,r,o,a){var s={send:function(e,i){function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,i)}function s(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),i=null,r()}function u(e,t){var n=new a;n.bind("TransportingComplete",function(){t(this.result)}),n.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),i instanceof o){var d;if(i.each(function(e,t){e instanceof n?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),i.hasBlob()){var h=i.getBlob();h.isDetached()?u(h,function(e){h.destroy(),s(d,e)}):s(d,h)}else i=null,r()}else i instanceof n?i.isDetached()?u(i,function(e){i.destroy(),i=e.uid,r()}):(i=i.uid,r()):r()},getResponse:function(e){var n,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob")){if(o=new i(a.uid,o),"blob"===e)return o;try{if(n=new r,~t.inArray(e,["","text"]))return n.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(n.readAsText(o))}finally{o.destroy()}}return null},abort:function(e){var t=this.getRuntime();t.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=s}),i(Z,[X,y],function(e,t){var n={getAsBlob:function(e){var n=this.getRuntime(),i=n.shimExec.call(this,"Transporter","getAsBlob",e);return i?new t(n.uid,i):null}};return e.Transporter=n}),i(K,[X,u,S,y,A],function(e,t,n,i,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(i,"Image","loadFromBlob",e.uid),i=r=null}var i=this,r=i.getRuntime();if(e.isDetached()){var o=new n;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSource(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getInfo:function(){var e=this.getRuntime(),t=e.shimExec.call(this,"Image","getInfo");return!t.meta||!t.meta.thumb||t.meta.thumb.data instanceof i||(t.meta.thumb.data=new i(e.uid,t.meta.thumb.data)),t},getAsBlob:function(e,t){var n=this.getRuntime(),r=n.shimExec.call(this,"Image","getAsBlob",e,t);return r?new i(n.uid,r):null},getAsDataURL:function(){var e=this.getRuntime(),t=e.Image.getAsBlob.apply(this,arguments),n;return t?(n=new r,n.readAsDataURL(t)):null}};return e.Image=o}),i(Q,[u,c,h,f,m],function(e,t,n,i,r){function o(e){var t=!1,n=null,i,r,o,a,s,u=0;try{try{n=new ActiveXObject("AgControl.AgControl"),n.IsVersionSupported(e)&&(t=!0),n=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(i=l.description,"1.0.30226.2"===i&&(i="2.0.30226.2"),r=i.split(".");r.length>3;)r.pop();for(;r.length<4;)r.push(0);for(o=e.split(".");o.length>4;)o.pop();do a=parseInt(o[u],10),s=parseInt(r[u],10),u++;while(u=a&&!isNaN(a)&&(t=!0)}}}catch(d){t=!1}return t}function a(a){var c=this,l;a=e.extend({xap_url:t.xap_url},a),r.call(this,a,s,{access_binary:r.capTrue,access_image_binary:r.capTrue,display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:r.capTrue,resize_image:r.capTrue,return_response_headers:function(e){return e&&"client"===c.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:r.capTrue,send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"client"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:r.capTrue,use_http_method:function(t){return"client"===c.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),o("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid).content.Moxie},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='',l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="silverlight",u={};return r.addConstructor(s,a),u}),i(ee,[Q,E,u],function(e,t,n){var i={init:function(e){function i(e){for(var t="",n=0;ni;i++)n=t.keys[i],s=t[n],s&&(/^(\d|[1-9]\d+)$/.test(s)?s=parseInt(s,10):/^\d*\.\d+$/.test(s)&&(s=parseFloat(s)),r.meta[e][n]=s)}),!r.meta||!r.meta.thumb||r.meta.thumb.data instanceof n||(r.meta.thumb.data=new n(e.uid,r.meta.thumb.data))),r.width=parseInt(o.width,10),r.height=parseInt(o.height,10),r.size=parseInt(o.size,10),r.type=o.type,r.name=o.name,r}})}),i(ue,[u,f,m,c],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue;n.call(this,t,o,{access_binary:s(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:s(a.Image&&(i.can("create_canvas")||i.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:s(function(){return"Chrome"===i.browser&&i.verComp(i.version,28,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||"Safari"===i.browser&&i.verComp(i.version,7,">=")}()),resize_image:function(){return a.Image&&r.can("access_binary")&&i.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return i.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return r.can("select_file")},summon_file_dialog:function(){return r.can("select_file")&&("Firefox"===i.browser&&i.verComp(i.version,4,">=")||"Opera"===i.browser&&i.verComp(i.version,12,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||!!~e.inArray(i.browser,["Chrome","Safari"]))},upload_filesize:u,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html4",a={};return n.addConstructor(o,r),a}),i(ce,[ue,E,u,h,N,d,c],function(e,t,n,i,r,o,a){function s(){function e(){var o=this,l=o.getRuntime(),d,h,f,p,m,g;g=n.guid("uid_"),d=l.getShimContainer(),s&&(f=i.get(s+"_form"),f&&n.extend(f.style,{top:"100%"})),p=document.createElement("form"),p.setAttribute("id",g+"_form"),p.setAttribute("method","post"),p.setAttribute("enctype","multipart/form-data"),p.setAttribute("encoding","multipart/form-data"),n.extend(p.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),m=document.createElement("input"),m.setAttribute("id",g),m.setAttribute("type","file"),m.setAttribute("name",c.name||"Filedata"),m.setAttribute("accept",u.join(",")),n.extend(m.style,{fontSize:"999px",opacity:0}),p.appendChild(m),d.appendChild(p),n.extend(m.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===a.browser&&a.verComp(a.version,10,"<")&&n.extend(m.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),m.onchange=function(){var n;if(this.value){if(this.files){if(n=this.files[0],0===n.size)return void p.parentNode.removeChild(p)}else n={name:this.value};n=new t(l.uid,n),this.onchange=function(){},e.call(o),o.files=[n],m.setAttribute("id",n.uid),p.setAttribute("id",n.uid+"_form"),o.trigger("change"),m=p=null}},l.can("summon_file_dialog")&&(h=i.get(c.browse_button),r.removeEvent(h,"click",o.uid),r.addEvent(h,"click",function(e){m&&!m.disabled&&m.click(),e.preventDefault()},o.uid)),s=g,d=f=h=null}var s,u=[],c;n.extend(this,{init:function(t){var n=this,a=n.getRuntime(),s;c=t,u=t.accept.mimes||o.extList2mimes(t.accept,a.can("filter_by_extension")),s=a.getShimContainer(),function(){var e,o,u;e=i.get(t.browse_button),a.can("summon_file_dialog")&&("static"===i.getStyle(e,"position")&&(e.style.position="relative"),o=parseInt(i.getStyle(e,"z-index"),10)||1,e.style.zIndex=o,s.style.zIndex=o-1),u=a.can("summon_file_dialog")?e:s,r.addEvent(u,"mouseover",function(){n.trigger("mouseenter")},n.uid),r.addEvent(u,"mouseout",function(){n.trigger("mouseleave")},n.uid),r.addEvent(u,"mousedown",function(){n.trigger("mousedown")},n.uid),r.addEvent(i.get(t.container),"mouseup",function(){n.trigger("mouseup")},n.uid),e=null}(),e.call(this),s=null,n.trigger({type:"ready",async:!0})},disable:function(e){var t;(t=i.get(s))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),n=e.getShimContainer();r.removeAllEvents(n,this.uid),r.removeAllEvents(c&&i.get(c.container),this.uid),r.removeAllEvents(c&&i.get(c.browse_button),this.uid),n&&(n.innerHTML=""),t.removeInstance(this.uid),s=u=c=n=t=null}})}return e.FileInput=s}),i(le,[ue,F],function(e,t){return e.FileReader=t}),i(de,[ue,u,h,x,f,N,y,I],function(e,t,n,i,r,o,a,s){function u(){function e(e){var t=this,i,r,a,s,u=!1;if(l){if(i=l.id.replace(/_iframe$/,""),r=n.get(i+"_form")){for(a=r.getElementsByTagName("input"),s=a.length;s--;)switch(a[s].getAttribute("type")){case"hidden":a[s].parentNode.removeChild(a[s]);break;case"file":u=!0}a=[],u||r.parentNode.removeChild(r),r=null}setTimeout(function(){o.removeEvent(l,"load",t.uid),l.parentNode&&l.parentNode.removeChild(l);var n=t.getRuntime().getShimContainer();n.children.length||n.parentNode.removeChild(n),n=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,h){function f(){var n=m.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='',l=r.firstChild,n.appendChild(l),o.addEvent(l,"load",function(){var n;try{n=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(n.title)?u=n.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(n.body.innerHTML),p.trigger({type:"progress",loaded:c.length,total:c.length}),y&&p.trigger({type:"uploadprogress",loaded:y.size||1025,total:y.size||1025}))}catch(r){if(!i.hasSameOrigin(d.url))return void e.call(p,function(){p.trigger("error")});u=404}e.call(p,function(){p.trigger("load")})},p.uid)}var p=this,m=p.getRuntime(),g,v,w,y;if(u=c=null,h instanceof s&&h.hasBlob()){if(y=h.getBlob(),g=y.uid,w=n.get(g),v=n.get(g+"_form"),!v)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else g=t.guid("uid_"),v=document.createElement("form"),v.setAttribute("id",g+"_form"),v.setAttribute("method",d.method),v.setAttribute("enctype","multipart/form-data"),v.setAttribute("encoding","multipart/form-data"),m.getShimContainer().appendChild(v);v.setAttribute("target",g+"_iframe"),h instanceof s&&h.each(function(e,n){if(e instanceof a)w&&w.setAttribute("name",n);else{var i=document.createElement("input");t.extend(i,{type:"hidden",name:n,value:e}),w?v.insertBefore(i,w):v.appendChild(i)}}),v.setAttribute("action",d.url),f(),v.submit(),p.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{ +return JSON.parse(c.replace(/^\s*]*>/,"").replace(/<\/pre>\s*$/,""))}catch(n){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})}})}return e.XMLHttpRequest=u}),i(he,[ue,j],function(e,t){return e.Image=t}),a([u,c,l,d,h,f,p,m,g,v,w,y,E,_,b,x,R,A,I,T,S,O,N])}(this);;(function(e){"use strict";var t={},n=e.moxie.core.utils.Basic.inArray;return function r(e){var i,s;for(i in e)s=typeof e[i],s==="object"&&!~n(i,["Exceptions","Env","Mime"])?r(e[i]):s==="function"&&(t[i]=e[i])}(e.moxie),t.Env=e.moxie.core.utils.Env,t.Mime=e.moxie.core.utils.Mime,t.Exceptions=e.moxie.core.Exceptions,e.mOxie=t,e.o||(e.o=t),t})(this); \ No newline at end of file diff --git a/qiniu_fields/static/qiniu_fields/plupload/plupload.dev.js b/qiniu_fields/static/qiniu_fields/plupload/plupload.dev.js new file mode 100644 index 0000000..606cf7f --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/plupload/plupload.dev.js @@ -0,0 +1,2347 @@ +/** + * Plupload - multi-runtime File Uploader + * v2.1.8 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2015-07-21 + */ +/** + * Plupload.js + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + */ + +/*global mOxie:true */ + +;(function(window, o, undef) { + +var delay = window.setTimeout +, fileFilters = {} +; + +// convert plupload features to caps acceptable by mOxie +function normalizeCaps(settings) { + var features = settings.required_features, caps = {}; + + function resolve(feature, value, strict) { + // Feature notation is deprecated, use caps (this thing here is required for backward compatibility) + var map = { + chunks: 'slice_blob', + jpgresize: 'send_binary_string', + pngresize: 'send_binary_string', + progress: 'report_upload_progress', + multi_selection: 'select_multiple', + dragdrop: 'drag_and_drop', + drop_element: 'drag_and_drop', + headers: 'send_custom_headers', + urlstream_upload: 'send_binary_string', + canSendBinary: 'send_binary', + triggerDialog: 'summon_file_dialog' + }; + + if (map[feature]) { + caps[map[feature]] = value; + } else if (!strict) { + caps[feature] = value; + } + } + + if (typeof(features) === 'string') { + plupload.each(features.split(/\s*,\s*/), function(feature) { + resolve(feature, true); + }); + } else if (typeof(features) === 'object') { + plupload.each(features, function(value, feature) { + resolve(feature, value); + }); + } else if (features === true) { + // check settings for required features + if (settings.chunk_size > 0) { + caps.slice_blob = true; + } + + if (settings.resize.enabled || !settings.multipart) { + caps.send_binary_string = true; + } + + plupload.each(settings, function(value, feature) { + resolve(feature, !!value, true); // strict check + }); + } + + return caps; +} + +/** + * @module plupload + * @static + */ +var plupload = { + /** + * Plupload version will be replaced on build. + * + * @property VERSION + * @for Plupload + * @static + * @final + */ + VERSION : '2.1.8', + + /** + * The state of the queue before it has started and after it has finished + * + * @property STOPPED + * @static + * @final + */ + STOPPED : 1, + + /** + * Upload process is running + * + * @property STARTED + * @static + * @final + */ + STARTED : 2, + + /** + * File is queued for upload + * + * @property QUEUED + * @static + * @final + */ + QUEUED : 1, + + /** + * File is being uploaded + * + * @property UPLOADING + * @static + * @final + */ + UPLOADING : 2, + + /** + * File has failed to be uploaded + * + * @property FAILED + * @static + * @final + */ + FAILED : 4, + + /** + * File has been uploaded successfully + * + * @property DONE + * @static + * @final + */ + DONE : 5, + + // Error constants used by the Error event + + /** + * Generic error for example if an exception is thrown inside Silverlight. + * + * @property GENERIC_ERROR + * @static + * @final + */ + GENERIC_ERROR : -100, + + /** + * HTTP transport error. For example if the server produces a HTTP status other than 200. + * + * @property HTTP_ERROR + * @static + * @final + */ + HTTP_ERROR : -200, + + /** + * Generic I/O error. For example if it wasn't possible to open the file stream on local machine. + * + * @property IO_ERROR + * @static + * @final + */ + IO_ERROR : -300, + + /** + * @property SECURITY_ERROR + * @static + * @final + */ + SECURITY_ERROR : -400, + + /** + * Initialization error. Will be triggered if no runtime was initialized. + * + * @property INIT_ERROR + * @static + * @final + */ + INIT_ERROR : -500, + + /** + * File size error. If the user selects a file that is too large it will be blocked and an error of this type will be triggered. + * + * @property FILE_SIZE_ERROR + * @static + * @final + */ + FILE_SIZE_ERROR : -600, + + /** + * File extension error. If the user selects a file that isn't valid according to the filters setting. + * + * @property FILE_EXTENSION_ERROR + * @static + * @final + */ + FILE_EXTENSION_ERROR : -601, + + /** + * Duplicate file error. If prevent_duplicates is set to true and user selects the same file again. + * + * @property FILE_DUPLICATE_ERROR + * @static + * @final + */ + FILE_DUPLICATE_ERROR : -602, + + /** + * Runtime will try to detect if image is proper one. Otherwise will throw this error. + * + * @property IMAGE_FORMAT_ERROR + * @static + * @final + */ + IMAGE_FORMAT_ERROR : -700, + + /** + * While working on files runtime may run out of memory and will throw this error. + * + * @since 2.1.2 + * @property MEMORY_ERROR + * @static + * @final + */ + MEMORY_ERROR : -701, + + /** + * Each runtime has an upper limit on a dimension of the image it can handle. If bigger, will throw this error. + * + * @property IMAGE_DIMENSIONS_ERROR + * @static + * @final + */ + IMAGE_DIMENSIONS_ERROR : -702, + + /** + * Mime type lookup table. + * + * @property mimeTypes + * @type Object + * @final + */ + mimeTypes : o.mimes, + + /** + * In some cases sniffing is the only way around :( + */ + ua: o.ua, + + /** + * Gets the true type of the built-in object (better version of typeof). + * @credits Angus Croll (http://javascriptweblog.wordpress.com/) + * + * @method typeOf + * @static + * @param {Object} o Object to check. + * @return {String} Object [[Class]] + */ + typeOf: o.typeOf, + + /** + * Extends the specified object with another object. + * + * @method extend + * @static + * @param {Object} target Object to extend. + * @param {Object..} obj Multiple objects to extend with. + * @return {Object} Same as target, the extended object. + */ + extend : o.extend, + + /** + * Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers. + * The only way a user would be able to get the same ID is if the two persons at the same exact millisecond manages + * to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique. + * It's more probable for the earth to be hit with an asteriod. You can also if you want to be 100% sure set the plupload.guidPrefix property + * to an user unique key. + * + * @method guid + * @static + * @return {String} Virtually unique id. + */ + guid : o.guid, + + /** + * Get array of DOM Elements by their ids. + * + * @method get + * @for Utils + * @param {String} id Identifier of the DOM Element + * @return {Array} + */ + get : function get(ids) { + var els = [], el; + + if (o.typeOf(ids) !== 'array') { + ids = [ids]; + } + + var i = ids.length; + while (i--) { + el = o.get(ids[i]); + if (el) { + els.push(el); + } + } + + return els.length ? els : null; + }, + + /** + * Executes the callback function for each item in array/object. If you return false in the + * callback it will break the loop. + * + * @method each + * @static + * @param {Object} obj Object to iterate. + * @param {function} callback Callback function to execute for each item. + */ + each : o.each, + + /** + * Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields. + * + * @method getPos + * @static + * @param {Element} node HTML element or element id to get x, y position from. + * @param {Element} root Optional root element to stop calculations at. + * @return {object} Absolute position of the specified element object with x, y fields. + */ + getPos : o.getPos, + + /** + * Returns the size of the specified node in pixels. + * + * @method getSize + * @static + * @param {Node} node Node to get the size of. + * @return {Object} Object with a w and h property. + */ + getSize : o.getSize, + + /** + * Encodes the specified string. + * + * @method xmlEncode + * @static + * @param {String} s String to encode. + * @return {String} Encoded string. + */ + xmlEncode : function(str) { + var xmlEncodeChars = {'<' : 'lt', '>' : 'gt', '&' : 'amp', '"' : 'quot', '\'' : '#39'}, xmlEncodeRegExp = /[<>&\"\']/g; + + return str ? ('' + str).replace(xmlEncodeRegExp, function(chr) { + return xmlEncodeChars[chr] ? '&' + xmlEncodeChars[chr] + ';' : chr; + }) : str; + }, + + /** + * Forces anything into an array. + * + * @method toArray + * @static + * @param {Object} obj Object with length field. + * @return {Array} Array object containing all items. + */ + toArray : o.toArray, + + /** + * Find an element in array and return its index if present, otherwise return -1. + * + * @method inArray + * @static + * @param {mixed} needle Element to find + * @param {Array} array + * @return {Int} Index of the element, or -1 if not found + */ + inArray : o.inArray, + + /** + * Extends the language pack object with new items. + * + * @method addI18n + * @static + * @param {Object} pack Language pack items to add. + * @return {Object} Extended language pack object. + */ + addI18n : o.addI18n, + + /** + * Translates the specified string by checking for the english string in the language pack lookup. + * + * @method translate + * @static + * @param {String} str String to look for. + * @return {String} Translated string or the input string if it wasn't found. + */ + translate : o.translate, + + /** + * Checks if object is empty. + * + * @method isEmptyObj + * @static + * @param {Object} obj Object to check. + * @return {Boolean} + */ + isEmptyObj : o.isEmptyObj, + + /** + * Checks if specified DOM element has specified class. + * + * @method hasClass + * @static + * @param {Object} obj DOM element like object to add handler to. + * @param {String} name Class name + */ + hasClass : o.hasClass, + + /** + * Adds specified className to specified DOM element. + * + * @method addClass + * @static + * @param {Object} obj DOM element like object to add handler to. + * @param {String} name Class name + */ + addClass : o.addClass, + + /** + * Removes specified className from specified DOM element. + * + * @method removeClass + * @static + * @param {Object} obj DOM element like object to add handler to. + * @param {String} name Class name + */ + removeClass : o.removeClass, + + /** + * Returns a given computed style of a DOM element. + * + * @method getStyle + * @static + * @param {Object} obj DOM element like object. + * @param {String} name Style you want to get from the DOM element + */ + getStyle : o.getStyle, + + /** + * Adds an event handler to the specified object and store reference to the handler + * in objects internal Plupload registry (@see removeEvent). + * + * @method addEvent + * @static + * @param {Object} obj DOM element like object to add handler to. + * @param {String} name Name to add event listener to. + * @param {Function} callback Function to call when event occurs. + * @param {String} (optional) key that might be used to add specifity to the event record. + */ + addEvent : o.addEvent, + + /** + * Remove event handler from the specified object. If third argument (callback) + * is not specified remove all events with the specified name. + * + * @method removeEvent + * @static + * @param {Object} obj DOM element to remove event listener(s) from. + * @param {String} name Name of event listener to remove. + * @param {Function|String} (optional) might be a callback or unique key to match. + */ + removeEvent: o.removeEvent, + + /** + * Remove all kind of events from the specified object + * + * @method removeAllEvents + * @static + * @param {Object} obj DOM element to remove event listeners from. + * @param {String} (optional) unique key to match, when removing events. + */ + removeAllEvents: o.removeAllEvents, + + /** + * Cleans the specified name from national characters (diacritics). The result will be a name with only a-z, 0-9 and _. + * + * @method cleanName + * @static + * @param {String} s String to clean up. + * @return {String} Cleaned string. + */ + cleanName : function(name) { + var i, lookup; + + // Replace diacritics + lookup = [ + /[\300-\306]/g, 'A', /[\340-\346]/g, 'a', + /\307/g, 'C', /\347/g, 'c', + /[\310-\313]/g, 'E', /[\350-\353]/g, 'e', + /[\314-\317]/g, 'I', /[\354-\357]/g, 'i', + /\321/g, 'N', /\361/g, 'n', + /[\322-\330]/g, 'O', /[\362-\370]/g, 'o', + /[\331-\334]/g, 'U', /[\371-\374]/g, 'u' + ]; + + for (i = 0; i < lookup.length; i += 2) { + name = name.replace(lookup[i], lookup[i + 1]); + } + + // Replace whitespace + name = name.replace(/\s+/g, '_'); + + // Remove anything else + name = name.replace(/[^a-z0-9_\-\.]+/gi, ''); + + return name; + }, + + /** + * Builds a full url out of a base URL and an object with items to append as query string items. + * + * @method buildUrl + * @static + * @param {String} url Base URL to append query string items to. + * @param {Object} items Name/value object to serialize as a querystring. + * @return {String} String with url + serialized query string items. + */ + buildUrl : function(url, items) { + var query = ''; + + plupload.each(items, function(value, name) { + query += (query ? '&' : '') + encodeURIComponent(name) + '=' + encodeURIComponent(value); + }); + + if (query) { + url += (url.indexOf('?') > 0 ? '&' : '?') + query; + } + + return url; + }, + + /** + * Formats the specified number as a size string for example 1024 becomes 1 KB. + * + * @method formatSize + * @static + * @param {Number} size Size to format as string. + * @return {String} Formatted size string. + */ + formatSize : function(size) { + + if (size === undef || /\D/.test(size)) { + return plupload.translate('N/A'); + } + + function round(num, precision) { + return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision); + } + + var boundary = Math.pow(1024, 4); + + // TB + if (size > boundary) { + return round(size / boundary, 1) + " " + plupload.translate('tb'); + } + + // GB + if (size > (boundary/=1024)) { + return round(size / boundary, 1) + " " + plupload.translate('gb'); + } + + // MB + if (size > (boundary/=1024)) { + return round(size / boundary, 1) + " " + plupload.translate('mb'); + } + + // KB + if (size > 1024) { + return Math.round(size / 1024) + " " + plupload.translate('kb'); + } + + return size + " " + plupload.translate('b'); + }, + + + /** + * Parses the specified size string into a byte value. For example 10kb becomes 10240. + * + * @method parseSize + * @static + * @param {String|Number} size String to parse or number to just pass through. + * @return {Number} Size in bytes. + */ + parseSize : o.parseSizeStr, + + + /** + * A way to predict what runtime will be choosen in the current environment with the + * specified settings. + * + * @method predictRuntime + * @static + * @param {Object|String} config Plupload settings to check + * @param {String} [runtimes] Comma-separated list of runtimes to check against + * @return {String} Type of compatible runtime + */ + predictRuntime : function(config, runtimes) { + var up, runtime; + + up = new plupload.Uploader(config); + runtime = o.Runtime.thatCan(up.getOption().required_features, runtimes || config.runtimes); + up.destroy(); + return runtime; + }, + + /** + * Registers a filter that will be executed for each file added to the queue. + * If callback returns false, file will not be added. + * + * Callback receives two arguments: a value for the filter as it was specified in settings.filters + * and a file to be filtered. Callback is executed in the context of uploader instance. + * + * @method addFileFilter + * @static + * @param {String} name Name of the filter by which it can be referenced in settings.filters + * @param {String} cb Callback - the actual routine that every added file must pass + */ + addFileFilter: function(name, cb) { + fileFilters[name] = cb; + } +}; + + +plupload.addFileFilter('mime_types', function(filters, file, cb) { + if (filters.length && !filters.regexp.test(file.name)) { + this.trigger('Error', { + code : plupload.FILE_EXTENSION_ERROR, + message : plupload.translate('File extension error.'), + file : file + }); + cb(false); + } else { + cb(true); + } +}); + + +plupload.addFileFilter('max_file_size', function(maxSize, file, cb) { + var undef; + + maxSize = plupload.parseSize(maxSize); + + // Invalid file size + if (file.size !== undef && maxSize && file.size > maxSize) { + this.trigger('Error', { + code : plupload.FILE_SIZE_ERROR, + message : plupload.translate('File size error.'), + file : file + }); + cb(false); + } else { + cb(true); + } +}); + + +plupload.addFileFilter('prevent_duplicates', function(value, file, cb) { + if (value) { + var ii = this.files.length; + while (ii--) { + // Compare by name and size (size might be 0 or undefined, but still equivalent for both) + if (file.name === this.files[ii].name && file.size === this.files[ii].size) { + this.trigger('Error', { + code : plupload.FILE_DUPLICATE_ERROR, + message : plupload.translate('Duplicate file error.'), + file : file + }); + cb(false); + return; + } + } + } + cb(true); +}); + + +/** +@class Uploader +@constructor + +@param {Object} settings For detailed information about each option check documentation. + @param {String|DOMElement} settings.browse_button id of the DOM element or DOM element itself to use as file dialog trigger. + @param {String} settings.url URL of the server-side upload handler. + @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled. + @param {Boolean} [settings.send_chunk_number=true] Whether to send chunks and chunk numbers, or total and offset bytes. + @param {String|DOMElement} [settings.container] id of the DOM element or DOM element itself that will be used to wrap uploader structures. Defaults to immediate parent of the `browse_button` element. + @param {String|DOMElement} [settings.drop_element] id of the DOM element or DOM element itself to use as a drop zone for Drag-n-Drop. + @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message. + @param {Object} [settings.filters={}] Set of file type filters. + @param {Array} [settings.filters.mime_types=[]] List of file types to accept, each one defined by title and list of extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR` + @param {String|Number} [settings.filters.max_file_size=0] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`. + @param {Boolean} [settings.filters.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`. + @param {String} [settings.flash_swf_url] URL of the Flash swf. + @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs. + @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event. + @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message. + @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload. + @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog. + @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess. + @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}` + @param {Number} [settings.resize.width] If image is bigger, it will be resized. + @param {Number} [settings.resize.height] If image is bigger, it will be resized. + @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100). + @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally. + @param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails. + @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap. + @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files. + @param {Boolean} [settings.send_file_name=true] Whether to send file name as additional argument - 'name' (required for chunked uploads and some other cases where file name cannot be sent via normal ways). +*/ +plupload.Uploader = function(options) { + /** + Fires when the current RunTime has been initialized. + + @event Init + @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + Fires after the init event incase you need to perform actions there. + + @event PostInit + @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + Fires when the option is changed in via uploader.setOption(). + + @event OptionChanged + @since 2.1 + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {String} name Name of the option that was changed + @param {Mixed} value New value for the specified option + @param {Mixed} oldValue Previous value of the option + */ + + /** + Fires when the silverlight/flash or other shim needs to move. + + @event Refresh + @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + Fires when the overall state is being changed for the upload queue. + + @event StateChanged + @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + Fires when browse_button is clicked and browse dialog shows. + + @event Browse + @since 2.1.2 + @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + Fires for every filtered file before it is added to the queue. + + @event FileFiltered + @since 2.1 + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {plupload.File} file Another file that has to be added to the queue. + */ + + /** + Fires when the file queue is changed. In other words when files are added/removed to the files array of the uploader instance. + + @event QueueChanged + @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + + /** + Fires after files were filtered and added to the queue. + + @event FilesAdded + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {Array} files Array of file objects that were added to queue by the user. + */ + + /** + Fires when file is removed from the queue. + + @event FilesRemoved + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {Array} files Array of files that got removed. + */ + + /** + Fires just before a file is uploaded. Can be used to cancel the upload for the specified file + by returning false from the handler. + + @event BeforeUpload + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {plupload.File} file File to be uploaded. + */ + + /** + Fires when a file is to be uploaded by the runtime. + + @event UploadFile + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {plupload.File} file File to be uploaded. + */ + + /** + Fires while a file is being uploaded. Use this event to update the current file upload progress. + + @event UploadProgress + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {plupload.File} file File that is currently being uploaded. + */ + + /** + Fires when file chunk is uploaded. + + @event ChunkUploaded + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {plupload.File} file File that the chunk was uploaded for. + @param {Object} result Object with response properties. + @param {Number} result.offset The amount of bytes the server has received so far, including this chunk. + @param {Number} result.total The size of the file. + @param {String} result.response The response body sent by the server. + @param {Number} result.status The HTTP status code sent by the server. + @param {String} result.responseHeaders All the response headers as a single string. + */ + + /** + Fires when a file is successfully uploaded. + + @event FileUploaded + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {plupload.File} file File that was uploaded. + @param {Object} result Object with response properties. + @param {String} result.response The response body sent by the server. + @param {Number} result.status The HTTP status code sent by the server. + @param {String} result.responseHeaders All the response headers as a single string. + */ + + /** + Fires when all files in a queue are uploaded. + + @event UploadComplete + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {Array} files Array of file objects that was added to queue/selected by the user. + */ + + /** + Fires when a error occurs. + + @event Error + @param {plupload.Uploader} uploader Uploader instance sending the event. + @param {Object} error Contains code, message and sometimes file and other details. + @param {Number} error.code The plupload error code. + @param {String} error.message Description of the error (uses i18n). + */ + + /** + Fires when destroy method is called. + + @event Destroy + @param {plupload.Uploader} uploader Uploader instance sending the event. + */ + var uid = plupload.guid() + , settings + , files = [] + , preferred_caps = {} + , fileInputs = [] + , fileDrops = [] + , startTime + , total + , disabled = false + , xhr + ; + + + // Private methods + function uploadNext() { + var file, count = 0, i; + + if (this.state == plupload.STARTED) { + // Find first QUEUED file + for (i = 0; i < files.length; i++) { + if (!file && files[i].status == plupload.QUEUED) { + file = files[i]; + if (this.trigger("BeforeUpload", file)) { + file.status = plupload.UPLOADING; + this.trigger("UploadFile", file); + } + } else { + count++; + } + } + + // All files are DONE or FAILED + if (count == files.length) { + if (this.state !== plupload.STOPPED) { + this.state = plupload.STOPPED; + this.trigger("StateChanged"); + } + this.trigger("UploadComplete", files); + } + } + } + + + function calcFile(file) { + file.percent = file.size > 0 ? Math.ceil(file.loaded / file.size * 100) : 100; + calc(); + } + + + function calc() { + var i, file; + + // Reset stats + total.reset(); + + // Check status, size, loaded etc on all files + for (i = 0; i < files.length; i++) { + file = files[i]; + + if (file.size !== undef) { + // We calculate totals based on original file size + total.size += file.origSize; + + // Since we cannot predict file size after resize, we do opposite and + // interpolate loaded amount to match magnitude of total + total.loaded += file.loaded * file.origSize / file.size; + } else { + total.size = undef; + } + + if (file.status == plupload.DONE) { + total.uploaded++; + } else if (file.status == plupload.FAILED) { + total.failed++; + } else { + total.queued++; + } + } + + // If we couldn't calculate a total file size then use the number of files to calc percent + if (total.size === undef) { + total.percent = files.length > 0 ? Math.ceil(total.uploaded / files.length * 100) : 0; + } else { + total.bytesPerSec = Math.ceil(total.loaded / ((+new Date() - startTime || 1) / 1000.0)); + total.percent = total.size > 0 ? Math.ceil(total.loaded / total.size * 100) : 0; + } + } + + + function getRUID() { + var ctrl = fileInputs[0] || fileDrops[0]; + if (ctrl) { + return ctrl.getRuntime().uid; + } + return false; + } + + + function runtimeCan(file, cap) { + if (file.ruid) { + var info = o.Runtime.getInfo(file.ruid); + if (info) { + return info.can(cap); + } + } + return false; + } + + + function bindEventListeners() { + this.bind('FilesAdded FilesRemoved', function(up) { + up.trigger('QueueChanged'); + up.refresh(); + }); + + this.bind('CancelUpload', onCancelUpload); + + this.bind('BeforeUpload', onBeforeUpload); + + this.bind('UploadFile', onUploadFile); + + this.bind('UploadProgress', onUploadProgress); + + this.bind('StateChanged', onStateChanged); + + this.bind('QueueChanged', calc); + + this.bind('Error', onError); + + this.bind('FileUploaded', onFileUploaded); + + this.bind('Destroy', onDestroy); + } + + + function initControls(settings, cb) { + var self = this, inited = 0, queue = []; + + // common settings + var options = { + runtime_order: settings.runtimes, + required_caps: settings.required_features, + preferred_caps: preferred_caps, + swf_url: settings.flash_swf_url, + xap_url: settings.silverlight_xap_url + }; + + // add runtime specific options if any + plupload.each(settings.runtimes.split(/\s*,\s*/), function(runtime) { + if (settings[runtime]) { + options[runtime] = settings[runtime]; + } + }); + + // initialize file pickers - there can be many + if (settings.browse_button) { + plupload.each(settings.browse_button, function(el) { + queue.push(function(cb) { + var fileInput = new o.FileInput(plupload.extend({}, options, { + accept: settings.filters.mime_types, + name: settings.file_data_name, + multiple: settings.multi_selection, + container: settings.container, + browse_button: el + })); + + fileInput.onready = function() { + var info = o.Runtime.getInfo(this.ruid); + + // for backward compatibility + o.extend(self.features, { + chunks: info.can('slice_blob'), + multipart: info.can('send_multipart'), + multi_selection: info.can('select_multiple') + }); + + inited++; + fileInputs.push(this); + cb(); + }; + + fileInput.onchange = function() { + self.addFile(this.files); + }; + + fileInput.bind('mouseenter mouseleave mousedown mouseup', function(e) { + if (!disabled) { + if (settings.browse_button_hover) { + if ('mouseenter' === e.type) { + o.addClass(el, settings.browse_button_hover); + } else if ('mouseleave' === e.type) { + o.removeClass(el, settings.browse_button_hover); + } + } + + if (settings.browse_button_active) { + if ('mousedown' === e.type) { + o.addClass(el, settings.browse_button_active); + } else if ('mouseup' === e.type) { + o.removeClass(el, settings.browse_button_active); + } + } + } + }); + + fileInput.bind('mousedown', function() { + self.trigger('Browse'); + }); + + fileInput.bind('error runtimeerror', function() { + fileInput = null; + cb(); + }); + + fileInput.init(); + }); + }); + } + + // initialize drop zones + if (settings.drop_element) { + plupload.each(settings.drop_element, function(el) { + queue.push(function(cb) { + var fileDrop = new o.FileDrop(plupload.extend({}, options, { + drop_zone: el + })); + + fileDrop.onready = function() { + var info = o.Runtime.getInfo(this.ruid); + + self.features.dragdrop = info.can('drag_and_drop'); // for backward compatibility + + inited++; + fileDrops.push(this); + cb(); + }; + + fileDrop.ondrop = function() { + self.addFile(this.files); + }; + + fileDrop.bind('error runtimeerror', function() { + fileDrop = null; + cb(); + }); + + fileDrop.init(); + }); + }); + } + + + o.inSeries(queue, function() { + if (typeof(cb) === 'function') { + cb(inited); + } + }); + } + + + function resizeImage(blob, params, cb) { + var img = new o.Image(); + + try { + img.onload = function() { + // no manipulation required if... + if (params.width > this.width && + params.height > this.height && + params.quality === undef && + params.preserve_headers && + !params.crop + ) { + this.destroy(); + return cb(blob); + } + // otherwise downsize + img.downsize(params.width, params.height, params.crop, params.preserve_headers); + }; + + img.onresize = function() { + cb(this.getAsBlob(blob.type, params.quality)); + this.destroy(); + }; + + img.onerror = function() { + cb(blob); + }; + + img.load(blob); + } catch(ex) { + cb(blob); + } + } + + + function setOption(option, value, init) { + var self = this, reinitRequired = false; + + function _setOption(option, value, init) { + var oldValue = settings[option]; + + switch (option) { + case 'max_file_size': + if (option === 'max_file_size') { + settings.max_file_size = settings.filters.max_file_size = value; + } + break; + + case 'chunk_size': + if (value = plupload.parseSize(value)) { + settings[option] = value; + settings.send_file_name = true; + } + break; + + case 'multipart': + settings[option] = value; + if (!value) { + settings.send_file_name = true; + } + break; + + case 'unique_names': + settings[option] = value; + if (value) { + settings.send_file_name = true; + } + break; + + case 'filters': + // for sake of backward compatibility + if (plupload.typeOf(value) === 'array') { + value = { + mime_types: value + }; + } + + if (init) { + plupload.extend(settings.filters, value); + } else { + settings.filters = value; + } + + // if file format filters are being updated, regenerate the matching expressions + if (value.mime_types) { + settings.filters.mime_types.regexp = (function(filters) { + var extensionsRegExp = []; + + plupload.each(filters, function(filter) { + plupload.each(filter.extensions.split(/,/), function(ext) { + if (/^\s*\*\s*$/.test(ext)) { + extensionsRegExp.push('\\.*'); + } else { + extensionsRegExp.push('\\.' + ext.replace(new RegExp('[' + ('/^$.*+?|()[]{}\\'.replace(/./g, '\\$&')) + ']', 'g'), '\\$&')); + } + }); + }); + + return new RegExp('(' + extensionsRegExp.join('|') + ')$', 'i'); + }(settings.filters.mime_types)); + } + break; + + case 'resize': + if (init) { + plupload.extend(settings.resize, value, { + enabled: true + }); + } else { + settings.resize = value; + } + break; + + case 'prevent_duplicates': + settings.prevent_duplicates = settings.filters.prevent_duplicates = !!value; + break; + + case 'browse_button': + case 'drop_element': + value = plupload.get(value); + + case 'container': + case 'runtimes': + case 'multi_selection': + case 'flash_swf_url': + case 'silverlight_xap_url': + settings[option] = value; + if (!init) { + reinitRequired = true; + } + break; + + default: + settings[option] = value; + } + + if (!init) { + self.trigger('OptionChanged', option, value, oldValue); + } + } + + if (typeof(option) === 'object') { + plupload.each(option, function(value, option) { + _setOption(option, value, init); + }); + } else { + _setOption(option, value, init); + } + + if (init) { + // Normalize the list of required capabilities + settings.required_features = normalizeCaps(plupload.extend({}, settings)); + + // Come up with the list of capabilities that can affect default mode in a multi-mode runtimes + preferred_caps = normalizeCaps(plupload.extend({}, settings, { + required_features: true + })); + } else if (reinitRequired) { + self.trigger('Destroy'); + + initControls.call(self, settings, function(inited) { + if (inited) { + self.runtime = o.Runtime.getInfo(getRUID()).type; + self.trigger('Init', { runtime: self.runtime }); + self.trigger('PostInit'); + } else { + self.trigger('Error', { + code : plupload.INIT_ERROR, + message : plupload.translate('Init error.') + }); + } + }); + } + } + + + // Internal event handlers + function onBeforeUpload(up, file) { + // Generate unique target filenames + if (up.settings.unique_names) { + var matches = file.name.match(/\.([^.]+)$/), ext = "part"; + if (matches) { + ext = matches[1]; + } + file.target_name = file.id + '.' + ext; + } + } + + + function onUploadFile(up, file) { + var url = up.settings.url + , chunkSize = up.settings.chunk_size + , retries = up.settings.max_retries + , features = up.features + , offset = 0 + , blob + ; + + // make sure we start at a predictable offset + if (file.loaded) { + offset = file.loaded = chunkSize ? chunkSize * Math.floor(file.loaded / chunkSize) : 0; + } + + function handleError() { + if (retries-- > 0) { + delay(uploadNextChunk, 1000); + } else { + file.loaded = offset; // reset all progress + + up.trigger('Error', { + code : plupload.HTTP_ERROR, + message : plupload.translate('HTTP Error.'), + file : file, + response : xhr.responseText, + status : xhr.status, + responseHeaders: xhr.getAllResponseHeaders() + }); + } + } + + function uploadNextChunk() { + var chunkBlob, formData, args = {}, curChunkSize; + + // make sure that file wasn't cancelled and upload is not stopped in general + if (file.status !== plupload.UPLOADING || up.state === plupload.STOPPED) { + return; + } + + // send additional 'name' parameter only if required + if (up.settings.send_file_name) { + args.name = file.target_name || file.name; + } + + if (chunkSize && features.chunks && blob.size > chunkSize) { // blob will be of type string if it was loaded in memory + curChunkSize = Math.min(chunkSize, blob.size - offset); + chunkBlob = blob.slice(offset, offset + curChunkSize); + } else { + curChunkSize = blob.size; + chunkBlob = blob; + } + + // If chunking is enabled add corresponding args, no matter if file is bigger than chunk or smaller + if (chunkSize && features.chunks) { + // Setup query string arguments + if (up.settings.send_chunk_number) { + args.chunk = Math.ceil(offset / chunkSize); + args.chunks = Math.ceil(blob.size / chunkSize); + } else { // keep support for experimental chunk format, just in case + args.offset = offset; + args.total = blob.size; + } + } + + xhr = new o.XMLHttpRequest(); + + // Do we have upload progress support + if (xhr.upload) { + xhr.upload.onprogress = function(e) { + file.loaded = Math.min(file.size, offset + e.loaded); + up.trigger('UploadProgress', file); + }; + } + + xhr.onload = function() { + // check if upload made itself through + if (xhr.status >= 400) { + handleError(); + return; + } + + retries = up.settings.max_retries; // reset the counter + + // Handle chunk response + if (curChunkSize < blob.size) { + chunkBlob.destroy(); + + offset += curChunkSize; + file.loaded = Math.min(offset, blob.size); + + up.trigger('ChunkUploaded', file, { + offset : file.loaded, + total : blob.size, + response : xhr.responseText, + status : xhr.status, + responseHeaders: xhr.getAllResponseHeaders() + }); + + // stock Android browser doesn't fire upload progress events, but in chunking mode we can fake them + if (o.Env.browser === 'Android Browser') { + // doesn't harm in general, but is not required anywhere else + up.trigger('UploadProgress', file); + } + } else { + file.loaded = file.size; + } + + chunkBlob = formData = null; // Free memory + + // Check if file is uploaded + if (!offset || offset >= blob.size) { + // If file was modified, destory the copy + if (file.size != file.origSize) { + blob.destroy(); + blob = null; + } + + up.trigger('UploadProgress', file); + + file.status = plupload.DONE; + + up.trigger('FileUploaded', file, { + response : xhr.responseText, + status : xhr.status, + responseHeaders: xhr.getAllResponseHeaders() + }); + } else { + // Still chunks left + delay(uploadNextChunk, 1); // run detached, otherwise event handlers interfere + } + }; + + xhr.onerror = function() { + handleError(); + }; + + xhr.onloadend = function() { + this.destroy(); + xhr = null; + }; + + // Build multipart request + if (up.settings.multipart && features.multipart) { + xhr.open("post", url, true); + + // Set custom headers + plupload.each(up.settings.headers, function(value, name) { + xhr.setRequestHeader(name, value); + }); + + formData = new o.FormData(); + + // Add multipart params + plupload.each(plupload.extend(args, up.settings.multipart_params), function(value, name) { + formData.append(name, value); + }); + + // Add file and send it + formData.append(up.settings.file_data_name, chunkBlob); + xhr.send(formData, { + runtime_order: up.settings.runtimes, + required_caps: up.settings.required_features, + preferred_caps: preferred_caps, + swf_url: up.settings.flash_swf_url, + xap_url: up.settings.silverlight_xap_url + }); + } else { + // if no multipart, send as binary stream + url = plupload.buildUrl(up.settings.url, plupload.extend(args, up.settings.multipart_params)); + + xhr.open("post", url, true); + + xhr.setRequestHeader('Content-Type', 'application/octet-stream'); // Binary stream header + + // Set custom headers + plupload.each(up.settings.headers, function(value, name) { + xhr.setRequestHeader(name, value); + }); + + xhr.send(chunkBlob, { + runtime_order: up.settings.runtimes, + required_caps: up.settings.required_features, + preferred_caps: preferred_caps, + swf_url: up.settings.flash_swf_url, + xap_url: up.settings.silverlight_xap_url + }); + } + } + + blob = file.getSource(); + + // Start uploading chunks + if (up.settings.resize.enabled && runtimeCan(blob, 'send_binary_string') && !!~o.inArray(blob.type, ['image/jpeg', 'image/png'])) { + // Resize if required + resizeImage.call(this, blob, up.settings.resize, function(resizedBlob) { + blob = resizedBlob; + file.size = resizedBlob.size; + uploadNextChunk(); + }); + } else { + uploadNextChunk(); + } + } + + + function onUploadProgress(up, file) { + calcFile(file); + } + + + function onStateChanged(up) { + if (up.state == plupload.STARTED) { + // Get start time to calculate bps + startTime = (+new Date()); + } else if (up.state == plupload.STOPPED) { + // Reset currently uploading files + for (var i = up.files.length - 1; i >= 0; i--) { + if (up.files[i].status == plupload.UPLOADING) { + up.files[i].status = plupload.QUEUED; + calc(); + } + } + } + } + + + function onCancelUpload() { + if (xhr) { + xhr.abort(); + } + } + + + function onFileUploaded(up) { + calc(); + + // Upload next file but detach it from the error event + // since other custom listeners might want to stop the queue + delay(function() { + uploadNext.call(up); + }, 1); + } + + + function onError(up, err) { + if (err.code === plupload.INIT_ERROR) { + up.destroy(); + } + // Set failed status if an error occured on a file + else if (err.code === plupload.HTTP_ERROR) { + err.file.status = plupload.FAILED; + calcFile(err.file); + + // Upload next file but detach it from the error event + // since other custom listeners might want to stop the queue + if (up.state == plupload.STARTED) { // upload in progress + up.trigger('CancelUpload'); + delay(function() { + uploadNext.call(up); + }, 1); + } + } + } + + + function onDestroy(up) { + up.stop(); + + // Purge the queue + plupload.each(files, function(file) { + file.destroy(); + }); + files = []; + + if (fileInputs.length) { + plupload.each(fileInputs, function(fileInput) { + fileInput.destroy(); + }); + fileInputs = []; + } + + if (fileDrops.length) { + plupload.each(fileDrops, function(fileDrop) { + fileDrop.destroy(); + }); + fileDrops = []; + } + + preferred_caps = {}; + disabled = false; + startTime = xhr = null; + total.reset(); + } + + + // Default settings + settings = { + runtimes: o.Runtime.order, + max_retries: 0, + chunk_size: 0, + multipart: true, + multi_selection: true, + file_data_name: 'file', + flash_swf_url: 'js/Moxie.swf', + silverlight_xap_url: 'js/Moxie.xap', + filters: { + mime_types: [], + prevent_duplicates: false, + max_file_size: 0 + }, + resize: { + enabled: false, + preserve_headers: true, + crop: false + }, + send_file_name: true, + send_chunk_number: true + }; + + + setOption.call(this, options, null, true); + + // Inital total state + total = new plupload.QueueProgress(); + + // Add public methods + plupload.extend(this, { + + /** + * Unique id for the Uploader instance. + * + * @property id + * @type String + */ + id : uid, + uid : uid, // mOxie uses this to differentiate between event targets + + /** + * Current state of the total uploading progress. This one can either be plupload.STARTED or plupload.STOPPED. + * These states are controlled by the stop/start methods. The default value is STOPPED. + * + * @property state + * @type Number + */ + state : plupload.STOPPED, + + /** + * Map of features that are available for the uploader runtime. Features will be filled + * before the init event is called, these features can then be used to alter the UI for the end user. + * Some of the current features that might be in this map is: dragdrop, chunks, jpgresize, pngresize. + * + * @property features + * @type Object + */ + features : {}, + + /** + * Current runtime name. + * + * @property runtime + * @type String + */ + runtime : null, + + /** + * Current upload queue, an array of File instances. + * + * @property files + * @type Array + * @see plupload.File + */ + files : files, + + /** + * Object with name/value settings. + * + * @property settings + * @type Object + */ + settings : settings, + + /** + * Total progess information. How many files has been uploaded, total percent etc. + * + * @property total + * @type plupload.QueueProgress + */ + total : total, + + + /** + * Initializes the Uploader instance and adds internal event listeners. + * + * @method init + */ + init : function() { + var self = this; + + if (typeof(settings.preinit) == "function") { + settings.preinit(self); + } else { + plupload.each(settings.preinit, function(func, name) { + self.bind(name, func); + }); + } + + bindEventListeners.call(this); + + // Check for required options + if (!settings.browse_button || !settings.url) { + this.trigger('Error', { + code : plupload.INIT_ERROR, + message : plupload.translate('Init error.') + }); + return; + } + + initControls.call(this, settings, function(inited) { + if (typeof(settings.init) == "function") { + settings.init(self); + } else { + plupload.each(settings.init, function(func, name) { + self.bind(name, func); + }); + } + + if (inited) { + self.runtime = o.Runtime.getInfo(getRUID()).type; + self.trigger('Init', { runtime: self.runtime }); + self.trigger('PostInit'); + } else { + self.trigger('Error', { + code : plupload.INIT_ERROR, + message : plupload.translate('Init error.') + }); + } + }); + }, + + /** + * Set the value for the specified option(s). + * + * @method setOption + * @since 2.1 + * @param {String|Object} option Name of the option to change or the set of key/value pairs + * @param {Mixed} [value] Value for the option (is ignored, if first argument is object) + */ + setOption: function(option, value) { + setOption.call(this, option, value, !this.runtime); // until runtime not set we do not need to reinitialize + }, + + /** + * Get the value for the specified option or the whole configuration, if not specified. + * + * @method getOption + * @since 2.1 + * @param {String} [option] Name of the option to get + * @return {Mixed} Value for the option or the whole set + */ + getOption: function(option) { + if (!option) { + return settings; + } + return settings[option]; + }, + + /** + * Refreshes the upload instance by dispatching out a refresh event to all runtimes. + * This would for example reposition flash/silverlight shims on the page. + * + * @method refresh + */ + refresh : function() { + if (fileInputs.length) { + plupload.each(fileInputs, function(fileInput) { + fileInput.trigger('Refresh'); + }); + } + this.trigger('Refresh'); + }, + + /** + * Starts uploading the queued files. + * + * @method start + */ + start : function() { + if (this.state != plupload.STARTED) { + this.state = plupload.STARTED; + this.trigger('StateChanged'); + + uploadNext.call(this); + } + }, + + /** + * Stops the upload of the queued files. + * + * @method stop + */ + stop : function() { + if (this.state != plupload.STOPPED) { + this.state = plupload.STOPPED; + this.trigger('StateChanged'); + this.trigger('CancelUpload'); + } + }, + + + /** + * Disables/enables browse button on request. + * + * @method disableBrowse + * @param {Boolean} disable Whether to disable or enable (default: true) + */ + disableBrowse : function() { + disabled = arguments[0] !== undef ? arguments[0] : true; + + if (fileInputs.length) { + plupload.each(fileInputs, function(fileInput) { + fileInput.disable(disabled); + }); + } + + this.trigger('DisableBrowse', disabled); + }, + + /** + * Returns the specified file object by id. + * + * @method getFile + * @param {String} id File id to look for. + * @return {plupload.File} File object or undefined if it wasn't found; + */ + getFile : function(id) { + var i; + for (i = files.length - 1; i >= 0; i--) { + if (files[i].id === id) { + return files[i]; + } + } + }, + + /** + * Adds file to the queue programmatically. Can be native file, instance of Plupload.File, + * instance of mOxie.File, input[type="file"] element, or array of these. Fires FilesAdded, + * if any files were added to the queue. Otherwise nothing happens. + * + * @method addFile + * @since 2.0 + * @param {plupload.File|mOxie.File|File|Node|Array} file File or files to add to the queue. + * @param {String} [fileName] If specified, will be used as a name for the file + */ + addFile : function(file, fileName) { + var self = this + , queue = [] + , filesAdded = [] + , ruid + ; + + function filterFile(file, cb) { + var queue = []; + o.each(self.settings.filters, function(rule, name) { + if (fileFilters[name]) { + queue.push(function(cb) { + fileFilters[name].call(self, rule, file, function(res) { + cb(!res); + }); + }); + } + }); + o.inSeries(queue, cb); + } + + /** + * @method resolveFile + * @private + * @param {o.File|o.Blob|plupload.File|File|Blob|input[type="file"]} file + */ + function resolveFile(file) { + var type = o.typeOf(file); + + // o.File + if (file instanceof o.File) { + if (!file.ruid && !file.isDetached()) { + if (!ruid) { // weird case + return false; + } + file.ruid = ruid; + file.connectRuntime(ruid); + } + resolveFile(new plupload.File(file)); + } + // o.Blob + else if (file instanceof o.Blob) { + resolveFile(file.getSource()); + file.destroy(); + } + // plupload.File - final step for other branches + else if (file instanceof plupload.File) { + if (fileName) { + file.name = fileName; + } + + queue.push(function(cb) { + // run through the internal and user-defined filters, if any + filterFile(file, function(err) { + if (!err) { + // make files available for the filters by updating the main queue directly + files.push(file); + // collect the files that will be passed to FilesAdded event + filesAdded.push(file); + + self.trigger("FileFiltered", file); + } + delay(cb, 1); // do not build up recursions or eventually we might hit the limits + }); + }); + } + // native File or blob + else if (o.inArray(type, ['file', 'blob']) !== -1) { + resolveFile(new o.File(null, file)); + } + // input[type="file"] + else if (type === 'node' && o.typeOf(file.files) === 'filelist') { + // if we are dealing with input[type="file"] + o.each(file.files, resolveFile); + } + // mixed array of any supported types (see above) + else if (type === 'array') { + fileName = null; // should never happen, but unset anyway to avoid funny situations + o.each(file, resolveFile); + } + } + + ruid = getRUID(); + + resolveFile(file); + + if (queue.length) { + o.inSeries(queue, function() { + // if any files left after filtration, trigger FilesAdded + if (filesAdded.length) { + self.trigger("FilesAdded", filesAdded); + } + }); + } + }, + + /** + * Removes a specific file. + * + * @method removeFile + * @param {plupload.File|String} file File to remove from queue. + */ + removeFile : function(file) { + var id = typeof(file) === 'string' ? file : file.id; + + for (var i = files.length - 1; i >= 0; i--) { + if (files[i].id === id) { + return this.splice(i, 1)[0]; + } + } + }, + + /** + * Removes part of the queue and returns the files removed. This will also trigger the FilesRemoved and QueueChanged events. + * + * @method splice + * @param {Number} start (Optional) Start index to remove from. + * @param {Number} length (Optional) Lengh of items to remove. + * @return {Array} Array of files that was removed. + */ + splice : function(start, length) { + // Splice and trigger events + var removed = files.splice(start === undef ? 0 : start, length === undef ? files.length : length); + + // if upload is in progress we need to stop it and restart after files are removed + var restartRequired = false; + if (this.state == plupload.STARTED) { // upload in progress + plupload.each(removed, function(file) { + if (file.status === plupload.UPLOADING) { + restartRequired = true; // do not restart, unless file that is being removed is uploading + return false; + } + }); + + if (restartRequired) { + this.stop(); + } + } + + this.trigger("FilesRemoved", removed); + + // Dispose any resources allocated by those files + plupload.each(removed, function(file) { + file.destroy(); + }); + + if (restartRequired) { + this.start(); + } + + return removed; + }, + + /** + Dispatches the specified event name and its arguments to all listeners. + + @method trigger + @param {String} name Event name to fire. + @param {Object..} Multiple arguments to pass along to the listener functions. + */ + + // override the parent method to match Plupload-like event logic + dispatchEvent: function(type) { + var list, args, result; + + type = type.toLowerCase(); + + list = this.hasEventListener(type); + + if (list) { + // sort event list by prority + list.sort(function(a, b) { return b.priority - a.priority; }); + + // first argument should be current plupload.Uploader instance + args = [].slice.call(arguments); + args.shift(); + args.unshift(this); + + for (var i = 0; i < list.length; i++) { + // Fire event, break chain if false is returned + if (list[i].fn.apply(list[i].scope, args) === false) { + return false; + } + } + } + return true; + }, + + /** + Check whether uploader has any listeners to the specified event. + + @method hasEventListener + @param {String} name Event name to check for. + */ + + + /** + Adds an event listener by name. + + @method bind + @param {String} name Event name to listen for. + @param {function} fn Function to call ones the event gets fired. + @param {Object} [scope] Optional scope to execute the specified function in. + @param {Number} [priority=0] Priority of the event handler - handlers with higher priorities will be called first + */ + bind: function(name, fn, scope, priority) { + // adapt moxie EventTarget style to Plupload-like + plupload.Uploader.prototype.bind.call(this, name, fn, priority, scope); + }, + + /** + Removes the specified event listener. + + @method unbind + @param {String} name Name of event to remove. + @param {function} fn Function to remove from listener. + */ + + /** + Removes all event listeners. + + @method unbindAll + */ + + + /** + * Destroys Plupload instance and cleans after itself. + * + * @method destroy + */ + destroy : function() { + this.trigger('Destroy'); + settings = total = null; // purge these exclusively + this.unbindAll(); + } + }); +}; + +plupload.Uploader.prototype = o.EventTarget.instance; + +/** + * Constructs a new file instance. + * + * @class File + * @constructor + * + * @param {Object} file Object containing file properties + * @param {String} file.name Name of the file. + * @param {Number} file.size File size. + */ +plupload.File = (function() { + var filepool = {}; + + function PluploadFile(file) { + + plupload.extend(this, { + + /** + * File id this is a globally unique id for the specific file. + * + * @property id + * @type String + */ + id: plupload.guid(), + + /** + * File name for example "myfile.gif". + * + * @property name + * @type String + */ + name: file.name || file.fileName, + + /** + * File type, `e.g image/jpeg` + * + * @property type + * @type String + */ + type: file.type || '', + + /** + * File size in bytes (may change after client-side manupilation). + * + * @property size + * @type Number + */ + size: file.size || file.fileSize, + + /** + * Original file size in bytes. + * + * @property origSize + * @type Number + */ + origSize: file.size || file.fileSize, + + /** + * Number of bytes uploaded of the files total size. + * + * @property loaded + * @type Number + */ + loaded: 0, + + /** + * Number of percentage uploaded of the file. + * + * @property percent + * @type Number + */ + percent: 0, + + /** + * Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE. + * + * @property status + * @type Number + * @see plupload + */ + status: plupload.QUEUED, + + /** + * Date of last modification. + * + * @property lastModifiedDate + * @type {String} + */ + lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString(), // Thu Aug 23 2012 19:40:00 GMT+0400 (GET) + + /** + * Returns native window.File object, when it's available. + * + * @method getNative + * @return {window.File} or null, if plupload.File is of different origin + */ + getNative: function() { + var file = this.getSource().getSource(); + return o.inArray(o.typeOf(file), ['blob', 'file']) !== -1 ? file : null; + }, + + /** + * Returns mOxie.File - unified wrapper object that can be used across runtimes. + * + * @method getSource + * @return {mOxie.File} or null + */ + getSource: function() { + if (!filepool[this.id]) { + return null; + } + return filepool[this.id]; + }, + + /** + * Destroys plupload.File object. + * + * @method destroy + */ + destroy: function() { + var src = this.getSource(); + if (src) { + src.destroy(); + delete filepool[this.id]; + } + } + }); + + filepool[this.id] = file; + } + + return PluploadFile; +}()); + + +/** + * Constructs a queue progress. + * + * @class QueueProgress + * @constructor + */ + plupload.QueueProgress = function() { + var self = this; // Setup alias for self to reduce code size when it's compressed + + /** + * Total queue file size. + * + * @property size + * @type Number + */ + self.size = 0; + + /** + * Total bytes uploaded. + * + * @property loaded + * @type Number + */ + self.loaded = 0; + + /** + * Number of files uploaded. + * + * @property uploaded + * @type Number + */ + self.uploaded = 0; + + /** + * Number of files failed to upload. + * + * @property failed + * @type Number + */ + self.failed = 0; + + /** + * Number of files yet to be uploaded. + * + * @property queued + * @type Number + */ + self.queued = 0; + + /** + * Total percent of the uploaded bytes. + * + * @property percent + * @type Number + */ + self.percent = 0; + + /** + * Bytes uploaded per second. + * + * @property bytesPerSec + * @type Number + */ + self.bytesPerSec = 0; + + /** + * Resets the progress to its initial values. + * + * @method reset + */ + self.reset = function() { + self.size = self.loaded = self.uploaded = self.failed = self.queued = self.percent = self.bytesPerSec = 0; + }; +}; + +window.plupload = plupload; + +}(window, mOxie)); diff --git a/qiniu_fields/static/qiniu_fields/plupload/plupload.full.min.js b/qiniu_fields/static/qiniu_fields/plupload/plupload.full.min.js new file mode 100644 index 0000000..2af434d --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/plupload/plupload.full.min.js @@ -0,0 +1,29 @@ +/** + * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill + * v1.3.4 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2015-07-18 + */ +!function(e,t){"use strict";function n(e,t){for(var n,i=[],r=0;r0&&n(o,function(n,o){n!==r&&(e(i[o])===e(n)&&~a(e(n),["array","object"])?t(i[o],n):i[o]=n)})}),i},n=function(t,n){var i,r,o,a;if(t)if("number"===e(t.length)){for(o=0,i=t.length;i>o;o++)if(n(t[o],o)===!1)return}else if("object"===e(t))for(r in t)if(t.hasOwnProperty(r)&&n(t[r],r)===!1)return},i=function(t){var n;if(!t||"object"!==e(t))return!0;for(n in t)return!1;return!0},r=function(t,n){function i(r){"function"===e(t[r])&&t[r](function(e){++rn;n++)if(t[n]===e)return n}return-1},s=function(t,n){var i=[];"array"!==e(t)&&(t=[t]),"array"!==e(n)&&(n=[n]);for(var r in t)-1===a(t[r],n)&&i.push(t[r]);return i.length?i:!1},u=function(e,t){var i=[];return n(e,function(e){-1!==a(e,t)&&i.push(e)}),i.length?i:null},c=function(e){var t,n=[];for(t=0;ti;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}(),d=function(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e},h=function(e){if("string"!=typeof e)return e;var t={t:1099511627776,g:1073741824,m:1048576,k:1024},n;return e=/^([0-9\.]+)([tmgk]?)$/.exec(e.toLowerCase().replace(/[^0-9\.tmkg]/g,"")),n=e[2],e=+e[1],t.hasOwnProperty(n)&&(e*=t[n]),Math.floor(e)},f=function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e(t)?t:""})};return{guid:l,typeOf:e,extend:t,each:n,isEmptyObj:i,inSeries:r,inParallel:o,inArray:a,arrayDiff:s,arrayIntersect:u,toArray:c,trim:d,sprintf:f,parseSizeStr:h}}),i(c,[u],function(e){function t(e,t,n){var i=0,r=0,o=0,a={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},s=function(e){return e=(""+e).replace(/[_\-+]/g,"."),e=e.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,"."),e.length?e.split("."):[-8]},u=function(e){return e?isNaN(e)?a[e]||-7:parseInt(e,10):0};for(e=s(e),t=s(t),r=Math.max(e.length,t.length),i=0;r>i;i++)if(e[i]!=t[i]){if(e[i]=u(e[i]),t[i]=u(t[i]),e[i]t[i]){o=1;break}}if(!n)return o;switch(n){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq":return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",n="?",i="function",r="undefined",o="object",a="major",s="model",u="name",c="type",l="vendor",d="version",h="architecture",f="console",p="mobile",m="tablet",g={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},v={rgx:function(){for(var t,n=0,a,s,u,c,l,d,h=arguments;n0?2==c.length?typeof c[1]==i?t[c[0]]=c[1].call(this,d):t[c[0]]=c[1]:3==c.length?typeof c[1]!==i||c[1].exec&&c[1].test?t[c[0]]=d?d.replace(c[1],c[2]):e:t[c[0]]=d?c[1].call(this,d,c[2]):e:4==c.length&&(t[c[0]]=d?c[3].call(this,d.replace(c[1],c[2])):e):t[c]=d?d:e;break}if(l)break}return t},str:function(t,i){for(var r in i)if(typeof i[r]===o&&i[r].length>0){for(var a=0;a=9)},use_data_uri_of:function(e){return t.use_data_uri&&33e3>e||t.use_data_uri_over32kb()},use_fileinput:function(){if(navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/))return!1;var e=document.createElement("input");return e.setAttribute("type","file"),!e.disabled}};return function(n){var i=[].slice.call(arguments);return i.shift(),"function"===e.typeOf(t[n])?t[n].apply(this,i):!!t[n]}}(),r=(new n).getResult(),o={can:i,uaParser:n,browser:r.browser.name,version:r.browser.version,os:r.os.name,osVersion:r.os.version,verComp:t,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return o.OS=o.os,o}),i(l,[u],function(e){var t={};return{addI18n:function(n){return e.extend(t,n)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),i(d,[u,l],function(e,t){var n="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",i={mimes:{},extensions:{},addMimeType:function(e){var t=e.split(/,/),n,i,r;for(n=0;n=0;o--)if(r[o].fn===i){r.splice(o,1);break}}else r=[];r.length||(delete e[this.uid][t],n.isEmptyObj(e[this.uid])&&delete e[this.uid])}},removeAllEventListeners:function(){e[this.uid]&&delete e[this.uid]},dispatchEvent:function(i){var r,o,a,s,u={},c=!0,l;if("string"!==n.typeOf(i)){if(s=i,"string"!==n.typeOf(s.type))throw new t.EventException(t.EventException.UNSPECIFIED_EVENT_TYPE_ERR);i=s.type,s.total!==l&&s.loaded!==l&&(u.total=s.total,u.loaded=s.loaded),u.async=s.async||!1}if(-1!==i.indexOf("::")?!function(e){r=e[0],i=e[1]}(i.split("::")):r=this.uid,i=i.toLowerCase(),o=e[r]&&e[r][i]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),u.type=i,a.unshift(u);var d=[];n.each(o,function(e){a[0].target=e.scope,d.push(u.async?function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}:function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&n.inSeries(d,function(e){c=!e})}return c},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},handleEventProps:function(e){var t=this;this.bind(e.join(" "),function(e){var t="on"+e.type.toLowerCase();"function"===n.typeOf(this[t])&&this[t].apply(this,arguments)}),n.each(e,function(e){e="on"+e.toLowerCase(e),"undefined"===n.typeOf(t[e])&&(t[e]=null)})}})}return i.instance=new i,i}),i(m,[c,u,h,p],function(e,t,n,i){function r(e,i,o,s,u){var c=this,l,d=t.guid(i+"_"),h=u||"browser";e=e||{},a[d]=this,o=t.extend({access_binary:!1,access_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_file_dialog:!1,upload_filesize:!0,use_http_method:!0},o),e.preferred_caps&&(h=r.getMode(s,e.preferred_caps,h)),l=function(){var e={};return{exec:function(t,n,i,r){return l[n]&&(e[t]||(e[t]={context:this,instance:new l[n]}),e[t].instance[i])?e[t].instance[i].apply(this,r):void 0},removeInstance:function(t){delete e[t]},removeAllInstances:function(){var n=this;t.each(e,function(e,i){"function"===t.typeOf(e.instance.destroy)&&e.instance.destroy.call(e.context),n.removeInstance(i)})}}}(),t.extend(this,{initialized:!1,uid:d,type:i,mode:r.getMode(s,e.required_caps,h),shimid:d+"_container",clients:0,options:e,can:function(e,n){var i=arguments[2]||o;if("string"===t.typeOf(e)&&"undefined"===t.typeOf(n)&&(e=r.parseCaps(e)),"object"===t.typeOf(e)){for(var a in e)if(!this.can(a,e[a],i))return!1;return!0}return"function"===t.typeOf(i[e])?i[e].call(this,n):n===i[e]},getShimContainer:function(){var e,i=n.get(this.shimid);return i||(e=this.options.container?n.get(this.options.container):document.body,i=document.createElement("div"),i.id=this.shimid,i.className="moxie-shim moxie-shim-"+this.type,t.extend(i.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),e.appendChild(i),e=null),i},getShim:function(){return l},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec.call(this,this.uid,e,t,n)},exec:function(e,t){var n=[].slice.call(arguments,2);return c[e]&&c[e][t]?c[e][t].apply(this,n):c.shimExec.apply(this,arguments)},destroy:function(){if(c){var e=n.get(this.shimid);e&&e.parentNode.removeChild(e),l&&l.removeAllInstances(),this.unbindAll(),delete a[this.uid],this.uid=null,d=c=l=e=null}}}),this.mode&&e.required_caps&&!this.can(e.required_caps)&&(this.mode=!1)}var o={},a={};return r.order="html5,flash,silverlight,html4",r.getRuntime=function(e){return a[e]?a[e]:!1},r.addConstructor=function(e,t){t.prototype=i.instance,o[e]=t},r.getConstructor=function(e){return o[e]||null},r.getInfo=function(e){var t=r.getRuntime(e);return t?{uid:t.uid,type:t.type,mode:t.mode,can:function(){return t.can.apply(t,arguments)}}:null},r.parseCaps=function(e){var n={};return"string"!==t.typeOf(e)?e||{}:(t.each(e.split(","),function(e){n[e]=!0}),n)},r.can=function(e,t){var n,i=r.getConstructor(e),o;return i?(n=new i({required_caps:t}),o=n.mode,n.destroy(),!!o):!1},r.thatCan=function(e,t){var n=(t||r.order).split(/\s*,\s*/);for(var i in n)if(r.can(n[i],e))return n[i];return null},r.getMode=function(e,n,i){var r=null;if("undefined"===t.typeOf(i)&&(i="browser"),n&&!t.isEmptyObj(e)){if(t.each(n,function(n,i){if(e.hasOwnProperty(i)){var o=e[i](n);if("string"==typeof o&&(o=[o]),r){if(!(r=t.arrayIntersect(r,o)))return r=!1}else r=o}}),r)return-1!==t.inArray(i,r)?i:r[0];if(r===!1)return!1}return i},r.capTrue=function(){return!0},r.capFalse=function(){return!1},r.capTest=function(e){return function(){return!!e}},r}),i(g,[c,f,u,m],function(e,t,n,i){return function r(){var e;n.extend(this,{connectRuntime:function(r){function o(n){var s,u;return n.length?(s=n.shift().toLowerCase(),(u=i.getConstructor(s))?(e=new u(r),e.bind("Init",function(){e.initialized=!0,setTimeout(function(){e.clients++,a.trigger("RuntimeInit",e)},1)}),e.bind("Error",function(){e.destroy(),o(n)}),e.mode?void e.init():void e.trigger("Error")):void o(n)):(a.trigger("RuntimeError",new t.RuntimeError(t.RuntimeError.NOT_INIT_ERR)),void(e=null))}var a=this,s;if("string"===n.typeOf(r)?s=r:"string"===n.typeOf(r.ruid)&&(s=r.ruid),s){if(e=i.getRuntime(s))return e.clients++,e;throw new t.RuntimeError(t.RuntimeError.NOT_INIT_ERR)}o((r.runtime_order||i.order).split(/\s*,\s*/))},disconnectRuntime:function(){e&&--e.clients<=0&&e.destroy(),e=null},getRuntime:function(){return e&&e.uid?e:e=null},exec:function(){return e?e.exec.apply(this,arguments):null}})}}),i(v,[u,c,d,h,f,p,l,m,g],function(e,t,n,i,r,o,a,s,u){function c(t){var o=this,c,d,h;if(-1!==e.inArray(e.typeOf(t),["string","node"])&&(t={browse_button:t}),d=i.get(t.browse_button),!d)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR);h={accept:[{title:a.translate("All Files"),extensions:"*"}],name:"file",multiple:!1,required_caps:!1,container:d.parentNode||document.body},t=e.extend({},h,t),"string"==typeof t.required_caps&&(t.required_caps=s.parseCaps(t.required_caps)),"string"==typeof t.accept&&(t.accept=n.mimes2extList(t.accept)),c=i.get(t.container),c||(c=document.body),"static"===i.getStyle(c,"position")&&(c.style.position="relative"),c=d=null,u.call(o),e.extend(o,{uid:e.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){o.bind("RuntimeInit",function(n,r){o.ruid=r.uid,o.shimid=r.shimid,o.bind("Ready",function(){o.trigger("Refresh")},999),o.bind("Refresh",function(){var n,o,a,s;a=i.get(t.browse_button),s=i.get(r.shimid),a&&(n=i.getPos(a,i.get(t.container)),o=i.getSize(a),s&&e.extend(s.style,{top:n.y+"px",left:n.x+"px",width:o.w+"px",height:o.h+"px"})),s=a=null}),r.exec.call(o,"FileInput","init",t)}),o.connectRuntime(e.extend({},t,{required_caps:{select_file:!0}}))},disable:function(t){var n=this.getRuntime();n&&n.exec.call(this,"FileInput","disable","undefined"===e.typeOf(t)?!0:t)},refresh:function(){o.trigger("Refresh")},destroy:function(){var t=this.getRuntime();t&&(t.exec.call(this,"FileInput","destroy"),this.disconnectRuntime()),"array"===e.typeOf(this.files)&&e.each(this.files,function(e){e.destroy()}),this.files=null,this.unbindAll()}}),this.handleEventProps(l)}var l=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];return c.prototype=o.instance,c}),i(w,[],function(){var e=function(e){return unescape(encodeURIComponent(e))},t=function(e){return decodeURIComponent(escape(e))},n=function(e,n){if("function"==typeof window.atob)return n?t(window.atob(e)):window.atob(e);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,h=0,f=0,p="",m=[];if(!e)return e;e+="";do s=i.indexOf(e.charAt(h++)),u=i.indexOf(e.charAt(h++)),c=i.indexOf(e.charAt(h++)),l=i.indexOf(e.charAt(h++)),d=s<<18|u<<12|c<<6|l,r=d>>16&255,o=d>>8&255,a=255&d,64==c?m[f++]=String.fromCharCode(r):64==l?m[f++]=String.fromCharCode(r,o):m[f++]=String.fromCharCode(r,o,a);while(h>18&63,u=d>>12&63,c=d>>6&63,l=63&d,m[f++]=i.charAt(s)+i.charAt(u)+i.charAt(c)+i.charAt(l);while(ha;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return i.call(this,"readAsDataURL",e)},readAsText:function(e){return i.call(this,"readAsText",e)}})}}),i(I,[f,u,y],function(e,t,n){function i(){var e,i=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof n?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):i.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(n){t.each(i,function(e){n(e.value,e.name)}),e&&n(e.value,e.name)},destroy:function(){e=null,i=[]}})}return i}),i(T,[u,f,p,w,x,m,R,y,A,I,c,d],function(e,t,n,i,r,o,a,s,u,c,l,d){function h(){this.uid=e.guid("uid_")}function f(){function n(e,t){return w.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?w[e]:v[e]:void(l.can("define_property")?w[e]=t:v[e]=t):void 0}function u(t){function i(){B&&(B.destroy(),B=null),s.dispatchEvent("loadend"),s=null}function r(r){B.bind("LoadStart",function(e){n("readyState",f.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),O&&s.upload.dispatchEvent(e)}),B.bind("Progress",function(e){n("readyState")!==f.LOADING&&(n("readyState",f.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),B.bind("UploadProgress",function(e){O&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),B.bind("Load",function(t){n("readyState",f.DONE),n("status",Number(r.exec.call(B,"XMLHttpRequest","getStatus")||0)),n("statusText",p[n("status")]||""),n("response",r.exec.call(B,"XMLHttpRequest","getResponse",n("responseType"))),~e.inArray(n("responseType"),["text",""])?n("responseText",n("response")):"document"===n("responseType")&&n("responseXML",n("response")),k=r.exec.call(B,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),n("status")>0?(O&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(N=!0,s.dispatchEvent("error")),i()}),B.bind("Abort",function(e){s.dispatchEvent(e),i()}),B.bind("Error",function(e){N=!0,n("readyState",f.DONE),s.dispatchEvent("readystatechange"),D=!0,s.dispatchEvent(e),i()}),r.exec.call(B,"XMLHttpRequest","send",{url:E,method:_,async:y,user:x,password:R,headers:b,mimeType:I,encoding:A,responseType:s.responseType,withCredentials:s.withCredentials,options:H},t)}var s=this;C=(new Date).getTime(),B=new a,"string"==typeof H.required_caps&&(H.required_caps=o.parseCaps(H.required_caps)),H.required_caps=e.extend({},H.required_caps,{return_response_type:s.responseType}),t instanceof c&&(H.required_caps.send_multipart=!0),e.isEmptyObj(b)||(H.required_caps.send_custom_headers=!0),L||(H.required_caps.do_cors=!0),H.ruid?r(B.connectRuntime(H)):(B.bind("RuntimeInit",function(e,t){r(t)}),B.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),B.connectRuntime(H))}function g(){n("responseText",""),n("responseXML",null),n("response",null),n("status",0),n("statusText",""),C=M=null}var v=this,w={timeout:0,readyState:f.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},y=!0,E,_,b={},x,R,A=null,I=null,T=!1,S=!1,O=!1,D=!1,N=!1,L=!1,C,M,F=null,P=null,H={},B,k="",U;e.extend(this,w,{uid:e.guid("uid_"),upload:new h,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||i.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(_=o.toUpperCase()),~e.inArray(_,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=i.utf8_encode(a),l=r.parseUrl(a),L=r.hasSameOrigin(l),E=r.resolveUrl(a),(u||c)&&!L)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(x=u||l.user,R=c||l.pass,y=s||!0,y===!1&&(n("timeout")||n("withCredentials")||""!==n("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);T=!y,S=!1,b={},g.call(this),n("readyState",f.OPENED),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(n("readyState")!==f.OPENED||S)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||i.utf8_encode(r)!==r)throw new t.DOMException(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(b[r]?b[r]+=", "+o:b[r]=o,!0)},getAllResponseHeaders:function(){return k||""},getResponseHeader:function(t){return t=t.toLowerCase(),N||~e.inArray(t,["set-cookie","set-cookie2"])?null:k&&""!==k&&(U||(U={},e.each(k.split(/\r\n/),function(t){var n=t.split(/:\s+/);2===n.length&&(n[0]=e.trim(n[0]),U[n[0].toLowerCase()]={header:n[0],value:e.trim(n[1])})})),U.hasOwnProperty(t))?U[t].header+": "+U[t].value:null},overrideMimeType:function(i){var r,o;if(~e.inArray(n("readyState"),[f.LOADING,f.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i=e.trim(i.toLowerCase()),/;/.test(i)&&(r=i.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(i=r[1],r[2]&&(o=r[2])),!d.mimes[i])throw new t.DOMException(t.DOMException.SYNTAX_ERR);F=i,P=o},send:function(n,r){if(H="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.readyState!==f.OPENED||S)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n instanceof s)H.ruid=n.ruid,I=n.type||"application/octet-stream";else if(n instanceof c){if(n.hasBlob()){var o=n.getBlob();H.ruid=o.ruid,I=o.type||"application/octet-stream"}}else"string"==typeof n&&(A="UTF-8",I="text/plain;charset=UTF-8",n=i.utf8_encode(n));this.withCredentials||(this.withCredentials=H.required_caps&&H.required_caps.send_browser_cookies&&!L),O=!T&&this.upload.hasEventListener(),N=!1,D=!n,T||(S=!0),u.call(this,n)},abort:function(){if(N=!0,T=!1,~e.inArray(n("readyState"),[f.UNSENT,f.OPENED,f.DONE]))n("readyState",f.UNSENT);else{if(n("readyState",f.DONE),S=!1,!B)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);B.getRuntime().exec.call(B,"XMLHttpRequest","abort",D),D=!0}},destroy:function(){B&&("function"===e.typeOf(B.destroy)&&B.destroy(),B=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}}),this.handleEventProps(m.concat(["readystatechange"])),this.upload.handleEventProps(m)}var p={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};h.prototype=n.instance;var m=["loadstart","progress","abort","error","load","timeout","loadend"],g=1,v=2;return f.UNSENT=0,f.OPENED=1,f.HEADERS_RECEIVED=2,f.LOADING=3,f.DONE=4,f.prototype=n.instance,f}),i(S,[u,w,g,p],function(e,t,n,i){function r(){function i(){l=d=0,c=this.result=null}function o(t,n){var i=this;u=n,i.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(i.state,[r.IDLE,r.DONE])&&a.call(i)},999),i.bind("TransportingComplete",function(){d=l,i.state=r.DONE,c=null,i.result=u.exec.call(i,"Transporter","getAsBlob",t||"")},999),i.state=r.BUSY,i.trigger("TransportingStarted"),a.call(i)}function a(){var e=this,n,i=l-d;h>i&&(h=i),n=t.btoa(c.substr(d,h)),u.exec.call(e,"Transporter","receive",n,l)}var s,u,c,l,d,h;n.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,n,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)&&(r.chunk_size+=3-s),h=r.chunk_size,i.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,n,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,n,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),i.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),i.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=i.instance,r}),i(O,[u,h,f,A,T,m,g,S,c,p,y,E,w],function(e,t,n,i,r,o,a,s,u,c,l,d,h){function f(){function i(e){e||(e=this.exec("Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}function c(t){var i=e.typeOf(t);try{if(t instanceof f){if(!t.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);m.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new n.ImageError(n.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(i,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===i)"data:"===t.substr(0,5)?c.call(this,new l(null,{data:t}),arguments[1]):v.apply(this,arguments);else{if("node"!==i||"img"!==t.nodeName.toLowerCase())throw new n.DOMException(n.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r.code)}}function m(t,n){var i=this.connectRuntime(t.ruid);this.ruid=i.uid,i.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(n)?!0:n)}function g(t,n){function i(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){i(t)}),n&&"string"==typeof n.required_caps&&(n.required_caps=o.parseCaps(n.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},n))):i(this.connectRuntime(t.ruid))}function v(e,t){var n=this,i;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){c.apply(this,arguments)},downsize:function(t){var i={width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90,crop:!1,preserveHeaders:!0,resample:!1};t="object"==typeof t?e.extend(i,t):e.extend(i,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]});try{if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>f.MAX_RESIZE_WIDTH||this.height>f.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);this.exec("Image","downsize",t.width,t.height,t.crop,t.preserveHeaders)}catch(r){this.trigger("error",r.code)}},crop:function(e,t,n){this.downsize(e,t,!0,n)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);var e=this.connectRuntime(this.ruid);return e.exec.call(this,"Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsBlob",e||"image/jpeg",t||90)},getAsDataURL:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsDataURL",e||"image/jpeg",t||90)},getAsBinaryString:function(e,t){var n=this.getAsDataURL(e,t);return h.atob(n.substring(n.indexOf("base64,")+7))},embed:function(i,r){function o(t,r){var o=this;if(u.can("create_canvas")){var l=o.getAsCanvas();if(l)return i.appendChild(l),l=null,o.destroy(),void a.trigger("embedded")}var d=o.getAsDataURL(t,r);if(!d)throw new n.ImageError(n.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",d.length))i.innerHTML='',o.destroy(),a.trigger("embedded");else{var f=new s;f.bind("TransportingComplete",function(){c=a.connectRuntime(this.result.ruid),a.bind("Embedded",function(){e.extend(c.getShimContainer().style,{top:"0px",left:"0px",width:o.width+"px",height:o.height+"px"}),c=null},999),c.exec.call(a,"ImageView","display",this.result.uid,width,height),o.destroy()}),f.transport(h.atob(d.substring(d.indexOf("base64,")+7)),t,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:i})}}var a=this,c;r=e.extend({width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90},r||{});try{if(!(i=t.get(i)))throw new n.DOMException(n.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);this.width>f.MAX_RESIZE_WIDTH||this.height>f.MAX_RESIZE_HEIGHT;var l=new f;return l.bind("Resize",function(){o.call(this,r.type,r.quality)}),l.bind("Load",function(){l.downsize(r)}),this.meta.thumb&&this.meta.thumb.width>=r.width&&this.meta.thumb.height>=r.height?l.load(this.meta.thumb.data):l.clone(this,!1),l}catch(d){this.trigger("error",d.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}}),this.handleEventProps(p),this.bind("Load Resize",function(){i.call(this)},999)}var p=["progress","load","error","resize","embedded"];return f.MAX_RESIZE_WIDTH=8192,f.MAX_RESIZE_HEIGHT=8192,f.prototype=c.instance,f}),i(D,[u,f,m,c],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue,c=e.extend({access_binary:s(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return r.can("access_binary")&&!!a.Image},display_media:s(i.can("create_canvas")||i.can("use_data_uri_over32kb")),do_cors:s(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:s(function(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==i.browser||i.verComp(i.version,9,">"))}()),filter_by_extension:s(function(){return"Chrome"===i.browser&&i.verComp(i.version,28,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||"Safari"===i.browser&&i.verComp(i.version,7,">=")}()),return_response_headers:u,return_response_type:function(e){return"json"===e&&window.JSON?!0:i.can("return_response_type",e)},return_status_code:u,report_upload_progress:s(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return r.can("access_binary")&&i.can("create_canvas")},select_file:function(){return i.can("use_fileinput")&&window.File},select_folder:function(){return r.can("select_file")&&"Chrome"===i.browser&&i.verComp(i.version,21,">=")},select_multiple:function(){return!(!r.can("select_file")||"Safari"===i.browser&&"Windows"===i.os||"iOS"===i.os&&i.verComp(i.osVersion,"7.0.0",">")&&i.verComp(i.osVersion,"8.0.0","<"))},send_binary_string:s(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:s(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||r.can("send_binary_string")},slice_blob:s(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return r.can("slice_blob")&&r.can("send_multipart")},summon_file_dialog:function(){return r.can("select_file")&&("Firefox"===i.browser&&i.verComp(i.version,4,">=")||"Opera"===i.browser&&i.verComp(i.version,12,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||!!~e.inArray(i.browser,["Chrome","Safari"]))},upload_filesize:u},arguments[2]);n.call(this,t,arguments[1]||o,c),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html5",a={};return n.addConstructor(o,r),a}),i(N,[u],function(e){function t(){this.returnValue=!1}function n(){this.cancelBubble=!0}var i={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=n,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid()),i.hasOwnProperty(o[r])||(i[o[r]]={}),l=i[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,n,o){var a,s;if(n=n.toLowerCase(),t[r]&&i[t[r]]&&i[t[r]][n]){a=i[t[r]][n];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(n,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+n,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete i[t[r]][n],e.isEmptyObj(i[t[r]])){delete i[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,n){t&&t[r]&&e.each(i[t[r]],function(e,i){a(t,i,n)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),i(L,[D,E,u,h,N,d,c],function(e,t,n,i,r,o,a){function s(){var e;n.extend(this,{init:function(s){var u=this,c=u.getRuntime(),l,d,h,f,p,m;e=s,h=e.accept.mimes||o.extList2mimes(e.accept,c.can("filter_by_extension")),d=c.getShimContainer(),d.innerHTML='",l=i.get(c.uid),n.extend(l.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),f=i.get(e.browse_button),c.can("summon_file_dialog")&&("static"===i.getStyle(f,"position")&&(f.style.position="relative"),p=parseInt(i.getStyle(f,"z-index"),10)||1,f.style.zIndex=p,d.style.zIndex=p-1,r.addEvent(f,"click",function(e){var t=i.get(c.uid);t&&!t.disabled&&t.click(),e.preventDefault()},u.uid)),m=c.can("summon_file_dialog")?f:d,r.addEvent(m,"mouseover",function(){u.trigger("mouseenter")},u.uid),r.addEvent(m,"mouseout",function(){u.trigger("mouseleave")},u.uid),r.addEvent(m,"mousedown",function(){u.trigger("mousedown")},u.uid),r.addEvent(i.get(e.container),"mouseup",function(){u.trigger("mouseup")},u.uid),l.onchange=function g(i){if(u.files=[],n.each(this.files,function(n){var i="";return e.directory&&"."==n.name?!0:(n.webkitRelativePath&&(i="/"+n.webkitRelativePath.replace(/^\//,"")),n=new t(c.uid,n),n.relativePath=i,void u.files.push(n))}),"IE"!==a.browser&&"IEMobile"!==a.browser)this.value="";else{var r=this.cloneNode(!0);this.parentNode.replaceChild(r,this),r.onchange=g}u.files.length&&u.trigger("change")},u.trigger({type:"ready",async:!0}),d=null},disable:function(e){var t=this.getRuntime(),n;(n=i.get(t.uid))&&(n.disabled=!!e)},destroy:function(){var t=this.getRuntime(),n=t.getShim(),o=t.getShimContainer();r.removeAllEvents(o,this.uid),r.removeAllEvents(e&&i.get(e.container),this.uid),r.removeAllEvents(e&&i.get(e.browse_button),this.uid),o&&(o.innerHTML=""),n.removeInstance(this.uid),e=o=n=null}})}return e.FileInput=s}),i(C,[D,y],function(e,t){function n(){function e(e,t,n){var i;if(!window.File.prototype.slice)return(i=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?i.call(e,t,n):null;try{return e.slice(),e.slice(t,n)}catch(r){return e.slice(t,n-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))}}return e.Blob=n}),i(M,[D,E,u,h,N,d],function(e,t,n,i,r,o){function a(){function e(e){if(!e.dataTransfer||!e.dataTransfer.types)return!1;var t=n.toArray(e.dataTransfer.types||[]);return-1!==n.inArray("Files",t)||-1!==n.inArray("public.file-url",t)||-1!==n.inArray("application/x-moz-file",t)}function a(e,n){if(u(e)){var i=new t(g,e);i.relativePath=n||"",f.push(i)}}function s(e){for(var t=[],i=0;i=")&&u.verComp(u.version,7,"<"),h="Android Browser"===u.browser,m=!1;if(p=n.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),f=c(),f.open(n.method,n.url,n.async,n.user,n.password),r instanceof o)r.isDetached()&&(m=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),m=!0;else if((l||h)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return void e.call(s,n,r);if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}f.upload?(n.withCredentials&&(f.withCredentials=!0),f.addEventListener("load",function(e){s.trigger(e)}),f.addEventListener("error",function(e){s.trigger(e)}),f.addEventListener("progress",function(e){s.trigger(e)}),f.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):f.onreadystatechange=function v(){switch(f.readyState){case 1:break;case 2:break;case 3:var e,t;try{i.hasSameOrigin(n.url)&&(e=f.getResponseHeader("Content-Length")||0),f.responseText&&(t=f.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:f.onreadystatechange=function(){},s.trigger(0===f.status?"error":"load")}},t.isEmptyObj(n.headers)||t.each(n.headers,function(e,t){f.setRequestHeader(t,e)}),""!==n.responseType&&"responseType"in f&&("json"!==n.responseType||u.can("return_response_type","json")?f.responseType=n.responseType:f.responseType="text"),m?f.sendAsBinary?f.sendAsBinary(r):!function(){for(var e=new Uint8Array(r.length),t=0;t0&&o.set(new Uint8Array(t.slice(0,e)),0),o.set(new Uint8Array(r),e),o.set(new Uint8Array(t.slice(e+i)),e+r.byteLength),this.clear(),t=o.buffer,n=new DataView(t);break}default:return t}},length:function(){return t?t.byteLength:0},clear:function(){n=t=null}})}function i(t){function n(e,n,i){i=3===arguments.length?i:t.length-n-1,t=t.substr(0,n)+e+t.substr(i+n)}e.extend(this,{readByteAt:function(e){return t.charCodeAt(e)},writeByteAt:function(e,t){n(String.fromCharCode(t),e,1)},SEGMENT:function(e,i,r){switch(arguments.length){case 1:return t.substr(e);case 2:return t.substr(e,i);case 3:n(null!==r?r:"",e,i);break;default:return t}},length:function(){return t?t.length:0},clear:function(){t=null}})}return e.extend(t.prototype,{littleEndian:!1,read:function(e,t){var n,i,r;if(e+t>this.length())throw new Error("You are trying to read outside the source boundaries.");for(i=this.littleEndian?0:-8*(t-1),r=0,n=0;t>r;r++)n|=this.readByteAt(e+r)<this.length())throw new Error("You are trying to write outside the source boundaries.");for(i=this.littleEndian?0:-8*(n-1),r=0;n>r;r++)this.writeByteAt(e+r,t>>Math.abs(i+8*r)&255)},BYTE:function(e){return this.read(e,1)},SHORT:function(e){return this.read(e,2)},LONG:function(e){return this.read(e,4)},SLONG:function(e){var t=this.read(e,4);return t>2147483647?t-4294967296:t},CHAR:function(e){return String.fromCharCode(this.read(e,1))},STRING:function(e,t){return this.asArray("CHAR",e,t).join("")},asArray:function(e,t,n){for(var i=[],r=0;n>r;r++)i[r]=this[e](t+r);return i}}),t}),i(B,[H,f],function(e,t){return function n(i){var r=[],o,a,s,u=0;if(o=new e(i),65496!==o.SHORT(0))throw o.clear(),new t.ImageError(t.ImageError.WRONG_FORMAT);for(a=2;a<=o.length();)if(s=o.SHORT(a),s>=65488&&65495>=s)a+=2;else{if(65498===s||65497===s)break;u=o.SHORT(a+2)+2,s>=65505&&65519>=s&&r.push({hex:s,name:"APP"+(15&s),start:a,length:u,segment:o.SEGMENT(a,u)}),a+=u}return o.clear(),{headers:r,restore:function(t){var n,i,o;for(o=new e(t),a=65504==o.SHORT(2)?4+o.SHORT(4):2,i=0,n=r.length;n>i;i++)o.SEGMENT(a,0,r[i].segment),a+=r[i].length;return t=o.SEGMENT(),o.clear(),t},strip:function(t){var i,r,o,a;for(o=new n(t),r=o.headers,o.purge(),i=new e(t),a=r.length;a--;)i.SEGMENT(r[a].start,r[a].length,"");return t=i.SEGMENT(),i.clear(),t},get:function(e){for(var t=[],n=0,i=r.length;i>n;n++)r[n].name===e.toUpperCase()&&t.push(r[n].segment);return t}, +set:function(e,t){var n=[],i,o,a;for("string"==typeof t?n.push(t):n=t,i=o=0,a=r.length;a>i&&(r[i].name===e.toUpperCase()&&(r[i].segment=n[o],r[i].length=n[o].length,o++),!(o>=n.length));i++);},purge:function(){this.headers=r=[]}}}}),i(k,[u,H,f],function(e,n,i){function r(o){function a(n,r){var o=this,a,s,u,c,h,f,p,m,g=[],v={},w={1:"BYTE",7:"UNDEFINED",2:"ASCII",3:"SHORT",4:"LONG",5:"RATIONAL",9:"SLONG",10:"SRATIONAL"},y={BYTE:1,UNDEFINED:1,ASCII:1,SHORT:2,LONG:4,RATIONAL:8,SLONG:4,SRATIONAL:8};for(a=o.SHORT(n),s=0;a>s;s++)if(g=[],p=n+2+12*s,u=r[o.SHORT(p)],u!==t){if(c=w[o.SHORT(p+=2)],h=o.LONG(p+=2),f=y[c],!f)throw new i.ImageError(i.ImageError.INVALID_META_ERR);if(p+=4,f*h>4&&(p=o.LONG(p)+d.tiffHeader),p+f*h>=this.length())throw new i.ImageError(i.ImageError.INVALID_META_ERR);"ASCII"!==c?(g=o.asArray(c,p,h),m=1==h?g[0]:g,l.hasOwnProperty(u)&&"object"!=typeof m?v[u]=l[u][m]:v[u]=m):v[u]=e.trim(o.STRING(p,h).replace(/\0$/,""))}return v}function s(e,t,n){var i,r,o,a=0;if("string"==typeof t){var s=c[e.toLowerCase()];for(var u in s)if(s[u]===t){t=u;break}}i=d[e.toLowerCase()+"IFD"],r=this.SHORT(i);for(var l=0;r>l;l++)if(o=i+12*l+2,this.SHORT(o)==t){a=o+8;break}if(!a)return!1;try{this.write(a,n,4)}catch(h){return!1}return!0}var u,c,l,d,h,f;if(n.call(this,o),c={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"},thumb:{513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},d={tiffHeader:10},h=d.tiffHeader,u={clear:this.clear},e.extend(this,{read:function(){try{return r.prototype.read.apply(this,arguments)}catch(e){throw new i.ImageError(i.ImageError.INVALID_META_ERR)}},write:function(){try{return r.prototype.write.apply(this,arguments)}catch(e){throw new i.ImageError(i.ImageError.INVALID_META_ERR)}},UNDEFINED:function(){return this.BYTE.apply(this,arguments)},RATIONAL:function(e){return this.LONG(e)/this.LONG(e+4)},SRATIONAL:function(e){return this.SLONG(e)/this.SLONG(e+4)},ASCII:function(e){return this.CHAR(e)},TIFF:function(){return f||null},EXIF:function(){var t=null;if(d.exifIFD){try{t=a.call(this,d.exifIFD,c.exif)}catch(n){return null}if(t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var i=0,r="";i=65472&&65475>=n)return t+=5,{height:e.SHORT(t),width:e.SHORT(t+=2)};i=e.SHORT(t+=2),t+=i-2}return null}function s(){var e=d.thumb(),t,n;return e&&(t=new i(e),n=a(t),t.clear(),n)?(n.data=e,n):null}function u(){d&&l&&c&&(d.clear(),l.purge(),c.clear(),h=l=d=c=null)}var c,l,d,h;if(c=new i(o),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new n(o);try{d=new r(l.get("app1")[0])}catch(f){}h=a.call(this),e.extend(this,{type:"image/jpeg",size:c.length(),width:h&&h.width||0,height:h&&h.height||0,setExif:function(t,n){return d?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,n),void l.set("app1",d.SEGMENT())):!1},writeHeaders:function(){return l.restore(arguments.length?arguments[0]:o)},stripHeaders:function(e){return l.strip(e)},purge:function(){u.call(this)}}),d&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS(),thumb:s()})}return o}),i(G,[f,u,H],function(e,t,n){function i(i){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:s.LONG(t),height:s.LONG(t+=4)}):null}function o(){s&&(s.clear(),i=l=u=c=s=null)}function a(e){var t,n,i,r;return t=s.LONG(e),n=s.STRING(e+=4,4),i=e+=4,r=s.LONG(e+t),{length:t,type:n,start:i,CRC:r}}var s,u,c,l;s=new n(i),function(){var t=0,n=0,i=[35152,20039,3338,6666];for(n=0;ng;){for(var v=g+h>a?a-g:h,w=0;o>w;){var y=w+h>o?o-w:h;p.clearRect(0,0,h,h),p.drawImage(e,-w,-g);var E=w*s/o+c<<0,_=Math.ceil(y*s/o),b=g*u/a/m+l<<0,x=Math.ceil(v*u/a/m);d.drawImage(f,0,0,y,v,E,b,_,x),w+=h}g+=h}f=p=null}function t(e){var t=e.naturalWidth,n=e.naturalHeight;if(t*n>1048576){var i=document.createElement("canvas");i.width=i.height=1;var r=i.getContext("2d");return r.drawImage(e,-t+1,0),0===r.getImageData(0,0,1,1).data[3]}return!1}function n(e,t,n){var i=document.createElement("canvas");i.width=1,i.height=n;var r=i.getContext("2d");r.drawImage(e,0,0);for(var o=r.getImageData(0,0,1,n).data,a=0,s=n,u=n;u>a;){var c=o[4*(u-1)+3];0===c?s=u:a=u,u=s+a>>1}i=null;var l=u/n;return 0===l?1:l}return{isSubsampled:t,renderTo:e}}),i(j,[D,u,f,w,y,E,z,q,d,c],function(e,t,n,i,r,o,a,s,u,c){function l(){function e(){if(!_&&!y)throw new n.ImageError(n.DOMException.INVALID_STATE_ERR);return _||y}function l(e){return i.atob(e.substring(e.indexOf("base64,")+7))}function d(e,t){return"data:"+(t||"")+";base64,"+i.btoa(e)}function h(e){var t=this;y=new Image,y.onerror=function(){v.call(this),t.trigger("error",n.ImageError.WRONG_FORMAT)},y.onload=function(){t.trigger("load")},y.src="data:"==e.substr(0,5)?e:d(e,x.type)}function f(e,t){var i=this,r;return window.FileReader?(r=new FileReader,r.onload=function(){t(this.result)},r.onerror=function(){i.trigger("error",n.ImageError.WRONG_FORMAT)},r.readAsDataURL(e),void 0):t(e.getAsDataURL())}function p(n,i,r,o){var a=this,s,u,c=0,l=0,d,h,f,p;if(A=o,p=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1,-1!==t.inArray(p,[5,6,7,8])){var v=n;n=i,i=v}return d=e(),r?(n=Math.min(n,d.width),i=Math.min(i,d.height),s=Math.max(n/d.width,i/d.height)):s=Math.min(n/d.width,i/d.height),s>1&&!r&&o?void this.trigger("Resize"):(_||(_=document.createElement("canvas")),h=Math.round(d.width*s),f=Math.round(d.height*s),r?(_.width=n,_.height=i,h>n&&(c=Math.round((h-n)/2)),f>i&&(l=Math.round((f-i)/2))):(_.width=h,_.height=f),A||g(_.width,_.height,p),m.call(this,d,_,-c,-l,h,f),this.width=_.width,this.height=_.height,R=!0,void a.trigger("Resize"))}function m(e,t,n,i,r,o){if("iOS"===c.OS)s.renderTo(e,t,{width:r,height:o,x:n,y:i});else{var a=t.getContext("2d");a.drawImage(e,n,i,r,o)}}function g(e,t,n){switch(n){case 5:case 6:case 7:case 8:_.width=t,_.height=e;break;default:_.width=e,_.height=t}var i=_.getContext("2d");switch(n){case 2:i.translate(e,0),i.scale(-1,1);break;case 3:i.translate(e,t),i.rotate(Math.PI);break;case 4:i.translate(0,t),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-t);break;case 7:i.rotate(.5*Math.PI),i.translate(e,-t),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-e,0)}}function v(){E&&(E.purge(),E=null),b=y=_=x=null,R=!1}var w=this,y,E,_,b,x,R=!1,A=!0;t.extend(this,{loadFromBlob:function(e){var t=this,i=t.getRuntime(),r=arguments.length>1?arguments[1]:!0;if(!i.can("access_binary"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);return x=e,e.isDetached()?(b=e.getSource(),void h.call(this,b)):void f.call(this,e.getSource(),function(e){r&&(b=l(e)),h.call(t,e)})},loadFromImage:function(e,t){this.meta=e.meta,x=new o(null,{name:e.name,size:e.size,type:e.type}),h.call(this,t?b=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t=this.getRuntime(),n;return!E&&b&&t.can("access_image_binary")&&(E=new a(b)),n={width:e().width||0,height:e().height||0,type:x.type||u.getFileMime(x.name),size:b&&b.length||x.size||0,name:x.name||"",meta:E&&E.meta||this.meta||{}},!n.meta||!n.meta.thumb||n.meta.thumb.data instanceof r||(n.meta.thumb.data=new r(null,{type:"image/jpeg",data:n.meta.thumb.data})),n},downsize:function(){p.apply(this,arguments)},getAsCanvas:function(){return _&&(_.id=this.uid+"_canvas"),_},getAsBlob:function(e,t){return e!==this.type&&p.call(this,this.width,this.height,!1),new o(null,{name:x.name||"",type:e,data:w.getAsBinaryString.call(this,e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!R)return y.src;if("image/jpeg"!==e)return _.toDataURL("image/png");try{return _.toDataURL("image/jpeg",t/100)}catch(n){return _.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!R)return b||(b=l(w.getAsDataURL(e,t))),b;if("image/jpeg"!==e)b=l(w.getAsDataURL(e,t));else{var n;t||(t=90);try{n=_.toDataURL("image/jpeg",t/100)}catch(i){n=_.toDataURL("image/jpeg")}b=l(n),E&&(b=E.stripHeaders(b),A&&(E.meta&&E.meta.exif&&E.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),b=E.writeHeaders(b)),E.purge(),E=null)}return R=!1,b},destroy:function(){w=null,v.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=l}),i(X,[u,c,h,f,m],function(e,t,n,i,r){function o(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(n){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function a(e){var i=n.get(e);i&&"OBJECT"==i.nodeName&&("IE"===t.browser?(i.style.display="none",function r(){4==i.readyState?s(e):setTimeout(r,10)}()):i.parentNode.removeChild(i))}function s(e){var t=n.get(e);if(t){for(var i in t)"function"==typeof t[i]&&(t[i]=null);t.parentNode.removeChild(t)}}function u(s){var u=this,d;s=e.extend({swf_url:t.swf_url},s),r.call(this,s,c,{access_binary:function(e){return e&&"browser"===u.mode},access_image_binary:function(e){return e&&"browser"===u.mode},display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===u.mode},resize_image:r.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===u.mode},return_status_code:function(t){return"browser"===u.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:function(e){return e&&"browser"===u.mode},send_browser_cookies:function(e){return e&&"browser"===u.mode},send_custom_headers:function(e){return e&&"browser"===u.mode},send_multipart:r.capTrue,slice_blob:function(e){return e&&"browser"===u.mode},stream_upload:function(e){return e&&"browser"===u.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===u.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),o()<10&&(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid)},shimExec:function(e,t){var n=[].slice.call(arguments,2);return u.getShim().exec(this.uid,e,t,n)},init:function(){var n,r,o;o=this.getShimContainer(),e.extend(o.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),n='',"IE"===t.browser?(r=document.createElement("div"),o.appendChild(r),r.outerHTML=n,r=o=null):o.innerHTML=n,d=setTimeout(function(){u&&!u.initialized&&u.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){a(u.uid),e.call(u),clearTimeout(d),s=d=e=u=null}}(this.destroy)},l)}var c="flash",l={};return r.addConstructor(c,u),l}),i(V,[X,E,u],function(e,t,n){var i={init:function(e){var i=this,r=this.getRuntime();this.bind("Change",function(){var e=r.shimExec.call(i,"FileInput","getFiles");i.files=[],n.each(e,function(e){i.files.push(new t(r.uid,e))})},999),this.getRuntime().shimExec.call(this,"FileInput","init",{name:e.name,accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=i}),i(W,[X,y],function(e,t){var n={slice:function(e,n,i,r){var o=this.getRuntime();return 0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),e=o.shimExec.call(this,"Blob","slice",n,i,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=n}),i(Y,[X,w],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i=this;return i.result="","readAsDataURL"===e&&(i.result="data:"+(t.type||"")+";base64,"),i.bind("Progress",function(t,r){r&&(i.result+=n(r,e))},999),i.getRuntime().shimExec.call(this,"FileReader","readAsBase64",t.uid)}};return e.FileReader=i}),i($,[X,w],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i,r=this.getRuntime();return(i=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"+i),n(i,e,t.type)):null}};return e.FileReaderSync=i}),i(J,[X,u,y,E,A,I,S],function(e,t,n,i,r,o,a){var s={send:function(e,i){function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,i)}function s(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),i=null,r()}function u(e,t){var n=new a;n.bind("TransportingComplete",function(){t(this.result)}),n.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),i instanceof o){var d;if(i.each(function(e,t){e instanceof n?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),i.hasBlob()){var h=i.getBlob();h.isDetached()?u(h,function(e){h.destroy(),s(d,e)}):s(d,h)}else i=null,r()}else i instanceof n?i.isDetached()?u(i,function(e){i.destroy(),i=e.uid,r()}):(i=i.uid,r()):r()},getResponse:function(e){var n,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob")){if(o=new i(a.uid,o),"blob"===e)return o;try{if(n=new r,~t.inArray(e,["","text"]))return n.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(n.readAsText(o))}finally{o.destroy()}}return null},abort:function(e){var t=this.getRuntime();t.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=s}),i(Z,[X,y],function(e,t){var n={getAsBlob:function(e){var n=this.getRuntime(),i=n.shimExec.call(this,"Transporter","getAsBlob",e);return i?new t(n.uid,i):null}};return e.Transporter=n}),i(K,[X,u,S,y,A],function(e,t,n,i,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(i,"Image","loadFromBlob",e.uid),i=r=null}var i=this,r=i.getRuntime();if(e.isDetached()){var o=new n;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSource(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getInfo:function(){var e=this.getRuntime(),t=e.shimExec.call(this,"Image","getInfo");return!t.meta||!t.meta.thumb||t.meta.thumb.data instanceof i||(t.meta.thumb.data=new i(e.uid,t.meta.thumb.data)),t},getAsBlob:function(e,t){var n=this.getRuntime(),r=n.shimExec.call(this,"Image","getAsBlob",e,t);return r?new i(n.uid,r):null},getAsDataURL:function(){var e=this.getRuntime(),t=e.Image.getAsBlob.apply(this,arguments),n;return t?(n=new r,n.readAsDataURL(t)):null}};return e.Image=o}),i(Q,[u,c,h,f,m],function(e,t,n,i,r){function o(e){var t=!1,n=null,i,r,o,a,s,u=0;try{try{n=new ActiveXObject("AgControl.AgControl"),n.IsVersionSupported(e)&&(t=!0),n=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(i=l.description,"1.0.30226.2"===i&&(i="2.0.30226.2"),r=i.split(".");r.length>3;)r.pop();for(;r.length<4;)r.push(0);for(o=e.split(".");o.length>4;)o.pop();do a=parseInt(o[u],10),s=parseInt(r[u],10),u++;while(u=a&&!isNaN(a)&&(t=!0)}}}catch(d){t=!1}return t}function a(a){var c=this,l;a=e.extend({xap_url:t.xap_url},a),r.call(this,a,s,{access_binary:r.capTrue,access_image_binary:r.capTrue,display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:r.capTrue,resize_image:r.capTrue,return_response_headers:function(e){return e&&"client"===c.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:r.capTrue,send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"client"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:r.capTrue,use_http_method:function(t){return"client"===c.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),o("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid).content.Moxie},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='',l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="silverlight",u={};return r.addConstructor(s,a),u}),i(ee,[Q,E,u],function(e,t,n){var i={init:function(e){function i(e){for(var t="",n=0;ni;i++)n=t.keys[i],s=t[n],s&&(/^(\d|[1-9]\d+)$/.test(s)?s=parseInt(s,10):/^\d*\.\d+$/.test(s)&&(s=parseFloat(s)),r.meta[e][n]=s)}),!r.meta||!r.meta.thumb||r.meta.thumb.data instanceof n||(r.meta.thumb.data=new n(e.uid,r.meta.thumb.data))),r.width=parseInt(o.width,10),r.height=parseInt(o.height,10),r.size=parseInt(o.size,10),r.type=o.type,r.name=o.name,r}})}),i(ue,[u,f,m,c],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue;n.call(this,t,o,{access_binary:s(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:s(a.Image&&(i.can("create_canvas")||i.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:s(function(){return"Chrome"===i.browser&&i.verComp(i.version,28,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||"Safari"===i.browser&&i.verComp(i.version,7,">=")}()),resize_image:function(){return a.Image&&r.can("access_binary")&&i.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return i.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return r.can("select_file")},summon_file_dialog:function(){return r.can("select_file")&&("Firefox"===i.browser&&i.verComp(i.version,4,">=")||"Opera"===i.browser&&i.verComp(i.version,12,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||!!~e.inArray(i.browser,["Chrome","Safari"]))},upload_filesize:u,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html4",a={};return n.addConstructor(o,r),a}),i(ce,[ue,E,u,h,N,d,c],function(e,t,n,i,r,o,a){function s(){function e(){var o=this,l=o.getRuntime(),d,h,f,p,m,g;g=n.guid("uid_"),d=l.getShimContainer(),s&&(f=i.get(s+"_form"),f&&n.extend(f.style,{top:"100%"})),p=document.createElement("form"),p.setAttribute("id",g+"_form"),p.setAttribute("method","post"),p.setAttribute("enctype","multipart/form-data"),p.setAttribute("encoding","multipart/form-data"),n.extend(p.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),m=document.createElement("input"),m.setAttribute("id",g),m.setAttribute("type","file"),m.setAttribute("name",c.name||"Filedata"),m.setAttribute("accept",u.join(",")),n.extend(m.style,{fontSize:"999px",opacity:0}),p.appendChild(m),d.appendChild(p),n.extend(m.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===a.browser&&a.verComp(a.version,10,"<")&&n.extend(m.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),m.onchange=function(){var n;if(this.value){if(this.files){if(n=this.files[0],0===n.size)return void p.parentNode.removeChild(p)}else n={name:this.value};n=new t(l.uid,n),this.onchange=function(){},e.call(o),o.files=[n],m.setAttribute("id",n.uid),p.setAttribute("id",n.uid+"_form"),o.trigger("change"),m=p=null}},l.can("summon_file_dialog")&&(h=i.get(c.browse_button),r.removeEvent(h,"click",o.uid),r.addEvent(h,"click",function(e){m&&!m.disabled&&m.click(),e.preventDefault()},o.uid)),s=g,d=f=h=null}var s,u=[],c;n.extend(this,{init:function(t){var n=this,a=n.getRuntime(),s;c=t,u=t.accept.mimes||o.extList2mimes(t.accept,a.can("filter_by_extension")),s=a.getShimContainer(),function(){var e,o,u;e=i.get(t.browse_button),a.can("summon_file_dialog")&&("static"===i.getStyle(e,"position")&&(e.style.position="relative"),o=parseInt(i.getStyle(e,"z-index"),10)||1,e.style.zIndex=o,s.style.zIndex=o-1),u=a.can("summon_file_dialog")?e:s,r.addEvent(u,"mouseover",function(){n.trigger("mouseenter")},n.uid),r.addEvent(u,"mouseout",function(){n.trigger("mouseleave")},n.uid),r.addEvent(u,"mousedown",function(){n.trigger("mousedown")},n.uid),r.addEvent(i.get(t.container),"mouseup",function(){n.trigger("mouseup")},n.uid),e=null}(),e.call(this),s=null,n.trigger({type:"ready",async:!0})},disable:function(e){var t;(t=i.get(s))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),n=e.getShimContainer();r.removeAllEvents(n,this.uid),r.removeAllEvents(c&&i.get(c.container),this.uid),r.removeAllEvents(c&&i.get(c.browse_button),this.uid),n&&(n.innerHTML=""),t.removeInstance(this.uid),s=u=c=n=t=null}})}return e.FileInput=s}),i(le,[ue,F],function(e,t){return e.FileReader=t}),i(de,[ue,u,h,x,f,N,y,I],function(e,t,n,i,r,o,a,s){function u(){function e(e){var t=this,i,r,a,s,u=!1;if(l){if(i=l.id.replace(/_iframe$/,""),r=n.get(i+"_form")){for(a=r.getElementsByTagName("input"),s=a.length;s--;)switch(a[s].getAttribute("type")){case"hidden":a[s].parentNode.removeChild(a[s]);break;case"file":u=!0}a=[],u||r.parentNode.removeChild(r),r=null}setTimeout(function(){o.removeEvent(l,"load",t.uid),l.parentNode&&l.parentNode.removeChild(l);var n=t.getRuntime().getShimContainer();n.children.length||n.parentNode.removeChild(n),n=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,h){function f(){var n=m.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='',l=r.firstChild,n.appendChild(l),o.addEvent(l,"load",function(){var n;try{n=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(n.title)?u=n.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(n.body.innerHTML),p.trigger({type:"progress",loaded:c.length,total:c.length}),y&&p.trigger({type:"uploadprogress",loaded:y.size||1025,total:y.size||1025}))}catch(r){if(!i.hasSameOrigin(d.url))return void e.call(p,function(){p.trigger("error")});u=404}e.call(p,function(){p.trigger("load")})},p.uid)}var p=this,m=p.getRuntime(),g,v,w,y;if(u=c=null,h instanceof s&&h.hasBlob()){if(y=h.getBlob(),g=y.uid,w=n.get(g),v=n.get(g+"_form"),!v)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else g=t.guid("uid_"),v=document.createElement("form"),v.setAttribute("id",g+"_form"),v.setAttribute("method",d.method),v.setAttribute("enctype","multipart/form-data"),v.setAttribute("encoding","multipart/form-data"),m.getShimContainer().appendChild(v);v.setAttribute("target",g+"_iframe"),h instanceof s&&h.each(function(e,n){if(e instanceof a)w&&w.setAttribute("name",n);else{var i=document.createElement("input");t.extend(i,{type:"hidden",name:n,value:e}),w?v.insertBefore(i,w):v.appendChild(i)}}),v.setAttribute("action",d.url),f(),v.submit(),p.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{ +return JSON.parse(c.replace(/^\s*]*>/,"").replace(/<\/pre>\s*$/,""))}catch(n){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})}})}return e.XMLHttpRequest=u}),i(he,[ue,j],function(e,t){return e.Image=t}),a([u,c,l,d,h,f,p,m,g,v,w,y,E,_,b,x,R,A,I,T,S,O,N])}(this);;(function(e){"use strict";var t={},n=e.moxie.core.utils.Basic.inArray;return function r(e){var i,s;for(i in e)s=typeof e[i],s==="object"&&!~n(i,["Exceptions","Env","Mime"])?r(e[i]):s==="function"&&(t[i]=e[i])}(e.moxie),t.Env=e.moxie.core.utils.Env,t.Mime=e.moxie.core.utils.Mime,t.Exceptions=e.moxie.core.Exceptions,e.mOxie=t,e.o||(e.o=t),t})(this); +/** + * Plupload - multi-runtime File Uploader + * v2.1.8 + * + * Copyright 2013, Moxiecode Systems AB + * Released under GPL License. + * + * License: http://www.plupload.com/license + * Contributing: http://www.plupload.com/contributing + * + * Date: 2015-07-21 + */ +;(function(e,t,n){function s(e){function r(e,t,r){var i={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};i[e]?n[i[e]]=t:r||(n[e]=t)}var t=e.required_features,n={};if(typeof t=="string")o.each(t.split(/\s*,\s*/),function(e){r(e,!0)});else if(typeof t=="object")o.each(t,function(e,t){r(t,e)});else if(t===!0){e.chunk_size>0&&(n.slice_blob=!0);if(e.resize.enabled||!e.multipart)n.send_binary_string=!0;o.each(e,function(e,t){r(t,!!e,!0)})}return n}var r=e.setTimeout,i={},o={VERSION:"2.1.8",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.isEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t0?"&":"?")+n),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n0?Math.ceil(e.loaded/e.size*100):100,b()}function b(){var e,t;d.reset();for(e=0;e0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",O),this.bind("BeforeUpload",C),this.bind("UploadFile",k),this.bind("UploadProgress",L),this.bind("StateChanged",A),this.bind("QueueChanged",b),this.bind("Error",_),this.bind("FileUploaded",M),this.bind("Destroy",D)}function x(e,n){var r=this,i=0,s=[],u={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_button_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("mousedown",function(){r.trigger("Browse")}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,r,i){var s=new t.Image;try{s.onload=function(){if(r.width>this.width&&r.height>this.height&&r.quality===n&&r.preserve_headers&&!r.crop)return this.destroy(),i(e);s.downsize(r.width,r.height,r.crop,r.preserve_headers)},s.onresize=function(){i(this.getAsBlob(e.type,r.quality)),this.destroy()},s.onerror=function(){i(e)},s.load(e)}catch(o){i(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t,a.send_file_name=!0;break;case"multipart":a[e]=t,t||(a.send_file_name=!0);break;case"unique_names":a[e]=t,t&&(a.send_file_name=!0);break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){if(e.settings.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function k(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g={},y;if(n.status!==o.UPLOADING||e.state===o.STOPPED)return;e.settings.send_file_name&&(g.name=n.target_name||n.name),s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s?s*Math.floor(n.loaded/s):0),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.settings.resize,function(e){c=e,n.size=e.size,p()}):p()}function L(e,t){y(t)}function A(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function O(){m&&m.abort()}function M(e){b(),r(function(){g.call(e)},1)}function _(e,t){t.code===o.INIT_ERROR?e.destroy():t.code===o.HTTP_ERROR&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function D(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)}),S.call(this);if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function c(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function h(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!l)return!1;e.ruid=l,e.connectRuntime(l)}h(new o.File(e))}else e instanceof t.Blob?(h(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){c(e,function(n){n||(f.push(e),a.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?h(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,h):i==="array"&&(n=null,t.each(e,h))}var s=this,u=[],a=[],l;l=w(),h(e),u.length&&t.inSeries(u,function(){a.length&&s.trigger("FilesAdded",a)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(o.each(r,function(e){if(e.status===o.UPLOADING)return i=!0,!1}),i&&this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),i&&this.start(),r},dispatchEvent:function(e){var t,n,r;e=e.toLowerCase(),t=this.hasEventListener(e);if(t){t.sort(function(e,t){return t.priority-e.priority}),n=[].slice.call(arguments),n.shift(),n.unshift(this);for(var i=0;i0&&(n.slice_blob=!0);if(e.resize.enabled||!e.multipart)n.send_binary_string=!0;o.each(e,function(e,t){r(t,!!e,!0)})}return n}var r=e.setTimeout,i={},o={VERSION:"2.1.8",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.isEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t0?"&":"?")+n),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n0?Math.ceil(e.loaded/e.size*100):100,b()}function b(){var e,t;d.reset();for(e=0;e0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",O),this.bind("BeforeUpload",C),this.bind("UploadFile",k),this.bind("UploadProgress",L),this.bind("StateChanged",A),this.bind("QueueChanged",b),this.bind("Error",_),this.bind("FileUploaded",M),this.bind("Destroy",D)}function x(e,n){var r=this,i=0,s=[],u={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_button_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("mousedown",function(){r.trigger("Browse")}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,r,i){var s=new t.Image;try{s.onload=function(){if(r.width>this.width&&r.height>this.height&&r.quality===n&&r.preserve_headers&&!r.crop)return this.destroy(),i(e);s.downsize(r.width,r.height,r.crop,r.preserve_headers)},s.onresize=function(){i(this.getAsBlob(e.type,r.quality)),this.destroy()},s.onerror=function(){i(e)},s.load(e)}catch(o){i(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t,a.send_file_name=!0;break;case"multipart":a[e]=t,t||(a.send_file_name=!0);break;case"unique_names":a[e]=t,t&&(a.send_file_name=!0);break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){if(e.settings.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function k(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g={},y;if(n.status!==o.UPLOADING||e.state===o.STOPPED)return;e.settings.send_file_name&&(g.name=n.target_name||n.name),s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s?s*Math.floor(n.loaded/s):0),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.settings.resize,function(e){c=e,n.size=e.size,p()}):p()}function L(e,t){y(t)}function A(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function O(){m&&m.abort()}function M(e){b(),r(function(){g.call(e)},1)}function _(e,t){t.code===o.INIT_ERROR?e.destroy():t.code===o.HTTP_ERROR&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function D(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)}),S.call(this);if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function c(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function h(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!l)return!1;e.ruid=l,e.connectRuntime(l)}h(new o.File(e))}else e instanceof t.Blob?(h(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){c(e,function(n){n||(f.push(e),a.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?h(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,h):i==="array"&&(n=null,t.each(e,h))}var s=this,u=[],a=[],l;l=w(),h(e),u.length&&t.inSeries(u,function(){a.length&&s.trigger("FilesAdded",a)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(o.each(r,function(e){if(e.status===o.UPLOADING)return i=!0,!1}),i&&this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),i&&this.start(),r},dispatchEvent:function(e){var t,n,r;e=e.toLowerCase(),t=this.hasEventListener(e);if(t){t.sort(function(e,t){return t.priority-e.priority}),n=[].slice.call(arguments),n.shift(),n.unshift(this);for(var i=0;iU1zK0aw_X$=hxGiT1+v}x0S96<3ux1VcBu(M-; ztC5}oGb2#H;!hSvE(Q(;9gtxlV;NY21x|Xd-pj#oX6v(H0groaGRIZBmUJ$|Yq z%$~;uB-qn00E(YLpglZ?QSF(M_<`vlnt#eI5||oc_AoP$V9$CHQ2ZnU?GZSFYR{Fz z56$TIurnmEG{Njq79hc%^Ae!=DFoUhaun4b5rz*ehtT{Z&XK^@470~sfdqTr%YfpC e0celJF;sg(1U|H)+oLX!z|jJ;C)ohg9%}&U_H8c! literal 0 HcmV?d00001 diff --git a/qiniu_fields/static/qiniu_fields/qiniu/qiniu.js b/qiniu_fields/static/qiniu_fields/qiniu/qiniu.js new file mode 100755 index 0000000..e1d8055 --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/qiniu/qiniu.js @@ -0,0 +1,1630 @@ +/*! + * qiniu-js-sdk v1.0.19 + * + * Copyright 2015 by Qiniu + * Released under GPL V2 License. + * + * GitHub: http://github.com/qiniu/js-sdk + * + * Date: 2017-3-15 +*/ + +/*global plupload ,mOxie*/ +/*global ActiveXObject */ +/*exported Qiniu */ +/*exported QiniuJsSDK */ + +;(function( global ){ + +/** + * Creates new cookie or removes cookie with negative expiration + * @param key The key or identifier for the store + * @param value Contents of the store + * @param exp Expiration - creation defaults to 30 days + */ +function createCookie(key, value, exp) { + var date = new Date(); + date.setTime(date.getTime() + (exp * 24 * 60 * 60 * 1000)); + var expires = "; expires=" + date.toGMTString(); + document.cookie = key + "=" + value + expires + "; path=/"; +} + +/** + * Returns contents of cookie + * @param key The key or identifier for the store + */ +function readCookie(key) { + var nameEQ = key + "="; + var ca = document.cookie.split(';'); + for (var i = 0, max = ca.length; i < max; i++) { + var c = ca[i]; + while (c.charAt(0) === ' ') { + c = c.substring(1, c.length); + } + if (c.indexOf(nameEQ) === 0) { + return c.substring(nameEQ.length, c.length); + } + } + return null; +} + +// if current browser is not support localStorage +// use cookie to make a polyfill +if ( !window.localStorage ) { + window.localStorage = { + setItem: function (key, value) { + createCookie(key, value, 30); + }, + getItem: function (key) { + return readCookie(key); + }, + removeItem: function (key) { + createCookie(key, '', -1); + } + }; +} + +function QiniuJsSDK() { + + var that = this; + + /** + * detect IE version + * if current browser is not IE + * it will return false + * else + * it will return version of current IE browser + * @return {Number|Boolean} IE version or false + */ + this.detectIEVersion = function() { + var v = 4, + div = document.createElement('div'), + all = div.getElementsByTagName('i'); + while ( + div.innerHTML = '', + all[0] + ) { + v++; + } + return v > 4 ? v : false; + }; + + var logger = { + MUTE: 0, + FATA: 1, + ERROR: 2, + WARN: 3, + INFO: 4, + DEBUG: 5, + TRACE: 6, + level: 0 + }; + + function log(type, args){ + var header = "[qiniu-js-sdk]["+type+"]"; + var msg = header; + for (var i = 0; i < args.length; i++) { + if (typeof args[i] === "string") { + msg += " " + args[i]; + } else { + msg += " " + that.stringifyJSON(args[i]); + } + } + if (that.detectIEVersion()) { + // http://stackoverflow.com/questions/5538972/console-log-apply-not-working-in-ie9 + //var log = Function.prototype.bind.call(console.log, console); + //log.apply(console, args); + console.log(msg); + }else{ + args.unshift(header); + console.log.apply(console, args); + } + if (document.getElementById('qiniu-js-sdk-log')) { + document.getElementById('qiniu-js-sdk-log').innerHTML += '

'+msg+'

'; + } + } + + function makeLogFunc(code){ + var func = code.toLowerCase(); + logger[func] = function(){ + // logger[func].history = logger[func].history || []; + // logger[func].history.push(arguments); + if(window.console && window.console.log && logger.level>=logger[code]){ + var args = Array.prototype.slice.call(arguments); + log(func,args); + } + }; + } + + for (var property in logger){ + if (logger.hasOwnProperty(property) && (typeof logger[property]) === "number" && !logger.hasOwnProperty(property.toLowerCase())) { + makeLogFunc(property); + } + } + + + var qiniuUploadUrl; + if (window.location.protocol === 'https:') { + qiniuUploadUrl = 'https://up.qbox.me'; + } else { + qiniuUploadUrl = 'http://upload.qiniu.com'; + } + + /** + * qiniu upload urls + * 'qiniuUploadUrls' is used to change target when current url is not avaliable + * @type {Array} + */ + var qiniuUploadUrls = [ + "http://upload.qiniu.com", + "http://up.qiniu.com" + ]; + + var qiniuUpHosts = { + "http": [ + "http://upload.qiniu.com", + "http://up.qiniu.com" + ], + "https": [ + "https://up.qbox.me" + ] + }; + + var changeUrlTimes = 0; + + /** + * reset upload url + * if current page protocal is https + * it will always return 'https://up.qbox.me' + * else + * it will set 'qiniuUploadUrl' value with 'qiniuUploadUrls' looply + */ + this.resetUploadUrl = function(){ + var hosts = window.location.protocol === 'https:' ? qiniuUpHosts.https : qiniuUpHosts.http; + var i = changeUrlTimes % hosts.length; + qiniuUploadUrl = hosts[i]; + changeUrlTimes++; + logger.debug('resetUploadUrl: '+qiniuUploadUrl); + }; + + // this.resetUploadUrl(); + + + /** + * is image + * @param {String} url of a file + * @return {Boolean} file is a image or not + */ + this.isImage = function(url) { + url = url.split(/[?#]/)[0]; + return (/\.(png|jpg|jpeg|gif|bmp)$/i).test(url); + }; + + /** + * get file extension + * @param {String} filename + * @return {String} file extension + * @example + * input: test.txt + * output: txt + */ + this.getFileExtension = function(filename) { + var tempArr = filename.split("."); + var ext; + if (tempArr.length === 1 || (tempArr[0] === "" && tempArr.length === 2)) { + ext = ""; + } else { + ext = tempArr.pop().toLowerCase(); //get the extension and make it lower-case + } + return ext; + }; + + /** + * encode string by utf8 + * @param {String} string to encode + * @return {String} encoded string + */ + this.utf8_encode = function(argString) { + // http://kevin.vanzonneveld.net + // + original by: Webtoolkit.info (http://www.webtoolkit.info/) + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + improved by: sowberry + // + tweaked by: Jack + // + bugfixed by: Onno Marsman + // + improved by: Yves Sucaet + // + bugfixed by: Onno Marsman + // + bugfixed by: Ulrich + // + bugfixed by: Rafal Kukawski + // + improved by: kirilloid + // + bugfixed by: kirilloid + // * example 1: this.utf8_encode('Kevin van Zonneveld'); + // * returns 1: 'Kevin van Zonneveld' + + if (argString === null || typeof argString === 'undefined') { + return ''; + } + + var string = (argString + ''); // .replace(/\r\n/g, '\n').replace(/\r/g, '\n'); + var utftext = '', + start, end, stringl = 0; + + start = end = 0; + stringl = string.length; + for (var n = 0; n < stringl; n++) { + var c1 = string.charCodeAt(n); + var enc = null; + + if (c1 < 128) { + end++; + } else if (c1 > 127 && c1 < 2048) { + enc = String.fromCharCode( + (c1 >> 6) | 192, (c1 & 63) | 128 + ); + } else if (c1 & 0xF800 ^ 0xD800 > 0) { + enc = String.fromCharCode( + (c1 >> 12) | 224, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128 + ); + } else { // surrogate pairs + if (c1 & 0xFC00 ^ 0xD800 > 0) { + throw new RangeError('Unmatched trail surrogate at ' + n); + } + var c2 = string.charCodeAt(++n); + if (c2 & 0xFC00 ^ 0xDC00 > 0) { + throw new RangeError('Unmatched lead surrogate at ' + (n - 1)); + } + c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000; + enc = String.fromCharCode( + (c1 >> 18) | 240, ((c1 >> 12) & 63) | 128, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128 + ); + } + if (enc !== null) { + if (end > start) { + utftext += string.slice(start, end); + } + utftext += enc; + start = end = n + 1; + } + } + + if (end > start) { + utftext += string.slice(start, stringl); + } + + return utftext; + }; + + this.base64_decode = function (data) { + // http://kevin.vanzonneveld.net + // + original by: Tyler Akins (http://rumkin.com) + // + improved by: Thunder.m + // + input by: Aman Gupta + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + bugfixed by: Onno Marsman + // + bugfixed by: Pellentesque Malesuada + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + input by: Brett Zamir (http://brett-zamir.me) + // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA=='); + // * returns 1: 'Kevin van Zonneveld' + // mozilla has this native + // - but breaks in 2.0.0.12! + //if (typeof this.window['atob'] == 'function') { + // return atob(data); + //} + var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, + ac = 0, + dec = "", + tmp_arr = []; + + if (!data) { + return data; + } + + data += ''; + + do { // unpack four hexets into three octets using index points in b64 + h1 = b64.indexOf(data.charAt(i++)); + h2 = b64.indexOf(data.charAt(i++)); + h3 = b64.indexOf(data.charAt(i++)); + h4 = b64.indexOf(data.charAt(i++)); + + bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; + + o1 = bits >> 16 & 0xff; + o2 = bits >> 8 & 0xff; + o3 = bits & 0xff; + + if (h3 === 64) { + tmp_arr[ac++] = String.fromCharCode(o1); + } else if (h4 === 64) { + tmp_arr[ac++] = String.fromCharCode(o1, o2); + } else { + tmp_arr[ac++] = String.fromCharCode(o1, o2, o3); + } + } while (i < data.length); + + dec = tmp_arr.join(''); + + return dec; + }; + + /** + * encode data by base64 + * @param {String} data to encode + * @return {String} encoded data + */ + this.base64_encode = function(data) { + // http://kevin.vanzonneveld.net + // + original by: Tyler Akins (http://rumkin.com) + // + improved by: Bayron Guevara + // + improved by: Thunder.m + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + bugfixed by: Pellentesque Malesuada + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // - depends on: this.utf8_encode + // * example 1: this.base64_encode('Kevin van Zonneveld'); + // * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' + // mozilla has this native + // - but breaks in 2.0.0.12! + //if (typeof this.window['atob'] == 'function') { + // return atob(data); + //} + var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, + ac = 0, + enc = '', + tmp_arr = []; + + if (!data) { + return data; + } + + data = this.utf8_encode(data + ''); + + do { // pack three octets into four hexets + o1 = data.charCodeAt(i++); + o2 = data.charCodeAt(i++); + o3 = data.charCodeAt(i++); + + bits = o1 << 16 | o2 << 8 | o3; + + h1 = bits >> 18 & 0x3f; + h2 = bits >> 12 & 0x3f; + h3 = bits >> 6 & 0x3f; + h4 = bits & 0x3f; + + // use hexets to index into b64, and append result to encoded string + tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); + } while (i < data.length); + + enc = tmp_arr.join(''); + + switch (data.length % 3) { + case 1: + enc = enc.slice(0, -2) + '=='; + break; + case 2: + enc = enc.slice(0, -1) + '='; + break; + } + + return enc; + }; + + /** + * encode string in url by base64 + * @param {String} string in url + * @return {String} encoded string + */ + this.URLSafeBase64Encode = function(v) { + v = this.base64_encode(v); + return v.replace(/\//g, '_').replace(/\+/g, '-'); + }; + + this.URLSafeBase64Decode = function(v) { + v = v.replace(/_/g, '/').replace(/-/g, '+'); + return this.base64_decode(v); + }; + + // TODO: use mOxie + /** + * craete object used to AJAX + * @return {Object} + */ + this.createAjax = function(argument) { + var xmlhttp = {}; + if (window.XMLHttpRequest) { + xmlhttp = new XMLHttpRequest(); + } else { + xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); + } + return xmlhttp; + }; + + // TODO: enhance IE compatibility + /** + * parse json string to javascript object + * @param {String} json string + * @return {Object} object + */ + this.parseJSON = function(data) { + // Attempt to parse using the native JSON parser first + if (window.JSON && window.JSON.parse) { + return window.JSON.parse(data); + } + + //var rx_one = /^[\],:{}\s]*$/, + // rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + // rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + // rx_four = /(?:^|:|,)(?:\s*\[)+/g, + var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + + //var json; + + var text = String(data); + rx_dangerous.lastIndex = 0; + if(rx_dangerous.test(text)){ + text = text.replace(rx_dangerous, function(a){ + return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + + // todo 使用一下判断,增加安全性 + //if ( + // rx_one.test( + // text + // .replace(rx_two, '@') + // .replace(rx_three, ']') + // .replace(rx_four, '') + // ) + //) { + // return eval('(' + text + ')'); + //} + + return eval('('+text+')'); + }; + + /** + * parse javascript object to json string + * @param {Object} object + * @return {String} json string + */ + this.stringifyJSON = function(obj) { + // Attempt to parse using the native JSON parser first + if (window.JSON && window.JSON.stringify) { + return window.JSON.stringify(obj); + } + switch (typeof (obj)) { + case 'string': + return '"' + obj.replace(/(["\\])/g, '\\$1') + '"'; + case 'array': + return '[' + obj.map(that.stringifyJSON).join(',') + ']'; + case 'object': + if (obj instanceof Array) { + var strArr = []; + var len = obj.length; + for (var i = 0; i < len; i++) { + strArr.push(that.stringifyJSON(obj[i])); + } + return '[' + strArr.join(',') + ']'; + } else if (obj === null) { + return 'null'; + } else { + var string = []; + for (var property in obj) { + if (obj.hasOwnProperty(property)) { + string.push(that.stringifyJSON(property) + ':' + that.stringifyJSON(obj[property])); + } + } + return '{' + string.join(',') + '}'; + } + break; + case 'number': + return obj; + case false: + return obj; + case 'boolean': + return obj; + } + }; + + /** + * trim space beside text + * @param {String} untrimed string + * @return {String} trimed string + */ + this.trim = function(text) { + return text === null ? "" : text.replace(/^\s+|\s+$/g, ''); + }; + + /** + * create a uploader by QiniuJsSDK + * @param {object} options to create a new uploader + * @return {object} uploader + */ + this.uploader = function(op) { + + /********** inner function define start **********/ + + // according the different condition to reset chunk size + // and the upload strategy according with the chunk size + // when chunk size is zero will cause to direct upload + // see the statement binded on 'BeforeUpload' event + var reset_chunk_size = function() { + var ie = that.detectIEVersion(); + var BLOCK_BITS, MAX_CHUNK_SIZE, chunk_size; + // case Safari 5、Windows 7、iOS 7 set isSpecialSafari to true + var isSpecialSafari = (mOxie.Env.browser === "Safari" && mOxie.Env.version <= 5 && mOxie.Env.os === "Windows" && mOxie.Env.osVersion === "7") || (mOxie.Env.browser === "Safari" && mOxie.Env.os === "iOS" && mOxie.Env.osVersion === "7"); + // case IE 9-,chunk_size is not empty and flash is included in runtimes + // set op.chunk_size to zero + //if (ie && ie < 9 && op.chunk_size && op.runtimes.indexOf('flash') >= 0) { + if (ie && ie < 9 && op.chunk_size && op.runtimes.indexOf('flash') >= 0) { + // link: http://www.plupload.com/docs/Frequently-Asked-Questions#when-to-use-chunking-and-when-not + // when plupload chunk_size setting is't null ,it cause bug in ie8/9 which runs flash runtimes (not support html5) . + op.chunk_size = 0; + } else if (isSpecialSafari) { + // win7 safari / iOS7 safari have bug when in chunk upload mode + // reset chunk_size to 0 + // disable chunk in special version safari + op.chunk_size = 0; + } else { + BLOCK_BITS = 20; + MAX_CHUNK_SIZE = 4 << BLOCK_BITS; //4M + + chunk_size = plupload.parseSize(op.chunk_size); + if (chunk_size > MAX_CHUNK_SIZE) { + op.chunk_size = MAX_CHUNK_SIZE; + } + // qiniu service max_chunk_size is 4m + // reset chunk_size to max_chunk_size(4m) when chunk_size > 4m + } + // if op.chunk_size set 0 will be cause to direct upload + }; + + var getHosts = function(hosts) { + var result = []; + for (var i = 0; i < hosts.length; i++) { + var host = hosts[i]; + if (host.indexOf('-H') === 0) { + result.push(host.split(' ')[2]); + } else { + result.push(host); + } + } + return result; + }; + + var getPutPolicy = function (uptoken) { + var segments = uptoken.split(":"); + var ak = segments[0]; + var putPolicy = that.parseJSON(that.URLSafeBase64Decode(segments[2])); + putPolicy.ak = ak; + if (putPolicy.scope.indexOf(":") >= 0) { + putPolicy.bucket = putPolicy.scope.split(":")[0]; + putPolicy.key = putPolicy.scope.split(":")[1]; + } else { + putPolicy.bucket = putPolicy.scope; + } + return putPolicy; + }; + + var getUpHosts = function(uptoken) { + var putPolicy = getPutPolicy(uptoken); + // var uphosts_url = "//uc.qbox.me/v1/query?ak="+ak+"&bucket="+putPolicy.scope; + // IE 9- is not support protocal relative url + var uphosts_url = window.location.protocol + "//uc.qbox.me/v1/query?ak=" + putPolicy.ak + "&bucket=" + putPolicy.bucket; + logger.debug("putPolicy: ", putPolicy); + logger.debug("get uphosts from: ", uphosts_url); + var ie = that.detectIEVersion(); + var ajax; + if (ie && ie <= 9) { + ajax = new mOxie.XMLHttpRequest(); + mOxie.Env.swf_url = op.flash_swf_url; + }else{ + ajax = that.createAjax(); + } + ajax.open('GET', uphosts_url, false); + var onreadystatechange = function(){ + logger.debug("ajax.readyState: ", ajax.readyState); + if (ajax.readyState === 4) { + logger.debug("ajax.status: ", ajax.status); + if (ajax.status < 400) { + var res = that.parseJSON(ajax.responseText); + qiniuUpHosts.http = getHosts(res.http.up); + qiniuUpHosts.https = getHosts(res.https.up); + logger.debug("get new uphosts: ", qiniuUpHosts); + that.resetUploadUrl(); + } else { + logger.error("get uphosts error: ", ajax.responseText); + } + } + }; + if (ie && ie <= 9) { + ajax.bind('readystatechange', onreadystatechange); + }else{ + ajax.onreadystatechange = onreadystatechange; + } + ajax.send(); + // ajax.send(); + // if (ajax.status < 400) { + // var res = that.parseJSON(ajax.responseText); + // qiniuUpHosts.http = getHosts(res.http.up); + // qiniuUpHosts.https = getHosts(res.https.up); + // logger.debug("get new uphosts: ", qiniuUpHosts); + // that.resetUploadUrl(); + // } else { + // logger.error("get uphosts error: ", ajax.responseText); + // } + return; + }; + + var getUptoken = function(file) { + if (!that.token || (op.uptoken_url && that.tokenInfo.isExpired())) { + return getNewUpToken(file); + } else { + return that.token; + } + }; + + // getNewUptoken maybe called at Init Event or BeforeUpload Event + // case Init Event, the file param of getUptken will be set a null value + // if op.uptoken has value, set uptoken with op.uptoken + // else if op.uptoken_url has value, set uptoken from op.uptoken_url + // else if op.uptoken_func has value, set uptoken by result of op.uptoken_func + var getNewUpToken = function(file) { + if (op.uptoken) { + that.token = op.uptoken; + } else if (op.uptoken_url) { + logger.debug("get uptoken from: ", that.uptoken_url); + // TODO: use mOxie + var ajax = that.createAjax(); + ajax.open('GET', that.uptoken_url, false); + ajax.setRequestHeader("If-Modified-Since", "0"); + // ajax.onreadystatechange = function() { + // if (ajax.readyState === 4 && ajax.status === 200) { + // var res = that.parseJSON(ajax.responseText); + // that.token = res.uptoken; + // } + // }; + ajax.send(); + if (ajax.status === 200) { + var res = that.parseJSON(ajax.responseText); + that.token = res.uptoken; + var segments = that.token.split(":"); + var putPolicy = that.parseJSON(that.URLSafeBase64Decode(segments[2])); + if (!that.tokenMap) { + that.tokenMap = {}; + } + var getTimestamp = function(time) { + return Math.ceil(time.getTime()/1000); + }; + var serverTime = getTimestamp(new Date(ajax.getResponseHeader("date"))); + var clientTime = getTimestamp(new Date()); + that.tokenInfo = { + serverDelay: clientTime - serverTime, + deadline: putPolicy.deadline, + isExpired: function() { + var leftTime = this.deadline - getTimestamp(new Date()) + this.serverDelay; + return leftTime < 600; + } + }; + logger.debug("get new uptoken: ", that.token); + logger.debug("get token info: ", that.tokenInfo); + } else { + logger.error("get uptoken error: ", ajax.responseText); + } + } else if (op.uptoken_func) { + logger.debug("get uptoken from uptoken_func"); + that.token = op.uptoken_func(file); + logger.debug("get new uptoken: ", that.token); + } else { + logger.error("one of [uptoken, uptoken_url, uptoken_func] settings in options is required!"); + } + if (that.token) { + getUpHosts(that.token); + } + return that.token; + }; + + // get file key according with the user passed options + var getFileKey = function(up, file, func) { + // WARNING + // When you set the key in putPolicy by "scope": "bucket:key" + // You should understand the risk of override a file in the bucket + // So the code below that automatically get key from uptoken has been commented + // var putPolicy = getPutPolicy(that.token) + // if (putPolicy.key) { + // logger.debug("key is defined in putPolicy.scope: ", putPolicy.key) + // return putPolicy.key + // } + var key = '', + unique_names = false; + if (!op.save_key) { + unique_names = up.getOption && up.getOption('unique_names'); + unique_names = unique_names || (up.settings && up.settings.unique_names); + if (unique_names) { + var ext = that.getFileExtension(file.name); + key = ext ? file.id + '.' + ext : file.id; + } else if (typeof func === 'function') { + key = func(up, file); + } else { + key = file.name; + } + } + return key; + }; + + /********** inner function define end **********/ + + if (op.log_level) { + logger.level = op.log_level; + } + + if (!op.domain) { + throw 'domain setting in options is required!'; + } + + if (!op.browse_button) { + throw 'browse_button setting in options is required!'; + } + + if (!op.uptoken && !op.uptoken_url && !op.uptoken_func) { + throw 'one of [uptoken, uptoken_url, uptoken_func] settings in options is required!'; + } + + logger.debug("init uploader start"); + + logger.debug("environment: ", mOxie.Env); + + logger.debug("userAgent: ", navigator.userAgent); + + var option = {}; + + // hold the handler from user passed options + var _Error_Handler = op.init && op.init.Error; + var _FileUploaded_Handler = op.init && op.init.FileUploaded; + + // replace the handler for intercept + op.init.Error = function() {}; + op.init.FileUploaded = function() {}; + + that.uptoken_url = op.uptoken_url; + that.token = ''; + that.key_handler = typeof op.init.Key === 'function' ? op.init.Key : ''; + this.domain = op.domain; + // TODO: ctx is global in scope of a uploader instance + // this maybe cause error + var ctx = ''; + var speedCalInfo = { + isResumeUpload: false, + resumeFilesize: 0, + startTime: '', + currentTime: '' + }; + + reset_chunk_size(); + logger.debug("invoke reset_chunk_size()"); + logger.debug("op.chunk_size: ", op.chunk_size); + + var defaultSetting = { + url: qiniuUploadUrl, + multipart_params: { + token: '' + } + }; + var ie = that.detectIEVersion(); + // case IE 9- + // add accept in multipart params + if (ie && ie <= 9) { + defaultSetting.multipart_params.accept = 'text/plain; charset=utf-8'; + logger.debug("add accept text/plain in multipart params"); + } + + // compose options with user passed options and default setting + plupload.extend(option, op, defaultSetting); + + logger.debug("option: ", option); + + // create a new uploader with composed options + var uploader = new plupload.Uploader(option); + + logger.debug("new plupload.Uploader(option)"); + + // bind getNewUpToken to 'Init' event + uploader.bind('Init', function(up, params) { + logger.debug("Init event activated"); + // if op.get_new_uptoken is not true + // invoke getNewUptoken when uploader init + // else + // getNewUptoken everytime before a new file upload + if(!op.get_new_uptoken){ + getNewUpToken(null); + } + //getNewUpToken(null); + }); + + logger.debug("bind Init event"); + + // bind 'FilesAdded' event + // when file be added and auto_start has set value + // uploader will auto start upload the file + uploader.bind('FilesAdded', function(up, files) { + logger.debug("FilesAdded event activated"); + var auto_start = up.getOption && up.getOption('auto_start'); + auto_start = auto_start || (up.settings && up.settings.auto_start); + logger.debug("auto_start: ", auto_start); + logger.debug("files: ", files); + + // detect is iOS + var is_ios = function (){ + if(mOxie.Env.OS.toLowerCase()==="ios") { + return true; + } else { + return false; + } + }; + + // if current env os is iOS change file name to [time].[ext] + if (is_ios()) { + for (var i = 0; i < files.length; i++) { + var file = files[i]; + var ext = that.getFileExtension(file.name); + file.name = file.id + "." + ext; + } + } + + if (auto_start) { + setTimeout(function(){ + up.start(); + logger.debug("invoke up.start()"); + }, 0); + // up.start(); + // plupload.each(files, function(i, file) { + // up.start(); + // logger.debug("invoke up.start()") + // logger.debug("file: ", file); + // }); + } + up.refresh(); // Reposition Flash/Silverlight + }); + + logger.debug("bind FilesAdded event"); + + // bind 'BeforeUpload' event + // intercept the process of upload + // - prepare uptoken + // - according the chunk size to make differnt upload strategy + // - resume upload with the last breakpoint of file + uploader.bind('BeforeUpload', function(up, file) { + logger.debug("BeforeUpload event activated"); + // add a key named speed for file object + file.speed = file.speed || 0; + ctx = ''; + + if(op.get_new_uptoken){ + getNewUpToken(file); + } + + var directUpload = function(up, file, func) { + speedCalInfo.startTime = new Date().getTime(); + var multipart_params_obj; + if (op.save_key) { + multipart_params_obj = { + 'token': that.token + }; + } else { + multipart_params_obj = { + 'key': getFileKey(up, file, func), + 'token': that.token + }; + } + var ie = that.detectIEVersion(); + // case IE 9- + // add accept in multipart params + if (ie && ie <= 9) { + multipart_params_obj.accept = 'text/plain; charset=utf-8'; + logger.debug("add accept text/plain in multipart params"); + } + + logger.debug("directUpload multipart_params_obj: ", multipart_params_obj); + + var x_vars = op.x_vars; + if (x_vars !== undefined && typeof x_vars === 'object') { + for (var x_key in x_vars) { + if (x_vars.hasOwnProperty(x_key)) { + if (typeof x_vars[x_key] === 'function') { + multipart_params_obj['x:' + x_key] = x_vars[x_key](up, file); + } else if (typeof x_vars[x_key] !== 'object') { + multipart_params_obj['x:' + x_key] = x_vars[x_key]; + } + } + } + } + + up.setOption({ + 'url': qiniuUploadUrl, + 'multipart': true, + 'chunk_size': is_android_weixin_or_qq() ? op.max_file_size : undefined, + 'multipart_params': multipart_params_obj + }); + }; + + // detect is weixin or qq inner browser + var is_android_weixin_or_qq = function (){ + var ua = navigator.userAgent.toLowerCase(); + if((ua.match(/MicroMessenger/i) || mOxie.Env.browser === "QQBrowser" || ua.match(/V1_AND_SQ/i)) && mOxie.Env.OS.toLowerCase()==="android") { + return true; + } else { + return false; + } + }; + + var chunk_size = up.getOption && up.getOption('chunk_size'); + chunk_size = chunk_size || (up.settings && up.settings.chunk_size); + + logger.debug("uploader.runtime: ",uploader.runtime); + logger.debug("chunk_size: ",chunk_size); + + // TODO: flash support chunk upload + if ((uploader.runtime === 'html5' || uploader.runtime === 'flash') && chunk_size) { + if (file.size < chunk_size || is_android_weixin_or_qq()) { + logger.debug("directUpload because file.size < chunk_size || is_android_weixin_or_qq()"); + // direct upload if file size is less then the chunk size + directUpload(up, file, that.key_handler); + } else { + // TODO: need a polifill to make it work in IE 9- + // ISSUE: if file.name is existed in localStorage + // but not the same file maybe cause error + var localFileInfo = localStorage.getItem(file.name); + var blockSize = chunk_size; + if (localFileInfo) { + // TODO: although only the html5 runtime will enter this statement + // but need uniform way to make convertion between string and json + localFileInfo = that.parseJSON(localFileInfo); + var now = (new Date()).getTime(); + var before = localFileInfo.time || 0; + var aDay = 24 * 60 * 60 * 1000; // milliseconds of one day + // if the last upload time is within one day + // will upload continuously follow the last breakpoint + // else + // will reupload entire file + if (now - before < aDay) { + + if (localFileInfo.percent !== 100) { + if (file.size === localFileInfo.total) { + // TODO: if file.name and file.size is the same + // but not the same file will cause error + file.percent = localFileInfo.percent; + file.loaded = localFileInfo.offset; + ctx = localFileInfo.ctx; + + // set speed info + speedCalInfo.isResumeUpload = true; + speedCalInfo.resumeFilesize = localFileInfo.offset; + + // set block size + if (localFileInfo.offset + blockSize > file.size) { + blockSize = file.size - localFileInfo.offset; + } + } else { + // remove file info when file.size is conflict with file info + localStorage.removeItem(file.name); + } + + } else { + // remove file info when upload percent is 100% + // avoid 499 bug + localStorage.removeItem(file.name); + } + } else { + // remove file info when last upload time is over one day + localStorage.removeItem(file.name); + } + } + speedCalInfo.startTime = new Date().getTime(); + var multipart_params_obj = {}; + var ie = that.detectIEVersion(); + // case IE 9- + // add accept in multipart params + if (ie && ie <= 9) { + multipart_params_obj.accept = 'text/plain; charset=utf-8'; + logger.debug("add accept text/plain in multipart params"); + } + // TODO: to support bput + // http://developer.qiniu.com/docs/v6/api/reference/up/bput.html + up.setOption({ + 'url': qiniuUploadUrl + '/mkblk/' + blockSize, + 'multipart': false, + 'chunk_size': chunk_size, + 'required_features': "chunks", + 'headers': { + 'Authorization': 'UpToken ' + getUptoken(file) + }, + 'multipart_params': multipart_params_obj + }); + } + } else { + logger.debug("directUpload because uploader.runtime !== 'html5' || uploader.runtime !== 'flash' || !chunk_size"); + // direct upload if runtime is not html5 + directUpload(up, file, that.key_handler); + } + }); + + logger.debug("bind BeforeUpload event"); + + // bind 'UploadProgress' event + // calculate upload speed + uploader.bind('UploadProgress', function(up, file) { + logger.trace("UploadProgress event activated"); + speedCalInfo.currentTime = new Date().getTime(); + var timeUsed = speedCalInfo.currentTime - speedCalInfo.startTime; // ms + var fileUploaded = file.loaded || 0; + if (speedCalInfo.isResumeUpload) { + fileUploaded = file.loaded - speedCalInfo.resumeFilesize; + } + file.speed = (fileUploaded / timeUsed * 1000).toFixed(0) || 0; // unit: byte/s + }); + + logger.debug("bind UploadProgress event"); + + // bind 'ChunkUploaded' event + // store the chunk upload info and set next chunk upload url + uploader.bind('ChunkUploaded', function(up, file, info) { + logger.debug("ChunkUploaded event activated"); + logger.debug("file: ", file); + logger.debug("info: ", info); + var res = that.parseJSON(info.response); + logger.debug("res: ", res); + // ctx should look like '[chunk01_ctx],[chunk02_ctx],[chunk03_ctx],...' + ctx = ctx ? ctx + ',' + res.ctx : res.ctx; + var leftSize = info.total - info.offset; + var chunk_size = up.getOption && up.getOption('chunk_size'); + chunk_size = chunk_size || (up.settings && up.settings.chunk_size); + if (leftSize < chunk_size) { + up.setOption({ + 'url': qiniuUploadUrl + '/mkblk/' + leftSize + }); + logger.debug("up.setOption url: ", qiniuUploadUrl + '/mkblk/' + leftSize); + } + up.setOption({ + 'headers': { + 'Authorization': 'UpToken ' + getUptoken(file) + } + }); + localStorage.setItem(file.name, that.stringifyJSON({ + ctx: ctx, + percent: file.percent, + total: info.total, + offset: info.offset, + time: (new Date()).getTime() + })); + }); + + logger.debug("bind ChunkUploaded event"); + + var retries = qiniuUploadUrls.length; + + // if error is unkown switch upload url and retry + var unknow_error_retry = function(file){ + if (retries-- > 0) { + setTimeout(function(){ + that.resetUploadUrl(); + file.status = plupload.QUEUED; + uploader.stop(); + uploader.start(); + }, 0); + return true; + }else{ + retries = qiniuUploadUrls.length; + return false; + } + }; + + // bind 'Error' event + // check the err.code and return the errTip + uploader.bind('Error', (function(_Error_Handler) { + return function(up, err) { + logger.error("Error event activated"); + logger.error("err: ", err); + var errTip = ''; + var file = err.file; + if (file) { + switch (err.code) { + case plupload.FAILED: + errTip = '上传失败。请稍后再试。'; + break; + case plupload.FILE_SIZE_ERROR: + var max_file_size = up.getOption && up.getOption('max_file_size'); + max_file_size = max_file_size || (up.settings && up.settings.max_file_size); + errTip = '浏览器最大可上传' + max_file_size + '。更大文件请使用命令行工具。'; + break; + case plupload.FILE_EXTENSION_ERROR: + errTip = '文件验证失败。请稍后重试。'; + break; + case plupload.HTTP_ERROR: + if (err.response === '') { + // Fix parseJSON error ,when http error is like net::ERR_ADDRESS_UNREACHABLE + errTip = err.message || '未知网络错误。'; + if (!unknow_error_retry(file)) { + return; + } + break; + } + var errorObj = that.parseJSON(err.response); + var errorText = errorObj.error; + switch (err.status) { + case 400: + errTip = "请求报文格式错误。"; + break; + case 401: + errTip = "客户端认证授权失败。请重试或提交反馈。"; + break; + case 405: + errTip = "客户端请求错误。请重试或提交反馈。"; + break; + case 579: + errTip = "资源上传成功,但回调失败。"; + break; + case 599: + errTip = "网络连接异常。请重试或提交反馈。"; + if (!unknow_error_retry(file)) { + return; + } + break; + case 614: + errTip = "文件已存在。"; + try { + errorObj = that.parseJSON(errorObj.error); + errorText = errorObj.error || 'file exists'; + } catch (e) { + errorText = errorObj.error || 'file exists'; + } + break; + case 631: + errTip = "指定空间不存在。"; + break; + case 701: + errTip = "上传数据块校验出错。请重试或提交反馈。"; + break; + default: + errTip = "未知错误。"; + if (!unknow_error_retry(file)) { + return; + } + break; + } + errTip = errTip + '(' + err.status + ':' + errorText + ')'; + break; + case plupload.SECURITY_ERROR: + errTip = '安全配置错误。请联系网站管理员。'; + break; + case plupload.GENERIC_ERROR: + errTip = '上传失败。请稍后再试。'; + break; + case plupload.IO_ERROR: + errTip = '上传失败。请稍后再试。'; + break; + case plupload.INIT_ERROR: + errTip = '网站配置错误。请联系网站管理员。'; + uploader.destroy(); + break; + default: + errTip = err.message + err.details; + if (!unknow_error_retry(file)) { + return; + } + break; + } + if (_Error_Handler) { + _Error_Handler(up, err, errTip); + } + } + up.refresh(); // Reposition Flash/Silverlight + }; + })(_Error_Handler)); + + logger.debug("bind Error event"); + + // bind 'FileUploaded' event + // intercept the complete of upload + // - get downtoken from downtoken_url if bucket is private + // - invoke mkfile api to compose chunks if upload strategy is chunk upload + uploader.bind('FileUploaded', (function(_FileUploaded_Handler) { + return function(up, file, info) { + logger.debug("FileUploaded event activated"); + logger.debug("file: ", file); + logger.debug("info: ", info); + var last_step = function(up, file, info) { + if (op.downtoken_url) { + // if op.dowontoken_url is not empty + // need get downtoken before invoke the _FileUploaded_Handler + var ajax_downtoken = that.createAjax(); + ajax_downtoken.open('POST', op.downtoken_url, true); + ajax_downtoken.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + ajax_downtoken.onreadystatechange = function() { + if (ajax_downtoken.readyState === 4) { + if (ajax_downtoken.status === 200) { + var res_downtoken; + try { + res_downtoken = that.parseJSON(ajax_downtoken.responseText); + } catch (e) { + throw ('invalid json format'); + } + var info_extended = {}; + plupload.extend(info_extended, that.parseJSON(info), res_downtoken); + if (_FileUploaded_Handler) { + _FileUploaded_Handler(up, file, that.stringifyJSON(info_extended)); + } + } else { + uploader.trigger('Error', { + status: ajax_downtoken.status, + response: ajax_downtoken.responseText, + file: file, + code: plupload.HTTP_ERROR + }); + } + } + }; + ajax_downtoken.send('key=' + that.parseJSON(info).key + '&domain=' + op.domain); + } else if (_FileUploaded_Handler) { + _FileUploaded_Handler(up, file, info); + } + }; + + var res = that.parseJSON(info.response); + ctx = ctx ? ctx : res.ctx; + // if ctx is not empty + // that means the upload strategy is chunk upload + // befroe the invoke the last_step + // we need request the mkfile to compose all uploaded chunks + // else + // invalke the last_step + logger.debug("ctx: ", ctx); + if (ctx) { + var key = ''; + logger.debug("save_key: ", op.save_key); + if (!op.save_key) { + key = getFileKey(up, file, that.key_handler); + key = key ? '/key/' + that.URLSafeBase64Encode(key) : ''; + } + + var fname = '/fname/' + that.URLSafeBase64Encode(file.name); + + logger.debug("op.x_vars: ", op.x_vars); + var x_vars = op.x_vars, + x_val = '', + x_vars_url = ''; + if (x_vars !== undefined && typeof x_vars === 'object') { + for (var x_key in x_vars) { + if (x_vars.hasOwnProperty(x_key)) { + if (typeof x_vars[x_key] === 'function') { + x_val = that.URLSafeBase64Encode(x_vars[x_key](up, file)); + } else if (typeof x_vars[x_key] !== 'object') { + x_val = that.URLSafeBase64Encode(x_vars[x_key]); + } + x_vars_url += '/x:' + x_key + '/' + x_val; + } + } + } + + var url = qiniuUploadUrl + '/mkfile/' + file.size + key + fname + x_vars_url; + + var ie = that.detectIEVersion(); + var ajax; + if (ie && ie <= 9) { + ajax = new mOxie.XMLHttpRequest(); + mOxie.Env.swf_url = op.flash_swf_url; + }else{ + ajax = that.createAjax(); + } + ajax.open('POST', url, true); + ajax.setRequestHeader('Content-Type', 'text/plain;charset=UTF-8'); + ajax.setRequestHeader('Authorization', 'UpToken ' + that.token); + var onreadystatechange = function(){ + logger.debug("ajax.readyState: ", ajax.readyState); + if (ajax.readyState === 4) { + localStorage.removeItem(file.name); + var info; + if (ajax.status === 200) { + info = ajax.responseText; + logger.debug("mkfile is success: ", info); + last_step(up, file, info); + } else { + info = { + status: ajax.status, + response: ajax.responseText, + file: file, + code: -200, + responseHeaders: ajax.getAllResponseHeaders() + }; + logger.debug("mkfile is error: ", info); + uploader.trigger('Error', info); + } + } + }; + if (ie && ie <= 9) { + ajax.bind('readystatechange', onreadystatechange); + }else{ + ajax.onreadystatechange = onreadystatechange; + } + ajax.send(ctx); + logger.debug("mkfile: ", url); + } else { + last_step(up, file, info.response); + } + + }; + })(_FileUploaded_Handler)); + + logger.debug("bind FileUploaded event"); + + // init uploader + uploader.init(); + + logger.debug("invoke uploader.init()"); + + logger.debug("init uploader end"); + + return uploader; + }; + + /** + * get url by key + * @param {String} key of file + * @return {String} url of file + */ + this.getUrl = function(key) { + if (!key) { + return false; + } + key = encodeURI(key); + var domain = this.domain; + if (domain.slice(domain.length - 1) !== '/') { + domain = domain + '/'; + } + return domain + key; + }; + + /** + * invoke the imageView2 api of Qiniu + * @param {Object} api params + * @param {String} key of file + * @return {String} url of processed image + */ + this.imageView2 = function(op, key) { + + if (!/^\d$/.test(op.mode)) { + return false; + } + + var mode = op.mode, + w = op.w || '', + h = op.h || '', + q = op.q || '', + format = op.format || ''; + + if (!w && !h) { + return false; + } + + var imageUrl = 'imageView2/' + mode; + imageUrl += w ? '/w/' + w : ''; + imageUrl += h ? '/h/' + h : ''; + imageUrl += q ? '/q/' + q : ''; + imageUrl += format ? '/format/' + format : ''; + if (key) { + imageUrl = this.getUrl(key) + '?' + imageUrl; + } + return imageUrl; + }; + + /** + * invoke the imageMogr2 api of Qiniu + * @param {Object} api params + * @param {String} key of file + * @return {String} url of processed image + */ + this.imageMogr2 = function(op, key) { + var auto_orient = op['auto-orient'] || '', + thumbnail = op.thumbnail || '', + strip = op.strip || '', + gravity = op.gravity || '', + crop = op.crop || '', + quality = op.quality || '', + rotate = op.rotate || '', + format = op.format || '', + blur = op.blur || ''; + //Todo check option + + var imageUrl = 'imageMogr2'; + + imageUrl += auto_orient ? '/auto-orient' : ''; + imageUrl += thumbnail ? '/thumbnail/' + thumbnail : ''; + imageUrl += strip ? '/strip' : ''; + imageUrl += gravity ? '/gravity/' + gravity : ''; + imageUrl += quality ? '/quality/' + quality : ''; + imageUrl += crop ? '/crop/' + crop : ''; + imageUrl += rotate ? '/rotate/' + rotate : ''; + imageUrl += format ? '/format/' + format : ''; + imageUrl += blur ? '/blur/' + blur : ''; + + if (key) { + imageUrl = this.getUrl(key) + '?' + imageUrl; + } + return imageUrl; + }; + + /** + * invoke the watermark api of Qiniu + * @param {Object} api params + * @param {String} key of file + * @return {String} url of processed image + */ + this.watermark = function(op, key) { + var mode = op.mode; + if (!mode) { + return false; + } + + var imageUrl = 'watermark/' + mode; + + if (mode === 1) { + var image = op.image || ''; + if (!image) { + return false; + } + imageUrl += image ? '/image/' + this.URLSafeBase64Encode(image) : ''; + } else if (mode === 2) { + var text = op.text ? op.text : '', + font = op.font ? op.font : '', + fontsize = op.fontsize ? op.fontsize : '', + fill = op.fill ? op.fill : ''; + if (!text) { + return false; + } + imageUrl += text ? '/text/' + this.URLSafeBase64Encode(text) : ''; + imageUrl += font ? '/font/' + this.URLSafeBase64Encode(font) : ''; + imageUrl += fontsize ? '/fontsize/' + fontsize : ''; + imageUrl += fill ? '/fill/' + this.URLSafeBase64Encode(fill) : ''; + } else { + // Todo mode3 + return false; + } + + var dissolve = op.dissolve || '', + gravity = op.gravity || '', + dx = op.dx || '', + dy = op.dy || ''; + + imageUrl += dissolve ? '/dissolve/' + dissolve : ''; + imageUrl += gravity ? '/gravity/' + gravity : ''; + imageUrl += dx ? '/dx/' + dx : ''; + imageUrl += dy ? '/dy/' + dy : ''; + + if (key) { + imageUrl = this.getUrl(key) + '?' + imageUrl; + } + return imageUrl; + }; + + /** + * invoke the imageInfo api of Qiniu + * @param {String} key of file + * @return {Object} image info + */ + this.imageInfo = function(key) { + if (!key) { + return false; + } + var url = this.getUrl(key) + '?imageInfo'; + var xhr = this.createAjax(); + var info; + var that = this; + xhr.open('GET', url, false); + xhr.onreadystatechange = function() { + if (xhr.readyState === 4 && xhr.status === 200) { + info = that.parseJSON(xhr.responseText); + } + }; + xhr.send(); + return info; + }; + + /** + * invoke the exif api of Qiniu + * @param {String} key of file + * @return {Object} image exif + */ + this.exif = function(key) { + if (!key) { + return false; + } + var url = this.getUrl(key) + '?exif'; + var xhr = this.createAjax(); + var info; + var that = this; + xhr.open('GET', url, false); + xhr.onreadystatechange = function() { + if (xhr.readyState === 4 && xhr.status === 200) { + info = that.parseJSON(xhr.responseText); + } + }; + xhr.send(); + return info; + }; + + /** + * invoke the exif or imageInfo api of Qiniu + * according with type param + * @param {String} ['exif'|'imageInfo']type of info + * @param {String} key of file + * @return {Object} image exif or info + */ + this.get = function(type, key) { + if (!key || !type) { + return false; + } + if (type === 'exif') { + return this.exif(key); + } else if (type === 'imageInfo') { + return this.imageInfo(key); + } + return false; + }; + + /** + * invoke api of Qiniu like a pipeline + * @param {Array of Object} params of a series api call + * each object in array is options of api which name is set as 'fop' property + * each api's output will be next api's input + * @param {String} key of file + * @return {String|Boolean} url of processed image + */ + this.pipeline = function(arr, key) { + var isArray = Object.prototype.toString.call(arr) === '[object Array]'; + var option, errOp, imageUrl = ''; + if (isArray) { + for (var i = 0, len = arr.length; i < len; i++) { + option = arr[i]; + if (!option.fop) { + return false; + } + switch (option.fop) { + case 'watermark': + imageUrl += this.watermark(option) + '|'; + break; + case 'imageView2': + imageUrl += this.imageView2(option) + '|'; + break; + case 'imageMogr2': + imageUrl += this.imageMogr2(option) + '|'; + break; + default: + errOp = true; + break; + } + if (errOp) { + return false; + } + } + if (key) { + imageUrl = this.getUrl(key) + '?' + imageUrl; + var length = imageUrl.length; + if (imageUrl.slice(length - 1) === '|') { + imageUrl = imageUrl.slice(0, length - 1); + } + } + return imageUrl; + } + return false; + }; +} + +var Qiniu = new QiniuJsSDK(); + +global.Qiniu = Qiniu; + +global.QiniuJsSDK = QiniuJsSDK; + +})( window ); diff --git a/qiniu_fields/static/qiniu_fields/qiniu/qiniu.min.js b/qiniu_fields/static/qiniu_fields/qiniu/qiniu.min.js new file mode 100755 index 0000000..15b6508 --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/qiniu/qiniu.min.js @@ -0,0 +1,3 @@ +/*! qiniu-js v1.0.19 | Copyright 2015 by Qiniu */ +!function(global){function createCookie(a,b,c){var d=new Date;d.setTime(d.getTime()+24*c*60*60*1e3);var e="; expires="+d.toGMTString();document.cookie=a+"="+b+e+"; path=/"}function readCookie(a){var b=a+"=";var c=document.cookie.split(";");for(var d=0,e=c.length;e>d;d++){var f=c[d];while(" "===f.charAt(0))f=f.substring(1,f.length);if(0===f.indexOf(b))return f.substring(b.length,f.length)}return null}window.localStorage||(window.localStorage={setItem:function(a,b){createCookie(a,b,30)},getItem:function(a){return readCookie(a)},removeItem:function(a){createCookie(a,"",-1)}});function QiniuJsSDK(){var that=this;this.detectIEVersion=function(){var a=4,b=document.createElement("div"),c=b.getElementsByTagName("i");while(b.innerHTML="",c[0])a++;return a>4?a:!1};var logger={MUTE:0,FATA:1,ERROR:2,WARN:3,INFO:4,DEBUG:5,TRACE:6,level:0};function log(a,b){var c="[qiniu-js-sdk]["+a+"]";var d=c;for(var e=0;e")}function makeLogFunc(a){var b=a.toLowerCase();logger[b]=function(){if(window.console&&window.console.log&&logger.level>=logger[a]){var c=Array.prototype.slice.call(arguments);log(b,c)}}}for(var property in logger)logger.hasOwnProperty(property)&&"number"==typeof logger[property]&&!logger.hasOwnProperty(property.toLowerCase())&&makeLogFunc(property);var qiniuUploadUrl;qiniuUploadUrl="https:"===window.location.protocol?"https://up.qbox.me":"http://upload.qiniu.com";var qiniuUploadUrls=["http://upload.qiniu.com","http://up.qiniu.com"];var qiniuUpHosts={http:["http://upload.qiniu.com","http://up.qiniu.com"],https:["https://up.qbox.me"]};var changeUrlTimes=0;this.resetUploadUrl=function(){var a="https:"===window.location.protocol?qiniuUpHosts.https:qiniuUpHosts.http;var b=changeUrlTimes%a.length;qiniuUploadUrl=a[b],changeUrlTimes++,logger.debug("resetUploadUrl: "+qiniuUploadUrl)},this.isImage=function(a){return a=a.split(/[?#]/)[0],/\.(png|jpg|jpeg|gif|bmp)$/i.test(a)},this.getFileExtension=function(a){var b=a.split(".");var c;return c=1===b.length||""===b[0]&&2===b.length?"":b.pop().toLowerCase()},this.utf8_encode=function(a){if(null===a||"undefined"==typeof a)return"";var b=a+"";var c="",d,e,f=0;d=e=0,f=b.length;for(var g=0;f>g;g++){var h=b.charCodeAt(g);var i=null;if(128>h)e++;else if(h>127&&2048>h)i=String.fromCharCode(h>>6|192,63&h|128);else if(63488&h^!0)i=String.fromCharCode(h>>12|224,h>>6&63|128,63&h|128);else{if(64512&h^!0)throw new RangeError("Unmatched trail surrogate at "+g);var j=b.charCodeAt(++g);if(64512&j^!0)throw new RangeError("Unmatched lead surrogate at "+(g-1));h=((1023&h)<<10)+(1023&j)+65536,i=String.fromCharCode(h>>18|240,h>>12&63|128,h>>6&63|128,63&h|128)}null!==i&&(e>d&&(c+=b.slice(d,e)),c+=i,d=e=g+1)}return e>d&&(c+=b.slice(d,f)),c},this.base64_decode=function(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var c,d,e,f,g,h,i,j,k=0,l=0,m="",n=[];if(!a)return a;a+="";do f=b.indexOf(a.charAt(k++)),g=b.indexOf(a.charAt(k++)),h=b.indexOf(a.charAt(k++)),i=b.indexOf(a.charAt(k++)),j=f<<18|g<<12|h<<6|i,c=j>>16&255,d=j>>8&255,e=255&j,64===h?n[l++]=String.fromCharCode(c):64===i?n[l++]=String.fromCharCode(c,d):n[l++]=String.fromCharCode(c,d,e);while(k>18&63,g=j>>12&63,h=j>>6&63,i=63&j,n[l++]=b.charAt(f)+b.charAt(g)+b.charAt(h)+b.charAt(i);while(kd;d++)b.push(that.stringifyJSON(a[d]));return"["+b.join(",")+"]"}if(null===a)return"null";var e=[];for(var f in a)a.hasOwnProperty(f)&&e.push(that.stringifyJSON(f)+":"+that.stringifyJSON(a[f]));return"{"+e.join(",")+"}";case"number":return a;case!1:return a;case"boolean":return a}},this.trim=function(a){return null===a?"":a.replace(/^\s+|\s+$/g,"")},this.uploader=function(a){var b=function(){var b=that.detectIEVersion();var c,d,e;var f="Safari"===mOxie.Env.browser&&mOxie.Env.version<=5&&"Windows"===mOxie.Env.os&&"7"===mOxie.Env.osVersion||"Safari"===mOxie.Env.browser&&"iOS"===mOxie.Env.os&&"7"===mOxie.Env.osVersion;b&&9>b&&a.chunk_size&&a.runtimes.indexOf("flash")>=0?a.chunk_size=0:f?a.chunk_size=0:(c=20,d=4<d&&(a.chunk_size=d))};var c=function(a){var b=[];for(var c=0;c=0?(d.bucket=d.scope.split(":")[0],d.key=d.scope.split(":")[1]):d.bucket=d.scope,d};var e=function(b){var e=d(b);var f=window.location.protocol+"//uc.qbox.me/v1/query?ak="+e.ak+"&bucket="+e.bucket;logger.debug("putPolicy: ",e),logger.debug("get uphosts from: ",f);var g=that.detectIEVersion();var h;g&&9>=g?(h=new mOxie.XMLHttpRequest,mOxie.Env.swf_url=a.flash_swf_url):h=that.createAjax(),h.open("GET",f,!1);var i=function(){if(logger.debug("ajax.readyState: ",h.readyState),4===h.readyState)if(logger.debug("ajax.status: ",h.status),h.status<400){var a=that.parseJSON(h.responseText);qiniuUpHosts.http=c(a.http.up),qiniuUpHosts.https=c(a.https.up),logger.debug("get new uphosts: ",qiniuUpHosts),that.resetUploadUrl()}else logger.error("get uphosts error: ",h.responseText)};g&&9>=g?h.bind("readystatechange",i):h.onreadystatechange=i,h.send()};var f=function(b){return!that.token||a.uptoken_url&&that.tokenInfo.isExpired()?g(b):that.token};var g=function(b){if(a.uptoken)that.token=a.uptoken;else if(a.uptoken_url){logger.debug("get uptoken from: ",that.uptoken_url);var c=that.createAjax();if(c.open("GET",that.uptoken_url,!1),c.setRequestHeader("If-Modified-Since","0"),c.send(),200===c.status){var d=that.parseJSON(c.responseText);that.token=d.uptoken;var f=that.token.split(":");var g=that.parseJSON(that.URLSafeBase64Decode(f[2]));that.tokenMap||(that.tokenMap={});var h=function(a){return Math.ceil(a.getTime()/1e3)};var i=h(new Date(c.getResponseHeader("date")));var j=h(new Date);that.tokenInfo={serverDelay:j-i,deadline:g.deadline,isExpired:function(){var a=this.deadline-h(new Date)+this.serverDelay;return 600>a}},logger.debug("get new uptoken: ",that.token),logger.debug("get token info: ",that.tokenInfo)}else logger.error("get uptoken error: ",c.responseText)}else a.uptoken_func?(logger.debug("get uptoken from uptoken_func"),that.token=a.uptoken_func(b),logger.debug("get new uptoken: ",that.token)):logger.error("one of [uptoken, uptoken_url, uptoken_func] settings in options is required!");return that.token&&e(that.token),that.token};var h=function(b,c,d){var e="",f=!1;if(!a.save_key)if(f=b.getOption&&b.getOption("unique_names"),f=f||b.settings&&b.settings.unique_names){var g=that.getFileExtension(c.name);e=g?c.id+"."+g:c.id}else e="function"==typeof d?d(b,c):c.name;return e};if(a.log_level&&(logger.level=a.log_level),!a.domain)throw"domain setting in options is required!";if(!a.browse_button)throw"browse_button setting in options is required!";if(!a.uptoken&&!a.uptoken_url&&!a.uptoken_func)throw"one of [uptoken, uptoken_url, uptoken_func] settings in options is required!";logger.debug("init uploader start"),logger.debug("environment: ",mOxie.Env),logger.debug("userAgent: ",navigator.userAgent);var i={};var j=a.init&&a.init.Error;var k=a.init&&a.init.FileUploaded;a.init.Error=function(){},a.init.FileUploaded=function(){},that.uptoken_url=a.uptoken_url,that.token="",that.key_handler="function"==typeof a.init.Key?a.init.Key:"",this.domain=a.domain;var l="";var m={isResumeUpload:!1,resumeFilesize:0,startTime:"",currentTime:""};b(),logger.debug("invoke reset_chunk_size()"),logger.debug("op.chunk_size: ",a.chunk_size);var n={url:qiniuUploadUrl,multipart_params:{token:""}};var o=that.detectIEVersion();o&&9>=o&&(n.multipart_params.accept="text/plain; charset=utf-8",logger.debug("add accept text/plain in multipart params")),plupload.extend(i,a,n),logger.debug("option: ",i);var p=new plupload.Uploader(i);logger.debug("new plupload.Uploader(option)"),p.bind("Init",function(b,c){logger.debug("Init event activated"),a.get_new_uptoken||g(null)}),logger.debug("bind Init event"),p.bind("FilesAdded",function(a,b){logger.debug("FilesAdded event activated");var c=a.getOption&&a.getOption("auto_start");c=c||a.settings&&a.settings.auto_start,logger.debug("auto_start: ",c),logger.debug("files: ",b);var d=function(){return"ios"===mOxie.Env.OS.toLowerCase()?!0:!1};if(d())for(var e=0;e=g&&(f.accept="text/plain; charset=utf-8",logger.debug("add accept text/plain in multipart params")),logger.debug("directUpload multipart_params_obj: ",f);var i=a.x_vars;if(void 0!==i&&"object"==typeof i)for(var j in i)i.hasOwnProperty(j)&&("function"==typeof i[j]?f["x:"+j]=i[j](b,c):"object"!=typeof i[j]&&(f["x:"+j]=i[j]));b.setOption({url:qiniuUploadUrl,multipart:!0,chunk_size:e()?a.max_file_size:void 0,multipart_params:f})};var e=function(){var a=navigator.userAgent.toLowerCase();return(a.match(/MicroMessenger/i)||"QQBrowser"===mOxie.Env.browser||a.match(/V1_AND_SQ/i))&&"android"===mOxie.Env.OS.toLowerCase()?!0:!1};var i=b.getOption&&b.getOption("chunk_size");if(i=i||b.settings&&b.settings.chunk_size,logger.debug("uploader.runtime: ",p.runtime),logger.debug("chunk_size: ",i),"html5"!==p.runtime&&"flash"!==p.runtime||!i)logger.debug("directUpload because uploader.runtime !== 'html5' || uploader.runtime !== 'flash' || !chunk_size"),d(b,c,that.key_handler);else if(c.sizen-o&&100!==j.percent&&c.size===j.total?(c.percent=j.percent,c.loaded=j.offset,l=j.ctx,m.isResumeUpload=!0,m.resumeFilesize=j.offset,j.offset+k>c.size&&(k=c.size-j.offset)):localStorage.removeItem(c.name)}m.startTime=(new Date).getTime();var r={};var s=that.detectIEVersion();s&&9>=s&&(r.accept="text/plain; charset=utf-8",logger.debug("add accept text/plain in multipart params")),b.setOption({url:qiniuUploadUrl+"/mkblk/"+k,multipart:!1,chunk_size:i,required_features:"chunks",headers:{Authorization:"UpToken "+f(c)},multipart_params:r})}}),logger.debug("bind BeforeUpload event"),p.bind("UploadProgress",function(a,b){logger.trace("UploadProgress event activated"),m.currentTime=(new Date).getTime();var c=m.currentTime-m.startTime;var d=b.loaded||0;m.isResumeUpload&&(d=b.loaded-m.resumeFilesize),b.speed=(d/c*1e3).toFixed(0)||0}),logger.debug("bind UploadProgress event"),p.bind("ChunkUploaded",function(a,b,c){logger.debug("ChunkUploaded event activated"),logger.debug("file: ",b),logger.debug("info: ",c);var d=that.parseJSON(c.response);logger.debug("res: ",d),l=l?l+","+d.ctx:d.ctx;var e=c.total-c.offset;var g=a.getOption&&a.getOption("chunk_size");g=g||a.settings&&a.settings.chunk_size,g>e&&(a.setOption({url:qiniuUploadUrl+"/mkblk/"+e}),logger.debug("up.setOption url: ",qiniuUploadUrl+"/mkblk/"+e)),a.setOption({headers:{Authorization:"UpToken "+f(b)}}),localStorage.setItem(b.name,that.stringifyJSON({ctx:l,percent:b.percent,total:c.total,offset:c.offset,time:(new Date).getTime()}))}),logger.debug("bind ChunkUploaded event");var q=qiniuUploadUrls.length;var r=function(a){return q-->0?(setTimeout(function(){that.resetUploadUrl(),a.status=plupload.QUEUED,p.stop(),p.start()},0),!0):(q=qiniuUploadUrls.length,!1)};return p.bind("Error",function(a){return function(b,c){logger.error("Error event activated"),logger.error("err: ",c);var d="";var e=c.file;if(e){switch(c.code){case plupload.FAILED:d="\u4e0a\u4f20\u5931\u8d25\u3002\u8bf7\u7a0d\u540e\u518d\u8bd5\u3002";break;case plupload.FILE_SIZE_ERROR:var f=b.getOption&&b.getOption("max_file_size");f=f||b.settings&&b.settings.max_file_size,d="\u6d4f\u89c8\u5668\u6700\u5927\u53ef\u4e0a\u4f20"+f+"\u3002\u66f4\u5927\u6587\u4ef6\u8bf7\u4f7f\u7528\u547d\u4ee4\u884c\u5de5\u5177\u3002";break;case plupload.FILE_EXTENSION_ERROR:d="\u6587\u4ef6\u9a8c\u8bc1\u5931\u8d25\u3002\u8bf7\u7a0d\u540e\u91cd\u8bd5\u3002";break;case plupload.HTTP_ERROR:if(""===c.response){if(d=c.message||"\u672a\u77e5\u7f51\u7edc\u9519\u8bef\u3002",!r(e))return;break}var g=that.parseJSON(c.response);var h=g.error;switch(c.status){case 400:d="\u8bf7\u6c42\u62a5\u6587\u683c\u5f0f\u9519\u8bef\u3002";break;case 401:d="\u5ba2\u6237\u7aef\u8ba4\u8bc1\u6388\u6743\u5931\u8d25\u3002\u8bf7\u91cd\u8bd5\u6216\u63d0\u4ea4\u53cd\u9988\u3002";break;case 405:d="\u5ba2\u6237\u7aef\u8bf7\u6c42\u9519\u8bef\u3002\u8bf7\u91cd\u8bd5\u6216\u63d0\u4ea4\u53cd\u9988\u3002";break;case 579:d="\u8d44\u6e90\u4e0a\u4f20\u6210\u529f\uff0c\u4f46\u56de\u8c03\u5931\u8d25\u3002";break;case 599:if(d="\u7f51\u7edc\u8fde\u63a5\u5f02\u5e38\u3002\u8bf7\u91cd\u8bd5\u6216\u63d0\u4ea4\u53cd\u9988\u3002",!r(e))return;break;case 614:d="\u6587\u4ef6\u5df2\u5b58\u5728\u3002";try{g=that.parseJSON(g.error),h=g.error||"file exists"}catch(i){h=g.error||"file exists"}break;case 631:d="\u6307\u5b9a\u7a7a\u95f4\u4e0d\u5b58\u5728\u3002";break;case 701:d="\u4e0a\u4f20\u6570\u636e\u5757\u6821\u9a8c\u51fa\u9519\u3002\u8bf7\u91cd\u8bd5\u6216\u63d0\u4ea4\u53cd\u9988\u3002";break;default:if(d="\u672a\u77e5\u9519\u8bef\u3002",!r(e))return}d=d+"("+c.status+"\uff1a"+h+")";break;case plupload.SECURITY_ERROR:d="\u5b89\u5168\u914d\u7f6e\u9519\u8bef\u3002\u8bf7\u8054\u7cfb\u7f51\u7ad9\u7ba1\u7406\u5458\u3002";break;case plupload.GENERIC_ERROR:d="\u4e0a\u4f20\u5931\u8d25\u3002\u8bf7\u7a0d\u540e\u518d\u8bd5\u3002";break;case plupload.IO_ERROR:d="\u4e0a\u4f20\u5931\u8d25\u3002\u8bf7\u7a0d\u540e\u518d\u8bd5\u3002";break;case plupload.INIT_ERROR:d="\u7f51\u7ad9\u914d\u7f6e\u9519\u8bef\u3002\u8bf7\u8054\u7cfb\u7f51\u7ad9\u7ba1\u7406\u5458\u3002",p.destroy();break;default:if(d=c.message+c.details,!r(e))return}a&&a(b,c,d)}b.refresh()}}(j)),logger.debug("bind Error event"),p.bind("FileUploaded",function(b){return function(c,d,e){logger.debug("FileUploaded event activated"),logger.debug("file: ",d),logger.debug("info: ",e);var f=function(c,d,e){if(a.downtoken_url){var f=that.createAjax();f.open("POST",a.downtoken_url,!0),f.setRequestHeader("Content-type","application/x-www-form-urlencoded"),f.onreadystatechange=function(){if(4===f.readyState)if(200===f.status){var a;try{a=that.parseJSON(f.responseText)}catch(g){throw"invalid json format"}var h={};plupload.extend(h,that.parseJSON(e),a),b&&b(c,d,that.stringifyJSON(h))}else p.trigger("Error",{status:f.status,response:f.responseText,file:d,code:plupload.HTTP_ERROR})},f.send("key="+that.parseJSON(e).key+"&domain="+a.domain)}else b&&b(c,d,e)};var g=that.parseJSON(e.response);if(l=l?l:g.ctx,logger.debug("ctx: ",l),l){var i="";logger.debug("save_key: ",a.save_key),a.save_key||(i=h(c,d,that.key_handler),i=i?"/key/"+that.URLSafeBase64Encode(i):"");var j="/fname/"+that.URLSafeBase64Encode(d.name);logger.debug("op.x_vars: ",a.x_vars);var k=a.x_vars,m="",n="";if(void 0!==k&&"object"==typeof k)for(var o in k)k.hasOwnProperty(o)&&("function"==typeof k[o]?m=that.URLSafeBase64Encode(k[o](c,d)):"object"!=typeof k[o]&&(m=that.URLSafeBase64Encode(k[o])),n+="/x:"+o+"/"+m);var q=qiniuUploadUrl+"/mkfile/"+d.size+i+j+n;var r=that.detectIEVersion();var s;r&&9>=r?(s=new mOxie.XMLHttpRequest,mOxie.Env.swf_url=a.flash_swf_url):s=that.createAjax(),s.open("POST",q,!0),s.setRequestHeader("Content-Type","text/plain;charset=UTF-8"),s.setRequestHeader("Authorization","UpToken "+that.token);var t=function(){if(logger.debug("ajax.readyState: ",s.readyState),4===s.readyState){localStorage.removeItem(d.name);var a;200===s.status?(a=s.responseText,logger.debug("mkfile is success: ",a),f(c,d,a)):(a={status:s.status,response:s.responseText,file:d,code:-200,responseHeaders:s.getAllResponseHeaders()},logger.debug("mkfile is error: ",a),p.trigger("Error",a))}};r&&9>=r?s.bind("readystatechange",t):s.onreadystatechange=t,s.send(l),logger.debug("mkfile: ",q)}else f(c,d,e.response)}}(k)),logger.debug("bind FileUploaded event"),p.init(),logger.debug("invoke uploader.init()"),logger.debug("init uploader end"),p},this.getUrl=function(a){if(!a)return!1;a=encodeURI(a);var b=this.domain;return"/"!==b.slice(b.length-1)&&(b+="/"),b+a},this.imageView2=function(a,b){if(!/^\d$/.test(a.mode))return!1;var c=a.mode,d=a.w||"",e=a.h||"",f=a.q||"",g=a.format||"";if(!d&&!e)return!1;var h="imageView2/"+c;return h+=d?"/w/"+d:"",h+=e?"/h/"+e:"",h+=f?"/q/"+f:"",h+=g?"/format/"+g:"",b&&(h=this.getUrl(b)+"?"+h),h},this.imageMogr2=function(a,b){var c=a["auto-orient"]||"",d=a.thumbnail||"",e=a.strip||"",f=a.gravity||"",g=a.crop||"",h=a.quality||"",i=a.rotate||"",j=a.format||"",k=a.blur||"";var l="imageMogr2";return l+=c?"/auto-orient":"",l+=d?"/thumbnail/"+d:"",l+=e?"/strip":"",l+=f?"/gravity/"+f:"",l+=h?"/quality/"+h:"",l+=g?"/crop/"+g:"",l+=i?"/rotate/"+i:"",l+=j?"/format/"+j:"",l+=k?"/blur/"+k:"",b&&(l=this.getUrl(b)+"?"+l),l},this.watermark=function(a,b){var c=a.mode;if(!c)return!1;var d="watermark/"+c;if(1===c){var e=a.image||"";if(!e)return!1;d+=e?"/image/"+this.URLSafeBase64Encode(e):""}else{if(2!==c)return!1;var f=a.text?a.text:"",g=a.font?a.font:"",h=a.fontsize?a.fontsize:"",i=a.fill?a.fill:"";if(!f)return!1;d+=f?"/text/"+this.URLSafeBase64Encode(f):"",d+=g?"/font/"+this.URLSafeBase64Encode(g):"",d+=h?"/fontsize/"+h:"",d+=i?"/fill/"+this.URLSafeBase64Encode(i):""}var j=a.dissolve||"",k=a.gravity||"",l=a.dx||"",m=a.dy||"";return d+=j?"/dissolve/"+j:"",d+=k?"/gravity/"+k:"",d+=l?"/dx/"+l:"",d+=m?"/dy/"+m:"",b&&(d=this.getUrl(b)+"?"+d),d},this.imageInfo=function(a){if(!a)return!1;var b=this.getUrl(a)+"?imageInfo";var c=this.createAjax();var d;var e=this;return c.open("GET",b,!1),c.onreadystatechange=function(){4===c.readyState&&200===c.status&&(d=e.parseJSON(c.responseText))},c.send(),d},this.exif=function(a){if(!a)return!1;var b=this.getUrl(a)+"?exif";var c=this.createAjax();var d;var e=this;return c.open("GET",b,!1),c.onreadystatechange=function(){4===c.readyState&&200===c.status&&(d=e.parseJSON(c.responseText))},c.send(),d},this.get=function(a,b){return b&&a?"exif"===a?this.exif(b):"imageInfo"===a?this.imageInfo(b):!1:!1},this.pipeline=function(a,b){var c="[object Array]"===Object.prototype.toString.call(a);var d,e,f="";if(c){for(var g=0,h=a.length;h>g;g++){if(d=a[g],!d.fop)return!1;switch(d.fop){case"watermark":f+=this.watermark(d)+"|";break;case"imageView2":f+=this.imageView2(d)+"|";break;case"imageMogr2":f+=this.imageMogr2(d)+"|";break;default:e=!0}if(e)return!1}if(b){f=this.getUrl(b)+"?"+f;var i=f.length;"|"===f.slice(i-1)&&(f=f.slice(0,i-1))}return f}return!1}}var Qiniu=new QiniuJsSDK;global.Qiniu=Qiniu,global.QiniuJsSDK=QiniuJsSDK}(window); +//# sourceMappingURL=dist/qiniu.min.map \ No newline at end of file diff --git a/qiniu_fields/static/qiniu_fields/qiniu/qiniu.min.map b/qiniu_fields/static/qiniu_fields/qiniu/qiniu.min.map new file mode 100755 index 0000000..bca46a2 --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/qiniu/qiniu.min.map @@ -0,0 +1 @@ +{"version":3,"file":"dist/qiniu.min.js","sources":["dist/qiniu.js"],"names":["global","createCookie","key","value","exp","date","Date","setTime","getTime","expires","toGMTString","document","cookie","readCookie","nameEQ","ca","split","i","max","length","c","charAt","substring","indexOf","window","localStorage","setItem","getItem","removeItem","QiniuJsSDK","that","this","detectIEVersion","v","div","createElement","all","getElementsByTagName","innerHTML","logger","MUTE","FATA","ERROR","WARN","INFO","DEBUG","TRACE","level","log","type","args","header","msg","stringifyJSON","console","unshift","apply","getElementById","makeLogFunc","code","func","toLowerCase","Array","prototype","slice","call","arguments","property","hasOwnProperty","qiniuUploadUrl","location","protocol","qiniuUploadUrls","qiniuUpHosts","http","https","changeUrlTimes","resetUploadUrl","hosts","debug","isImage","url","test","getFileExtension","filename","tempArr","ext","pop","utf8_encode","argString","string","utftext","start","end","stringl","n","c1","charCodeAt","enc","String","fromCharCode","RangeError","c2","base64_decode","data","b64","o1","o2","o3","h1","h2","h3","h4","bits","ac","dec","tmp_arr","join","base64_encode","URLSafeBase64Encode","replace","URLSafeBase64Decode","createAjax","argument","xmlhttp","XMLHttpRequest","ActiveXObject","parseJSON","JSON","parse","rx_dangerous","text","lastIndex","a","toString","eval","obj","stringify","map","strArr","len","push","trim","uploader","op","reset_chunk_size","ie","BLOCK_BITS","MAX_CHUNK_SIZE","chunk_size","isSpecialSafari","mOxie","Env","browser","version","os","osVersion","runtimes","plupload","parseSize","getHosts","result","host","getPutPolicy","uptoken","segments","ak","putPolicy","scope","bucket","getUpHosts","uphosts_url","ajax","swf_url","flash_swf_url","open","onreadystatechange","readyState","status","res","responseText","up","error","bind","send","getUptoken","file","token","uptoken_url","tokenInfo","isExpired","getNewUpToken","setRequestHeader","tokenMap","getTimestamp","time","Math","ceil","serverTime","getResponseHeader","clientTime","serverDelay","deadline","leftTime","uptoken_func","getFileKey","unique_names","save_key","getOption","settings","name","id","log_level","domain","browse_button","navigator","userAgent","option","_Error_Handler","init","Error","_FileUploaded_Handler","FileUploaded","key_handler","Key","ctx","speedCalInfo","isResumeUpload","resumeFilesize","startTime","currentTime","defaultSetting","multipart_params","accept","extend","Uploader","params","get_new_uptoken","files","auto_start","is_ios","OS","setTimeout","refresh","speed","directUpload","multipart_params_obj","x_vars","undefined","x_key","setOption","multipart","is_android_weixin_or_qq","max_file_size","ua","match","runtime","size","localFileInfo","blockSize","now","before","aDay","percent","total","loaded","offset","required_features","headers","Authorization","trace","timeUsed","fileUploaded","toFixed","info","response","leftSize","retries","unknow_error_retry","QUEUED","stop","err","errTip","FAILED","FILE_SIZE_ERROR","FILE_EXTENSION_ERROR","HTTP_ERROR","message","errorObj","errorText","e","SECURITY_ERROR","GENERIC_ERROR","IO_ERROR","INIT_ERROR","destroy","details","last_step","downtoken_url","ajax_downtoken","res_downtoken","info_extended","trigger","fname","x_val","x_vars_url","responseHeaders","getAllResponseHeaders","getUrl","encodeURI","imageView2","mode","w","h","q","format","imageUrl","imageMogr2","auto_orient","thumbnail","strip","gravity","crop","quality","rotate","blur","watermark","image","font","fontsize","fill","dissolve","dx","dy","imageInfo","xhr","exif","get","pipeline","arr","isArray","Object","errOp","fop","Qiniu"],"mappings":"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"} \ No newline at end of file diff --git a/qiniu_fields/static/qiniu_fields/qiniu/ui.js b/qiniu_fields/static/qiniu_fields/qiniu/ui.js new file mode 100644 index 0000000..545a875 --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/qiniu/ui.js @@ -0,0 +1,233 @@ +/*global plupload */ +/*global qiniu */ +function FileProgress(file, targetID) { + this.fileProgressID = file.id; + this.file = file; + + this.opacity = 100; + this.height = 0; + this.fileProgressWrapper = $('#' + this.fileProgressID); + if (!this.fileProgressWrapper.length) { + this.fileProgressWrapper = $('
'); + var Wrappeer = this.fileProgressWrapper; + Wrappeer.attr('id', this.fileProgressID).addClass('progressContainer'); + + var progressBarBox = $("
"); + progressBarBox.addClass('info'); + var progressBarWrapper = $("
"); + progressBarWrapper.addClass("progress progress-striped"); + progressBarWrapper.attr('style', 'width: 200px'); + + var progressBar = $("
"); + progressBar.addClass("progress-bar progress-bar-info") + .attr('role', 'progressbar') + .attr('aria-valuemax', 100) + .attr('aria-valuenow', 0) + .attr('aria-valuein', 0) + .width('0%'); + + progressBarWrapper.append(progressBar); + progressBarBox.append(progressBarWrapper); + + var progressBarStatus = $(''); + progressBarBox.append(progressBarStatus); + var progressCancel = $(''); + progressCancel.show().addClass('progressCancel ml15').text('×'); + progressBarBox.append(progressCancel); + + Wrappeer.append(progressBarBox); + + $('#' + targetID).append(Wrappeer); + } else { + this.reset(); + } + + this.height = this.fileProgressWrapper.offset().top; + this.setTimer(null); +} + +FileProgress.prototype.setTimer = function(timer) { + this.fileProgressWrapper.FP_TIMER = timer; +}; + +FileProgress.prototype.getTimer = function(timer) { + return this.fileProgressWrapper.FP_TIMER || null; +}; + +FileProgress.prototype.reset = function() { + this.fileProgressWrapper.attr('class', "progressContainer"); + this.fileProgressWrapper.find('td .progress .progress-bar-info').attr('aria-valuenow', 0).width('0%').find('span').text(''); + this.appear(); +}; + +FileProgress.prototype.setChunkProgress = function(chunk_size) { + var chunk_amount = Math.ceil(this.file.size / chunk_size); + if (chunk_amount === 1) { + return false; + } + + var viewProgress = $(''); + var progressBarChunkTr = $(''); + var progressBarChunk = $('
'); + for (var i = 1; i <= chunk_amount; i++) { + var col = $('
'); + var progressBarWrapper = $('
"); + progressBar.addClass("progress-bar progress-bar-info text-left") + .attr('role', 'progressbar') + .attr('aria-valuemax', 100) + .attr('aria-valuenow', 0) + .attr('aria-valuein', 0) + .width('0%') + .attr('id', this.file.id + '_' + i) + .text(''); + + var progressBarStatus = $(''); + progressBarStatus.addClass('chunk-status').text(); + + progressBarWrapper.append(progressBar); + progressBarWrapper.append(progressBarStatus); + + col.append(progressBarWrapper); + progressBarChunk.append(col); + } + + if(!this.fileProgressWrapper.find('td:eq(2) .btn-default').length){ + this.fileProgressWrapper.find('td>div').append(viewProgress); + } + progressBarChunkTr.hide().find('td').append(progressBarChunk); + progressBarChunkTr.insertAfter(this.fileProgressWrapper); + +}; + +FileProgress.prototype.setProgress = function(percentage, speed, chunk_size) { + this.fileProgressWrapper.attr('class', "progressContainer green"); + + var file = this.file; + var uploaded = file.loaded; + var totalSize = plupload.formatSize(file.size).toUpperCase(), + size = plupload.formatSize(uploaded).toUpperCase(); + var formatSpeed = plupload.formatSize(speed).toUpperCase(); + var progressbar = this.fileProgressWrapper.find('div.progress').find('.progress-bar-info'); + if (this.fileProgressWrapper.find('.status').text() === '取消上传') { + return; + } + this.fileProgressWrapper.find('.status').text("已上传: " + size + ' / ' + totalSize + " 上传速度: " + formatSpeed + "/s"); + percentage = parseInt(percentage, 10); + if (file.status !== plupload.DONE && percentage === 100) { + percentage = 99; + } + progressbar.attr('aria-valuenow', percentage).css('width', percentage + '%'); + + if (chunk_size) { + var chunk_amount = Math.ceil(file.size / chunk_size); + if (chunk_amount === 1) { + return false; + } + var current_uploading_chunk = Math.ceil(uploaded / chunk_size); + var pre_chunk, text; + + for (var index = 0; index < current_uploading_chunk; index++) { + pre_chunk = $('#' + file.id + "_" + index); + pre_chunk.width('100%').removeClass().addClass('alert-success').attr('aria-valuenow', 100); + text = "块" + index + "上传进度100%"; + pre_chunk.next().html(text); + } + + var currentProgessBar = $('#' + file.id + "_" + current_uploading_chunk); + var current_chunk_percent; + if (current_uploading_chunk < chunk_amount) { + if (uploaded % chunk_size) { + current_chunk_percent = ((uploaded % chunk_size) / chunk_size * 100).toFixed(2); + } else { + current_chunk_percent = 100; + currentProgessBar.removeClass().addClass('alert-success'); + } + } else { + var last_chunk_size = file.size - chunk_size * (chunk_amount - 1); + var left_file_size = file.size - uploaded; + if (left_file_size % last_chunk_size) { + current_chunk_percent = ((uploaded % chunk_size) / last_chunk_size * 100).toFixed(2); + } else { + current_chunk_percent = 100; + currentProgessBar.removeClass().addClass('alert-success'); + } + } + currentProgessBar.width(current_chunk_percent + '%'); + currentProgessBar.attr('aria-valuenow', current_chunk_percent); + text = "块" + current_uploading_chunk + "上传进度" + current_chunk_percent + '%'; + currentProgessBar.next().html(text); + } + + this.appear(); +}; + +FileProgress.prototype.setComplete = function(up, info) { + var td = this.fileProgressWrapper.find('td:eq(2)'), + tdProgress = td.find('.progress'); + tdProgress.html('').removeClass().next().next('.status').hide(); + td.find('.progressCancel').hide(); +}; +FileProgress.prototype.setError = function() { + this.fileProgressWrapper.find('td:eq(2)').attr('class', 'text-warning'); + this.fileProgressWrapper.find('td:eq(2) .progress').css('width', 0).hide(); + this.fileProgressWrapper.find('button').hide(); + this.fileProgressWrapper.next('.chunk-status-tr').hide(); +}; + +FileProgress.prototype.setCancelled = function(manual) { + var progressContainer = 'progressContainer'; + if (!manual) { + progressContainer += ' red'; + } + this.fileProgressWrapper.attr('class', progressContainer); + this.fileProgressWrapper.find('td .progress').remove(); + this.fileProgressWrapper.find('td:eq(2) .btn-default').hide(); + this.fileProgressWrapper.find('td:eq(2) .progressCancel').hide(); +}; + +FileProgress.prototype.setStatus = function(status, isUploading) { + if (!isUploading) { + this.fileProgressWrapper.find('.status').text(status).attr('class', 'status text-left'); + } +}; + +// 绑定取消上传事件 +FileProgress.prototype.bindUploadCancel = function(up) { + var self = this; + if (up) { + self.fileProgressWrapper.find('td:eq(2) .progressCancel').on('click', function(){ + self.setCancelled(false); + self.setStatus("取消上传"); + self.fileProgressWrapper.find('.status').css('left', '0'); + up.removeFile(self.file); + }); + } + +}; + +FileProgress.prototype.appear = function() { + if (this.getTimer() !== null) { + clearTimeout(this.getTimer()); + this.setTimer(null); + } + + if (this.fileProgressWrapper[0].filters) { + try { + this.fileProgressWrapper[0].filters.item("DXImageTransform.Microsoft.Alpha").opacity = 100; + } catch (e) { + // If it is not set initially, the browser will throw an error. This will set it if it is not set yet. + this.fileProgressWrapper.css('filter', "progid:DXImageTransform.Microsoft.Alpha(opacity=100)"); + } + } else { + this.fileProgressWrapper.css('opacity', 1); + } + + this.fileProgressWrapper.css('height', ''); + + this.height = this.fileProgressWrapper.offset().top; + this.opacity = 100; + this.fileProgressWrapper.show(); + +}; diff --git a/qiniu_fields/static/qiniu_fields/qiniu/ui.min.js b/qiniu_fields/static/qiniu_fields/qiniu/ui.min.js new file mode 100644 index 0000000..11131d1 --- /dev/null +++ b/qiniu_fields/static/qiniu_fields/qiniu/ui.min.js @@ -0,0 +1,2 @@ +function FileProgress(c,b){this.fileProgressID=c.id;this.file=c;this.opacity=100;this.height=0;this.fileProgressWrapper=$("#"+this.fileProgressID);if(!this.fileProgressWrapper.length){this.fileProgressWrapper=$("
");var e=this.fileProgressWrapper;e.attr("id",this.fileProgressID).addClass("progressContainer");var d=$("
");d.addClass("info");var h=$("
");h.addClass("progress progress-striped");h.attr("style","width: 200px");var g=$("
");g.addClass("progress-bar progress-bar-info").attr("role","progressbar").attr("aria-valuemax",100).attr("aria-valuenow",0).attr("aria-valuein",0).width("0%");h.append(g);d.append(h);var a=$('');d.append(a);var f=$("");f.show().addClass("progressCancel ml15").text("×");d.append(f);e.append(d);$("#"+b).append(e)}else{this.reset()}this.height=this.fileProgressWrapper.offset().top;this.setTimer(null)}FileProgress.prototype.setTimer=function(a){this.fileProgressWrapper.FP_TIMER=a};FileProgress.prototype.getTimer=function(a){return this.fileProgressWrapper.FP_TIMER||null};FileProgress.prototype.reset=function(){this.fileProgressWrapper.attr("class","progressContainer");this.fileProgressWrapper.find("td .progress .progress-bar-info").attr("aria-valuenow",0).width("0%").find("span").text("");this.appear()};FileProgress.prototype.setChunkProgress=function(j){var k=Math.ceil(this.file.size/j);if(k===1){return false}var f=$('');var e=$('');var g=$("
");for(var c=1;c<=k;c++){var b=$('
');var a=$(' + + diff --git a/qiniu_fields/templates/file_list.html b/qiniu_fields/templates/file_list.html new file mode 100644 index 0000000..b4882ba --- /dev/null +++ b/qiniu_fields/templates/file_list.html @@ -0,0 +1,107 @@ +
+ + 选择文件 +
+ + diff --git a/qiniu_fields/widgets.py b/qiniu_fields/widgets.py new file mode 100644 index 0000000..e486009 --- /dev/null +++ b/qiniu_fields/widgets.py @@ -0,0 +1,55 @@ +#! -*- coding: utf-8 -*- +from django import forms +from django.conf import settings +from django.utils.html import smart_urlquote + + +class QiniuFileWidget(forms.URLInput): + input_type = 'file' + template_name = 'file.html' + + def __init__(self, attrs=None): + final_attrs = { + 'domain': settings.QINIU_DOMAIN, + 'uptoken_url': settings.QINIU_UPTOKEN_URL, + } + if attrs is not None: + final_attrs.update(attrs) + super(QiniuFileWidget, self).__init__(attrs=final_attrs) + + def get_context(self, name, value, attrs): + context = super(QiniuFileWidget, self).get_context(name, value, attrs) + context['current_label'] = '当前:' + context['widget']['href'] = smart_urlquote(context['widget']['value']) if value else '' + return context + + @property + def media(self): + return forms.Media(js=('qiniu_fields/plupload/plupload.full.min.js', 'qiniu_fields/plupload/i18n/zh_CN.js', + 'qiniu_fields/qiniu/qiniu.min.js', 'qiniu_fields/qiniu/ui.min.js')) + + # class Media: + # js = ('qiniu_fields/plupload/plupload.full.min.js', 'qiniu_fields/plupload/i18n/zh_CN.js', + # 'qiniu_fields/qiniu/qiniu.min.js', 'qiniu_fields/qiniu/ui.min.js') + + +class QiniuFileListWidget(forms.Textarea): + template_name = 'file_list.html' + + def __init__(self, attrs=None): + final_attrs = { + 'domain': settings.QINIU_DOMAIN, + 'uptoken_url': settings.QINIU_UPTOKEN_URL, + } + if attrs is not None: + final_attrs.update(attrs) + super(QiniuFileListWidget, self).__init__(attrs=final_attrs) + + @property + def media(self): + return forms.Media(js=('qiniu_fields/plupload/plupload.full.min.js', 'qiniu_fields/plupload/i18n/zh_CN.js', + 'qiniu_fields/qiniu/qiniu.min.js', 'qiniu_fields/qiniu/ui.min.js')) + + # class Media: + # js = ('qiniu_fields/plupload/plupload.full.min.js', 'qiniu_fields/plupload/i18n/zh_CN.js', + # 'qiniu_fields/qiniu/qiniu.min.js', 'qiniu_fields/qiniu/ui.min.js') diff --git a/qiniu_fields_demo/__init__.py b/qiniu_fields_demo/__init__.py new file mode 100644 index 0000000..063cd2c --- /dev/null +++ b/qiniu_fields_demo/__init__.py @@ -0,0 +1,2 @@ +import pymysql +pymysql.install_as_MySQLdb() diff --git a/qiniu_fields_demo/settings.py b/qiniu_fields_demo/settings.py new file mode 100644 index 0000000..fc738e4 --- /dev/null +++ b/qiniu_fields_demo/settings.py @@ -0,0 +1,141 @@ +""" +Django settings for qiniu_fields_demo project. + +Generated by 'django-admin startproject' using Django 1.11.5. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.11/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'b(2kyt&=@kb!te4394*o4z**%7w9yi#back++rv2r@2=(iu+um' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + + 'xadmin', + 'crispy_forms', + 'reversion', + 'qiniu_fields', + 'demo', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'qiniu_fields_demo.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'qiniu_fields_demo.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'USER': 'root', + 'PASSWORD': '123456', + 'HOST': '127.0.0.1', + 'PORT': '3306', + 'NAME': 'qiniu_fields', + }, +} + + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/1.11/topics/i18n/ + +LANGUAGE_CODE = 'zh-hans' + +TIME_ZONE = 'Asia/Shanghai' + +USE_I18N = True + +USE_L10N = False + +USE_TZ = False + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.11/howto/static-files/ + +STATIC_URL = '/static/' + +# date and datetime field formats +DATE_FORMAT = 'Y-m-d' +DATETIME_FORMAT = 'Y-m-d H:i:s' + +# 七牛云存储 +QINIU_ACCESS_KEY = 'qiniu-access-key' # your own +QINIU_SECRET_KEY = 'qiniu-secret-key' # your own +QINIU_BUCKET = 'bucket-name' # your own +QINIU_DOMAIN = 'qiniu-domain-or-your-own-domain' # your own +QINIU_UPTOKEN_URL = '/console/api/get_qiniu_token' diff --git a/qiniu_fields_demo/urls.py b/qiniu_fields_demo/urls.py new file mode 100644 index 0000000..7501f40 --- /dev/null +++ b/qiniu_fields_demo/urls.py @@ -0,0 +1,37 @@ +"""prizeclaw URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.11/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url +from django.conf import settings + +from demo.views import get_qiniu_token + +import xadmin +from xadmin.plugins import xversion + +from reversion.models import Revision +xadmin.site.unregister(Revision) + +xadmin.autodiscover() +xversion.register_models() + +urlpatterns = [ + url(r'^console/', xadmin.site.urls), + url(r'^console/api/get_qiniu_token$', get_qiniu_token, name='get_qiniu_token'), +] + +if settings.DEBUG: + from django.contrib.staticfiles.urls import staticfiles_urlpatterns + urlpatterns += staticfiles_urlpatterns() diff --git a/qiniu_fields_demo/wsgi.py b/qiniu_fields_demo/wsgi.py new file mode 100644 index 0000000..c8560bf --- /dev/null +++ b/qiniu_fields_demo/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for qiniu_fields_demo project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "qiniu_fields_demo.settings") + +application = get_wsgi_application() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f2d2d3d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +django==1.11.5 +pymysql==0.7.11 +django-reversion +git+git://github.com/WuXianglong/xadmin.git +qiniu