diff options
author | Mike Macgirvin <mike@macgirvin.com> | 2018-10-31 15:56:08 +1100 |
---|---|---|
committer | Mike Macgirvin <mike@macgirvin.com> | 2018-10-31 15:56:08 +1100 |
commit | 7e1f431eca7a8aa68fc0badfaa88e88de3ba094c (patch) | |
tree | 16beba352cd4ace4aa6eb13c7f9c1c82c92013b4 /library/blueimp_upload | |
parent | 70c55da1df69d90dcbeb5a78c994b23a8456bfc9 (diff) | |
download | volse-hubzilla-7e1f431eca7a8aa68fc0badfaa88e88de3ba094c.tar.gz volse-hubzilla-7e1f431eca7a8aa68fc0badfaa88e88de3ba094c.tar.bz2 volse-hubzilla-7e1f431eca7a8aa68fc0badfaa88e88de3ba094c.zip |
yet another blueimp vulnerability. Move to composer.
Diffstat (limited to 'library/blueimp_upload')
53 files changed, 0 insertions, 10383 deletions
diff --git a/library/blueimp_upload/.gitignore b/library/blueimp_upload/.gitignore deleted file mode 100644 index 29a41a8c4..000000000 --- a/library/blueimp_upload/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.DS_Store -*.pyc -node_modules diff --git a/library/blueimp_upload/.jshintrc b/library/blueimp_upload/.jshintrc deleted file mode 100644 index 4ad82e664..000000000 --- a/library/blueimp_upload/.jshintrc +++ /dev/null @@ -1,81 +0,0 @@ -{ - "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) - "camelcase" : true, // true: Identifiers must be in camelCase - "curly" : true, // true: Require {} for every new block or scope - "eqeqeq" : true, // true: Require triple equals (===) for comparison - "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() - "immed" : true, // true: Require immediate invocations to be wrapped in parens - // e.g. `(function () { } ());` - "indent" : 4, // {int} Number of spaces to use for indentation - "latedef" : true, // true: Require variables/functions to be defined before being used - "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()` - "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` - "noempty" : true, // true: Prohibit use of empty blocks - "nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment) - "plusplus" : false, // true: Prohibit use of `++` & `--` - "quotmark" : "single", // Quotation mark consistency: - // false : do nothing (default) - // true : ensure whatever is used is consistent - // "single" : require single quotes - // "double" : require double quotes - "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) - "unused" : true, // true: Require all defined variables be used - "strict" : true, // true: Requires all functions run in ES5 Strict Mode - "trailing" : true, // true: Prohibit trailing whitespaces - "maxparams" : false, // {int} Max number of formal params allowed per function - "maxdepth" : false, // {int} Max depth of nested blocks (within functions) - "maxstatements" : false, // {int} Max number statements per function - "maxcomplexity" : false, // {int} Max cyclomatic complexity per function - "maxlen" : false, // {int} Max number of characters per line - - // Relaxing - "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) - "boss" : false, // true: Tolerate assignments where comparisons would be expected - "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. - "eqnull" : false, // true: Tolerate use of `== null` - "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) - "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) - "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) - // (ex: `for each`, multiple try/catch, function expression…) - "evil" : false, // true: Tolerate use of `eval` and `new Function()` - "expr" : false, // true: Tolerate `ExpressionStatement` as Programs - "funcscope" : false, // true: Tolerate defining variables inside control statements" - "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') - "iterator" : false, // true: Tolerate using the `__iterator__` property - "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block - "laxbreak" : false, // true: Tolerate possibly unsafe line breakings - "laxcomma" : false, // true: Tolerate comma-first style coding - "loopfunc" : false, // true: Tolerate functions being defined in loops - "multistr" : false, // true: Tolerate multi-line strings - "proto" : false, // true: Tolerate using the `__proto__` property - "scripturl" : false, // true: Tolerate script-targeted URLs - "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment - "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` - "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation - "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` - "validthis" : false, // true: Tolerate using this in a non-constructor function - - // Environments - "browser" : false, // Web Browser (window, document, etc) - "couch" : false, // CouchDB - "devel" : false, // Development/debugging (alert, confirm, etc) - "dojo" : false, // Dojo Toolkit - "jquery" : false, // jQuery - "mootools" : false, // MooTools - "node" : false, // Node.js - "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) - "prototypejs" : false, // Prototype and Scriptaculous - "rhino" : false, // Rhino - "worker" : false, // Web Workers - "wsh" : false, // Windows Scripting Host - "yui" : false, // Yahoo User Interface - - // Legacy - "nomen" : true, // true: Prohibit dangling `_` in variables - "onevar" : true, // true: Allow only one `var` statement per function - "passfail" : false, // true: Stop on first error - "white" : true, // true: Check against strict whitespace and indentation rules - - // Custom Globals - "globals" : {} // additional predefined global variables -} diff --git a/library/blueimp_upload/.npmignore b/library/blueimp_upload/.npmignore deleted file mode 100644 index 0530f5dbd..000000000 --- a/library/blueimp_upload/.npmignore +++ /dev/null @@ -1,20 +0,0 @@ -* -!css/jquery.fileupload-noscript.css -!css/jquery.fileupload-ui-noscript.css -!css/jquery.fileupload-ui.css -!css/jquery.fileupload.css -!img/loading.gif -!img/progressbar.gif -!js/cors/jquery.postmessage-transport.js -!js/cors/jquery.xdr-transport.js -!js/vendor/jquery.ui.widget.js -!js/jquery.fileupload-angular.js -!js/jquery.fileupload-audio.js -!js/jquery.fileupload-image.js -!js/jquery.fileupload-jquery-ui.js -!js/jquery.fileupload-process.js -!js/jquery.fileupload-ui.js -!js/jquery.fileupload-validate.js -!js/jquery.fileupload-video.js -!js/jquery.fileupload.js -!js/jquery.iframe-transport.js diff --git a/library/blueimp_upload/CONTRIBUTING.md b/library/blueimp_upload/CONTRIBUTING.md deleted file mode 100644 index e182f9b37..000000000 --- a/library/blueimp_upload/CONTRIBUTING.md +++ /dev/null @@ -1,15 +0,0 @@ -Please follow these pull request guidelines: - -1. Update your fork to the latest upstream version. - -2. Follow the coding conventions of the original source files (indentation, spaces, brackets layout). - -3. Code changes must pass JSHint validation with the `.jshintrc` settings of this project. - -4. Code changes must pass the QUnit tests defined in the `test` folder. - -5. New features should be covered by accompanying QUnit tests. - -6. Keep your commits as atomic as possible, i.e. create a new commit for every single bug fix or feature added. - -7. Always add meaningful commit messages. diff --git a/library/blueimp_upload/LICENSE.txt b/library/blueimp_upload/LICENSE.txt deleted file mode 100644 index 87a644638..000000000 --- a/library/blueimp_upload/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright © 2010 Sebastian Tschan, https://blueimp.net - -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. diff --git a/library/blueimp_upload/README.md b/library/blueimp_upload/README.md deleted file mode 100644 index 76bdf89d5..000000000 --- a/library/blueimp_upload/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# jQuery File Upload Plugin - -## Demo -[Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/) - -## Description -File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery. -Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads. - -## Setup -* [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup) -* [How to use only the basic plugin (minimal setup guide).](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin) - -## Features -* **Multiple file upload:** - Allows to select multiple files at once and upload them simultaneously. -* **Drag & Drop support:** - Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window. -* **Upload progress bar:** - Shows a progress bar indicating the upload progress for individual files and for all uploads combined. -* **Cancelable uploads:** - Individual file uploads can be canceled to stop the upload progress. -* **Resumable uploads:** - Aborted uploads can be resumed with browsers supporting the Blob API. -* **Chunked uploads:** - Large files can be uploaded in smaller chunks with browsers supporting the Blob API. -* **Client-side image resizing:** - Images can be automatically resized on client-side with browsers supporting the required JS APIs. -* **Preview images, audio and video:** - A preview of image, audio and video files can be displayed before uploading with browsers supporting the required APIs. -* **No browser plugins (e.g. Adobe Flash) required:** - The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins. -* **Graceful fallback for legacy browsers:** - Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers. -* **HTML file upload form fallback:** - Allows progressive enhancement by using a standard HTML file upload form as widget element. -* **Cross-site file uploads:** - Supports uploading files to a different domain with cross-site XMLHttpRequests or iframe redirects. -* **Multiple plugin instances:** - Allows to use multiple plugin instances on the same webpage. -* **Customizable and extensible:** - Provides an API to set individual options and define callback methods for various upload events. -* **Multipart and file contents stream uploads:** - Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload). -* **Compatible with any server-side application platform:** - Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads. - -## Requirements - -### Mandatory requirements -* [jQuery](https://jquery.com/) v. 1.6+ -* [jQuery UI widget factory](https://api.jqueryui.com/jQuery.widget/) v. 1.9+ (included): Required for the basic File Upload plugin, but very lightweight without any other dependencies from the jQuery UI suite. -* [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) (included): Required for [browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support). - -### Optional requirements -* [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates) v. 2.5.4+: Used to render the selected and uploaded files for the Basic Plus UI and jQuery UI versions. -* [JavaScript Load Image library](https://github.com/blueimp/JavaScript-Load-Image) v. 1.13.0+: Required for the image previews and resizing functionality. -* [JavaScript Canvas to Blob polyfill](https://github.com/blueimp/JavaScript-Canvas-to-Blob) v. 2.1.1+:Required for the image previews and resizing functionality. -* [blueimp Gallery](https://github.com/blueimp/Gallery) v. 2.15.1+: Used to display the uploaded images in a lightbox. -* [Bootstrap](http://getbootstrap.com/) v. 3.2.0+ -* [Glyphicons](http://glyphicons.com/) - -The user interface of all versions, except the jQuery UI version, is built with [Bootstrap](http://getbootstrap.com/) and icons from [Glyphicons](http://glyphicons.com/). - -### Cross-domain requirements -[Cross-domain File Uploads](https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads) using the [Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) require a redirect back to the origin server to retrieve the upload results. The [example implementation](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/main.js) makes use of [result.html](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/result.html) as a static redirect page for the origin server. - -The repository also includes the [jQuery XDomainRequest Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/cors/jquery.xdr-transport.js), which enables limited cross-domain AJAX requests in Microsoft Internet Explorer 8 and 9 (IE 10 supports cross-domain XHR requests). -The XDomainRequest object allows GET and POST requests only and doesn't support file uploads. It is used on the [Demo](https://blueimp.github.io/jQuery-File-Upload/) to delete uploaded files from the cross-domain demo file upload service. - -### Custom Backends - -You can add support for various backends by adhering to the specification [outlined here](https://github.com/blueimp/jQuery-File-Upload/wiki/JSON-Response). - -## Browsers - -### Desktop browsers -The File Upload plugin is regularly tested with the latest browser versions and supports the following minimal versions: - -* Google Chrome -* Apple Safari 4.0+ -* Mozilla Firefox 3.0+ -* Opera 11.0+ -* Microsoft Internet Explorer 6.0+ - -### Mobile browsers -The File Upload plugin has been tested with and supports the following mobile browsers: - -* Apple Safari on iOS 6.0+ -* Google Chrome on iOS 6.0+ -* Google Chrome on Android 4.0+ -* Default Browser on Android 2.3+ -* Opera Mobile 12.0+ - -### Supported features -For a detailed overview of the features supported by each browser version, please have a look at the [Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support). - -## Contributing -**Bug fixes** and **new features** can be proposed using [pull requests](https://github.com/blueimp/jQuery-File-Upload/pulls). -Please read the [contribution guidelines](https://github.com/blueimp/jQuery-File-Upload/blob/master/CONTRIBUTING.md) before submitting a pull request. - -## Support -This project is actively maintained, but there is no official support channel. -If you have a question that another developer might help you with, please post to [Stack Overflow](http://stackoverflow.com/questions/tagged/blueimp+jquery+file-upload) and tag your question with `blueimp jquery file upload`. - -## License -Released under the [MIT license](https://opensource.org/licenses/MIT). diff --git a/library/blueimp_upload/angularjs.html b/library/blueimp_upload/angularjs.html deleted file mode 100644 index 2051bbf79..000000000 --- a/library/blueimp_upload/angularjs.html +++ /dev/null @@ -1,211 +0,0 @@ -<!DOCTYPE HTML> -<!-- -/* - * jQuery File Upload Plugin AngularJS Demo - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ ---> -<html lang="en"> -<head> -<!-- Force latest IE rendering engine or ChromeFrame if installed --> -<!--[if IE]> -<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> -<![endif]--> -<meta charset="utf-8"> -<title>jQuery File Upload Demo - AngularJS version</title> -<meta name="description" content="File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for AngularJS. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads."> -<meta name="viewport" content="width=device-width, initial-scale=1.0"> -<!-- Bootstrap styles --> -<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> -<!-- Generic page styles --> -<link rel="stylesheet" href="css/style.css"> -<!-- blueimp Gallery styles --> -<link rel="stylesheet" href="https://blueimp.github.io/Gallery/css/blueimp-gallery.min.css"> -<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars --> -<link rel="stylesheet" href="css/jquery.fileupload.css"> -<link rel="stylesheet" href="css/jquery.fileupload-ui.css"> -<!-- CSS adjustments for browsers with JavaScript disabled --> -<noscript><link rel="stylesheet" href="css/jquery.fileupload-noscript.css"></noscript> -<noscript><link rel="stylesheet" href="css/jquery.fileupload-ui-noscript.css"></noscript> -<style> -/* Hide Angular JS elements before initializing */ -.ng-cloak { - display: none; -} -</style> -</head> -<body> -<div class="navbar navbar-default navbar-fixed-top"> - <div class="container"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-fixed-top .navbar-collapse"> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - <a class="navbar-brand" href="https://github.com/blueimp/jQuery-File-Upload">jQuery File Upload</a> - </div> - <div class="navbar-collapse collapse"> - <ul class="nav navbar-nav"> - <li><a href="https://github.com/blueimp/jQuery-File-Upload/tags">Download</a></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload">Source Code</a></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload/wiki">Documentation</a></li> - <li><a href="https://blueimp.net">© Sebastian Tschan</a></li> - </ul> - </div> - </div> -</div> -<div class="container"> - <h1>jQuery File Upload Demo</h1> - <h2 class="lead">AngularJS version</h2> - <ul class="nav nav-tabs"> - <li><a href="basic.html">Basic</a></li> - <li><a href="basic-plus.html">Basic Plus</a></li> - <li><a href="index.html">Basic Plus UI</a></li> - <li class="active"><a href="angularjs.html">AngularJS</a></li> - <li><a href="jquery-ui.html">jQuery UI</a></li> - </ul> - <br> - <blockquote> - <p>File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for AngularJS.<br> - Supports cross-domain, chunked and resumable file uploads and client-side image resizing.<br> - Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.</p> - </blockquote> - <br> - <!-- The file upload form used as target for the file upload widget --> - <form id="fileupload" action="https://jquery-file-upload.appspot.com/" method="POST" enctype="multipart/form-data" data-ng-app="demo" data-ng-controller="DemoFileUploadController" data-file-upload="options" data-ng-class="{'fileupload-processing': processing() || loadingFiles}"> - <!-- Redirect browsers with JavaScript disabled to the origin page --> - <noscript><input type="hidden" name="redirect" value="https://blueimp.github.io/jQuery-File-Upload/"></noscript> - <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --> - <div class="row fileupload-buttonbar"> - <div class="col-lg-7"> - <!-- The fileinput-button span is used to style the file input field as button --> - <span class="btn btn-success fileinput-button" ng-class="{disabled: disabled}"> - <i class="glyphicon glyphicon-plus"></i> - <span>Add files...</span> - <input type="file" name="files[]" multiple ng-disabled="disabled"> - </span> - <button type="button" class="btn btn-primary start" data-ng-click="submit()"> - <i class="glyphicon glyphicon-upload"></i> - <span>Start upload</span> - </button> - <button type="button" class="btn btn-warning cancel" data-ng-click="cancel()"> - <i class="glyphicon glyphicon-ban-circle"></i> - <span>Cancel upload</span> - </button> - <!-- The global file processing state --> - <span class="fileupload-process"></span> - </div> - <!-- The global progress state --> - <div class="col-lg-5 fade" data-ng-class="{in: active()}"> - <!-- The global progress bar --> - <div class="progress progress-striped active" data-file-upload-progress="progress()"><div class="progress-bar progress-bar-success" data-ng-style="{width: num + '%'}"></div></div> - <!-- The extended global progress state --> - <div class="progress-extended"> </div> - </div> - </div> - <!-- The table listing the files available for upload/download --> - <table class="table table-striped files ng-cloak"> - <tr data-ng-repeat="file in queue" data-ng-class="{'processing': file.$processing()}"> - <td data-ng-switch data-on="!!file.thumbnailUrl"> - <div class="preview" data-ng-switch-when="true"> - <a data-ng-href="{{file.url}}" title="{{file.name}}" download="{{file.name}}" data-gallery><img data-ng-src="{{file.thumbnailUrl}}" alt=""></a> - </div> - <div class="preview" data-ng-switch-default data-file-upload-preview="file"></div> - </td> - <td> - <p class="name" data-ng-switch data-on="!!file.url"> - <span data-ng-switch-when="true" data-ng-switch data-on="!!file.thumbnailUrl"> - <a data-ng-switch-when="true" data-ng-href="{{file.url}}" title="{{file.name}}" download="{{file.name}}" data-gallery>{{file.name}}</a> - <a data-ng-switch-default data-ng-href="{{file.url}}" title="{{file.name}}" download="{{file.name}}">{{file.name}}</a> - </span> - <span data-ng-switch-default>{{file.name}}</span> - </p> - <strong data-ng-show="file.error" class="error text-danger">{{file.error}}</strong> - </td> - <td> - <p class="size">{{file.size | formatFileSize}}</p> - <div class="progress progress-striped active fade" data-ng-class="{pending: 'in'}[file.$state()]" data-file-upload-progress="file.$progress()"><div class="progress-bar progress-bar-success" data-ng-style="{width: num + '%'}"></div></div> - </td> - <td> - <button type="button" class="btn btn-primary start" data-ng-click="file.$submit()" data-ng-hide="!file.$submit || options.autoUpload" data-ng-disabled="file.$state() == 'pending' || file.$state() == 'rejected'"> - <i class="glyphicon glyphicon-upload"></i> - <span>Start</span> - </button> - <button type="button" class="btn btn-warning cancel" data-ng-click="file.$cancel()" data-ng-hide="!file.$cancel"> - <i class="glyphicon glyphicon-ban-circle"></i> - <span>Cancel</span> - </button> - <button data-ng-controller="FileDestroyController" type="button" class="btn btn-danger destroy" data-ng-click="file.$destroy()" data-ng-hide="!file.$destroy"> - <i class="glyphicon glyphicon-trash"></i> - <span>Delete</span> - </button> - </td> - </tr> - </table> - </form> - <br> - <div class="panel panel-default"> - <div class="panel-heading"> - <h3 class="panel-title">Demo Notes</h3> - </div> - <div class="panel-body"> - <ul> - <li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li> - <li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li> - <li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li> - <li>You can <strong>drag & drop</strong> files from your desktop on this webpage (see <a href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support">Browser support</a>).</li> - <li>Please refer to the <a href="https://github.com/blueimp/jQuery-File-Upload">project website</a> and <a href="https://github.com/blueimp/jQuery-File-Upload/wiki">documentation</a> for more information.</li> - <li>Built with the <a href="http://getbootstrap.com/">Bootstrap</a> CSS framework and Icons from <a href="http://glyphicons.com/">Glyphicons</a>.</li> - </ul> - </div> - </div> -</div> -<!-- The blueimp Gallery widget --> -<div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=":even"> - <div class="slides"></div> - <h3 class="title"></h3> - <a class="prev">‹</a> - <a class="next">›</a> - <a class="close">×</a> - <a class="play-pause"></a> - <ol class="indicator"></ol> -</div> -<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> -<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script> -<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included --> -<script src="js/vendor/jquery.ui.widget.js"></script> -<!-- The Load Image plugin is included for the preview images and image resizing functionality --> -<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script> -<!-- The Canvas to Blob plugin is included for image resizing functionality --> -<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script> -<!-- Bootstrap JS is not required, but included for the responsive demo navigation --> -<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> -<!-- blueimp Gallery script --> -<script src="https://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script> -<!-- The Iframe Transport is required for browsers without support for XHR file uploads --> -<script src="js/jquery.iframe-transport.js"></script> -<!-- The basic File Upload plugin --> -<script src="js/jquery.fileupload.js"></script> -<!-- The File Upload processing plugin --> -<script src="js/jquery.fileupload-process.js"></script> -<!-- The File Upload image preview & resize plugin --> -<script src="js/jquery.fileupload-image.js"></script> -<!-- The File Upload audio preview plugin --> -<script src="js/jquery.fileupload-audio.js"></script> -<!-- The File Upload video preview plugin --> -<script src="js/jquery.fileupload-video.js"></script> -<!-- The File Upload validation plugin --> -<script src="js/jquery.fileupload-validate.js"></script> -<!-- The File Upload Angular JS module --> -<script src="js/jquery.fileupload-angular.js"></script> -<!-- The main application script --> -<script src="js/app.js"></script> -</body> -</html> diff --git a/library/blueimp_upload/basic-plus.html b/library/blueimp_upload/basic-plus.html deleted file mode 100644 index acee24843..000000000 --- a/library/blueimp_upload/basic-plus.html +++ /dev/null @@ -1,226 +0,0 @@ -<!DOCTYPE HTML> -<!-- -/* - * jQuery File Upload Plugin Basic Plus Demo - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ ---> -<html lang="en"> -<head> -<!-- Force latest IE rendering engine or ChromeFrame if installed --> -<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><![endif]--> -<meta charset="utf-8"> -<title>jQuery File Upload Demo - Basic Plus version</title> -<meta name="description" content="File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads."> -<meta name="viewport" content="width=device-width, initial-scale=1.0"> -<!-- Bootstrap styles --> -<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> -<!-- Generic page styles --> -<link rel="stylesheet" href="css/style.css"> -<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars --> -<link rel="stylesheet" href="css/jquery.fileupload.css"> -</head> -<body> -<div class="navbar navbar-default navbar-fixed-top"> - <div class="container"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-fixed-top .navbar-collapse"> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - <a class="navbar-brand" href="https://github.com/blueimp/jQuery-File-Upload">jQuery File Upload</a> - </div> - <div class="navbar-collapse collapse"> - <ul class="nav navbar-nav"> - <li><a href="https://github.com/blueimp/jQuery-File-Upload/tags">Download</a></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload">Source Code</a></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload/wiki">Documentation</a></li> - <li><a href="https://blueimp.net">© Sebastian Tschan</a></li> - </ul> - </div> - </div> -</div> -<div class="container"> - <h1>jQuery File Upload Demo</h1> - <h2 class="lead">Basic Plus version</h2> - <ul class="nav nav-tabs"> - <li><a href="basic.html">Basic</a></li> - <li class="active"><a href="basic-plus.html">Basic Plus</a></li> - <li><a href="index.html">Basic Plus UI</a></li> - <li><a href="angularjs.html">AngularJS</a></li> - <li><a href="jquery-ui.html">jQuery UI</a></li> - </ul> - <br> - <blockquote> - <p>File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery.<br> - Supports cross-domain, chunked and resumable file uploads and client-side image resizing.<br> - Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.</p> - </blockquote> - <br> - <!-- The fileinput-button span is used to style the file input field as button --> - <span class="btn btn-success fileinput-button"> - <i class="glyphicon glyphicon-plus"></i> - <span>Add files...</span> - <!-- The file input field used as target for the file upload widget --> - <input id="fileupload" type="file" name="files[]" multiple> - </span> - <br> - <br> - <!-- The global progress bar --> - <div id="progress" class="progress"> - <div class="progress-bar progress-bar-success"></div> - </div> - <!-- The container for the uploaded files --> - <div id="files" class="files"></div> - <br> - <div class="panel panel-default"> - <div class="panel-heading"> - <h3 class="panel-title">Demo Notes</h3> - </div> - <div class="panel-body"> - <ul> - <li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li> - <li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li> - <li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li> - <li>You can <strong>drag & drop</strong> files from your desktop on this webpage (see <a href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support">Browser support</a>).</li> - <li>Please refer to the <a href="https://github.com/blueimp/jQuery-File-Upload">project website</a> and <a href="https://github.com/blueimp/jQuery-File-Upload/wiki">documentation</a> for more information.</li> - <li>Built with the <a href="http://getbootstrap.com/">Bootstrap</a> CSS framework and Icons from <a href="http://glyphicons.com/">Glyphicons</a>.</li> - </ul> - </div> - </div> -</div> -<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> -<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included --> -<script src="js/vendor/jquery.ui.widget.js"></script> -<!-- The Load Image plugin is included for the preview images and image resizing functionality --> -<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script> -<!-- The Canvas to Blob plugin is included for image resizing functionality --> -<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script> -<!-- Bootstrap JS is not required, but included for the responsive demo navigation --> -<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> -<!-- The Iframe Transport is required for browsers without support for XHR file uploads --> -<script src="js/jquery.iframe-transport.js"></script> -<!-- The basic File Upload plugin --> -<script src="js/jquery.fileupload.js"></script> -<!-- The File Upload processing plugin --> -<script src="js/jquery.fileupload-process.js"></script> -<!-- The File Upload image preview & resize plugin --> -<script src="js/jquery.fileupload-image.js"></script> -<!-- The File Upload audio preview plugin --> -<script src="js/jquery.fileupload-audio.js"></script> -<!-- The File Upload video preview plugin --> -<script src="js/jquery.fileupload-video.js"></script> -<!-- The File Upload validation plugin --> -<script src="js/jquery.fileupload-validate.js"></script> -<script> -/*jslint unparam: true, regexp: true */ -/*global window, $ */ -$(function () { - 'use strict'; - // Change this to the location of your server-side upload handler: - var url = window.location.hostname === 'blueimp.github.io' ? - '//jquery-file-upload.appspot.com/' : 'server/php/', - uploadButton = $('<button/>') - .addClass('btn btn-primary') - .prop('disabled', true) - .text('Processing...') - .on('click', function () { - var $this = $(this), - data = $this.data(); - $this - .off('click') - .text('Abort') - .on('click', function () { - $this.remove(); - data.abort(); - }); - data.submit().always(function () { - $this.remove(); - }); - }); - $('#fileupload').fileupload({ - url: url, - dataType: 'json', - autoUpload: false, - acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, - maxFileSize: 999000, - // Enable image resizing, except for Android and Opera, - // which actually support image resizing, but fail to - // send Blob objects via XHR requests: - disableImageResize: /Android(?!.*Chrome)|Opera/ - .test(window.navigator.userAgent), - previewMaxWidth: 100, - previewMaxHeight: 100, - previewCrop: true - }).on('fileuploadadd', function (e, data) { - data.context = $('<div/>').appendTo('#files'); - $.each(data.files, function (index, file) { - var node = $('<p/>') - .append($('<span/>').text(file.name)); - if (!index) { - node - .append('<br>') - .append(uploadButton.clone(true).data(data)); - } - node.appendTo(data.context); - }); - }).on('fileuploadprocessalways', function (e, data) { - var index = data.index, - file = data.files[index], - node = $(data.context.children()[index]); - if (file.preview) { - node - .prepend('<br>') - .prepend(file.preview); - } - if (file.error) { - node - .append('<br>') - .append($('<span class="text-danger"/>').text(file.error)); - } - if (index + 1 === data.files.length) { - data.context.find('button') - .text('Upload') - .prop('disabled', !!data.files.error); - } - }).on('fileuploadprogressall', function (e, data) { - var progress = parseInt(data.loaded / data.total * 100, 10); - $('#progress .progress-bar').css( - 'width', - progress + '%' - ); - }).on('fileuploaddone', function (e, data) { - $.each(data.result.files, function (index, file) { - if (file.url) { - var link = $('<a>') - .attr('target', '_blank') - .prop('href', file.url); - $(data.context.children()[index]) - .wrap(link); - } else if (file.error) { - var error = $('<span class="text-danger"/>').text(file.error); - $(data.context.children()[index]) - .append('<br>') - .append(error); - } - }); - }).on('fileuploadfail', function (e, data) { - $.each(data.files, function (index) { - var error = $('<span class="text-danger"/>').text('File upload failed.'); - $(data.context.children()[index]) - .append('<br>') - .append(error); - }); - }).prop('disabled', !$.support.fileInput) - .parent().addClass($.support.fileInput ? undefined : 'disabled'); -}); -</script> -</body> -</html> diff --git a/library/blueimp_upload/basic.html b/library/blueimp_upload/basic.html deleted file mode 100644 index 232a24624..000000000 --- a/library/blueimp_upload/basic.html +++ /dev/null @@ -1,136 +0,0 @@ -<!DOCTYPE HTML> -<!-- -/* - * jQuery File Upload Plugin Basic Demo - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ ---> -<html lang="en"> -<head> -<!-- Force latest IE rendering engine or ChromeFrame if installed --> -<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><![endif]--> -<meta charset="utf-8"> -<title>jQuery File Upload Demo - Basic version</title> -<meta name="description" content="File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads."> -<meta name="viewport" content="width=device-width, initial-scale=1.0"> -<!-- Bootstrap styles --> -<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> -<!-- Generic page styles --> -<link rel="stylesheet" href="css/style.css"> -<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars --> -<link rel="stylesheet" href="css/jquery.fileupload.css"> -</head> -<body> -<div class="navbar navbar-default navbar-fixed-top"> - <div class="container"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-fixed-top .navbar-collapse"> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - <a class="navbar-brand" href="https://github.com/blueimp/jQuery-File-Upload">jQuery File Upload</a> - </div> - <div class="navbar-collapse collapse"> - <ul class="nav navbar-nav"> - <li><a href="https://github.com/blueimp/jQuery-File-Upload/tags">Download</a></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload">Source Code</a></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload/wiki">Documentation</a></li> - <li><a href="https://blueimp.net">© Sebastian Tschan</a></li> - </ul> - </div> - </div> -</div> -<div class="container"> - <h1>jQuery File Upload Demo</h1> - <h2 class="lead">Basic version</h2> - <ul class="nav nav-tabs"> - <li class="active"><a href="basic.html">Basic</a></li> - <li><a href="basic-plus.html">Basic Plus</a></li> - <li><a href="index.html">Basic Plus UI</a></li> - <li><a href="angularjs.html">AngularJS</a></li> - <li><a href="jquery-ui.html">jQuery UI</a></li> - </ul> - <br> - <blockquote> - <p>File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery.<br> - Supports cross-domain, chunked and resumable file uploads.<br> - Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.</p> - </blockquote> - <br> - <!-- The fileinput-button span is used to style the file input field as button --> - <span class="btn btn-success fileinput-button"> - <i class="glyphicon glyphicon-plus"></i> - <span>Select files...</span> - <!-- The file input field used as target for the file upload widget --> - <input id="fileupload" type="file" name="files[]" multiple> - </span> - <br> - <br> - <!-- The global progress bar --> - <div id="progress" class="progress"> - <div class="progress-bar progress-bar-success"></div> - </div> - <!-- The container for the uploaded files --> - <div id="files" class="files"></div> - <br> - <div class="panel panel-default"> - <div class="panel-heading"> - <h3 class="panel-title">Demo Notes</h3> - </div> - <div class="panel-body"> - <ul> - <li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li> - <li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li> - <li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li> - <li>You can <strong>drag & drop</strong> files from your desktop on this webpage (see <a href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support">Browser support</a>).</li> - <li>Please refer to the <a href="https://github.com/blueimp/jQuery-File-Upload">project website</a> and <a href="https://github.com/blueimp/jQuery-File-Upload/wiki">documentation</a> for more information.</li> - <li>Built with the <a href="http://getbootstrap.com/">Bootstrap</a> CSS framework and Icons from <a href="http://glyphicons.com/">Glyphicons</a>.</li> - </ul> - </div> - </div> -</div> -<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> -<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included --> -<script src="js/vendor/jquery.ui.widget.js"></script> -<!-- The Iframe Transport is required for browsers without support for XHR file uploads --> -<script src="js/jquery.iframe-transport.js"></script> -<!-- The basic File Upload plugin --> -<script src="js/jquery.fileupload.js"></script> -<!-- Bootstrap JS is not required, but included for the responsive demo navigation --> -<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> -<script> -/*jslint unparam: true */ -/*global window, $ */ -$(function () { - 'use strict'; - // Change this to the location of your server-side upload handler: - var url = window.location.hostname === 'blueimp.github.io' ? - '//jquery-file-upload.appspot.com/' : 'server/php/'; - $('#fileupload').fileupload({ - url: url, - dataType: 'json', - done: function (e, data) { - $.each(data.result.files, function (index, file) { - $('<p/>').text(file.name).appendTo('#files'); - }); - }, - progressall: function (e, data) { - var progress = parseInt(data.loaded / data.total * 100, 10); - $('#progress .progress-bar').css( - 'width', - progress + '%' - ); - } - }).prop('disabled', !$.support.fileInput) - .parent().addClass($.support.fileInput ? undefined : 'disabled'); -}); -</script> -</body> -</html> diff --git a/library/blueimp_upload/bower-version-update.js b/library/blueimp_upload/bower-version-update.js deleted file mode 100755 index 09ce3927e..000000000 --- a/library/blueimp_upload/bower-version-update.js +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -var path = require('path'); -var packageJSON = require(path.join(__dirname, 'package.json')); -var bowerFile = path.join(__dirname, 'bower.json'); -var bowerJSON = require('bower-json').parse( - require(bowerFile), - {normalize: true} -); -bowerJSON.version = packageJSON.version; -require('fs').writeFileSync( - bowerFile, - JSON.stringify(bowerJSON, null, 2) + '\n' -); diff --git a/library/blueimp_upload/bower.json b/library/blueimp_upload/bower.json deleted file mode 100644 index 4f4cd8adb..000000000 --- a/library/blueimp_upload/bower.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "name": "blueimp-file-upload", - "version": "9.23.0", - "title": "jQuery File Upload", - "description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images.", - "keywords": [ - "jquery", - "file", - "upload", - "widget", - "multiple", - "selection", - "drag", - "drop", - "progress", - "preview", - "cross-domain", - "cross-site", - "chunk", - "resume", - "gae", - "go", - "python", - "php", - "bootstrap" - ], - "homepage": "https://github.com/blueimp/jQuery-File-Upload", - "author": { - "name": "Sebastian Tschan", - "url": "https://blueimp.net" - }, - "maintainers": [ - { - "name": "Sebastian Tschan", - "url": "https://blueimp.net" - } - ], - "repository": { - "type": "git", - "url": "git://github.com/blueimp/jQuery-File-Upload.git" - }, - "bugs": "https://github.com/blueimp/jQuery-File-Upload/issues", - "license": "MIT", - "dependencies": { - "jquery": ">=1.6", - "blueimp-tmpl": ">=2.5.4", - "blueimp-load-image": ">=1.13.0", - "blueimp-canvas-to-blob": ">=2.1.1" - }, - "main": [ - "js/jquery.fileupload.js" - ], - "ignore": [ - "/*.*", - "/cors", - "css/jquery-ui-demo-ie8.css", - "css/jquery-ui-demo.css", - "css/style.css", - "js/app.js", - "js/main.js", - "server", - "test" - ] -} diff --git a/library/blueimp_upload/cors/postmessage.html b/library/blueimp_upload/cors/postmessage.html deleted file mode 100644 index 6a56cf0b6..000000000 --- a/library/blueimp_upload/cors/postmessage.html +++ /dev/null @@ -1,75 +0,0 @@ -<!DOCTYPE HTML> -<!-- -/* - * jQuery File Upload Plugin postMessage API - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ ---> -<html lang="en"> -<head> -<meta charset="utf-8"> -<title>jQuery File Upload Plugin postMessage API</title> -<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> -</head> -<body> -<script> -/*jslint unparam: true, regexp: true */ -/*global $, Blob, FormData, location */ -'use strict'; -var origin = /^http:\/\/example.org/, - target = new RegExp('^(http(s)?:)?\\/\\/' + location.host + '\\/'); -$(window).on('message', function (e) { - e = e.originalEvent; - var s = e.data, - xhr = $.ajaxSettings.xhr(), - f; - if (!origin.test(e.origin)) { - throw new Error('Origin "' + e.origin + '" does not match ' + origin); - } - if (!target.test(e.data.url)) { - throw new Error('Target "' + e.data.url + '" does not match ' + target); - } - $(xhr.upload).on('progress', function (ev) { - ev = ev.originalEvent; - e.source.postMessage({ - id: s.id, - type: ev.type, - timeStamp: ev.timeStamp, - lengthComputable: ev.lengthComputable, - loaded: ev.loaded, - total: ev.total - }, e.origin); - }); - s.xhr = function () { - return xhr; - }; - if (!(s.data instanceof Blob)) { - f = new FormData(); - $.each(s.data, function (i, v) { - f.append(v.name, v.value); - }); - s.data = f; - } - $.ajax(s).always(function (result, statusText, jqXHR) { - if (!jqXHR.done) { - jqXHR = result; - result = null; - } - e.source.postMessage({ - id: s.id, - status: jqXHR.status, - statusText: statusText, - result: result, - headers: jqXHR.getAllResponseHeaders() - }, e.origin); - }); -}); -</script> -</body> -</html> diff --git a/library/blueimp_upload/cors/result.html b/library/blueimp_upload/cors/result.html deleted file mode 100644 index e3d629814..000000000 --- a/library/blueimp_upload/cors/result.html +++ /dev/null @@ -1,24 +0,0 @@ -<!DOCTYPE HTML> -<!-- -/* - * jQuery Iframe Transport Plugin Redirect Page - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ ---> -<html lang="en"> -<head> -<meta charset="utf-8"> -<title>jQuery Iframe Transport Plugin Redirect Page</title> -</head> -<body> -<script> -document.body.innerText=document.body.textContent=decodeURIComponent(window.location.search.slice(1)); -</script> -</body> -</html> diff --git a/library/blueimp_upload/css/jquery-ui-demo-ie8.css b/library/blueimp_upload/css/jquery-ui-demo-ie8.css deleted file mode 100644 index e0e8ea9b0..000000000 --- a/library/blueimp_upload/css/jquery-ui-demo-ie8.css +++ /dev/null @@ -1,21 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload Demo CSS Fixes for IE<9 - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -.navigation { - list-style: none; - padding: 0; - margin: 1em 0; -} -.navigation li { - display: inline; - margin-right: 10px; -} diff --git a/library/blueimp_upload/css/jquery-ui-demo.css b/library/blueimp_upload/css/jquery-ui-demo.css deleted file mode 100644 index d7d524df5..000000000 --- a/library/blueimp_upload/css/jquery-ui-demo.css +++ /dev/null @@ -1,67 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload Demo CSS - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -body { - max-width: 750px; - margin: 0 auto; - padding: 1em; - font-family: "Lucida Grande", "Lucida Sans Unicode", Arial, sans-serif; - font-size: 1em; - line-height: 1.4em; - background: #222; - color: #fff; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -a { - color: orange; - text-decoration: none; -} -img { - border: 0; - vertical-align: middle; -} -h1 { - line-height: 1em; -} -blockquote { - padding: 0 0 0 15px; - margin: 0 0 20px; - border-left: 5px solid #eee; -} -table { - width: 100%; - margin: 10px 0; -} - -.fileupload-progress { - margin: 10px 0; -} -.fileupload-progress .progress-extended { - margin-top: 5px; -} -.error { - color: red; -} - -@media (min-width: 481px) { - .navigation { - list-style: none; - padding: 0; - } - .navigation li { - display: inline-block; - } - .navigation li:not(:first-child):before { - content: "| "; - } -} diff --git a/library/blueimp_upload/css/jquery.fileupload-noscript.css b/library/blueimp_upload/css/jquery.fileupload-noscript.css deleted file mode 100644 index 2409bfb0a..000000000 --- a/library/blueimp_upload/css/jquery.fileupload-noscript.css +++ /dev/null @@ -1,22 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload Plugin NoScript CSS - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -.fileinput-button input { - position: static; - opacity: 1; - filter: none; - font-size: inherit !important; - direction: inherit; -} -.fileinput-button span { - display: none; -} diff --git a/library/blueimp_upload/css/jquery.fileupload-ui-noscript.css b/library/blueimp_upload/css/jquery.fileupload-ui-noscript.css deleted file mode 100644 index 30651acf0..000000000 --- a/library/blueimp_upload/css/jquery.fileupload-ui-noscript.css +++ /dev/null @@ -1,17 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload UI Plugin NoScript CSS - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2012, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -.fileinput-button i, -.fileupload-buttonbar .delete, -.fileupload-buttonbar .toggle { - display: none; -} diff --git a/library/blueimp_upload/css/jquery.fileupload-ui.css b/library/blueimp_upload/css/jquery.fileupload-ui.css deleted file mode 100644 index 9e36c42c5..000000000 --- a/library/blueimp_upload/css/jquery.fileupload-ui.css +++ /dev/null @@ -1,57 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload UI Plugin CSS - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -.fileupload-buttonbar .btn, -.fileupload-buttonbar .toggle { - margin-bottom: 5px; -} -.progress-animated .progress-bar, -.progress-animated .bar { - background: url("../img/progressbar.gif") !important; - filter: none; -} -.fileupload-process { - float: right; - display: none; -} -.fileupload-processing .fileupload-process, -.files .processing .preview { - display: block; - width: 32px; - height: 32px; - background: url("../img/loading.gif") center no-repeat; - background-size: contain; -} -.files audio, -.files video { - max-width: 300px; -} - -@media (max-width: 767px) { - .fileupload-buttonbar .toggle, - .files .toggle, - .files .btn span { - display: none; - } - .files .name { - width: 80px; - word-wrap: break-word; - } - .files audio, - .files video { - max-width: 80px; - } - .files img, - .files canvas { - max-width: 100%; - } -} diff --git a/library/blueimp_upload/css/jquery.fileupload.css b/library/blueimp_upload/css/jquery.fileupload.css deleted file mode 100644 index 8ae3b09d4..000000000 --- a/library/blueimp_upload/css/jquery.fileupload.css +++ /dev/null @@ -1,37 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload Plugin CSS - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -.fileinput-button { - position: relative; - overflow: hidden; - display: inline-block; -} -.fileinput-button input { - position: absolute; - top: 0; - right: 0; - margin: 0; - opacity: 0; - -ms-filter: 'alpha(opacity=0)'; - font-size: 200px !important; - direction: ltr; - cursor: pointer; -} - -/* Fixes for IE < 8 */ -@media screen\9 { - .fileinput-button input { - filter: alpha(opacity=0); - font-size: 100%; - height: 100%; - } -} diff --git a/library/blueimp_upload/css/style.css b/library/blueimp_upload/css/style.css deleted file mode 100644 index 3aee25689..000000000 --- a/library/blueimp_upload/css/style.css +++ /dev/null @@ -1,15 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload Plugin CSS Example - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -body { - padding-top: 60px; -} diff --git a/library/blueimp_upload/img/loading.gif b/library/blueimp_upload/img/loading.gif Binary files differdeleted file mode 100644 index 90f28cbdb..000000000 --- a/library/blueimp_upload/img/loading.gif +++ /dev/null diff --git a/library/blueimp_upload/img/progressbar.gif b/library/blueimp_upload/img/progressbar.gif Binary files differdeleted file mode 100644 index fbcce6bc9..000000000 --- a/library/blueimp_upload/img/progressbar.gif +++ /dev/null diff --git a/library/blueimp_upload/index.html b/library/blueimp_upload/index.html deleted file mode 100644 index c8c66ad8b..000000000 --- a/library/blueimp_upload/index.html +++ /dev/null @@ -1,255 +0,0 @@ -<!DOCTYPE HTML> -<!-- -/* - * jQuery File Upload Plugin Demo - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ ---> -<html lang="en"> -<head> -<!-- Force latest IE rendering engine or ChromeFrame if installed --> -<!--[if IE]> -<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> -<![endif]--> -<meta charset="utf-8"> -<title>jQuery File Upload Demo</title> -<meta name="description" content="File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads."> -<meta name="viewport" content="width=device-width, initial-scale=1.0"> -<!-- Bootstrap styles --> -<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> -<!-- Generic page styles --> -<link rel="stylesheet" href="css/style.css"> -<!-- blueimp Gallery styles --> -<link rel="stylesheet" href="https://blueimp.github.io/Gallery/css/blueimp-gallery.min.css"> -<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars --> -<link rel="stylesheet" href="css/jquery.fileupload.css"> -<link rel="stylesheet" href="css/jquery.fileupload-ui.css"> -<!-- CSS adjustments for browsers with JavaScript disabled --> -<noscript><link rel="stylesheet" href="css/jquery.fileupload-noscript.css"></noscript> -<noscript><link rel="stylesheet" href="css/jquery.fileupload-ui-noscript.css"></noscript> -</head> -<body> -<div class="navbar navbar-default navbar-fixed-top"> - <div class="container"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-fixed-top .navbar-collapse"> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - <a class="navbar-brand" href="https://github.com/blueimp/jQuery-File-Upload">jQuery File Upload</a> - </div> - <div class="navbar-collapse collapse"> - <ul class="nav navbar-nav"> - <li><a href="https://github.com/blueimp/jQuery-File-Upload/tags">Download</a></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload">Source Code</a></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload/wiki">Documentation</a></li> - <li><a href="https://blueimp.net">© Sebastian Tschan</a></li> - </ul> - </div> - </div> -</div> -<div class="container"> - <h1>jQuery File Upload Demo</h1> - <h2 class="lead">Basic Plus UI version</h2> - <ul class="nav nav-tabs"> - <li><a href="basic.html">Basic</a></li> - <li><a href="basic-plus.html">Basic Plus</a></li> - <li class="active"><a href="index.html">Basic Plus UI</a></li> - <li><a href="angularjs.html">AngularJS</a></li> - <li><a href="jquery-ui.html">jQuery UI</a></li> - </ul> - <br> - <blockquote> - <p>File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery.<br> - Supports cross-domain, chunked and resumable file uploads and client-side image resizing.<br> - Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.</p> - </blockquote> - <br> - <!-- The file upload form used as target for the file upload widget --> - <form id="fileupload" action="https://jquery-file-upload.appspot.com/" method="POST" enctype="multipart/form-data"> - <!-- Redirect browsers with JavaScript disabled to the origin page --> - <noscript><input type="hidden" name="redirect" value="https://blueimp.github.io/jQuery-File-Upload/"></noscript> - <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --> - <div class="row fileupload-buttonbar"> - <div class="col-lg-7"> - <!-- The fileinput-button span is used to style the file input field as button --> - <span class="btn btn-success fileinput-button"> - <i class="glyphicon glyphicon-plus"></i> - <span>Add files...</span> - <input type="file" name="files[]" multiple> - </span> - <button type="submit" class="btn btn-primary start"> - <i class="glyphicon glyphicon-upload"></i> - <span>Start upload</span> - </button> - <button type="reset" class="btn btn-warning cancel"> - <i class="glyphicon glyphicon-ban-circle"></i> - <span>Cancel upload</span> - </button> - <button type="button" class="btn btn-danger delete"> - <i class="glyphicon glyphicon-trash"></i> - <span>Delete</span> - </button> - <input type="checkbox" class="toggle"> - <!-- The global file processing state --> - <span class="fileupload-process"></span> - </div> - <!-- The global progress state --> - <div class="col-lg-5 fileupload-progress fade"> - <!-- The global progress bar --> - <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100"> - <div class="progress-bar progress-bar-success" style="width:0%;"></div> - </div> - <!-- The extended global progress state --> - <div class="progress-extended"> </div> - </div> - </div> - <!-- The table listing the files available for upload/download --> - <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table> - </form> - <br> - <div class="panel panel-default"> - <div class="panel-heading"> - <h3 class="panel-title">Demo Notes</h3> - </div> - <div class="panel-body"> - <ul> - <li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li> - <li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li> - <li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li> - <li>You can <strong>drag & drop</strong> files from your desktop on this webpage (see <a href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support">Browser support</a>).</li> - <li>Please refer to the <a href="https://github.com/blueimp/jQuery-File-Upload">project website</a> and <a href="https://github.com/blueimp/jQuery-File-Upload/wiki">documentation</a> for more information.</li> - <li>Built with the <a href="http://getbootstrap.com/">Bootstrap</a> CSS framework and Icons from <a href="http://glyphicons.com/">Glyphicons</a>.</li> - </ul> - </div> - </div> -</div> -<!-- The blueimp Gallery widget --> -<div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=":even"> - <div class="slides"></div> - <h3 class="title"></h3> - <a class="prev">‹</a> - <a class="next">›</a> - <a class="close">×</a> - <a class="play-pause"></a> - <ol class="indicator"></ol> -</div> -<!-- The template to display files available for upload --> -<script id="template-upload" type="text/x-tmpl"> -{% for (var i=0, file; file=o.files[i]; i++) { %} - <tr class="template-upload fade"> - <td> - <span class="preview"></span> - </td> - <td> - <p class="name">{%=file.name%}</p> - <strong class="error text-danger"></strong> - </td> - <td> - <p class="size">Processing...</p> - <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div> - </td> - <td> - {% if (!i && !o.options.autoUpload) { %} - <button class="btn btn-primary start" disabled> - <i class="glyphicon glyphicon-upload"></i> - <span>Start</span> - </button> - {% } %} - {% if (!i) { %} - <button class="btn btn-warning cancel"> - <i class="glyphicon glyphicon-ban-circle"></i> - <span>Cancel</span> - </button> - {% } %} - </td> - </tr> -{% } %} -</script> -<!-- The template to display files available for download --> -<script id="template-download" type="text/x-tmpl"> -{% for (var i=0, file; file=o.files[i]; i++) { %} - <tr class="template-download fade"> - <td> - <span class="preview"> - {% if (file.thumbnailUrl) { %} - <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a> - {% } %} - </span> - </td> - <td> - <p class="name"> - {% if (file.url) { %} - <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a> - {% } else { %} - <span>{%=file.name%}</span> - {% } %} - </p> - {% if (file.error) { %} - <div><span class="label label-danger">Error</span> {%=file.error%}</div> - {% } %} - </td> - <td> - <span class="size">{%=o.formatFileSize(file.size)%}</span> - </td> - <td> - {% if (file.deleteUrl) { %} - <button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}> - <i class="glyphicon glyphicon-trash"></i> - <span>Delete</span> - </button> - <input type="checkbox" name="delete" value="1" class="toggle"> - {% } else { %} - <button class="btn btn-warning cancel"> - <i class="glyphicon glyphicon-ban-circle"></i> - <span>Cancel</span> - </button> - {% } %} - </td> - </tr> -{% } %} -</script> -<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> -<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included --> -<script src="js/vendor/jquery.ui.widget.js"></script> -<!-- The Templates plugin is included to render the upload/download listings --> -<script src="https://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script> -<!-- The Load Image plugin is included for the preview images and image resizing functionality --> -<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script> -<!-- The Canvas to Blob plugin is included for image resizing functionality --> -<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script> -<!-- Bootstrap JS is not required, but included for the responsive demo navigation --> -<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> -<!-- blueimp Gallery script --> -<script src="https://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script> -<!-- The Iframe Transport is required for browsers without support for XHR file uploads --> -<script src="js/jquery.iframe-transport.js"></script> -<!-- The basic File Upload plugin --> -<script src="js/jquery.fileupload.js"></script> -<!-- The File Upload processing plugin --> -<script src="js/jquery.fileupload-process.js"></script> -<!-- The File Upload image preview & resize plugin --> -<script src="js/jquery.fileupload-image.js"></script> -<!-- The File Upload audio preview plugin --> -<script src="js/jquery.fileupload-audio.js"></script> -<!-- The File Upload video preview plugin --> -<script src="js/jquery.fileupload-video.js"></script> -<!-- The File Upload validation plugin --> -<script src="js/jquery.fileupload-validate.js"></script> -<!-- The File Upload user interface plugin --> -<script src="js/jquery.fileupload-ui.js"></script> -<!-- The main application script --> -<script src="js/main.js"></script> -<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 --> -<!--[if (gte IE 8)&(lt IE 10)]> -<script src="js/cors/jquery.xdr-transport.js"></script> -<![endif]--> -</body> -</html> diff --git a/library/blueimp_upload/jquery-ui.html b/library/blueimp_upload/jquery-ui.html deleted file mode 100644 index 842dd4ca7..000000000 --- a/library/blueimp_upload/jquery-ui.html +++ /dev/null @@ -1,252 +0,0 @@ -<!DOCTYPE HTML> -<!-- -/* - * jQuery File Upload Plugin jQuery UI Demo - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ ---> -<html lang="en"> -<head> -<!-- Force latest IE rendering engine or ChromeFrame if installed --> -<!--[if IE]> -<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> -<![endif]--> -<meta charset="utf-8"> -<title>jQuery File Upload Demo - jQuery UI version</title> -<meta name="description" content="File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads."> -<meta name="viewport" content="width=device-width, initial-scale=1.0"> -<!-- jQuery UI styles --> -<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/dark-hive/jquery-ui.css" id="theme"> -<!-- Generic page styles --> -<link rel="stylesheet" href="css/style.css"> -<!-- Demo styles --> -<link rel="stylesheet" href="css/jquery-ui-demo.css"> -<!--[if lte IE 8]> -<link rel="stylesheet" href="css/jquery-ui-demo-ie8.css"> -<![endif]--> -<style> -/* Adjust the jQuery UI widget font-size: */ -.ui-widget { - font-size: 0.95em; -} -</style> -<!-- blueimp Gallery styles --> -<link rel="stylesheet" href="https://blueimp.github.io/Gallery/css/blueimp-gallery.min.css"> -<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars --> -<link rel="stylesheet" href="css/jquery.fileupload.css"> -<link rel="stylesheet" href="css/jquery.fileupload-ui.css"> -<!-- CSS adjustments for browsers with JavaScript disabled --> -<noscript><link rel="stylesheet" href="css/jquery.fileupload-noscript.css"></noscript> -<noscript><link rel="stylesheet" href="css/jquery.fileupload-ui-noscript.css"></noscript> -</head> -<body> -<ul class="navigation"> - <li><h3><a href="https://github.com/blueimp/jQuery-File-Upload">jQuery File Upload</a></h3></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload/tags">Download</a></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload">Source Code</a></li> - <li><a href="https://github.com/blueimp/jQuery-File-Upload/wiki">Documentation</a></li> - <li><a href="https://blueimp.net">© blueimp.net</a></li> -</ul> -<h1>jQuery File Upload Demo</h1> -<h2>jQuery UI version</h2> -<form> - <label for="theme-switcher">Theme:</label> - <select id="theme-switcher" class="pull-right"> - <option value="black-tie">Black Tie</option> - <option value="blitzer">Blitzer</option> - <option value="cupertino">Cupertino</option> - <option value="dark-hive" selected>Dark Hive</option> - <option value="dot-luv">Dot Luv</option> - <option value="eggplant">Eggplant</option> - <option value="excite-bike">Excite Bike</option> - <option value="flick">Flick</option> - <option value="hot-sneaks">Hot sneaks</option> - <option value="humanity">Humanity</option> - <option value="le-frog">Le Frog</option> - <option value="mint-choc">Mint Choc</option> - <option value="overcast">Overcast</option> - <option value="pepper-grinder">Pepper Grinder</option> - <option value="redmond">Redmond</option> - <option value="smoothness">Smoothness</option> - <option value="south-street">South Street</option> - <option value="start">Start</option> - <option value="sunny">Sunny</option> - <option value="swanky-purse">Swanky Purse</option> - <option value="trontastic">Trontastic</option> - <option value="ui-darkness">UI Darkness</option> - <option value="ui-lightness">UI Lightness</option> - <option value="vader">Vader</option> - </select> -</form> -<ul class="navigation"> - <li><a href="basic.html">Basic</a></li> - <li><a href="basic-plus.html">Basic Plus</a></li> - <li><a href="index.html">Basic Plus UI</a></li> - <li><a href="angularjs.html">AngularJS</a></li> - <li class="active"><a href="jquery-ui.html">jQuery UI</a></li> -</ul> -<blockquote> - <p>File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery UI.<br> - Supports cross-domain, chunked and resumable file uploads and client-side image resizing.<br> - Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.</p> -</blockquote> -<!-- The file upload form used as target for the file upload widget --> -<form id="fileupload" action="https://jquery-file-upload.appspot.com/" method="POST" enctype="multipart/form-data"> - <!-- Redirect browsers with JavaScript disabled to the origin page --> - <noscript><input type="hidden" name="redirect" value="https://blueimp.github.io/jQuery-File-Upload/"></noscript> - <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --> - <div class="fileupload-buttonbar"> - <div class="fileupload-buttons"> - <!-- The fileinput-button span is used to style the file input field as button --> - <span class="fileinput-button"> - <span>Add files...</span> - <input type="file" name="files[]" multiple> - </span> - <button type="submit" class="start">Start upload</button> - <button type="reset" class="cancel">Cancel upload</button> - <button type="button" class="delete">Delete</button> - <input type="checkbox" class="toggle"> - <!-- The global file processing state --> - <span class="fileupload-process"></span> - </div> - <!-- The global progress state --> - <div class="fileupload-progress fade" style="display:none"> - <!-- The global progress bar --> - <div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100"></div> - <!-- The extended global progress state --> - <div class="progress-extended"> </div> - </div> - </div> - <!-- The table listing the files available for upload/download --> - <table role="presentation"><tbody class="files"></tbody></table> -</form> -<br> -<h3>Demo Notes</h3> -<ul> - <li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li> - <li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li> - <li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li> - <li>You can <strong>drag & drop</strong> files from your desktop on this webpage (see <a href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support">Browser support</a>).</li> - <li>Please refer to the <a href="https://github.com/blueimp/jQuery-File-Upload">project website</a> and <a href="https://github.com/blueimp/jQuery-File-Upload/wiki">documentation</a> for more information.</li> - <li>Built with <a href="https://jqueryui.com">jQuery UI</a>.</li> -</ul> -<!-- The blueimp Gallery widget --> -<div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=":even"> - <div class="slides"></div> - <h3 class="title"></h3> - <a class="prev">‹</a> - <a class="next">›</a> - <a class="close">×</a> - <a class="play-pause"></a> - <ol class="indicator"></ol> -</div> -<!-- The template to display files available for upload --> -<script id="template-upload" type="text/x-tmpl"> -{% for (var i=0, file; file=o.files[i]; i++) { %} - <tr class="template-upload fade"> - <td> - <span class="preview"></span> - </td> - <td> - <p class="name">{%=file.name%}</p> - <strong class="error"></strong> - </td> - <td> - <p class="size">Processing...</p> - <div class="progress"></div> - </td> - <td> - {% if (!i && !o.options.autoUpload) { %} - <button class="start" disabled>Start</button> - {% } %} - {% if (!i) { %} - <button class="cancel">Cancel</button> - {% } %} - </td> - </tr> -{% } %} -</script> -<!-- The template to display files available for download --> -<script id="template-download" type="text/x-tmpl"> -{% for (var i=0, file; file=o.files[i]; i++) { %} - <tr class="template-download fade"> - <td> - <span class="preview"> - {% if (file.thumbnailUrl) { %} - <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a> - {% } %} - </span> - </td> - <td> - <p class="name"> - <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a> - </p> - {% if (file.error) { %} - <div><span class="error">Error</span> {%=file.error%}</div> - {% } %} - </td> - <td> - <span class="size">{%=o.formatFileSize(file.size)%}</span> - </td> - <td> - <button class="delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>Delete</button> - <input type="checkbox" name="delete" value="1" class="toggle"> - </td> - </tr> -{% } %} -</script> -<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> -<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> -<!-- The Templates plugin is included to render the upload/download listings --> -<script src="https://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script> -<!-- The Load Image plugin is included for the preview images and image resizing functionality --> -<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script> -<!-- The Canvas to Blob plugin is included for image resizing functionality --> -<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script> -<!-- blueimp Gallery script --> -<script src="https://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script> -<!-- The Iframe Transport is required for browsers without support for XHR file uploads --> -<script src="js/jquery.iframe-transport.js"></script> -<!-- The basic File Upload plugin --> -<script src="js/jquery.fileupload.js"></script> -<!-- The File Upload processing plugin --> -<script src="js/jquery.fileupload-process.js"></script> -<!-- The File Upload image preview & resize plugin --> -<script src="js/jquery.fileupload-image.js"></script> -<!-- The File Upload audio preview plugin --> -<script src="js/jquery.fileupload-audio.js"></script> -<!-- The File Upload video preview plugin --> -<script src="js/jquery.fileupload-video.js"></script> -<!-- The File Upload validation plugin --> -<script src="js/jquery.fileupload-validate.js"></script> -<!-- The File Upload user interface plugin --> -<script src="js/jquery.fileupload-ui.js"></script> -<!-- The File Upload jQuery UI plugin --> -<script src="js/jquery.fileupload-jquery-ui.js"></script> -<!-- The main application script --> -<script src="js/main.js"></script> -<script> -// Initialize the jQuery UI theme switcher: -$('#theme-switcher').change(function () { - var theme = $('#theme'); - theme.prop( - 'href', - theme.prop('href').replace( - /[\w\-]+\/jquery-ui.css/, - $(this).val() + '/jquery-ui.css' - ) - ); -}); -</script> -<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 --> -<!--[if (gte IE 8)&(lt IE 10)]> -<script src="js/cors/jquery.xdr-transport.js"></script> -<![endif]--> -</body> -</html> diff --git a/library/blueimp_upload/js/app.js b/library/blueimp_upload/js/app.js deleted file mode 100644 index e6b7bce3e..000000000 --- a/library/blueimp_upload/js/app.js +++ /dev/null @@ -1,101 +0,0 @@ -/* - * jQuery File Upload Plugin Angular JS Example - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global window, angular */ - -;(function () { - 'use strict'; - - var isOnGitHub = window.location.hostname === 'blueimp.github.io', - url = isOnGitHub ? '//jquery-file-upload.appspot.com/' : 'server/php/'; - - angular.module('demo', [ - 'blueimp.fileupload' - ]) - .config([ - '$httpProvider', 'fileUploadProvider', - function ($httpProvider, fileUploadProvider) { - delete $httpProvider.defaults.headers.common['X-Requested-With']; - fileUploadProvider.defaults.redirect = window.location.href.replace( - /\/[^\/]*$/, - '/cors/result.html?%s' - ); - if (isOnGitHub) { - // Demo settings: - angular.extend(fileUploadProvider.defaults, { - // Enable image resizing, except for Android and Opera, - // which actually support image resizing, but fail to - // send Blob objects via XHR requests: - disableImageResize: /Android(?!.*Chrome)|Opera/ - .test(window.navigator.userAgent), - maxFileSize: 999000, - acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i - }); - } - } - ]) - - .controller('DemoFileUploadController', [ - '$scope', '$http', '$filter', '$window', - function ($scope, $http) { - $scope.options = { - url: url - }; - if (!isOnGitHub) { - $scope.loadingFiles = true; - $http.get(url) - .then( - function (response) { - $scope.loadingFiles = false; - $scope.queue = response.data.files || []; - }, - function () { - $scope.loadingFiles = false; - } - ); - } - } - ]) - - .controller('FileDestroyController', [ - '$scope', '$http', - function ($scope, $http) { - var file = $scope.file, - state; - if (file.url) { - file.$state = function () { - return state; - }; - file.$destroy = function () { - state = 'pending'; - return $http({ - url: file.deleteUrl, - method: file.deleteType - }).then( - function () { - state = 'resolved'; - $scope.clear(file); - }, - function () { - state = 'rejected'; - } - ); - }; - } else if (!file.$cancel && !file._index) { - file.$cancel = function () { - $scope.clear(file); - }; - } - } - ]); - -}()); diff --git a/library/blueimp_upload/js/cors/jquery.postmessage-transport.js b/library/blueimp_upload/js/cors/jquery.postmessage-transport.js deleted file mode 100644 index 2a0c38cb6..000000000 --- a/library/blueimp_upload/js/cors/jquery.postmessage-transport.js +++ /dev/null @@ -1,126 +0,0 @@ -/* - * jQuery postMessage Transport Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* global define, require, window, document */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define(['jquery'], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory(require('jquery')); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - - var counter = 0, - names = [ - 'accepts', - 'cache', - 'contents', - 'contentType', - 'crossDomain', - 'data', - 'dataType', - 'headers', - 'ifModified', - 'mimeType', - 'password', - 'processData', - 'timeout', - 'traditional', - 'type', - 'url', - 'username' - ], - convert = function (p) { - return p; - }; - - $.ajaxSetup({ - converters: { - 'postmessage text': convert, - 'postmessage json': convert, - 'postmessage html': convert - } - }); - - $.ajaxTransport('postmessage', function (options) { - if (options.postMessage && window.postMessage) { - var iframe, - loc = $('<a>').prop('href', options.postMessage)[0], - target = loc.protocol + '//' + loc.host, - xhrUpload = options.xhr().upload; - // IE always includes the port for the host property of a link - // element, but not in the location.host or origin property for the - // default http port 80 and https port 443, so we strip it: - if (/^(http:\/\/.+:80)|(https:\/\/.+:443)$/.test(target)) { - target = target.replace(/:(80|443)$/, ''); - } - return { - send: function (_, completeCallback) { - counter += 1; - var message = { - id: 'postmessage-transport-' + counter - }, - eventName = 'message.' + message.id; - iframe = $( - '<iframe style="display:none;" src="' + - options.postMessage + '" name="' + - message.id + '"></iframe>' - ).bind('load', function () { - $.each(names, function (i, name) { - message[name] = options[name]; - }); - message.dataType = message.dataType.replace('postmessage ', ''); - $(window).bind(eventName, function (e) { - e = e.originalEvent; - var data = e.data, - ev; - if (e.origin === target && data.id === message.id) { - if (data.type === 'progress') { - ev = document.createEvent('Event'); - ev.initEvent(data.type, false, true); - $.extend(ev, data); - xhrUpload.dispatchEvent(ev); - } else { - completeCallback( - data.status, - data.statusText, - {postmessage: data.result}, - data.headers - ); - iframe.remove(); - $(window).unbind(eventName); - } - } - }); - iframe[0].contentWindow.postMessage( - message, - target - ); - }).appendTo(document.body); - }, - abort: function () { - if (iframe) { - iframe.remove(); - } - } - }; - } - }); - -})); diff --git a/library/blueimp_upload/js/cors/jquery.xdr-transport.js b/library/blueimp_upload/js/cors/jquery.xdr-transport.js deleted file mode 100644 index a4e2699c6..000000000 --- a/library/blueimp_upload/js/cors/jquery.xdr-transport.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * jQuery XDomainRequest Transport Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - * - * Based on Julian Aubourg's ajaxHooks xdr.js: - * https://github.com/jaubourg/ajaxHooks/ - */ - -/* global define, require, window, XDomainRequest */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define(['jquery'], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory(require('jquery')); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - if (window.XDomainRequest && !$.support.cors) { - $.ajaxTransport(function (s) { - if (s.crossDomain && s.async) { - if (s.timeout) { - s.xdrTimeout = s.timeout; - delete s.timeout; - } - var xdr; - return { - send: function (headers, completeCallback) { - var addParamChar = /\?/.test(s.url) ? '&' : '?'; - function callback(status, statusText, responses, responseHeaders) { - xdr.onload = xdr.onerror = xdr.ontimeout = $.noop; - xdr = null; - completeCallback(status, statusText, responses, responseHeaders); - } - xdr = new XDomainRequest(); - // XDomainRequest only supports GET and POST: - if (s.type === 'DELETE') { - s.url = s.url + addParamChar + '_method=DELETE'; - s.type = 'POST'; - } else if (s.type === 'PUT') { - s.url = s.url + addParamChar + '_method=PUT'; - s.type = 'POST'; - } else if (s.type === 'PATCH') { - s.url = s.url + addParamChar + '_method=PATCH'; - s.type = 'POST'; - } - xdr.open(s.type, s.url); - xdr.onload = function () { - callback( - 200, - 'OK', - {text: xdr.responseText}, - 'Content-Type: ' + xdr.contentType - ); - }; - xdr.onerror = function () { - callback(404, 'Not Found'); - }; - if (s.xdrTimeout) { - xdr.ontimeout = function () { - callback(0, 'timeout'); - }; - xdr.timeout = s.xdrTimeout; - } - xdr.send((s.hasContent && s.data) || null); - }, - abort: function () { - if (xdr) { - xdr.onerror = $.noop(); - xdr.abort(); - } - } - }; - } - }); - } -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-angular.js b/library/blueimp_upload/js/jquery.fileupload-angular.js deleted file mode 100644 index 185907d36..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-angular.js +++ /dev/null @@ -1,438 +0,0 @@ -/* - * jQuery File Upload AngularJS Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, angular, require */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'angular', - './jquery.fileupload-image', - './jquery.fileupload-audio', - './jquery.fileupload-video', - './jquery.fileupload-validate' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('angular'), - require('./jquery.fileupload-image'), - require('./jquery.fileupload-audio'), - require('./jquery.fileupload-video'), - require('./jquery.fileupload-validate') - ); - } else { - factory(); - } -}(function () { - 'use strict'; - - angular.module('blueimp.fileupload', []) - - // The fileUpload service provides configuration options - // for the fileUpload directive and default handlers for - // File Upload events: - .provider('fileUpload', function () { - var scopeEvalAsync = function (expression) { - var scope = angular.element(this) - .fileupload('option', 'scope'); - // Schedule a new $digest cycle if not already inside of one - // and evaluate the given expression: - scope.$evalAsync(expression); - }, - addFileMethods = function (scope, data) { - var files = data.files, - file = files[0]; - angular.forEach(files, function (file, index) { - file._index = index; - file.$state = function () { - return data.state(); - }; - file.$processing = function () { - return data.processing(); - }; - file.$progress = function () { - return data.progress(); - }; - file.$response = function () { - return data.response(); - }; - }); - file.$submit = function () { - if (!file.error) { - return data.submit(); - } - }; - file.$cancel = function () { - return data.abort(); - }; - }, - $config; - $config = this.defaults = { - handleResponse: function (e, data) { - var files = data.result && data.result.files; - if (files) { - data.scope.replace(data.files, files); - } else if (data.errorThrown || - data.textStatus === 'error') { - data.files[0].error = data.errorThrown || - data.textStatus; - } - }, - add: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var scope = data.scope, - filesCopy = []; - angular.forEach(data.files, function (file) { - filesCopy.push(file); - }); - scope.$parent.$applyAsync(function () { - addFileMethods(scope, data); - var method = scope.option('prependFiles') ? - 'unshift' : 'push'; - Array.prototype[method].apply(scope.queue, data.files); - }); - data.process(function () { - return scope.process(data); - }).always(function () { - scope.$parent.$applyAsync(function () { - addFileMethods(scope, data); - scope.replace(filesCopy, data.files); - }); - }).then(function () { - if ((scope.option('autoUpload') || - data.autoUpload) && - data.autoUpload !== false) { - data.submit(); - } - }); - }, - done: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = this; - data.scope.$apply(function () { - data.handleResponse.call(that, e, data); - }); - }, - fail: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = this, - scope = data.scope; - if (data.errorThrown === 'abort') { - scope.clear(data.files); - return; - } - scope.$apply(function () { - data.handleResponse.call(that, e, data); - }); - }, - stop: scopeEvalAsync, - processstart: scopeEvalAsync, - processstop: scopeEvalAsync, - getNumberOfFiles: function () { - var scope = this.scope; - return scope.queue.length - scope.processing(); - }, - dataType: 'json', - autoUpload: false - }; - this.$get = [ - function () { - return { - defaults: $config - }; - } - ]; - }) - - // Format byte numbers to readable presentations: - .provider('formatFileSizeFilter', function () { - var $config = { - // Byte units following the IEC format - // http://en.wikipedia.org/wiki/Kilobyte - units: [ - {size: 1000000000, suffix: ' GB'}, - {size: 1000000, suffix: ' MB'}, - {size: 1000, suffix: ' KB'} - ] - }; - this.defaults = $config; - this.$get = function () { - return function (bytes) { - if (!angular.isNumber(bytes)) { - return ''; - } - var unit = true, - i = 0, - prefix, - suffix; - while (unit) { - unit = $config.units[i]; - prefix = unit.prefix || ''; - suffix = unit.suffix || ''; - if (i === $config.units.length - 1 || bytes >= unit.size) { - return prefix + (bytes / unit.size).toFixed(2) + suffix; - } - i += 1; - } - }; - }; - }) - - // The FileUploadController initializes the fileupload widget and - // provides scope methods to control the File Upload functionality: - .controller('FileUploadController', [ - '$scope', '$element', '$attrs', '$window', 'fileUpload','$q', - function ($scope, $element, $attrs, $window, fileUpload, $q) { - var uploadMethods = { - progress: function () { - return $element.fileupload('progress'); - }, - active: function () { - return $element.fileupload('active'); - }, - option: function (option, data) { - if (arguments.length === 1) { - return $element.fileupload('option', option); - } - $element.fileupload('option', option, data); - }, - add: function (data) { - return $element.fileupload('add', data); - }, - send: function (data) { - return $element.fileupload('send', data); - }, - process: function (data) { - return $element.fileupload('process', data); - }, - processing: function (data) { - return $element.fileupload('processing', data); - } - }; - $scope.disabled = !$window.jQuery.support.fileInput; - $scope.queue = $scope.queue || []; - $scope.clear = function (files) { - var queue = this.queue, - i = queue.length, - file = files, - length = 1; - if (angular.isArray(files)) { - file = files[0]; - length = files.length; - } - while (i) { - i -= 1; - if (queue[i] === file) { - return queue.splice(i, length); - } - } - }; - $scope.replace = function (oldFiles, newFiles) { - var queue = this.queue, - file = oldFiles[0], - i, - j; - for (i = 0; i < queue.length; i += 1) { - if (queue[i] === file) { - for (j = 0; j < newFiles.length; j += 1) { - queue[i + j] = newFiles[j]; - } - return; - } - } - }; - $scope.applyOnQueue = function (method) { - var list = this.queue.slice(0), - i, - file, - promises = []; - for (i = 0; i < list.length; i += 1) { - file = list[i]; - if (file[method]) { - promises.push(file[method]()); - } - } - return $q.all(promises); - }; - $scope.submit = function () { - return this.applyOnQueue('$submit'); - }; - $scope.cancel = function () { - return this.applyOnQueue('$cancel'); - }; - // Add upload methods to the scope: - angular.extend($scope, uploadMethods); - // The fileupload widget will initialize with - // the options provided via "data-"-parameters, - // as well as those given via options object: - $element.fileupload(angular.extend( - {scope: $scope}, - fileUpload.defaults - )).on('fileuploadadd', function (e, data) { - data.scope = $scope; - }).on('fileuploadfail', function (e, data) { - if (data.errorThrown === 'abort') { - return; - } - if (data.dataType && - data.dataType.indexOf('json') === data.dataType.length - 4) { - try { - data.result = angular.fromJson(data.jqXHR.responseText); - } catch (ignore) {} - } - }).on([ - 'fileuploadadd', - 'fileuploadsubmit', - 'fileuploadsend', - 'fileuploaddone', - 'fileuploadfail', - 'fileuploadalways', - 'fileuploadprogress', - 'fileuploadprogressall', - 'fileuploadstart', - 'fileuploadstop', - 'fileuploadchange', - 'fileuploadpaste', - 'fileuploaddrop', - 'fileuploaddragover', - 'fileuploadchunkbeforesend', - 'fileuploadchunksend', - 'fileuploadchunkdone', - 'fileuploadchunkfail', - 'fileuploadchunkalways', - 'fileuploadprocessstart', - 'fileuploadprocess', - 'fileuploadprocessdone', - 'fileuploadprocessfail', - 'fileuploadprocessalways', - 'fileuploadprocessstop' - ].join(' '), function (e, data) { - $scope.$parent.$applyAsync(function () { - if ($scope.$emit(e.type, data).defaultPrevented) { - e.preventDefault(); - } - }); - }).on('remove', function () { - // Remove upload methods from the scope, - // when the widget is removed: - var method; - for (method in uploadMethods) { - if (uploadMethods.hasOwnProperty(method)) { - delete $scope[method]; - } - } - }); - // Observe option changes: - $scope.$watch( - $attrs.fileUpload, - function (newOptions) { - if (newOptions) { - $element.fileupload('option', newOptions); - } - } - ); - } - ]) - - // Provide File Upload progress feedback: - .controller('FileUploadProgressController', [ - '$scope', '$attrs', '$parse', - function ($scope, $attrs, $parse) { - var fn = $parse($attrs.fileUploadProgress), - update = function () { - var progress = fn($scope); - if (!progress || !progress.total) { - return; - } - $scope.num = Math.floor( - progress.loaded / progress.total * 100 - ); - }; - update(); - $scope.$watch( - $attrs.fileUploadProgress + '.loaded', - function (newValue, oldValue) { - if (newValue !== oldValue) { - update(); - } - } - ); - } - ]) - - // Display File Upload previews: - .controller('FileUploadPreviewController', [ - '$scope', '$element', '$attrs', - function ($scope, $element, $attrs) { - $scope.$watch( - $attrs.fileUploadPreview + '.preview', - function (preview) { - $element.empty(); - if (preview) { - $element.append(preview); - } - } - ); - } - ]) - - .directive('fileUpload', function () { - return { - controller: 'FileUploadController', - scope: true - }; - }) - - .directive('fileUploadProgress', function () { - return { - controller: 'FileUploadProgressController', - scope: true - }; - }) - - .directive('fileUploadPreview', function () { - return { - controller: 'FileUploadPreviewController' - }; - }) - - // Enhance the HTML5 download attribute to - // allow drag&drop of files to the desktop: - .directive('download', function () { - return function (scope, elm) { - elm.on('dragstart', function (e) { - try { - e.originalEvent.dataTransfer.setData( - 'DownloadURL', - [ - 'application/octet-stream', - elm.prop('download'), - elm.prop('href') - ].join(':') - ); - } catch (ignore) {} - }); - }; - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-audio.js b/library/blueimp_upload/js/jquery.fileupload-audio.js deleted file mode 100644 index a25377619..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-audio.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * jQuery File Upload Audio Preview Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window, document */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'load-image', - './jquery.fileupload-process' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('blueimp-load-image/js/load-image'), - require('./jquery.fileupload-process') - ); - } else { - // Browser globals: - factory( - window.jQuery, - window.loadImage - ); - } -}(function ($, loadImage) { - 'use strict'; - - // Prepend to the default processQueue: - $.blueimp.fileupload.prototype.options.processQueue.unshift( - { - action: 'loadAudio', - // Use the action as prefix for the "@" options: - prefix: true, - fileTypes: '@', - maxFileSize: '@', - disabled: '@disableAudioPreview' - }, - { - action: 'setAudio', - name: '@audioPreviewName', - disabled: '@disableAudioPreview' - } - ); - - // The File Upload Audio Preview plugin extends the fileupload widget - // with audio preview functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // The regular expression for the types of audio files to load, - // matched against the file type: - loadAudioFileTypes: /^audio\/.*$/ - }, - - _audioElement: document.createElement('audio'), - - processActions: { - - // Loads the audio file given via data.files and data.index - // as audio element if the browser supports playing it. - // Accepts the options fileTypes (regular expression) - // and maxFileSize (integer) to limit the files to load: - loadAudio: function (data, options) { - if (options.disabled) { - return data; - } - var file = data.files[data.index], - url, - audio; - if (this._audioElement.canPlayType && - this._audioElement.canPlayType(file.type) && - ($.type(options.maxFileSize) !== 'number' || - file.size <= options.maxFileSize) && - (!options.fileTypes || - options.fileTypes.test(file.type))) { - url = loadImage.createObjectURL(file); - if (url) { - audio = this._audioElement.cloneNode(false); - audio.src = url; - audio.controls = true; - data.audio = audio; - return data; - } - } - return data; - }, - - // Sets the audio element as a property of the file object: - setAudio: function (data, options) { - if (data.audio && !options.disabled) { - data.files[data.index][options.name || 'preview'] = data.audio; - } - return data; - } - - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-image.js b/library/blueimp_upload/js/jquery.fileupload-image.js deleted file mode 100644 index 65fc6d7b8..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-image.js +++ /dev/null @@ -1,326 +0,0 @@ -/* - * jQuery File Upload Image Preview & Resize Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window, Blob */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'load-image', - 'load-image-meta', - 'load-image-scale', - 'load-image-exif', - 'canvas-to-blob', - './jquery.fileupload-process' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('blueimp-load-image/js/load-image'), - require('blueimp-load-image/js/load-image-meta'), - require('blueimp-load-image/js/load-image-scale'), - require('blueimp-load-image/js/load-image-exif'), - require('blueimp-canvas-to-blob'), - require('./jquery.fileupload-process') - ); - } else { - // Browser globals: - factory( - window.jQuery, - window.loadImage - ); - } -}(function ($, loadImage) { - 'use strict'; - - // Prepend to the default processQueue: - $.blueimp.fileupload.prototype.options.processQueue.unshift( - { - action: 'loadImageMetaData', - disableImageHead: '@', - disableExif: '@', - disableExifThumbnail: '@', - disableExifSub: '@', - disableExifGps: '@', - disabled: '@disableImageMetaDataLoad' - }, - { - action: 'loadImage', - // Use the action as prefix for the "@" options: - prefix: true, - fileTypes: '@', - maxFileSize: '@', - noRevoke: '@', - disabled: '@disableImageLoad' - }, - { - action: 'resizeImage', - // Use "image" as prefix for the "@" options: - prefix: 'image', - maxWidth: '@', - maxHeight: '@', - minWidth: '@', - minHeight: '@', - crop: '@', - orientation: '@', - forceResize: '@', - disabled: '@disableImageResize' - }, - { - action: 'saveImage', - quality: '@imageQuality', - type: '@imageType', - disabled: '@disableImageResize' - }, - { - action: 'saveImageMetaData', - disabled: '@disableImageMetaDataSave' - }, - { - action: 'resizeImage', - // Use "preview" as prefix for the "@" options: - prefix: 'preview', - maxWidth: '@', - maxHeight: '@', - minWidth: '@', - minHeight: '@', - crop: '@', - orientation: '@', - thumbnail: '@', - canvas: '@', - disabled: '@disableImagePreview' - }, - { - action: 'setImage', - name: '@imagePreviewName', - disabled: '@disableImagePreview' - }, - { - action: 'deleteImageReferences', - disabled: '@disableImageReferencesDeletion' - } - ); - - // The File Upload Resize plugin extends the fileupload widget - // with image resize functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // The regular expression for the types of images to load: - // matched against the file type: - loadImageFileTypes: /^image\/(gif|jpeg|png|svg\+xml)$/, - // The maximum file size of images to load: - loadImageMaxFileSize: 10000000, // 10MB - // The maximum width of resized images: - imageMaxWidth: 1920, - // The maximum height of resized images: - imageMaxHeight: 1080, - // Defines the image orientation (1-8) or takes the orientation - // value from Exif data if set to true: - imageOrientation: false, - // Define if resized images should be cropped or only scaled: - imageCrop: false, - // Disable the resize image functionality by default: - disableImageResize: true, - // The maximum width of the preview images: - previewMaxWidth: 80, - // The maximum height of the preview images: - previewMaxHeight: 80, - // Defines the preview orientation (1-8) or takes the orientation - // value from Exif data if set to true: - previewOrientation: true, - // Create the preview using the Exif data thumbnail: - previewThumbnail: true, - // Define if preview images should be cropped or only scaled: - previewCrop: false, - // Define if preview images should be resized as canvas elements: - previewCanvas: true - }, - - processActions: { - - // Loads the image given via data.files and data.index - // as img element, if the browser supports the File API. - // Accepts the options fileTypes (regular expression) - // and maxFileSize (integer) to limit the files to load: - loadImage: function (data, options) { - if (options.disabled) { - return data; - } - var that = this, - file = data.files[data.index], - dfd = $.Deferred(); - if (($.type(options.maxFileSize) === 'number' && - file.size > options.maxFileSize) || - (options.fileTypes && - !options.fileTypes.test(file.type)) || - !loadImage( - file, - function (img) { - if (img.src) { - data.img = img; - } - dfd.resolveWith(that, [data]); - }, - options - )) { - return data; - } - return dfd.promise(); - }, - - // Resizes the image given as data.canvas or data.img - // and updates data.canvas or data.img with the resized image. - // Also stores the resized image as preview property. - // Accepts the options maxWidth, maxHeight, minWidth, - // minHeight, canvas and crop: - resizeImage: function (data, options) { - if (options.disabled || !(data.canvas || data.img)) { - return data; - } - options = $.extend({canvas: true}, options); - var that = this, - dfd = $.Deferred(), - img = (options.canvas && data.canvas) || data.img, - resolve = function (newImg) { - if (newImg && (newImg.width !== img.width || - newImg.height !== img.height || - options.forceResize)) { - data[newImg.getContext ? 'canvas' : 'img'] = newImg; - } - data.preview = newImg; - dfd.resolveWith(that, [data]); - }, - thumbnail; - if (data.exif) { - if (options.orientation === true) { - options.orientation = data.exif.get('Orientation'); - } - if (options.thumbnail) { - thumbnail = data.exif.get('Thumbnail'); - if (thumbnail) { - loadImage(thumbnail, resolve, options); - return dfd.promise(); - } - } - // Prevent orienting the same image twice: - if (data.orientation) { - delete options.orientation; - } else { - data.orientation = options.orientation; - } - } - if (img) { - resolve(loadImage.scale(img, options)); - return dfd.promise(); - } - return data; - }, - - // Saves the processed image given as data.canvas - // inplace at data.index of data.files: - saveImage: function (data, options) { - if (!data.canvas || options.disabled) { - return data; - } - var that = this, - file = data.files[data.index], - dfd = $.Deferred(); - if (data.canvas.toBlob) { - data.canvas.toBlob( - function (blob) { - if (!blob.name) { - if (file.type === blob.type) { - blob.name = file.name; - } else if (file.name) { - blob.name = file.name.replace( - /\.\w+$/, - '.' + blob.type.substr(6) - ); - } - } - // Don't restore invalid meta data: - if (file.type !== blob.type) { - delete data.imageHead; - } - // Store the created blob at the position - // of the original file in the files list: - data.files[data.index] = blob; - dfd.resolveWith(that, [data]); - }, - options.type || file.type, - options.quality - ); - } else { - return data; - } - return dfd.promise(); - }, - - loadImageMetaData: function (data, options) { - if (options.disabled) { - return data; - } - var that = this, - dfd = $.Deferred(); - loadImage.parseMetaData(data.files[data.index], function (result) { - $.extend(data, result); - dfd.resolveWith(that, [data]); - }, options); - return dfd.promise(); - }, - - saveImageMetaData: function (data, options) { - if (!(data.imageHead && data.canvas && - data.canvas.toBlob && !options.disabled)) { - return data; - } - var file = data.files[data.index], - blob = new Blob([ - data.imageHead, - // Resized images always have a head size of 20 bytes, - // including the JPEG marker and a minimal JFIF header: - this._blobSlice.call(file, 20) - ], {type: file.type}); - blob.name = file.name; - data.files[data.index] = blob; - return data; - }, - - // Sets the resized version of the image as a property of the - // file object, must be called after "saveImage": - setImage: function (data, options) { - if (data.preview && !options.disabled) { - data.files[data.index][options.name || 'preview'] = data.preview; - } - return data; - }, - - deleteImageReferences: function (data, options) { - if (!options.disabled) { - delete data.img; - delete data.canvas; - delete data.preview; - delete data.imageHead; - } - return data; - } - - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-jquery-ui.js b/library/blueimp_upload/js/jquery.fileupload-jquery-ui.js deleted file mode 100644 index 7b136b379..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-jquery-ui.js +++ /dev/null @@ -1,161 +0,0 @@ -/* - * jQuery File Upload jQuery UI Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - './jquery.fileupload-ui' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('./jquery.fileupload-ui') - ); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - processdone: function (e, data) { - data.context.find('.start').button('enable'); - }, - progress: function (e, data) { - if (data.context) { - data.context.find('.progress').progressbar( - 'option', - 'value', - parseInt(data.loaded / data.total * 100, 10) - ); - } - }, - progressall: function (e, data) { - var $this = $(this); - $this.find('.fileupload-progress') - .find('.progress').progressbar( - 'option', - 'value', - parseInt(data.loaded / data.total * 100, 10) - ).end() - .find('.progress-extended').each(function () { - $(this).html( - ($this.data('blueimp-fileupload') || - $this.data('fileupload')) - ._renderExtendedProgress(data) - ); - }); - } - }, - - _renderUpload: function (func, files) { - var node = this._super(func, files), - showIconText = $(window).width() > 480; - node.find('.progress').empty().progressbar(); - node.find('.start').button({ - icons: {primary: 'ui-icon-circle-arrow-e'}, - text: showIconText - }); - node.find('.cancel').button({ - icons: {primary: 'ui-icon-cancel'}, - text: showIconText - }); - if (node.hasClass('fade')) { - node.hide(); - } - return node; - }, - - _renderDownload: function (func, files) { - var node = this._super(func, files), - showIconText = $(window).width() > 480; - node.find('.delete').button({ - icons: {primary: 'ui-icon-trash'}, - text: showIconText - }); - if (node.hasClass('fade')) { - node.hide(); - } - return node; - }, - - _startHandler: function (e) { - $(e.currentTarget).button('disable'); - this._super(e); - }, - - _transition: function (node) { - var deferred = $.Deferred(); - if (node.hasClass('fade')) { - node.fadeToggle( - this.options.transitionDuration, - this.options.transitionEasing, - function () { - deferred.resolveWith(node); - } - ); - } else { - deferred.resolveWith(node); - } - return deferred; - }, - - _create: function () { - this._super(); - this.element - .find('.fileupload-buttonbar') - .find('.fileinput-button').each(function () { - var input = $(this).find('input:file').detach(); - $(this) - .button({icons: {primary: 'ui-icon-plusthick'}}) - .append(input); - }) - .end().find('.start') - .button({icons: {primary: 'ui-icon-circle-arrow-e'}}) - .end().find('.cancel') - .button({icons: {primary: 'ui-icon-cancel'}}) - .end().find('.delete') - .button({icons: {primary: 'ui-icon-trash'}}) - .end().find('.progress').progressbar(); - }, - - _destroy: function () { - this.element - .find('.fileupload-buttonbar') - .find('.fileinput-button').each(function () { - var input = $(this).find('input:file').detach(); - $(this) - .button('destroy') - .append(input); - }) - .end().find('.start') - .button('destroy') - .end().find('.cancel') - .button('destroy') - .end().find('.delete') - .button('destroy') - .end().find('.progress').progressbar('destroy'); - this._super(); - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-process.js b/library/blueimp_upload/js/jquery.fileupload-process.js deleted file mode 100644 index 638f0d26b..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-process.js +++ /dev/null @@ -1,178 +0,0 @@ -/* - * jQuery File Upload Processing Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2012, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - './jquery.fileupload' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('./jquery.fileupload') - ); - } else { - // Browser globals: - factory( - window.jQuery - ); - } -}(function ($) { - 'use strict'; - - var originalAdd = $.blueimp.fileupload.prototype.options.add; - - // The File Upload Processing plugin extends the fileupload widget - // with file processing functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // The list of processing actions: - processQueue: [ - /* - { - action: 'log', - type: 'debug' - } - */ - ], - add: function (e, data) { - var $this = $(this); - data.process(function () { - return $this.fileupload('process', data); - }); - originalAdd.call(this, e, data); - } - }, - - processActions: { - /* - log: function (data, options) { - console[options.type]( - 'Processing "' + data.files[data.index].name + '"' - ); - } - */ - }, - - _processFile: function (data, originalData) { - var that = this, - dfd = $.Deferred().resolveWith(that, [data]), - chain = dfd.promise(); - this._trigger('process', null, data); - $.each(data.processQueue, function (i, settings) { - var func = function (data) { - if (originalData.errorThrown) { - return $.Deferred() - .rejectWith(that, [originalData]).promise(); - } - return that.processActions[settings.action].call( - that, - data, - settings - ); - }; - chain = chain.then(func, settings.always && func); - }); - chain - .done(function () { - that._trigger('processdone', null, data); - that._trigger('processalways', null, data); - }) - .fail(function () { - that._trigger('processfail', null, data); - that._trigger('processalways', null, data); - }); - return chain; - }, - - // Replaces the settings of each processQueue item that - // are strings starting with an "@", using the remaining - // substring as key for the option map, - // e.g. "@autoUpload" is replaced with options.autoUpload: - _transformProcessQueue: function (options) { - var processQueue = []; - $.each(options.processQueue, function () { - var settings = {}, - action = this.action, - prefix = this.prefix === true ? action : this.prefix; - $.each(this, function (key, value) { - if ($.type(value) === 'string' && - value.charAt(0) === '@') { - settings[key] = options[ - value.slice(1) || (prefix ? prefix + - key.charAt(0).toUpperCase() + key.slice(1) : key) - ]; - } else { - settings[key] = value; - } - - }); - processQueue.push(settings); - }); - options.processQueue = processQueue; - }, - - // Returns the number of files currently in the processsing queue: - processing: function () { - return this._processing; - }, - - // Processes the files given as files property of the data parameter, - // returns a Promise object that allows to bind callbacks: - process: function (data) { - var that = this, - options = $.extend({}, this.options, data); - if (options.processQueue && options.processQueue.length) { - this._transformProcessQueue(options); - if (this._processing === 0) { - this._trigger('processstart'); - } - $.each(data.files, function (index) { - var opts = index ? $.extend({}, options) : options, - func = function () { - if (data.errorThrown) { - return $.Deferred() - .rejectWith(that, [data]).promise(); - } - return that._processFile(opts, data); - }; - opts.index = index; - that._processing += 1; - that._processingQueue = that._processingQueue.then(func, func) - .always(function () { - that._processing -= 1; - if (that._processing === 0) { - that._trigger('processstop'); - } - }); - }); - } - return this._processingQueue; - }, - - _create: function () { - this._super(); - this._processing = 0; - this._processingQueue = $.Deferred().resolveWith(this) - .promise(); - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-ui.js b/library/blueimp_upload/js/jquery.fileupload-ui.js deleted file mode 100644 index 5058084b4..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-ui.js +++ /dev/null @@ -1,714 +0,0 @@ -/* - * jQuery File Upload User Interface Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'blueimp-tmpl', - './jquery.fileupload-image', - './jquery.fileupload-audio', - './jquery.fileupload-video', - './jquery.fileupload-validate' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('blueimp-tmpl'), - require('./jquery.fileupload-image'), - require('./jquery.fileupload-audio'), - require('./jquery.fileupload-video'), - require('./jquery.fileupload-validate') - ); - } else { - // Browser globals: - factory( - window.jQuery, - window.tmpl - ); - } -}(function ($, tmpl) { - 'use strict'; - - $.blueimp.fileupload.prototype._specialOptions.push( - 'filesContainer', - 'uploadTemplateId', - 'downloadTemplateId' - ); - - // The UI version extends the file upload widget - // and adds complete user interface interaction: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // By default, files added to the widget are uploaded as soon - // as the user clicks on the start buttons. To enable automatic - // uploads, set the following option to true: - autoUpload: false, - // The ID of the upload template: - uploadTemplateId: 'template-upload', - // The ID of the download template: - downloadTemplateId: 'template-download', - // The container for the list of files. If undefined, it is set to - // an element with class "files" inside of the widget element: - filesContainer: undefined, - // By default, files are appended to the files container. - // Set the following option to true, to prepend files instead: - prependFiles: false, - // The expected data type of the upload response, sets the dataType - // option of the $.ajax upload requests: - dataType: 'json', - - // Error and info messages: - messages: { - unknownError: 'Unknown error' - }, - - // Function returning the current number of files, - // used by the maxNumberOfFiles validation: - getNumberOfFiles: function () { - return this.filesContainer.children() - .not('.processing').length; - }, - - // Callback to retrieve the list of files from the server response: - getFilesFromResponse: function (data) { - if (data.result && $.isArray(data.result.files)) { - return data.result.files; - } - return []; - }, - - // The add callback is invoked as soon as files are added to the fileupload - // widget (via file input selection, drag & drop or add API call). - // See the basic file upload widget for more information: - add: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var $this = $(this), - that = $this.data('blueimp-fileupload') || - $this.data('fileupload'), - options = that.options; - data.context = that._renderUpload(data.files) - .data('data', data) - .addClass('processing'); - options.filesContainer[ - options.prependFiles ? 'prepend' : 'append' - ](data.context); - that._forceReflow(data.context); - that._transition(data.context); - data.process(function () { - return $this.fileupload('process', data); - }).always(function () { - data.context.each(function (index) { - $(this).find('.size').text( - that._formatFileSize(data.files[index].size) - ); - }).removeClass('processing'); - that._renderPreviews(data); - }).done(function () { - data.context.find('.start').prop('disabled', false); - if ((that._trigger('added', e, data) !== false) && - (options.autoUpload || data.autoUpload) && - data.autoUpload !== false) { - data.submit(); - } - }).fail(function () { - if (data.files.error) { - data.context.each(function (index) { - var error = data.files[index].error; - if (error) { - $(this).find('.error').text(error); - } - }); - } - }); - }, - // Callback for the start of each file upload request: - send: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'); - if (data.context && data.dataType && - data.dataType.substr(0, 6) === 'iframe') { - // Iframe Transport does not support progress events. - // In lack of an indeterminate progress bar, we set - // the progress to 100%, showing the full animated bar: - data.context - .find('.progress').addClass( - !$.support.transition && 'progress-animated' - ) - .attr('aria-valuenow', 100) - .children().first().css( - 'width', - '100%' - ); - } - return that._trigger('sent', e, data); - }, - // Callback for successful uploads: - done: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'), - getFilesFromResponse = data.getFilesFromResponse || - that.options.getFilesFromResponse, - files = getFilesFromResponse(data), - template, - deferred; - if (data.context) { - data.context.each(function (index) { - var file = files[index] || - {error: 'Empty file upload result'}; - deferred = that._addFinishedDeferreds(); - that._transition($(this)).done( - function () { - var node = $(this); - template = that._renderDownload([file]) - .replaceAll(node); - that._forceReflow(template); - that._transition(template).done( - function () { - data.context = $(this); - that._trigger('completed', e, data); - that._trigger('finished', e, data); - deferred.resolve(); - } - ); - } - ); - }); - } else { - template = that._renderDownload(files)[ - that.options.prependFiles ? 'prependTo' : 'appendTo' - ](that.options.filesContainer); - that._forceReflow(template); - deferred = that._addFinishedDeferreds(); - that._transition(template).done( - function () { - data.context = $(this); - that._trigger('completed', e, data); - that._trigger('finished', e, data); - deferred.resolve(); - } - ); - } - }, - // Callback for failed (abort or error) uploads: - fail: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'), - template, - deferred; - if (data.context) { - data.context.each(function (index) { - if (data.errorThrown !== 'abort') { - var file = data.files[index]; - file.error = file.error || data.errorThrown || - data.i18n('unknownError'); - deferred = that._addFinishedDeferreds(); - that._transition($(this)).done( - function () { - var node = $(this); - template = that._renderDownload([file]) - .replaceAll(node); - that._forceReflow(template); - that._transition(template).done( - function () { - data.context = $(this); - that._trigger('failed', e, data); - that._trigger('finished', e, data); - deferred.resolve(); - } - ); - } - ); - } else { - deferred = that._addFinishedDeferreds(); - that._transition($(this)).done( - function () { - $(this).remove(); - that._trigger('failed', e, data); - that._trigger('finished', e, data); - deferred.resolve(); - } - ); - } - }); - } else if (data.errorThrown !== 'abort') { - data.context = that._renderUpload(data.files)[ - that.options.prependFiles ? 'prependTo' : 'appendTo' - ](that.options.filesContainer) - .data('data', data); - that._forceReflow(data.context); - deferred = that._addFinishedDeferreds(); - that._transition(data.context).done( - function () { - data.context = $(this); - that._trigger('failed', e, data); - that._trigger('finished', e, data); - deferred.resolve(); - } - ); - } else { - that._trigger('failed', e, data); - that._trigger('finished', e, data); - that._addFinishedDeferreds().resolve(); - } - }, - // Callback for upload progress events: - progress: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var progress = Math.floor(data.loaded / data.total * 100); - if (data.context) { - data.context.each(function () { - $(this).find('.progress') - .attr('aria-valuenow', progress) - .children().first().css( - 'width', - progress + '%' - ); - }); - } - }, - // Callback for global upload progress events: - progressall: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var $this = $(this), - progress = Math.floor(data.loaded / data.total * 100), - globalProgressNode = $this.find('.fileupload-progress'), - extendedProgressNode = globalProgressNode - .find('.progress-extended'); - if (extendedProgressNode.length) { - extendedProgressNode.html( - ($this.data('blueimp-fileupload') || $this.data('fileupload')) - ._renderExtendedProgress(data) - ); - } - globalProgressNode - .find('.progress') - .attr('aria-valuenow', progress) - .children().first().css( - 'width', - progress + '%' - ); - }, - // Callback for uploads start, equivalent to the global ajaxStart event: - start: function (e) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'); - that._resetFinishedDeferreds(); - that._transition($(this).find('.fileupload-progress')).done( - function () { - that._trigger('started', e); - } - ); - }, - // Callback for uploads stop, equivalent to the global ajaxStop event: - stop: function (e) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'), - deferred = that._addFinishedDeferreds(); - $.when.apply($, that._getFinishedDeferreds()) - .done(function () { - that._trigger('stopped', e); - }); - that._transition($(this).find('.fileupload-progress')).done( - function () { - $(this).find('.progress') - .attr('aria-valuenow', '0') - .children().first().css('width', '0%'); - $(this).find('.progress-extended').html(' '); - deferred.resolve(); - } - ); - }, - processstart: function (e) { - if (e.isDefaultPrevented()) { - return false; - } - $(this).addClass('fileupload-processing'); - }, - processstop: function (e) { - if (e.isDefaultPrevented()) { - return false; - } - $(this).removeClass('fileupload-processing'); - }, - // Callback for file deletion: - destroy: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'), - removeNode = function () { - that._transition(data.context).done( - function () { - $(this).remove(); - that._trigger('destroyed', e, data); - } - ); - }; - if (data.url) { - data.dataType = data.dataType || that.options.dataType; - $.ajax(data).done(removeNode).fail(function () { - that._trigger('destroyfailed', e, data); - }); - } else { - removeNode(); - } - } - }, - - _resetFinishedDeferreds: function () { - this._finishedUploads = []; - }, - - _addFinishedDeferreds: function (deferred) { - if (!deferred) { - deferred = $.Deferred(); - } - this._finishedUploads.push(deferred); - return deferred; - }, - - _getFinishedDeferreds: function () { - return this._finishedUploads; - }, - - // Link handler, that allows to download files - // by drag & drop of the links to the desktop: - _enableDragToDesktop: function () { - var link = $(this), - url = link.prop('href'), - name = link.prop('download'), - type = 'application/octet-stream'; - link.bind('dragstart', function (e) { - try { - e.originalEvent.dataTransfer.setData( - 'DownloadURL', - [type, name, url].join(':') - ); - } catch (ignore) {} - }); - }, - - _formatFileSize: function (bytes) { - if (typeof bytes !== 'number') { - return ''; - } - if (bytes >= 1000000000) { - return (bytes / 1000000000).toFixed(2) + ' GB'; - } - if (bytes >= 1000000) { - return (bytes / 1000000).toFixed(2) + ' MB'; - } - return (bytes / 1000).toFixed(2) + ' KB'; - }, - - _formatBitrate: function (bits) { - if (typeof bits !== 'number') { - return ''; - } - if (bits >= 1000000000) { - return (bits / 1000000000).toFixed(2) + ' Gbit/s'; - } - if (bits >= 1000000) { - return (bits / 1000000).toFixed(2) + ' Mbit/s'; - } - if (bits >= 1000) { - return (bits / 1000).toFixed(2) + ' kbit/s'; - } - return bits.toFixed(2) + ' bit/s'; - }, - - _formatTime: function (seconds) { - var date = new Date(seconds * 1000), - days = Math.floor(seconds / 86400); - days = days ? days + 'd ' : ''; - return days + - ('0' + date.getUTCHours()).slice(-2) + ':' + - ('0' + date.getUTCMinutes()).slice(-2) + ':' + - ('0' + date.getUTCSeconds()).slice(-2); - }, - - _formatPercentage: function (floatValue) { - return (floatValue * 100).toFixed(2) + ' %'; - }, - - _renderExtendedProgress: function (data) { - return this._formatBitrate(data.bitrate) + ' | ' + - this._formatTime( - (data.total - data.loaded) * 8 / data.bitrate - ) + ' | ' + - this._formatPercentage( - data.loaded / data.total - ) + ' | ' + - this._formatFileSize(data.loaded) + ' / ' + - this._formatFileSize(data.total); - }, - - _renderTemplate: function (func, files) { - if (!func) { - return $(); - } - var result = func({ - files: files, - formatFileSize: this._formatFileSize, - options: this.options - }); - if (result instanceof $) { - return result; - } - return $(this.options.templatesContainer).html(result).children(); - }, - - _renderPreviews: function (data) { - data.context.find('.preview').each(function (index, elm) { - $(elm).append(data.files[index].preview); - }); - }, - - _renderUpload: function (files) { - return this._renderTemplate( - this.options.uploadTemplate, - files - ); - }, - - _renderDownload: function (files) { - return this._renderTemplate( - this.options.downloadTemplate, - files - ).find('a[download]').each(this._enableDragToDesktop).end(); - }, - - _startHandler: function (e) { - e.preventDefault(); - var button = $(e.currentTarget), - template = button.closest('.template-upload'), - data = template.data('data'); - button.prop('disabled', true); - if (data && data.submit) { - data.submit(); - } - }, - - _cancelHandler: function (e) { - e.preventDefault(); - var template = $(e.currentTarget) - .closest('.template-upload,.template-download'), - data = template.data('data') || {}; - data.context = data.context || template; - if (data.abort) { - data.abort(); - } else { - data.errorThrown = 'abort'; - this._trigger('fail', e, data); - } - }, - - _deleteHandler: function (e) { - e.preventDefault(); - var button = $(e.currentTarget); - this._trigger('destroy', e, $.extend({ - context: button.closest('.template-download'), - type: 'DELETE' - }, button.data())); - }, - - _forceReflow: function (node) { - return $.support.transition && node.length && - node[0].offsetWidth; - }, - - _transition: function (node) { - var dfd = $.Deferred(); - if ($.support.transition && node.hasClass('fade') && node.is(':visible')) { - node.bind( - $.support.transition.end, - function (e) { - // Make sure we don't respond to other transitions events - // in the container element, e.g. from button elements: - if (e.target === node[0]) { - node.unbind($.support.transition.end); - dfd.resolveWith(node); - } - } - ).toggleClass('in'); - } else { - node.toggleClass('in'); - dfd.resolveWith(node); - } - return dfd; - }, - - _initButtonBarEventHandlers: function () { - var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'), - filesList = this.options.filesContainer; - this._on(fileUploadButtonBar.find('.start'), { - click: function (e) { - e.preventDefault(); - filesList.find('.start').click(); - } - }); - this._on(fileUploadButtonBar.find('.cancel'), { - click: function (e) { - e.preventDefault(); - filesList.find('.cancel').click(); - } - }); - this._on(fileUploadButtonBar.find('.delete'), { - click: function (e) { - e.preventDefault(); - filesList.find('.toggle:checked') - .closest('.template-download') - .find('.delete').click(); - fileUploadButtonBar.find('.toggle') - .prop('checked', false); - } - }); - this._on(fileUploadButtonBar.find('.toggle'), { - change: function (e) { - filesList.find('.toggle').prop( - 'checked', - $(e.currentTarget).is(':checked') - ); - } - }); - }, - - _destroyButtonBarEventHandlers: function () { - this._off( - this.element.find('.fileupload-buttonbar') - .find('.start, .cancel, .delete'), - 'click' - ); - this._off( - this.element.find('.fileupload-buttonbar .toggle'), - 'change.' - ); - }, - - _initEventHandlers: function () { - this._super(); - this._on(this.options.filesContainer, { - 'click .start': this._startHandler, - 'click .cancel': this._cancelHandler, - 'click .delete': this._deleteHandler - }); - this._initButtonBarEventHandlers(); - }, - - _destroyEventHandlers: function () { - this._destroyButtonBarEventHandlers(); - this._off(this.options.filesContainer, 'click'); - this._super(); - }, - - _enableFileInputButton: function () { - this.element.find('.fileinput-button input') - .prop('disabled', false) - .parent().removeClass('disabled'); - }, - - _disableFileInputButton: function () { - this.element.find('.fileinput-button input') - .prop('disabled', true) - .parent().addClass('disabled'); - }, - - _initTemplates: function () { - var options = this.options; - options.templatesContainer = this.document[0].createElement( - options.filesContainer.prop('nodeName') - ); - if (tmpl) { - if (options.uploadTemplateId) { - options.uploadTemplate = tmpl(options.uploadTemplateId); - } - if (options.downloadTemplateId) { - options.downloadTemplate = tmpl(options.downloadTemplateId); - } - } - }, - - _initFilesContainer: function () { - var options = this.options; - if (options.filesContainer === undefined) { - options.filesContainer = this.element.find('.files'); - } else if (!(options.filesContainer instanceof $)) { - options.filesContainer = $(options.filesContainer); - } - }, - - _initSpecialOptions: function () { - this._super(); - this._initFilesContainer(); - this._initTemplates(); - }, - - _create: function () { - this._super(); - this._resetFinishedDeferreds(); - if (!$.support.fileInput) { - this._disableFileInputButton(); - } - }, - - enable: function () { - var wasDisabled = false; - if (this.options.disabled) { - wasDisabled = true; - } - this._super(); - if (wasDisabled) { - this.element.find('input, button').prop('disabled', false); - this._enableFileInputButton(); - } - }, - - disable: function () { - if (!this.options.disabled) { - this.element.find('input, button').prop('disabled', true); - this._disableFileInputButton(); - } - this._super(); - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-validate.js b/library/blueimp_upload/js/jquery.fileupload-validate.js deleted file mode 100644 index eebeb3733..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-validate.js +++ /dev/null @@ -1,125 +0,0 @@ -/* - * jQuery File Upload Validation Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* global define, require, window */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - './jquery.fileupload-process' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('./jquery.fileupload-process') - ); - } else { - // Browser globals: - factory( - window.jQuery - ); - } -}(function ($) { - 'use strict'; - - // Append to the default processQueue: - $.blueimp.fileupload.prototype.options.processQueue.push( - { - action: 'validate', - // Always trigger this action, - // even if the previous action was rejected: - always: true, - // Options taken from the global options map: - acceptFileTypes: '@', - maxFileSize: '@', - minFileSize: '@', - maxNumberOfFiles: '@', - disabled: '@disableValidation' - } - ); - - // The File Upload Validation plugin extends the fileupload widget - // with file validation functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - /* - // The regular expression for allowed file types, matches - // against either file type or file name: - acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, - // The maximum allowed file size in bytes: - maxFileSize: 10000000, // 10 MB - // The minimum allowed file size in bytes: - minFileSize: undefined, // No minimal file size - // The limit of files to be uploaded: - maxNumberOfFiles: 10, - */ - - // Function returning the current number of files, - // has to be overriden for maxNumberOfFiles validation: - getNumberOfFiles: $.noop, - - // Error and info messages: - messages: { - maxNumberOfFiles: 'Maximum number of files exceeded', - acceptFileTypes: 'File type not allowed', - maxFileSize: 'File is too large', - minFileSize: 'File is too small' - } - }, - - processActions: { - - validate: function (data, options) { - if (options.disabled) { - return data; - } - var dfd = $.Deferred(), - settings = this.options, - file = data.files[data.index], - fileSize; - if (options.minFileSize || options.maxFileSize) { - fileSize = file.size; - } - if ($.type(options.maxNumberOfFiles) === 'number' && - (settings.getNumberOfFiles() || 0) + data.files.length > - options.maxNumberOfFiles) { - file.error = settings.i18n('maxNumberOfFiles'); - } else if (options.acceptFileTypes && - !(options.acceptFileTypes.test(file.type) || - options.acceptFileTypes.test(file.name))) { - file.error = settings.i18n('acceptFileTypes'); - } else if (fileSize > options.maxFileSize) { - file.error = settings.i18n('maxFileSize'); - } else if ($.type(fileSize) === 'number' && - fileSize < options.minFileSize) { - file.error = settings.i18n('minFileSize'); - } else { - delete file.error; - } - if (file.error || data.files.error) { - data.files.error = true; - dfd.rejectWith(this, [data]); - } else { - dfd.resolveWith(this, [data]); - } - return dfd.promise(); - } - - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-video.js b/library/blueimp_upload/js/jquery.fileupload-video.js deleted file mode 100644 index aedcec2ba..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-video.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * jQuery File Upload Video Preview Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window, document */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'load-image', - './jquery.fileupload-process' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('blueimp-load-image/js/load-image'), - require('./jquery.fileupload-process') - ); - } else { - // Browser globals: - factory( - window.jQuery, - window.loadImage - ); - } -}(function ($, loadImage) { - 'use strict'; - - // Prepend to the default processQueue: - $.blueimp.fileupload.prototype.options.processQueue.unshift( - { - action: 'loadVideo', - // Use the action as prefix for the "@" options: - prefix: true, - fileTypes: '@', - maxFileSize: '@', - disabled: '@disableVideoPreview' - }, - { - action: 'setVideo', - name: '@videoPreviewName', - disabled: '@disableVideoPreview' - } - ); - - // The File Upload Video Preview plugin extends the fileupload widget - // with video preview functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // The regular expression for the types of video files to load, - // matched against the file type: - loadVideoFileTypes: /^video\/.*$/ - }, - - _videoElement: document.createElement('video'), - - processActions: { - - // Loads the video file given via data.files and data.index - // as video element if the browser supports playing it. - // Accepts the options fileTypes (regular expression) - // and maxFileSize (integer) to limit the files to load: - loadVideo: function (data, options) { - if (options.disabled) { - return data; - } - var file = data.files[data.index], - url, - video; - if (this._videoElement.canPlayType && - this._videoElement.canPlayType(file.type) && - ($.type(options.maxFileSize) !== 'number' || - file.size <= options.maxFileSize) && - (!options.fileTypes || - options.fileTypes.test(file.type))) { - url = loadImage.createObjectURL(file); - if (url) { - video = this._videoElement.cloneNode(false); - video.src = url; - video.controls = true; - data.video = video; - return data; - } - } - return data; - }, - - // Sets the video element as a property of the file object: - setVideo: function (data, options) { - if (data.video && !options.disabled) { - data.files[data.index][options.name || 'preview'] = data.video; - } - return data; - } - - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload.js b/library/blueimp_upload/js/jquery.fileupload.js deleted file mode 100644 index 700f9013c..000000000 --- a/library/blueimp_upload/js/jquery.fileupload.js +++ /dev/null @@ -1,1502 +0,0 @@ -/* - * jQuery File Upload Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window, document, location, Blob, FormData */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'jquery-ui/ui/widget' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('./vendor/jquery.ui.widget') - ); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - - // Detect file input support, based on - // http://viljamis.com/blog/2012/file-upload-support-on-mobile/ - $.support.fileInput = !(new RegExp( - // Handle devices which give false positives for the feature detection: - '(Android (1\\.[0156]|2\\.[01]))' + - '|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' + - '|(w(eb)?OSBrowser)|(webOS)' + - '|(Kindle/(1\\.0|2\\.[05]|3\\.0))' - ).test(window.navigator.userAgent) || - // Feature detection for all other devices: - $('<input type="file"/>').prop('disabled')); - - // The FileReader API is not actually used, but works as feature detection, - // as some Safari versions (5?) support XHR file uploads via the FormData API, - // but not non-multipart XHR file uploads. - // window.XMLHttpRequestUpload is not available on IE10, so we check for - // window.ProgressEvent instead to detect XHR2 file upload capability: - $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader); - $.support.xhrFormDataFileUpload = !!window.FormData; - - // Detect support for Blob slicing (required for chunked uploads): - $.support.blobSlice = window.Blob && (Blob.prototype.slice || - Blob.prototype.webkitSlice || Blob.prototype.mozSlice); - - // Helper function to create drag handlers for dragover/dragenter/dragleave: - function getDragHandler(type) { - var isDragOver = type === 'dragover'; - return function (e) { - e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; - var dataTransfer = e.dataTransfer; - if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 && - this._trigger( - type, - $.Event(type, {delegatedEvent: e}) - ) !== false) { - e.preventDefault(); - if (isDragOver) { - dataTransfer.dropEffect = 'copy'; - } - } - }; - } - - // The fileupload widget listens for change events on file input fields defined - // via fileInput setting and paste or drop events of the given dropZone. - // In addition to the default jQuery Widget methods, the fileupload widget - // exposes the "add" and "send" methods, to add or directly send files using - // the fileupload API. - // By default, files added via file input selection, paste, drag & drop or - // "add" method are uploaded immediately, but it is possible to override - // the "add" callback option to queue file uploads. - $.widget('blueimp.fileupload', { - - options: { - // The drop target element(s), by the default the complete document. - // Set to null to disable drag & drop support: - dropZone: $(document), - // The paste target element(s), by the default undefined. - // Set to a DOM node or jQuery object to enable file pasting: - pasteZone: undefined, - // The file input field(s), that are listened to for change events. - // If undefined, it is set to the file input fields inside - // of the widget element on plugin initialization. - // Set to null to disable the change listener. - fileInput: undefined, - // By default, the file input field is replaced with a clone after - // each input field change event. This is required for iframe transport - // queues and allows change events to be fired for the same file - // selection, but can be disabled by setting the following option to false: - replaceFileInput: true, - // The parameter name for the file form data (the request argument name). - // If undefined or empty, the name property of the file input field is - // used, or "files[]" if the file input name property is also empty, - // can be a string or an array of strings: - paramName: undefined, - // By default, each file of a selection is uploaded using an individual - // request for XHR type uploads. Set to false to upload file - // selections in one request each: - singleFileUploads: true, - // To limit the number of files uploaded with one XHR request, - // set the following option to an integer greater than 0: - limitMultiFileUploads: undefined, - // The following option limits the number of files uploaded with one - // XHR request to keep the request size under or equal to the defined - // limit in bytes: - limitMultiFileUploadSize: undefined, - // Multipart file uploads add a number of bytes to each uploaded file, - // therefore the following option adds an overhead for each file used - // in the limitMultiFileUploadSize configuration: - limitMultiFileUploadSizeOverhead: 512, - // Set the following option to true to issue all file upload requests - // in a sequential order: - sequentialUploads: false, - // To limit the number of concurrent uploads, - // set the following option to an integer greater than 0: - limitConcurrentUploads: undefined, - // Set the following option to true to force iframe transport uploads: - forceIframeTransport: false, - // Set the following option to the location of a redirect url on the - // origin server, for cross-domain iframe transport uploads: - redirect: undefined, - // The parameter name for the redirect url, sent as part of the form - // data and set to 'redirect' if this option is empty: - redirectParamName: undefined, - // Set the following option to the location of a postMessage window, - // to enable postMessage transport uploads: - postMessage: undefined, - // By default, XHR file uploads are sent as multipart/form-data. - // The iframe transport is always using multipart/form-data. - // Set to false to enable non-multipart XHR uploads: - multipart: true, - // To upload large files in smaller chunks, set the following option - // to a preferred maximum chunk size. If set to 0, null or undefined, - // or the browser does not support the required Blob API, files will - // be uploaded as a whole. - maxChunkSize: undefined, - // When a non-multipart upload or a chunked multipart upload has been - // aborted, this option can be used to resume the upload by setting - // it to the size of the already uploaded bytes. This option is most - // useful when modifying the options object inside of the "add" or - // "send" callbacks, as the options are cloned for each file upload. - uploadedBytes: undefined, - // By default, failed (abort or error) file uploads are removed from the - // global progress calculation. Set the following option to false to - // prevent recalculating the global progress data: - recalculateProgress: true, - // Interval in milliseconds to calculate and trigger progress events: - progressInterval: 100, - // Interval in milliseconds to calculate progress bitrate: - bitrateInterval: 500, - // By default, uploads are started automatically when adding files: - autoUpload: true, - - // Error and info messages: - messages: { - uploadedBytes: 'Uploaded bytes exceed file size' - }, - - // Translation function, gets the message key to be translated - // and an object with context specific data as arguments: - i18n: function (message, context) { - message = this.messages[message] || message.toString(); - if (context) { - $.each(context, function (key, value) { - message = message.replace('{' + key + '}', value); - }); - } - return message; - }, - - // Additional form data to be sent along with the file uploads can be set - // using this option, which accepts an array of objects with name and - // value properties, a function returning such an array, a FormData - // object (for XHR file uploads), or a simple object. - // The form of the first fileInput is given as parameter to the function: - formData: function (form) { - return form.serializeArray(); - }, - - // The add callback is invoked as soon as files are added to the fileupload - // widget (via file input selection, drag & drop, paste or add API call). - // If the singleFileUploads option is enabled, this callback will be - // called once for each file in the selection for XHR file uploads, else - // once for each file selection. - // - // The upload starts when the submit method is invoked on the data parameter. - // The data object contains a files property holding the added files - // and allows you to override plugin options as well as define ajax settings. - // - // Listeners for this callback can also be bound the following way: - // .bind('fileuploadadd', func); - // - // data.submit() returns a Promise object and allows to attach additional - // handlers using jQuery's Deferred callbacks: - // data.submit().done(func).fail(func).always(func); - add: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - if (data.autoUpload || (data.autoUpload !== false && - $(this).fileupload('option', 'autoUpload'))) { - data.process().done(function () { - data.submit(); - }); - } - }, - - // Other callbacks: - - // Callback for the submit event of each file upload: - // submit: function (e, data) {}, // .bind('fileuploadsubmit', func); - - // Callback for the start of each file upload request: - // send: function (e, data) {}, // .bind('fileuploadsend', func); - - // Callback for successful uploads: - // done: function (e, data) {}, // .bind('fileuploaddone', func); - - // Callback for failed (abort or error) uploads: - // fail: function (e, data) {}, // .bind('fileuploadfail', func); - - // Callback for completed (success, abort or error) requests: - // always: function (e, data) {}, // .bind('fileuploadalways', func); - - // Callback for upload progress events: - // progress: function (e, data) {}, // .bind('fileuploadprogress', func); - - // Callback for global upload progress events: - // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func); - - // Callback for uploads start, equivalent to the global ajaxStart event: - // start: function (e) {}, // .bind('fileuploadstart', func); - - // Callback for uploads stop, equivalent to the global ajaxStop event: - // stop: function (e) {}, // .bind('fileuploadstop', func); - - // Callback for change events of the fileInput(s): - // change: function (e, data) {}, // .bind('fileuploadchange', func); - - // Callback for paste events to the pasteZone(s): - // paste: function (e, data) {}, // .bind('fileuploadpaste', func); - - // Callback for drop events of the dropZone(s): - // drop: function (e, data) {}, // .bind('fileuploaddrop', func); - - // Callback for dragover events of the dropZone(s): - // dragover: function (e) {}, // .bind('fileuploaddragover', func); - - // Callback before the start of each chunk upload request (before form data initialization): - // chunkbeforesend: function (e, data) {}, // .bind('fileuploadchunkbeforesend', func); - - // Callback for the start of each chunk upload request: - // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func); - - // Callback for successful chunk uploads: - // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func); - - // Callback for failed (abort or error) chunk uploads: - // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func); - - // Callback for completed (success, abort or error) chunk upload requests: - // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func); - - // The plugin options are used as settings object for the ajax calls. - // The following are jQuery ajax settings required for the file uploads: - processData: false, - contentType: false, - cache: false, - timeout: 0 - }, - - // A list of options that require reinitializing event listeners and/or - // special initialization code: - _specialOptions: [ - 'fileInput', - 'dropZone', - 'pasteZone', - 'multipart', - 'forceIframeTransport' - ], - - _blobSlice: $.support.blobSlice && function () { - var slice = this.slice || this.webkitSlice || this.mozSlice; - return slice.apply(this, arguments); - }, - - _BitrateTimer: function () { - this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime()); - this.loaded = 0; - this.bitrate = 0; - this.getBitrate = function (now, loaded, interval) { - var timeDiff = now - this.timestamp; - if (!this.bitrate || !interval || timeDiff > interval) { - this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; - this.loaded = loaded; - this.timestamp = now; - } - return this.bitrate; - }; - }, - - _isXHRUpload: function (options) { - return !options.forceIframeTransport && - ((!options.multipart && $.support.xhrFileUpload) || - $.support.xhrFormDataFileUpload); - }, - - _getFormData: function (options) { - var formData; - if ($.type(options.formData) === 'function') { - return options.formData(options.form); - } - if ($.isArray(options.formData)) { - return options.formData; - } - if ($.type(options.formData) === 'object') { - formData = []; - $.each(options.formData, function (name, value) { - formData.push({name: name, value: value}); - }); - return formData; - } - return []; - }, - - _getTotal: function (files) { - var total = 0; - $.each(files, function (index, file) { - total += file.size || 1; - }); - return total; - }, - - _initProgressObject: function (obj) { - var progress = { - loaded: 0, - total: 0, - bitrate: 0 - }; - if (obj._progress) { - $.extend(obj._progress, progress); - } else { - obj._progress = progress; - } - }, - - _initResponseObject: function (obj) { - var prop; - if (obj._response) { - for (prop in obj._response) { - if (obj._response.hasOwnProperty(prop)) { - delete obj._response[prop]; - } - } - } else { - obj._response = {}; - } - }, - - _onProgress: function (e, data) { - if (e.lengthComputable) { - var now = ((Date.now) ? Date.now() : (new Date()).getTime()), - loaded; - if (data._time && data.progressInterval && - (now - data._time < data.progressInterval) && - e.loaded !== e.total) { - return; - } - data._time = now; - loaded = Math.floor( - e.loaded / e.total * (data.chunkSize || data._progress.total) - ) + (data.uploadedBytes || 0); - // Add the difference from the previously loaded state - // to the global loaded counter: - this._progress.loaded += (loaded - data._progress.loaded); - this._progress.bitrate = this._bitrateTimer.getBitrate( - now, - this._progress.loaded, - data.bitrateInterval - ); - data._progress.loaded = data.loaded = loaded; - data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate( - now, - loaded, - data.bitrateInterval - ); - // Trigger a custom progress event with a total data property set - // to the file size(s) of the current upload and a loaded data - // property calculated accordingly: - this._trigger( - 'progress', - $.Event('progress', {delegatedEvent: e}), - data - ); - // Trigger a global progress event for all current file uploads, - // including ajax calls queued for sequential file uploads: - this._trigger( - 'progressall', - $.Event('progressall', {delegatedEvent: e}), - this._progress - ); - } - }, - - _initProgressListener: function (options) { - var that = this, - xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); - // Accesss to the native XHR object is required to add event listeners - // for the upload progress event: - if (xhr.upload) { - $(xhr.upload).bind('progress', function (e) { - var oe = e.originalEvent; - // Make sure the progress event properties get copied over: - e.lengthComputable = oe.lengthComputable; - e.loaded = oe.loaded; - e.total = oe.total; - that._onProgress(e, options); - }); - options.xhr = function () { - return xhr; - }; - } - }, - - _deinitProgressListener: function (options) { - var xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); - if (xhr.upload) { - $(xhr.upload).unbind('progress'); - } - }, - - _isInstanceOf: function (type, obj) { - // Cross-frame instanceof check - return Object.prototype.toString.call(obj) === '[object ' + type + ']'; - }, - - _initXHRData: function (options) { - var that = this, - formData, - file = options.files[0], - // Ignore non-multipart setting if not supported: - multipart = options.multipart || !$.support.xhrFileUpload, - paramName = $.type(options.paramName) === 'array' ? - options.paramName[0] : options.paramName; - options.headers = $.extend({}, options.headers); - if (options.contentRange) { - options.headers['Content-Range'] = options.contentRange; - } - if (!multipart || options.blob || !this._isInstanceOf('File', file)) { - options.headers['Content-Disposition'] = 'attachment; filename="' + - encodeURI(file.uploadName || file.name) + '"'; - } - if (!multipart) { - options.contentType = file.type || 'application/octet-stream'; - options.data = options.blob || file; - } else if ($.support.xhrFormDataFileUpload) { - if (options.postMessage) { - // window.postMessage does not allow sending FormData - // objects, so we just add the File/Blob objects to - // the formData array and let the postMessage window - // create the FormData object out of this array: - formData = this._getFormData(options); - if (options.blob) { - formData.push({ - name: paramName, - value: options.blob - }); - } else { - $.each(options.files, function (index, file) { - formData.push({ - name: ($.type(options.paramName) === 'array' && - options.paramName[index]) || paramName, - value: file - }); - }); - } - } else { - if (that._isInstanceOf('FormData', options.formData)) { - formData = options.formData; - } else { - formData = new FormData(); - $.each(this._getFormData(options), function (index, field) { - formData.append(field.name, field.value); - }); - } - if (options.blob) { - formData.append( - paramName, - options.blob, - file.uploadName || file.name - ); - } else { - $.each(options.files, function (index, file) { - // This check allows the tests to run with - // dummy objects: - if (that._isInstanceOf('File', file) || - that._isInstanceOf('Blob', file)) { - formData.append( - ($.type(options.paramName) === 'array' && - options.paramName[index]) || paramName, - file, - file.uploadName || file.name - ); - } - }); - } - } - options.data = formData; - } - // Blob reference is not needed anymore, free memory: - options.blob = null; - }, - - _initIframeSettings: function (options) { - var targetHost = $('<a></a>').prop('href', options.url).prop('host'); - // Setting the dataType to iframe enables the iframe transport: - options.dataType = 'iframe ' + (options.dataType || ''); - // The iframe transport accepts a serialized array as form data: - options.formData = this._getFormData(options); - // Add redirect url to form data on cross-domain uploads: - if (options.redirect && targetHost && targetHost !== location.host) { - options.formData.push({ - name: options.redirectParamName || 'redirect', - value: options.redirect - }); - } - }, - - _initDataSettings: function (options) { - if (this._isXHRUpload(options)) { - if (!this._chunkedUpload(options, true)) { - if (!options.data) { - this._initXHRData(options); - } - this._initProgressListener(options); - } - if (options.postMessage) { - // Setting the dataType to postmessage enables the - // postMessage transport: - options.dataType = 'postmessage ' + (options.dataType || ''); - } - } else { - this._initIframeSettings(options); - } - }, - - _getParamName: function (options) { - var fileInput = $(options.fileInput), - paramName = options.paramName; - if (!paramName) { - paramName = []; - fileInput.each(function () { - var input = $(this), - name = input.prop('name') || 'files[]', - i = (input.prop('files') || [1]).length; - while (i) { - paramName.push(name); - i -= 1; - } - }); - if (!paramName.length) { - paramName = [fileInput.prop('name') || 'files[]']; - } - } else if (!$.isArray(paramName)) { - paramName = [paramName]; - } - return paramName; - }, - - _initFormSettings: function (options) { - // Retrieve missing options from the input field and the - // associated form, if available: - if (!options.form || !options.form.length) { - options.form = $(options.fileInput.prop('form')); - // If the given file input doesn't have an associated form, - // use the default widget file input's form: - if (!options.form.length) { - options.form = $(this.options.fileInput.prop('form')); - } - } - options.paramName = this._getParamName(options); - if (!options.url) { - options.url = options.form.prop('action') || location.href; - } - // The HTTP request method must be "POST" or "PUT": - options.type = (options.type || - ($.type(options.form.prop('method')) === 'string' && - options.form.prop('method')) || '' - ).toUpperCase(); - if (options.type !== 'POST' && options.type !== 'PUT' && - options.type !== 'PATCH') { - options.type = 'POST'; - } - if (!options.formAcceptCharset) { - options.formAcceptCharset = options.form.attr('accept-charset'); - } - }, - - _getAJAXSettings: function (data) { - var options = $.extend({}, this.options, data); - this._initFormSettings(options); - this._initDataSettings(options); - return options; - }, - - // jQuery 1.6 doesn't provide .state(), - // while jQuery 1.8+ removed .isRejected() and .isResolved(): - _getDeferredState: function (deferred) { - if (deferred.state) { - return deferred.state(); - } - if (deferred.isResolved()) { - return 'resolved'; - } - if (deferred.isRejected()) { - return 'rejected'; - } - return 'pending'; - }, - - // Maps jqXHR callbacks to the equivalent - // methods of the given Promise object: - _enhancePromise: function (promise) { - promise.success = promise.done; - promise.error = promise.fail; - promise.complete = promise.always; - return promise; - }, - - // Creates and returns a Promise object enhanced with - // the jqXHR methods abort, success, error and complete: - _getXHRPromise: function (resolveOrReject, context, args) { - var dfd = $.Deferred(), - promise = dfd.promise(); - context = context || this.options.context || promise; - if (resolveOrReject === true) { - dfd.resolveWith(context, args); - } else if (resolveOrReject === false) { - dfd.rejectWith(context, args); - } - promise.abort = dfd.promise; - return this._enhancePromise(promise); - }, - - // Adds convenience methods to the data callback argument: - _addConvenienceMethods: function (e, data) { - var that = this, - getPromise = function (args) { - return $.Deferred().resolveWith(that, args).promise(); - }; - data.process = function (resolveFunc, rejectFunc) { - if (resolveFunc || rejectFunc) { - data._processQueue = this._processQueue = - (this._processQueue || getPromise([this])).then( - function () { - if (data.errorThrown) { - return $.Deferred() - .rejectWith(that, [data]).promise(); - } - return getPromise(arguments); - } - ).then(resolveFunc, rejectFunc); - } - return this._processQueue || getPromise([this]); - }; - data.submit = function () { - if (this.state() !== 'pending') { - data.jqXHR = this.jqXHR = - (that._trigger( - 'submit', - $.Event('submit', {delegatedEvent: e}), - this - ) !== false) && that._onSend(e, this); - } - return this.jqXHR || that._getXHRPromise(); - }; - data.abort = function () { - if (this.jqXHR) { - return this.jqXHR.abort(); - } - this.errorThrown = 'abort'; - that._trigger('fail', null, this); - return that._getXHRPromise(false); - }; - data.state = function () { - if (this.jqXHR) { - return that._getDeferredState(this.jqXHR); - } - if (this._processQueue) { - return that._getDeferredState(this._processQueue); - } - }; - data.processing = function () { - return !this.jqXHR && this._processQueue && that - ._getDeferredState(this._processQueue) === 'pending'; - }; - data.progress = function () { - return this._progress; - }; - data.response = function () { - return this._response; - }; - }, - - // Parses the Range header from the server response - // and returns the uploaded bytes: - _getUploadedBytes: function (jqXHR) { - var range = jqXHR.getResponseHeader('Range'), - parts = range && range.split('-'), - upperBytesPos = parts && parts.length > 1 && - parseInt(parts[1], 10); - return upperBytesPos && upperBytesPos + 1; - }, - - // Uploads a file in multiple, sequential requests - // by splitting the file up in multiple blob chunks. - // If the second parameter is true, only tests if the file - // should be uploaded in chunks, but does not invoke any - // upload requests: - _chunkedUpload: function (options, testOnly) { - options.uploadedBytes = options.uploadedBytes || 0; - var that = this, - file = options.files[0], - fs = file.size, - ub = options.uploadedBytes, - mcs = options.maxChunkSize || fs, - slice = this._blobSlice, - dfd = $.Deferred(), - promise = dfd.promise(), - jqXHR, - upload; - if (!(this._isXHRUpload(options) && slice && (ub || ($.type(mcs) === 'function' ? mcs(options) : mcs) < fs)) || - options.data) { - return false; - } - if (testOnly) { - return true; - } - if (ub >= fs) { - file.error = options.i18n('uploadedBytes'); - return this._getXHRPromise( - false, - options.context, - [null, 'error', file.error] - ); - } - // The chunk upload method: - upload = function () { - // Clone the options object for each chunk upload: - var o = $.extend({}, options), - currentLoaded = o._progress.loaded; - o.blob = slice.call( - file, - ub, - ub + ($.type(mcs) === 'function' ? mcs(o) : mcs), - file.type - ); - // Store the current chunk size, as the blob itself - // will be dereferenced after data processing: - o.chunkSize = o.blob.size; - // Expose the chunk bytes position range: - o.contentRange = 'bytes ' + ub + '-' + - (ub + o.chunkSize - 1) + '/' + fs; - // Trigger chunkbeforesend to allow form data to be updated for this chunk - that._trigger('chunkbeforesend', null, o); - // Process the upload data (the blob and potential form data): - that._initXHRData(o); - // Add progress listeners for this chunk upload: - that._initProgressListener(o); - jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) || - that._getXHRPromise(false, o.context)) - .done(function (result, textStatus, jqXHR) { - ub = that._getUploadedBytes(jqXHR) || - (ub + o.chunkSize); - // Create a progress event if no final progress event - // with loaded equaling total has been triggered - // for this chunk: - if (currentLoaded + o.chunkSize - o._progress.loaded) { - that._onProgress($.Event('progress', { - lengthComputable: true, - loaded: ub - o.uploadedBytes, - total: ub - o.uploadedBytes - }), o); - } - options.uploadedBytes = o.uploadedBytes = ub; - o.result = result; - o.textStatus = textStatus; - o.jqXHR = jqXHR; - that._trigger('chunkdone', null, o); - that._trigger('chunkalways', null, o); - if (ub < fs) { - // File upload not yet complete, - // continue with the next chunk: - upload(); - } else { - dfd.resolveWith( - o.context, - [result, textStatus, jqXHR] - ); - } - }) - .fail(function (jqXHR, textStatus, errorThrown) { - o.jqXHR = jqXHR; - o.textStatus = textStatus; - o.errorThrown = errorThrown; - that._trigger('chunkfail', null, o); - that._trigger('chunkalways', null, o); - dfd.rejectWith( - o.context, - [jqXHR, textStatus, errorThrown] - ); - }) - .always(function () { - that._deinitProgressListener(o); - }); - }; - this._enhancePromise(promise); - promise.abort = function () { - return jqXHR.abort(); - }; - upload(); - return promise; - }, - - _beforeSend: function (e, data) { - if (this._active === 0) { - // the start callback is triggered when an upload starts - // and no other uploads are currently running, - // equivalent to the global ajaxStart event: - this._trigger('start'); - // Set timer for global bitrate progress calculation: - this._bitrateTimer = new this._BitrateTimer(); - // Reset the global progress values: - this._progress.loaded = this._progress.total = 0; - this._progress.bitrate = 0; - } - // Make sure the container objects for the .response() and - // .progress() methods on the data object are available - // and reset to their initial state: - this._initResponseObject(data); - this._initProgressObject(data); - data._progress.loaded = data.loaded = data.uploadedBytes || 0; - data._progress.total = data.total = this._getTotal(data.files) || 1; - data._progress.bitrate = data.bitrate = 0; - this._active += 1; - // Initialize the global progress values: - this._progress.loaded += data.loaded; - this._progress.total += data.total; - }, - - _onDone: function (result, textStatus, jqXHR, options) { - var total = options._progress.total, - response = options._response; - if (options._progress.loaded < total) { - // Create a progress event if no final progress event - // with loaded equaling total has been triggered: - this._onProgress($.Event('progress', { - lengthComputable: true, - loaded: total, - total: total - }), options); - } - response.result = options.result = result; - response.textStatus = options.textStatus = textStatus; - response.jqXHR = options.jqXHR = jqXHR; - this._trigger('done', null, options); - }, - - _onFail: function (jqXHR, textStatus, errorThrown, options) { - var response = options._response; - if (options.recalculateProgress) { - // Remove the failed (error or abort) file upload from - // the global progress calculation: - this._progress.loaded -= options._progress.loaded; - this._progress.total -= options._progress.total; - } - response.jqXHR = options.jqXHR = jqXHR; - response.textStatus = options.textStatus = textStatus; - response.errorThrown = options.errorThrown = errorThrown; - this._trigger('fail', null, options); - }, - - _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { - // jqXHRorResult, textStatus and jqXHRorError are added to the - // options object via done and fail callbacks - this._trigger('always', null, options); - }, - - _onSend: function (e, data) { - if (!data.submit) { - this._addConvenienceMethods(e, data); - } - var that = this, - jqXHR, - aborted, - slot, - pipe, - options = that._getAJAXSettings(data), - send = function () { - that._sending += 1; - // Set timer for bitrate progress calculation: - options._bitrateTimer = new that._BitrateTimer(); - jqXHR = jqXHR || ( - ((aborted || that._trigger( - 'send', - $.Event('send', {delegatedEvent: e}), - options - ) === false) && - that._getXHRPromise(false, options.context, aborted)) || - that._chunkedUpload(options) || $.ajax(options) - ).done(function (result, textStatus, jqXHR) { - that._onDone(result, textStatus, jqXHR, options); - }).fail(function (jqXHR, textStatus, errorThrown) { - that._onFail(jqXHR, textStatus, errorThrown, options); - }).always(function (jqXHRorResult, textStatus, jqXHRorError) { - that._deinitProgressListener(options); - that._onAlways( - jqXHRorResult, - textStatus, - jqXHRorError, - options - ); - that._sending -= 1; - that._active -= 1; - if (options.limitConcurrentUploads && - options.limitConcurrentUploads > that._sending) { - // Start the next queued upload, - // that has not been aborted: - var nextSlot = that._slots.shift(); - while (nextSlot) { - if (that._getDeferredState(nextSlot) === 'pending') { - nextSlot.resolve(); - break; - } - nextSlot = that._slots.shift(); - } - } - if (that._active === 0) { - // The stop callback is triggered when all uploads have - // been completed, equivalent to the global ajaxStop event: - that._trigger('stop'); - } - }); - return jqXHR; - }; - this._beforeSend(e, options); - if (this.options.sequentialUploads || - (this.options.limitConcurrentUploads && - this.options.limitConcurrentUploads <= this._sending)) { - if (this.options.limitConcurrentUploads > 1) { - slot = $.Deferred(); - this._slots.push(slot); - pipe = slot.then(send); - } else { - this._sequence = this._sequence.then(send, send); - pipe = this._sequence; - } - // Return the piped Promise object, enhanced with an abort method, - // which is delegated to the jqXHR object of the current upload, - // and jqXHR callbacks mapped to the equivalent Promise methods: - pipe.abort = function () { - aborted = [undefined, 'abort', 'abort']; - if (!jqXHR) { - if (slot) { - slot.rejectWith(options.context, aborted); - } - return send(); - } - return jqXHR.abort(); - }; - return this._enhancePromise(pipe); - } - return send(); - }, - - _onAdd: function (e, data) { - var that = this, - result = true, - options = $.extend({}, this.options, data), - files = data.files, - filesLength = files.length, - limit = options.limitMultiFileUploads, - limitSize = options.limitMultiFileUploadSize, - overhead = options.limitMultiFileUploadSizeOverhead, - batchSize = 0, - paramName = this._getParamName(options), - paramNameSet, - paramNameSlice, - fileSet, - i, - j = 0; - if (!filesLength) { - return false; - } - if (limitSize && files[0].size === undefined) { - limitSize = undefined; - } - if (!(options.singleFileUploads || limit || limitSize) || - !this._isXHRUpload(options)) { - fileSet = [files]; - paramNameSet = [paramName]; - } else if (!(options.singleFileUploads || limitSize) && limit) { - fileSet = []; - paramNameSet = []; - for (i = 0; i < filesLength; i += limit) { - fileSet.push(files.slice(i, i + limit)); - paramNameSlice = paramName.slice(i, i + limit); - if (!paramNameSlice.length) { - paramNameSlice = paramName; - } - paramNameSet.push(paramNameSlice); - } - } else if (!options.singleFileUploads && limitSize) { - fileSet = []; - paramNameSet = []; - for (i = 0; i < filesLength; i = i + 1) { - batchSize += files[i].size + overhead; - if (i + 1 === filesLength || - ((batchSize + files[i + 1].size + overhead) > limitSize) || - (limit && i + 1 - j >= limit)) { - fileSet.push(files.slice(j, i + 1)); - paramNameSlice = paramName.slice(j, i + 1); - if (!paramNameSlice.length) { - paramNameSlice = paramName; - } - paramNameSet.push(paramNameSlice); - j = i + 1; - batchSize = 0; - } - } - } else { - paramNameSet = paramName; - } - data.originalFiles = files; - $.each(fileSet || files, function (index, element) { - var newData = $.extend({}, data); - newData.files = fileSet ? element : [element]; - newData.paramName = paramNameSet[index]; - that._initResponseObject(newData); - that._initProgressObject(newData); - that._addConvenienceMethods(e, newData); - result = that._trigger( - 'add', - $.Event('add', {delegatedEvent: e}), - newData - ); - return result; - }); - return result; - }, - - _replaceFileInput: function (data) { - var input = data.fileInput, - inputClone = input.clone(true), - restoreFocus = input.is(document.activeElement); - // Add a reference for the new cloned file input to the data argument: - data.fileInputClone = inputClone; - $('<form></form>').append(inputClone)[0].reset(); - // Detaching allows to insert the fileInput on another form - // without loosing the file input value: - input.after(inputClone).detach(); - // If the fileInput had focus before it was detached, - // restore focus to the inputClone. - if (restoreFocus) { - inputClone.focus(); - } - // Avoid memory leaks with the detached file input: - $.cleanData(input.unbind('remove')); - // Replace the original file input element in the fileInput - // elements set with the clone, which has been copied including - // event handlers: - this.options.fileInput = this.options.fileInput.map(function (i, el) { - if (el === input[0]) { - return inputClone[0]; - } - return el; - }); - // If the widget has been initialized on the file input itself, - // override this.element with the file input clone: - if (input[0] === this.element[0]) { - this.element = inputClone; - } - }, - - _handleFileTreeEntry: function (entry, path) { - var that = this, - dfd = $.Deferred(), - entries = [], - dirReader, - errorHandler = function (e) { - if (e && !e.entry) { - e.entry = entry; - } - // Since $.when returns immediately if one - // Deferred is rejected, we use resolve instead. - // This allows valid files and invalid items - // to be returned together in one set: - dfd.resolve([e]); - }, - successHandler = function (entries) { - that._handleFileTreeEntries( - entries, - path + entry.name + '/' - ).done(function (files) { - dfd.resolve(files); - }).fail(errorHandler); - }, - readEntries = function () { - dirReader.readEntries(function (results) { - if (!results.length) { - successHandler(entries); - } else { - entries = entries.concat(results); - readEntries(); - } - }, errorHandler); - }; - path = path || ''; - if (entry.isFile) { - if (entry._file) { - // Workaround for Chrome bug #149735 - entry._file.relativePath = path; - dfd.resolve(entry._file); - } else { - entry.file(function (file) { - file.relativePath = path; - dfd.resolve(file); - }, errorHandler); - } - } else if (entry.isDirectory) { - dirReader = entry.createReader(); - readEntries(); - } else { - // Return an empty list for file system items - // other than files or directories: - dfd.resolve([]); - } - return dfd.promise(); - }, - - _handleFileTreeEntries: function (entries, path) { - var that = this; - return $.when.apply( - $, - $.map(entries, function (entry) { - return that._handleFileTreeEntry(entry, path); - }) - ).then(function () { - return Array.prototype.concat.apply( - [], - arguments - ); - }); - }, - - _getDroppedFiles: function (dataTransfer) { - dataTransfer = dataTransfer || {}; - var items = dataTransfer.items; - if (items && items.length && (items[0].webkitGetAsEntry || - items[0].getAsEntry)) { - return this._handleFileTreeEntries( - $.map(items, function (item) { - var entry; - if (item.webkitGetAsEntry) { - entry = item.webkitGetAsEntry(); - if (entry) { - // Workaround for Chrome bug #149735: - entry._file = item.getAsFile(); - } - return entry; - } - return item.getAsEntry(); - }) - ); - } - return $.Deferred().resolve( - $.makeArray(dataTransfer.files) - ).promise(); - }, - - _getSingleFileInputFiles: function (fileInput) { - fileInput = $(fileInput); - var entries = fileInput.prop('webkitEntries') || - fileInput.prop('entries'), - files, - value; - if (entries && entries.length) { - return this._handleFileTreeEntries(entries); - } - files = $.makeArray(fileInput.prop('files')); - if (!files.length) { - value = fileInput.prop('value'); - if (!value) { - return $.Deferred().resolve([]).promise(); - } - // If the files property is not available, the browser does not - // support the File API and we add a pseudo File object with - // the input value as name with path information removed: - files = [{name: value.replace(/^.*\\/, '')}]; - } else if (files[0].name === undefined && files[0].fileName) { - // File normalization for Safari 4 and Firefox 3: - $.each(files, function (index, file) { - file.name = file.fileName; - file.size = file.fileSize; - }); - } - return $.Deferred().resolve(files).promise(); - }, - - _getFileInputFiles: function (fileInput) { - if (!(fileInput instanceof $) || fileInput.length === 1) { - return this._getSingleFileInputFiles(fileInput); - } - return $.when.apply( - $, - $.map(fileInput, this._getSingleFileInputFiles) - ).then(function () { - return Array.prototype.concat.apply( - [], - arguments - ); - }); - }, - - _onChange: function (e) { - var that = this, - data = { - fileInput: $(e.target), - form: $(e.target.form) - }; - this._getFileInputFiles(data.fileInput).always(function (files) { - data.files = files; - if (that.options.replaceFileInput) { - that._replaceFileInput(data); - } - if (that._trigger( - 'change', - $.Event('change', {delegatedEvent: e}), - data - ) !== false) { - that._onAdd(e, data); - } - }); - }, - - _onPaste: function (e) { - var items = e.originalEvent && e.originalEvent.clipboardData && - e.originalEvent.clipboardData.items, - data = {files: []}; - if (items && items.length) { - $.each(items, function (index, item) { - var file = item.getAsFile && item.getAsFile(); - if (file) { - data.files.push(file); - } - }); - if (this._trigger( - 'paste', - $.Event('paste', {delegatedEvent: e}), - data - ) !== false) { - this._onAdd(e, data); - } - } - }, - - _onDrop: function (e) { - e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; - var that = this, - dataTransfer = e.dataTransfer, - data = {}; - if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { - e.preventDefault(); - this._getDroppedFiles(dataTransfer).always(function (files) { - data.files = files; - if (that._trigger( - 'drop', - $.Event('drop', {delegatedEvent: e}), - data - ) !== false) { - that._onAdd(e, data); - } - }); - } - }, - - _onDragOver: getDragHandler('dragover'), - - _onDragEnter: getDragHandler('dragenter'), - - _onDragLeave: getDragHandler('dragleave'), - - _initEventHandlers: function () { - if (this._isXHRUpload(this.options)) { - this._on(this.options.dropZone, { - dragover: this._onDragOver, - drop: this._onDrop, - // event.preventDefault() on dragenter is required for IE10+: - dragenter: this._onDragEnter, - // dragleave is not required, but added for completeness: - dragleave: this._onDragLeave - }); - this._on(this.options.pasteZone, { - paste: this._onPaste - }); - } - if ($.support.fileInput) { - this._on(this.options.fileInput, { - change: this._onChange - }); - } - }, - - _destroyEventHandlers: function () { - this._off(this.options.dropZone, 'dragenter dragleave dragover drop'); - this._off(this.options.pasteZone, 'paste'); - this._off(this.options.fileInput, 'change'); - }, - - _destroy: function () { - this._destroyEventHandlers(); - }, - - _setOption: function (key, value) { - var reinit = $.inArray(key, this._specialOptions) !== -1; - if (reinit) { - this._destroyEventHandlers(); - } - this._super(key, value); - if (reinit) { - this._initSpecialOptions(); - this._initEventHandlers(); - } - }, - - _initSpecialOptions: function () { - var options = this.options; - if (options.fileInput === undefined) { - options.fileInput = this.element.is('input[type="file"]') ? - this.element : this.element.find('input[type="file"]'); - } else if (!(options.fileInput instanceof $)) { - options.fileInput = $(options.fileInput); - } - if (!(options.dropZone instanceof $)) { - options.dropZone = $(options.dropZone); - } - if (!(options.pasteZone instanceof $)) { - options.pasteZone = $(options.pasteZone); - } - }, - - _getRegExp: function (str) { - var parts = str.split('/'), - modifiers = parts.pop(); - parts.shift(); - return new RegExp(parts.join('/'), modifiers); - }, - - _isRegExpOption: function (key, value) { - return key !== 'url' && $.type(value) === 'string' && - /^\/.*\/[igm]{0,3}$/.test(value); - }, - - _initDataAttributes: function () { - var that = this, - options = this.options, - data = this.element.data(); - // Initialize options set via HTML5 data-attributes: - $.each( - this.element[0].attributes, - function (index, attr) { - var key = attr.name.toLowerCase(), - value; - if (/^data-/.test(key)) { - // Convert hyphen-ated key to camelCase: - key = key.slice(5).replace(/-[a-z]/g, function (str) { - return str.charAt(1).toUpperCase(); - }); - value = data[key]; - if (that._isRegExpOption(key, value)) { - value = that._getRegExp(value); - } - options[key] = value; - } - } - ); - }, - - _create: function () { - this._initDataAttributes(); - this._initSpecialOptions(); - this._slots = []; - this._sequence = this._getXHRPromise(true); - this._sending = this._active = 0; - this._initProgressObject(this); - this._initEventHandlers(); - }, - - // This method is exposed to the widget API and allows to query - // the number of active uploads: - active: function () { - return this._active; - }, - - // This method is exposed to the widget API and allows to query - // the widget upload progress. - // It returns an object with loaded, total and bitrate properties - // for the running uploads: - progress: function () { - return this._progress; - }, - - // This method is exposed to the widget API and allows adding files - // using the fileupload API. The data parameter accepts an object which - // must have a files property and can contain additional options: - // .fileupload('add', {files: filesList}); - add: function (data) { - var that = this; - if (!data || this.options.disabled) { - return; - } - if (data.fileInput && !data.files) { - this._getFileInputFiles(data.fileInput).always(function (files) { - data.files = files; - that._onAdd(null, data); - }); - } else { - data.files = $.makeArray(data.files); - this._onAdd(null, data); - } - }, - - // This method is exposed to the widget API and allows sending files - // using the fileupload API. The data parameter accepts an object which - // must have a files or fileInput property and can contain additional options: - // .fileupload('send', {files: filesList}); - // The method returns a Promise object for the file upload call. - send: function (data) { - if (data && !this.options.disabled) { - if (data.fileInput && !data.files) { - var that = this, - dfd = $.Deferred(), - promise = dfd.promise(), - jqXHR, - aborted; - promise.abort = function () { - aborted = true; - if (jqXHR) { - return jqXHR.abort(); - } - dfd.reject(null, 'abort', 'abort'); - return promise; - }; - this._getFileInputFiles(data.fileInput).always( - function (files) { - if (aborted) { - return; - } - if (!files.length) { - dfd.reject(); - return; - } - data.files = files; - jqXHR = that._onSend(null, data); - jqXHR.then( - function (result, textStatus, jqXHR) { - dfd.resolve(result, textStatus, jqXHR); - }, - function (jqXHR, textStatus, errorThrown) { - dfd.reject(jqXHR, textStatus, errorThrown); - } - ); - } - ); - return this._enhancePromise(promise); - } - data.files = $.makeArray(data.files); - if (data.files.length) { - return this._onSend(null, data); - } - } - return this._getXHRPromise(false, data && data.context); - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.iframe-transport.js b/library/blueimp_upload/js/jquery.iframe-transport.js deleted file mode 100644 index 8d25c4641..000000000 --- a/library/blueimp_upload/js/jquery.iframe-transport.js +++ /dev/null @@ -1,224 +0,0 @@ -/* - * jQuery Iframe Transport Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* global define, require, window, document, JSON */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define(['jquery'], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory(require('jquery')); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - - // Helper variable to create unique names for the transport iframes: - var counter = 0, - jsonAPI = $, - jsonParse = 'parseJSON'; - - if ('JSON' in window && 'parse' in JSON) { - jsonAPI = JSON; - jsonParse = 'parse'; - } - - // The iframe transport accepts four additional options: - // options.fileInput: a jQuery collection of file input fields - // options.paramName: the parameter name for the file form data, - // overrides the name property of the file input field(s), - // can be a string or an array of strings. - // options.formData: an array of objects with name and value properties, - // equivalent to the return data of .serializeArray(), e.g.: - // [{name: 'a', value: 1}, {name: 'b', value: 2}] - // options.initialIframeSrc: the URL of the initial iframe src, - // by default set to "javascript:false;" - $.ajaxTransport('iframe', function (options) { - if (options.async) { - // javascript:false as initial iframe src - // prevents warning popups on HTTPS in IE6: - /*jshint scripturl: true */ - var initialIframeSrc = options.initialIframeSrc || 'javascript:false;', - /*jshint scripturl: false */ - form, - iframe, - addParamChar; - return { - send: function (_, completeCallback) { - form = $('<form style="display:none;"></form>'); - form.attr('accept-charset', options.formAcceptCharset); - addParamChar = /\?/.test(options.url) ? '&' : '?'; - // XDomainRequest only supports GET and POST: - if (options.type === 'DELETE') { - options.url = options.url + addParamChar + '_method=DELETE'; - options.type = 'POST'; - } else if (options.type === 'PUT') { - options.url = options.url + addParamChar + '_method=PUT'; - options.type = 'POST'; - } else if (options.type === 'PATCH') { - options.url = options.url + addParamChar + '_method=PATCH'; - options.type = 'POST'; - } - // IE versions below IE8 cannot set the name property of - // elements that have already been added to the DOM, - // so we set the name along with the iframe HTML markup: - counter += 1; - iframe = $( - '<iframe src="' + initialIframeSrc + - '" name="iframe-transport-' + counter + '"></iframe>' - ).bind('load', function () { - var fileInputClones, - paramNames = $.isArray(options.paramName) ? - options.paramName : [options.paramName]; - iframe - .unbind('load') - .bind('load', function () { - var response; - // Wrap in a try/catch block to catch exceptions thrown - // when trying to access cross-domain iframe contents: - try { - response = iframe.contents(); - // Google Chrome and Firefox do not throw an - // exception when calling iframe.contents() on - // cross-domain requests, so we unify the response: - if (!response.length || !response[0].firstChild) { - throw new Error(); - } - } catch (e) { - response = undefined; - } - // The complete callback returns the - // iframe content document as response object: - completeCallback( - 200, - 'success', - {'iframe': response} - ); - // Fix for IE endless progress bar activity bug - // (happens on form submits to iframe targets): - $('<iframe src="' + initialIframeSrc + '"></iframe>') - .appendTo(form); - window.setTimeout(function () { - // Removing the form in a setTimeout call - // allows Chrome's developer tools to display - // the response result - form.remove(); - }, 0); - }); - form - .prop('target', iframe.prop('name')) - .prop('action', options.url) - .prop('method', options.type); - if (options.formData) { - $.each(options.formData, function (index, field) { - $('<input type="hidden"/>') - .prop('name', field.name) - .val(field.value) - .appendTo(form); - }); - } - if (options.fileInput && options.fileInput.length && - options.type === 'POST') { - fileInputClones = options.fileInput.clone(); - // Insert a clone for each file input field: - options.fileInput.after(function (index) { - return fileInputClones[index]; - }); - if (options.paramName) { - options.fileInput.each(function (index) { - $(this).prop( - 'name', - paramNames[index] || options.paramName - ); - }); - } - // Appending the file input fields to the hidden form - // removes them from their original location: - form - .append(options.fileInput) - .prop('enctype', 'multipart/form-data') - // enctype must be set as encoding for IE: - .prop('encoding', 'multipart/form-data'); - // Remove the HTML5 form attribute from the input(s): - options.fileInput.removeAttr('form'); - } - form.submit(); - // Insert the file input fields at their original location - // by replacing the clones with the originals: - if (fileInputClones && fileInputClones.length) { - options.fileInput.each(function (index, input) { - var clone = $(fileInputClones[index]); - // Restore the original name and form properties: - $(input) - .prop('name', clone.prop('name')) - .attr('form', clone.attr('form')); - clone.replaceWith(input); - }); - } - }); - form.append(iframe).appendTo(document.body); - }, - abort: function () { - if (iframe) { - // javascript:false as iframe src aborts the request - // and prevents warning popups on HTTPS in IE6. - // concat is used to avoid the "Script URL" JSLint error: - iframe - .unbind('load') - .prop('src', initialIframeSrc); - } - if (form) { - form.remove(); - } - } - }; - } - }); - - // The iframe transport returns the iframe content document as response. - // The following adds converters from iframe to text, json, html, xml - // and script. - // Please note that the Content-Type for JSON responses has to be text/plain - // or text/html, if the browser doesn't include application/json in the - // Accept header, else IE will show a download dialog. - // The Content-Type for XML responses on the other hand has to be always - // application/xml or text/xml, so IE properly parses the XML response. - // See also - // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation - $.ajaxSetup({ - converters: { - 'iframe text': function (iframe) { - return iframe && $(iframe[0].body).text(); - }, - 'iframe json': function (iframe) { - return iframe && jsonAPI[jsonParse]($(iframe[0].body).text()); - }, - 'iframe html': function (iframe) { - return iframe && $(iframe[0].body).html(); - }, - 'iframe xml': function (iframe) { - var xmlDoc = iframe && iframe[0]; - return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc : - $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) || - $(xmlDoc.body).html()); - }, - 'iframe script': function (iframe) { - return iframe && $.globalEval($(iframe[0].body).text()); - } - } - }); - -})); diff --git a/library/blueimp_upload/js/main.js b/library/blueimp_upload/js/main.js deleted file mode 100644 index 0403682e7..000000000 --- a/library/blueimp_upload/js/main.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * jQuery File Upload Plugin JS Example - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* global $, window */ - -$(function () { - 'use strict'; - - // Initialize the jQuery File Upload widget: - $('#fileupload').fileupload({ - // Uncomment the following to send cross-domain cookies: - //xhrFields: {withCredentials: true}, - url: 'server/php/' - }); - - // Enable iframe cross-domain access via redirect option: - $('#fileupload').fileupload( - 'option', - 'redirect', - window.location.href.replace( - /\/[^\/]*$/, - '/cors/result.html?%s' - ) - ); - - if (window.location.hostname === 'blueimp.github.io') { - // Demo settings: - $('#fileupload').fileupload('option', { - url: '//jquery-file-upload.appspot.com/', - // Enable image resizing, except for Android and Opera, - // which actually support image resizing, but fail to - // send Blob objects via XHR requests: - disableImageResize: /Android(?!.*Chrome)|Opera/ - .test(window.navigator.userAgent), - maxFileSize: 999000, - acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i - }); - // Upload server status check for browsers with CORS support: - if ($.support.cors) { - $.ajax({ - url: '//jquery-file-upload.appspot.com/', - type: 'HEAD' - }).fail(function () { - $('<div class="alert alert-danger"/>') - .text('Upload server currently unavailable - ' + - new Date()) - .appendTo('#fileupload'); - }); - } - } else { - // Load existing files: - $('#fileupload').addClass('fileupload-processing'); - $.ajax({ - // Uncomment the following to send cross-domain cookies: - //xhrFields: {withCredentials: true}, - url: $('#fileupload').fileupload('option', 'url'), - dataType: 'json', - context: $('#fileupload')[0] - }).always(function () { - $(this).removeClass('fileupload-processing'); - }).done(function (result) { - $(this).fileupload('option', 'done') - .call(this, $.Event('done'), {result: result}); - }); - } - -}); diff --git a/library/blueimp_upload/js/vendor/jquery.ui.widget.js b/library/blueimp_upload/js/vendor/jquery.ui.widget.js deleted file mode 100644 index 914b8ffb8..000000000 --- a/library/blueimp_upload/js/vendor/jquery.ui.widget.js +++ /dev/null @@ -1,752 +0,0 @@ -/*! jQuery UI - v1.12.1+CommonJS - 2018-02-10 - * http://jqueryui.com - * Includes: widget.js - * Copyright jQuery Foundation and other contributors; Licensed MIT */ - -(function( factory ) { - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define([ "jquery" ], factory ); - } else if ( typeof exports === "object" ) { - - // Node/CommonJS - factory( require( "jquery" ) ); - } else { - - // Browser globals - factory( jQuery ); - } -}(function( $ ) { - - $.ui = $.ui || {}; - - var version = $.ui.version = "1.12.1"; - - - /*! - * jQuery UI Widget 1.12.1 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - */ - - //>>label: Widget - //>>group: Core - //>>description: Provides a factory for creating stateful widgets with a common API. - //>>docs: http://api.jqueryui.com/jQuery.widget/ - //>>demos: http://jqueryui.com/widget/ - - - - var widgetUuid = 0; - var widgetSlice = Array.prototype.slice; - - $.cleanData = ( function( orig ) { - return function( elems ) { - var events, elem, i; - for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { - try { - - // Only trigger remove when necessary to save time - events = $._data( elem, "events" ); - if ( events && events.remove ) { - $( elem ).triggerHandler( "remove" ); - } - - // Http://bugs.jquery.com/ticket/8235 - } catch ( e ) {} - } - orig( elems ); - }; - } )( $.cleanData ); - - $.widget = function( name, base, prototype ) { - var existingConstructor, constructor, basePrototype; - - // ProxiedPrototype allows the provided prototype to remain unmodified - // so that it can be used as a mixin for multiple widgets (#8876) - var proxiedPrototype = {}; - - var namespace = name.split( "." )[ 0 ]; - name = name.split( "." )[ 1 ]; - var fullName = namespace + "-" + name; - - if ( !prototype ) { - prototype = base; - base = $.Widget; - } - - if ( $.isArray( prototype ) ) { - prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); - } - - // Create selector for plugin - $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { - return !!$.data( elem, fullName ); - }; - - $[ namespace ] = $[ namespace ] || {}; - existingConstructor = $[ namespace ][ name ]; - constructor = $[ namespace ][ name ] = function( options, element ) { - - // Allow instantiation without "new" keyword - if ( !this._createWidget ) { - return new constructor( options, element ); - } - - // Allow instantiation without initializing for simple inheritance - // must use "new" keyword (the code above always passes args) - if ( arguments.length ) { - this._createWidget( options, element ); - } - }; - - // Extend with the existing constructor to carry over any static properties - $.extend( constructor, existingConstructor, { - version: prototype.version, - - // Copy the object used to create the prototype in case we need to - // redefine the widget later - _proto: $.extend( {}, prototype ), - - // Track widgets that inherit from this widget in case this widget is - // redefined after a widget inherits from it - _childConstructors: [] - } ); - - basePrototype = new base(); - - // We need to make the options hash a property directly on the new instance - // otherwise we'll modify the options hash on the prototype that we're - // inheriting from - basePrototype.options = $.widget.extend( {}, basePrototype.options ); - $.each( prototype, function( prop, value ) { - if ( !$.isFunction( value ) ) { - proxiedPrototype[ prop ] = value; - return; - } - proxiedPrototype[ prop ] = ( function() { - function _super() { - return base.prototype[ prop ].apply( this, arguments ); - } - - function _superApply( args ) { - return base.prototype[ prop ].apply( this, args ); - } - - return function() { - var __super = this._super; - var __superApply = this._superApply; - var returnValue; - - this._super = _super; - this._superApply = _superApply; - - returnValue = value.apply( this, arguments ); - - this._super = __super; - this._superApply = __superApply; - - return returnValue; - }; - } )(); - } ); - constructor.prototype = $.widget.extend( basePrototype, { - - // TODO: remove support for widgetEventPrefix - // always use the name + a colon as the prefix, e.g., draggable:start - // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name - }, proxiedPrototype, { - constructor: constructor, - namespace: namespace, - widgetName: name, - widgetFullName: fullName - } ); - - // If this widget is being redefined then we need to find all widgets that - // are inheriting from it and redefine all of them so that they inherit from - // the new version of this widget. We're essentially trying to replace one - // level in the prototype chain. - if ( existingConstructor ) { - $.each( existingConstructor._childConstructors, function( i, child ) { - var childPrototype = child.prototype; - - // Redefine the child widget using the same prototype that was - // originally used, but inherit from the new version of the base - $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, - child._proto ); - } ); - - // Remove the list of existing child constructors from the old constructor - // so the old child constructors can be garbage collected - delete existingConstructor._childConstructors; - } else { - base._childConstructors.push( constructor ); - } - - $.widget.bridge( name, constructor ); - - return constructor; - }; - - $.widget.extend = function( target ) { - var input = widgetSlice.call( arguments, 1 ); - var inputIndex = 0; - var inputLength = input.length; - var key; - var value; - - for ( ; inputIndex < inputLength; inputIndex++ ) { - for ( key in input[ inputIndex ] ) { - value = input[ inputIndex ][ key ]; - if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - - // Clone objects - if ( $.isPlainObject( value ) ) { - target[ key ] = $.isPlainObject( target[ key ] ) ? - $.widget.extend( {}, target[ key ], value ) : - - // Don't extend strings, arrays, etc. with objects - $.widget.extend( {}, value ); - - // Copy everything else by reference - } else { - target[ key ] = value; - } - } - } - } - return target; - }; - - $.widget.bridge = function( name, object ) { - var fullName = object.prototype.widgetFullName || name; - $.fn[ name ] = function( options ) { - var isMethodCall = typeof options === "string"; - var args = widgetSlice.call( arguments, 1 ); - var returnValue = this; - - if ( isMethodCall ) { - - // If this is an empty collection, we need to have the instance method - // return undefined instead of the jQuery instance - if ( !this.length && options === "instance" ) { - returnValue = undefined; - } else { - this.each( function() { - var methodValue; - var instance = $.data( this, fullName ); - - if ( options === "instance" ) { - returnValue = instance; - return false; - } - - if ( !instance ) { - return $.error( "cannot call methods on " + name + - " prior to initialization; " + - "attempted to call method '" + options + "'" ); - } - - if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) { - return $.error( "no such method '" + options + "' for " + name + - " widget instance" ); - } - - methodValue = instance[ options ].apply( instance, args ); - - if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue && methodValue.jquery ? - returnValue.pushStack( methodValue.get() ) : - methodValue; - return false; - } - } ); - } - } else { - - // Allow multiple hashes to be passed on init - if ( args.length ) { - options = $.widget.extend.apply( null, [ options ].concat( args ) ); - } - - this.each( function() { - var instance = $.data( this, fullName ); - if ( instance ) { - instance.option( options || {} ); - if ( instance._init ) { - instance._init(); - } - } else { - $.data( this, fullName, new object( options, this ) ); - } - } ); - } - - return returnValue; - }; - }; - - $.Widget = function( /* options, element */ ) {}; - $.Widget._childConstructors = []; - - $.Widget.prototype = { - widgetName: "widget", - widgetEventPrefix: "", - defaultElement: "<div>", - - options: { - classes: {}, - disabled: false, - - // Callbacks - create: null - }, - - _createWidget: function( options, element ) { - element = $( element || this.defaultElement || this )[ 0 ]; - this.element = $( element ); - this.uuid = widgetUuid++; - this.eventNamespace = "." + this.widgetName + this.uuid; - - this.bindings = $(); - this.hoverable = $(); - this.focusable = $(); - this.classesElementLookup = {}; - - if ( element !== this ) { - $.data( element, this.widgetFullName, this ); - this._on( true, this.element, { - remove: function( event ) { - if ( event.target === element ) { - this.destroy(); - } - } - } ); - this.document = $( element.style ? - - // Element within the document - element.ownerDocument : - - // Element is window or document - element.document || element ); - this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); - } - - this.options = $.widget.extend( {}, - this.options, - this._getCreateOptions(), - options ); - - this._create(); - - if ( this.options.disabled ) { - this._setOptionDisabled( this.options.disabled ); - } - - this._trigger( "create", null, this._getCreateEventData() ); - this._init(); - }, - - _getCreateOptions: function() { - return {}; - }, - - _getCreateEventData: $.noop, - - _create: $.noop, - - _init: $.noop, - - destroy: function() { - var that = this; - - this._destroy(); - $.each( this.classesElementLookup, function( key, value ) { - that._removeClass( value, key ); - } ); - - // We can probably remove the unbind calls in 2.0 - // all event bindings should go through this._on() - this.element - .off( this.eventNamespace ) - .removeData( this.widgetFullName ); - this.widget() - .off( this.eventNamespace ) - .removeAttr( "aria-disabled" ); - - // Clean up events and states - this.bindings.off( this.eventNamespace ); - }, - - _destroy: $.noop, - - widget: function() { - return this.element; - }, - - option: function( key, value ) { - var options = key; - var parts; - var curOption; - var i; - - if ( arguments.length === 0 ) { - - // Don't return a reference to the internal hash - return $.widget.extend( {}, this.options ); - } - - if ( typeof key === "string" ) { - - // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } - options = {}; - parts = key.split( "." ); - key = parts.shift(); - if ( parts.length ) { - curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); - for ( i = 0; i < parts.length - 1; i++ ) { - curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; - curOption = curOption[ parts[ i ] ]; - } - key = parts.pop(); - if ( arguments.length === 1 ) { - return curOption[ key ] === undefined ? null : curOption[ key ]; - } - curOption[ key ] = value; - } else { - if ( arguments.length === 1 ) { - return this.options[ key ] === undefined ? null : this.options[ key ]; - } - options[ key ] = value; - } - } - - this._setOptions( options ); - - return this; - }, - - _setOptions: function( options ) { - var key; - - for ( key in options ) { - this._setOption( key, options[ key ] ); - } - - return this; - }, - - _setOption: function( key, value ) { - if ( key === "classes" ) { - this._setOptionClasses( value ); - } - - this.options[ key ] = value; - - if ( key === "disabled" ) { - this._setOptionDisabled( value ); - } - - return this; - }, - - _setOptionClasses: function( value ) { - var classKey, elements, currentElements; - - for ( classKey in value ) { - currentElements = this.classesElementLookup[ classKey ]; - if ( value[ classKey ] === this.options.classes[ classKey ] || - !currentElements || - !currentElements.length ) { - continue; - } - - // We are doing this to create a new jQuery object because the _removeClass() call - // on the next line is going to destroy the reference to the current elements being - // tracked. We need to save a copy of this collection so that we can add the new classes - // below. - elements = $( currentElements.get() ); - this._removeClass( currentElements, classKey ); - - // We don't use _addClass() here, because that uses this.options.classes - // for generating the string of classes. We want to use the value passed in from - // _setOption(), this is the new value of the classes option which was passed to - // _setOption(). We pass this value directly to _classes(). - elements.addClass( this._classes( { - element: elements, - keys: classKey, - classes: value, - add: true - } ) ); - } - }, - - _setOptionDisabled: function( value ) { - this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); - - // If the widget is becoming disabled, then nothing is interactive - if ( value ) { - this._removeClass( this.hoverable, null, "ui-state-hover" ); - this._removeClass( this.focusable, null, "ui-state-focus" ); - } - }, - - enable: function() { - return this._setOptions( { disabled: false } ); - }, - - disable: function() { - return this._setOptions( { disabled: true } ); - }, - - _classes: function( options ) { - var full = []; - var that = this; - - options = $.extend( { - element: this.element, - classes: this.options.classes || {} - }, options ); - - function processClassString( classes, checkOption ) { - var current, i; - for ( i = 0; i < classes.length; i++ ) { - current = that.classesElementLookup[ classes[ i ] ] || $(); - if ( options.add ) { - current = $( $.unique( current.get().concat( options.element.get() ) ) ); - } else { - current = $( current.not( options.element ).get() ); - } - that.classesElementLookup[ classes[ i ] ] = current; - full.push( classes[ i ] ); - if ( checkOption && options.classes[ classes[ i ] ] ) { - full.push( options.classes[ classes[ i ] ] ); - } - } - } - - this._on( options.element, { - "remove": "_untrackClassesElement" - } ); - - if ( options.keys ) { - processClassString( options.keys.match( /\S+/g ) || [], true ); - } - if ( options.extra ) { - processClassString( options.extra.match( /\S+/g ) || [] ); - } - - return full.join( " " ); - }, - - _untrackClassesElement: function( event ) { - var that = this; - $.each( that.classesElementLookup, function( key, value ) { - if ( $.inArray( event.target, value ) !== -1 ) { - that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); - } - } ); - }, - - _removeClass: function( element, keys, extra ) { - return this._toggleClass( element, keys, extra, false ); - }, - - _addClass: function( element, keys, extra ) { - return this._toggleClass( element, keys, extra, true ); - }, - - _toggleClass: function( element, keys, extra, add ) { - add = ( typeof add === "boolean" ) ? add : extra; - var shift = ( typeof element === "string" || element === null ), - options = { - extra: shift ? keys : extra, - keys: shift ? element : keys, - element: shift ? this.element : element, - add: add - }; - options.element.toggleClass( this._classes( options ), add ); - return this; - }, - - _on: function( suppressDisabledCheck, element, handlers ) { - var delegateElement; - var instance = this; - - // No suppressDisabledCheck flag, shuffle arguments - if ( typeof suppressDisabledCheck !== "boolean" ) { - handlers = element; - element = suppressDisabledCheck; - suppressDisabledCheck = false; - } - - // No element argument, shuffle and use this.element - if ( !handlers ) { - handlers = element; - element = this.element; - delegateElement = this.widget(); - } else { - element = delegateElement = $( element ); - this.bindings = this.bindings.add( element ); - } - - $.each( handlers, function( event, handler ) { - function handlerProxy() { - - // Allow widgets to customize the disabled handling - // - disabled as an array instead of boolean - // - disabled class as method for disabling individual parts - if ( !suppressDisabledCheck && - ( instance.options.disabled === true || - $( this ).hasClass( "ui-state-disabled" ) ) ) { - return; - } - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - - // Copy the guid so direct unbinding works - if ( typeof handler !== "string" ) { - handlerProxy.guid = handler.guid = - handler.guid || handlerProxy.guid || $.guid++; - } - - var match = event.match( /^([\w:-]*)\s*(.*)$/ ); - var eventName = match[ 1 ] + instance.eventNamespace; - var selector = match[ 2 ]; - - if ( selector ) { - delegateElement.on( eventName, selector, handlerProxy ); - } else { - element.on( eventName, handlerProxy ); - } - } ); - }, - - _off: function( element, eventName ) { - eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + - this.eventNamespace; - element.off( eventName ).off( eventName ); - - // Clear the stack to avoid memory leaks (#10056) - this.bindings = $( this.bindings.not( element ).get() ); - this.focusable = $( this.focusable.not( element ).get() ); - this.hoverable = $( this.hoverable.not( element ).get() ); - }, - - _delay: function( handler, delay ) { - function handlerProxy() { - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - var instance = this; - return setTimeout( handlerProxy, delay || 0 ); - }, - - _hoverable: function( element ) { - this.hoverable = this.hoverable.add( element ); - this._on( element, { - mouseenter: function( event ) { - this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); - }, - mouseleave: function( event ) { - this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); - } - } ); - }, - - _focusable: function( element ) { - this.focusable = this.focusable.add( element ); - this._on( element, { - focusin: function( event ) { - this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); - }, - focusout: function( event ) { - this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); - } - } ); - }, - - _trigger: function( type, event, data ) { - var prop, orig; - var callback = this.options[ type ]; - - data = data || {}; - event = $.Event( event ); - event.type = ( type === this.widgetEventPrefix ? - type : - this.widgetEventPrefix + type ).toLowerCase(); - - // The original event may come from any element - // so we need to reset the target on the new event - event.target = this.element[ 0 ]; - - // Copy original event properties over to the new event - orig = event.originalEvent; - if ( orig ) { - for ( prop in orig ) { - if ( !( prop in event ) ) { - event[ prop ] = orig[ prop ]; - } - } - } - - this.element.trigger( event, data ); - return !( $.isFunction( callback ) && - callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || - event.isDefaultPrevented() ); - } - }; - - $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { - $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { - if ( typeof options === "string" ) { - options = { effect: options }; - } - - var hasOptions; - var effectName = !options ? - method : - options === true || typeof options === "number" ? - defaultEffect : - options.effect || defaultEffect; - - options = options || {}; - if ( typeof options === "number" ) { - options = { duration: options }; - } - - hasOptions = !$.isEmptyObject( options ); - options.complete = callback; - - if ( options.delay ) { - element.delay( options.delay ); - } - - if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { - element[ method ]( options ); - } else if ( effectName !== method && element[ effectName ] ) { - element[ effectName ]( options.duration, options.easing, callback ); - } else { - element.queue( function( next ) { - $( this )[ method ](); - if ( callback ) { - callback.call( element[ 0 ] ); - } - next(); - } ); - } - }; - } ); - - var widget = $.widget; - - - - -})); diff --git a/library/blueimp_upload/package.json b/library/blueimp_upload/package.json deleted file mode 100644 index 4801d7913..000000000 --- a/library/blueimp_upload/package.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "blueimp-file-upload", - "version": "9.23.0", - "title": "jQuery File Upload", - "description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.", - "keywords": [ - "jquery", - "file", - "upload", - "widget", - "multiple", - "selection", - "drag", - "drop", - "progress", - "preview", - "cross-domain", - "cross-site", - "chunk", - "resume", - "gae", - "go", - "python", - "php", - "bootstrap" - ], - "homepage": "https://github.com/blueimp/jQuery-File-Upload", - "author": { - "name": "Sebastian Tschan", - "url": "https://blueimp.net" - }, - "repository": { - "type": "git", - "url": "git://github.com/blueimp/jQuery-File-Upload.git" - }, - "license": "MIT", - "optionalDependencies": { - "blueimp-canvas-to-blob": "3.5.0", - "blueimp-load-image": "2.12.2", - "blueimp-tmpl": "3.6.0" - }, - "devDependencies": { - "bower-json": "0.8.1", - "jshint": "2.9.3" - }, - "scripts": { - "bower-version-update": "./bower-version-update.js", - "lint": "jshint *.js js/*.js js/cors/*.js", - "test": "npm run lint", - "preversion": "npm test", - "version": "npm run bower-version-update && git add bower.json", - "postversion": "git push --tags origin master && npm publish" - }, - "main": "js/jquery.fileupload.js" -} diff --git a/library/blueimp_upload/server/gae-go/app.yaml b/library/blueimp_upload/server/gae-go/app.yaml deleted file mode 100644 index 2d09daa56..000000000 --- a/library/blueimp_upload/server/gae-go/app.yaml +++ /dev/null @@ -1,12 +0,0 @@ -application: jquery-file-upload -version: 2 -runtime: go -api_version: go1 - -handlers: -- url: /(favicon\.ico|robots\.txt) - static_files: static/\1 - upload: static/(.*) - expiration: '1d' -- url: /.* - script: _go_app diff --git a/library/blueimp_upload/server/gae-go/app/main.go b/library/blueimp_upload/server/gae-go/app/main.go deleted file mode 100644 index a92d128c0..000000000 --- a/library/blueimp_upload/server/gae-go/app/main.go +++ /dev/null @@ -1,361 +0,0 @@ -/* - * jQuery File Upload Plugin GAE Go Example - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -package app - -import ( - "bufio" - "bytes" - "encoding/json" - "fmt" - "github.com/disintegration/gift" - "golang.org/x/net/context" - "google.golang.org/appengine" - "google.golang.org/appengine/memcache" - "hash/crc32" - "image" - "image/gif" - "image/jpeg" - "image/png" - "io" - "log" - "mime/multipart" - "net/http" - "net/url" - "path/filepath" - "regexp" - "strings" -) - -const ( - WEBSITE = "https://blueimp.github.io/jQuery-File-Upload/" - MIN_FILE_SIZE = 1 // bytes - // Max file size is memcache limit (1MB) minus key size minus overhead: - MAX_FILE_SIZE = 999000 // bytes - IMAGE_TYPES = "image/(gif|p?jpeg|(x-)?png)" - ACCEPT_FILE_TYPES = IMAGE_TYPES - THUMB_MAX_WIDTH = 80 - THUMB_MAX_HEIGHT = 80 - EXPIRATION_TIME = 300 // seconds - // If empty, only allow redirects to the referer protocol+host. - // Set to a regexp string for custom pattern matching: - REDIRECT_ALLOW_TARGET = "" -) - -var ( - imageTypes = regexp.MustCompile(IMAGE_TYPES) - acceptFileTypes = regexp.MustCompile(ACCEPT_FILE_TYPES) - thumbSuffix = "." + fmt.Sprint(THUMB_MAX_WIDTH) + "x" + - fmt.Sprint(THUMB_MAX_HEIGHT) -) - -func escape(s string) string { - return strings.Replace(url.QueryEscape(s), "+", "%20", -1) -} - -func extractKey(r *http.Request) string { - // Use RequestURI instead of r.URL.Path, as we need the encoded form: - path := strings.Split(r.RequestURI, "?")[0] - // Also adjust double encoded slashes: - return strings.Replace(path[1:], "%252F", "%2F", -1) -} - -func check(err error) { - if err != nil { - panic(err) - } -} - -type FileInfo struct { - Key string `json:"-"` - ThumbnailKey string `json:"-"` - Url string `json:"url,omitempty"` - ThumbnailUrl string `json:"thumbnailUrl,omitempty"` - Name string `json:"name"` - Type string `json:"type"` - Size int64 `json:"size"` - Error string `json:"error,omitempty"` - DeleteUrl string `json:"deleteUrl,omitempty"` - DeleteType string `json:"deleteType,omitempty"` -} - -func (fi *FileInfo) ValidateType() (valid bool) { - if acceptFileTypes.MatchString(fi.Type) { - return true - } - fi.Error = "Filetype not allowed" - return false -} - -func (fi *FileInfo) ValidateSize() (valid bool) { - if fi.Size < MIN_FILE_SIZE { - fi.Error = "File is too small" - } else if fi.Size > MAX_FILE_SIZE { - fi.Error = "File is too big" - } else { - return true - } - return false -} - -func (fi *FileInfo) CreateUrls(r *http.Request, c context.Context) { - u := &url.URL{ - Scheme: r.URL.Scheme, - Host: appengine.DefaultVersionHostname(c), - Path: "/", - } - uString := u.String() - fi.Url = uString + fi.Key - fi.DeleteUrl = fi.Url - fi.DeleteType = "DELETE" - if fi.ThumbnailKey != "" { - fi.ThumbnailUrl = uString + fi.ThumbnailKey - } -} - -func (fi *FileInfo) SetKey(checksum uint32) { - fi.Key = escape(string(fi.Type)) + "/" + - escape(fmt.Sprint(checksum)) + "/" + - escape(string(fi.Name)) -} - -func (fi *FileInfo) createThumb(buffer *bytes.Buffer, c context.Context) { - if imageTypes.MatchString(fi.Type) { - src, _, err := image.Decode(bytes.NewReader(buffer.Bytes())) - check(err) - filter := gift.New(gift.ResizeToFit( - THUMB_MAX_WIDTH, - THUMB_MAX_HEIGHT, - gift.LanczosResampling, - )) - dst := image.NewNRGBA(filter.Bounds(src.Bounds())) - filter.Draw(dst, src) - buffer.Reset() - bWriter := bufio.NewWriter(buffer) - switch fi.Type { - case "image/jpeg", "image/pjpeg": - err = jpeg.Encode(bWriter, dst, nil) - case "image/gif": - err = gif.Encode(bWriter, dst, nil) - default: - err = png.Encode(bWriter, dst) - } - check(err) - bWriter.Flush() - thumbnailKey := fi.Key + thumbSuffix + filepath.Ext(fi.Name) - item := &memcache.Item{ - Key: thumbnailKey, - Value: buffer.Bytes(), - } - err = memcache.Set(c, item) - check(err) - fi.ThumbnailKey = thumbnailKey - } -} - -func handleUpload(r *http.Request, p *multipart.Part) (fi *FileInfo) { - fi = &FileInfo{ - Name: p.FileName(), - Type: p.Header.Get("Content-Type"), - } - if !fi.ValidateType() { - return - } - defer func() { - if rec := recover(); rec != nil { - log.Println(rec) - fi.Error = rec.(error).Error() - } - }() - var buffer bytes.Buffer - hash := crc32.NewIEEE() - mw := io.MultiWriter(&buffer, hash) - lr := &io.LimitedReader{R: p, N: MAX_FILE_SIZE + 1} - _, err := io.Copy(mw, lr) - check(err) - fi.Size = MAX_FILE_SIZE + 1 - lr.N - if !fi.ValidateSize() { - return - } - fi.SetKey(hash.Sum32()) - item := &memcache.Item{ - Key: fi.Key, - Value: buffer.Bytes(), - } - context := appengine.NewContext(r) - err = memcache.Set(context, item) - check(err) - fi.createThumb(&buffer, context) - fi.CreateUrls(r, context) - return -} - -func getFormValue(p *multipart.Part) string { - var b bytes.Buffer - io.CopyN(&b, p, int64(1<<20)) // Copy max: 1 MiB - return b.String() -} - -func handleUploads(r *http.Request) (fileInfos []*FileInfo) { - fileInfos = make([]*FileInfo, 0) - mr, err := r.MultipartReader() - check(err) - r.Form, err = url.ParseQuery(r.URL.RawQuery) - check(err) - part, err := mr.NextPart() - for err == nil { - if name := part.FormName(); name != "" { - if part.FileName() != "" { - fileInfos = append(fileInfos, handleUpload(r, part)) - } else { - r.Form[name] = append(r.Form[name], getFormValue(part)) - } - } - part, err = mr.NextPart() - } - return -} - -func validateRedirect(r *http.Request, redirect string) bool { - if redirect != "" { - var redirectAllowTarget *regexp.Regexp - if REDIRECT_ALLOW_TARGET != "" { - redirectAllowTarget = regexp.MustCompile(REDIRECT_ALLOW_TARGET) - } else { - referer := r.Referer() - if referer == "" { - return false - } - refererUrl, err := url.Parse(referer) - if err != nil { - return false - } - redirectAllowTarget = regexp.MustCompile("^" + regexp.QuoteMeta( - refererUrl.Scheme+"://"+refererUrl.Host+"/", - )) - } - return redirectAllowTarget.MatchString(redirect) - } - return false -} - -func get(w http.ResponseWriter, r *http.Request) { - if r.URL.Path == "/" { - http.Redirect(w, r, WEBSITE, http.StatusFound) - return - } - // Use RequestURI instead of r.URL.Path, as we need the encoded form: - key := extractKey(r) - parts := strings.Split(key, "/") - if len(parts) == 3 { - context := appengine.NewContext(r) - item, err := memcache.Get(context, key) - if err == nil { - w.Header().Add("X-Content-Type-Options", "nosniff") - contentType, _ := url.QueryUnescape(parts[0]) - if !imageTypes.MatchString(contentType) { - contentType = "application/octet-stream" - } - w.Header().Add("Content-Type", contentType) - w.Header().Add( - "Cache-Control", - fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME), - ) - w.Write(item.Value) - return - } - } - http.Error(w, "404 Not Found", http.StatusNotFound) -} - -func post(w http.ResponseWriter, r *http.Request) { - result := make(map[string][]*FileInfo, 1) - result["files"] = handleUploads(r) - b, err := json.Marshal(result) - check(err) - if redirect := r.FormValue("redirect"); validateRedirect(r, redirect) { - if strings.Contains(redirect, "%s") { - redirect = fmt.Sprintf( - redirect, - escape(string(b)), - ) - } - http.Redirect(w, r, redirect, http.StatusFound) - return - } - w.Header().Set("Cache-Control", "no-cache") - jsonType := "application/json" - if strings.Index(r.Header.Get("Accept"), jsonType) != -1 { - w.Header().Set("Content-Type", jsonType) - } - fmt.Fprintln(w, string(b)) -} - -func delete(w http.ResponseWriter, r *http.Request) { - key := extractKey(r) - parts := strings.Split(key, "/") - if len(parts) == 3 { - result := make(map[string]bool, 1) - context := appengine.NewContext(r) - err := memcache.Delete(context, key) - if err == nil { - result[key] = true - contentType, _ := url.QueryUnescape(parts[0]) - if imageTypes.MatchString(contentType) { - thumbnailKey := key + thumbSuffix + filepath.Ext(parts[2]) - err := memcache.Delete(context, thumbnailKey) - if err == nil { - result[thumbnailKey] = true - } - } - } - w.Header().Set("Content-Type", "application/json") - b, err := json.Marshal(result) - check(err) - fmt.Fprintln(w, string(b)) - } else { - http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed) - } -} - -func handle(w http.ResponseWriter, r *http.Request) { - params, err := url.ParseQuery(r.URL.RawQuery) - check(err) - w.Header().Add("Access-Control-Allow-Origin", "*") - w.Header().Add( - "Access-Control-Allow-Methods", - "OPTIONS, HEAD, GET, POST, DELETE", - ) - w.Header().Add( - "Access-Control-Allow-Headers", - "Content-Type, Content-Range, Content-Disposition", - ) - switch r.Method { - case "OPTIONS", "HEAD": - return - case "GET": - get(w, r) - case "POST": - if len(params["_method"]) > 0 && params["_method"][0] == "DELETE" { - delete(w, r) - } else { - post(w, r) - } - case "DELETE": - delete(w, r) - default: - http.Error(w, "501 Not Implemented", http.StatusNotImplemented) - } -} - -func init() { - http.HandleFunc("/", handle) -} diff --git a/library/blueimp_upload/server/gae-go/static/robots.txt b/library/blueimp_upload/server/gae-go/static/robots.txt deleted file mode 100644 index eb0536286..000000000 --- a/library/blueimp_upload/server/gae-go/static/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: diff --git a/library/blueimp_upload/server/gae-python/app.yaml b/library/blueimp_upload/server/gae-python/app.yaml deleted file mode 100644 index 764449b74..000000000 --- a/library/blueimp_upload/server/gae-python/app.yaml +++ /dev/null @@ -1,17 +0,0 @@ -application: jquery-file-upload -version: 1 -runtime: python27 -api_version: 1 -threadsafe: true - -libraries: -- name: PIL - version: latest - -handlers: -- url: /(favicon\.ico|robots\.txt) - static_files: static/\1 - upload: static/(.*) - expiration: '1d' -- url: /.* - script: main.app diff --git a/library/blueimp_upload/server/gae-python/main.py b/library/blueimp_upload/server/gae-python/main.py deleted file mode 100644 index 1955ac00a..000000000 --- a/library/blueimp_upload/server/gae-python/main.py +++ /dev/null @@ -1,204 +0,0 @@ -# -*- coding: utf-8 -*- -# -# jQuery File Upload Plugin GAE Python Example -# https://github.com/blueimp/jQuery-File-Upload -# -# Copyright 2011, Sebastian Tschan -# https://blueimp.net -# -# Licensed under the MIT license: -# https://opensource.org/licenses/MIT -# - -from google.appengine.api import memcache, images -import json -import os -import re -import urllib -import webapp2 - -DEBUG=os.environ.get('SERVER_SOFTWARE', '').startswith('Dev') -WEBSITE = 'https://blueimp.github.io/jQuery-File-Upload/' -MIN_FILE_SIZE = 1 # bytes -# Max file size is memcache limit (1MB) minus key size minus overhead: -MAX_FILE_SIZE = 999000 # bytes -IMAGE_TYPES = re.compile('image/(gif|p?jpeg|(x-)?png)') -ACCEPT_FILE_TYPES = IMAGE_TYPES -THUMB_MAX_WIDTH = 80 -THUMB_MAX_HEIGHT = 80 -THUMB_SUFFIX = '.'+str(THUMB_MAX_WIDTH)+'x'+str(THUMB_MAX_HEIGHT)+'.png' -EXPIRATION_TIME = 300 # seconds -# If set to None, only allow redirects to the referer protocol+host. -# Set to a regexp for custom pattern matching against the redirect value: -REDIRECT_ALLOW_TARGET = None - -class CORSHandler(webapp2.RequestHandler): - def cors(self): - headers = self.response.headers - headers['Access-Control-Allow-Origin'] = '*' - headers['Access-Control-Allow-Methods'] =\ - 'OPTIONS, HEAD, GET, POST, DELETE' - headers['Access-Control-Allow-Headers'] =\ - 'Content-Type, Content-Range, Content-Disposition' - - def initialize(self, request, response): - super(CORSHandler, self).initialize(request, response) - self.cors() - - def json_stringify(self, obj): - return json.dumps(obj, separators=(',', ':')) - - def options(self, *args, **kwargs): - pass - -class UploadHandler(CORSHandler): - def validate(self, file): - if file['size'] < MIN_FILE_SIZE: - file['error'] = 'File is too small' - elif file['size'] > MAX_FILE_SIZE: - file['error'] = 'File is too big' - elif not ACCEPT_FILE_TYPES.match(file['type']): - file['error'] = 'Filetype not allowed' - else: - return True - return False - - def validate_redirect(self, redirect): - if redirect: - if REDIRECT_ALLOW_TARGET: - return REDIRECT_ALLOW_TARGET.match(redirect) - referer = self.request.headers['referer'] - if referer: - from urlparse import urlparse - parts = urlparse(referer) - redirect_allow_target = '^' + re.escape( - parts.scheme + '://' + parts.netloc + '/' - ) - return re.match(redirect_allow_target, redirect) - return False - - def get_file_size(self, file): - file.seek(0, 2) # Seek to the end of the file - size = file.tell() # Get the position of EOF - file.seek(0) # Reset the file position to the beginning - return size - - def write_blob(self, data, info): - key = urllib.quote(info['type'].encode('utf-8'), '') +\ - '/' + str(hash(data)) +\ - '/' + urllib.quote(info['name'].encode('utf-8'), '') - try: - memcache.set(key, data, time=EXPIRATION_TIME) - except: #Failed to add to memcache - return (None, None) - thumbnail_key = None - if IMAGE_TYPES.match(info['type']): - try: - img = images.Image(image_data=data) - img.resize( - width=THUMB_MAX_WIDTH, - height=THUMB_MAX_HEIGHT - ) - thumbnail_data = img.execute_transforms() - thumbnail_key = key + THUMB_SUFFIX - memcache.set( - thumbnail_key, - thumbnail_data, - time=EXPIRATION_TIME - ) - except: #Failed to resize Image or add to memcache - thumbnail_key = None - return (key, thumbnail_key) - - def handle_upload(self): - results = [] - for name, fieldStorage in self.request.POST.items(): - if type(fieldStorage) is unicode: - continue - result = {} - result['name'] = urllib.unquote(fieldStorage.filename) - result['type'] = fieldStorage.type - result['size'] = self.get_file_size(fieldStorage.file) - if self.validate(result): - key, thumbnail_key = self.write_blob( - fieldStorage.value, - result - ) - if key is not None: - result['url'] = self.request.host_url + '/' + key - result['deleteUrl'] = result['url'] - result['deleteType'] = 'DELETE' - if thumbnail_key is not None: - result['thumbnailUrl'] = self.request.host_url +\ - '/' + thumbnail_key - else: - result['error'] = 'Failed to store uploaded file.' - results.append(result) - return results - - def head(self): - pass - - def get(self): - self.redirect(WEBSITE) - - def post(self): - if (self.request.get('_method') == 'DELETE'): - return self.delete() - result = {'files': self.handle_upload()} - s = self.json_stringify(result) - redirect = self.request.get('redirect') - if self.validate_redirect(redirect): - return self.redirect(str( - redirect.replace('%s', urllib.quote(s, ''), 1) - )) - if 'application/json' in self.request.headers.get('Accept'): - self.response.headers['Content-Type'] = 'application/json' - self.response.write(s) - -class FileHandler(CORSHandler): - def normalize(self, str): - return urllib.quote(urllib.unquote(str), '') - - def get(self, content_type, data_hash, file_name): - content_type = self.normalize(content_type) - file_name = self.normalize(file_name) - key = content_type + '/' + data_hash + '/' + file_name - data = memcache.get(key) - if data is None: - return self.error(404) - # Prevent browsers from MIME-sniffing the content-type: - self.response.headers['X-Content-Type-Options'] = 'nosniff' - content_type = urllib.unquote(content_type) - if not IMAGE_TYPES.match(content_type): - # Force a download dialog for non-image types: - content_type = 'application/octet-stream' - elif file_name.endswith(THUMB_SUFFIX): - content_type = 'image/png' - self.response.headers['Content-Type'] = content_type - # Cache for the expiration time: - self.response.headers['Cache-Control'] = 'public,max-age=%d' \ - % EXPIRATION_TIME - self.response.write(data) - - def delete(self, content_type, data_hash, file_name): - content_type = self.normalize(content_type) - file_name = self.normalize(file_name) - key = content_type + '/' + data_hash + '/' + file_name - result = {key: memcache.delete(key)} - content_type = urllib.unquote(content_type) - if IMAGE_TYPES.match(content_type): - thumbnail_key = key + THUMB_SUFFIX - result[thumbnail_key] = memcache.delete(thumbnail_key) - if 'application/json' in self.request.headers.get('Accept'): - self.response.headers['Content-Type'] = 'application/json' - s = self.json_stringify(result) - self.response.write(s) - -app = webapp2.WSGIApplication( - [ - ('/', UploadHandler), - ('/(.+)/([^/]+)/([^/]+)', FileHandler) - ], - debug=DEBUG -) diff --git a/library/blueimp_upload/server/gae-python/static/robots.txt b/library/blueimp_upload/server/gae-python/static/robots.txt deleted file mode 100644 index eb0536286..000000000 --- a/library/blueimp_upload/server/gae-python/static/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: diff --git a/library/blueimp_upload/server/php/Dockerfile b/library/blueimp_upload/server/php/Dockerfile deleted file mode 100644 index 8633fee74..000000000 --- a/library/blueimp_upload/server/php/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM php:7-apache - -# Enable the Apache Headers module: -RUN ln -s /etc/apache2/mods-available/headers.load \ - /etc/apache2/mods-enabled/headers.load - -# Enable the Apache Rewrite module: -RUN ln -s /etc/apache2/mods-available/rewrite.load \ - /etc/apache2/mods-enabled/rewrite.load - -# Install GD, Imagick and ImageMagick as image conversion options: -RUN DEBIAN_FRONTEND=noninteractive \ - apt-get update && apt-get install -y --no-install-recommends \ - libpng-dev \ - libjpeg-dev \ - libmagickwand-dev \ - imagemagick \ - && pecl install \ - imagick \ - && docker-php-ext-enable \ - imagick \ - && docker-php-ext-configure \ - gd --with-jpeg-dir=/usr/include/ \ - && docker-php-ext-install \ - gd \ - # Uninstall obsolete packages: - && apt-get autoremove -y \ - libpng-dev \ - libjpeg-dev \ - libmagickwand-dev \ - # Remove obsolete files: - && apt-get clean \ - && rm -rf \ - /tmp/* \ - /usr/share/doc/* \ - /var/cache/* \ - /var/lib/apt/lists/* \ - /var/tmp/* diff --git a/library/blueimp_upload/server/php/UploadHandler.php b/library/blueimp_upload/server/php/UploadHandler.php deleted file mode 100755 index 285d046aa..000000000 --- a/library/blueimp_upload/server/php/UploadHandler.php +++ /dev/null @@ -1,1411 +0,0 @@ -<?php -/* - * jQuery File Upload Plugin PHP Class - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -class UploadHandler -{ - - protected $options; - - // PHP File Upload error message codes: - // http://php.net/manual/en/features.file-upload.errors.php - protected $error_messages = array( - 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini', - 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', - 3 => 'The uploaded file was only partially uploaded', - 4 => 'No file was uploaded', - 6 => 'Missing a temporary folder', - 7 => 'Failed to write file to disk', - 8 => 'A PHP extension stopped the file upload', - 'post_max_size' => 'The uploaded file exceeds the post_max_size directive in php.ini', - 'max_file_size' => 'File is too big', - 'min_file_size' => 'File is too small', - 'accept_file_types' => 'Filetype not allowed', - 'max_number_of_files' => 'Maximum number of files exceeded', - 'max_width' => 'Image exceeds maximum width', - 'min_width' => 'Image requires a minimum width', - 'max_height' => 'Image exceeds maximum height', - 'min_height' => 'Image requires a minimum height', - 'abort' => 'File upload aborted', - 'image_resize' => 'Failed to resize image' - ); - - protected $image_objects = array(); - - public function __construct($options = null, $initialize = true, $error_messages = null) { - $this->response = array(); - $this->options = array( - 'script_url' => $this->get_full_url().'/'.$this->basename($this->get_server_var('SCRIPT_NAME')), - 'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/files/', - 'upload_url' => $this->get_full_url().'/files/', - 'input_stream' => 'php://input', - 'user_dirs' => false, - 'mkdir_mode' => 0755, - 'param_name' => 'files', - // Set the following option to 'POST', if your server does not support - // DELETE requests. This is a parameter sent to the client: - 'delete_type' => 'DELETE', - 'access_control_allow_origin' => '*', - 'access_control_allow_credentials' => false, - 'access_control_allow_methods' => array( - 'OPTIONS', - 'HEAD', - 'GET', - 'POST', - 'PUT', - 'PATCH', - 'DELETE' - ), - 'access_control_allow_headers' => array( - 'Content-Type', - 'Content-Range', - 'Content-Disposition' - ), - // By default, allow redirects to the referer protocol+host: - 'redirect_allow_target' => '/^'.preg_quote( - parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_SCHEME) - .'://' - .parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_HOST) - .'/', // Trailing slash to not match subdomains by mistake - '/' // preg_quote delimiter param - ).'/', - // Enable to provide file downloads via GET requests to the PHP script: - // 1. Set to 1 to download files via readfile method through PHP - // 2. Set to 2 to send a X-Sendfile header for lighttpd/Apache - // 3. Set to 3 to send a X-Accel-Redirect header for nginx - // If set to 2 or 3, adjust the upload_url option to the base path of - // the redirect parameter, e.g. '/files/'. - 'download_via_php' => false, - // Read files in chunks to avoid memory limits when download_via_php - // is enabled, set to 0 to disable chunked reading of files: - 'readfile_chunk_size' => 10 * 1024 * 1024, // 10 MiB - // Defines which files can be displayed inline when downloaded: - 'inline_file_types' => '/\.(gif|jpe?g|png)$/i', - // Defines which files (based on their names) are accepted for upload: - 'accept_file_types' => '/.+$/i', - // The php.ini settings upload_max_filesize and post_max_size - // take precedence over the following max_file_size setting: - 'max_file_size' => null, - 'min_file_size' => 1, - // The maximum number of files for the upload directory: - 'max_number_of_files' => null, - // Defines which files are handled as image files: - 'image_file_types' => '/\.(gif|jpe?g|png)$/i', - // Use exif_imagetype on all files to correct file extensions: - 'correct_image_extensions' => false, - // Image resolution restrictions: - 'max_width' => null, - 'max_height' => null, - 'min_width' => 1, - 'min_height' => 1, - // Set the following option to false to enable resumable uploads: - 'discard_aborted_uploads' => true, - // Set to 0 to use the GD library to scale and orient images, - // set to 1 to use imagick (if installed, falls back to GD), - // set to 2 to use the ImageMagick convert binary directly: - 'image_library' => 1, - // Uncomment the following to define an array of resource limits - // for imagick: - /* - 'imagick_resource_limits' => array( - imagick::RESOURCETYPE_MAP => 32, - imagick::RESOURCETYPE_MEMORY => 32 - ), - */ - // Command or path for to the ImageMagick convert binary: - 'convert_bin' => 'convert', - // Uncomment the following to add parameters in front of each - // ImageMagick convert call (the limit constraints seem only - // to have an effect if put in front): - /* - 'convert_params' => '-limit memory 32MiB -limit map 32MiB', - */ - // Command or path for to the ImageMagick identify binary: - 'identify_bin' => 'identify', - 'image_versions' => array( - // The empty image version key defines options for the original image. - // Keep in mind: these image manipulations are inherited by all other image versions from this point onwards. - // Also note that the property 'no_cache' is not inherited, since it's not a manipulation. - '' => array( - // Automatically rotate images based on EXIF meta data: - 'auto_orient' => true - ), - // You can add arrays to generate different versions. - // The name of the key is the name of the version (example: 'medium'). - // the array contains the options to apply. - /* - 'medium' => array( - 'max_width' => 800, - 'max_height' => 600 - ), - */ - 'thumbnail' => array( - // Uncomment the following to use a defined directory for the thumbnails - // instead of a subdirectory based on the version identifier. - // Make sure that this directory doesn't allow execution of files if you - // don't pose any restrictions on the type of uploaded files, e.g. by - // copying the .htaccess file from the files directory for Apache: - //'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/thumb/', - //'upload_url' => $this->get_full_url().'/thumb/', - // Uncomment the following to force the max - // dimensions and e.g. create square thumbnails: - // 'auto_orient' => true, - // 'crop' => true, - // 'jpeg_quality' => 70, - // 'no_cache' => true, (there's a caching option, but this remembers thumbnail sizes from a previous action!) - // 'strip' => true, (this strips EXIF tags, such as geolocation) - 'max_width' => 80, // either specify width, or set to 0. Then width is automatically adjusted - keeping aspect ratio to a specified max_height. - 'max_height' => 80 // either specify height, or set to 0. Then height is automatically adjusted - keeping aspect ratio to a specified max_width. - ) - ), - 'print_response' => true - ); - if ($options) { - $this->options = $options + $this->options; - } - if ($error_messages) { - $this->error_messages = $error_messages + $this->error_messages; - } - if ($initialize) { - $this->initialize(); - } - } - - protected function initialize() { - switch ($this->get_server_var('REQUEST_METHOD')) { - case 'OPTIONS': - case 'HEAD': - $this->head(); - break; - case 'GET': - $this->get($this->options['print_response']); - break; - case 'PATCH': - case 'PUT': - case 'POST': - $this->post($this->options['print_response']); - break; - case 'DELETE': - $this->delete($this->options['print_response']); - break; - default: - $this->header('HTTP/1.1 405 Method Not Allowed'); - } - } - - protected function get_full_url() { - $https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0 || - !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && - strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0; - return - ($https ? 'https://' : 'http://'). - (!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : ''). - (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME']. - ($https && $_SERVER['SERVER_PORT'] === 443 || - $_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))). - substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], '/')); - } - - protected function get_user_id() { - @session_start(); - return session_id(); - } - - protected function get_user_path() { - if ($this->options['user_dirs']) { - return $this->get_user_id().'/'; - } - return ''; - } - - protected function get_upload_path($file_name = null, $version = null) { - $file_name = $file_name ? $file_name : ''; - if (empty($version)) { - $version_path = ''; - } else { - $version_dir = @$this->options['image_versions'][$version]['upload_dir']; - if ($version_dir) { - return $version_dir.$this->get_user_path().$file_name; - } - $version_path = $version.'/'; - } - return $this->options['upload_dir'].$this->get_user_path() - .$version_path.$file_name; - } - - protected function get_query_separator($url) { - return strpos($url, '?') === false ? '?' : '&'; - } - - protected function get_download_url($file_name, $version = null, $direct = false) { - if (!$direct && $this->options['download_via_php']) { - $url = $this->options['script_url'] - .$this->get_query_separator($this->options['script_url']) - .$this->get_singular_param_name() - .'='.rawurlencode($file_name); - if ($version) { - $url .= '&version='.rawurlencode($version); - } - return $url.'&download=1'; - } - if (empty($version)) { - $version_path = ''; - } else { - $version_url = @$this->options['image_versions'][$version]['upload_url']; - if ($version_url) { - return $version_url.$this->get_user_path().rawurlencode($file_name); - } - $version_path = rawurlencode($version).'/'; - } - return $this->options['upload_url'].$this->get_user_path() - .$version_path.rawurlencode($file_name); - } - - protected function set_additional_file_properties($file) { - $file->deleteUrl = $this->options['script_url'] - .$this->get_query_separator($this->options['script_url']) - .$this->get_singular_param_name() - .'='.rawurlencode($file->name); - $file->deleteType = $this->options['delete_type']; - if ($file->deleteType !== 'DELETE') { - $file->deleteUrl .= '&_method=DELETE'; - } - if ($this->options['access_control_allow_credentials']) { - $file->deleteWithCredentials = true; - } - } - - // Fix for overflowing signed 32 bit integers, - // works for sizes up to 2^32-1 bytes (4 GiB - 1): - protected function fix_integer_overflow($size) { - if ($size < 0) { - $size += 2.0 * (PHP_INT_MAX + 1); - } - return $size; - } - - protected function get_file_size($file_path, $clear_stat_cache = false) { - if ($clear_stat_cache) { - if (version_compare(PHP_VERSION, '5.3.0') >= 0) { - clearstatcache(true, $file_path); - } else { - clearstatcache(); - } - } - return $this->fix_integer_overflow(filesize($file_path)); - } - - protected function is_valid_file_object($file_name) { - $file_path = $this->get_upload_path($file_name); - if (is_file($file_path) && $file_name[0] !== '.') { - return true; - } - return false; - } - - protected function get_file_object($file_name) { - if ($this->is_valid_file_object($file_name)) { - $file = new \stdClass(); - $file->name = $file_name; - $file->size = $this->get_file_size( - $this->get_upload_path($file_name) - ); - $file->url = $this->get_download_url($file->name); - foreach ($this->options['image_versions'] as $version => $options) { - if (!empty($version)) { - if (is_file($this->get_upload_path($file_name, $version))) { - $file->{$version.'Url'} = $this->get_download_url( - $file->name, - $version - ); - } - } - } - $this->set_additional_file_properties($file); - return $file; - } - return null; - } - - protected function get_file_objects($iteration_method = 'get_file_object') { - $upload_dir = $this->get_upload_path(); - if (!is_dir($upload_dir)) { - return array(); - } - return array_values(array_filter(array_map( - array($this, $iteration_method), - scandir($upload_dir) - ))); - } - - protected function count_file_objects() { - return count($this->get_file_objects('is_valid_file_object')); - } - - protected function get_error_message($error) { - return isset($this->error_messages[$error]) ? - $this->error_messages[$error] : $error; - } - - public function get_config_bytes($val) { - $val = trim($val); - $last = strtolower($val[strlen($val)-1]); - $val = (int)$val; - switch ($last) { - case 'g': - $val *= 1024; - case 'm': - $val *= 1024; - case 'k': - $val *= 1024; - } - return $this->fix_integer_overflow($val); - } - - protected function validate($uploaded_file, $file, $error, $index) { - if ($error) { - $file->error = $this->get_error_message($error); - return false; - } - $content_length = $this->fix_integer_overflow( - (int)$this->get_server_var('CONTENT_LENGTH') - ); - $post_max_size = $this->get_config_bytes(ini_get('post_max_size')); - if ($post_max_size && ($content_length > $post_max_size)) { - $file->error = $this->get_error_message('post_max_size'); - return false; - } - if (!preg_match($this->options['accept_file_types'], $file->name)) { - $file->error = $this->get_error_message('accept_file_types'); - return false; - } - if ($uploaded_file && is_uploaded_file($uploaded_file)) { - $file_size = $this->get_file_size($uploaded_file); - } else { - $file_size = $content_length; - } - if ($this->options['max_file_size'] && ( - $file_size > $this->options['max_file_size'] || - $file->size > $this->options['max_file_size']) - ) { - $file->error = $this->get_error_message('max_file_size'); - return false; - } - if ($this->options['min_file_size'] && - $file_size < $this->options['min_file_size']) { - $file->error = $this->get_error_message('min_file_size'); - return false; - } - if (is_int($this->options['max_number_of_files']) && - ($this->count_file_objects() >= $this->options['max_number_of_files']) && - // Ignore additional chunks of existing files: - !is_file($this->get_upload_path($file->name))) { - $file->error = $this->get_error_message('max_number_of_files'); - return false; - } - $max_width = @$this->options['max_width']; - $max_height = @$this->options['max_height']; - $min_width = @$this->options['min_width']; - $min_height = @$this->options['min_height']; - if (($max_width || $max_height || $min_width || $min_height) - && preg_match($this->options['image_file_types'], $file->name)) { - list($img_width, $img_height) = $this->get_image_size($uploaded_file); - - // If we are auto rotating the image by default, do the checks on - // the correct orientation - if ( - @$this->options['image_versions']['']['auto_orient'] && - function_exists('exif_read_data') && - ($exif = @exif_read_data($uploaded_file)) && - (((int) @$exif['Orientation']) >= 5) - ) { - $tmp = $img_width; - $img_width = $img_height; - $img_height = $tmp; - unset($tmp); - } - - } - if (!empty($img_width)) { - if ($max_width && $img_width > $max_width) { - $file->error = $this->get_error_message('max_width'); - return false; - } - if ($max_height && $img_height > $max_height) { - $file->error = $this->get_error_message('max_height'); - return false; - } - if ($min_width && $img_width < $min_width) { - $file->error = $this->get_error_message('min_width'); - return false; - } - if ($min_height && $img_height < $min_height) { - $file->error = $this->get_error_message('min_height'); - return false; - } - } - return true; - } - - protected function upcount_name_callback($matches) { - $index = isset($matches[1]) ? ((int)$matches[1]) + 1 : 1; - $ext = isset($matches[2]) ? $matches[2] : ''; - return ' ('.$index.')'.$ext; - } - - protected function upcount_name($name) { - return preg_replace_callback( - '/(?:(?: \(([\d]+)\))?(\.[^.]+))?$/', - array($this, 'upcount_name_callback'), - $name, - 1 - ); - } - - protected function get_unique_filename($file_path, $name, $size, $type, $error, - $index, $content_range) { - while(is_dir($this->get_upload_path($name))) { - $name = $this->upcount_name($name); - } - // Keep an existing filename if this is part of a chunked upload: - $uploaded_bytes = $this->fix_integer_overflow((int)$content_range[1]); - while (is_file($this->get_upload_path($name))) { - if ($uploaded_bytes === $this->get_file_size( - $this->get_upload_path($name))) { - break; - } - $name = $this->upcount_name($name); - } - return $name; - } - - protected function fix_file_extension($file_path, $name, $size, $type, $error, - $index, $content_range) { - // Add missing file extension for known image types: - if (strpos($name, '.') === false && - preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) { - $name .= '.'.$matches[1]; - } - if ($this->options['correct_image_extensions'] && - function_exists('exif_imagetype')) { - switch (@exif_imagetype($file_path)){ - case IMAGETYPE_JPEG: - $extensions = array('jpg', 'jpeg'); - break; - case IMAGETYPE_PNG: - $extensions = array('png'); - break; - case IMAGETYPE_GIF: - $extensions = array('gif'); - break; - } - // Adjust incorrect image file extensions: - if (!empty($extensions)) { - $parts = explode('.', $name); - $extIndex = count($parts) - 1; - $ext = strtolower(@$parts[$extIndex]); - if (!in_array($ext, $extensions)) { - $parts[$extIndex] = $extensions[0]; - $name = implode('.', $parts); - } - } - } - return $name; - } - - protected function trim_file_name($file_path, $name, $size, $type, $error, - $index, $content_range) { - // Remove path information and dots around the filename, to prevent uploading - // into different directories or replacing hidden system files. - // Also remove control characters and spaces (\x00..\x20) around the filename: - $name = trim($this->basename(stripslashes($name)), ".\x00..\x20"); - // Use a timestamp for empty filenames: - if (!$name) { - $name = str_replace('.', '-', microtime(true)); - } - return $name; - } - - protected function get_file_name($file_path, $name, $size, $type, $error, - $index, $content_range) { - $name = $this->trim_file_name($file_path, $name, $size, $type, $error, - $index, $content_range); - return $this->get_unique_filename( - $file_path, - $this->fix_file_extension($file_path, $name, $size, $type, $error, - $index, $content_range), - $size, - $type, - $error, - $index, - $content_range - ); - } - - protected function get_scaled_image_file_paths($file_name, $version) { - $file_path = $this->get_upload_path($file_name); - if (!empty($version)) { - $version_dir = $this->get_upload_path(null, $version); - if (!is_dir($version_dir)) { - mkdir($version_dir, $this->options['mkdir_mode'], true); - } - $new_file_path = $version_dir.'/'.$file_name; - } else { - $new_file_path = $file_path; - } - return array($file_path, $new_file_path); - } - - protected function gd_get_image_object($file_path, $func, $no_cache = false) { - if (empty($this->image_objects[$file_path]) || $no_cache) { - $this->gd_destroy_image_object($file_path); - $this->image_objects[$file_path] = $func($file_path); - } - return $this->image_objects[$file_path]; - } - - protected function gd_set_image_object($file_path, $image) { - $this->gd_destroy_image_object($file_path); - $this->image_objects[$file_path] = $image; - } - - protected function gd_destroy_image_object($file_path) { - $image = (isset($this->image_objects[$file_path])) ? $this->image_objects[$file_path] : null ; - return $image && imagedestroy($image); - } - - protected function gd_imageflip($image, $mode) { - if (function_exists('imageflip')) { - return imageflip($image, $mode); - } - $new_width = $src_width = imagesx($image); - $new_height = $src_height = imagesy($image); - $new_img = imagecreatetruecolor($new_width, $new_height); - $src_x = 0; - $src_y = 0; - switch ($mode) { - case '1': // flip on the horizontal axis - $src_y = $new_height - 1; - $src_height = -$new_height; - break; - case '2': // flip on the vertical axis - $src_x = $new_width - 1; - $src_width = -$new_width; - break; - case '3': // flip on both axes - $src_y = $new_height - 1; - $src_height = -$new_height; - $src_x = $new_width - 1; - $src_width = -$new_width; - break; - default: - return $image; - } - imagecopyresampled( - $new_img, - $image, - 0, - 0, - $src_x, - $src_y, - $new_width, - $new_height, - $src_width, - $src_height - ); - return $new_img; - } - - protected function gd_orient_image($file_path, $src_img) { - if (!function_exists('exif_read_data')) { - return false; - } - $exif = @exif_read_data($file_path); - if ($exif === false) { - return false; - } - $orientation = (int)@$exif['Orientation']; - if ($orientation < 2 || $orientation > 8) { - return false; - } - switch ($orientation) { - case 2: - $new_img = $this->gd_imageflip( - $src_img, - defined('IMG_FLIP_VERTICAL') ? IMG_FLIP_VERTICAL : 2 - ); - break; - case 3: - $new_img = imagerotate($src_img, 180, 0); - break; - case 4: - $new_img = $this->gd_imageflip( - $src_img, - defined('IMG_FLIP_HORIZONTAL') ? IMG_FLIP_HORIZONTAL : 1 - ); - break; - case 5: - $tmp_img = $this->gd_imageflip( - $src_img, - defined('IMG_FLIP_HORIZONTAL') ? IMG_FLIP_HORIZONTAL : 1 - ); - $new_img = imagerotate($tmp_img, 270, 0); - imagedestroy($tmp_img); - break; - case 6: - $new_img = imagerotate($src_img, 270, 0); - break; - case 7: - $tmp_img = $this->gd_imageflip( - $src_img, - defined('IMG_FLIP_VERTICAL') ? IMG_FLIP_VERTICAL : 2 - ); - $new_img = imagerotate($tmp_img, 270, 0); - imagedestroy($tmp_img); - break; - case 8: - $new_img = imagerotate($src_img, 90, 0); - break; - default: - return false; - } - $this->gd_set_image_object($file_path, $new_img); - return true; - } - - protected function gd_create_scaled_image($file_name, $version, $options) { - if (!function_exists('imagecreatetruecolor')) { - error_log('Function not found: imagecreatetruecolor'); - return false; - } - list($file_path, $new_file_path) = - $this->get_scaled_image_file_paths($file_name, $version); - $type = strtolower(substr(strrchr($file_name, '.'), 1)); - switch ($type) { - case 'jpg': - case 'jpeg': - $src_func = 'imagecreatefromjpeg'; - $write_func = 'imagejpeg'; - $image_quality = isset($options['jpeg_quality']) ? - $options['jpeg_quality'] : 75; - break; - case 'gif': - $src_func = 'imagecreatefromgif'; - $write_func = 'imagegif'; - $image_quality = null; - break; - case 'png': - $src_func = 'imagecreatefrompng'; - $write_func = 'imagepng'; - $image_quality = isset($options['png_quality']) ? - $options['png_quality'] : 9; - break; - default: - return false; - } - $src_img = $this->gd_get_image_object( - $file_path, - $src_func, - !empty($options['no_cache']) - ); - $image_oriented = false; - if (!empty($options['auto_orient']) && $this->gd_orient_image( - $file_path, - $src_img - )) { - $image_oriented = true; - $src_img = $this->gd_get_image_object( - $file_path, - $src_func - ); - } - $max_width = $img_width = imagesx($src_img); - $max_height = $img_height = imagesy($src_img); - if (!empty($options['max_width'])) { - $max_width = $options['max_width']; - } - if (!empty($options['max_height'])) { - $max_height = $options['max_height']; - } - $scale = min( - $max_width / $img_width, - $max_height / $img_height - ); - if ($scale >= 1) { - if ($image_oriented) { - return $write_func($src_img, $new_file_path, $image_quality); - } - if ($file_path !== $new_file_path) { - return copy($file_path, $new_file_path); - } - return true; - } - if (empty($options['crop'])) { - $new_width = $img_width * $scale; - $new_height = $img_height * $scale; - $dst_x = 0; - $dst_y = 0; - $new_img = imagecreatetruecolor($new_width, $new_height); - } else { - if (($img_width / $img_height) >= ($max_width / $max_height)) { - $new_width = $img_width / ($img_height / $max_height); - $new_height = $max_height; - } else { - $new_width = $max_width; - $new_height = $img_height / ($img_width / $max_width); - } - $dst_x = 0 - ($new_width - $max_width) / 2; - $dst_y = 0 - ($new_height - $max_height) / 2; - $new_img = imagecreatetruecolor($max_width, $max_height); - } - // Handle transparency in GIF and PNG images: - switch ($type) { - case 'gif': - case 'png': - imagecolortransparent($new_img, imagecolorallocate($new_img, 0, 0, 0)); - case 'png': - imagealphablending($new_img, false); - imagesavealpha($new_img, true); - break; - } - $success = imagecopyresampled( - $new_img, - $src_img, - $dst_x, - $dst_y, - 0, - 0, - $new_width, - $new_height, - $img_width, - $img_height - ) && $write_func($new_img, $new_file_path, $image_quality); - $this->gd_set_image_object($file_path, $new_img); - return $success; - } - - protected function imagick_get_image_object($file_path, $no_cache = false) { - if (empty($this->image_objects[$file_path]) || $no_cache) { - $this->imagick_destroy_image_object($file_path); - $image = new \Imagick(); - if (!empty($this->options['imagick_resource_limits'])) { - foreach ($this->options['imagick_resource_limits'] as $type => $limit) { - $image->setResourceLimit($type, $limit); - } - } - $image->readImage($file_path); - $this->image_objects[$file_path] = $image; - } - return $this->image_objects[$file_path]; - } - - protected function imagick_set_image_object($file_path, $image) { - $this->imagick_destroy_image_object($file_path); - $this->image_objects[$file_path] = $image; - } - - protected function imagick_destroy_image_object($file_path) { - $image = (isset($this->image_objects[$file_path])) ? $this->image_objects[$file_path] : null ; - return $image && $image->destroy(); - } - - protected function imagick_orient_image($image) { - $orientation = $image->getImageOrientation(); - $background = new \ImagickPixel('none'); - switch ($orientation) { - case \imagick::ORIENTATION_TOPRIGHT: // 2 - $image->flopImage(); // horizontal flop around y-axis - break; - case \imagick::ORIENTATION_BOTTOMRIGHT: // 3 - $image->rotateImage($background, 180); - break; - case \imagick::ORIENTATION_BOTTOMLEFT: // 4 - $image->flipImage(); // vertical flip around x-axis - break; - case \imagick::ORIENTATION_LEFTTOP: // 5 - $image->flopImage(); // horizontal flop around y-axis - $image->rotateImage($background, 270); - break; - case \imagick::ORIENTATION_RIGHTTOP: // 6 - $image->rotateImage($background, 90); - break; - case \imagick::ORIENTATION_RIGHTBOTTOM: // 7 - $image->flipImage(); // vertical flip around x-axis - $image->rotateImage($background, 270); - break; - case \imagick::ORIENTATION_LEFTBOTTOM: // 8 - $image->rotateImage($background, 270); - break; - default: - return false; - } - $image->setImageOrientation(\imagick::ORIENTATION_TOPLEFT); // 1 - return true; - } - - protected function imagick_create_scaled_image($file_name, $version, $options) { - list($file_path, $new_file_path) = - $this->get_scaled_image_file_paths($file_name, $version); - $image = $this->imagick_get_image_object( - $file_path, - !empty($options['crop']) || !empty($options['no_cache']) - ); - if ($image->getImageFormat() === 'GIF') { - // Handle animated GIFs: - $images = $image->coalesceImages(); - foreach ($images as $frame) { - $image = $frame; - $this->imagick_set_image_object($file_name, $image); - break; - } - } - $image_oriented = false; - if (!empty($options['auto_orient'])) { - $image_oriented = $this->imagick_orient_image($image); - } - - $image_resize = false; - $new_width = $max_width = $img_width = $image->getImageWidth(); - $new_height = $max_height = $img_height = $image->getImageHeight(); - - // use isset(). User might be setting max_width = 0 (auto in regular resizing). Value 0 would be considered empty when you use empty() - if (isset($options['max_width'])) { - $image_resize = true; - $new_width = $max_width = $options['max_width']; - } - if (isset($options['max_height'])) { - $image_resize = true; - $new_height = $max_height = $options['max_height']; - } - - $image_strip = (isset($options['strip']) ? $options['strip'] : false); - - if ( !$image_oriented && ($max_width >= $img_width) && ($max_height >= $img_height) && !$image_strip && empty($options["jpeg_quality"]) ) { - if ($file_path !== $new_file_path) { - return copy($file_path, $new_file_path); - } - return true; - } - $crop = (isset($options['crop']) ? $options['crop'] : false); - - if ($crop) { - $x = 0; - $y = 0; - if (($img_width / $img_height) >= ($max_width / $max_height)) { - $new_width = 0; // Enables proportional scaling based on max_height - $x = ($img_width / ($img_height / $max_height) - $max_width) / 2; - } else { - $new_height = 0; // Enables proportional scaling based on max_width - $y = ($img_height / ($img_width / $max_width) - $max_height) / 2; - } - } - $success = $image->resizeImage( - $new_width, - $new_height, - isset($options['filter']) ? $options['filter'] : \imagick::FILTER_LANCZOS, - isset($options['blur']) ? $options['blur'] : 1, - $new_width && $new_height // fit image into constraints if not to be cropped - ); - if ($success && $crop) { - $success = $image->cropImage( - $max_width, - $max_height, - $x, - $y - ); - if ($success) { - $success = $image->setImagePage($max_width, $max_height, 0, 0); - } - } - $type = strtolower(substr(strrchr($file_name, '.'), 1)); - switch ($type) { - case 'jpg': - case 'jpeg': - if (!empty($options['jpeg_quality'])) { - $image->setImageCompression(\imagick::COMPRESSION_JPEG); - $image->setImageCompressionQuality($options['jpeg_quality']); - } - break; - } - if ( $image_strip ) { - $image->stripImage(); - } - return $success && $image->writeImage($new_file_path); - } - - protected function imagemagick_create_scaled_image($file_name, $version, $options) { - list($file_path, $new_file_path) = - $this->get_scaled_image_file_paths($file_name, $version); - $resize = @$options['max_width'] - .(empty($options['max_height']) ? '' : 'X'.$options['max_height']); - if (!$resize && empty($options['auto_orient'])) { - if ($file_path !== $new_file_path) { - return copy($file_path, $new_file_path); - } - return true; - } - $cmd = $this->options['convert_bin']; - if (!empty($this->options['convert_params'])) { - $cmd .= ' '.$this->options['convert_params']; - } - $cmd .= ' '.escapeshellarg($file_path); - if (!empty($options['auto_orient'])) { - $cmd .= ' -auto-orient'; - } - if ($resize) { - // Handle animated GIFs: - $cmd .= ' -coalesce'; - if (empty($options['crop'])) { - $cmd .= ' -resize '.escapeshellarg($resize.'>'); - } else { - $cmd .= ' -resize '.escapeshellarg($resize.'^'); - $cmd .= ' -gravity center'; - $cmd .= ' -crop '.escapeshellarg($resize.'+0+0'); - } - // Make sure the page dimensions are correct (fixes offsets of animated GIFs): - $cmd .= ' +repage'; - } - if (!empty($options['convert_params'])) { - $cmd .= ' '.$options['convert_params']; - } - $cmd .= ' '.escapeshellarg($new_file_path); - exec($cmd, $output, $error); - if ($error) { - error_log(implode('\n', $output)); - return false; - } - return true; - } - - protected function get_image_size($file_path) { - if ($this->options['image_library']) { - if (extension_loaded('imagick')) { - $image = new \Imagick(); - try { - if (@$image->pingImage($file_path)) { - $dimensions = array($image->getImageWidth(), $image->getImageHeight()); - $image->destroy(); - return $dimensions; - } - return false; - } catch (\Exception $e) { - error_log($e->getMessage()); - } - } - if ($this->options['image_library'] === 2) { - $cmd = $this->options['identify_bin']; - $cmd .= ' -ping '.escapeshellarg($file_path); - exec($cmd, $output, $error); - if (!$error && !empty($output)) { - // image.jpg JPEG 1920x1080 1920x1080+0+0 8-bit sRGB 465KB 0.000u 0:00.000 - $infos = preg_split('/\s+/', substr($output[0], strlen($file_path))); - $dimensions = preg_split('/x/', $infos[2]); - return $dimensions; - } - return false; - } - } - if (!function_exists('getimagesize')) { - error_log('Function not found: getimagesize'); - return false; - } - return @getimagesize($file_path); - } - - protected function create_scaled_image($file_name, $version, $options) { - if ($this->options['image_library'] === 2) { - return $this->imagemagick_create_scaled_image($file_name, $version, $options); - } - if ($this->options['image_library'] && extension_loaded('imagick')) { - return $this->imagick_create_scaled_image($file_name, $version, $options); - } - return $this->gd_create_scaled_image($file_name, $version, $options); - } - - protected function destroy_image_object($file_path) { - if ($this->options['image_library'] && extension_loaded('imagick')) { - return $this->imagick_destroy_image_object($file_path); - } - } - - protected function is_valid_image_file($file_path) { - if (!preg_match($this->options['image_file_types'], $file_path)) { - return false; - } - if (function_exists('exif_imagetype')) { - return @exif_imagetype($file_path); - } - $image_info = $this->get_image_size($file_path); - return $image_info && $image_info[0] && $image_info[1]; - } - - protected function handle_image_file($file_path, $file) { - $failed_versions = array(); - foreach ($this->options['image_versions'] as $version => $options) { - if ($this->create_scaled_image($file->name, $version, $options)) { - if (!empty($version)) { - $file->{$version.'Url'} = $this->get_download_url( - $file->name, - $version - ); - } else { - $file->size = $this->get_file_size($file_path, true); - } - } else { - $failed_versions[] = $version ? $version : 'original'; - } - } - if (count($failed_versions)) { - $file->error = $this->get_error_message('image_resize') - .' ('.implode($failed_versions, ', ').')'; - } - // Free memory: - $this->destroy_image_object($file_path); - } - - protected function handle_file_upload($uploaded_file, $name, $size, $type, $error, - $index = null, $content_range = null) { - $file = new \stdClass(); - $file->name = $this->get_file_name($uploaded_file, $name, $size, $type, $error, - $index, $content_range); - $file->size = $this->fix_integer_overflow((int)$size); - $file->type = $type; - if ($this->validate($uploaded_file, $file, $error, $index)) { - $this->handle_form_data($file, $index); - $upload_dir = $this->get_upload_path(); - if (!is_dir($upload_dir)) { - mkdir($upload_dir, $this->options['mkdir_mode'], true); - } - $file_path = $this->get_upload_path($file->name); - $append_file = $content_range && is_file($file_path) && - $file->size > $this->get_file_size($file_path); - if ($uploaded_file && is_uploaded_file($uploaded_file)) { - // multipart/formdata uploads (POST method uploads) - if ($append_file) { - file_put_contents( - $file_path, - fopen($uploaded_file, 'r'), - FILE_APPEND - ); - } else { - move_uploaded_file($uploaded_file, $file_path); - } - } else { - // Non-multipart uploads (PUT method support) - file_put_contents( - $file_path, - fopen($this->options['input_stream'], 'r'), - $append_file ? FILE_APPEND : 0 - ); - } - $file_size = $this->get_file_size($file_path, $append_file); - if ($file_size === $file->size) { - $file->url = $this->get_download_url($file->name); - if ($this->is_valid_image_file($file_path)) { - $this->handle_image_file($file_path, $file); - } - } else { - $file->size = $file_size; - if (!$content_range && $this->options['discard_aborted_uploads']) { - unlink($file_path); - $file->error = $this->get_error_message('abort'); - } - } - $this->set_additional_file_properties($file); - } - return $file; - } - - protected function readfile($file_path) { - $file_size = $this->get_file_size($file_path); - $chunk_size = $this->options['readfile_chunk_size']; - if ($chunk_size && $file_size > $chunk_size) { - $handle = fopen($file_path, 'rb'); - while (!feof($handle)) { - echo fread($handle, $chunk_size); - @ob_flush(); - @flush(); - } - fclose($handle); - return $file_size; - } - return readfile($file_path); - } - - protected function body($str) { - echo $str; - } - - protected function header($str) { - header($str); - } - - protected function get_upload_data($id) { - return @$_FILES[$id]; - } - - protected function get_post_param($id) { - return @$_POST[$id]; - } - - protected function get_query_param($id) { - return @$_GET[$id]; - } - - protected function get_server_var($id) { - return @$_SERVER[$id]; - } - - protected function handle_form_data($file, $index) { - // Handle form data, e.g. $_POST['description'][$index] - } - - protected function get_version_param() { - return $this->basename(stripslashes($this->get_query_param('version'))); - } - - protected function get_singular_param_name() { - return substr($this->options['param_name'], 0, -1); - } - - protected function get_file_name_param() { - $name = $this->get_singular_param_name(); - return $this->basename(stripslashes($this->get_query_param($name))); - } - - protected function get_file_names_params() { - $params = $this->get_query_param($this->options['param_name']); - if (!$params) { - return null; - } - foreach ($params as $key => $value) { - $params[$key] = $this->basename(stripslashes($value)); - } - return $params; - } - - protected function get_file_type($file_path) { - switch (strtolower(pathinfo($file_path, PATHINFO_EXTENSION))) { - case 'jpeg': - case 'jpg': - return 'image/jpeg'; - case 'png': - return 'image/png'; - case 'gif': - return 'image/gif'; - default: - return ''; - } - } - - protected function download() { - switch ($this->options['download_via_php']) { - case 1: - $redirect_header = null; - break; - case 2: - $redirect_header = 'X-Sendfile'; - break; - case 3: - $redirect_header = 'X-Accel-Redirect'; - break; - default: - return $this->header('HTTP/1.1 403 Forbidden'); - } - $file_name = $this->get_file_name_param(); - if (!$this->is_valid_file_object($file_name)) { - return $this->header('HTTP/1.1 404 Not Found'); - } - if ($redirect_header) { - return $this->header( - $redirect_header.': '.$this->get_download_url( - $file_name, - $this->get_version_param(), - true - ) - ); - } - $file_path = $this->get_upload_path($file_name, $this->get_version_param()); - // Prevent browsers from MIME-sniffing the content-type: - $this->header('X-Content-Type-Options: nosniff'); - if (!preg_match($this->options['inline_file_types'], $file_name)) { - $this->header('Content-Type: application/octet-stream'); - $this->header('Content-Disposition: attachment; filename="'.$file_name.'"'); - } else { - $this->header('Content-Type: '.$this->get_file_type($file_path)); - $this->header('Content-Disposition: inline; filename="'.$file_name.'"'); - } - $this->header('Content-Length: '.$this->get_file_size($file_path)); - $this->header('Last-Modified: '.gmdate('D, d M Y H:i:s T', filemtime($file_path))); - $this->readfile($file_path); - } - - protected function send_content_type_header() { - $this->header('Vary: Accept'); - if (strpos($this->get_server_var('HTTP_ACCEPT'), 'application/json') !== false) { - $this->header('Content-type: application/json'); - } else { - $this->header('Content-type: text/plain'); - } - } - - protected function send_access_control_headers() { - $this->header('Access-Control-Allow-Origin: '.$this->options['access_control_allow_origin']); - $this->header('Access-Control-Allow-Credentials: ' - .($this->options['access_control_allow_credentials'] ? 'true' : 'false')); - $this->header('Access-Control-Allow-Methods: ' - .implode(', ', $this->options['access_control_allow_methods'])); - $this->header('Access-Control-Allow-Headers: ' - .implode(', ', $this->options['access_control_allow_headers'])); - } - - public function generate_response($content, $print_response = true) { - $this->response = $content; - if ($print_response) { - $json = json_encode($content); - $redirect = stripslashes($this->get_post_param('redirect')); - if ($redirect && preg_match($this->options['redirect_allow_target'], $redirect)) { - $this->header('Location: '.sprintf($redirect, rawurlencode($json))); - return; - } - $this->head(); - if ($this->get_server_var('HTTP_CONTENT_RANGE')) { - $files = isset($content[$this->options['param_name']]) ? - $content[$this->options['param_name']] : null; - if ($files && is_array($files) && is_object($files[0]) && $files[0]->size) { - $this->header('Range: 0-'.( - $this->fix_integer_overflow((int)$files[0]->size) - 1 - )); - } - } - $this->body($json); - } - return $content; - } - - public function get_response () { - return $this->response; - } - - public function head() { - $this->header('Pragma: no-cache'); - $this->header('Cache-Control: no-store, no-cache, must-revalidate'); - $this->header('Content-Disposition: inline; filename="files.json"'); - // Prevent Internet Explorer from MIME-sniffing the content-type: - $this->header('X-Content-Type-Options: nosniff'); - if ($this->options['access_control_allow_origin']) { - $this->send_access_control_headers(); - } - $this->send_content_type_header(); - } - - public function get($print_response = true) { - if ($print_response && $this->get_query_param('download')) { - return $this->download(); - } - $file_name = $this->get_file_name_param(); - if ($file_name) { - $response = array( - $this->get_singular_param_name() => $this->get_file_object($file_name) - ); - } else { - $response = array( - $this->options['param_name'] => $this->get_file_objects() - ); - } - return $this->generate_response($response, $print_response); - } - - public function post($print_response = true) { - if ($this->get_query_param('_method') === 'DELETE') { - return $this->delete($print_response); - } - $upload = $this->get_upload_data($this->options['param_name']); - // Parse the Content-Disposition header, if available: - $content_disposition_header = $this->get_server_var('HTTP_CONTENT_DISPOSITION'); - $file_name = $content_disposition_header ? - rawurldecode(preg_replace( - '/(^[^"]+")|("$)/', - '', - $content_disposition_header - )) : null; - // Parse the Content-Range header, which has the following form: - // Content-Range: bytes 0-524287/2000000 - $content_range_header = $this->get_server_var('HTTP_CONTENT_RANGE'); - $content_range = $content_range_header ? - preg_split('/[^0-9]+/', $content_range_header) : null; - $size = $content_range ? $content_range[3] : null; - $files = array(); - if ($upload) { - if (is_array($upload['tmp_name'])) { - // param_name is an array identifier like "files[]", - // $upload is a multi-dimensional array: - foreach ($upload['tmp_name'] as $index => $value) { - $files[] = $this->handle_file_upload( - $upload['tmp_name'][$index], - $file_name ? $file_name : $upload['name'][$index], - $size ? $size : $upload['size'][$index], - $upload['type'][$index], - $upload['error'][$index], - $index, - $content_range - ); - } - } else { - // param_name is a single object identifier like "file", - // $upload is a one-dimensional array: - $files[] = $this->handle_file_upload( - isset($upload['tmp_name']) ? $upload['tmp_name'] : null, - $file_name ? $file_name : (isset($upload['name']) ? - $upload['name'] : null), - $size ? $size : (isset($upload['size']) ? - $upload['size'] : $this->get_server_var('CONTENT_LENGTH')), - isset($upload['type']) ? - $upload['type'] : $this->get_server_var('CONTENT_TYPE'), - isset($upload['error']) ? $upload['error'] : null, - null, - $content_range - ); - } - } - $response = array($this->options['param_name'] => $files); - return $this->generate_response($response, $print_response); - } - - public function delete($print_response = true) { - $file_names = $this->get_file_names_params(); - if (empty($file_names)) { - $file_names = array($this->get_file_name_param()); - } - $response = array(); - foreach ($file_names as $file_name) { - $file_path = $this->get_upload_path($file_name); - $success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path); - if ($success) { - foreach ($this->options['image_versions'] as $version => $options) { - if (!empty($version)) { - $file = $this->get_upload_path($file_name, $version); - if (is_file($file)) { - unlink($file); - } - } - } - } - $response[$file_name] = $success; - } - return $this->generate_response($response, $print_response); - } - - protected function basename($filepath, $suffix = null) { - $splited = preg_split('/\//', rtrim ($filepath, '/ ')); - return substr(basename('X'.$splited[count($splited)-1], $suffix), 1); - } -} diff --git a/library/blueimp_upload/server/php/docker-compose.yml b/library/blueimp_upload/server/php/docker-compose.yml deleted file mode 100644 index 74eabf7dc..000000000 --- a/library/blueimp_upload/server/php/docker-compose.yml +++ /dev/null @@ -1,9 +0,0 @@ -version: '2.3' -services: - apache: - build: ./ - network_mode: bridge - ports: - - "80:80" - volumes: - - "../../:/var/www/html" diff --git a/library/blueimp_upload/server/php/files/.gitignore b/library/blueimp_upload/server/php/files/.gitignore deleted file mode 100644 index e24a60fae..000000000 --- a/library/blueimp_upload/server/php/files/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -* -!.gitignore -!.htaccess diff --git a/library/blueimp_upload/server/php/files/.htaccess b/library/blueimp_upload/server/php/files/.htaccess deleted file mode 100644 index 6f454afb9..000000000 --- a/library/blueimp_upload/server/php/files/.htaccess +++ /dev/null @@ -1,26 +0,0 @@ -# To enable the Headers module, execute the following command and reload Apache: -# sudo a2enmod headers - -# The following directives prevent the execution of script files -# in the context of the website. -# They also force the content-type application/octet-stream and -# force browsers to display a download dialog for non-image files. -SetHandler default-handler -ForceType application/octet-stream -Header set Content-Disposition attachment - -# The following unsets the forced type and Content-Disposition headers -# for known image files: -<FilesMatch "(?i)\.(gif|jpe?g|png)$"> - ForceType none - Header unset Content-Disposition -</FilesMatch> - -# The following directive prevents browsers from MIME-sniffing the content-type. -# This is an important complement to the ForceType directive above: -Header set X-Content-Type-Options nosniff - -# Uncomment the following lines to prevent unauthorized download of files: -#AuthName "Authorization required" -#AuthType Basic -#require valid-user diff --git a/library/blueimp_upload/test/index.html b/library/blueimp_upload/test/index.html deleted file mode 100644 index 0b5cf57b7..000000000 --- a/library/blueimp_upload/test/index.html +++ /dev/null @@ -1,172 +0,0 @@ -<!DOCTYPE HTML> -<!-- -/* - * jQuery File Upload Plugin Test - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ ---> -<html lang="en"> -<head> -<!-- Force latest IE rendering engine or ChromeFrame if installed --> -<!--[if IE]> -<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> -<![endif]--> -<meta charset="utf-8"> -<title>jQuery File Upload Plugin Test</title> -<meta name="viewport" content="width=device-width, initial-scale=1.0"> -<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-1.23.1.css"> -</head> -<body> -<h1 id="qunit-header">jQuery File Upload Plugin Test</h1> -<h2 id="qunit-banner"></h2> -<div id="qunit-testrunner-toolbar"></div> -<h2 id="qunit-userAgent"></h2> -<ol id="qunit-tests"></ol> -<div id="qunit-fixture"> - <!-- The file upload form used as target for the file upload widget --> - <form id="fileupload" action="../server/php/" method="POST" enctype="multipart/form-data"> - <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --> - <div class="row fileupload-buttonbar"> - <div class="col-lg-7"> - <!-- The fileinput-button span is used to style the file input field as button --> - <span class="btn btn-success fileinput-button"> - <i class="icon-plus icon-white"></i> - <span>Add files...</span> - <input type="file" name="files[]" multiple> - </span> - <button type="submit" class="btn btn-primary start"> - <i class="icon-upload icon-white"></i> - <span>Start upload</span> - </button> - <button type="reset" class="btn btn-warning cancel"> - <i class="icon-ban-circle icon-white"></i> - <span>Cancel upload</span> - </button> - <button type="button" class="btn btn-danger delete"> - <i class="icon-trash icon-white"></i> - <span>Delete</span> - </button> - <input type="checkbox" class="toggle"> - <!-- The global file processing state --> - <span class="fileupload-process"></span> - </div> - <!-- The global progress state --> - <div class="col-lg-5 fileupload-progress"> - <!-- The global progress bar --> - <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100"> - <div class="progress-bar progress-bar-success" style="width:0%;"></div> - </div> - <!-- The extended global progress state --> - <div class="progress-extended"> </div> - </div> - </div> - <!-- The table listing the files available for upload/download --> - <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table> - </form> -</div> -<!-- The template to display files available for upload --> -<script id="template-upload" type="text/x-tmpl"> -{% for (var i=0, file; file=o.files[i]; i++) { %} - <tr class="template-upload"> - <td> - <span class="preview"></span> - </td> - <td> - <p class="name">{%=file.name%}</p> - <strong class="error text-danger"></strong> - </td> - <td> - <p class="size">Processing...</p> - <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div> - </td> - <td> - {% if (!i && !o.options.autoUpload) { %} - <button class="btn btn-primary start" disabled> - <i class="glyphicon glyphicon-upload"></i> - <span>Start</span> - </button> - {% } %} - {% if (!i) { %} - <button class="btn btn-warning cancel"> - <i class="glyphicon glyphicon-ban-circle"></i> - <span>Cancel</span> - </button> - {% } %} - </td> - </tr> -{% } %} -</script> -<!-- The template to display files available for download --> -<script id="template-download" type="text/x-tmpl"> -{% for (var i=0, file; file=o.files[i]; i++) { %} - <tr class="template-download"> - <td> - <span class="preview"> - {% if (file.thumbnailUrl) { %} - <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a> - {% } %} - </span> - </td> - <td> - <p class="name"> - {% if (file.url) { %} - <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a> - {% } else { %} - <span>{%=file.name%}</span> - {% } %} - </p> - {% if (file.error) { %} - <div><span class="label label-danger">Error</span> {%=file.error%}</div> - {% } %} - </td> - <td> - <span class="size">{%=o.formatFileSize(file.size)%}</span> - </td> - <td> - {% if (file.deleteUrl) { %} - <button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}> - <i class="glyphicon glyphicon-trash"></i> - <span>Delete</span> - </button> - <input type="checkbox" name="delete" value="1" class="toggle"> - {% } else { %} - <button class="btn btn-warning cancel"> - <i class="glyphicon glyphicon-ban-circle"></i> - <span>Cancel</span> - </button> - {% } %} - </td> - </tr> -{% } %} -</script> -<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> -<script src="../js/vendor/jquery.ui.widget.js"></script> -<script src="https://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script> -<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script> -<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script> -<script src="../js/jquery.iframe-transport.js"></script> -<script src="../js/jquery.fileupload.js"></script> -<script> -/* global window, $ */ -window.testBasicWidget = $.blueimp.fileupload; -</script> -<script src="../js/jquery.fileupload-process.js"></script> -<script src="../js/jquery.fileupload-image.js"></script> -<script src="../js/jquery.fileupload-audio.js"></script> -<script src="../js/jquery.fileupload-video.js"></script> -<script src="../js/jquery.fileupload-validate.js"></script> -<script src="../js/jquery.fileupload-ui.js"></script> -<script> -/* global window, $ */ -window.testUIWidget = $.blueimp.fileupload; -</script> -<script src="https://code.jquery.com/qunit/qunit-1.23.1.js"></script> -<script src="test.js"></script> -</body> -</html> diff --git a/library/blueimp_upload/test/test.js b/library/blueimp_upload/test/test.js deleted file mode 100644 index 452127567..000000000 --- a/library/blueimp_upload/test/test.js +++ /dev/null @@ -1,1292 +0,0 @@ -/* - * jQuery File Upload Plugin Test - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* global $, QUnit, window, document, expect, module, test, asyncTest, start, ok, strictEqual, notStrictEqual */ - -$(function () { - // jshint nomen:false - 'use strict'; - - QUnit.done = function () { - // Delete all uploaded files: - var url = $('#fileupload').prop('action'); - $.getJSON(url, function (result) { - $.each(result.files, function (index, file) { - $.ajax({ - url: url + '?file=' + encodeURIComponent(file.name), - type: 'DELETE' - }); - }); - }); - }; - - var lifecycle = { - setup: function () { - // Set the .fileupload method to the basic widget method: - $.widget('blueimp.fileupload', window.testBasicWidget, {}); - }, - teardown: function () { - // Remove all remaining event listeners: - $(document).unbind(); - } - }, - lifecycleUI = { - setup: function () { - // Set the .fileupload method to the UI widget method: - $.widget('blueimp.fileupload', window.testUIWidget, {}); - }, - teardown: function () { - // Remove all remaining event listeners: - $(document).unbind(); - } - }; - - module('Initialization', lifecycle); - - test('Widget initialization', function () { - var fu = $('#fileupload').fileupload(); - ok(fu.data('blueimp-fileupload') || fu.data('fileupload')); - }); - - test('Data attribute options', function () { - $('#fileupload').attr('data-url', 'http://example.org'); - $('#fileupload').fileupload(); - strictEqual( - $('#fileupload').fileupload('option', 'url'), - 'http://example.org' - ); - }); - - test('File input initialization', function () { - var fu = $('#fileupload').fileupload(); - ok( - fu.fileupload('option', 'fileInput').length, - 'File input field inside of the widget' - ); - ok( - fu.fileupload('option', 'fileInput').length, - 'Widget element as file input field' - ); - }); - - test('Drop zone initialization', function () { - ok($('#fileupload').fileupload() - .fileupload('option', 'dropZone').length); - }); - - test('Paste zone initialization', function () { - ok($('#fileupload').fileupload({pasteZone: document}) - .fileupload('option', 'pasteZone').length); - }); - - test('Event listeners initialization', function () { - expect( - $.support.xhrFormDataFileUpload ? 4 : 1 - ); - var eo = { - originalEvent: { - dataTransfer: {files: [{}], types: ['Files']}, - clipboardData: {items: [{}]} - } - }, - fu = $('#fileupload').fileupload({ - pasteZone: document, - dragover: function () { - ok(true, 'Triggers dragover callback'); - return false; - }, - drop: function () { - ok(true, 'Triggers drop callback'); - return false; - }, - paste: function () { - ok(true, 'Triggers paste callback'); - return false; - }, - change: function () { - ok(true, 'Triggers change callback'); - return false; - } - }), - fileInput = fu.fileupload('option', 'fileInput'), - dropZone = fu.fileupload('option', 'dropZone'), - pasteZone = fu.fileupload('option', 'pasteZone'); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - }); - - module('API', lifecycle); - - test('destroy', function () { - expect(4); - var eo = { - originalEvent: { - dataTransfer: {files: [{}], types: ['Files']}, - clipboardData: {items: [{}]} - } - }, - options = { - pasteZone: document, - dragover: function () { - ok(true, 'Triggers dragover callback'); - return false; - }, - drop: function () { - ok(true, 'Triggers drop callback'); - return false; - }, - paste: function () { - ok(true, 'Triggers paste callback'); - return false; - }, - change: function () { - ok(true, 'Triggers change callback'); - return false; - } - }, - fu = $('#fileupload').fileupload(options), - fileInput = fu.fileupload('option', 'fileInput'), - dropZone = fu.fileupload('option', 'dropZone'), - pasteZone = fu.fileupload('option', 'pasteZone'); - dropZone.bind('dragover', options.dragover); - dropZone.bind('drop', options.drop); - pasteZone.bind('paste', options.paste); - fileInput.bind('change', options.change); - fu.fileupload('destroy'); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - }); - - test('disable/enable', function () { - expect( - $.support.xhrFormDataFileUpload ? 4 : 1 - ); - var eo = { - originalEvent: { - dataTransfer: {files: [{}], types: ['Files']}, - clipboardData: {items: [{}]} - } - }, - fu = $('#fileupload').fileupload({ - pasteZone: document, - dragover: function () { - ok(true, 'Triggers dragover callback'); - return false; - }, - drop: function () { - ok(true, 'Triggers drop callback'); - return false; - }, - paste: function () { - ok(true, 'Triggers paste callback'); - return false; - }, - change: function () { - ok(true, 'Triggers change callback'); - return false; - } - }), - fileInput = fu.fileupload('option', 'fileInput'), - dropZone = fu.fileupload('option', 'dropZone'), - pasteZone = fu.fileupload('option', 'pasteZone'); - fu.fileupload('disable'); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - fu.fileupload('enable'); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - }); - - test('option', function () { - expect( - $.support.xhrFormDataFileUpload ? 10 : 7 - ); - var eo = { - originalEvent: { - dataTransfer: {files: [{}], types: ['Files']}, - clipboardData: {items: [{}]} - } - }, - fu = $('#fileupload').fileupload({ - pasteZone: document, - dragover: function () { - ok(true, 'Triggers dragover callback'); - return false; - }, - drop: function () { - ok(true, 'Triggers drop callback'); - return false; - }, - paste: function () { - ok(true, 'Triggers paste callback'); - return false; - }, - change: function () { - ok(true, 'Triggers change callback'); - return false; - } - }), - fileInput = fu.fileupload('option', 'fileInput'), - dropZone = fu.fileupload('option', 'dropZone'), - pasteZone = fu.fileupload('option', 'pasteZone'); - fu.fileupload('option', 'fileInput', null); - fu.fileupload('option', 'dropZone', null); - fu.fileupload('option', 'pasteZone', null); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - fu.fileupload('option', 'dropZone', 'body'); - strictEqual( - fu.fileupload('option', 'dropZone')[0], - document.body, - 'Allow a query string as parameter for the dropZone option' - ); - fu.fileupload('option', 'dropZone', document); - strictEqual( - fu.fileupload('option', 'dropZone')[0], - document, - 'Allow a document element as parameter for the dropZone option' - ); - fu.fileupload('option', 'pasteZone', 'body'); - strictEqual( - fu.fileupload('option', 'pasteZone')[0], - document.body, - 'Allow a query string as parameter for the pasteZone option' - ); - fu.fileupload('option', 'pasteZone', document); - strictEqual( - fu.fileupload('option', 'pasteZone')[0], - document, - 'Allow a document element as parameter for the pasteZone option' - ); - fu.fileupload('option', 'fileInput', ':file'); - strictEqual( - fu.fileupload('option', 'fileInput')[0], - $(':file')[0], - 'Allow a query string as parameter for the fileInput option' - ); - fu.fileupload('option', 'fileInput', $(':file')[0]); - strictEqual( - fu.fileupload('option', 'fileInput')[0], - $(':file')[0], - 'Allow a document element as parameter for the fileInput option' - ); - fu.fileupload('option', 'fileInput', fileInput); - fu.fileupload('option', 'dropZone', dropZone); - fu.fileupload('option', 'pasteZone', pasteZone); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - }); - - asyncTest('add', function () { - expect(2); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - add: function (e, data) { - strictEqual( - data.files[0].name, - param.files[0].name, - 'Triggers add callback' - ); - } - }).fileupload('add', param).fileupload( - 'option', - 'add', - function (e, data) { - data.submit().complete(function () { - ok(true, 'data.submit() Returns a jqXHR object'); - start(); - }); - } - ).fileupload('add', param); - }); - - asyncTest('send', function () { - expect(3); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - send: function (e, data) { - strictEqual( - data.files[0].name, - 'test', - 'Triggers send callback' - ); - } - }).fileupload('send', param).fail(function () { - ok(true, 'Allows to abort the request'); - }).complete(function () { - ok(true, 'Returns a jqXHR object'); - start(); - }).abort(); - }); - - module('Callbacks', lifecycle); - - asyncTest('add', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - add: function () { - ok(true, 'Triggers add callback'); - start(); - } - }).fileupload('add', param); - }); - - asyncTest('submit', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - submit: function () { - ok(true, 'Triggers submit callback'); - start(); - return false; - } - }).fileupload('add', param); - }); - - asyncTest('send', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - send: function () { - ok(true, 'Triggers send callback'); - start(); - return false; - } - }).fileupload('send', param); - }); - - asyncTest('done', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - done: function () { - ok(true, 'Triggers done callback'); - start(); - } - }).fileupload('send', param); - }); - - asyncTest('fail', function () { - expect(1); - var param = {files: [{name: 'test'}]}, - fu = $('#fileupload').fileupload({ - url: '404', - fail: function () { - ok(true, 'Triggers fail callback'); - start(); - } - }); - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - fu.fileupload('send', param); - }); - - asyncTest('always', function () { - expect(2); - var param = {files: [{name: 'test'}]}, - counter = 0, - fu = $('#fileupload').fileupload({ - always: function () { - ok(true, 'Triggers always callback'); - if (counter === 1) { - start(); - } else { - counter += 1; - } - } - }); - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - fu.fileupload('add', param).fileupload( - 'option', - 'url', - '404' - ).fileupload('add', param); - }); - - asyncTest('progress', function () { - expect(1); - var param = {files: [{name: 'test'}]}, - counter = 0; - $('#fileupload').fileupload({ - forceIframeTransport: true, - progress: function () { - ok(true, 'Triggers progress callback'); - if (counter === 0) { - start(); - } else { - counter += 1; - } - } - }).fileupload('send', param); - }); - - asyncTest('progressall', function () { - expect(1); - var param = {files: [{name: 'test'}]}, - counter = 0; - $('#fileupload').fileupload({ - forceIframeTransport: true, - progressall: function () { - ok(true, 'Triggers progressall callback'); - if (counter === 0) { - start(); - } else { - counter += 1; - } - } - }).fileupload('send', param); - }); - - asyncTest('start', function () { - expect(1); - var param = {files: [{name: '1'}, {name: '2'}]}, - active = 0; - $('#fileupload').fileupload({ - send: function () { - active += 1; - }, - start: function () { - ok(!active, 'Triggers start callback before uploads'); - start(); - } - }).fileupload('send', param); - }); - - asyncTest('stop', function () { - expect(1); - var param = {files: [{name: '1'}, {name: '2'}]}, - active = 0; - $('#fileupload').fileupload({ - send: function () { - active += 1; - }, - always: function () { - active -= 1; - }, - stop: function () { - ok(!active, 'Triggers stop callback after uploads'); - start(); - } - }).fileupload('send', param); - }); - - test('change', function () { - var fu = $('#fileupload').fileupload(), - fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'), - fileInput = fu.fileupload('option', 'fileInput'); - expect(2); - fu.fileupload({ - change: function (e, data) { - ok(true, 'Triggers change callback'); - strictEqual( - data.files.length, - 0, - 'Returns empty files list' - ); - }, - add: $.noop - }); - fuo._onChange({ - data: {fileupload: fuo}, - target: fileInput[0] - }); - }); - - test('paste', function () { - var fu = $('#fileupload').fileupload(), - fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'); - expect(1); - fu.fileupload({ - paste: function () { - ok(true, 'Triggers paste callback'); - }, - add: $.noop - }); - fuo._onPaste({ - data: {fileupload: fuo}, - originalEvent: { - dataTransfer: {files: [{}]}, - clipboardData: {items: [{}]} - }, - preventDefault: $.noop - }); - }); - - test('drop', function () { - var fu = $('#fileupload').fileupload(), - fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'); - expect(1); - fu.fileupload({ - drop: function () { - ok(true, 'Triggers drop callback'); - }, - add: $.noop - }); - fuo._onDrop({ - data: {fileupload: fuo}, - originalEvent: { - dataTransfer: {files: [{}]}, - clipboardData: {items: [{}]} - }, - preventDefault: $.noop - }); - }); - - test('dragover', function () { - var fu = $('#fileupload').fileupload(), - fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'); - expect(1); - fu.fileupload({ - dragover: function () { - ok(true, 'Triggers dragover callback'); - }, - add: $.noop - }); - fuo._onDragOver({ - data: {fileupload: fuo}, - originalEvent: {dataTransfer: {types: ['Files']}}, - preventDefault: $.noop - }); - }); - - module('Options', lifecycle); - - test('paramName', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - paramName: null, - send: function (e, data) { - strictEqual( - data.paramName[0], - data.fileInput.prop('name'), - 'Takes paramName from file input field if not set' - ); - return false; - } - }).fileupload('send', param); - }); - - test('url', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - url: null, - send: function (e, data) { - strictEqual( - data.url, - $(data.fileInput.prop('form')).prop('action'), - 'Takes url from form action if not set' - ); - return false; - } - }).fileupload('send', param); - }); - - test('type', function () { - expect(2); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - type: null, - send: function (e, data) { - strictEqual( - data.type, - 'POST', - 'Request type is "POST" if not set to "PUT"' - ); - return false; - } - }).fileupload('send', param); - $('#fileupload').fileupload({ - type: 'PUT', - send: function (e, data) { - strictEqual( - data.type, - 'PUT', - 'Request type is "PUT" if set to "PUT"' - ); - return false; - } - }).fileupload('send', param); - }); - - test('replaceFileInput', function () { - var fu = $('#fileupload').fileupload(), - fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'), - fileInput = fu.fileupload('option', 'fileInput'), - fileInputElement = fileInput[0]; - expect(2); - fu.fileupload({ - replaceFileInput: false, - change: function () { - strictEqual( - fu.fileupload('option', 'fileInput')[0], - fileInputElement, - 'Keeps file input with replaceFileInput: false' - ); - }, - add: $.noop - }); - fuo._onChange({ - data: {fileupload: fuo}, - target: fileInput[0] - }); - fu.fileupload({ - replaceFileInput: true, - change: function () { - notStrictEqual( - fu.fileupload('option', 'fileInput')[0], - fileInputElement, - 'Replaces file input with replaceFileInput: true' - ); - }, - add: $.noop - }); - fuo._onChange({ - data: {fileupload: fuo}, - target: fileInput[0] - }); - }); - - asyncTest('forceIframeTransport', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - forceIframeTransport: true, - done: function (e, data) { - strictEqual( - data.dataType.substr(0, 6), - 'iframe', - 'Iframe Transport is used' - ); - start(); - } - }).fileupload('send', param); - }); - - test('singleFileUploads', function () { - expect(3); - var fu = $('#fileupload').fileupload(), - param = {files: [{name: '1'}, {name: '2'}]}, - index = 1; - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - $('#fileupload').fileupload({ - singleFileUploads: true, - add: function () { - ok(true, 'Triggers callback number ' + index.toString()); - index += 1; - } - }).fileupload('add', param).fileupload( - 'option', - 'singleFileUploads', - false - ).fileupload('add', param); - }); - - test('limitMultiFileUploads', function () { - expect(3); - var fu = $('#fileupload').fileupload(), - param = {files: [ - {name: '1'}, - {name: '2'}, - {name: '3'}, - {name: '4'}, - {name: '5'} - ]}, - index = 1; - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - $('#fileupload').fileupload({ - singleFileUploads: false, - limitMultiFileUploads: 2, - add: function () { - ok(true, 'Triggers callback number ' + index.toString()); - index += 1; - } - }).fileupload('add', param); - }); - - test('limitMultiFileUploadSize', function () { - expect(7); - var fu = $('#fileupload').fileupload(), - param = {files: [ - {name: '1-1', size: 100000}, - {name: '1-2', size: 40000}, - {name: '2-1', size: 100000}, - {name: '3-1', size: 50000}, - {name: '3-2', size: 40000}, - {name: '4-1', size: 45000} // New request due to limitMultiFileUploads - ]}, - param2 = {files: [ - {name: '5-1'}, - {name: '5-2'}, - {name: '6-1'}, - {name: '6-2'}, - {name: '7-1'} - ]}, - index = 1; - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - $('#fileupload').fileupload({ - singleFileUploads: false, - limitMultiFileUploads: 2, - limitMultiFileUploadSize: 150000, - limitMultiFileUploadSizeOverhead: 5000, - add: function () { - ok(true, 'Triggers callback number ' + index.toString()); - index += 1; - } - }).fileupload('add', param).fileupload('add', param2); - }); - - asyncTest('sequentialUploads', function () { - expect(6); - var param = {files: [ - {name: '1'}, - {name: '2'}, - {name: '3'}, - {name: '4'}, - {name: '5'}, - {name: '6'} - ]}, - addIndex = 0, - sendIndex = 0, - loadIndex = 0, - fu = $('#fileupload').fileupload({ - sequentialUploads: true, - add: function (e, data) { - addIndex += 1; - if (addIndex === 4) { - data.submit().abort(); - } else { - data.submit(); - } - }, - send: function () { - sendIndex += 1; - }, - done: function () { - loadIndex += 1; - strictEqual(sendIndex, loadIndex, 'upload in order'); - }, - fail: function (e, data) { - strictEqual(data.errorThrown, 'abort', 'upload aborted'); - }, - stop: function () { - start(); - } - }); - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - fu.fileupload('add', param); - }); - - asyncTest('limitConcurrentUploads', function () { - expect(12); - var param = {files: [ - {name: '1'}, - {name: '2'}, - {name: '3'}, - {name: '4'}, - {name: '5'}, - {name: '6'}, - {name: '7'}, - {name: '8'}, - {name: '9'}, - {name: '10'}, - {name: '11'}, - {name: '12'} - ]}, - addIndex = 0, - sendIndex = 0, - loadIndex = 0, - fu = $('#fileupload').fileupload({ - limitConcurrentUploads: 3, - add: function (e, data) { - addIndex += 1; - if (addIndex === 4) { - data.submit().abort(); - } else { - data.submit(); - } - }, - send: function () { - sendIndex += 1; - }, - done: function () { - loadIndex += 1; - ok(sendIndex - loadIndex < 3); - }, - fail: function (e, data) { - strictEqual(data.errorThrown, 'abort', 'upload aborted'); - }, - stop: function () { - start(); - } - }); - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - fu.fileupload('add', param); - }); - - if ($.support.xhrFileUpload) { - asyncTest('multipart', function () { - expect(2); - var param = {files: [{ - name: 'test.png', - size: 123, - type: 'image/png' - }]}, - fu = $('#fileupload').fileupload({ - multipart: false, - always: function (e, data) { - strictEqual( - data.contentType, - param.files[0].type, - 'non-multipart upload sets file type as contentType' - ); - strictEqual( - data.headers['Content-Disposition'], - 'attachment; filename="' + param.files[0].name + '"', - 'non-multipart upload sets Content-Disposition header' - ); - start(); - } - }); - fu.fileupload('send', param); - }); - } - - module('UI Initialization', lifecycleUI); - - test('Widget initialization', function () { - var fu = $('#fileupload').fileupload(); - ok(fu.data('blueimp-fileupload') || fu.data('fileupload')); - ok( - $('#fileupload').fileupload('option', 'uploadTemplate').length, - 'Initialized upload template' - ); - ok( - $('#fileupload').fileupload('option', 'downloadTemplate').length, - 'Initialized download template' - ); - }); - - test('Buttonbar event listeners', function () { - var buttonbar = $('#fileupload .fileupload-buttonbar'), - files = [{name: 'test'}]; - expect(4); - $('#fileupload').fileupload({ - send: function () { - ok(true, 'Started file upload via global start button'); - }, - fail: function (e, data) { - ok(true, 'Canceled file upload via global cancel button'); - data.context.remove(); - }, - destroy: function () { - ok(true, 'Delete action called via global delete button'); - } - }); - $('#fileupload').fileupload('add', {files: files}); - buttonbar.find('.cancel').click(); - $('#fileupload').fileupload('add', {files: files}); - buttonbar.find('.start').click(); - buttonbar.find('.cancel').click(); - files[0].deleteUrl = 'http://example.org/banana.jpg'; - ($('#fileupload').data('blueimp-fileupload') || - $('#fileupload').data('fileupload')) - ._renderDownload(files) - .appendTo($('#fileupload .files')).show() - .find('.toggle').click(); - buttonbar.find('.delete').click(); - }); - - module('UI API', lifecycleUI); - - test('destroy', function () { - var buttonbar = $('#fileupload .fileupload-buttonbar'), - files = [{name: 'test'}]; - expect(1); - $('#fileupload').fileupload({ - send: function () { - ok(true, 'This test should not run'); - return false; - } - }) - .fileupload('add', {files: files}) - .fileupload('destroy'); - buttonbar.find('.start').click(function () { - ok(true, 'Clicked global start button'); - return false; - }).click(); - }); - - test('disable/enable', function () { - var buttonbar = $('#fileupload .fileupload-buttonbar'); - $('#fileupload').fileupload(); - $('#fileupload').fileupload('disable'); - strictEqual( - buttonbar.find('input[type=file], button').not(':disabled').length, - 0, - 'Disables the buttonbar buttons' - ); - $('#fileupload').fileupload('enable'); - strictEqual( - buttonbar.find('input[type=file], button').not(':disabled').length, - 4, - 'Enables the buttonbar buttons' - ); - }); - - module('UI Callbacks', lifecycleUI); - - test('destroy', function () { - expect(3); - $('#fileupload').fileupload({ - destroy: function (e, data) { - ok(true, 'Triggers destroy callback'); - strictEqual( - data.url, - 'test', - 'Passes over deletion url parameter' - ); - strictEqual( - data.type, - 'DELETE', - 'Passes over deletion request type parameter' - ); - } - }); - ($('#fileupload').data('blueimp-fileupload') || - $('#fileupload').data('fileupload')) - ._renderDownload([{ - name: 'test', - deleteUrl: 'test', - deleteType: 'DELETE' - }]) - .appendTo($('#fileupload .files')) - .show() - .find('.toggle').click(); - $('#fileupload .fileupload-buttonbar .delete').click(); - }); - - asyncTest('added', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - added: function (e, data) { - start(); - strictEqual( - data.files[0].name, - param.files[0].name, - 'Triggers added callback' - ); - }, - send: function () { - return false; - } - }).fileupload('add', param); - }); - - asyncTest('started', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - started: function () { - start(); - ok('Triggers started callback'); - return false; - }, - sent: function () { - return false; - } - }).fileupload('send', param); - }); - - asyncTest('sent', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - sent: function (e, data) { - start(); - strictEqual( - data.files[0].name, - param.files[0].name, - 'Triggers sent callback' - ); - return false; - } - }).fileupload('send', param); - }); - - asyncTest('completed', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - completed: function () { - start(); - ok('Triggers completed callback'); - return false; - } - }).fileupload('send', param); - }); - - asyncTest('failed', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - failed: function () { - start(); - ok('Triggers failed callback'); - return false; - } - }).fileupload('send', param).abort(); - }); - - asyncTest('stopped', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - stopped: function () { - start(); - ok('Triggers stopped callback'); - return false; - } - }).fileupload('send', param); - }); - - asyncTest('destroyed', function () { - expect(1); - $('#fileupload').fileupload({ - dataType: 'html', - destroyed: function () { - start(); - ok(true, 'Triggers destroyed callback'); - } - }); - ($('#fileupload').data('blueimp-fileupload') || - $('#fileupload').data('fileupload')) - ._renderDownload([{ - name: 'test', - deleteUrl: '.', - deleteType: 'GET' - }]) - .appendTo($('#fileupload .files')) - .show() - .find('.toggle').click(); - $('#fileupload .fileupload-buttonbar .delete').click(); - }); - - module('UI Options', lifecycleUI); - - test('autoUpload', function () { - expect(1); - $('#fileupload') - .fileupload({ - autoUpload: true, - send: function () { - ok(true, 'Started file upload automatically'); - return false; - } - }) - .fileupload('add', {files: [{name: 'test'}]}) - .fileupload('option', 'autoUpload', false) - .fileupload('add', {files: [{name: 'test'}]}); - }); - - test('maxNumberOfFiles', function () { - expect(3); - var addIndex = 0, - sendIndex = 0; - $('#fileupload') - .fileupload({ - autoUpload: true, - maxNumberOfFiles: 3, - singleFileUploads: false, - send: function () { - strictEqual( - sendIndex += 1, - addIndex - ); - }, - progress: $.noop, - progressall: $.noop, - done: $.noop, - stop: $.noop - }) - .fileupload('add', {files: [{name: (addIndex += 1)}]}) - .fileupload('add', {files: [{name: (addIndex += 1)}]}) - .fileupload('add', {files: [{name: (addIndex += 1)}]}) - .fileupload('add', {files: [{name: 'test'}]}); - }); - - test('maxFileSize', function () { - expect(2); - var addIndex = 0, - sendIndex = 0; - $('#fileupload') - .fileupload({ - autoUpload: true, - maxFileSize: 1000, - send: function () { - strictEqual( - sendIndex += 1, - addIndex - ); - return false; - } - }) - .fileupload('add', {files: [{ - name: (addIndex += 1) - }]}) - .fileupload('add', {files: [{ - name: (addIndex += 1), - size: 999 - }]}) - .fileupload('add', {files: [{ - name: 'test', - size: 1001 - }]}) - .fileupload({ - send: function (e, data) { - ok( - !$.blueimp.fileupload.prototype.options - .send.call(this, e, data) - ); - return false; - } - }); - }); - - test('minFileSize', function () { - expect(2); - var addIndex = 0, - sendIndex = 0; - $('#fileupload') - .fileupload({ - autoUpload: true, - minFileSize: 1000, - send: function () { - strictEqual( - sendIndex += 1, - addIndex - ); - return false; - } - }) - .fileupload('add', {files: [{ - name: (addIndex += 1) - }]}) - .fileupload('add', {files: [{ - name: (addIndex += 1), - size: 1001 - }]}) - .fileupload('add', {files: [{ - name: 'test', - size: 999 - }]}) - .fileupload({ - send: function (e, data) { - ok( - !$.blueimp.fileupload.prototype.options - .send.call(this, e, data) - ); - return false; - } - }); - }); - - test('acceptFileTypes', function () { - expect(2); - var addIndex = 0, - sendIndex = 0; - $('#fileupload') - .fileupload({ - autoUpload: true, - acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, - disableImageMetaDataLoad: true, - send: function () { - strictEqual( - sendIndex += 1, - addIndex - ); - return false; - } - }) - .fileupload('add', {files: [{ - name: (addIndex += 1) + '.jpg' - }]}) - .fileupload('add', {files: [{ - name: (addIndex += 1), - type: 'image/jpeg' - }]}) - .fileupload('add', {files: [{ - name: 'test.txt', - type: 'text/plain' - }]}) - .fileupload({ - send: function (e, data) { - ok( - !$.blueimp.fileupload.prototype.options - .send.call(this, e, data) - ); - return false; - } - }); - }); - - test('acceptFileTypes as HTML5 data attribute', function () { - expect(2); - var regExp = /(\.|\/)(gif|jpe?g|png)$/i; - $('#fileupload') - .attr('data-accept-file-types', regExp.toString()) - .fileupload(); - strictEqual( - $.type($('#fileupload').fileupload('option', 'acceptFileTypes')), - $.type(regExp) - ); - strictEqual( - $('#fileupload').fileupload('option', 'acceptFileTypes').toString(), - regExp.toString() - ); - }); - -}); |