Showing preview only (2,496K chars total). Download the full file or copy to clipboard to get everything.
Repository: FineUploader/fine-uploader
Branch: master
Commit: 057cc83a7e76
Files: 246
Total size: 2.3 MB
Directory structure:
gitextract_c09cz4qu/
├── .editorconfig
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ └── PULL_REQUEST_TEMPLATE
├── .gitignore
├── .jshintignore
├── .jshintrc
├── .travis.yml
├── ATTRIBUTION.txt
├── LICENSE
├── Makefile
├── README.md
├── client/
│ ├── README.md
│ ├── commonJs/
│ │ ├── all.js
│ │ ├── azure.js
│ │ ├── core/
│ │ │ ├── all.js
│ │ │ ├── azure.js
│ │ │ ├── index.js
│ │ │ ├── s3.js
│ │ │ └── traditional.js
│ │ ├── dnd.js
│ │ ├── jquery/
│ │ │ ├── azure.js
│ │ │ ├── s3.js
│ │ │ └── traditional.js
│ │ ├── s3.js
│ │ └── traditional.js
│ ├── fine-uploader-gallery.css
│ ├── fine-uploader-new.css
│ ├── fine-uploader.css
│ ├── html/
│ │ └── templates/
│ │ ├── default.html
│ │ ├── gallery.html
│ │ └── simple-thumbnails.html
│ ├── js/
│ │ ├── ajax.requester.js
│ │ ├── azure/
│ │ │ ├── azure.xhr.upload.handler.js
│ │ │ ├── get-sas.js
│ │ │ ├── jquery-plugin.js
│ │ │ ├── rest/
│ │ │ │ ├── delete-blob.js
│ │ │ │ ├── put-blob.js
│ │ │ │ ├── put-block-list.js
│ │ │ │ └── put-block.js
│ │ │ ├── uploader.basic.js
│ │ │ ├── uploader.js
│ │ │ └── util.js
│ │ ├── blob-proxy.js
│ │ ├── button.js
│ │ ├── deletefile.ajax.requester.js
│ │ ├── dnd.js
│ │ ├── error/
│ │ │ └── error.js
│ │ ├── export.js
│ │ ├── features.js
│ │ ├── form-support.js
│ │ ├── identify.js
│ │ ├── iframe.xss.response.js
│ │ ├── image-support/
│ │ │ ├── exif.js
│ │ │ ├── image.js
│ │ │ ├── megapix-image.js
│ │ │ ├── scaler.js
│ │ │ └── validation.image.js
│ │ ├── jquery-dnd.js
│ │ ├── jquery-plugin.js
│ │ ├── non-traditional-common/
│ │ │ └── uploader.basic.api.js
│ │ ├── paste.js
│ │ ├── promise.js
│ │ ├── s3/
│ │ │ ├── jquery-plugin.js
│ │ │ ├── multipart.abort.ajax.requester.js
│ │ │ ├── multipart.complete.ajax.requester.js
│ │ │ ├── multipart.initiate.ajax.requester.js
│ │ │ ├── request-signer.js
│ │ │ ├── s3.form.upload.handler.js
│ │ │ ├── s3.xhr.upload.handler.js
│ │ │ ├── uploader.basic.js
│ │ │ ├── uploader.js
│ │ │ └── util.js
│ │ ├── session.ajax.requester.js
│ │ ├── session.js
│ │ ├── templating.js
│ │ ├── third-party/
│ │ │ ├── ExifRestorer.js
│ │ │ └── crypto-js/
│ │ │ ├── core.js
│ │ │ ├── enc-base64.js
│ │ │ ├── hmac.js
│ │ │ ├── lib-typedarrays.js
│ │ │ ├── sha1.js
│ │ │ └── sha256.js
│ │ ├── total-progress.js
│ │ ├── traditional/
│ │ │ ├── all-chunks-done.ajax.requester.js
│ │ │ ├── traditional.form.upload.handler.js
│ │ │ └── traditional.xhr.upload.handler.js
│ │ ├── ui.handler.click.filebuttons.js
│ │ ├── ui.handler.click.filename.js
│ │ ├── ui.handler.edit.filename.js
│ │ ├── ui.handler.events.js
│ │ ├── ui.handler.focus.filenameinput.js
│ │ ├── ui.handler.focusin.filenameinput.js
│ │ ├── upload-data.js
│ │ ├── upload-handler/
│ │ │ ├── form.upload.handler.js
│ │ │ ├── upload.handler.controller.js
│ │ │ ├── upload.handler.js
│ │ │ └── xhr.upload.handler.js
│ │ ├── uploader.api.js
│ │ ├── uploader.basic.api.js
│ │ ├── uploader.basic.js
│ │ ├── uploader.js
│ │ ├── uploadsuccess.ajax.requester.js
│ │ ├── util.js
│ │ ├── version.js
│ │ └── window.receive.message.js
│ └── typescript/
│ ├── fine-uploader.d.ts
│ └── fine-uploader.test.ts
├── config/
│ └── karma.conf.js
├── docs/
│ ├── _static/
│ │ ├── css/
│ │ │ ├── main.css
│ │ │ └── pygments.css
│ │ └── js/
│ │ ├── main.js
│ │ ├── navbar.js
│ │ └── sidebar.js
│ ├── _templates/
│ │ ├── api.html
│ │ ├── base.html
│ │ ├── feature.html
│ │ ├── footer.html
│ │ ├── layout.html
│ │ ├── macros/
│ │ │ ├── alerts.html
│ │ │ ├── code.html
│ │ │ └── github.html
│ │ └── navbar.html
│ ├── api/
│ │ ├── events-s3.jmd
│ │ ├── events.jmd
│ │ ├── methods-azure.jmd
│ │ ├── methods-s3.jmd
│ │ ├── methods.jmd
│ │ ├── options-azure.jmd
│ │ ├── options-s3.jmd
│ │ ├── options-ui.jmd
│ │ ├── options.jmd
│ │ └── qq.jmd
│ ├── browser-support.jmd
│ ├── endpoint_handlers/
│ │ ├── amazon-s3.jmd
│ │ ├── azure.jmd
│ │ └── traditional.jmd
│ ├── faq.jmd
│ ├── features/
│ │ ├── CORS.jmd
│ │ ├── async-tasks-and-promises.jmd
│ │ ├── azure.jmd
│ │ ├── cancellable-uploads.jmd
│ │ ├── chunking.jmd
│ │ ├── concurrent-chunking.jmd
│ │ ├── delete.jmd
│ │ ├── drag-and-drop.jmd
│ │ ├── extra-buttons.jmd
│ │ ├── filename-edit.jmd
│ │ ├── forms.jmd
│ │ ├── handling-errors.jmd
│ │ ├── modules.jmd
│ │ ├── no-server-uploads.jmd
│ │ ├── paste-to-upload.jmd
│ │ ├── pause.jmd
│ │ ├── progress-bars.jmd
│ │ ├── request-parameters.jmd
│ │ ├── resume.jmd
│ │ ├── retry.jmd
│ │ ├── s3.jmd
│ │ ├── scaling.jmd
│ │ ├── session.jmd
│ │ ├── statistics-and-status-updates.jmd
│ │ ├── styling.jmd
│ │ ├── thumbnails.jmd
│ │ ├── upload-files.jmd
│ │ ├── upload-from-mobile-camera.jmd
│ │ └── validation.jmd
│ ├── index.jmd
│ ├── integrating/
│ │ └── jquery.jmd
│ ├── modes/
│ │ ├── core.jmd
│ │ └── ui.jmd
│ ├── quickstart/
│ │ ├── 01-getting-started.jmd
│ │ ├── 02-setting_options-azure.jmd
│ │ ├── 02-setting_options-s3.jmd
│ │ ├── 02-setting_options.jmd
│ │ ├── 03-setting_up_server-azure.jmd
│ │ ├── 03-setting_up_server-s3.jmd
│ │ └── 03-setting_up_server.jmd
│ ├── upgrading-to-4.jmd
│ └── upgrading-to-5.jmd
├── package.json
└── test/
├── dev/
│ ├── devenv.js
│ ├── handlers/
│ │ ├── composer.json
│ │ └── php.ini
│ ├── index.html
│ └── styles.css
├── static/
│ ├── local/
│ │ ├── blob-maker.js
│ │ ├── client.js
│ │ ├── formdata.js
│ │ ├── helpme.js
│ │ └── karma-runner.js
│ └── third-party/
│ ├── assert/
│ │ └── assert.js
│ ├── jquery/
│ │ └── jquery.js
│ ├── jquery.simulate/
│ │ └── jquery.simulate.js
│ ├── json2/
│ │ ├── README
│ │ ├── cycle.js
│ │ ├── json.js
│ │ ├── json2.js
│ │ ├── json_parse.js
│ │ └── json_parse_state.js
│ ├── mocha/
│ │ ├── css/
│ │ │ └── mocha.css
│ │ └── js/
│ │ └── mocha.js
│ ├── purl/
│ │ └── purl.js
│ ├── q/
│ │ └── q-1.0.1.js
│ └── sinon/
│ ├── event.js
│ ├── fake_xml_http_request.js
│ └── sinon.js
└── unit/
├── azure/
│ ├── chunked-uploads.js
│ ├── delete-files.js
│ └── simple-file-uploads.js
├── basic.js
├── button.js
├── chunked-uploads.js
├── concurrent-chunks.js
├── delete-file.js
├── dnd.js
├── exif.js
├── file-upload-params-and-headers.js
├── form-support.js
├── identify.js
├── iframe.xss.response.js
├── image.js
├── on-all-complete.js
├── promise.js
├── resources/
│ ├── empty.txt
│ ├── sample.tif
│ └── simpletext.txt
├── s3/
│ ├── cdn/
│ │ ├── generic-chunked.js
│ │ └── generic-non-chunked.js
│ ├── chunked-uploads.js
│ ├── serverless-uploads.js
│ ├── simple-file-uploads.js
│ └── util.js
├── scaling.js
├── session.js
├── set-status.js
├── simple-file-uploads.js
├── submit-validate-cancel.js
├── templating.js
├── total-progress.js
├── ui.handler.click.filebuttons.js
├── ui.handler.click.filename.js
├── upload-data.js
├── uploader.basic.api.js
├── util.js
├── validation.image.js
└── workarounds.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Matches multiple files with brace expansion notation
# Set default charset
[{*.js}]
charset = utf-8
indent_style = space
indent_size = 4
# Tab indentation (no size specified)
[Makefile]
indent_style = tab
# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
## Type of issue
- [ ] Bug report
- [ ] Feature request
## Uploader type
- [ ] Traditional
- [ ] S3
- [ ] Azure
### Note: Support requests cannot be accepted due to lack of time.
<details>
<summary>Bug Report</summary>
#### Fine Uploader version
{example: 5.5.1}
#### Browsers where the bug is reproducible
{example: "Firefox" and "IE11"}
#### Operating systems where the bug is reproducible
{example: "iOS 9.1.0" and "Windows 8.1"}
#### Exact steps required to reproduce the issue
For example:
1. Select 3 files
2. Pause the 2nd file before it completes, but after it has started.
3. Attempt to resume the paused file.
#### All relevant Fine Uploader-related code that you have written
{simply copy and paste the JS used to control Fine Uploader browsers-ide}
{also include your template HTML if related to a UI issue}
#### Your Fine Uploader template markup (if using Fine Uploader UI and the issue is UI-related)
{simply copy and paste your template markup}
#### Detailed explanation of the problem
{describe the bug here}
</details>
<details>
<summary>Feature Request</summary>
#### Feature request details
{why is this feature important, not just for you, but for many others?}
</details>
================================================
FILE: .github/PULL_REQUEST_TEMPLATE
================================================
## Brief description of the changes
{also describe what problem(s) these changes solve & reference any related issues/PRs}
## What browsers and operating systems have you tested these changes on?
{example: Safari on iOS 9.1.0 and IE11 on Windows 8.1}
## Have you written unit tests? If not, explain why.
{unit tests should accompany almost all PRs, unless the change is to documentation}
================================================
FILE: .gitignore
================================================
.*
!.editorconfig
*.ipr
*~
.*.sw[a-z]
*.iml
*.iws
!.github
!.gitignore
!.jshintrc
!.jshintignore
Thumbs.db
_build/
_dist/
*.zip
release/*
master
!.travis.yml
hardcopy*
selenium.log*
root-server.PID
test-resources-server.PID
fine-uploader/
test/upload/*
test/uploadsTemp/
test/coverage/*
test/vendor/*
test/uploads/*
test/temp*
test/_temp*
test/_vendor*
node_modules/
bin/
src
npm-debug.log
Vagrantfile
test/dev/handlers/s3/composer.lock
test/dev/handlers/traditional/files
test/dev/handlers/traditional/chunks
s3keys.php
s3keys.sh
test/dev/handlers/vendor/*
test/dev/handlers/composer.lock
test/dev/handlers/composer.phar
================================================
FILE: .jshintignore
================================================
client/js/third-party/*
================================================
FILE: .jshintrc
================================================
{
// --------------------------------------------------------------------
// JSHint Configuration, Strict Edition
// --------------------------------------------------------------------
//
// This is a options template for [JSHint][1], using [JSHint example][2]
// and [Ory Band's example][3] as basis and setting config values to
// be most strict:
//
// * set all enforcing options to true
// * set all relaxing options to false
// * set all environment options to false, except the browser value
// * set all JSLint legacy options to false
//
// [1]: http://www.jshint.com/
// [2]: https://github.com/jshint/node-jshint/blob/master/example/config.json
// [3]: https://github.com/oryband/dotfiles/blob/master/jshintrc
//
// @author http://michael.haschke.biz/
// @license http://unlicense.org/
// == Enforcing Options ===============================================
//
// These options tell JSHint to be more strict towards your code. Use
// them if you want to allow only a safe subset of JavaScript, very
// useful when your codebase is shared with a big number of developers
// with different skill levels.
"bitwise" : true, // Prohibit bitwise operators (&, |, ^, etc.).
"curly" : true, // Require {} for every new block or scope.
"eqeqeq" : true, // Require triple equals i.e. `===`.
"forin" : true, // Tolerate `for in` loops without `hasOwnPrototype`.
"immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
"latedef" : false, // Prohibit variable use before definition.
"newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`.
"noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`.
"noempty" : true, // Prohibit use of empty blocks.
"nonew" : true, // Prohibit use of constructors for side-effects.
"plusplus" : false, // Prohibit use of `++` & `--`.
"regexp" : true, // Prohibit `.` and `[^...]` in regular expressions.
"undef" : true, // Require all non-global variables be declared before they are used.
"unused" : false, // Prohibit the use of defined, yet unused variables.
"strict" : true, // Require `use strict` pragma in every file.
"trailing" : true, // Prohibit trailing whitespaces.
// == Relaxing Options ================================================
//
// These options allow you to suppress certain types of warnings. Use
// them only if you are absolutely positive that you know what you are
// doing.
"asi" : false, // Tolerate Automatic Semicolon Insertion (no semicolons).
"boss" : false, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
"debug" : false, // Allow debugger statements e.g. browser breakpoints.
"eqnull" : true, // Tolerate use of `== null`.
"esnext" : false, // Allow ES.next specific features such as `const` and `let`.
"evil" : false, // Tolerate use of `eval`.
"expr" : true, // Tolerate `ExpressionStatement` as Programs.
"funcscope" : false, // Tolerate declarations of variables inside of control structures while accessing them later from the outside.
"globalstrict" : false, // Allow global "use strict" (also enables 'strict').
"iterator" : false, // Allow usage of __iterator__ property.
"lastsemic" : false, // Tolerat missing semicolons when the it is omitted for the last statement in a one-line block.
"laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
"laxcomma" : false, // Suppress warnings about comma-first coding style.
"loopfunc" : false, // Allow functions to be defined within loops.
"multistr" : false, // Tolerate multi-line strings.
"onecase" : false, // Tolerate switches with just one case.
"proto" : false, // Tolerate __proto__ property. This property is deprecated.
"regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`.
"scripturl" : false, // Tolerate script-targeted URLs.
"smarttabs" : false, // Tolerate mixed tabs and spaces when the latter are used for alignmnent only.
"shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`.
"sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
"supernew" : false, // Tolerate `new function () { ... };` and `new Object;`.
"validthis" : false, // Tolerate strict violations when the code is running in strict mode and you use this in a non-constructor function.
// == Environments ====================================================
//
// These options pre-define global variables that are exposed by
// popular JavaScript libraries and runtime environments—such as
// browser or node.js.
"browser" : true, // Standard browser globals e.g. `window`, `document`.
"couch" : false, // Enable globals exposed by CouchDB.
"devel" : false, // Allow development statements e.g. `console.log();`.
"dojo" : false, // Enable globals exposed by Dojo Toolkit.
"jquery" : true, // Enable globals exposed by jQuery JavaScript library.
"mootools" : false, // Enable globals exposed by MooTools JavaScript framework.
"node" : false, // Enable globals available when code is running inside of the NodeJS runtime environment.
"nonstandard" : true, // Define non-standard but widely adopted globals such as escape and unescape.
"prototypejs" : false, // Enable globals exposed by Prototype JavaScript framework.
"rhino" : false, // Enable globals available when your code is running inside of the Rhino runtime environment.
"wsh" : false, // Enable globals available when your code is running as a script for the Windows Script Host.
// == JSLint Legacy ===================================================
//
// These options are legacy from JSLint. Aside from bug fixes they will
// not be improved in any way and might be removed at any point.
"nomen" : false, // Prohibit use of initial or trailing underbars in names.
"onevar" : false, // Allow only one `var` statement per function.
"passfail" : false, // Stop on first error.
"white" : false, // Check against strict whitespace and indentation rules.
// == Undocumented Options ============================================
//
// While I've found these options in [example1][2] and [example2][3]
// they are not described in the [JSHint Options documentation][4].
//
// [4]: http://www.jshint.com/options/
"maxerr" : 100, // Maximum errors before stopping.
"predef" : ["qq"],
"quotmark" : "double", // Enforces consistencey of quotation marks.
//"maxlen" : "80", // Enfore a maximum line length
"indent" : 4 // Specify indentation spacing
}
================================================
FILE: .travis.yml
================================================
addons:
firefox: latest
sudo: false
language: python
python:
- 2.7
env:
global:
- DISPLAY=:99.0
- DOCS_GH_REF: github.com/FineUploader/docs.fineuploader.com
# fineuploader-docs-bot access token has been moved to Travis-CI settings in the UI due to https://github.com/travis-ci/travis-ci/issues/7806
install:
- . $HOME/.nvm/nvm.sh
- nvm install 5.0.0
- nvm use 5.0.0
- npm install
before_script:
- sh -e /etc/init.d/xvfb start
script:
- npm test
- if [ $TRAVIS_TEST_RESULT -eq 0 ]; then make docs-travis; fi
================================================
FILE: ATTRIBUTION.txt
================================================
Third-party credits (client/js/third-party/)
MegaPixImage module
Licensed under MIT (https://github.com/stomita/ios-imagefile-megapixel/blob/master/LICENSE)
https://github.com/stomita/ios-imagefile-megapixel
Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com>
CryptoJS
Licensed under MIT (https://code.google.com/p/crypto-js/wiki/License)
https://code.google.com/p/crypto-js/
Copyright (c) 2009-2013 Jeff Mott <Jeff.Mott.OR@gmail.com>
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2010-2012, Andrew Valums
Copyright (c) 2012-2013, Andrew Valums and Raymond S. Nicholus, III
Copyright (c) 2013-present, Widen Enterprises, Inc.
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.
================================================
FILE: Makefile
================================================
.PHONY: clean _build publish start-test-resources-server test-resources-server.PID start-root-server root-server.PID
version=$(shell node -pe "require('./package.json').version")
dist-out-dir = _dist
pub-dir = $(dist-out-dir)/$(version)
# properly get npm-bin in cygwin (Eg. CYGWIN_NT-10.0)
platform = $(shell uname -s)
ifeq ($(findstring _NT,$(platform)),_NT)
npm-bin = $(shell cygpath -u $(shell npm bin))
else
npm-bin = $(shell npm bin)
endif
build-out-dir = _build
src-dir = client
js-src-dir = $(src-dir)/js
js-3rdparty-src-dir = $(js-src-dir)/third-party
test-dir = test
unit-test-dir = $(test-dir)/unit
export-file = $(js-src-dir)/export.js
preamble = "// Fine Uploader $(version) - MIT licensed. http://fineuploader.com"
cryptojs-files = \
$(js-3rdparty-src-dir)/crypto-js/core.js \
$(js-3rdparty-src-dir)/crypto-js/enc-base64.js \
$(js-3rdparty-src-dir)/crypto-js/hmac.js \
$(js-3rdparty-src-dir)/crypto-js/sha1.js \
$(js-3rdparty-src-dir)/crypto-js/sha256.js \
$(js-3rdparty-src-dir)/crypto-js/lib-typedarrays.js
jquery-files = \
$(js-src-dir)/jquery-plugin.js \
$(js-src-dir)/jquery-dnd.js
dnd-files-only = \
$(js-src-dir)/dnd.js
dnd-files = \
$(js-src-dir)/util.js \
$(export-file) \
$(js-src-dir)/version.js \
$(js-src-dir)/features.js \
$(js-src-dir)/promise.js \
$(js-src-dir)/dnd.js
core-files = \
$(js-src-dir)/util.js \
$(export-file) \
$(js-src-dir)/error/error.js \
$(js-src-dir)/version.js \
$(js-src-dir)/features.js \
$(js-src-dir)/promise.js \
$(js-src-dir)/blob-proxy.js \
$(js-src-dir)/button.js \
$(js-src-dir)/upload-data.js \
$(js-src-dir)/uploader.basic.api.js \
$(js-src-dir)/uploader.basic.js \
$(js-src-dir)/ajax.requester.js \
$(js-src-dir)/upload-handler/upload.handler.js \
$(js-src-dir)/upload-handler/upload.handler.controller.js \
$(js-src-dir)/window.receive.message.js \
$(js-src-dir)/upload-handler/form.upload.handler.js \
$(js-src-dir)/upload-handler/xhr.upload.handler.js \
$(js-src-dir)/deletefile.ajax.requester.js \
$(js-src-dir)/image-support/megapix-image.js \
$(js-src-dir)/image-support/image.js \
$(js-src-dir)/image-support/exif.js \
$(js-src-dir)/identify.js \
$(js-src-dir)/image-support/validation.image.js \
$(js-src-dir)/session.js \
$(js-src-dir)/session.ajax.requester.js \
$(js-src-dir)/image-support/scaler.js \
$(js-src-dir)/third-party/ExifRestorer.js \
$(js-src-dir)/total-progress.js \
$(js-src-dir)/paste.js \
$(js-src-dir)/form-support.js \
ui-files = \
$(dnd-files-only) \
$(js-src-dir)/uploader.api.js \
$(js-src-dir)/uploader.js \
$(js-src-dir)/templating.js \
$(js-src-dir)/ui.handler.events.js \
$(js-src-dir)/ui.handler.click.filebuttons.js \
$(js-src-dir)/ui.handler.click.filename.js \
$(js-src-dir)/ui.handler.focusin.filenameinput.js \
$(js-src-dir)/ui.handler.focus.filenameinput.js \
$(js-src-dir)/ui.handler.edit.filename.js
traditional-files-only = \
$(js-src-dir)/traditional/traditional.form.upload.handler.js \
$(js-src-dir)/traditional/traditional.xhr.upload.handler.js \
$(js-src-dir)/traditional/all-chunks-done.ajax.requester.js \
traditional-files = \
$(core-files) \
$(traditional-files-only)
traditional-jquery-files = \
$(jquery-files) \
$(traditional-files)
traditional-ui-files = \
$(core-files) \
$(traditional-files-only) \
$(ui-files)
traditional-ui-jquery-files = \
$(jquery-files) \
$(traditional-ui-files)
s3-files-only = \
$(cryptojs-files) \
$(js-src-dir)/s3/util.js \
$(js-src-dir)/non-traditional-common/uploader.basic.api.js \
$(js-src-dir)/s3/uploader.basic.js \
$(js-src-dir)/s3/request-signer.js \
$(js-src-dir)/uploadsuccess.ajax.requester.js \
$(js-src-dir)/s3/multipart.initiate.ajax.requester.js \
$(js-src-dir)/s3/multipart.complete.ajax.requester.js \
$(js-src-dir)/s3/multipart.abort.ajax.requester.js \
$(js-src-dir)/s3/s3.xhr.upload.handler.js \
$(js-src-dir)/s3/s3.form.upload.handler.js
s3-files = \
$(core-files) \
$(s3-files-only)
s3-ui-files-only = \
$(js-src-dir)/s3/uploader.js
s3-ui-files = \
$(core-files) \
$(s3-files-only) \
$(ui-files) \
$(s3-ui-files-only) \
s3-ui-jquery-files = \
$(jquery-files) \
$(js-src-dir)/s3/jquery-plugin.js \
$(s3-ui-files)
azure-files-only = \
$(js-src-dir)/azure/util.js \
$(js-src-dir)/non-traditional-common/uploader.basic.api.js \
$(js-src-dir)/azure/uploader.basic.js \
$(js-src-dir)/azure/azure.xhr.upload.handler.js \
$(js-src-dir)/azure/get-sas.js \
$(js-src-dir)/uploadsuccess.ajax.requester.js \
$(js-src-dir)/azure/rest/delete-blob.js \
$(js-src-dir)/azure/rest/put-blob.js \
$(js-src-dir)/azure/rest/put-block.js \
$(js-src-dir)/azure/rest/put-block-list.js
azure-files = \
$(core-files) \
$(azure-files-only)
azure-ui-files-only = \
$(js-src-dir)/azure/uploader.js
azure-ui-files = \
$(core-files) \
$(azure-files-only) \
$(ui-files) \
$(azure-ui-files-only)
azure-ui-jquery-files = \
$(jquery-files) \
$(js-src-dir)/azure/jquery-plugin.js \
$(azure-ui-files)
all-core-files = \
$(core-files) \
$(traditional-files-only) \
$(s3-files-only) \
$(azure-files-only)
all-core-jquery-files = \
$(jquery-files) \
$(all-core-files)
all-files = \
$(core-files) \
$(traditional-files-only) \
$(ui-files) \
$(s3-files-only) \
$(s3-ui-files-only) \
$(azure-files-only) \
$(azure-ui-files-only)
all-jquery-files = \
$(jquery-files) \
$(all-files)
clean:
rm -rf $(build-out-dir)
rm -rf $(dist-out-dir)
lint:
$(npm-bin)/jscs $(js-src-dir)/*
$(npm-bin)/jshint $(js-src-dir)/* $(unit-test-dir)/* $(test-dir)/static/local/*
_build:
mkdir -p $@
cp -pR $(src-dir)/placeholders $@
cp -pR $(src-dir)/html/templates $@
cp LICENSE $@
cp $(src-dir)/*.css $@
cp $(src-dir)/*.gif $@
$(npm-bin)/cleancss --source-map $@/fine-uploader.css -o $@/fine-uploader.min.css
$(npm-bin)/cleancss --source-map $@/fine-uploader-gallery.css -o $@/fine-uploader-gallery.min.css
$(npm-bin)/cleancss --source-map $@/fine-uploader-new.css -o $@/fine-uploader-new.min.css
uglify = $(npm-bin)/uglifyjs -b --preamble $(preamble) -e window:global -p relative --source-map-include-sources
uglify-min = $(npm-bin)/uglifyjs -c -m --preamble $(preamble) -e window:global -p relative --source-map-include-sources
build-dnd-standalone: _build
$(uglify) $(dnd-files) -o $(build-out-dir)/dnd.js --source-map $(build-out-dir)/dnd.js.map
build-dnd-standalone-min: _build
$(uglify-min) $(dnd-files) -o $(build-out-dir)/dnd.min.js --source-map $(build-out-dir)/dnd.min.js.map
build-core-traditional: _build
$(uglify) $(traditional-files) -o $(build-out-dir)/fine-uploader.core.js --source-map $(build-out-dir)/fine-uploader.core.js.map
build-core-traditional-min: _build
$(uglify-min) $(traditional-files) -o $(build-out-dir)/fine-uploader.core.min.js --source-map $(build-out-dir)/fine-uploader.core.min.js.map
build-ui-traditional: _build
$(uglify) $(traditional-ui-files) -o $(build-out-dir)/fine-uploader.js --source-map $(build-out-dir)/fine-uploader.js.map
build-ui-traditional-min: _build
$(uglify-min) $(traditional-ui-files) -o $(build-out-dir)/fine-uploader.min.js --source-map $(build-out-dir)/fine-uploader.min.js.map
build-ui-traditional-jquery: _build
$(uglify) $(traditional-ui-jquery-files) -o $(build-out-dir)/jquery.fine-uploader.js --source-map $(build-out-dir)/jquery.fine-uploader.js.map
build-ui-traditional-jquery-min: _build
$(uglify-min) $(traditional-ui-jquery-files) -o $(build-out-dir)/jquery.fine-uploader.min.js --source-map $(build-out-dir)/jquery.fine-uploader.min.js.map
build-core-s3: _build
$(uglify) $(s3-files) -o $(build-out-dir)/s3.fine-uploader.core.js --source-map $(build-out-dir)/s3.fine-uploader.core.js.map
build-core-s3-min: _build
$(uglify-min) $(s3-files) -o $(build-out-dir)/s3.fine-uploader.core.min.js --source-map $(build-out-dir)/s3.fine-uploader.core.min.js.map
build-ui-s3: _build
$(uglify) $(s3-ui-files) -o $(build-out-dir)/s3.fine-uploader.js --source-map $(build-out-dir)/s3.fine-uploader.js.map
build-ui-s3-min: _build
$(uglify-min) $(s3-ui-jquery-files) -o $(build-out-dir)/s3.jquery.fine-uploader.min.js --source-map $(build-out-dir)/s3.jquery.fine-uploader.min.js.map
build-ui-s3-jquery: _build
$(uglify) $(s3-ui-jquery-files) -o $(build-out-dir)/s3.jquery.fine-uploader.js --source-map $(build-out-dir)/s3.jquery.fine-uploader.js.map
build-ui-s3-jquery-min: _build
$(uglify-min) $(s3-ui-files) -o $(build-out-dir)/s3.fine-uploader.min.js -e window:global --source-map $(build-out-dir)/s3.fine-uploader.min.js.map
build-core-azure: _build
$(uglify) $(azure-files) -o $(build-out-dir)/azure.fine-uploader.core.js --source-map $(build-out-dir)/azure.fine-uploader.core.js.map
build-core-azure-min: _build
$(uglify-min) $(azure-files) -o $(build-out-dir)/azure.fine-uploader.core.min.js -e window:global --source-map $(build-out-dir)/azure.fine-uploader.core.min.js.map
build-ui-azure: _build
$(uglify) $(azure-ui-files) -o $(build-out-dir)/azure.fine-uploader.js --source-map $(build-out-dir)/azure.fine-uploader.js.map
build-ui-azure-min: _build
$(uglify-min) $(azure-ui-files) -o $(build-out-dir)/azure.fine-uploader.min.js -e window:global --source-map $(build-out-dir)/azure.fine-uploader.min.js.map
build-ui-azure-jquery: _build
$(uglify) $(azure-ui-jquery-files) -o $(build-out-dir)/azure.jquery.fine-uploader.js --source-map $(build-out-dir)/azure.jquery.fine-uploader.js.map
build-ui-azure-jquery-min: _build
$(uglify-min) $(azure-ui-jquery-files) -o $(build-out-dir)/azure.jquery.fine-uploader.min.js -e window:global --source-map $(build-out-dir)/azure.jquery.fine-uploader.min.js.map
build-all-core: _build
$(uglify) $(all-core-files) -o $(build-out-dir)/all.fine-uploader.core.js --source-map $(build-out-dir)/all.fine-uploader.core.js.map
build-all-core-min: _build
$(uglify-min) $(all-core-files) -o $(build-out-dir)/all.fine-uploader.core.min.js -e window:global --source-map $(build-out-dir)/all.fine-uploader.core.min.js.map
build-all-ui: _build
$(uglify) $(all-files) -o $(build-out-dir)/all.fine-uploader.js --source-map $(build-out-dir)/all.fine-uploader.js.map
build-all-ui-min: _build
$(uglify-min) $(all-files) -o $(build-out-dir)/all.fine-uploader.min.js --source-map $(build-out-dir)/all.fine-uploader.min.js.map
build: \
build-dnd-standalone \
build-dnd-standalone-min \
build-core-traditional \
build-core-traditional-min \
build-ui-traditional \
build-ui-traditional-min \
build-ui-traditional-jquery \
build-ui-traditional-jquery-min \
build-core-s3 \
build-core-s3-min \
build-ui-s3 \
build-ui-s3-min \
build-ui-s3-jquery \
build-ui-s3-jquery-min \
build-core-azure \
build-core-azure-min \
build-ui-azure \
build-ui-azure-min \
build-ui-azure-jquery \
build-ui-azure-jquery-min \
build-all-core \
build-all-core-min \
build-all-ui \
build-all-ui-min
start-test-resources-server: test-resources-server.PID
start-root-server: root-server.PID
test-resources-server.PID:
$(npm-bin)/static test/unit/resources -H '{"Access-Control-Allow-Origin": "*"}' -p 4000 & echo $$! > $@
root-server.PID:
$(npm-bin)/static . -p 4001 & echo $$! > $@
stop-test-resources-server: test-resources-server.PID
kill `cat $<` && rm $<
stop-root-server: root-server.PID
kill `cat $<` && rm $<
test:
$(MAKE) stop-test-resources-server
$(MAKE) stop-root-server
$(MAKE) start-test-resources-server
$(MAKE) start-root-server
$(MAKE) build-all-ui
$(npm-bin)/karma start config/karma.conf.js
$(MAKE) stop-test-resources-server
$(MAKE) stop-root-server
.PHONY: test
zip: zip-traditional zip-s3 zip-azure zip-all
common-zip-files = \
dnd*.* \
LICENSE \
placeholders/* \
templates/* \
*.gif \
fine-uploader*.css*
zip-traditional:
(cd $(build-out-dir) ; zip fine-uploader.zip $(common-zip-files) fine-uploader*.* jquery.fine-uploader*.*)
zip-s3:
(cd $(build-out-dir) ; zip s3.fine-uploader.zip $(common-zip-files) s3*.*)
zip-azure:
(cd $(build-out-dir) ; zip azure.fine-uploader.zip $(common-zip-files) azure*.*)
zip-all:
(cd $(build-out-dir) ; zip all.fine-uploader.zip $(common-zip-files) all*.*)
setup-dist:
mkdir -p $(pub-dir)
cp LICENSE README.md package.json $(pub-dir)
cp -pR $(src-dir)/commonJs/ $(pub-dir)/lib/
cp -pR $(src-dir)/typescript $(pub-dir)/
copy-build-to-dist:
mkdir -p $(pub-dir)/$(PUB-SUBDIR)
cp -pR $(build-out-dir)/placeholders $(build-out-dir)/templates $(pub-dir)/$(PUB-SUBDIR)
cp $(build-out-dir)/*.gif $(pub-dir)/$(PUB-SUBDIR)
ifneq (,$(findstring jquery,$(PUB-SUBDIR)))
else
cp $(build-out-dir)/$(PUB-SUBDIR).core.min* $(build-out-dir)/$(PUB-SUBDIR).core.js* $(pub-dir)/$(PUB-SUBDIR)/
endif
cp $(build-out-dir)/$(PUB-SUBDIR).min* $(build-out-dir)/$(PUB-SUBDIR).js* $(pub-dir)/$(PUB-SUBDIR)
cp $(build-out-dir)/fine-uploader*.css* $(pub-dir)/$(PUB-SUBDIR)
copy-dnd:
mkdir -p $(pub-dir)/dnd
cp $(build-out-dir)/dnd*.* $(pub-dir)/dnd
copy-traditional-dist:
make copy-build-to-dist PUB-SUBDIR=fine-uploader
cp $(js-src-dir)/iframe.xss.response.js $(pub-dir)/fine-uploader
copy-traditional-jquery-dist:
make copy-build-to-dist PUB-SUBDIR=jquery.fine-uploader
cp $(js-src-dir)/iframe.xss.response.js $(pub-dir)/jquery.fine-uploader
copy-s3-dist:
make copy-build-to-dist PUB-SUBDIR=s3.fine-uploader
copy-s3-jquery-dist:
make copy-build-to-dist PUB-SUBDIR=s3.jquery.fine-uploader
copy-azure-dist:
make copy-build-to-dist PUB-SUBDIR=azure.fine-uploader
copy-azure-jquery-dist:
make copy-build-to-dist PUB-SUBDIR=azure.jquery.fine-uploader
copy-all-dist:
make copy-build-to-dist PUB-SUBDIR=all.fine-uploader
docs: install-docfu
git config --global user.email "fineuploader-docs-bot@raynicholus.com"
git config --global user.name "fineuploader-docs-bot"
docfu --$(type) "$(type-value)" "FineUploader/fine-uploader" "docfu-temp"
git clone --depth 1 https://github.com/FineUploader/docs.fineuploader.com.git
cp -pR docfu-temp/$(type) docs.fineuploader.com/
make maybe-update-root-docs
(cd docs.fineuploader.com ; git add .)
(cd docs.fineuploader.com ; git diff --cached --quiet || git commit -a -m "update docs for $(type) $(type-value)")
@(cd docs.fineuploader.com ; git push https://$(DOCS_PUSH_ACCESS_TOKEN)@$(DOCS_GH_REF))
.PHONY: docs
maybe-update-root-docs:
ifndef TRAVIS_TAG
ifeq ($(TRAVIS_BRANCH), master)
cp -pR docs.fineuploader.com/branch/master/. docs.fineuploader.com/
endif
endif
.PHONY: maybe-update-root-docs
docs-travis:
ifneq ($(TRAVIS_PULL_REQUEST), false)
@echo skipping docs build - not a non-PR or tag push
else ifdef TRAVIS_TAG
make docs type=tag type-value=$(TRAVIS_TAG)
else
make docs type=branch type-value=$(TRAVIS_BRANCH)
endif
.PHONY: docs-travis
install-docfu:
git clone --depth 1 -b 1.0.4 https://github.com/FineUploader/docfu
(cd docfu ; python setup.py install)
rm -rf docfu
.PHONY: install-docfu
tag-release:
ifeq ($(simulate), true)
@echo version is $(version)
else
git tag $(version)
git push origin $(version)
endif
push-to-npm:
ifeq ($(simulate), true)
@echo not publishing - simulation mode
else
(cd $(pub-dir) ; npm publish)
endif
publish: \
clean \
build \
zip \
setup-dist \
copy-dnd \
copy-traditional-dist \
copy-traditional-jquery-dist \
copy-s3-dist \
copy-s3-jquery-dist \
copy-azure-dist \
copy-azure-jquery-dist \
copy-all-dist \
tag-release \
push-to-npm
setup-dev:
(cd test/dev/handlers; curl -sS https://getcomposer.org/installer | php; php composer.phar install)
start-local-dev:
(. test/dev/handlers/s3keys.sh; php -S 0.0.0.0:9090 -t . -c test/dev/handlers/php.ini)
update-dev:
(cd test/dev/handlers; php composer.phar update)
rev-version:
sed -i "" -e 's/$(version)/$(target)/g' client/js/version.js
sed -i "" -e 's/$(version)/$(target)/g' package.json
================================================
FILE: README.md
================================================
**Fine Uploader is no longer maintained and the project has been effectively shut down. For more info, see https://github.com/FineUploader/fine-uploader/issues/2073.**
<a href="http://fineuploader.com">
<img src="https://fineuploader.com/img/fineuploader-header-logo.png" width="300">
</a>
[](https://travis-ci.org/FineUploader/fine-uploader)
[](https://www.npmjs.com/package/fine-uploader)
[](https://cdnjs.com/libraries/file-uploader)
[](LICENSE)
[](https://twitter.com/fineuploader)
[**Documentation**](http://docs.fineuploader.com) |
[**Examples**](http://fineuploader.com/demos) |
[**Support**](../../issues) |
[**Blog**](http://blog.fineuploader.com/) |
[**Changelog**](../../releases)
---
Fine Uploader is:
- Cross-browser
- Dependency-free
- 100% JavaScript
- 100% Free Open Source Software
FineUploader is also simple to use. In the simplest case, you only need to include one JavaScript file.
There are absolutely no other required external dependencies. For more information, please see the [**documentation**](http://docs.fineuploader.com).
## Contributing
If you'd like to help and keep this project strong and relevant, you have several options.
### Help us pay the bills
Fine Uploader is currently looking for a sponsor to pay the AWS bills (which have recently lapsed).
These add up to about $40/month. Please open an issue if you are interesting in becoming a sponsor.
We will happily list you as sponsor on the site and README.
### File a bug report
If you see something that isn't quite right, whether it be in the code, or on the docs site, or even on FineUploader.com (which is hosted on GitHub), _please_ file a bug report. Be sure to make sure the [bug hasn't already been filed][issues] by someone else. If it has, feel free to upvote the issue and/or add your comments.
### Join the team
Are you interested in working on a very popular JavaScript-based file upload library with countless users? If you're strong in JavaScript, HTML, and CSS, and have a desire to help push the FOSS movement forward, let us know! The project can always use more experts.
### Help spread the word
Are you using Fine Uploader in your library or project? If so, let us know and we may add a link to your project or application _and_ your logo to FineUploader.com. If you care to write an article about Fine Uploader, we would be open to reading and publicizing it through our site, blog, or Twitter feed.
### Develop an integration library
Are you using Fine Uploader inside of a larger framework (such as React, Angular2, Ember.js, etc)? If so, perhaps you've already written a library that wraps Fine Uploader and makes it simple to use Fine Uploader in this context. Let us know and it may make sense to either link to your library, or even move it into the FineUploader GitHub organization (with your approval, of course). We'd also love to see libraries that make it simple to pair Fine Uploader with other useful libraries, such as image editors and rich text editors.
### Contribute code
The best way to contribute code is to open up a pull request that addresses one of the open [feature requests or bugs][issues]. In order to get started developing Fine Uploader, read this entire section to get the project up and running on your local development machine. This section describes how you can build and test Fine Uploader locally. You may use these instructions to build a copy for yourself, or to contribute changes back to the library.
#### Setup
You must have Node.js instaled locally (any version should be fine), _and_ you must have Unix-like environment to work with. Linux, FreeBSD/OS X, Cygwin, and Windows 10 bash all _should_ be acceptable environments. Please open up a new issue if you have trouble building. The build process is centered around a single Makefile, so GNU Make is required as well (though most if not all Unix-like OSes should already have this installed). Finally, you will need a git client.
To pull down the project & build dependencies:
1. Download the project repository: `git clone https://github.com/FineUploader/fine-uploader.git`.
2. Install all project development dependencies: `npm install`.
#### Generating build artifacts
- To build all build artifacts for all endpoint types: `make build`. You can speed this process up a bit by using the parallel recipes feature of Make: `make build -j`. If you would like to build only a specific endpoint type, see the Makefile for the appropriate recipe. The build output will be created in the `_build` directory.
- To build zip files for all endpoint types: `make zip`. To build a zip for only a specific endpoint type, see the Makefile for the appropriate recipe. The zip files will be included alongside the build output in the `_build` directory.
- To rev the version number: `make rev-version target=NEW_VERSION`, where `NEW_VERSION` is the semver-compatible target version identifier.
#### Running tests
To build, run the tests & linter: `npm test` (you'll need Firefox installed locally).
#### Commiting new code and changes
- Follow the [Angular.js commit guidelines][angular-commit].
- Follow the [Git Flow][git-flow] branching strategy.
[angular-commit]: https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit
[git-flow]: http://nvie.com/posts/a-successful-git-branching-model/
[issues]: https://github.com/FineUploader/fine-uploader/issues
================================================
FILE: client/README.md
================================================
Do not add files from this directory into your project. Please visit the
downloads page for zips that contain combined and version-stamped javascript
and css files, along with all required resources.
# Download
To download a pre-packaged version of Fine Uploader visit: http://fineuploader.com/downloads.html
# Build
For instructions on building your own packaged version of Fine Uploader visit: http://docs.fineuploader.com/contributing.htm
================================================
FILE: client/commonJs/all.js
================================================
"use strict";
module.exports = require("../all.fine-uploader/all.fine-uploader");
================================================
FILE: client/commonJs/azure.js
================================================
"use strict";
module.exports = require("../azure.fine-uploader/azure.fine-uploader");
================================================
FILE: client/commonJs/core/all.js
================================================
"use strict";
module.exports = require("../../all.fine-uploader/all.fine-uploader.core");
================================================
FILE: client/commonJs/core/azure.js
================================================
"use strict";
module.exports = require("../../azure.fine-uploader/azure.fine-uploader.core");
================================================
FILE: client/commonJs/core/index.js
================================================
"use strict";
module.exports = require("../../fine-uploader/fine-uploader.core");
================================================
FILE: client/commonJs/core/s3.js
================================================
"use strict";
module.exports = require("../../s3.fine-uploader/s3.fine-uploader.core");
================================================
FILE: client/commonJs/core/traditional.js
================================================
"use strict";
module.exports = require("../../fine-uploader/fine-uploader.core");
================================================
FILE: client/commonJs/dnd.js
================================================
"use strict";
module.exports = require("../dnd/dnd");
================================================
FILE: client/commonJs/jquery/azure.js
================================================
"use strict";
module.exports = require("../../azure.jquery.fine-uploader/azure.jquery.fine-uploader");
================================================
FILE: client/commonJs/jquery/s3.js
================================================
"use strict";
module.exports = require("../../s3.jquery.fine-uploader/s3.jquery.fine-uploader");
================================================
FILE: client/commonJs/jquery/traditional.js
================================================
"use strict";
module.exports = require("../../jquery.fine-uploader/jquery.fine-uploader");
================================================
FILE: client/commonJs/s3.js
================================================
"use strict";
module.exports = require("../s3.fine-uploader/s3.fine-uploader");
================================================
FILE: client/commonJs/traditional.js
================================================
"use strict";
module.exports = require("../fine-uploader/fine-uploader");
================================================
FILE: client/fine-uploader-gallery.css
================================================
/* ---------------------------------------
/* Fine Uploader Gallery View Styles
/* ---------------------------------------
/* Buttons
------------------------------------------ */
.qq-gallery .qq-btn
{
float: right;
border: none;
padding: 0;
margin: 0;
box-shadow: none;
}
/* Upload Button
------------------------------------------ */
.qq-gallery .qq-upload-button {
display: inline;
width: 105px;
padding: 7px 10px;
float: left;
text-align: center;
background: #00ABC7;
color: #FFFFFF;
border-radius: 2px;
border: 1px solid #37B7CC;
box-shadow: 0 1px 1px rgba(255, 255, 255, 0.37) inset,
1px 0 1px rgba(255, 255, 255, 0.07) inset,
0 1px 0 rgba(0, 0, 0, 0.36),
0 -2px 12px rgba(0, 0, 0, 0.08) inset
}
.qq-gallery .qq-upload-button-hover {
background: #33B6CC;
}
.qq-gallery .qq-upload-button-focus {
outline: 1px dotted #000000;
}
/* Drop Zone
------------------------------------------ */
.qq-gallery.qq-uploader {
position: relative;
min-height: 200px;
max-height: 490px;
overflow-y: hidden;
width: inherit;
border-radius: 6px;
border: 1px dashed #CCCCCC;
background-color: #FAFAFA;
padding: 20px;
}
.qq-gallery.qq-uploader:before {
content: attr(qq-drop-area-text) " ";
position: absolute;
font-size: 200%;
left: 0;
width: 100%;
text-align: center;
top: 45%;
opacity: 0.25;
filter: alpha(opacity=25);
}
.qq-gallery .qq-upload-drop-area, .qq-upload-extra-drop-area {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
min-height: 30px;
z-index: 2;
background: #F9F9F9;
border-radius: 4px;
text-align: center;
}
.qq-gallery .qq-upload-drop-area span {
display: block;
position: absolute;
top: 50%;
width: 100%;
margin-top: -8px;
font-size: 16px;
}
.qq-gallery .qq-upload-extra-drop-area {
position: relative;
margin-top: 50px;
font-size: 16px;
padding-top: 30px;
height: 20px;
min-height: 40px;
}
.qq-gallery .qq-upload-drop-area-active {
background: #FDFDFD;
border-radius: 4px;
}
.qq-gallery .qq-upload-list {
margin: 0;
padding: 10px 0 0;
list-style: none;
max-height: 450px;
overflow-y: auto;
clear: both;
box-shadow: none;
}
/* Uploaded Elements
------------------------------------------ */
.qq-gallery .qq-upload-list li {
display: inline-block;
position: relative;
max-width: 120px;
margin: 0 25px 25px 0;
padding: 0;
line-height: 16px;
font-size: 13px;
color: #424242;
background-color: #FFFFFF;
border-radius: 2px;
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.22);
vertical-align: top;
/* to ensure consistent size of tiles - may need to change if qq-max-size attr on preview img changes */
height: 186px;
}
.qq-gallery .qq-upload-spinner,
.qq-gallery .qq-upload-size,
.qq-gallery .qq-upload-retry,
.qq-gallery .qq-upload-failed-text,
.qq-gallery .qq-upload-delete,
.qq-gallery .qq-upload-pause,
.qq-gallery .qq-upload-continue {
display: inline;
}
.qq-gallery .qq-upload-retry:hover,
.qq-gallery .qq-upload-delete:hover,
.qq-gallery .qq-upload-pause:hover,
.qq-gallery .qq-upload-continue:hover {
background-color: transparent;
}
.qq-gallery .qq-upload-delete,
.qq-gallery .qq-upload-pause,
.qq-gallery .qq-upload-continue,
.qq-gallery .qq-upload-cancel {
cursor: pointer;
}
.qq-gallery .qq-upload-delete,
.qq-gallery .qq-upload-pause,
.qq-gallery .qq-upload-continue {
border:none;
background: none;
color: #00A0BA;
font-size: 12px;
padding: 0;
}
/* to ensure consistent size of tiles - only display status text before auto-retry or after failure */
.qq-gallery .qq-upload-status-text {
color: #333333;
font-size: 12px;
padding-left: 3px;
padding-top: 2px;
width: inherit;
display: none;
width: 108px;
}
.qq-gallery .qq-upload-fail .qq-upload-status-text {
text-overflow: ellipsis;
white-space: nowrap;
overflow-x: hidden;
display: block;
}
.qq-gallery .qq-upload-retrying .qq-upload-status-text {
display: inline-block;
}
.qq-gallery .qq-upload-retrying .qq-progress-bar-container {
display: none;
}
.qq-gallery .qq-upload-cancel {
background-color: #525252;
color: #F7F7F7;
font-weight: bold;
font-family: Arial, Helvetica, sans-serif;
border-radius: 12px;
border: none;
height: 22px;
width: 22px;
padding: 4px;
position: absolute;
right: -5px;
top: -6px;
margin: 0;
line-height: 17px;
}
.qq-gallery .qq-upload-cancel:hover {
background-color: #525252;
}
.qq-gallery .qq-upload-retry {
cursor: pointer;
position: absolute;
top: 30px;
left: 50%;
margin-left: -31px;
box-shadow: 0 1px 1px rgba(255, 255, 255, 0.37) inset,
1px 0 1px rgba(255, 255, 255, 0.07) inset,
0 4px 4px rgba(0, 0, 0, 0.5),
0 -2px 12px rgba(0, 0, 0, 0.08) inset;
padding: 3px 4px;
border: 1px solid #d2ddc7;
border-radius: 2px;
color: inherit;
background-color: #EBF6E0;
z-index: 1;
}
.qq-gallery .qq-upload-retry:hover {
background-color: #f7ffec;
}
.qq-gallery .qq-file-info {
padding: 10px 6px 4px;
margin-top: -3px;
border-radius: 0 0 2px 2px;
text-align: left;
overflow: hidden;
}
.qq-gallery .qq-file-info .qq-file-name {
position: relative;
}
.qq-gallery .qq-upload-file {
display: block;
margin-right: 0;
margin-bottom: 3px;
width: auto;
/* to ensure consistent size of tiles - constrain text to single line */
text-overflow: ellipsis;
white-space: nowrap;
overflow-x: hidden;
}
.qq-gallery .qq-upload-spinner {
display: inline-block;
background: url("loading.gif");
position: absolute;
left: 50%;
margin-left: -7px;
top: 53px;
width: 15px;
height: 15px;
vertical-align: text-bottom;
}
.qq-gallery .qq-drop-processing {
display: block;
}
.qq-gallery .qq-drop-processing-spinner {
display: inline-block;
background: url("processing.gif");
width: 24px;
height: 24px;
vertical-align: text-bottom;
}
.qq-gallery .qq-upload-failed-text {
display: none;
font-style: italic;
font-weight: bold;
}
.qq-gallery .qq-upload-failed-icon {
display:none;
width:15px;
height:15px;
vertical-align:text-bottom;
}
.qq-gallery .qq-upload-fail .qq-upload-failed-text {
display: inline;
}
.qq-gallery .qq-upload-retrying .qq-upload-failed-text {
display: inline;
}
.qq-gallery .qq-upload-list li.qq-upload-success {
background-color: #F2F7ED;
}
.qq-gallery .qq-upload-list li.qq-upload-fail {
background-color: #F5EDED;
box-shadow: 0 0 1px 0 red;
border: 0;
}
.qq-gallery .qq-progress-bar {
display: block;
background: #00abc7;
width: 0%;
height: 15px;
border-radius: 6px;
margin-bottom: 3px;
}
.qq-gallery .qq-total-progress-bar {
height: 25px;
border-radius: 9px;
}
.qq-gallery .qq-total-progress-bar-container {
margin-left: 9px;
display: inline;
float: right;
width: 500px;
}
.qq-gallery .qq-upload-size {
float: left;
font-size: 11px;
color: #929292;
margin-bottom: 3px;
margin-right: 0;
display: inline-block;
}
.qq-gallery INPUT.qq-edit-filename {
position: absolute;
opacity: 0;
filter: alpha(opacity=0);
z-index: -1;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
}
.qq-gallery .qq-upload-file.qq-editable {
cursor: pointer;
margin-right: 20px;
}
.qq-gallery .qq-edit-filename-icon.qq-editable {
display: inline-block;
cursor: pointer;
position: absolute;
right: 0;
top: 0;
}
.qq-gallery INPUT.qq-edit-filename.qq-editing {
position: static;
height: 28px;
width: 90px;
width: -moz-available;
padding: 0 8px;
margin-bottom: 3px;
border: 1px solid #ccc;
border-radius: 2px;
font-size: 13px;
opacity: 1;
filter: alpha(opacity=100);
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
}
.qq-gallery .qq-edit-filename-icon {
display: none;
background: url("edit.gif");
width: 15px;
height: 15px;
vertical-align: text-bottom;
}
.qq-gallery .qq-delete-icon {
background: url("trash.gif");
width: 15px;
height: 15px;
vertical-align: sub;
display: inline-block;
}
.qq-gallery .qq-retry-icon {
background: url("retry.gif");
width: 15px;
height: 15px;
vertical-align: sub;
display: inline-block;
float: none;
}
.qq-gallery .qq-continue-icon {
background: url("continue.gif");
width: 15px;
height: 15px;
vertical-align: sub;
display: inline-block;
}
.qq-gallery .qq-pause-icon {
background: url("pause.gif");
width: 15px;
height: 15px;
vertical-align: sub;
display: inline-block;
}
.qq-gallery .qq-hide {
display: none;
}
/* Thumbnail
------------------------------------------ */
.qq-gallery .qq-in-progress .qq-thumbnail-wrapper {
/* makes the spinner on top of the thumbnail more visible */
opacity: 0.5;
filter: alpha(opacity=50);
}
.qq-gallery .qq-thumbnail-wrapper {
overflow: hidden;
position: relative;
/* to ensure consistent size of tiles - should match qq-max-size attribute value on qq-thumbnail-selector IMG element */
height: 120px;
width: 120px;
}
.qq-gallery .qq-thumbnail-selector {
border-radius: 2px 2px 0 0;
bottom: 0;
/* we will override this in the :root thumbnail selector (to help center the preview) for everything other than IE8 */
top: 0;
/* center the thumb horizontally in the tile */
margin:auto;
display: block;
}
/* hack to ensure we don't try to center preview in IE8, since -ms-filter doesn't mimic translateY as expected in all cases */
:root *> .qq-gallery .qq-thumbnail-selector {
/* vertically center preview image on tile */
position: relative;
top: 50%;
transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-webkit-transform: translateY(-50%);
}
/* <dialog> element styles */
.qq-gallery.qq-uploader DIALOG {
display: none;
}
.qq-gallery.qq-uploader DIALOG[open] {
display: block;
}
.qq-gallery.qq-uploader DIALOG {
display: none;
}
.qq-gallery.qq-uploader DIALOG[open] {
display: block;
}
.qq-gallery.qq-uploader DIALOG .qq-dialog-buttons {
text-align: center;
padding-top: 10px;
}
.qq-gallery.qq-uploader DIALOG .qq-dialog-buttons BUTTON {
margin-left: 5px;
margin-right: 5px;
}
.qq-gallery.qq-uploader DIALOG .qq-dialog-message-selector {
padding-bottom: 10px;
}
.qq-gallery .qq-uploader DIALOG::backdrop {
background-color: rgba(0, 0, 0, 0.7);
}
================================================
FILE: client/fine-uploader-new.css
================================================
/* ---------------------------------------
/* Fine Uploader Styles
/* ---------------------------------------
/* Buttons
------------------------------------------ */
.qq-btn
{
box-shadow: 0 1px 1px rgba(255, 255, 255, 0.37) inset,
1px 0 1px rgba(255, 255, 255, 0.07) inset,
0 1px 0 rgba(0, 0, 0, 0.36),
0 -2px 12px rgba(0, 0, 0, 0.08) inset;
padding: 3px 4px;
border: 1px solid #CCCCCC;
border-radius: 2px;
color: inherit;
background-color: #FFFFFF;
}
.qq-upload-delete, .qq-upload-pause, .qq-upload-continue {
display: inline;
}
.qq-upload-delete
{
background-color: #e65c47;
color: #FAFAFA;
border-color: #dc523d;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.55);
}
.qq-upload-delete:hover {
background-color: #f56b56;
}
.qq-upload-cancel
{
background-color: #F5D7D7;
border-color: #e6c8c8;
}
.qq-upload-cancel:hover {
background-color: #ffe1e1;
}
.qq-upload-retry
{
background-color: #EBF6E0;
border-color: #d2ddc7;
}
.qq-upload-retry:hover {
background-color: #f7ffec;
}
.qq-upload-pause, .qq-upload-continue {
background-color: #00ABC7;
color: #FAFAFA;
border-color: #2dadc2;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.55);
}
.qq-upload-pause:hover, .qq-upload-continue:hover {
background-color: #0fbad6;
}
/* Upload Button
------------------------------------------ */
.qq-upload-button {
display: inline;
width: 105px;
margin-bottom: 10px;
padding: 7px 10px;
text-align: center;
float: left;
background: #00ABC7;
color: #FFFFFF;
border-radius: 2px;
border: 1px solid #2dadc2;
box-shadow: 0 1px 1px rgba(255, 255, 255, 0.37) inset,
1px 0 1px rgba(255, 255, 255, 0.07) inset,
0 1px 0 rgba(0, 0, 0, 0.36),
0 -2px 12px rgba(0, 0, 0, 0.08) inset;
}
.qq-upload-button-hover {
background: #33B6CC;
}
.qq-upload-button-focus {
outline: 1px dotted #000000;
}
/* Drop Zone
------------------------------------------ */
.qq-uploader {
position: relative;
min-height: 200px;
max-height: 490px;
overflow-y: hidden;
width: inherit;
border-radius: 6px;
background-color: #FDFDFD;
border: 1px dashed #CCCCCC;
padding: 20px;
}
.qq-uploader:before {
content: attr(qq-drop-area-text) " ";
position: absolute;
font-size: 200%;
left: 0;
width: 100%;
text-align: center;
top: 45%;
opacity: 0.25;
}
.qq-upload-drop-area, .qq-upload-extra-drop-area {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
min-height: 30px;
z-index: 2;
background: #F9F9F9;
border-radius: 4px;
border: 1px dashed #CCCCCC;
text-align: center;
}
.qq-upload-drop-area span {
display: block;
position: absolute;
top: 50%;
width: 100%;
margin-top: -8px;
font-size: 16px;
}
.qq-upload-extra-drop-area {
position: relative;
margin-top: 50px;
font-size: 16px;
padding-top: 30px;
height: 20px;
min-height: 40px;
}
.qq-upload-drop-area-active {
background: #FDFDFD;
border-radius: 4px;
border: 1px dashed #CCCCCC;
}
.qq-upload-list {
margin: 0;
padding: 0;
list-style: none;
max-height: 450px;
overflow-y: auto;
box-shadow: 0px 1px 0px rgba(15, 15, 50, 0.14);
clear: both;
}
/* Uploaded Elements
------------------------------------------ */
.qq-upload-list li {
margin: 0;
padding: 9px;
line-height: 15px;
font-size: 16px;
color: #424242;
background-color: #F6F6F6;
border-top: 1px solid #FFFFFF;
border-bottom: 1px solid #DDDDDD;
}
.qq-upload-list li:first-child {
border-top: none;
}
.qq-upload-list li:last-child {
border-bottom: none;
}
.qq-upload-file, .qq-upload-spinner, .qq-upload-size,
.qq-upload-cancel, .qq-upload-retry, .qq-upload-failed-text,
.qq-upload-delete, .qq-upload-pause, .qq-upload-continue {
margin-right: 12px;
display: inline;
}
.qq-upload-file {
vertical-align: middle;
display: inline-block;
width: 300px;
text-overflow: ellipsis;
white-space: nowrap;
overflow-x: hidden;
height: 18px;
}
.qq-upload-spinner {
display: inline-block;
background: url("loading.gif");
width: 15px;
height: 15px;
vertical-align: text-bottom;
}
.qq-drop-processing {
display: block;
}
.qq-drop-processing-spinner {
display: inline-block;
background: url("processing.gif");
width: 24px;
height: 24px;
vertical-align: text-bottom;
}
.qq-upload-size, .qq-upload-cancel, .qq-upload-retry,
.qq-upload-delete, .qq-upload-pause, .qq-upload-continue {
font-size: 12px;
font-weight: normal;
cursor: pointer;
vertical-align: middle;
}
.qq-upload-status-text {
font-size: 14px;
font-weight: bold;
display: block;
}
.qq-upload-failed-text {
display: none;
font-style: italic;
font-weight: bold;
}
.qq-upload-failed-icon {
display:none;
width:15px;
height:15px;
vertical-align:text-bottom;
}
.qq-upload-fail .qq-upload-failed-text {
display: inline;
}
.qq-upload-retrying .qq-upload-failed-text {
display: inline;
}
.qq-upload-list li.qq-upload-success {
background-color: #EBF6E0;
color: #424242;
border-bottom: 1px solid #D3DED1;
border-top: 1px solid #F7FFF5;
}
.qq-upload-list li.qq-upload-fail {
background-color: #F5D7D7;
color: #424242;
border-bottom: 1px solid #DECACA;
border-top: 1px solid #FCE6E6;
}
.qq-progress-bar {
display: block;
display: block;
background: #00abc7;
width: 0%;
height: 15px;
border-radius: 6px;
margin-bottom: 3px;
}
.qq-total-progress-bar {
height: 25px;
border-radius: 9px;
}
.qq-total-progress-bar-container {
margin-left: 9px;
display: inline;
float: right;
width: 500px;
}
INPUT.qq-edit-filename {
position: absolute;
opacity: 0;
filter: alpha(opacity=0);
z-index: -1;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
}
.qq-upload-file.qq-editable {
cursor: pointer;
margin-right: 4px;
}
.qq-edit-filename-icon.qq-editable {
display: inline-block;
cursor: pointer;
}
INPUT.qq-edit-filename.qq-editing {
position: static;
height: 28px;
padding: 0 8px;
margin-right: 10px;
margin-bottom: -5px;
border: 1px solid #ccc;
border-radius: 2px;
font-size: 16px;
opacity: 1;
filter: alpha(opacity=100);
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
}
.qq-edit-filename-icon {
display: none;
background: url("edit.gif");
width: 15px;
height: 15px;
vertical-align: text-bottom;
margin-right: 16px;
}
.qq-hide {
display: none;
}
/* Thumbnail
------------------------------------------ */
.qq-thumbnail-selector {
vertical-align: middle;
margin-right: 12px;
}
/* <dialog> element styles */
.qq-uploader DIALOG {
display: none;
}
.qq-uploader DIALOG[open] {
display: block;
}
.qq-uploader DIALOG {
display: none;
}
.qq-uploader DIALOG[open] {
display: block;
}
.qq-uploader DIALOG .qq-dialog-buttons {
text-align: center;
padding-top: 10px;
}
.qq-uploader DIALOG .qq-dialog-buttons BUTTON {
margin-left: 5px;
margin-right: 5px;
}
.qq-uploader DIALOG .qq-dialog-message-selector {
padding-bottom: 10px;
}
.qq-uploader DIALOG::backdrop {
background-color: rgba(0, 0, 0, 0.7);
}
================================================
FILE: client/fine-uploader.css
================================================
.qq-uploader {
position: relative;
width: 100%;
}
.qq-upload-button {
display: block;
width: 105px;
padding: 7px 0;
text-align: center;
background: #880000;
border-bottom: 1px solid #DDD;
color: #FFF;
}
.qq-upload-button-hover {
background: #CC0000;
}
.qq-upload-button-focus {
outline: 1px dotted #000000;
}
.qq-upload-drop-area, .qq-upload-extra-drop-area {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
min-height: 30px;
z-index: 2;
background: #FF9797;
text-align: center;
}
.qq-upload-drop-area span {
display: block;
position: absolute;
top: 50%;
width: 100%;
margin-top: -8px;
font-size: 16px;
}
.qq-upload-extra-drop-area {
position: relative;
margin-top: 50px;
font-size: 16px;
padding-top: 30px;
height: 20px;
min-height: 40px;
}
.qq-upload-drop-area-active {
background: #FF7171;
}
.qq-upload-list {
margin: 0;
padding: 0;
list-style: none;
}
.qq-upload-list li {
margin: 0;
padding: 9px;
line-height: 15px;
font-size: 16px;
background-color: #FFF0BD;
}
.qq-upload-file, .qq-upload-spinner, .qq-upload-size,
.qq-upload-cancel, .qq-upload-retry, .qq-upload-failed-text,
.qq-upload-delete, .qq-upload-pause, .qq-upload-continue {
margin-right: 12px;
display: inline;
}
.qq-upload-file {
}
.qq-upload-spinner {
display: inline-block;
background: url("loading.gif");
width: 15px;
height: 15px;
vertical-align: text-bottom;
}
.qq-drop-processing {
display: block;
}
.qq-drop-processing-spinner {
display: inline-block;
background: url("processing.gif");
width: 24px;
height: 24px;
vertical-align: text-bottom;
}
.qq-upload-delete, .qq-upload-pause, .qq-upload-continue {
display: inline;
}
.qq-upload-retry, .qq-upload-delete, .qq-upload-cancel,
.qq-upload-pause, .qq-upload-continue {
color: #000000;
}
.qq-upload-size, .qq-upload-cancel, .qq-upload-retry,
.qq-upload-delete, .qq-upload-pause, .qq-upload-continue {
font-size: 12px;
font-weight: normal;
}
.qq-upload-failed-text {
display: none;
font-style: italic;
font-weight: bold;
}
.qq-upload-failed-icon {
display:none;
width:15px;
height:15px;
vertical-align:text-bottom;
}
.qq-upload-fail .qq-upload-failed-text {
display: inline;
}
.qq-upload-retrying .qq-upload-failed-text {
display: inline;
color: #D60000;
}
.qq-upload-list li.qq-upload-success {
background-color: #5DA30C;
color: #FFFFFF;
}
.qq-upload-list li.qq-upload-fail {
background-color: #D60000;
color: #FFFFFF;
}
.qq-progress-bar {
display: block;
background: -moz-linear-gradient(top, rgba(30,87,153,1) 0%, rgba(41,137,216,1) 50%, rgba(32,124,202,1) 51%, rgba(125,185,232,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(30,87,153,1)), color-stop(50%,rgba(41,137,216,1)), color-stop(51%,rgba(32,124,202,1)), color-stop(100%,rgba(125,185,232,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(30,87,153,1) 0%,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(30,87,153,1) 0%,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(30,87,153,1) 0%,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgba(30,87,153,1) 0%,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%); /* W3C */
width: 0%;
height: 15px;
border-radius: 6px;
margin-bottom: 3px;
}
.qq-total-progress-bar {
height: 25px;
border-radius: 9px;
}
.qq-total-progress-bar-container {
margin: 9px;
}
INPUT.qq-edit-filename {
position: absolute;
opacity: 0;
filter: alpha(opacity=0);
z-index: -1;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
}
.qq-upload-file.qq-editable {
cursor: pointer;
}
.qq-edit-filename-icon.qq-editable {
display: inline-block;
cursor: pointer;
}
INPUT.qq-edit-filename.qq-editing {
position: static;
margin-top: -5px;
margin-right: 10px;
margin-bottom: -5px;
opacity: 1;
filter: alpha(opacity=100);
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
}
.qq-edit-filename-icon {
display: none;
background: url("edit.gif");
width: 15px;
height: 15px;
vertical-align: text-bottom;
margin-right: 5px;
}
.qq-hide {
display: none;
}
/* <dialog> element styles */
.qq-uploader DIALOG {
display: none;
}
.qq-uploader DIALOG[open] {
display: block;
}
.qq-uploader DIALOG {
display: none;
}
.qq-uploader DIALOG[open] {
display: block;
}
.qq-uploader DIALOG .qq-dialog-buttons {
text-align: center;
padding-top: 10px;
}
.qq-uploader DIALOG .qq-dialog-buttons BUTTON {
margin-left: 5px;
margin-right: 5px;
}
.qq-uploader DIALOG .qq-dialog-message-selector {
padding-bottom: 10px;
}
.qq-uploader DIALOG::backdrop {
background-color: rgba(0, 0, 0, 0.7);
}
================================================
FILE: client/html/templates/default.html
================================================
<!--
This is a legacy template and is not meant to be used in new Fine Uploader integrated projects.
Read the "Getting Started Guide" at http://docs.fineuploader.com/quickstart/01-getting-started.html
if you are not yet familiar with Fine Uploader UI.
-->
<script type="text/template" id="qq-template">
<div class="qq-uploader-selector qq-uploader" qq-drop-area-text="Drop files here">
<div class="qq-total-progress-bar-container-selector qq-total-progress-bar-container">
<div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-total-progress-bar-selector qq-progress-bar qq-total-progress-bar"></div>
</div>
<div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone>
<span class="qq-upload-drop-area-text-selector"></span>
</div>
<div class="qq-upload-button-selector qq-upload-button">
<div>Upload a file</div>
</div>
<span class="qq-drop-processing-selector qq-drop-processing">
<span>Processing dropped files...</span>
<span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span>
</span>
<ul class="qq-upload-list-selector qq-upload-list" aria-live="polite" aria-relevant="additions removals">
<li>
<div class="qq-progress-bar-container-selector">
<div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-progress-bar-selector qq-progress-bar"></div>
</div>
<span class="qq-upload-spinner-selector qq-upload-spinner"></span>
<span class="qq-upload-file-selector qq-upload-file"></span>
<span class="qq-edit-filename-icon-selector qq-edit-filename-icon" aria-label="Edit filename"></span>
<input class="qq-edit-filename-selector qq-edit-filename" tabindex="0" type="text">
<span class="qq-upload-size-selector qq-upload-size"></span>
<button type="button" class="qq-btn qq-upload-cancel-selector qq-upload-cancel">Cancel</button>
<button type="button" class="qq-btn qq-upload-retry-selector qq-upload-retry">Retry</button>
<button type="button" class="qq-btn qq-upload-delete-selector qq-upload-delete">Delete</button>
<span role="status" class="qq-upload-status-text-selector qq-upload-status-text"></span>
</li>
</ul>
<dialog class="qq-alert-dialog-selector">
<div class="qq-dialog-message-selector"></div>
<div class="qq-dialog-buttons">
<button type="button" class="qq-cancel-button-selector">Close</button>
</div>
</dialog>
<dialog class="qq-confirm-dialog-selector">
<div class="qq-dialog-message-selector"></div>
<div class="qq-dialog-buttons">
<button type="button" class="qq-cancel-button-selector">No</button>
<button type="button" class="qq-ok-button-selector">Yes</button>
</div>
</dialog>
<dialog class="qq-prompt-dialog-selector">
<div class="qq-dialog-message-selector"></div>
<input type="text">
<div class="qq-dialog-buttons">
<button type="button" class="qq-cancel-button-selector">Cancel</button>
<button type="button" class="qq-ok-button-selector">Ok</button>
</div>
</dialog>
</div>
</script>
================================================
FILE: client/html/templates/gallery.html
================================================
<!--
Read the "Getting Started Guide" at http://docs.fineuploader.com/quickstart/01-getting-started.html
if you are not yet familiar with Fine Uploader UI.
Please see http://docs.fineuploader.com/features/styling.html for information
on how to customize this template.
-->
<script type="text/template" id="qq-template">
<div class="qq-uploader-selector qq-uploader qq-gallery" qq-drop-area-text="Drop files here">
<div class="qq-total-progress-bar-container-selector qq-total-progress-bar-container">
<div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-total-progress-bar-selector qq-progress-bar qq-total-progress-bar"></div>
</div>
<div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone>
<span class="qq-upload-drop-area-text-selector"></span>
</div>
<div class="qq-upload-button-selector qq-upload-button">
<div>Upload a file</div>
</div>
<span class="qq-drop-processing-selector qq-drop-processing">
<span>Processing dropped files...</span>
<span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span>
</span>
<ul class="qq-upload-list-selector qq-upload-list" role="region" aria-live="polite" aria-relevant="additions removals">
<li>
<span role="status" class="qq-upload-status-text-selector qq-upload-status-text"></span>
<div class="qq-progress-bar-container-selector qq-progress-bar-container">
<div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-progress-bar-selector qq-progress-bar"></div>
</div>
<span class="qq-upload-spinner-selector qq-upload-spinner"></span>
<div class="qq-thumbnail-wrapper">
<img class="qq-thumbnail-selector" qq-max-size="120" qq-server-scale>
</div>
<button type="button" class="qq-upload-cancel-selector qq-upload-cancel">X</button>
<button type="button" class="qq-upload-retry-selector qq-upload-retry">
<span class="qq-btn qq-retry-icon" aria-label="Retry"></span>
Retry
</button>
<div class="qq-file-info">
<div class="qq-file-name">
<span class="qq-upload-file-selector qq-upload-file"></span>
<span class="qq-edit-filename-icon-selector qq-btn qq-edit-filename-icon" aria-label="Edit filename"></span>
</div>
<input class="qq-edit-filename-selector qq-edit-filename" tabindex="0" type="text">
<span class="qq-upload-size-selector qq-upload-size"></span>
<button type="button" class="qq-btn qq-upload-delete-selector qq-upload-delete">
<span class="qq-btn qq-delete-icon" aria-label="Delete"></span>
</button>
<button type="button" class="qq-btn qq-upload-pause-selector qq-upload-pause">
<span class="qq-btn qq-pause-icon" aria-label="Pause"></span>
</button>
<button type="button" class="qq-btn qq-upload-continue-selector qq-upload-continue">
<span class="qq-btn qq-continue-icon" aria-label="Continue"></span>
</button>
</div>
</li>
</ul>
<dialog class="qq-alert-dialog-selector">
<div class="qq-dialog-message-selector"></div>
<div class="qq-dialog-buttons">
<button type="button" class="qq-cancel-button-selector">Close</button>
</div>
</dialog>
<dialog class="qq-confirm-dialog-selector">
<div class="qq-dialog-message-selector"></div>
<div class="qq-dialog-buttons">
<button type="button" class="qq-cancel-button-selector">No</button>
<button type="button" class="qq-ok-button-selector">Yes</button>
</div>
</dialog>
<dialog class="qq-prompt-dialog-selector">
<div class="qq-dialog-message-selector"></div>
<input type="text">
<div class="qq-dialog-buttons">
<button type="button" class="qq-cancel-button-selector">Cancel</button>
<button type="button" class="qq-ok-button-selector">Ok</button>
</div>
</dialog>
</div>
</script>
================================================
FILE: client/html/templates/simple-thumbnails.html
================================================
<!--
Read the "Getting Started Guide" at http://docs.fineuploader.com/quickstart/01-getting-started.html
if you are not yet familiar with Fine Uploader UI.
Please see http://docs.fineuploader.com/features/styling.html for information
on how to customize this template.
-->
<script type="text/template" id="qq-simple-thumbnails-template">
<div class="qq-uploader-selector qq-uploader" qq-drop-area-text="Drop files here">
<div class="qq-total-progress-bar-container-selector qq-total-progress-bar-container">
<div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-total-progress-bar-selector qq-progress-bar qq-total-progress-bar"></div>
</div>
<div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone>
<span class="qq-upload-drop-area-text-selector"></span>
</div>
<div class="qq-upload-button-selector qq-upload-button">
<div>Upload a file</div>
</div>
<span class="qq-drop-processing-selector qq-drop-processing">
<span>Processing dropped files...</span>
<span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span>
</span>
<ul class="qq-upload-list-selector qq-upload-list" aria-live="polite" aria-relevant="additions removals">
<li>
<div class="qq-progress-bar-container-selector">
<div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-progress-bar-selector qq-progress-bar"></div>
</div>
<span class="qq-upload-spinner-selector qq-upload-spinner"></span>
<img class="qq-thumbnail-selector" qq-max-size="100" qq-server-scale>
<span class="qq-upload-file-selector qq-upload-file"></span>
<span class="qq-edit-filename-icon-selector qq-edit-filename-icon" aria-label="Edit filename"></span>
<input class="qq-edit-filename-selector qq-edit-filename" tabindex="0" type="text">
<span class="qq-upload-size-selector qq-upload-size"></span>
<button type="button" class="qq-btn qq-upload-cancel-selector qq-upload-cancel">Cancel</button>
<button type="button" class="qq-btn qq-upload-retry-selector qq-upload-retry">Retry</button>
<button type="button" class="qq-btn qq-upload-delete-selector qq-upload-delete">Delete</button>
<span role="status" class="qq-upload-status-text-selector qq-upload-status-text"></span>
</li>
</ul>
<dialog class="qq-alert-dialog-selector">
<div class="qq-dialog-message-selector"></div>
<div class="qq-dialog-buttons">
<button type="button" class="qq-cancel-button-selector">Close</button>
</div>
</dialog>
<dialog class="qq-confirm-dialog-selector">
<div class="qq-dialog-message-selector"></div>
<div class="qq-dialog-buttons">
<button type="button" class="qq-cancel-button-selector">No</button>
<button type="button" class="qq-ok-button-selector">Yes</button>
</div>
</dialog>
<dialog class="qq-prompt-dialog-selector">
<div class="qq-dialog-message-selector"></div>
<input type="text">
<div class="qq-dialog-buttons">
<button type="button" class="qq-cancel-button-selector">Cancel</button>
<button type="button" class="qq-ok-button-selector">Ok</button>
</div>
</dialog>
</div>
</script>
================================================
FILE: client/js/ajax.requester.js
================================================
/*globals qq, XDomainRequest*/
/** Generic class for sending non-upload ajax requests and handling the associated responses **/
qq.AjaxRequester = function(o) {
"use strict";
var log, shouldParamsBeInQueryString,
queue = [],
requestData = {},
options = {
acceptHeader: null,
validMethods: ["PATCH", "POST", "PUT"],
method: "POST",
contentType: "application/x-www-form-urlencoded",
maxConnections: 3,
customHeaders: {},
endpointStore: {},
paramsStore: {},
mandatedParams: {},
allowXRequestedWithAndCacheControl: true,
successfulResponseCodes: {
DELETE: [200, 202, 204],
PATCH: [200, 201, 202, 203, 204],
POST: [200, 201, 202, 203, 204],
PUT: [200, 201, 202, 203, 204],
GET: [200]
},
cors: {
expected: false,
sendCredentials: false
},
log: function(str, level) {},
onSend: function(id) {},
onComplete: function(id, xhrOrXdr, isError) {},
onProgress: null
};
qq.extend(options, o);
log = options.log;
if (qq.indexOf(options.validMethods, options.method) < 0) {
throw new Error("'" + options.method + "' is not a supported method for this type of request!");
}
// [Simple methods](http://www.w3.org/TR/cors/#simple-method)
// are defined by the W3C in the CORS spec as a list of methods that, in part,
// make a CORS request eligible to be exempt from preflighting.
function isSimpleMethod() {
return qq.indexOf(["GET", "POST", "HEAD"], options.method) >= 0;
}
// [Simple headers](http://www.w3.org/TR/cors/#simple-header)
// are defined by the W3C in the CORS spec as a list of headers that, in part,
// make a CORS request eligible to be exempt from preflighting.
function containsNonSimpleHeaders(headers) {
var containsNonSimple = false;
qq.each(containsNonSimple, function(idx, header) {
if (qq.indexOf(["Accept", "Accept-Language", "Content-Language", "Content-Type"], header) < 0) {
containsNonSimple = true;
return false;
}
});
return containsNonSimple;
}
function isXdr(xhr) {
//The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS.
return options.cors.expected && xhr.withCredentials === undefined;
}
// Returns either a new `XMLHttpRequest` or `XDomainRequest` instance.
function getCorsAjaxTransport() {
var xhrOrXdr;
if (window.XMLHttpRequest || window.ActiveXObject) {
xhrOrXdr = qq.createXhrInstance();
if (xhrOrXdr.withCredentials === undefined) {
xhrOrXdr = new XDomainRequest();
// Workaround for XDR bug in IE9 - https://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment
xhrOrXdr.onload = function() {};
xhrOrXdr.onerror = function() {};
xhrOrXdr.ontimeout = function() {};
xhrOrXdr.onprogress = function() {};
}
}
return xhrOrXdr;
}
// Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`.
function getXhrOrXdr(id, suppliedXhr) {
var xhrOrXdr = requestData[id] && requestData[id].xhr;
if (!xhrOrXdr) {
if (suppliedXhr) {
xhrOrXdr = suppliedXhr;
}
else {
if (options.cors.expected) {
xhrOrXdr = getCorsAjaxTransport();
}
else {
xhrOrXdr = qq.createXhrInstance();
}
}
requestData[id].xhr = xhrOrXdr;
}
return xhrOrXdr;
}
// Removes element from queue, sends next request
function dequeue(id) {
var i = qq.indexOf(queue, id),
max = options.maxConnections,
nextId;
delete requestData[id];
queue.splice(i, 1);
if (queue.length >= max && i < max) {
nextId = queue[max - 1];
sendRequest(nextId);
}
}
function onComplete(id, xdrError) {
var xhr = getXhrOrXdr(id),
method = options.method,
isError = xdrError === true;
dequeue(id);
if (isError) {
log(method + " request for " + id + " has failed", "error");
}
else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) {
isError = true;
log(method + " request for " + id + " has failed - response code " + xhr.status, "error");
}
options.onComplete(id, xhr, isError);
}
function getParams(id) {
var onDemandParams = requestData[id].additionalParams,
mandatedParams = options.mandatedParams,
params;
if (options.paramsStore.get) {
params = options.paramsStore.get(id);
}
if (onDemandParams) {
qq.each(onDemandParams, function(name, val) {
params = params || {};
params[name] = val;
});
}
if (mandatedParams) {
qq.each(mandatedParams, function(name, val) {
params = params || {};
params[name] = val;
});
}
return params;
}
function sendRequest(id, optXhr) {
var xhr = getXhrOrXdr(id, optXhr),
method = options.method,
params = getParams(id),
payload = requestData[id].payload,
url;
options.onSend(id);
url = createUrl(id, params, requestData[id].additionalQueryParams);
// XDR and XHR status detection APIs differ a bit.
if (isXdr(xhr)) {
xhr.onload = getXdrLoadHandler(id);
xhr.onerror = getXdrErrorHandler(id);
}
else {
xhr.onreadystatechange = getXhrReadyStateChangeHandler(id);
}
registerForUploadProgress(id);
// The last parameter is assumed to be ignored if we are actually using `XDomainRequest`.
xhr.open(method, url, true);
// Instruct the transport to send cookies along with the CORS request,
// unless we are using `XDomainRequest`, which is not capable of this.
if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) {
xhr.withCredentials = true;
}
setHeaders(id);
log("Sending " + method + " request for " + id);
if (payload) {
xhr.send(payload);
}
else if (shouldParamsBeInQueryString || !params) {
xhr.send();
}
else if (params && options.contentType && options.contentType.toLowerCase().indexOf("application/x-www-form-urlencoded") >= 0) {
xhr.send(qq.obj2url(params, ""));
}
else if (params && options.contentType && options.contentType.toLowerCase().indexOf("application/json") >= 0) {
xhr.send(JSON.stringify(params));
}
else {
xhr.send(params);
}
return xhr;
}
function createUrl(id, params, additionalQueryParams) {
var endpoint = options.endpointStore.get(id),
addToPath = requestData[id].addToPath;
/*jshint -W116,-W041 */
if (addToPath != undefined) {
endpoint += "/" + addToPath;
}
if (shouldParamsBeInQueryString && params) {
endpoint = qq.obj2url(params, endpoint);
}
if (additionalQueryParams) {
endpoint = qq.obj2url(additionalQueryParams, endpoint);
}
return endpoint;
}
// Invoked by the UA to indicate a number of possible states that describe
// a live `XMLHttpRequest` transport.
function getXhrReadyStateChangeHandler(id) {
return function() {
if (getXhrOrXdr(id).readyState === 4) {
onComplete(id);
}
};
}
function registerForUploadProgress(id) {
var onProgress = options.onProgress;
if (onProgress) {
getXhrOrXdr(id).upload.onprogress = function(e) {
if (e.lengthComputable) {
onProgress(id, e.loaded, e.total);
}
};
}
}
// This will be called by IE to indicate **success** for an associated
// `XDomainRequest` transported request.
function getXdrLoadHandler(id) {
return function() {
onComplete(id);
};
}
// This will be called by IE to indicate **failure** for an associated
// `XDomainRequest` transported request.
function getXdrErrorHandler(id) {
return function() {
onComplete(id, true);
};
}
function setHeaders(id) {
var xhr = getXhrOrXdr(id),
customHeaders = options.customHeaders,
onDemandHeaders = requestData[id].additionalHeaders || {},
method = options.method,
allHeaders = {};
// If XDomainRequest is being used, we can't set headers, so just ignore this block.
if (!isXdr(xhr)) {
options.acceptHeader && xhr.setRequestHeader("Accept", options.acceptHeader);
// Only attempt to add X-Requested-With & Cache-Control if permitted
if (options.allowXRequestedWithAndCacheControl) {
// Do not add X-Requested-With & Cache-Control if this is a cross-origin request
// OR the cross-origin request contains a non-simple method or header.
// This is done to ensure a preflight is not triggered exclusively based on the
// addition of these 2 non-simple headers.
if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) {
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("Cache-Control", "no-cache");
}
}
if (options.contentType && (method === "POST" || method === "PUT")) {
xhr.setRequestHeader("Content-Type", options.contentType);
}
qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders);
qq.extend(allHeaders, onDemandHeaders);
qq.each(allHeaders, function(name, val) {
xhr.setRequestHeader(name, val);
});
}
}
function isResponseSuccessful(responseCode) {
return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0;
}
function prepareToSend(id, optXhr, addToPath, additionalParams, additionalQueryParams, additionalHeaders, payload) {
requestData[id] = {
addToPath: addToPath,
additionalParams: additionalParams,
additionalQueryParams: additionalQueryParams,
additionalHeaders: additionalHeaders,
payload: payload
};
var len = queue.push(id);
// if too many active connections, wait...
if (len <= options.maxConnections) {
return sendRequest(id, optXhr);
}
}
shouldParamsBeInQueryString = options.method === "GET" || options.method === "DELETE";
qq.extend(this, {
// Start the process of sending the request. The ID refers to the file associated with the request.
initTransport: function(id) {
var path, params, headers, payload, cacheBuster, additionalQueryParams;
return {
// Optionally specify the end of the endpoint path for the request.
withPath: function(appendToPath) {
path = appendToPath;
return this;
},
// Optionally specify additional parameters to send along with the request.
// These will be added to the query string for GET/DELETE requests or the payload
// for POST/PUT requests. The Content-Type of the request will be used to determine
// how these parameters should be formatted as well.
withParams: function(additionalParams) {
params = additionalParams;
return this;
},
withQueryParams: function(_additionalQueryParams_) {
additionalQueryParams = _additionalQueryParams_;
return this;
},
// Optionally specify additional headers to send along with the request.
withHeaders: function(additionalHeaders) {
headers = additionalHeaders;
return this;
},
// Optionally specify a payload/body for the request.
withPayload: function(thePayload) {
payload = thePayload;
return this;
},
// Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE)
withCacheBuster: function() {
cacheBuster = true;
return this;
},
// Send the constructed request.
send: function(optXhr) {
if (cacheBuster && qq.indexOf(["GET", "DELETE"], options.method) >= 0) {
params.qqtimestamp = new Date().getTime();
}
return prepareToSend(id, optXhr, path, params, additionalQueryParams, headers, payload);
}
};
},
canceled: function(id) {
dequeue(id);
}
});
};
================================================
FILE: client/js/azure/azure.xhr.upload.handler.js
================================================
/*globals qq */
/**
* Upload handler used by the upload to Azure module that depends on File API support, and, therefore, makes use of
* `XMLHttpRequest` level 2 to upload `File`s and `Blob`s directly to Azure Blob Storage containers via the
* associated Azure API.
*
* @param spec Options passed from the base handler
* @param proxy Callbacks & methods used to query for or push out data/changes
*/
// TODO l18n for error messages returned to UI
qq.azure.XhrUploadHandler = function(spec, proxy) {
"use strict";
var handler = this,
log = proxy.log,
cors = spec.cors,
endpointStore = spec.endpointStore,
paramsStore = spec.paramsStore,
signature = spec.signature,
filenameParam = spec.filenameParam,
minFileSizeForChunking = spec.chunking.minFileSize,
deleteBlob = spec.deleteBlob,
onGetBlobName = spec.onGetBlobName,
getName = proxy.getName,
getSize = proxy.getSize,
getBlobMetadata = function(id) {
var params = paramsStore.get(id);
params[filenameParam] = getName(id);
return params;
},
api = {
putBlob: new qq.azure.PutBlob({
getBlobMetadata: getBlobMetadata,
log: log
}),
putBlock: new qq.azure.PutBlock({
log: log
}),
putBlockList: new qq.azure.PutBlockList({
getBlobMetadata: getBlobMetadata,
log: log
}),
getSasForPutBlobOrBlock: new qq.azure.GetSas({
cors: cors,
customHeaders: signature.customHeaders,
endpointStore: {
get: function() {
return signature.endpoint;
}
},
log: log,
restRequestVerb: "PUT"
})
};
function combineChunks(id) {
var promise = new qq.Promise();
getSignedUrl(id).then(function(sasUri) {
var mimeType = handler._getMimeType(id),
blockIdEntries = handler._getPersistableData(id).blockIdEntries;
api.putBlockList.send(id, sasUri, blockIdEntries, mimeType, function(xhr) {
handler._registerXhr(id, null, xhr, api.putBlockList);
})
.then(function(xhr) {
log("Success combining chunks for id " + id);
promise.success({}, xhr);
}, function(xhr) {
log("Attempt to combine chunks failed for id " + id, "error");
handleFailure(xhr, promise);
});
},
promise.failure);
return promise;
}
function determineBlobUrl(id) {
var containerUrl = endpointStore.get(id),
promise = new qq.Promise(),
getBlobNameSuccess = function(blobName) {
handler._setThirdPartyFileId(id, blobName);
promise.success(containerUrl + "/" + blobName);
},
getBlobNameFailure = function(reason) {
promise.failure(reason);
};
onGetBlobName(id).then(getBlobNameSuccess, getBlobNameFailure);
return promise;
}
function getSignedUrl(id, optChunkIdx) {
// We may have multiple SAS requests in progress for the same file, so we must include the chunk idx
// as part of the ID when communicating with the SAS ajax requester to avoid collisions.
var getSasId = optChunkIdx == null ? id : id + "." + optChunkIdx,
promise = new qq.Promise(),
getSasSuccess = function(sasUri) {
log("GET SAS request succeeded.");
promise.success(sasUri);
},
getSasFailure = function(reason, getSasXhr) {
log("GET SAS request failed: " + reason, "error");
promise.failure({error: "Problem communicating with local server"}, getSasXhr);
},
determineBlobUrlSuccess = function(blobUrl) {
api.getSasForPutBlobOrBlock.request(getSasId, blobUrl).then(
getSasSuccess,
getSasFailure
);
},
determineBlobUrlFailure = function(reason) {
log(qq.format("Failed to determine blob name for ID {} - {}", id, reason), "error");
promise.failure({error: reason});
};
determineBlobUrl(id).then(determineBlobUrlSuccess, determineBlobUrlFailure);
return promise;
}
function handleFailure(xhr, promise) {
var azureError = qq.azure.util.parseAzureError(xhr.responseText, log),
errorMsg = "Problem sending file to Azure";
promise.failure({error: errorMsg,
azureError: azureError && azureError.message,
reset: xhr.status === 403
});
}
qq.extend(this, {
uploadChunk: function(params) {
var chunkIdx = params.chunkIdx;
var id = params.id;
var promise = new qq.Promise();
getSignedUrl(id, chunkIdx).then(
function(sasUri) {
var xhr = handler._createXhr(id, chunkIdx),
chunkData = handler._getChunkData(id, chunkIdx);
handler._registerProgressHandler(id, chunkIdx, chunkData.size);
handler._registerXhr(id, chunkIdx, xhr, api.putBlock);
// We may have multiple put block requests in progress for the same file, so we must include the chunk idx
// as part of the ID when communicating with the put block ajax requester to avoid collisions.
api.putBlock.upload(id + "." + chunkIdx, xhr, sasUri, chunkIdx, chunkData.blob).then(
function(blockIdEntry) {
if (!handler._getPersistableData(id).blockIdEntries) {
handler._getPersistableData(id).blockIdEntries = [];
}
handler._getPersistableData(id).blockIdEntries.push(blockIdEntry);
log("Put Block call succeeded for " + id);
promise.success({}, xhr);
},
function() {
log(qq.format("Put Block call failed for ID {} on part {}", id, chunkIdx), "error");
handleFailure(xhr, promise);
}
);
},
promise.failure
);
return promise;
},
uploadFile: function(id) {
var promise = new qq.Promise(),
fileOrBlob = handler.getFile(id);
getSignedUrl(id).then(function(sasUri) {
var xhr = handler._createXhr(id);
handler._registerProgressHandler(id);
api.putBlob.upload(id, xhr, sasUri, fileOrBlob).then(
function() {
log("Put Blob call succeeded for " + id);
promise.success({}, xhr);
},
function() {
log("Put Blob call failed for " + id, "error");
handleFailure(xhr, promise);
}
);
},
promise.failure);
return promise;
}
});
qq.extend(this,
new qq.XhrUploadHandler({
options: qq.extend({namespace: "azure"}, spec),
proxy: qq.extend({getEndpoint: spec.endpointStore.get}, proxy)
}
));
qq.override(this, function(super_) {
return {
expunge: function(id) {
var relatedToCancel = handler._wasCanceled(id),
chunkingData = handler._getPersistableData(id),
blockIdEntries = (chunkingData && chunkingData.blockIdEntries) || [];
if (relatedToCancel && blockIdEntries.length > 0) {
deleteBlob(id);
}
super_.expunge(id);
},
finalizeChunks: function(id) {
return combineChunks(id);
},
_shouldChunkThisFile: function(id) {
var maybePossible = super_._shouldChunkThisFile(id);
return maybePossible && getSize(id) >= minFileSizeForChunking;
}
};
});
};
================================================
FILE: client/js/azure/get-sas.js
================================================
/* globals qq */
/**
* Sends a GET request to the integrator's server, which should return a Shared Access Signature URI used to
* make a specific request on a Blob via the Azure REST API.
*/
qq.azure.GetSas = function(o) {
"use strict";
var requester,
options = {
cors: {
expected: false,
sendCredentials: false
},
customHeaders: {},
restRequestVerb: "PUT",
endpointStore: null,
log: function(str, level) {}
},
requestPromises = {};
qq.extend(options, o);
function sasResponseReceived(id, xhr, isError) {
var promise = requestPromises[id];
if (isError) {
promise.failure("Received response code " + xhr.status, xhr);
}
else {
if (xhr.responseText.length) {
promise.success(xhr.responseText);
}
else {
promise.failure("Empty response.", xhr);
}
}
delete requestPromises[id];
}
requester = qq.extend(this, new qq.AjaxRequester({
acceptHeader: "application/json",
validMethods: ["GET"],
method: "GET",
successfulResponseCodes: {
GET: [200]
},
contentType: null,
customHeaders: options.customHeaders,
endpointStore: options.endpointStore,
cors: options.cors,
log: options.log,
onComplete: sasResponseReceived
}));
qq.extend(this, {
request: function(id, blobUri) {
var requestPromise = new qq.Promise(),
restVerb = options.restRequestVerb;
options.log(qq.format("Submitting GET SAS request for a {} REST request related to file ID {}.", restVerb, id));
requestPromises[id] = requestPromise;
requester.initTransport(id)
.withParams({
bloburi: blobUri,
_method: restVerb
})
.withCacheBuster()
.send();
return requestPromise;
}
});
};
================================================
FILE: client/js/azure/jquery-plugin.js
================================================
/*globals jQuery*/
/**
* Simply an alias for the `fineUploader` plug-in wrapper, but hides the required `endpointType` option from the
* integrator. I thought it may be confusing to convey to the integrator that, when using Fine Uploader in Azure mode,
* you need to specify an `endpointType` with a value of "azure", and perhaps an `uploaderType` with a value of "basic" if
* you want to use basic mode when uploading directly to Azure as well. So, you can use this plug-in alias and not worry
* about the `endpointType` option at all.
*/
(function($) {
"use strict";
$.fn.fineUploaderAzure = function(optionsOrCommand) {
if (typeof optionsOrCommand === "object") {
// This option is used to tell the plug-in wrapper to instantiate the appropriate Azure-namespace modules.
optionsOrCommand.endpointType = "azure";
}
return $.fn.fineUploader.apply(this, arguments);
};
}(jQuery));
================================================
FILE: client/js/azure/rest/delete-blob.js
================================================
/* globals qq */
/**
* Implements the Delete Blob Azure REST API call. http://msdn.microsoft.com/en-us/library/windowsazure/dd179413.aspx.
*/
qq.azure.DeleteBlob = function(o) {
"use strict";
var requester,
method = "DELETE",
options = {
endpointStore: {},
onDelete: function(id) {},
onDeleteComplete: function(id, xhr, isError) {},
log: function(str, level) {}
};
qq.extend(options, o);
requester = qq.extend(this, new qq.AjaxRequester({
validMethods: [method],
method: method,
successfulResponseCodes: (function() {
var codes = {};
codes[method] = [202];
return codes;
}()),
contentType: null,
endpointStore: options.endpointStore,
allowXRequestedWithAndCacheControl: false,
cors: {
expected: true
},
log: options.log,
onSend: options.onDelete,
onComplete: options.onDeleteComplete
}));
qq.extend(this, {
method: method,
send: function(id) {
options.log("Submitting Delete Blob request for " + id);
return requester.initTransport(id)
.send();
}
});
};
================================================
FILE: client/js/azure/rest/put-blob.js
================================================
/* globals qq */
/**
* Implements the Put Blob Azure REST API call. http://msdn.microsoft.com/en-us/library/windowsazure/dd179451.aspx.
*/
qq.azure.PutBlob = function(o) {
"use strict";
var requester,
method = "PUT",
options = {
getBlobMetadata: function(id) {},
log: function(str, level) {}
},
endpoints = {},
promises = {},
endpointHandler = {
get: function(id) {
return endpoints[id];
}
};
qq.extend(options, o);
requester = qq.extend(this, new qq.AjaxRequester({
validMethods: [method],
method: method,
successfulResponseCodes: (function() {
var codes = {};
codes[method] = [201];
return codes;
}()),
contentType: null,
customHeaders: function(id) {
var params = options.getBlobMetadata(id),
headers = qq.azure.util.getParamsAsHeaders(params);
headers["x-ms-blob-type"] = "BlockBlob";
return headers;
},
endpointStore: endpointHandler,
allowXRequestedWithAndCacheControl: false,
cors: {
expected: true
},
log: options.log,
onComplete: function(id, xhr, isError) {
var promise = promises[id];
delete endpoints[id];
delete promises[id];
if (isError) {
promise.failure();
}
else {
promise.success();
}
}
}));
qq.extend(this, {
method: method,
upload: function(id, xhr, url, file) {
var promise = new qq.Promise();
options.log("Submitting Put Blob request for " + id);
promises[id] = promise;
endpoints[id] = url;
requester.initTransport(id)
.withPayload(file)
.withHeaders({"Content-Type": file.type})
.send(xhr);
return promise;
}
});
};
================================================
FILE: client/js/azure/rest/put-block-list.js
================================================
/* globals qq */
/**
* Implements the Put Block List Azure REST API call. http://msdn.microsoft.com/en-us/library/windowsazure/dd179467.aspx.
*/
qq.azure.PutBlockList = function(o) {
"use strict";
var requester,
method = "PUT",
promises = {},
options = {
getBlobMetadata: function(id) {},
log: function(str, level) {}
},
endpoints = {},
endpointHandler = {
get: function(id) {
return endpoints[id];
}
};
qq.extend(options, o);
requester = qq.extend(this, new qq.AjaxRequester({
validMethods: [method],
method: method,
successfulResponseCodes: (function() {
var codes = {};
codes[method] = [201];
return codes;
}()),
customHeaders: function(id) {
var params = options.getBlobMetadata(id);
return qq.azure.util.getParamsAsHeaders(params);
},
contentType: "text/plain",
endpointStore: endpointHandler,
allowXRequestedWithAndCacheControl: false,
cors: {
expected: true
},
log: options.log,
onSend: function() {},
onComplete: function(id, xhr, isError) {
var promise = promises[id];
delete endpoints[id];
delete promises[id];
if (isError) {
promise.failure(xhr);
}
else {
promise.success(xhr);
}
}
}));
function createRequestBody(blockIdEntries) {
var doc = document.implementation.createDocument(null, "BlockList", null);
// If we don't sort the block ID entries by part number, the file will be combined incorrectly by Azure
blockIdEntries.sort(function(a, b) {
return a.part - b.part;
});
// Construct an XML document for each pair of etag/part values that correspond to part uploads.
qq.each(blockIdEntries, function(idx, blockIdEntry) {
var latestEl = doc.createElement("Latest"),
latestTextEl = doc.createTextNode(blockIdEntry.id);
latestEl.appendChild(latestTextEl);
qq(doc).children()[0].appendChild(latestEl);
});
// Turn the resulting XML document into a string fit for transport.
return new XMLSerializer().serializeToString(doc);
}
qq.extend(this, {
method: method,
send: function(id, sasUri, blockIdEntries, fileMimeType, registerXhrCallback) {
var promise = new qq.Promise(),
blockIdsXml = createRequestBody(blockIdEntries),
xhr;
promises[id] = promise;
options.log(qq.format("Submitting Put Block List request for {}", id));
endpoints[id] = qq.format("{}&comp=blocklist", sasUri);
xhr = requester.initTransport(id)
.withPayload(blockIdsXml)
.withHeaders({"x-ms-blob-content-type": fileMimeType})
.send();
registerXhrCallback(xhr);
return promise;
}
});
};
================================================
FILE: client/js/azure/rest/put-block.js
================================================
/* globals qq */
/**
* Implements the Put Block Azure REST API call. http://msdn.microsoft.com/en-us/library/windowsazure/dd135726.aspx.
*/
qq.azure.PutBlock = function(o) {
"use strict";
var requester,
method = "PUT",
blockIdEntries = {},
promises = {},
options = {
log: function(str, level) {}
},
endpoints = {},
endpointHandler = {
get: function(id) {
return endpoints[id];
}
};
qq.extend(options, o);
requester = qq.extend(this, new qq.AjaxRequester({
validMethods: [method],
method: method,
successfulResponseCodes: (function() {
var codes = {};
codes[method] = [201];
return codes;
}()),
contentType: null,
endpointStore: endpointHandler,
allowXRequestedWithAndCacheControl: false,
cors: {
expected: true
},
log: options.log,
onComplete: function(id, xhr, isError) {
var promise = promises[id],
blockIdEntry = blockIdEntries[id];
delete endpoints[id];
delete promises[id];
delete blockIdEntries[id];
if (isError) {
promise.failure();
}
else {
promise.success(blockIdEntry);
}
}
}));
function createBlockId(partNum) {
var digits = 5,
zeros = new Array(digits + 1).join("0"),
paddedPartNum = (zeros + partNum).slice(-digits);
return btoa(paddedPartNum);
}
qq.extend(this, {
method: method,
upload: function(id, xhr, sasUri, partNum, blob) {
var promise = new qq.Promise(),
blockId = createBlockId(partNum);
promises[id] = promise;
options.log(qq.format("Submitting Put Block request for {} = part {}", id, partNum));
endpoints[id] = qq.format("{}&comp=block&blockid={}", sasUri, encodeURIComponent(blockId));
blockIdEntries[id] = {part: partNum, id: blockId};
requester.initTransport(id)
.withPayload(blob)
.send(xhr);
return promise;
}
});
};
================================================
FILE: client/js/azure/uploader.basic.js
================================================
/*globals qq */
/**
* This defines FineUploaderBasic mode w/ support for uploading to Azure, which provides all the basic
* functionality of Fine Uploader Basic as well as code to handle uploads directly to Azure.
* Some inherited options and API methods have a special meaning in the context of the Azure uploader.
*/
(function() {
"use strict";
qq.azure.FineUploaderBasic = function(o) {
if (!qq.supportedFeatures.ajaxUploading) {
throw new qq.Error("Uploading directly to Azure is not possible in this browser.");
}
var options = {
signature: {
endpoint: null,
customHeaders: {}
},
// 'uuid', 'filename', or a function which may be promissory
blobProperties: {
name: "uuid"
},
uploadSuccess: {
endpoint: null,
method: "POST",
// In addition to the default params sent by Fine Uploader
params: {},
customHeaders: {}
},
chunking: {
// If this is increased, Azure may respond with a 413
partSize: 4000000,
// Don't chunk files less than this size
minFileSize: 4000001
}
};
// Replace any default options with user defined ones
qq.extend(options, o, true);
// Call base module
qq.FineUploaderBasic.call(this, options);
this._uploadSuccessParamsStore = this._createStore(this._options.uploadSuccess.params);
this._uploadSuccessEndpointStore = this._createStore(this._options.uploadSuccess.endpoint);
// This will hold callbacks for failed uploadSuccess requests that will be invoked on retry.
// Indexed by file ID.
this._failedSuccessRequestCallbacks = {};
// Holds blob names for file representations constructed from a session request.
this._cannedBlobNames = {};
};
// Inherit basic public & private API methods.
qq.extend(qq.azure.FineUploaderBasic.prototype, qq.basePublicApi);
qq.extend(qq.azure.FineUploaderBasic.prototype, qq.basePrivateApi);
qq.extend(qq.azure.FineUploaderBasic.prototype, qq.nonTraditionalBasePublicApi);
qq.extend(qq.azure.FineUploaderBasic.prototype, qq.nonTraditionalBasePrivateApi);
// Define public & private API methods for this module.
qq.extend(qq.azure.FineUploaderBasic.prototype, {
getBlobName: function(id) {
/* jshint eqnull:true */
if (this._cannedBlobNames[id] == null) {
return this._handler.getThirdPartyFileId(id);
}
return this._cannedBlobNames[id];
},
_getEndpointSpecificParams: function(id) {
return {
blob: this.getBlobName(id),
uuid: this.getUuid(id),
name: this.getName(id),
container: this._endpointStore.get(id)
};
},
_createUploadHandler: function() {
return qq.FineUploaderBasic.prototype._createUploadHandler.call(this,
{
signature: this._options.signature,
onGetBlobName: qq.bind(this._determineBlobName, this),
deleteBlob: qq.bind(this._deleteBlob, this, true)
},
"azure");
},
_determineBlobName: function(id) {
var self = this,
blobNameOptionValue = this._options.blobProperties.name,
uuid = this.getUuid(id),
filename = this.getName(id),
fileExtension = qq.getExtension(filename),
blobNameToUse = uuid;
if (qq.isString(blobNameOptionValue)) {
switch (blobNameOptionValue) {
case "uuid":
if (fileExtension !== undefined) {
blobNameToUse += "." + fileExtension;
}
return new qq.Promise().success(blobNameToUse);
case "filename":
return new qq.Promise().success(filename);
default:
return new qq.Promise.failure("Invalid blobName option value - " + blobNameOptionValue);
}
}
else {
return blobNameOptionValue.call(this, id);
}
},
_addCannedFile: function(sessionData) {
var id;
/* jshint eqnull:true */
if (sessionData.blobName == null) {
throw new qq.Error("Did not find blob name property in server session response. This is required!");
}
else {
id = qq.FineUploaderBasic.prototype._addCannedFile.apply(this, arguments);
this._cannedBlobNames[id] = sessionData.blobName;
}
return id;
},
_deleteBlob: function(relatedToCancel, id) {
var self = this,
deleteBlobSasUri = {},
blobUriStore = {
get: function(id) {
return self._endpointStore.get(id) + "/" + self.getBlobName(id);
}
},
deleteFileEndpointStore = {
get: function(id) {
return deleteBlobSasUri[id];
}
},
getSasSuccess = function(id, sasUri) {
deleteBlobSasUri[id] = sasUri;
deleteBlob.send(id);
},
getSasFailure = function(id, reason, xhr) {
if (relatedToCancel) {
self.log("Will cancel upload, but cannot remove uncommitted parts from Azure due to issue retrieving SAS", "error");
qq.FineUploaderBasic.prototype._onCancel.call(self, id, self.getName(id));
}
else {
self._onDeleteComplete(id, xhr, true);
self._options.callbacks.onDeleteComplete(id, xhr, true);
}
},
deleteBlob = new qq.azure.DeleteBlob({
endpointStore: deleteFileEndpointStore,
log: qq.bind(self.log, self),
onDelete: function(id) {
self._onDelete(id);
self._options.callbacks.onDelete(id);
},
onDeleteComplete: function(id, xhrOrXdr, isError) {
delete deleteBlobSasUri[id];
if (isError) {
if (relatedToCancel) {
self.log("Will cancel upload, but failed to remove uncommitted parts from Azure.", "error");
}
else {
qq.azure.util.parseAzureError(xhrOrXdr.responseText, qq.bind(self.log, self));
}
}
if (relatedToCancel) {
qq.FineUploaderBasic.prototype._onCancel.call(self, id, self.getName(id));
self.log("Deleted uncommitted blob chunks for " + id);
}
else {
self._onDeleteComplete(id, xhrOrXdr, isError);
self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError);
}
}
}),
getSas = new qq.azure.GetSas({
cors: this._options.cors,
customHeaders: this._options.signature.customHeaders,
endpointStore: {
get: function() {
return self._options.signature.endpoint;
}
},
restRequestVerb: deleteBlob.method,
log: qq.bind(self.log, self)
});
getSas.request(id, blobUriStore.get(id)).then(
qq.bind(getSasSuccess, self, id),
qq.bind(getSasFailure, self, id));
},
_createDeleteHandler: function() {
var self = this;
return {
sendDelete: function(id, uuid) {
self._deleteBlob(false, id);
}
};
}
});
}());
================================================
FILE: client/js/azure/uploader.js
================================================
/*globals qq */
/**
* This defines FineUploader mode w/ support for uploading to Azure, which provides all the basic
* functionality of Fine Uploader as well as code to handle uploads directly to Azure.
* This module inherits all logic from UI & core mode and adds some UI-related logic
* specific to the upload-to-Azure workflow. Some inherited options and API methods have a special meaning
* in the context of the Azure uploader.
*/
(function() {
"use strict";
qq.azure.FineUploader = function(o) {
var options = {
failedUploadTextDisplay: {
mode: "custom"
}
};
// Replace any default options with user defined ones
qq.extend(options, o, true);
// Inherit instance data from FineUploader, which should in turn inherit from azure.FineUploaderBasic.
qq.FineUploader.call(this, options, "azure");
};
// Inherit the API methods from FineUploaderBasicS3
qq.extend(qq.azure.FineUploader.prototype, qq.azure.FineUploaderBasic.prototype);
// Inherit public and private API methods related to UI
qq.extend(qq.azure.FineUploader.prototype, qq.uiPublicApi);
qq.extend(qq.azure.FineUploader.prototype, qq.uiPrivateApi);
// Define public & private API methods for this module.
qq.extend(qq.azure.FineUploader.prototype, {
});
}());
================================================
FILE: client/js/azure/util.js
================================================
/*globals qq */
qq.azure = qq.azure || {};
qq.azure.util = qq.azure.util || (function() {
"use strict";
return {
AZURE_PARAM_PREFIX: "x-ms-meta-",
/** Test if a request header is actually a known Azure parameter. See: https://msdn.microsoft.com/en-us/library/azure/dd179451.aspx
*
* @param name Name of the Request Header parameter.
* @returns {Boolean} Test result.
*/
_paramNameMatchesAzureParameter: function(name) {
switch (name) {
case "Cache-Control":
case "Content-Disposition":
case "Content-Encoding":
case "Content-MD5":
case "x-ms-blob-content-encoding":
case "x-ms-blob-content-disposition":
case "x-ms-blob-content-md5":
case "x-ms-blob-cache-control":
return true;
default:
return false;
}
},
/** Create Prefixed request headers which are appropriate for Azure.
*
* If the request header is appropriate for Azure (e.g. Cache-Control) then it should be
* passed along without a metadata prefix. For all other request header parameter names,
* qq.azure.util.AZURE_PARAM_PREFIX should be prepended.
*
* @param name Name of the Request Header parameter to construct a (possibly) prefixed name.
* @returns {String} A valid Request Header parameter name.
*/
_getPrefixedParamName: function(name) {
if (qq.azure.util._paramNameMatchesAzureParameter(name)) {
return name;
}
else {
return qq.azure.util.AZURE_PARAM_PREFIX + name;
}
},
getParamsAsHeaders: function(params) {
var headers = {};
qq.each(params, function(name, val) {
var headerName = qq.azure.util._getPrefixedParamName(name),
value = null;
if (qq.isFunction(val)) {
value = String(val());
}
else if (qq.isObject(val)) {
qq.extend(headers, qq.azure.util.getParamsAsHeaders(val));
}
else {
value = String(val);
}
if (value !== null) {
if (qq.azure.util._paramNameMatchesAzureParameter(name)) {
headers[headerName] = value;
} else {
headers[headerName] = encodeURIComponent(value);
}
}
});
return headers;
},
parseAzureError: function(responseText, log) {
var domParser = new DOMParser(),
responseDoc = domParser.parseFromString(responseText, "application/xml"),
errorTag = responseDoc.getElementsByTagName("Error")[0],
errorDetails = {},
codeTag, messageTag;
log("Received error response: " + responseText, "error");
if (errorTag) {
messageTag = errorTag.getElementsByTagName("Message")[0];
if (messageTag) {
errorDetails.message = messageTag.textContent;
}
codeTag = errorTag.getElementsByTagName("Code")[0];
if (codeTag) {
errorDetails.code = codeTag.textContent;
}
log("Parsed Azure error: " + JSON.stringify(errorDetails), "error");
return errorDetails;
}
}
};
}());
================================================
FILE: client/js/blob-proxy.js
================================================
/* globals qq */
/**
* Placeholder for a Blob that will be generated on-demand.
*
* @param referenceBlob Parent of the generated blob
* @param onCreate Function to invoke when the blob must be created. Must be promissory.
* @constructor
*/
qq.BlobProxy = function(referenceBlob, onCreate) {
"use strict";
qq.extend(this, {
referenceBlob: referenceBlob,
create: function() {
return onCreate(referenceBlob);
}
});
};
================================================
FILE: client/js/button.js
================================================
/*globals qq*/
/**
* This module represents an upload or "Select File(s)" button. It's job is to embed an opaque `<input type="file">`
* element as a child of a provided "container" element. This "container" element (`options.element`) is used to provide
* a custom style for the `<input type="file">` element. The ability to change the style of the container element is also
* provided here by adding CSS classes to the container on hover/focus.
*
* TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be
* available on all supported browsers.
*
* @param o Options to override the default values
*/
qq.UploadButton = function(o) {
"use strict";
var self = this,
disposeSupport = new qq.DisposeSupport(),
options = {
// Corresponds to the `accept` attribute on the associated `<input type="file">`
acceptFiles: null,
// "Container" element
element: null,
focusClass: "qq-upload-button-focus",
// A true value allows folders to be selected, if supported by the UA
folders: false,
// **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers
hoverClass: "qq-upload-button-hover",
ios8BrowserCrashWorkaround: false,
// If true adds `multiple` attribute to `<input type="file">`
multiple: false,
// `name` attribute of `<input type="file">`
name: "qqfile",
// Called when the browser invokes the onchange handler on the `<input type="file">`
onChange: function(input) {},
title: null
},
input, buttonId;
// Overrides any of the default option values with any option values passed in during construction.
qq.extend(options, o);
buttonId = qq.getUniqueId();
// Embed an opaque `<input type="file">` element as a child of `options.element`.
function createInput() {
var input = document.createElement("input");
input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId);
input.setAttribute("title", options.title);
self.setMultiple(options.multiple, input);
if (options.folders && qq.supportedFeatures.folderSelection) {
// selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute
input.setAttribute("webkitdirectory", "");
}
if (options.acceptFiles) {
input.setAttribute("accept", options.acceptFiles);
}
input.setAttribute("type", "file");
input.setAttribute("name", options.name);
qq(input).css({
position: "absolute",
// in Opera only 'browse' button
// is clickable and it is located at
// the right side of the input
right: 0,
top: 0,
fontFamily: "Arial",
// It's especially important to make this an arbitrarily large value
// to ensure the rendered input button in IE takes up the entire
// space of the container element. Otherwise, the left side of the
// button will require a double-click to invoke the file chooser.
// In other browsers, this might cause other issues, so a large font-size
// is only used in IE. There is a bug in IE8 where the opacity style is ignored
// in some cases when the font-size is large. So, this workaround is not applied
// to IE8.
fontSize: qq.ie() && !qq.ie8() ? "3500px" : "118px",
margin: 0,
padding: 0,
cursor: "pointer",
opacity: 0
});
// Setting the file input's height to 100% in IE7 causes
// most of the visible button to be unclickable.
!qq.ie7() && qq(input).css({height: "100%"});
options.element.appendChild(input);
disposeSupport.attach(input, "change", function() {
options.onChange(input);
});
// **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers
disposeSupport.attach(input, "mouseover", function() {
qq(options.element).addClass(options.hoverClass);
});
disposeSupport.attach(input, "mouseout", function() {
qq(options.element).removeClass(options.hoverClass);
});
disposeSupport.attach(input, "focus", function() {
qq(options.element).addClass(options.focusClass);
});
disposeSupport.attach(input, "blur", function() {
qq(options.element).removeClass(options.focusClass);
});
return input;
}
// Make button suitable container for input
qq(options.element).css({
position: "relative",
overflow: "hidden",
// Make sure browse button is in the right side in Internet Explorer
direction: "ltr"
});
// Exposed API
qq.extend(this, {
getInput: function() {
return input;
},
getButtonId: function() {
return buttonId;
},
setMultiple: function(isMultiple, optInput) {
var input = optInput || this.getInput();
// Temporary workaround for bug in in iOS8 UIWebView that causes the browser to crash
// before the file chooser appears if the file input doesn't contain a multiple attribute.
// See #1283.
if (options.ios8BrowserCrashWorkaround && qq.ios8() && (qq.iosChrome() || qq.iosSafariWebView())) {
input.setAttribute("multiple", "");
}
else {
if (isMultiple) {
input.setAttribute("multiple", "");
}
else {
input.removeAttribute("multiple");
}
}
},
setAcceptFiles: function(acceptFiles) {
if (acceptFiles !== options.acceptFiles) {
input.setAttribute("accept", acceptFiles);
}
},
reset: function() {
if (input.parentNode) {
qq(input).remove();
}
qq(options.element).removeClass(options.focusClass);
input = null;
input = createInput();
}
});
input = createInput();
};
qq.UploadButton.BUTTON_ID_ATTR_NAME = "qq-button-id";
================================================
FILE: client/js/deletefile.ajax.requester.js
================================================
/*globals qq, XMLHttpRequest*/
qq.DeleteFileAjaxRequester = function(o) {
"use strict";
var requester,
options = {
method: "DELETE",
uuidParamName: "qquuid",
endpointStore: {},
maxConnections: 3,
customHeaders: function(id) {return {};},
paramsStore: {},
cors: {
expected: false,
sendCredentials: false
},
log: function(str, level) {},
onDelete: function(id) {},
onDeleteComplete: function(id, xhrOrXdr, isError) {}
};
qq.extend(options, o);
function getMandatedParams() {
if (options.method.toUpperCase() === "POST") {
return {
_method: "DELETE"
};
}
return {};
}
requester = qq.extend(this, new qq.AjaxRequester({
acceptHeader: "application/json",
validMethods: ["POST", "DELETE"],
method: options.method,
endpointStore: options.endpointStore,
paramsStore: options.paramsStore,
mandatedParams: getMandatedParams(),
maxConnections: options.maxConnections,
customHeaders: function(id) {
return options.customHeaders.get(id);
},
log: options.log,
onSend: options.onDelete,
onComplete: options.onDeleteComplete,
cors: options.cors
}));
qq.extend(this, {
sendDelete: function(id, uuid, additionalMandatedParams) {
var additionalOptions = additionalMandatedParams || {};
options.log("Submitting delete file request for " + id);
if (options.method === "DELETE") {
requester.initTransport(id)
.withPath(uuid)
.withParams(additionalOptions)
.send();
}
else {
additionalOptions[options.uuidParamName] = uuid;
requester.initTransport(id)
.withParams(additionalOptions)
.send();
}
}
});
};
================================================
FILE: client/js/dnd.js
================================================
/*globals qq, document, CustomEvent*/
qq.DragAndDrop = function(o) {
"use strict";
var options,
HIDE_ZONES_EVENT_NAME = "qq-hidezones",
HIDE_BEFORE_ENTER_ATTR = "qq-hide-dropzone",
uploadDropZones = [],
droppedFiles = [],
disposeSupport = new qq.DisposeSupport();
options = {
dropZoneElements: [],
allowMultipleItems: true,
classes: {
dropActive: null
},
callbacks: new qq.DragAndDrop.callbacks()
};
qq.extend(options, o, true);
function uploadDroppedFiles(files, uploadDropZone) {
// We need to convert the `FileList` to an actual `Array` to avoid iteration issues
var filesAsArray = Array.prototype.slice.call(files);
options.callbacks.dropLog("Grabbed " + files.length + " dropped files.");
uploadDropZone.dropDisabled(false);
options.callbacks.processingDroppedFilesComplete(filesAsArray, uploadDropZone.getElement());
}
function traverseFileTree(entry) {
var parseEntryPromise = new qq.Promise();
if (entry.isFile) {
entry.file(function(file) {
file.qqPath = extractDirectoryPath(entry);
droppedFiles.push(file);
parseEntryPromise.success();
},
function(fileError) {
options.callbacks.dropLog("Problem parsing '" + entry.fullPath + "'. FileError code " + fileError.code + ".", "error");
parseEntryPromise.failure();
});
}
else if (entry.isDirectory) {
getFilesInDirectory(entry).then(
function allEntriesRead(entries) {
var entriesLeft = entries.length;
qq.each(entries, function(idx, entry) {
traverseFileTree(entry).done(function() {
entriesLeft -= 1;
if (entriesLeft === 0) {
parseEntryPromise.success();
}
});
});
if (!entries.length) {
parseEntryPromise.success();
}
},
function readFailure(fileError) {
options.callbacks.dropLog("Problem parsing '" + entry.fullPath + "'. FileError code " + fileError.code + ".", "error");
parseEntryPromise.failure();
}
);
}
return parseEntryPromise;
}
function extractDirectoryPath(entry) {
var name = entry.name,
fullPath = entry.fullPath,
indexOfNameInFullPath = fullPath.lastIndexOf(name);
// remove file name from full path string
fullPath = fullPath.substr(0, indexOfNameInFullPath);
// remove leading slash in full path string
if (fullPath.charAt(0) === "/") {
fullPath = fullPath.substr(1);
}
return fullPath;
}
// Promissory. Guaranteed to read all files in the root of the passed directory.
function getFilesInDirectory(entry, reader, accumEntries, existingPromise) {
var promise = existingPromise || new qq.Promise(),
dirReader = reader || entry.createReader();
dirReader.readEntries(
function readSuccess(entries) {
var newEntries = accumEntries ? accumEntries.concat(entries) : entries;
if (entries.length) {
setTimeout(function() { // prevent stack overflow, however unlikely
getFilesInDirectory(entry, dirReader, newEntries, promise);
}, 0);
}
else {
promise.success(newEntries);
}
},
promise.failure
);
return promise;
}
function handleDataTransfer(dataTransfer, uploadDropZone) {
var pendingFolderPromises = [],
handleDataTransferPromise = new qq.Promise();
options.callbacks.processingDroppedFiles();
uploadDropZone.dropDisabled(true);
if (dataTransfer.files.length > 1 && !options.allowMultipleItems) {
options.callbacks.processingDroppedFilesComplete([]);
options.callbacks.dropError("tooManyFilesError", "");
uploadDropZone.dropDisabled(false);
handleDataTransferPromise.failure();
}
else {
droppedFiles = [];
if (qq.isFolderDropSupported(dataTransfer)) {
qq.each(dataTransfer.items, function(idx, item) {
var entry = item.webkitGetAsEntry();
if (entry) {
//due to a bug in Chrome's File System API impl - #149735
if (entry.isFile) {
droppedFiles.push(item.getAsFile());
}
else {
pendingFolderPromises.push(traverseFileTree(entry).done(function() {
pendingFolderPromises.pop();
if (pendingFolderPromises.length === 0) {
handleDataTransferPromise.success();
}
}));
}
}
});
}
else {
droppedFiles = dataTransfer.files;
}
if (pendingFolderPromises.length === 0) {
handleDataTransferPromise.success();
}
}
return handleDataTransferPromise;
}
function setupDropzone(dropArea) {
var dropZone = new qq.UploadDropZone({
HIDE_ZONES_EVENT_NAME: HIDE_ZONES_EVENT_NAME,
element: dropArea,
onEnter: function(e) {
qq(dropArea).addClass(options.classes.dropActive);
options.callbacks.dragEnter();
e.stopPropagation();
},
onLeaveNotDescendants: function(e) {
qq(dropArea).removeClass(options.classes.dropActive);
options.callbacks.dragLeave();
},
onDrop: function(e) {
handleDataTransfer(e.dataTransfer, dropZone).then(
function() {
uploadDroppedFiles(droppedFiles, dropZone);
},
function() {
options.callbacks.dropLog("Drop event DataTransfer parsing failed. No files will be uploaded.", "error");
}
);
}
});
disposeSupport.addDisposer(function() {
dropZone.dispose();
});
qq(dropArea).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropArea).hide();
uploadDropZones.push(dropZone);
return dropZone;
}
function isFileDrag(dragEvent) {
var fileDrag;
qq.each(dragEvent.dataTransfer.types, function(key, val) {
if (val === "Files") {
fileDrag = true;
return false;
}
});
return fileDrag;
}
// Attempt to determine when the file has left the document. It is not always possible to detect this
// in all cases, but it is generally possible in all browsers, with a few exceptions.
//
// Exceptions:
// * IE10+ & Safari: We can't detect a file leaving the document if the Explorer window housing the file
// overlays the browser window.
// * IE10+: If the file is dragged out of the window too quickly, IE does not set the expected values of the
// event's X & Y properties.
function leavingDocumentOut(e) {
if (qq.safari()) {
return e.x < 0 || e.y < 0;
}
return e.x === 0 && e.y === 0;
}
function setupDragDrop() {
var dropZones = options.dropZoneElements,
maybeHideDropZones = function() {
setTimeout(function() {
qq.each(dropZones, function(idx, dropZone) {
qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR) && qq(dropZone).hide();
qq(dropZone).removeClass(options.classes.dropActive);
});
}, 10);
};
qq.each(dropZones, function(idx, dropZone) {
var uploadDropZone = setupDropzone(dropZone);
// IE <= 9 does not support the File API used for drag+drop uploads
if (dropZones.length && qq.supportedFeatures.fileDrop) {
disposeSupport.attach(document, "dragenter", function(e) {
if (!uploadDropZone.dropDisabled() && isFileDrag(e)) {
qq.each(dropZones, function(idx, dropZone) {
// We can't apply styles to non-HTMLElements, since they lack the `style` property.
// Also, if the drop zone isn't initially hidden, let's not mess with `style.display`.
if (dropZone instanceof HTMLElement &&
qq(dropZone).hasAttribute(HIDE_BEFORE_ENTER_ATTR)) {
qq(dropZone).css({display: "block"});
}
});
}
});
}
});
disposeSupport.attach(document, "dragleave", function(e) {
if (leavingDocumentOut(e)) {
maybeHideDropZones();
}
});
// Just in case we were not able to detect when a dragged file has left the document,
// hide all relevant drop zones the next time the mouse enters the document.
// Note that mouse events such as this one are not fired during drag operations.
disposeSupport.attach(qq(document).children()[0], "mouseenter", function(e) {
maybeHideDropZones();
});
disposeSupport.attach(document, "drop", function(e) {
if (isFileDrag(e)) {
e.preventDefault();
maybeHideDropZones();
}
});
disposeSupport.attach(document, HIDE_ZONES_EVENT_NAME, maybeHideDropZones);
}
setupDragDrop();
qq.extend(this, {
setupExtraDropzone: function(element) {
options.dropZoneElements.push(element);
setupDropzone(element);
},
removeDropzone: function(element) {
var i,
dzs = options.dropZoneElements;
for (i in dzs) {
if (dzs[i] === element) {
return dzs.splice(i, 1);
}
}
},
dispose: function() {
disposeSupport.dispose();
qq.each(uploadDropZones, function(idx, dropZone) {
dropZone.dispose();
});
}
});
this._testing = {};
this._testing.extractDirectoryPath = extractDirectoryPath;
};
qq.DragAndDrop.callbacks = function() {
"use strict";
return {
dragEnter: function () {},
dragLeave: function () {},
processingDroppedFiles: function() {},
processingDroppedFilesComplete: function(files, targetEl) {},
dropError: function(code, errorSpecifics) {
qq.log("Drag & drop error code '" + code + " with these specifics: '" + errorSpecifics + "'", "error");
},
dropLog: function(message, level) {
qq.log(message, level);
}
};
};
qq.UploadDropZone = function(o) {
"use strict";
var disposeSupport = new qq.DisposeSupport(),
options, element, preventDrop, dropOutsideDisabled;
options = {
element: null,
onEnter: function(e) {},
onLeave: function(e) {},
// is not fired when leaving element by hovering descendants
onLeaveNotDescendants: function(e) {},
onDrop: function(e) {}
};
qq.extend(options, o);
element = options.element;
function dragoverShouldBeCanceled() {
return qq.safari() || (qq.firefox() && qq.windows());
}
function disableDropOutside(e) {
// run only once for all instances
if (!dropOutsideDisabled) {
// for these cases we need to catch onDrop to reset dropArea
if (dragoverShouldBeCanceled) {
disposeSupport.attach(document, "dragover", function(e) {
e.preventDefault();
});
} else {
disposeSupport.attach(document, "dragover", function(e) {
if (e.dataTransfer) {
e.dataTransfer.dropEffect = "none";
e.preventDefault();
}
});
}
dropOutsideDisabled = true;
}
}
function isValidFileDrag(e) {
// e.dataTransfer currently causing IE errors
// IE9 does NOT support file API, so drag-and-drop is not possible
if (!qq.supportedFeatures.fileDrop) {
return false;
}
var effectTest, dt = e.dataTransfer,
// do not check dt.types.contains in webkit, because it crashes safari 4
isSafari = qq.safari();
// dt.effectAllowed is none in Safari 5
// dt.effectAllowed crashes IE 11 & 10 when files have been dragged from
// the filesystem
effectTest = qq.ie() && qq.supportedFeatures.fileDrop ? true : dt.effectAllowed !== "none";
return dt && effectTest &&
(
(dt.files && dt.files.length) || // Valid for drop events with files
(!isSafari && dt.types.contains && dt.types.contains("Files")) || // Valid in Chrome/Firefox
(dt.types.includes && dt.types.includes("Files")) // Valid in IE
);
}
function isOrSetDropDisabled(isDisabled) {
if (isDisabled !== undefined) {
preventDrop = isDisabled;
}
return preventDrop;
}
function triggerHidezonesEvent() {
var hideZonesEvent;
function triggerUsingOldApi() {
hideZonesEvent = document.createEvent("Event");
hideZonesEvent.initEvent(options.HIDE_ZONES_EVENT_NAME, true, true);
}
if (window.CustomEvent) {
try {
hideZonesEvent = new CustomEvent(options.HIDE_ZONES_EVENT_NAME);
}
catch (err) {
triggerUsingOldApi();
}
}
else {
triggerUsingOldApi();
}
document.dispatchEvent(hideZonesEvent);
}
function attachEvents() {
disposeSupport.attach(element, "dragover", function(e) {
if (!isValidFileDrag(e)) {
return;
}
// dt.effectAllowed crashes IE 11 & 10 when files have been dragged from
// the filesystem
var effect = qq.ie() && qq.supportedFeatures.fileDrop ? null : e.dataTransfer.effectAllowed;
if (effect === "move" || effect === "linkMove") {
e.dataTransfer.dropEffect = "move"; // for FF (only move allowed)
} else {
e.dataTransfer.dropEffect = "copy"; // for Chrome
}
e.stopPropagation();
e.preventDefault();
});
disposeSupport.attach(element, "dragenter", function(e) {
if (!isOrSetDropDisabled()) {
if (!isValidFileDrag(e)) {
return;
}
options.onEnter(e);
}
});
disposeSupport.attach(element, "dragleave", function(e) {
if (!isValidFileDrag(e)) {
return;
}
options.onLeave(e);
var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);
// do not fire when moving a mouse over a descendant
if (qq(this).contains(relatedTarget)) {
return;
}
options.onLeaveNotDescendants(e);
});
disposeSupport.attach(element, "drop", function(e) {
if (!isOrSetDropDisabled()) {
if (!isValidFileDrag(e)) {
return;
}
e.preventDefault();
e.stopPropagation();
options.onDrop(e);
triggerHidezonesEvent();
}
});
}
disableDropOutside();
attachEvents();
qq.extend(this, {
dropDisabled: function(isDisabled) {
return isOrSetDropDisabled(isDisabled);
},
dispose: function() {
disposeSupport.dispose();
},
getElement: function() {
return element;
}
});
this._testing = {};
this._testing.isValidFileDrag = isValidFileDrag;
};
================================================
FILE: client/js/error/error.js
================================================
/* globals qq */
/**
* Fine Uploader top-level Error container. Inherits from `Error`.
*/
(function() {
"use strict";
qq.Error = function(message) {
this.message = "[Fine Uploader " + qq.version + "] " + message;
};
qq.Error.prototype = new Error();
}());
================================================
FILE: client/js/export.js
================================================
/* globals define, module, global, qq */
(function() {
"use strict";
if (typeof define === "function" && define.amd) {
define(function() {
return qq;
});
}
else if (typeof module !== "undefined" && module.exports) {
module.exports = qq;
}
else {
global.qq = qq;
}
}());
================================================
FILE: client/js/features.js
================================================
/* globals qq */
qq.supportedFeatures = (function() {
"use strict";
var supportsUploading,
supportsUploadingBlobs,
supportsFileDrop,
supportsAjaxFileUploading,
supportsFolderDrop,
supportsChunking,
supportsResume,
supportsUploadViaPaste,
supportsUploadCors,
supportsDeleteFileXdr,
supportsDeleteFileCorsXhr,
supportsDeleteFileCors,
supportsFolderSelection,
supportsImagePreviews,
supportsUploadProgress;
function testSupportsFileInputElement() {
var supported = true,
tempInput;
try {
tempInput = document.createElement("input");
tempInput.type = "file";
qq(tempInput).hide();
if (tempInput.disabled) {
supported = false;
}
}
catch (ex) {
supported = false;
}
return supported;
}
//only way to test for complete Clipboard API support at this time
function isChrome14OrHigher() {
return (qq.chrome() || qq.opera()) &&
navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/) !== undefined;
}
//Ensure we can send cross-origin `XMLHttpRequest`s
function isCrossOriginXhrSupported() {
if (window.XMLHttpRequest) {
var xhr = qq.createXhrInstance();
//Commonly accepted test for XHR CORS support.
return xhr.withCredentials !== undefined;
}
return false;
}
//Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8
function isXdrSupported() {
return window.XDomainRequest !== undefined;
}
// CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s,
// or if `XDomainRequest` is an available alternative.
function isCrossOriginAjaxSupported() {
if (isCrossOriginXhrSupported()) {
return true;
}
return isXdrSupported();
}
function isFolderSelectionSupported() {
// We know that folder selection is only supported in Chrome via this proprietary attribute for now
return document.createElement("input").webkitdirectory !== undefined;
}
function isLocalStorageSupported() {
try {
return !!window.localStorage &&
// unpatched versions of IE10/11 have buggy impls of localStorage where setItem is a string
qq.isFunction(window.localStorage.setItem);
}
catch (error) {
// probably caught a security exception, so no localStorage for you
return false;
}
}
function isDragAndDropSupported() {
var span = document.createElement("span");
return ("draggable" in span || ("ondragstart" in span && "ondrop" in span)) &&
!qq.android() && !qq.ios();
}
supportsUploading = testSupportsFileInputElement();
supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported();
supportsUploadingBlobs = supportsAjaxFileUploading && !qq.androidStock();
supportsFileDrop = supportsAjaxFileUploading && isDragAndDropSupported();
// adapted from https://stackoverflow.com/a/23278460/486979
supportsFolderDrop = supportsFileDrop && (function() {
var input = document.createElement("input");
input.type = "file";
return !!("webkitdirectory" in (input || document.querySelectorAll("input[type=file]")[0]));
}());
supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported();
supportsResume = supportsAjaxFileUploading && supportsChunking && isLocalStorageSupported();
supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher();
supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading);
supportsDeleteFileCorsXhr = isCrossOriginXhrSupported();
supportsDeleteFileXdr = isXdrSupported();
supportsDeleteFileCors = isCrossOriginAjaxSupported();
supportsFolderSelection = isFolderSelectionSupported();
supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined;
supportsUploadProgress = (function() {
if (supportsAjaxFileUploading) {
return !qq.androidStock() && !qq.iosChrome();
}
return false;
}());
return {
ajaxUploading: supportsAjaxFileUploading,
blobUploading: supportsUploadingBlobs,
canDetermineSize: supportsAjaxFileUploading,
chunking: supportsChunking,
deleteFileCors: supportsDeleteFileCors,
deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported
deleteFileCorsXhr: supportsDeleteFileCorsXhr,
dialogElement: !!window.HTMLDialogElement,
fileDrop: supportsFileDrop,
folderDrop: supportsFolderDrop,
folderSelection: supportsFolderSelection,
imagePreviews: supportsImagePreviews,
imageValidation: supportsImagePreviews,
itemSizeValidation: supportsAjaxFileUploading,
pause: supportsChunking,
progressBar: supportsUploadProgress,
resume: supportsResume,
scaling: supportsImagePreviews && supportsUploadingBlobs,
tiffPreviews: qq.safari(), // Not the best solution, but simple and probably accurate enough (for now)
unlimitedScaledImageSize: !qq.ios(), // false simply indicates that there is some known limit
uploading: supportsUploading,
uploadCors: supportsUploadCors,
uploadCustomHeaders: supportsAjaxFileUploading,
uploadNonMultipart: supportsAjaxFileUploading,
uploadViaPaste: supportsUploadViaPaste
};
}());
================================================
FILE: client/js/form-support.js
================================================
/* globals qq */
/**
* Module that handles support for existing forms.
*
* @param options Options passed from the integrator-supplied options related to form support.
* @param startUpload Callback to invoke when files "stored" should be uploaded.
* @param log Proxy for the logger
* @constructor
*/
qq.FormSupport = function(options, startUpload, log) {
"use strict";
var self = this,
interceptSubmit = options.interceptSubmit,
formEl = options.element,
autoUpload = options.autoUpload;
// Available on the public API associated with this module.
qq.extend(this, {
// To be used by the caller to determine if the endpoint will be determined by some processing
// that occurs in this module, such as if the form has an action attribute.
// Ignore if `attachToForm === false`.
newEndpoint: null,
// To be used by the caller to determine if auto uploading should be allowed.
// Ignore if `attachToForm === false`.
newAutoUpload: autoUpload,
// true if a form was detected and is being tracked by this module
attachedToForm: false,
// Returns an object with names and values for all valid form elements associated with the attached form.
getFormInputsAsObject: function() {
/* jshint eqnull:true */
if (formEl == null) {
return null;
}
return self._form2Obj(formEl);
}
});
// If the form contains an action attribute, this should be the new upload endpoint.
function determineNewEndpoint(formEl) {
if (formEl.getAttribute("action")) {
self.newEndpoint = formEl.getAttribute("action");
}
}
// Return true only if the form is valid, or if we cannot make this determination.
// If the form is invalid, ensure invalid field(s) are highlighted in the UI.
function validateForm(formEl, nativeSubmit) {
if (formEl.checkValidity && !formEl.checkValidity()) {
log("Form did not pass validation checks - will not upload.", "error");
nativeSubmit();
}
else {
return true;
}
}
// Intercept form submit attempts, unless the integrator has told us not to do this.
function maybeUploadOnSubmit(formEl) {
var nativeSubmit = formEl.submit;
// Intercept and squelch submit events.
qq(formEl).attach("submit", function(event) {
event = event || window.event;
if (event.preventDefault) {
event.preventDefault();
}
else {
event.returnValue = false;
}
validateForm(formEl, nativeSubmit) && startUpload();
});
// The form's `submit()` function may be called instead (i.e. via jQuery.submit()).
// Intercept that too.
formEl.submit = function() {
validateForm(formEl, nativeSubmit) && startUpload();
};
}
// If the element value passed from the uploader is a string, assume it is an element ID - select it.
// The rest of the code in this module depends on this being an HTMLElement.
function determineFormEl(formEl) {
if (formEl) {
if (qq.isString(formEl)) {
formEl = document.getElementById(formEl);
}
if (formEl) {
log("Attaching to form element.");
determineNewEndpoint(formEl);
interceptSubmit && maybeUploadOnSubmit(formEl);
}
}
return formEl;
}
formEl = determineFormEl(formEl);
this.attachedToForm = !!formEl;
};
qq.extend(qq.FormSupport.prototype, {
// Converts all relevant form fields to key/value pairs. This is meant to mimic the data a browser will
// construct from a given form when the form is submitted.
_form2Obj: function(form) {
"use strict";
var obj = {},
notIrrelevantType = function(type) {
var irrelevantTypes = [
"button",
"image",
"reset",
"submit"
];
return qq.indexOf(irrelevantTypes, type.toLowerCase()) < 0;
},
radioOrCheckbox = function(type) {
return qq.indexOf(["checkbox", "radio"], type.toLowerCase()) >= 0;
},
ignoreValue = function(el) {
if (radioOrCheckbox(el.type) && !el.checked) {
return true;
}
return el.disabled && el.type.toLowerCase() !== "hidden";
},
selectValue = function(select) {
var value = null;
qq.each(qq(select).children(), function(idx, child) {
if (child.tagName.toLowerCase() === "option" && child.selected) {
value = child.value;
return false;
}
});
return value;
};
qq.each(form.elements, function(idx, el) {
if ((qq.isInput(el, true) || el.tagName.toLowerCase() === "textarea") &&
notIrrelevantType(el.type) &&
!ignoreValue(el)) {
obj[el.name] = el.value;
}
else if (el.tagName.toLowerCase() === "select" && !ignoreValue(el)) {
var value = selectValue(el);
if (value !== null) {
obj[el.name] = value;
}
}
});
return obj;
}
});
================================================
FILE: client/js/identify.js
================================================
/*globals qq */
qq.Identify = function(fileOrBlob, log) {
"use strict";
function isIdentifiable(magicBytes, questionableBytes) {
var identifiable = false,
magicBytesEntries = [].concat(magicBytes);
qq.each(magicBytesEntries, function(idx, magicBytesArrayEntry) {
if (questionableBytes.indexOf(magicBytesArrayEntry) === 0) {
identifiable = true;
return false;
}
});
return identifiable;
}
qq.extend(this, {
/**
* Determines if a Blob can be displayed natively in the current browser. This is done by reading magic
* bytes in the beginning of the file, so this is an asynchronous operation. Before we attempt to read the
* file, we will examine the blob's type attribute to save CPU cycles.
*
* @returns {qq.Promise} Promise that is fulfilled when identification is complete.
* If successful, the MIME string is passed to the success handler.
*/
isPreviewable: function() {
var self = this,
identifier = new qq.Promise(),
previewable = false,
name = fileOrBlob.name === undefined ? "blob" : fileOrBlob.name;
log(qq.format("Attempting to determine if {} can be rendered in this browser", name));
log("First pass: check type attribute of blob object.");
if (this.isPreviewableSync()) {
log("Second pass: check for magic bytes in file header.");
qq.readBlobToHex(fileOrBlob, 0, 4).then(function(hex) {
qq.each(self.PREVIEWABLE_MIME_TYPES, function(mime, bytes) {
if (isIdentifiable(bytes, hex)) {
// Safari is the only supported browser that can deal with TIFFs natively,
// so, if this is a TIFF and the UA isn't Safari, declare this file "non-previewable".
if (mime !== "image/tiff" || qq.supportedFeatures.tiffPreviews) {
previewable = true;
identifier.success(mime);
}
return false;
}
});
log(qq.format("'{}' is {} able to be rendered in this browser", name, previewable ? "" : "NOT"));
if (!previewable) {
identifier.failure();
}
},
function() {
log("Error reading file w/ name '" + name + "'. Not able to be rendered in this browser.");
identifier.failure();
});
}
else {
identifier.failure();
}
return identifier;
},
/**
* Determines if a Blob can be displayed natively in the current browser. This is done by checking the
* blob's type attribute. This is a synchronous operation, useful for situations where an asynchronous operation
* would be challenging to support. Note that the blob's type property is not as accurate as reading the
* file's magic bytes.
*
* @returns {Boolean} true if the blob can be rendered in the current browser
*/
isPreviewableSync: function() {
var fileMime = fileOrBlob.type,
// Assumption: This will only ever be executed in browsers that support `Object.keys`.
isRecognizedImage = qq.indexOf(Object.keys(this.PREVIEWABLE_MIME_TYPES), fileMime) >= 0,
previewable = false,
name = fileOrBlob.name === undefined ? "blob" : fileOrBlob.name;
if (isRecognizedImage) {
if (fileMime === "image/tiff") {
previewable = qq.supportedFeatures.tiffPreviews;
}
else {
previewable = true;
}
}
!previewable && log(name + " is not previewable in this browser per the blob's type attr");
return previewable;
}
});
};
qq.Identify.prototype.PREVIEWABLE_MIME_TYPES = {
"image/jpeg": "ffd8ff",
"image/gif": "474946",
"image/png": "89504e",
"image/bmp": "424d",
"image/tiff": ["49492a00", "4d4d002a"]
};
================================================
FILE: client/js/iframe.xss.response.js
================================================
(function() {
"use strict";
var match = /(\{.*\})/.exec(document.body.innerHTML);
if (match) {
parent.postMessage(match[1], "*");
}
}());
================================================
FILE: client/js/image-support/exif.js
================================================
/*globals qq */
/**
* EXIF image data parser. Currently only parses the Orientation tag value,
* but this may be expanded to other tags in the future.
*
* @param fileOrBlob Attempt to parse EXIF data in this `Blob`
* @constructor
*/
qq.Exif = function(fileOrBlob, log) {
"use strict";
// Orientation is the only tag parsed here at this time.
var TAG_IDS = [274],
TAG_INFO = {
274: {
name: "Orientation",
bytes: 2
}
};
// Convert a little endian (hex string) to big endian (decimal).
function parseLittleEndian(hex) {
var result = 0,
pow = 0;
while (hex.length > 0) {
result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);
hex = hex.substring(2, hex.length);
pow += 8;
}
return result;
}
// Find the byte offset, of Application Segment 1 (EXIF).
// External callers need not supply any arguments.
function seekToApp1(offset, promise) {
var theOffset = offset,
thePromise = promise;
if (theOffset === undefined) {
theOffset = 2;
thePromise = new qq.Promise();
}
qq.readBlobToHex(fileOrBlob, theOffset, 4).then(function(hex) {
var match = /^ffe([0-9])/.exec(hex),
segmentLength;
if (match) {
if (match[1] !== "1") {
segmentLength = parseInt(hex.slice(4, 8), 16);
seekToApp1(theOffset + segmentLength + 2, thePromise);
}
else {
thePromise.success(theOffset);
}
}
else {
thePromise.failure("No EXIF header to be found!");
}
});
return thePromise;
}
// Find the byte offset of Application Segment 1 (EXIF) for valid JPEGs only.
function getApp1Offset() {
var promise = new qq.Promise();
qq.readBlobToHex(fileOrBlob, 0, 6).then(function(hex) {
if (hex.indexOf("ffd8") !== 0) {
promise.failure("Not a valid JPEG!");
}
else {
seekToApp1().then(function(offset) {
promise.success(offset);
},
function(error) {
promise.failure(error);
});
}
});
return promise;
}
// Determine the byte ordering of the EXIF header.
function isLittleEndian(app1Start) {
var promise = new qq.Promise();
qq.readBlobToHex(fileOrBlob, app1Start + 10, 2).then(function(hex) {
promise.success(hex === "4949");
});
return promise;
}
// Determine the number of directory entries in the EXIF header.
function getDirEntryCount(app1Start, littleEndian) {
var promise = new qq.Promise();
qq.readBlobToHex(fileOrBlob, app1Start + 18, 2).then(function(hex) {
if (littleEndian) {
return promise.success(parseLittleEndian(hex));
}
else {
promise.success(parseInt(hex, 16));
}
});
return promise;
}
// Get the IFD portion of the EXIF header as a hex string.
function getIfd(app1Start, dirEntries) {
var offset = app1Start + 20,
bytes = dirEntries * 12;
return qq.readBlobToHex(fileOrBlob, offset, bytes);
}
// Obtain an array of all directory entries (as hex strings) in the EXIF header.
function getDirEntries(ifdHex) {
var entries = [],
offset = 0;
while (offset + 24 <= ifdHex.length) {
entries.push(ifdHex.slice(offset, offset + 24));
offset += 24;
}
return entries;
}
// Obtain values for all relevant tags and return them.
function getTagValues(littleEndian, dirEntries) {
var TAG_VAL_OFFSET = 16,
tagsToFind = qq.extend([], TAG_IDS),
vals = {};
qq.each(dirEntries, function(idx, entry) {
var idHex = entry.slice(0, 4),
id = littleEndian ? parseLittleEndian(idHex) : parseInt(idHex, 16),
tagsToFindIdx = tagsToFind.indexOf(id),
tagValHex, tagName, tagValLength;
if (tagsToFindIdx >= 0) {
tagName = TAG_INFO[id].name;
tagValLength = TAG_INFO[id].bytes;
tagValHex = entry.slice(TAG_VAL_OFFSET, TAG_VAL_OFFSET + (tagValLength * 2));
vals[tagName] = littleEndian ? parseLittleEndian(tagValHex) : parseInt(tagValHex, 16);
tagsToFind.splice(tagsToFindIdx, 1);
}
if (tagsToFind.length === 0) {
return false;
}
});
return vals;
}
qq.extend(this, {
/**
* Attempt to parse the EXIF header for the `Blob` associated with this instance.
*
* @returns {qq.Promise} To be fulfilled when the parsing is complete.
* If successful, the parsed EXIF header as an object will be included.
*/
parse: function() {
var parser = new qq.Promise(),
onParseFailure = function(message) {
log(qq.format("EXIF header parse failed: '{}' ", message));
parser.failure(message);
};
getApp1Offset().then(function(app1Offset) {
log(qq.format("Moving forward with EXIF header parsing for '{}'", fileOrBlob.name === undefined ? "blob" : fileOrBlob.name));
isLittleEndian(app1Offset).then(function(littleEndian) {
log(qq.format("EXIF Byte order is {} endian", littleEndian ? "little" : "big"));
getDirEntryCount(app1Offset, littleEndian).then(function(dirEntryCount) {
log(qq.format("Found {} APP1 directory entries", dirEntryCount));
getIfd(app1Offset, dirEntryCount).then(function(ifdHex) {
var dirEntries = getDirEntries(ifdHex),
tagValues = getTagValues(littleEndian, dirEntries);
log("Successfully parsed some EXIF tags");
parser.success(tagValues);
}, onParseFailure);
}, onParseFailure);
}, onParseFailure);
}, onParseFailure);
return parser;
}
});
/*<testing>*/
this._testing = {};
this._testing.parseLittleEndian = parseLittleEndian;
/*</testing>*/
};
================================================
FILE: client/js/image-support/image.js
================================================
/*globals qq */
/**
* Draws a thumbnail of a Blob/File/URL onto an <img> or <canvas>.
*
* @constructor
*/
qq.ImageGenerator = function(log) {
"use strict";
function isImg(el) {
return el.tagName.toLowerCase() === "img";
}
function isCanvas(el) {
return el.tagName.toLowerCase() === "canvas";
}
function isImgCorsSupported() {
return new Image().crossOrigin !== undefined;
}
function isCanvasSupported() {
var canvas = document.createElement("canvas");
return canvas.getContext && canvas.getContext("2d");
}
// This is only meant to determine the MIME type of a renderable image file.
// It is used to ensure images drawn from a URL that have transparent backgrounds
// are rendered correctly, among other things.
function determineMimeOfFileName(nameWithPath) {
/*jshint -W015 */
var pathSegments = nameWithPath.split("/"),
name = pathSegments[pathSegments.length - 1].split("?")[0],
extension = qq.getExtension(name);
extension = extension && extension.toLowerCase();
switch (extension) {
case "jpeg":
case "jpg":
return "image/jpeg";
case "png":
return "image/png";
case "bmp":
return "image/bmp";
case "gif":
return "image/gif";
case "tiff":
case "tif":
return "image/tiff";
}
}
// This will likely not work correctly in IE8 and older.
// It's only used as part of a formula to determine
// if a canvas can be used to scale a server-hosted thumbnail.
// If canvas isn't supported by the UA (IE8 and older)
// this method should not even be called.
function isCrossOrigin(url) {
var targetAnchor = document.createElement("a"),
targetProtocol, targetHostname, targetPort;
targetAnchor.href = url;
targetProtocol = targetAnchor.protocol;
targetPort = targetAnchor.port;
targetHostname = targetAnchor.hostname;
if (targetProtocol.toLowerCase() !== window.location.protocol.toLowerCase()) {
return true;
}
if (targetHostname.toLowerCase() !== window.location.hostname.toLowerCase()) {
return true;
}
// IE doesn't take ports into consideration when determining if two endpoints are same origin.
if (targetPort !== window.location.port && !qq.ie()) {
return true;
}
return false;
}
function registerImgLoadListeners(img, promise) {
img.onload = function() {
img.onload = null;
img.onerror = null;
promise.success(img);
};
img.onerror = function() {
img.onload = null;
img.onerror = null;
log("Problem drawing thumbnail!", "error");
promise.failure(img, "Problem drawing thumbnail!");
};
}
function registerCanvasDrawImageListener(canvas, promise) {
// The image is drawn on the canvas by a third-party library,
// and we want to know when this is completed. Since the library
// may invoke drawImage many times in a loop, we need to be called
// back when the image is fully rendered. So, we are expecting the
// code that draws this image to follow a convention that involves a
// function attached to the canvas instance be invoked when it is done.
canvas.qqImageRendered = function() {
promise.success(canvas);
};
}
// Fulfills a `qq.Promise` when an image has been drawn onto the target,
// whether that is a <canvas> or an <img>. The attempt is considered a
// failure if the target is not an <img> or a <canvas>, or if the drawing
// attempt was not successful.
function registerThumbnailRenderedListener(imgOrCanvas, promise) {
var registered = isImg(imgOrCanvas) || isCanvas(imgOrCanvas);
if (isImg(imgOrCanvas)) {
registerImgLoadListeners(imgOrCanvas, promise);
}
else if (isCanvas(imgOrCanvas)) {
registerCanvasDrawImageListener(imgOrCanvas, promise);
}
else {
promise.failure(imgOrCanvas);
log(qq.format("Element container of type {} is not supported!", imgOrCanvas.tagName), "error");
}
return registered;
}
// Draw a preview iff the current UA can natively display it.
// Also rotate the image if necessary.
function draw(fileOrBlob, container, options) {
var drawPreview = new qq.Promise(),
identifier = new qq.Identify(fileOrBlob, log),
maxSize = options.maxSize,
// jshint eqnull:true
orient = options.orient == null ? true : options.orient,
megapixErrorHandler = function() {
container.onerror = null;
container.onload = null;
log("Could not render preview, file may be too large!", "error");
drawPreview.failure(container, "Browser cannot render image!");
};
identifier.isPreviewable().then(
function(mime) {
// If options explicitly specify that Orientation is not desired,
// replace the orient task with a dummy promise that "succeeds" immediately.
var dummyExif = {
parse: function() {
return new qq.Promise().success();
}
},
exif = orient ? new qq.Exif(fileOrBlob, log) : dummyExif,
mpImg = new qq.MegaPixImage(fileOrBlob, megapixErrorHandler);
if (registerThumbnailRenderedListener(container, drawPreview)) {
exif.parse().then(
function(exif) {
var orientation = exif && exif.Orientation;
mpImg.render(container, {
maxWidth: maxSize,
maxHeight: maxSize,
orientation: orientation,
mime: mime,
resize: options.customResizeFunction
});
},
function(failureMsg) {
log(qq.format("EXIF data could not be parsed ({}). Assuming orientation = 1.", failureMsg));
mpImg.render(container, {
maxWidth: maxSize,
maxHeight: maxSize,
mime: mime,
resize: options.customResizeFunction
});
}
);
}
},
function() {
log("Not previewable");
drawPreview.failure(container, "Not previewable");
}
);
return drawPreview;
}
function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {
var tempImg = new Image(),
tempImgRender = new qq.Promise();
registerThumbnailRenderedListener(tempImg, tempImgRender);
if (isCrossOrigin(url)) {
tempImg.crossOrigin = "anonymous";
}
tempImg.src = url;
tempImgRender.then(
function rendered() {
registerThumbnailRenderedListener(canvasOrImg, draw);
var mpImg = new qq.MegaPixImage(tempImg);
mpImg.render(canvasOrImg, {
maxWidth: maxSize,
maxHeight: maxSize,
mime: determineMimeOfFileName(url),
resize: customResizeFunction
});
},
draw.failure
);
}
function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {
registerThumbnailRenderedListener(img, draw);
// NOTE: The fact that maxWidth/height is set on the thumbnail for scaled images
// that must drop back to CSS is known and exploited by the templating module.
// In this module, we pre-render "waiting" thumbs for all files immediately after they
// are submitted, and we must be sure to pass any style associated with the "waiting" preview.
qq(img).css({
maxWidth: maxSize + "px",
maxHeight: maxSize + "px"
});
img.src = url;
}
// Draw a (server-hosted) thumbnail given a URL.
// This will optionally scale the thumbnail as well.
// It attempts to use <canvas> to scale, but will fall back
// to max-width and max-height style properties if the UA
// doesn't support canvas or if the images is cross-domain and
// the UA doesn't support the crossorigin attribute on img tags,
// which is required to scale a cross-origin image using <canvas> &
// then export it back to an <img>.
function drawFromUrl(url, container, options) {
var draw = new qq.Promise(),
scale = options.scale,
maxSize = scale ? options.maxSize : null;
// container is an img, scaling needed
if (scale && isImg(container)) {
// Iff canvas is available in this UA, try to use it for scaling.
// Otherwise, fall back to CSS scaling
if (isCanvasSupported()) {
// Attempt to use <canvas> for image scaling,
// but we must fall back to scaling via CSS/styles
// if this is a cross-origin image and the UA doesn't support <img> CORS.
if (isCrossOrigin(url) && !isImgCorsSupported()) {
drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);
}
else {
drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);
}
}
else {
drawOnImgFromUrlWithCssScaling(url, container, draw, maxSize);
}
}
// container is a canvas, scaling optional
else if (isCanvas(container)) {
drawOnCanvasOrImgFromUrl(url, container, draw, maxSize);
}
// container is an img & no scaling: just set the src attr to the passed url
else if (registerThumbnailRenderedListener(container, draw)) {
container.src = url;
}
return draw;
}
qq.extend(this, {
/**
* Generate a thumbnail. Depending on the arguments, this may either result in
* a client-side rendering of an image (if a `Blob` is supplied) or a server-generated
* image that may optionally be scaled client-side using <canvas> or CSS/styles (as a fallback).
*
* @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image
* @param container <img> or <canvas> to contain the preview
* @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.
* @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed
*/
generate: function(fileBlobOrUrl, container, options) {
if (qq.isString(fileBlobOrUrl)) {
log("Attempting to update thumbnail based on server response.");
return drawFromUrl(fileBlobOrUrl, container, options || {});
}
else {
log("Attempting to draw client-side image preview.");
return draw(fileBlobOrUrl, container, options || {});
}
}
});
/*<testing>*/
this._testing = {};
this._testing.isImg = isImg;
this._testing.isCanvas = isCanvas;
this._testing.isCrossOrigin = isCrossOrigin;
this._testing.determineMimeOfFileName = determineMimeOfFileName;
/*</testing>*/
};
================================================
FILE: client/js/image-support/megapix-image.js
================================================
/*global qq, define */
/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */
/**
* Mega pixel image rendering library for iOS6+
*
* Fixes iOS6+'s image file rendering issue for large size image (over mega-pixel),
* which causes unexpected subsampling when drawing it in canvas.
* By using this library, you can safely render the image with proper stretching.
*
* Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com>
* Released under the MIT license
*
* Heavily modified by Widen for Fine Uploader
*/
(function() {
/**
* Detect subsampling in loaded image.
* In iOS, larger images than 2M pixels may be subsampled in rendering.
*/
function detectSubsampling(img) {
var iw = img.naturalWidth,
ih = img.naturalHeight,
canvas = document.createElement("canvas"),
ctx;
if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image
canvas.width = canvas.height = 1;
ctx = canvas.getContext("2d");
ctx.drawImage(img, -iw + 1, 0);
// subsampled image becomes half smaller in rendering size.
// check alpha channel value to confirm image is covering edge pixel or not.
// if alpha value is 0 image is not covering, hence subsampled.
return ctx.getImageData(0, 0, 1, 1).data[3] === 0;
} else {
return false;
}
}
/**
* Detecting vertical squash in loaded image.
* Fixes a bug which squash image vertically while drawing into canvas for some images.
*/
function detectVerticalSquash(img, iw, ih) {
var canvas = document.createElement("canvas"),
sy = 0,
ey = ih,
py = ih,
ctx, data, alpha, ratio;
canvas.width = 1;
canvas.height = ih;
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
data = ctx.getImageData(0, 0, 1, ih).data;
// search image edge pixel position in case it is squashed vertically.
while (py > sy) {
alpha = data[(py - 1) * 4 + 3];
if (alpha === 0) {
ey = py;
} else {
sy = py;
}
py = (ey + sy) >> 1;
}
ratio = (py / ih);
return (ratio === 0) ? 1 : ratio;
}
/**
* Rendering image element (with resizing) and get its data URL
*/
function renderImageToDataURL(img, blob, options, doSquash) {
var canvas = document.createElement("canvas"),
mime = options.mime || "image/jpeg",
promise = new qq.Promise();
renderImageToCanvas(img, blob, canvas, options, doSquash)
.then(function() {
promise.success(
canvas.toDataURL(mime, options.quality || 0.8)
);
});
return promise;
}
function maybeCalculateDownsampledDimensions(spec) {
var maxPixels = 5241000; //iOS specific value
if (!qq.ios()) {
throw new qq.Error("Downsampled dimensions can only be reliably calculated for iOS!");
}
if (spec.origHeight * spec.origWidth > maxPixels) {
return {
newHeight: Math.round(Math.sqrt(maxPixels * (spec.origHeight / spec.origWidth))),
newWidth: Math.round(Math.sqrt(maxPixels * (spec.origWidth / spec.origHeight)))
};
}
}
/**
* Rendering image element (with resizing) into the canvas element
*/
function renderImageToCanvas(img, blob, canvas, options, doSquash) {
var iw = img.naturalWidth,
ih = img.naturalHeight,
width = options.width,
height = options.height,
ctx = canvas.getContext("2d"),
promise = new qq.Promise(),
modifiedDimensions;
ctx.save();
if (options.resize) {
return renderImageToCanvasWithCustomResizer({
blob: blob,
canvas: canvas,
image: img,
imageHeight: ih,
imageWidth: iw,
orientation: options.orientation,
resize: options.resize,
targetHeight: height,
targetWidth: width
});
}
if (!qq.supportedFeatures.unlimitedScaledImageSize) {
modifiedDimensions = maybeCalculateDownsampledDimensions({
origWidth: width,
origHeight: height
});
if (modifiedDimensions) {
qq.log(qq.format("Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h",
width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),
"warn");
width = modifiedDimensions.newWidth;
height = modifiedDimensions.newHeight;
}
}
transformCoordinate(canvas, width, height, options.orientation);
// Fine Uploader specific: Save some CPU cycles if not using iOS
// Assumption: This logic is only needed to overcome iOS image sampling issues
if (qq.ios()) {
(function() {
if (detectSubsampling(img)) {
iw /= 2;
ih /= 2;
}
var d = 1024, // size of tiling canvas
tmpCanvas = document.createElement("canvas"),
vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1,
dw = Math.ceil(d * width / iw),
dh = Math.ceil(d * height / ih / vertSquashRatio),
sy = 0,
dy = 0,
tmpCtx, sx, dx;
tmpCanvas.width = tmpCanvas.height = d;
tmpCtx = tmpCanvas.getContext("2d");
while (sy < ih) {
sx = 0;
dx = 0;
while (sx < iw) {
tmpCtx.clearRect(0, 0, d, d);
tmpCtx.drawImage(img, -sx, -sy);
ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);
sx += d;
dx += dw;
}
sy += d;
dy += dh;
}
ctx.restore();
tmpCanvas = tmpCtx = null;
}());
}
else {
ctx.drawImage(img, 0, 0, width, height);
}
canvas.qqImageRendered && canvas.qqImageRendered();
promise.success();
return promise;
}
function renderImageToCanvasWithCustomResizer(resizeInfo) {
var blob = resizeInfo.blob,
image = resizeInfo.image,
imageHeight = resizeInfo.imageHeight,
imageWidth = resizeInfo.imageWidth,
orientation = resizeInfo.orientation,
promise = new qq.Promise(),
resize = resizeInfo.resize,
sourceCanvas = document.createElement("canvas"),
sourceCanvasContext = sourceCanvas.getContext("2d"),
targetCanvas = resizeInfo.canvas,
targetHeight = resizeInfo.targetHeight,
targetWidth = resizeInfo.targetWidth;
transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);
targetCanvas.height = targetHeight;
targetCanvas.width = targetWidth;
sourceCanvasContext.drawImage(image, 0, 0);
resize({
blob: blob,
height: targetHeight,
image: image,
sourceCanvas: sourceCanvas,
targetCanvas: targetCanvas,
width: targetWidth
})
.then(
function success() {
targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();
promise.success();
},
promise.failure
);
return promise;
}
/**
* Transform canvas coordination according to specified frame size and orientation
* Orientation value is from EXIF tag
*/
function transformCoordinate(canvas, width, height, orientation) {
switch (orientation) {
case 5:
case 6:
case 7:
case 8:
canvas.width = height;
canvas.height = width;
break;
default:
canvas.width = width;
canvas.height = height;
}
var ctx = canvas.getContext("2d");
switch (orientation) {
case 2:
// horizontal flip
ctx.translate(width, 0);
ctx.scale(-1, 1);
break;
case 3:
// 180 rotate left
ctx.translate(width, height);
ctx.rotate(Math.PI);
break;
case 4:
// vertical flip
ctx.translate(0, height);
ctx.scale(1, -1);
break;
case 5:
// vertical flip + 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.scale(1, -1);
break;
case 6:
// 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.translate(0, -height);
break;
case 7:
// horizontal flip + 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.translate(width, -height);
ctx.scale(-1, 1);
break;
case 8:
// 90 rotate left
ctx.rotate(-0.5 * Math.PI);
ctx.translate(-width, 0);
break;
default:
break;
}
}
/**
* MegaPixImage class
*/
function MegaPixImage(srcImage, errorCallback) {
var self = this;
if (window.Blob && srcImage instanceof Blob) {
(function() {
var img = new Image(),
URL = window.URL && window.URL.createObjectURL ? window.URL :
window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;
if (!URL) { throw Error("No createObjectURL function found to create blob url"); }
img.src = URL.createObjectURL(srcImage);
self.blob = srcImage;
srcImage = img;
}());
}
if (!srcImage.naturalWidth && !srcImage.naturalHeight) {
srcImage.onload = function() {
var listeners = self.imageLoadListeners;
if (listeners) {
self.imageLoadListeners = null;
// IE11 doesn't reliably report actual image dimensions immediately after onload for small files,
// so let's push this to the end of the UI thread queue.
setTimeout(function() {
for (var i = 0, len = listeners.length; i < len; i++) {
listeners[i]();
}
}, 0);
}
};
srcImage.onerror = errorCallback;
this.imageLoadListeners = [];
}
this.srcImage = srcImage;
}
/**
* Rendering megapix image into specified target element
*/
MegaPixImage.prototype.render = function(target, options) {
options = options || {};
var self = thi
gitextract_c09cz4qu/
├── .editorconfig
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ └── PULL_REQUEST_TEMPLATE
├── .gitignore
├── .jshintignore
├── .jshintrc
├── .travis.yml
├── ATTRIBUTION.txt
├── LICENSE
├── Makefile
├── README.md
├── client/
│ ├── README.md
│ ├── commonJs/
│ │ ├── all.js
│ │ ├── azure.js
│ │ ├── core/
│ │ │ ├── all.js
│ │ │ ├── azure.js
│ │ │ ├── index.js
│ │ │ ├── s3.js
│ │ │ └── traditional.js
│ │ ├── dnd.js
│ │ ├── jquery/
│ │ │ ├── azure.js
│ │ │ ├── s3.js
│ │ │ └── traditional.js
│ │ ├── s3.js
│ │ └── traditional.js
│ ├── fine-uploader-gallery.css
│ ├── fine-uploader-new.css
│ ├── fine-uploader.css
│ ├── html/
│ │ └── templates/
│ │ ├── default.html
│ │ ├── gallery.html
│ │ └── simple-thumbnails.html
│ ├── js/
│ │ ├── ajax.requester.js
│ │ ├── azure/
│ │ │ ├── azure.xhr.upload.handler.js
│ │ │ ├── get-sas.js
│ │ │ ├── jquery-plugin.js
│ │ │ ├── rest/
│ │ │ │ ├── delete-blob.js
│ │ │ │ ├── put-blob.js
│ │ │ │ ├── put-block-list.js
│ │ │ │ └── put-block.js
│ │ │ ├── uploader.basic.js
│ │ │ ├── uploader.js
│ │ │ └── util.js
│ │ ├── blob-proxy.js
│ │ ├── button.js
│ │ ├── deletefile.ajax.requester.js
│ │ ├── dnd.js
│ │ ├── error/
│ │ │ └── error.js
│ │ ├── export.js
│ │ ├── features.js
│ │ ├── form-support.js
│ │ ├── identify.js
│ │ ├── iframe.xss.response.js
│ │ ├── image-support/
│ │ │ ├── exif.js
│ │ │ ├── image.js
│ │ │ ├── megapix-image.js
│ │ │ ├── scaler.js
│ │ │ └── validation.image.js
│ │ ├── jquery-dnd.js
│ │ ├── jquery-plugin.js
│ │ ├── non-traditional-common/
│ │ │ └── uploader.basic.api.js
│ │ ├── paste.js
│ │ ├── promise.js
│ │ ├── s3/
│ │ │ ├── jquery-plugin.js
│ │ │ ├── multipart.abort.ajax.requester.js
│ │ │ ├── multipart.complete.ajax.requester.js
│ │ │ ├── multipart.initiate.ajax.requester.js
│ │ │ ├── request-signer.js
│ │ │ ├── s3.form.upload.handler.js
│ │ │ ├── s3.xhr.upload.handler.js
│ │ │ ├── uploader.basic.js
│ │ │ ├── uploader.js
│ │ │ └── util.js
│ │ ├── session.ajax.requester.js
│ │ ├── session.js
│ │ ├── templating.js
│ │ ├── third-party/
│ │ │ ├── ExifRestorer.js
│ │ │ └── crypto-js/
│ │ │ ├── core.js
│ │ │ ├── enc-base64.js
│ │ │ ├── hmac.js
│ │ │ ├── lib-typedarrays.js
│ │ │ ├── sha1.js
│ │ │ └── sha256.js
│ │ ├── total-progress.js
│ │ ├── traditional/
│ │ │ ├── all-chunks-done.ajax.requester.js
│ │ │ ├── traditional.form.upload.handler.js
│ │ │ └── traditional.xhr.upload.handler.js
│ │ ├── ui.handler.click.filebuttons.js
│ │ ├── ui.handler.click.filename.js
│ │ ├── ui.handler.edit.filename.js
│ │ ├── ui.handler.events.js
│ │ ├── ui.handler.focus.filenameinput.js
│ │ ├── ui.handler.focusin.filenameinput.js
│ │ ├── upload-data.js
│ │ ├── upload-handler/
│ │ │ ├── form.upload.handler.js
│ │ │ ├── upload.handler.controller.js
│ │ │ ├── upload.handler.js
│ │ │ └── xhr.upload.handler.js
│ │ ├── uploader.api.js
│ │ ├── uploader.basic.api.js
│ │ ├── uploader.basic.js
│ │ ├── uploader.js
│ │ ├── uploadsuccess.ajax.requester.js
│ │ ├── util.js
│ │ ├── version.js
│ │ └── window.receive.message.js
│ └── typescript/
│ ├── fine-uploader.d.ts
│ └── fine-uploader.test.ts
├── config/
│ └── karma.conf.js
├── docs/
│ ├── _static/
│ │ ├── css/
│ │ │ ├── main.css
│ │ │ └── pygments.css
│ │ └── js/
│ │ ├── main.js
│ │ ├── navbar.js
│ │ └── sidebar.js
│ ├── _templates/
│ │ ├── api.html
│ │ ├── base.html
│ │ ├── feature.html
│ │ ├── footer.html
│ │ ├── layout.html
│ │ ├── macros/
│ │ │ ├── alerts.html
│ │ │ ├── code.html
│ │ │ └── github.html
│ │ └── navbar.html
│ ├── api/
│ │ ├── events-s3.jmd
│ │ ├── events.jmd
│ │ ├── methods-azure.jmd
│ │ ├── methods-s3.jmd
│ │ ├── methods.jmd
│ │ ├── options-azure.jmd
│ │ ├── options-s3.jmd
│ │ ├── options-ui.jmd
│ │ ├── options.jmd
│ │ └── qq.jmd
│ ├── browser-support.jmd
│ ├── endpoint_handlers/
│ │ ├── amazon-s3.jmd
│ │ ├── azure.jmd
│ │ └── traditional.jmd
│ ├── faq.jmd
│ ├── features/
│ │ ├── CORS.jmd
│ │ ├── async-tasks-and-promises.jmd
│ │ ├── azure.jmd
│ │ ├── cancellable-uploads.jmd
│ │ ├── chunking.jmd
│ │ ├── concurrent-chunking.jmd
│ │ ├── delete.jmd
│ │ ├── drag-and-drop.jmd
│ │ ├── extra-buttons.jmd
│ │ ├── filename-edit.jmd
│ │ ├── forms.jmd
│ │ ├── handling-errors.jmd
│ │ ├── modules.jmd
│ │ ├── no-server-uploads.jmd
│ │ ├── paste-to-upload.jmd
│ │ ├── pause.jmd
│ │ ├── progress-bars.jmd
│ │ ├── request-parameters.jmd
│ │ ├── resume.jmd
│ │ ├── retry.jmd
│ │ ├── s3.jmd
│ │ ├── scaling.jmd
│ │ ├── session.jmd
│ │ ├── statistics-and-status-updates.jmd
│ │ ├── styling.jmd
│ │ ├── thumbnails.jmd
│ │ ├── upload-files.jmd
│ │ ├── upload-from-mobile-camera.jmd
│ │ └── validation.jmd
│ ├── index.jmd
│ ├── integrating/
│ │ └── jquery.jmd
│ ├── modes/
│ │ ├── core.jmd
│ │ └── ui.jmd
│ ├── quickstart/
│ │ ├── 01-getting-started.jmd
│ │ ├── 02-setting_options-azure.jmd
│ │ ├── 02-setting_options-s3.jmd
│ │ ├── 02-setting_options.jmd
│ │ ├── 03-setting_up_server-azure.jmd
│ │ ├── 03-setting_up_server-s3.jmd
│ │ └── 03-setting_up_server.jmd
│ ├── upgrading-to-4.jmd
│ └── upgrading-to-5.jmd
├── package.json
└── test/
├── dev/
│ ├── devenv.js
│ ├── handlers/
│ │ ├── composer.json
│ │ └── php.ini
│ ├── index.html
│ └── styles.css
├── static/
│ ├── local/
│ │ ├── blob-maker.js
│ │ ├── client.js
│ │ ├── formdata.js
│ │ ├── helpme.js
│ │ └── karma-runner.js
│ └── third-party/
│ ├── assert/
│ │ └── assert.js
│ ├── jquery/
│ │ └── jquery.js
│ ├── jquery.simulate/
│ │ └── jquery.simulate.js
│ ├── json2/
│ │ ├── README
│ │ ├── cycle.js
│ │ ├── json.js
│ │ ├── json2.js
│ │ ├── json_parse.js
│ │ └── json_parse_state.js
│ ├── mocha/
│ │ ├── css/
│ │ │ └── mocha.css
│ │ └── js/
│ │ └── mocha.js
│ ├── purl/
│ │ └── purl.js
│ ├── q/
│ │ └── q-1.0.1.js
│ └── sinon/
│ ├── event.js
│ ├── fake_xml_http_request.js
│ └── sinon.js
└── unit/
├── azure/
│ ├── chunked-uploads.js
│ ├── delete-files.js
│ └── simple-file-uploads.js
├── basic.js
├── button.js
├── chunked-uploads.js
├── concurrent-chunks.js
├── delete-file.js
├── dnd.js
├── exif.js
├── file-upload-params-and-headers.js
├── form-support.js
├── identify.js
├── iframe.xss.response.js
├── image.js
├── on-all-complete.js
├── promise.js
├── resources/
│ ├── empty.txt
│ ├── sample.tif
│ └── simpletext.txt
├── s3/
│ ├── cdn/
│ │ ├── generic-chunked.js
│ │ └── generic-non-chunked.js
│ ├── chunked-uploads.js
│ ├── serverless-uploads.js
│ ├── simple-file-uploads.js
│ └── util.js
├── scaling.js
├── session.js
├── set-status.js
├── simple-file-uploads.js
├── submit-validate-cancel.js
├── templating.js
├── total-progress.js
├── ui.handler.click.filebuttons.js
├── ui.handler.click.filename.js
├── upload-data.js
├── uploader.basic.api.js
├── util.js
├── validation.image.js
└── workarounds.js
SYMBOL INDEX (567 symbols across 74 files)
FILE: client/js/ajax.requester.js
function isSimpleMethod (line 47) | function isSimpleMethod() {
function containsNonSimpleHeaders (line 54) | function containsNonSimpleHeaders(headers) {
function isXdr (line 67) | function isXdr(xhr) {
function getCorsAjaxTransport (line 73) | function getCorsAjaxTransport() {
function getXhrOrXdr (line 93) | function getXhrOrXdr(id, suppliedXhr) {
function dequeue (line 116) | function dequeue(id) {
function onComplete (line 130) | function onComplete(id, xdrError) {
function getParams (line 148) | function getParams(id) {
function sendRequest (line 174) | function sendRequest(id, optXhr) {
function createUrl (line 228) | function createUrl(id, params, additionalQueryParams) {
function getXhrReadyStateChangeHandler (line 250) | function getXhrReadyStateChangeHandler(id) {
function registerForUploadProgress (line 258) | function registerForUploadProgress(id) {
function getXdrLoadHandler (line 272) | function getXdrLoadHandler(id) {
function getXdrErrorHandler (line 280) | function getXdrErrorHandler(id) {
function setHeaders (line 286) | function setHeaders(id) {
function isResponseSuccessful (line 322) | function isResponseSuccessful(responseCode) {
function prepareToSend (line 326) | function prepareToSend(id, optXhr, addToPath, additionalParams, addition...
FILE: client/js/azure/azure.xhr.upload.handler.js
function combineChunks (line 61) | function combineChunks(id) {
function determineBlobUrl (line 85) | function determineBlobUrl(id) {
function getSignedUrl (line 101) | function getSignedUrl(id, optChunkIdx) {
function handleFailure (line 131) | function handleFailure(xhr, promise) {
FILE: client/js/azure/get-sas.js
function sasResponseReceived (line 24) | function sasResponseReceived(id, xhr, isError) {
FILE: client/js/azure/rest/put-block-list.js
function createRequestBody (line 61) | function createRequestBody(blockIdEntries) {
FILE: client/js/azure/rest/put-block.js
function createBlockId (line 56) | function createBlockId(partNum) {
FILE: client/js/button.js
function createInput (line 57) | function createInput() {
FILE: client/js/deletefile.ajax.requester.js
function getMandatedParams (line 24) | function getMandatedParams() {
FILE: client/js/dnd.js
function uploadDroppedFiles (line 23) | function uploadDroppedFiles(files, uploadDropZone) {
function traverseFileTree (line 32) | function traverseFileTree(entry) {
function extractDirectoryPath (line 76) | function extractDirectoryPath(entry) {
function getFilesInDirectory (line 93) | function getFilesInDirectory(entry, reader, accumEntries, existingPromis...
function handleDataTransfer (line 117) | function handleDataTransfer(dataTransfer, uploadDropZone) {
function setupDropzone (line 166) | function setupDropzone(dropArea) {
function isFileDrag (line 202) | function isFileDrag(dragEvent) {
function leavingDocumentOut (line 223) | function leavingDocumentOut(e) {
function setupDragDrop (line 231) | function setupDragDrop() {
function dragoverShouldBeCanceled (line 353) | function dragoverShouldBeCanceled() {
function disableDropOutside (line 357) | function disableDropOutside(e) {
function isValidFileDrag (line 379) | function isValidFileDrag(e) {
function isOrSetDropDisabled (line 403) | function isOrSetDropDisabled(isDisabled) {
function triggerHidezonesEvent (line 410) | function triggerHidezonesEvent() {
function attachEvents (line 433) | function attachEvents() {
FILE: client/js/features.js
function testSupportsFileInputElement (line 21) | function testSupportsFileInputElement() {
function isChrome14OrHigher (line 42) | function isChrome14OrHigher() {
function isCrossOriginXhrSupported (line 48) | function isCrossOriginXhrSupported() {
function isXdrSupported (line 60) | function isXdrSupported() {
function isCrossOriginAjaxSupported (line 66) | function isCrossOriginAjaxSupported() {
function isFolderSelectionSupported (line 74) | function isFolderSelectionSupported() {
function isLocalStorageSupported (line 79) | function isLocalStorageSupported() {
function isDragAndDropSupported (line 91) | function isDragAndDropSupported() {
FILE: client/js/form-support.js
function determineNewEndpoint (line 43) | function determineNewEndpoint(formEl) {
function validateForm (line 51) | function validateForm(formEl, nativeSubmit) {
function maybeUploadOnSubmit (line 62) | function maybeUploadOnSubmit(formEl) {
function determineFormEl (line 88) | function determineFormEl(formEl) {
FILE: client/js/identify.js
function isIdentifiable (line 5) | function isIdentifiable(magicBytes, questionableBytes) {
FILE: client/js/image-support/exif.js
function parseLittleEndian (line 22) | function parseLittleEndian(hex) {
function seekToApp1 (line 37) | function seekToApp1(offset, promise) {
function getApp1Offset (line 67) | function getApp1Offset() {
function isLittleEndian (line 88) | function isLittleEndian(app1Start) {
function getDirEntryCount (line 99) | function getDirEntryCount(app1Start, littleEndian) {
function getIfd (line 115) | function getIfd(app1Start, dirEntries) {
function getDirEntries (line 123) | function getDirEntries(ifdHex) {
function getTagValues (line 136) | function getTagValues(littleEndian, dirEntries) {
FILE: client/js/image-support/image.js
function isImg (line 10) | function isImg(el) {
function isCanvas (line 14) | function isCanvas(el) {
function isImgCorsSupported (line 18) | function isImgCorsSupported() {
function isCanvasSupported (line 22) | function isCanvasSupported() {
function determineMimeOfFileName (line 31) | function determineMimeOfFileName(nameWithPath) {
function isCrossOrigin (line 60) | function isCrossOrigin(url) {
function registerImgLoadListeners (line 86) | function registerImgLoadListeners(img, promise) {
function registerCanvasDrawImageListener (line 101) | function registerCanvasDrawImageListener(canvas, promise) {
function registerThumbnailRenderedListener (line 117) | function registerThumbnailRenderedListener(imgOrCanvas, promise) {
function draw (line 136) | function draw(fileOrBlob, container, options) {
function drawOnCanvasOrImgFromUrl (line 198) | function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, custo...
function drawOnImgFromUrlWithCssScaling (line 227) | function drawOnImgFromUrlWithCssScaling(url, img, draw, maxSize) {
function drawFromUrl (line 249) | function drawFromUrl(url, container, options) {
FILE: client/js/image-support/megapix-image.js
function detectSubsampling (line 21) | function detectSubsampling(img) {
function detectVerticalSquash (line 44) | function detectVerticalSquash(img, iw, ih) {
function renderImageToDataURL (line 75) | function renderImageToDataURL(img, blob, options, doSquash) {
function maybeCalculateDownsampledDimensions (line 90) | function maybeCalculateDownsampledDimensions(spec) {
function renderImageToCanvas (line 108) | function renderImageToCanvas(img, blob, canvas, options, doSquash) {
function renderImageToCanvasWithCustomResizer (line 199) | function renderImageToCanvasWithCustomResizer(resizeInfo) {
function transformCoordinate (line 243) | function transformCoordinate(canvas, width, height, orientation) {
function MegaPixImage (line 302) | function MegaPixImage(srcImage, errorCallback) {
FILE: client/js/image-support/validation.image.js
function hasNonZeroLimits (line 16) | function hasNonZeroLimits(limits) {
function getWidthHeight (line 34) | function getWidthHeight() {
function getFailingLimit (line 73) | function getFailingLimit(limits, dimensions) {
FILE: client/js/jquery-dnd.js
function init (line 7) | function init(options) {
function dataStore (line 20) | function dataStore(key, val) {
function dnd (line 38) | function dnd(instanceToStore) {
function addCallbacks (line 42) | function addCallbacks(transformedOpts) {
function transformVariables (line 61) | function transformVariables(source, dest) {
function isValidCommand (line 101) | function isValidCommand(command) {
function delegateCommand (line 107) | function delegateCommand(command) {
FILE: client/js/jquery-plugin.js
function init (line 7) | function init(options) {
function getNewUploaderInstance (line 17) | function getNewUploaderInstance(params) {
function dataStore (line 42) | function dataStore(key, val) {
function uploader (line 62) | function uploader(instanceToStore) {
function pluginOption (line 66) | function pluginOption(option, optionVal) {
function addCallbacks (line 72) | function addCallbacks(transformedOpts, newUploaderInstance) {
function transformVariables (line 112) | function transformVariables(source, dest) {
function isValidCommand (line 166) | function isValidCommand(command) {
function delegateCommand (line 174) | function delegateCommand(command) {
function maybeWrapInJquery (line 187) | function maybeWrapInJquery(val) {
FILE: client/js/paste.js
function isImage (line 15) | function isImage(item) {
function registerPasteHandler (line 20) | function registerPasteHandler() {
function unregisterPasteHandler (line 35) | function unregisterPasteHandler() {
FILE: client/js/s3/multipart.abort.ajax.requester.js
function getHeaders (line 44) | function getHeaders(id, uploadId) {
function handleAbortRequestComplete (line 67) | function handleAbortRequestComplete(id, xhr, isError) {
FILE: client/js/s3/multipart.complete.ajax.requester.js
function getHeaders (line 44) | function getHeaders(id, uploadId, body) {
function handleCompleteRequestComplete (line 69) | function handleCompleteRequestComplete(id, xhr, isError) {
function getCompleteRequestBody (line 114) | function getCompleteRequestBody(etagEntries) {
FILE: client/js/s3/multipart.initiate.ajax.requester.js
function getHeaders (line 51) | function getHeaders(id) {
function handleInitiateRequestComplete (line 99) | function handleInitiateRequestComplete(id, xhr, isError) {
FILE: client/js/s3/request-signer.js
function handleSignatureReceived (line 263) | function handleSignatureReceived(id, xhrOrXdr, isError) {
function getStringToSignArtifacts (line 325) | function getStringToSignArtifacts(id, version, requestInfo) {
function determineSignatureClientSide (line 421) | function determineSignatureClientSide(id, toBeSigned, signatureEffort, u...
function signPolicy (line 445) | function signPolicy(policy, signatureEffort, updatedAccessKey, updatedSe...
function signApiRequest (line 454) | function signApiRequest(signatureConstructor, headersStr, signatureEffor...
FILE: client/js/s3/s3.form.upload.handler.js
function isValidResponse (line 51) | function isValidResponse(id, iframe) {
function generateAwsParams (line 82) | function generateAwsParams(id) {
function createForm (line 112) | function createForm(id, iframe) {
function handleUpload (line 136) | function handleUpload(id) {
function handleFinishedUpload (line 183) | function handleFinishedUpload(id, iframe) {
FILE: client/js/session.ajax.requester.js
function onComplete (line 27) | function onComplete(id, xhrOrXdr, isError) {
FILE: client/js/session.js
function isJsonResponseValid (line 21) | function isJsonResponseValid(response) {
function handleFileItems (line 29) | function handleFileItems(fileItems, success, xhrOrXdr, promise) {
FILE: client/js/third-party/crypto-js/core.js
function F (line 25) | function F() {}
FILE: client/js/third-party/crypto-js/sha256.js
function isPrime (line 21) | function isPrime(n) {
function getFractionalBits (line 32) | function getFractionalBits(n) {
FILE: client/js/traditional/traditional.form.upload.handler.js
function getIframeContentJson (line 22) | function getIframeContentJson(id, iframe) {
function createForm (line 53) | function createForm(id, iframe) {
FILE: client/js/ui.handler.click.filebuttons.js
function examineEvent (line 24) | function examineEvent(target, event) {
FILE: client/js/ui.handler.click.filename.js
function examineEvent (line 21) | function examineEvent(target, event) {
FILE: client/js/ui.handler.edit.filename.js
function getFilenameSansExtension (line 16) | function getFilenameSansExtension(fileId) {
function getOriginalExtension (line 27) | function getOriginalExtension(fileId) {
function handleNameUpdate (line 33) | function handleNameUpdate(newFilenameInputEl, fileId) {
function registerInputBlurHandler (line 51) | function registerInputBlurHandler(inputEl, fileId) {
function registerInputEnterKeyHandler (line 58) | function registerInputEnterKeyHandler(inputEl, fileId) {
FILE: client/js/ui.handler.events.js
function addHandler (line 26) | function addHandler(element) {
FILE: client/js/ui.handler.focusin.filenameinput.js
function handleInputFocus (line 17) | function handleInputFocus(target, event) {
FILE: client/js/upload-data.js
function getDataByIds (line 11) | function getDataByIds(idOrIds) {
function getDataByUuids (line 25) | function getDataByUuids(uuids) {
function getDataByStatus (line 39) | function getDataByStatus(status) {
FILE: client/js/upload-handler/form.upload.handler.js
function expungeFile (line 29) | function expungeFile(id) {
function getFileIdForIframeName (line 56) | function getFileIdForIframeName(iframeName) {
function initIframeForUpload (line 67) | function initIframeForUpload(name) {
function registerPostMessageCallback (line 85) | function registerPostMessageCallback(iframe, callback) {
FILE: client/js/upload-handler/xhr.upload.handler.js
function abort (line 46) | function abort(id) {
FILE: client/js/uploader.api.js
function completeUpload (line 355) | function completeUpload(result) {
function r (line 613) | function r(name, replacement) { message = message.replace(name, replacem...
FILE: client/js/uploader.basic.api.js
function allowMultiple (line 676) | function allowMultiple() {
function r (line 1288) | function r(name, replacement) { message = message.replace(name, replacem...
FILE: client/js/uploadsuccess.ajax.requester.js
function handleSuccessResponse (line 30) | function handleSuccessResponse(id, xhrOrXdr, isError) {
FILE: client/typescript/fine-uploader.d.ts
class FineUploaderBasic (line 9) | class FineUploaderBasic {
type CustomResizerCallBack (line 589) | interface CustomResizerCallBack {
type ResizeInfo (line 606) | interface ResizeInfo {
type UploadFilter (line 637) | interface UploadFilter {
type FoundUploadItems (line 655) | interface FoundUploadItems extends UploadFilter {
type ScaleImageOptions (line 669) | interface ScaleImageOptions {
type PromiseOptions (line 703) | interface PromiseOptions {
type BlobWrapper (line 751) | interface BlobWrapper {
type CanvasWrapper (line 765) | interface CanvasWrapper {
type ResumableFileObject (line 787) | interface ResumableFileObject {
type CoreOptions (line 816) | interface CoreOptions {
type FormatFileNameFuncton (line 943) | interface FormatFileNameFuncton {
type BlobsOptions (line 950) | interface BlobsOptions {
type CameraOptions (line 962) | interface CameraOptions {
type ConcurrentOptions (line 985) | interface ConcurrentOptions {
type ChunkingOptions (line 997) | interface ChunkingOptions {
type ParamNamesOptions (line 1037) | interface ParamNamesOptions {
type SuccessOptions (line 1079) | interface SuccessOptions {
type CorsOptions (line 1125) | interface CorsOptions {
type DeleteFileOptions (line 1149) | interface DeleteFileOptions {
type ExtraButtonsOptions (line 1187) | interface ExtraButtonsOptions {
type FormOptions (line 1227) | interface FormOptions {
type Messages (line 1253) | interface Messages {
type PasteOptions (line 1337) | interface PasteOptions {
type ResumeOptions (line 1355) | interface ResumeOptions {
type RetryOptions (line 1387) | interface RetryOptions {
type RequestOptions (line 1417) | interface RequestOptions {
type SizeOptions (line 1498) | interface SizeOptions {
type ScalingOptions (line 1516) | interface ScalingOptions {
type SessionOptions (line 1580) | interface SessionOptions {
type TextOptions (line 1610) | interface TextOptions {
type ImageOptions (line 1636) | interface ImageOptions {
type ValidationOptions (line 1666) | interface ValidationOptions {
type WorkArounds (line 1716) | interface WorkArounds {
type CoreEvents (line 1748) | interface CoreEvents {
type OnAutoRetry (line 1944) | interface OnAutoRetry {
type OnCancel (line 1956) | interface OnCancel {
type OnComplete (line 1967) | interface OnComplete {
type OnAllComplete (line 1980) | interface OnAllComplete {
type OnDelete (line 1991) | interface OnDelete {
type OnDeleteComplete (line 2001) | interface OnDeleteComplete {
type OnError (line 2013) | interface OnError {
type OnManualRetry (line 2026) | interface OnManualRetry {
type OnPasteReceived (line 2037) | interface OnPasteReceived {
type OnProgress (line 2047) | interface OnProgress {
type OnResume (line 2060) | interface OnResume {
type OnSessionRequestComplete (line 2073) | interface OnSessionRequestComplete {
type OnStatusChange (line 2085) | interface OnStatusChange {
type OnSubmit (line 2094) | interface OnSubmit {
type OnSubmitDelete (line 2105) | interface OnSubmitDelete {
type OnSubmitted (line 2115) | interface OnSubmitted {
type OnTotalProgress (line 2126) | interface OnTotalProgress {
type OnUpload (line 2137) | interface OnUpload {
type ChunkData (line 2149) | interface ChunkData {
type OnUploadChunk (line 2171) | interface OnUploadChunk {
type OnUploadChunkSuccess (line 2183) | interface OnUploadChunkSuccess {
type BlobDataObject (line 2196) | interface BlobDataObject {
type OnValidate (line 2210) | interface OnValidate {
type OnValidateBatch (line 2221) | interface OnValidateBatch {
class FineUploader (line 2250) | class FineUploader extends FineUploaderBasic {
type UIOptions (line 2303) | interface UIOptions extends CoreOptions {
type ShowMessageFunction (line 2403) | interface ShowMessageFunction {
type ShowConfirmFunction (line 2410) | interface ShowConfirmFunction {
type ShowPromptFunction (line 2417) | interface ShowPromptFunction {
type UIDeleteFileOptions (line 2424) | interface UIDeleteFileOptions extends DeleteFileOptions {
type UIDisplayOptions (line 2454) | interface UIDisplayOptions {
type UIDragAndDropOptions (line 2472) | interface UIDragAndDropOptions {
type UIFailedUploadTextDisplay (line 2490) | interface UIFailedUploadTextDisplay {
type UIMessages (line 2516) | interface UIMessages extends Messages {
type UIRetryOptions (line 2534) | interface UIRetryOptions extends RetryOptions {
type UIThumbnailsOptions (line 2562) | interface UIThumbnailsOptions {
type UIThumbnailsPlaceholderOptions (line 2599) | interface UIThumbnailsPlaceholderOptions {
type UIPasteOptions (line 2626) | interface UIPasteOptions extends PasteOptions {
type UIScalingOptions (line 2644) | interface UIScalingOptions extends ScalingOptions {
type UITextOptions (line 2664) | interface UITextOptions extends TextOptions {
class FineUploader (line 2722) | class FineUploader extends FineUploaderCore {
class FineUploaderBasic (line 2774) | class FineUploaderBasic extends FineUploaderBasicCore {
type AzureChunkingOptions (line 2831) | interface AzureChunkingOptions extends ChunkingOptions {
type AzureCorsOptions (line 2849) | interface AzureCorsOptions extends CorsOptions {
type AzureBlobPropertyNameFunction (line 2861) | interface AzureBlobPropertyNameFunction {
type AzureBlobPropertyOptions (line 2868) | interface AzureBlobPropertyOptions {
type AzureRequestOptions (line 2888) | interface AzureRequestOptions extends RequestOptions {
type AzureCustomHeaderFunction (line 2913) | interface AzureCustomHeaderFunction {
type AzureSignatureOptions (line 2920) | interface AzureSignatureOptions {
type AzureUploadSuccessOptions (line 2942) | interface AzureUploadSuccessOptions {
type AzureFailedUploadTextDisplayOptions (line 2975) | interface AzureFailedUploadTextDisplayOptions {
type AzureResumableFileObject (line 2987) | interface AzureResumableFileObject extends ResumableFileObject {
type AzureCoreOptions (line 2997) | interface AzureCoreOptions extends CoreOptions {
type AzureUIOptions (line 3027) | interface AzureUIOptions extends UIOptions, AzureCoreOptions {
class FineUploader (line 3102) | class FineUploader extends FineUploaderCore {
class FineUploaderBasic (line 3178) | class FineUploaderBasic extends FineUploaderBasicCore {
type S3CredentialsOptions (line 3259) | interface S3CredentialsOptions {
type S3ChunkingOptions (line 3289) | interface S3ChunkingOptions extends ChunkingOptions {
type S3CorsOptions (line 3301) | interface S3CorsOptions extends CorsOptions {
type S3iFrameSupportOptions (line 3313) | interface S3iFrameSupportOptions {
type BucketFunction (line 3326) | interface BucketFunction {
type HostFunction (line 3333) | interface HostFunction {
type KeyFunction (line 3340) | interface KeyFunction {
type S3ObjectPropertyOptions (line 3347) | interface S3ObjectPropertyOptions {
type S3RequestOptions (line 3412) | interface S3RequestOptions extends RequestOptions {
type S3CustomHeaderFunction (line 3453) | interface S3CustomHeaderFunction {
type S3SignatureOptions (line 3460) | interface S3SignatureOptions {
type S3UploadSuccessOptions (line 3486) | interface S3UploadSuccessOptions {
type S3CoreOptions (line 3519) | interface S3CoreOptions extends CoreOptions {
type S3FailedUploadTextDisplayOptions (line 3557) | interface S3FailedUploadTextDisplayOptions {
type OnCredentialsExpired (line 3569) | interface OnCredentialsExpired {
type S3Events (line 3576) | interface S3Events extends CoreEvents {
type S3UIOptions (line 3589) | interface S3UIOptions extends UIOptions, S3CoreOptions {
type S3ResumableFileObject (line 3631) | interface S3ResumableFileObject extends ResumableFileObject {
FILE: test/static/local/client.js
function FancyJSON (line 2) | function FancyJSON(runner) {
function mochaSaucePlease (line 78) | function mochaSaucePlease(fn) {
FILE: test/static/local/formdata.js
function mockFormData (line 2) | function mockFormData() {
function unmockFormData (line 47) | function unmockFormData() {
FILE: test/static/local/helpme.js
function XMLHttpRequest (line 3) | function XMLHttpRequest() {} // jshint ignore:line
function mockXhr (line 96) | function mockXhr() {
function unmockXhr (line 103) | function unmockXhr() {
FILE: test/static/local/karma-runner.js
function checkIfDone (line 12) | function checkIfDone() {
FILE: test/static/third-party/assert/assert.js
function f (line 32) | function f() {}
function replacer (line 160) | function replacer(key, value) {
function truncate (line 173) | function truncate(s, n) {
function getMessage (line 181) | function getMessage(self) {
function fail (line 198) | function fail(actual, expected, message, operator, stackStartFunction) {
function ok (line 218) | function ok(value, message) {
function _deepEqual (line 249) | function _deepEqual(actual, expected) {
function isArguments (line 294) | function isArguments(object) {
function objEquiv (line 298) | function objEquiv(a, b) {
function expectedException (line 368) | function expectedException(actual, expected) {
function _throws (line 384) | function _throws(shouldThrow, block, expected, message) {
FILE: test/static/third-party/jquery.simulate/jquery.simulate.js
function trigger (line 218) | function trigger() {
function trigger (line 239) | function trigger() {
function findCenter (line 270) | function findCenter( elem ) {
FILE: test/static/third-party/jquery/jquery.js
function isArraylike (line 983) | function isArraylike( obj ) {
function Sizzle (line 1177) | function Sizzle( selector, context, results, seed ) {
function isNative (line 1290) | function isNative( fn ) {
function createCache (line 1300) | function createCache() {
function markFunction (line 1318) | function markFunction( fn ) {
function assert (line 1327) | function assert( fn ) {
function addHandle (line 1350) | function addHandle( attrs, handler, test ) {
function boolHandler (line 1369) | function boolHandler( elem, name ) {
function interpolationHandler (line 1383) | function interpolationHandler( elem, name ) {
function valueHandler (line 1393) | function valueHandler( elem ) {
function siblingCheck (line 1408) | function siblingCheck( a, b ) {
function createInputPseudo (line 1435) | function createInputPseudo( type ) {
function createButtonPseudo (line 1446) | function createButtonPseudo( type ) {
function createPositionalPseudo (line 1457) | function createPositionalPseudo( fn ) {
function tokenize (line 2455) | function tokenize( selector, parseOnly ) {
function toSelector (line 2522) | function toSelector( tokens ) {
function addCombinator (line 2532) | function addCombinator( matcher, combinator, base ) {
function elementMatcher (line 2582) | function elementMatcher( matchers ) {
function condense (line 2596) | function condense( unmatched, map, filter, context, xml ) {
function setMatcher (line 2617) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
function matcherFromTokens (line 2710) | function matcherFromTokens( tokens ) {
function matcherFromGroupMatchers (line 2765) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
function multipleContexts (line 2893) | function multipleContexts( selector, contexts, results ) {
function select (line 2902) | function select( selector, context, results, seed ) {
function setFilters (line 2970) | function setFilters() {}
function createOptions (line 3001) | function createOptions( options ) {
function internalData (line 3584) | function internalData( elem, name, data, pvt /* Internal Use Only */ ){
function internalRemoveData (line 3673) | function internalRemoveData( elem, name, pvt ) {
function dataAttr (line 3870) | function dataAttr( elem, key, data ) {
function isEmptyDataObject (line 3902) | function isEmptyDataObject( obj ) {
function returnTrue (line 4724) | function returnTrue() {
function returnFalse (line 4728) | function returnFalse() {
function safeActiveElement (line 4732) | function safeActiveElement() {
function sibling (line 5850) | function sibling( cur, dir ) {
function winnow (line 5968) | function winnow( elements, qualifier, not ) {
function createSafeFragment (line 5996) | function createSafeFragment( document ) {
function manipulationTarget (line 6310) | function manipulationTarget( elem, content ) {
function disableScript (line 6320) | function disableScript( elem ) {
function restoreScript (line 6324) | function restoreScript( elem ) {
function setGlobalEval (line 6335) | function setGlobalEval( elems, refElements ) {
function cloneCopyEvent (line 6343) | function cloneCopyEvent( src, dest ) {
function fixCloneNodeIssues (line 6371) | function fixCloneNodeIssues( src, dest ) {
function getAll (line 6464) | function getAll( context, tag ) {
function fixDefaultChecked (line 6487) | function fixDefaultChecked( elem ) {
function vendorPropName (line 6829) | function vendorPropName( style, name ) {
function isHidden (line 6851) | function isHidden( elem, el ) {
function showHide (line 6858) | function showHide( elements, show ) {
function setPositiveNumber (line 7184) | function setPositiveNumber( elem, value, subtract ) {
function augmentWidthOrHeight (line 7192) | function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
function getWidthOrHeight (line 7231) | function getWidthOrHeight( elem, name, extra ) {
function css_defaultDisplay (line 7275) | function css_defaultDisplay( nodeName ) {
function actualDisplay (line 7307) | function actualDisplay( name, doc ) {
function buildParams (line 7536) | function buildParams( prefix, obj, traditional, add ) {
function addToPrefiltersOrTransports (line 7651) | function addToPrefiltersOrTransports( structure ) {
function inspectPrefiltersOrTransports (line 7683) | function inspectPrefiltersOrTransports( structure, options, originalOpti...
function ajaxExtend (line 7710) | function ajaxExtend( target, src ) {
function done (line 8158) | function done( status, nativeStatusText, responses, headers ) {
function ajaxHandleResponses (line 8305) | function ajaxHandleResponses( s, jqXHR, responses ) {
function ajaxConvert (line 8360) | function ajaxConvert( s, response, jqXHR, isSuccess ) {
function createStandardXHR (line 8628) | function createStandardXHR() {
function createActiveXHR (line 8634) | function createActiveXHR() {
function createFxNow (line 8880) | function createFxNow() {
function createTween (line 8887) | function createTween( value, prop, animation ) {
function Animation (line 8901) | function Animation( elem, properties, options ) {
function propFilter (line 9005) | function propFilter( props, specialEasing ) {
function defaultPrefilter (line 9072) | function defaultPrefilter( elem, props, opts ) {
function Tween (line 9197) | function Tween( elem, options, prop, end, easing ) {
function genFx (line 9423) | function genFx( type, includeWidth ) {
function getWindow (line 9719) | function getWindow( elem ) {
FILE: test/static/third-party/json2/json.js
function f (line 206) | function f(n) {
function quote (line 240) | function quote(string) {
function str (line 257) | function str(key, holder) {
function walk (line 452) | function walk(holder, key) {
FILE: test/static/third-party/json2/json2.js
function f (line 169) | function f(n) {
function quote (line 203) | function quote(string) {
function str (line 220) | function str(key, holder) {
function walk (line 416) | function walk(holder, key) {
FILE: test/static/third-party/json2/json_parse_state.js
function debackslashify (line 286) | function debackslashify(text) {
FILE: test/static/third-party/mocha/js/mocha.js
function require (line 5) | function require(p){
function clonePath (line 77) | function clonePath(path) {
function removeEmpty (line 80) | function removeEmpty(array) {
function escapeHTML (line 89) | function escapeHTML(s) {
function contextLines (line 250) | function contextLines(lines) {
function eofNL (line 253) | function eofNL(curRange, i, current) {
function isArray (line 362) | function isArray(obj) {
function EventEmitter (line 372) | function EventEmitter(){}
function on (line 407) | function on () {
function Progress (line 551) | function Progress() {
function Context (line 693) | function Context(){}
function Hook (line 774) | function Hook(title, fn) {
function F (line 783) | function F(){}
function visit (line 977) | function visit(obj) {
function image (line 1312) | function image(name) {
function Mocha (line 1334) | function Mocha(options) {
function parse (line 1622) | function parse(str) {
function format (line 1661) | function format(ms) {
function Base (line 1894) | function Base(runner) {
function pluralize (line 1962) | function pluralize(n) {
function pad (line 2012) | function pad(str, len) {
function errorDiff (line 2025) | function errorDiff(err, type, escape) {
function colorLines (line 2048) | function colorLines(name, str) {
function Doc (line 2078) | function Doc(runner) {
function Dot (line 2138) | function Dot(runner) {
function F (line 2178) | function F(){}
function HTMLCov (line 2207) | function HTMLCov(runner) {
function coverageClass (line 2231) | function coverageClass(n) {
function HTML (line 2284) | function HTML(runner, root) {
function error (line 2423) | function error(msg) {
function fragment (line 2431) | function fragment(html) {
function hideSuitesWithout (line 2451) | function hideSuitesWithout(classname) {
function unhide (line 2463) | function unhide() {
function text (line 2474) | function text(el, str) {
function on (line 2486) | function on(el, event, fn) {
function JSONCov (line 2541) | function JSONCov(runner, output) {
function map (line 2584) | function map(cov) {
function coverage (line 2623) | function coverage(filename, data) {
function clean (line 2666) | function clean(test) {
function List (line 2698) | function List(runner) {
function clean (line 2731) | function clean(test) {
function JSONReporter (line 2763) | function JSONReporter(runner) {
function clean (line 2804) | function clean(test) {
function Landing (line 2854) | function Landing(runner) {
function F (line 2910) | function F(){}
function List (line 2940) | function List(runner) {
function F (line 2981) | function F(){}
function Markdown (line 3010) | function Markdown(runner) {
function Min (line 3104) | function Min(runner) {
function F (line 3121) | function F(){}
function NyanCat (line 3150) | function NyanCat(runner) {
function draw (line 3216) | function draw(color, n) {
function write (line 3374) | function write(string) {
function F (line 3382) | function F(){}
function Progress (line 3420) | function Progress(runner, options) {
function F (line 3476) | function F(){}
function Spec (line 3507) | function Spec(runner) {
function F (line 3571) | function F(){}
function TAP (line 3602) | function TAP(runner) {
function title (line 3650) | function title(test) {
function Teamcity (line 3677) | function Teamcity(runner) {
function escape (line 3710) | function escape(str) {
function XUnit (line 3758) | function XUnit(runner) {
function F (line 3792) | function F(){}
function test (line 3802) | function test(test) {
function tag (line 3824) | function tag(name, attrs, close, content) {
function cdata (line 3842) | function cdata(str) {
function Runnable (line 3888) | function Runnable(title, fn) {
function F (line 3902) | function F(){}
function multiple (line 4026) | function multiple(err) {
function done (line 4033) | function done(err) {
function Runner (line 4126) | function Runner(suite) {
function F (line 4151) | function F(){}
function next (line 4311) | function next(i) {
function next (line 4351) | function next(suite) {
function next (line 4450) | function next(err) {
function next (line 4517) | function next() {
function done (line 4523) | function done() {
function uncaught (line 4575) | function uncaught(err){
function filterLeaks (line 4610) | function filterLeaks(ok, globals) {
function Suite (line 4675) | function Suite(title, ctx) {
function F (line 4695) | function F(){}
function Test (line 4952) | function Test(title, fn) {
function F (line 4962) | function F(){}
function ignored (line 5116) | function ignored(path){
function highlight (line 5228) | function highlight(js) {
function timeslice (line 5312) | function timeslice() {
FILE: test/static/third-party/purl/purl.js
function parseUri (line 37) | function parseUri( url, strictMode ) {
function getAttrName (line 61) | function getAttrName( elm ) {
function promote (line 67) | function promote(parent, key) {
function parse (line 75) | function parse(parts, parent, key, val) {
function merge (line 109) | function merge(parent, key, val) {
function parseString (line 126) | function parseString(str) {
function set (line 149) | function set(obj, key, val) {
function lastBraceInKey (line 160) | function lastBraceInKey(str) {
function reduce (line 172) | function reduce(obj, accumulator){
function isArray (line 183) | function isArray(vArg) {
function keys (line 187) | function keys(obj) {
function purl (line 195) | function purl( url, strictMode ) {
FILE: test/static/third-party/q/q-1.0.1.js
function flush (line 93) | function flush() {
function uncurryThis (line 219) | function uncurryThis(f) {
function Type (line 283) | function Type() { }
function isObject (line 302) | function isObject(value) {
function isStopIteration (line 309) | function isStopIteration(exception) {
function makeStackTraceLong (line 331) | function makeStackTraceLong(error, promise) {
function filterStackString (line 354) | function filterStackString(stackString) {
function isNodeFrame (line 367) | function isNodeFrame(stackLine) {
function getFileNameAndLineNumber (line 372) | function getFileNameAndLineNumber(stackLine) {
function isInternalFrame (line 393) | function isInternalFrame(stackLine) {
function captureLine (line 410) | function captureLine() {
function deprecate (line 430) | function deprecate(callback, name, alternative) {
function Q (line 449) | function Q(value) {
function defer (line 488) | function defer() {
function promise (line 629) | function promise(resolver) {
function race (line 692) | function race(answerPs) {
function Promise (line 721) | function Promise(descriptor, fallback, inspect) {
function _fulfilled (line 785) | function _fulfilled(value) {
function _rejected (line 793) | function _rejected(exception) {
function _progressed (line 805) | function _progressed(value) {
function when (line 867) | function when(value, fulfilled, rejected, progressed) {
function nearer (line 899) | function nearer(value) {
function isPromise (line 914) | function isPromise(object) {
function isPromiseAlike (line 921) | function isPromiseAlike(object) {
function isPending (line 930) | function isPending(object) {
function isFulfilled (line 943) | function isFulfilled(object) {
function isRejected (line 955) | function isRejected(object) {
function resetUnhandledRejections (line 973) | function resetUnhandledRejections() {
function trackRejection (line 982) | function trackRejection(promise, reason) {
function untrackRejection (line 995) | function untrackRejection(promise) {
function reject (line 1028) | function reject(reason) {
function fulfill (line 1054) | function fulfill(value) {
function coerce (line 1093) | function coerce(promise) {
function master (line 1115) | function master(object) {
function spread (line 1136) | function spread(value, fulfilled, rejected) {
function async (line 1173) | function async(makeGenerator) {
function spawn (line 1230) | function spawn(makeGenerator) {
function _return (line 1260) | function _return(value) {
function promised (line 1280) | function promised(callback) {
function dispatch (line 1296) | function dispatch(object, op, args) {
function all (line 1474) | function all(promises) {
function allResolved (line 1523) | function allResolved(promises) {
function allSettled (line 1542) | function allSettled(promises) {
function regardless (line 1557) | function regardless() {
function progress (line 1593) | function progress(object, progressed) {
function bound (line 1801) | function bound() {
function nodeify (line 1879) | function nodeify(object, nodeback) {
FILE: test/static/third-party/sinon/fake_xml_http_request.js
function FakeXMLHttpRequest (line 56) | function FakeXMLHttpRequest() {
function UploadProgress (line 91) | function UploadProgress() {
function verifyState (line 112) | function verifyState(xhr) {
function each (line 124) | function each(collection, callback) {
function some (line 130) | function some(collection, callback) {
function verifyRequestSent (line 202) | function verifyRequestSent(xhr) {
function verifyHeadersReceived (line 208) | function verifyHeadersReceived(xhr) {
function verifyResponseBodyType (line 214) | function verifyResponseBodyType(body) {
FILE: test/static/third-party/sinon/sinon.js
function isDOMNode (line 17) | function isDOMNode(obj) {
function isElement (line 36) | function isElement(obj) {
function isFunction (line 40) | function isFunction(obj) {
function mirrorProperties (line 44) | function mirrorProperties(target, source) {
function isRestorable (line 52) | function isRestorable (obj) {
FILE: test/unit/azure/simple-file-uploads.js
function runTest (line 125) | function runTest(uploader, done) {
FILE: test/unit/basic.js
function getFileInput (line 7) | function getFileInput($containerEl) {
FILE: test/unit/chunked-uploads.js
function testChunkedUpload (line 22) | function testChunkedUpload(spec) {
function testChunkedFailureAndRecovery (line 112) | function testChunkedFailureAndRecovery(restartAfterFailure, done) {
function testChunkedEveryFailureAndRecovery (line 203) | function testChunkedEveryFailureAndRecovery(done) {
function testResumeRecordsLogic (line 401) | function testResumeRecordsLogic(onUploadChunkSuccess, customKeys) {
function testChunkingLogic (line 467) | function testChunkingLogic(forceChunking, done) {
function testChunkingLogic (line 507) | function testChunkingLogic(chunkingSuccess, onComplete) {
function testChunkingLogic (line 639) | function testChunkingLogic(chunkingSuccess, onComplete, chunkingSuccessS...
function testChunkingLogic (line 699) | function testChunkingLogic(request, onComplete, sinonResponse) {
function testOnUploadChunkLogic (line 834) | function testOnUploadChunkLogic(callbacks, options) {
FILE: test/unit/delete-file.js
function testDeleteFile (line 21) | function testDeleteFile(done, expectedMethod, deleteEnabled, successful,...
FILE: test/unit/dnd.js
function sameValueZero (line 35) | function sameValueZero(x, y) {
FILE: test/unit/exif.js
function testOrientation (line 18) | function testOrientation(key, expectedOrientation, done) {
FILE: test/unit/file-upload-params-and-headers.js
function getSimpleParamsUploader (line 20) | function getSimpleParamsUploader(mpe, paramsAsOptions) {
function getSimpleHeadersUploader (line 35) | function getSimpleHeadersUploader(headersAsOptions) {
function assertParamsInRequest (line 48) | function assertParamsInRequest(uploader, mpe, done, overrideParams) {
function assertHeadersInRequest (line 76) | function assertHeadersInRequest(uploader, done) {
FILE: test/unit/identify.js
function testPreviewability (line 6) | function testPreviewability(expectedToBePreviewable, key, expectedMime, ...
FILE: test/unit/s3/serverless-uploads.js
function runTest (line 189) | function runTest(callback, done) {
FILE: test/unit/s3/simple-file-uploads.js
function runTest (line 401) | function runTest(keyFunc, done) {
function runTest (line 445) | function runTest(keyFunc, done) {
function runTest (line 482) | function runTest(keyFunc, done) {
FILE: test/unit/scaling.js
function runTestWithImage (line 41) | function runTestWithImage(includeOriginal) {
function runTestWithNonImage (line 83) | function runTestWithNonImage(includeOriginal) {
function runScaleTest (line 160) | function runScaleTest(orient, customResizer, done) {
function runTest (line 288) | function runTest(customResizer, done) {
function runTest (line 372) | function runTest(customResizer, done) {
function runTest (line 569) | function runTest(customResizer, done) {
function runTest (line 790) | function runTest(customResizer, done) {
function runTest (line 847) | function runTest(customResizer, done) {
FILE: test/unit/session.js
function runTest (line 376) | function runTest(namespace, requiredKeyName, done) {
FILE: test/unit/simple-file-uploads.js
function getSimpleUploader (line 9) | function getSimpleUploader(autoUpload, mpe) {
function runQueuedStatusTest (line 346) | function runQueuedStatusTest(autoUpload, done) {
function testOnUploadLogic (line 508) | function testOnUploadLogic(callbacks) {
FILE: test/unit/submit-validate-cancel.js
function setupUploader (line 133) | function setupUploader(callback, blob, done, useQ) {
function setupUploader (line 247) | function setupUploader(limits, numBlobsOrTheBlob, statusChangeLogic) {
function setupStopOnFirstInvalidFileUploader (line 379) | function setupStopOnFirstInvalidFileUploader(stopOnFirstInvalidFile, don...
function runCancelTest (line 418) | function runCancelTest(batch, done) {
FILE: test/unit/templating.js
function renderTemplate (line 113) | function renderTemplate(content) {
FILE: test/unit/ui.handler.click.filename.js
function testFilenameInputBlur (line 56) | function testFilenameInputBlur(origName, origNameSansExt, newName, newNa...
FILE: test/unit/uploader.basic.api.js
function runTest (line 229) | function runTest(callback, done) {
function runTest (line 273) | function runTest(callback, done) {
function setupUploader (line 357) | function setupUploader(allowedItems) {
FILE: test/unit/validation.image.js
function validate (line 15) | function validate(done, expectedErrorCode, limits) {
FILE: test/unit/workarounds.js
function getFileInput (line 7) | function getFileInput($containerEl) {
Condensed preview — 246 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,586K chars).
[
{
"path": ".editorconfig",
"chars": 482,
"preview": "# top-most EditorConfig file\nroot = true\n\n# Unix-style newlines with a newline ending every file\n[*]\nend_of_line = lf\nin"
},
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 1211,
"preview": "## Type of issue\n- [ ] Bug report\n- [ ] Feature request\n\n## Uploader type\n- [ ] Traditional\n- [ ] S3\n- [ ] Azure\n\n### No"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE",
"chars": 392,
"preview": "## Brief description of the changes\n{also describe what problem(s) these changes solve & reference any related issues/PR"
},
{
"path": ".gitignore",
"chars": 631,
"preview": ".*\n!.editorconfig\n*.ipr\n*~\n.*.sw[a-z]\n*.iml\n*.iws\n!.github\n!.gitignore\n!.jshintrc\n!.jshintignore\nThumbs.db\n\n_build/\n_dis"
},
{
"path": ".jshintignore",
"chars": 24,
"preview": "client/js/third-party/*\n"
},
{
"path": ".jshintrc",
"chars": 7531,
"preview": "{\n // --------------------------------------------------------------------\n // JSHint Configuration, Strict Editio"
},
{
"path": ".travis.yml",
"chars": 525,
"preview": "addons:\n firefox: latest\nsudo: false\nlanguage: python\npython:\n- 2.7\nenv:\n global:\n - DISPLAY=:99.0\n - DOCS_GH_REF: g"
},
{
"path": "ATTRIBUTION.txt",
"chars": 472,
"preview": "Third-party credits (client/js/third-party/)\n\nMegaPixImage module\n Licensed under MIT (https://github.com/stomita/ios"
},
{
"path": "LICENSE",
"chars": 1206,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2010-2012, Andrew Valums\nCopyright (c) 2012-2013, Andrew Valums and Raymond S. Nich"
},
{
"path": "Makefile",
"chars": 15668,
"preview": ".PHONY: clean _build publish start-test-resources-server test-resources-server.PID start-root-server root-server.PID\n\nve"
},
{
"path": "README.md",
"chars": 5802,
"preview": "**Fine Uploader is no longer maintained and the project has been effectively shut down. For more info, see https://githu"
},
{
"path": "client/README.md",
"chars": 446,
"preview": "Do not add files from this directory into your project. Please visit the\ndownloads page for zips that contain combined "
},
{
"path": "client/commonJs/all.js",
"chars": 83,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../all.fine-uploader/all.fine-uploader\");\n"
},
{
"path": "client/commonJs/azure.js",
"chars": 87,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../azure.fine-uploader/azure.fine-uploader\");\n"
},
{
"path": "client/commonJs/core/all.js",
"chars": 91,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../../all.fine-uploader/all.fine-uploader.core\");\n"
},
{
"path": "client/commonJs/core/azure.js",
"chars": 95,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../../azure.fine-uploader/azure.fine-uploader.core\");\n"
},
{
"path": "client/commonJs/core/index.js",
"chars": 83,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../../fine-uploader/fine-uploader.core\");\n"
},
{
"path": "client/commonJs/core/s3.js",
"chars": 89,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../../s3.fine-uploader/s3.fine-uploader.core\");\n"
},
{
"path": "client/commonJs/core/traditional.js",
"chars": 83,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../../fine-uploader/fine-uploader.core\");\n"
},
{
"path": "client/commonJs/dnd.js",
"chars": 55,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../dnd/dnd\");\n"
},
{
"path": "client/commonJs/jquery/azure.js",
"chars": 104,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../../azure.jquery.fine-uploader/azure.jquery.fine-uploader\");\n"
},
{
"path": "client/commonJs/jquery/s3.js",
"chars": 98,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../../s3.jquery.fine-uploader/s3.jquery.fine-uploader\");\n"
},
{
"path": "client/commonJs/jquery/traditional.js",
"chars": 92,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../../jquery.fine-uploader/jquery.fine-uploader\");\n"
},
{
"path": "client/commonJs/s3.js",
"chars": 81,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../s3.fine-uploader/s3.fine-uploader\");\n"
},
{
"path": "client/commonJs/traditional.js",
"chars": 75,
"preview": "\"use strict\";\n\nmodule.exports = require(\"../fine-uploader/fine-uploader\");\n"
},
{
"path": "client/fine-uploader-gallery.css",
"chars": 10829,
"preview": "/* ---------------------------------------\n/* Fine Uploader Gallery View Styles\n/* -------------------------------------"
},
{
"path": "client/fine-uploader-new.css",
"chars": 7477,
"preview": "/* ---------------------------------------\n/* Fine Uploader Styles\n/* ---------------------------------------\n\n/* Button"
},
{
"path": "client/fine-uploader.css",
"chars": 5246,
"preview": ".qq-uploader {\n position: relative;\n width: 100%;\n}\n.qq-upload-button {\n display: block;\n width: 105px;\n "
},
{
"path": "client/html/templates/default.html",
"chars": 3577,
"preview": "<!--\n This is a legacy template and is not meant to be used in new Fine Uploader integrated projects.\n Read the \"G"
},
{
"path": "client/html/templates/gallery.html",
"chars": 4619,
"preview": "<!--\n Read the \"Getting Started Guide\" at http://docs.fineuploader.com/quickstart/01-getting-started.html\n if you "
},
{
"path": "client/html/templates/simple-thumbnails.html",
"chars": 3686,
"preview": "<!--\n Read the \"Getting Started Guide\" at http://docs.fineuploader.com/quickstart/01-getting-started.html\n if you "
},
{
"path": "client/js/ajax.requester.js",
"chars": 14119,
"preview": "/*globals qq, XDomainRequest*/\n/** Generic class for sending non-upload ajax requests and handling the associated respon"
},
{
"path": "client/js/azure/azure.xhr.upload.handler.js",
"chars": 8595,
"preview": "/*globals qq */\n/**\n * Upload handler used by the upload to Azure module that depends on File API support, and, therefor"
},
{
"path": "client/js/azure/get-sas.js",
"chars": 2143,
"preview": "/* globals qq */\n/**\n * Sends a GET request to the integrator's server, which should return a Shared Access Signature UR"
},
{
"path": "client/js/azure/jquery-plugin.js",
"chars": 953,
"preview": "/*globals jQuery*/\n/**\n * Simply an alias for the `fineUploader` plug-in wrapper, but hides the required `endpointType` "
},
{
"path": "client/js/azure/rest/delete-blob.js",
"chars": 1270,
"preview": "/* globals qq */\n/**\n * Implements the Delete Blob Azure REST API call. http://msdn.microsoft.com/en-us/library/windows"
},
{
"path": "client/js/azure/rest/put-blob.js",
"chars": 2075,
"preview": "/* globals qq */\n/**\n * Implements the Put Blob Azure REST API call. http://msdn.microsoft.com/en-us/library/windowsazu"
},
{
"path": "client/js/azure/rest/put-block-list.js",
"chars": 3175,
"preview": "/* globals qq */\n/**\n * Implements the Put Block List Azure REST API call. http://msdn.microsoft.com/en-us/library/wind"
},
{
"path": "client/js/azure/rest/put-block.js",
"chars": 2300,
"preview": "/* globals qq */\n/**\n * Implements the Put Block Azure REST API call. http://msdn.microsoft.com/en-us/library/windowsaz"
},
{
"path": "client/js/azure/uploader.basic.js",
"chars": 8623,
"preview": "/*globals qq */\n/**\n * This defines FineUploaderBasic mode w/ support for uploading to Azure, which provides all the bas"
},
{
"path": "client/js/azure/uploader.js",
"chars": 1367,
"preview": "/*globals qq */\n/**\n * This defines FineUploader mode w/ support for uploading to Azure, which provides all the basic\n *"
},
{
"path": "client/js/azure/util.js",
"chars": 3708,
"preview": "/*globals qq */\nqq.azure = qq.azure || {};\nqq.azure.util = qq.azure.util || (function() {\n \"use strict\";\n\n return "
},
{
"path": "client/js/blob-proxy.js",
"chars": 472,
"preview": "/* globals qq */\n/**\n * Placeholder for a Blob that will be generated on-demand.\n *\n * @param referenceBlob Parent of th"
},
{
"path": "client/js/button.js",
"chars": 6578,
"preview": "/*globals qq*/\n\n/**\n * This module represents an upload or \"Select File(s)\" button. It's job is to embed an opaque `<in"
},
{
"path": "client/js/deletefile.ajax.requester.js",
"chars": 2120,
"preview": "/*globals qq, XMLHttpRequest*/\nqq.DeleteFileAjaxRequester = function(o) {\n \"use strict\";\n\n var requester,\n "
},
{
"path": "client/js/dnd.js",
"chars": 17082,
"preview": "/*globals qq, document, CustomEvent*/\nqq.DragAndDrop = function(o) {\n \"use strict\";\n\n var options,\n HIDE_ZO"
},
{
"path": "client/js/error/error.js",
"chars": 285,
"preview": "/* globals qq */\n/**\n * Fine Uploader top-level Error container. Inherits from `Error`.\n */\n(function() {\n \"use stri"
},
{
"path": "client/js/export.js",
"chars": 342,
"preview": "/* globals define, module, global, qq */\n(function() {\n \"use strict\";\n if (typeof define === \"function\" && define."
},
{
"path": "client/js/features.js",
"chars": 5811,
"preview": "/* globals qq */\nqq.supportedFeatures = (function() {\n \"use strict\";\n\n var supportsUploading,\n supportsUplo"
},
{
"path": "client/js/form-support.js",
"chars": 5656,
"preview": "/* globals qq */\n/**\n * Module that handles support for existing forms.\n *\n * @param options Options passed from the int"
},
{
"path": "client/js/identify.js",
"chars": 4435,
"preview": "/*globals qq */\nqq.Identify = function(fileOrBlob, log) {\n \"use strict\";\n\n function isIdentifiable(magicBytes, que"
},
{
"path": "client/js/iframe.xss.response.js",
"chars": 162,
"preview": "(function() {\n \"use strict\";\n var match = /(\\{.*\\})/.exec(document.body.innerHTML);\n if (match) {\n paren"
},
{
"path": "client/js/image-support/exif.js",
"chars": 6720,
"preview": "/*globals qq */\n/**\n * EXIF image data parser. Currently only parses the Orientation tag value,\n * but this may be expa"
},
{
"path": "client/js/image-support/image.js",
"chars": 12120,
"preview": "/*globals qq */\n/**\n * Draws a thumbnail of a Blob/File/URL onto an <img> or <canvas>.\n *\n * @constructor\n */\nqq.ImageGe"
},
{
"path": "client/js/image-support/megapix-image.js",
"chars": 13636,
"preview": "/*global qq, define */\n/*jshint strict:false,bitwise:false,nonew:false,asi:true,-W064,-W116,-W089 */\n/**\n * Mega pixel i"
},
{
"path": "client/js/image-support/scaler.js",
"chars": 15419,
"preview": "/* globals qq, ExifRestorer */\n/**\n * Controls generation of scaled images based on a reference image encapsulated in a "
},
{
"path": "client/js/image-support/validation.image.js",
"chars": 4471,
"preview": "/*globals qq*/\n/**\n * Attempts to validate an image, wherever possible.\n *\n * @param blob File or Blob representing a us"
},
{
"path": "client/js/jquery-dnd.js",
"chars": 3933,
"preview": "/*globals jQuery, qq*/\n(function($) {\n \"use strict\";\n var rootDataKey = \"fineUploaderDnd\",\n $el;\n\n funct"
},
{
"path": "client/js/jquery-plugin.js",
"chars": 7702,
"preview": "/*globals jQuery, qq*/\n(function($) {\n \"use strict\";\n var $el,\n pluginOptions = [\"uploaderType\", \"endpointT"
},
{
"path": "client/js/non-traditional-common/uploader.basic.api.js",
"chars": 5451,
"preview": "/*globals qq*/\n/**\n * Defines the public API for non-traditional FineUploaderBasic mode.\n */\n(function() {\n \"use stri"
},
{
"path": "client/js/paste.js",
"chars": 1193,
"preview": "/*globals qq*/\nqq.PasteSupport = function(o) {\n \"use strict\";\n\n var options, detachPasteHandler;\n\n options = {\n"
},
{
"path": "client/js/promise.js",
"chars": 2330,
"preview": "/*globals qq*/\n\n// Is the passed object a promise instance?\nqq.isGenericPromise = function(maybePromise) {\n \"use stri"
},
{
"path": "client/js/s3/jquery-plugin.js",
"chars": 933,
"preview": "/*globals jQuery*/\n/**\n * Simply an alias for the `fineUploader` plug-in wrapper, but hides the required `endpointType` "
},
{
"path": "client/js/s3/multipart.abort.ajax.requester.js",
"chars": 4869,
"preview": "/*globals qq */\n/**\n * Ajax requester used to send an [\"Abort Multipart Upload\"](http://docs.aws.amazon.com/AmazonS3/lat"
},
{
"path": "client/js/s3/multipart.complete.ajax.requester.js",
"chars": 7624,
"preview": "/*globals qq*/\n/**\n * Ajax requester used to send an [\"Complete Multipart Upload\"](http://docs.aws.amazon.com/AmazonS3/l"
},
{
"path": "client/js/s3/multipart.initiate.ajax.requester.js",
"chars": 7326,
"preview": "/*globals qq*/\n/**\n * Ajax requester used to send an [\"Initiate Multipart Upload\"](http://docs.aws.amazon.com/AmazonS3/l"
},
{
"path": "client/js/s3/request-signer.js",
"chars": 27103,
"preview": "/* globals qq, CryptoJS */\n\n// IE 10 does not support Uint8ClampedArray. We don't need it, but CryptoJS attempts to refe"
},
{
"path": "client/js/s3/s3.form.upload.handler.js",
"chars": 9046,
"preview": "/*globals qq */\n/**\n * Upload handler used by the upload to S3 module that assumes the current user agent does not have "
},
{
"path": "client/js/s3/s3.xhr.upload.handler.js",
"chars": 25952,
"preview": "/*globals qq */\n/**\n * Upload handler used by the upload to S3 module that depends on File API support, and, therefore, "
},
{
"path": "client/js/s3/uploader.basic.js",
"chars": 17389,
"preview": "/*globals qq */\n/**\n * This defines FineUploaderBasic mode w/ support for uploading to S3, which provides all the basic\n"
},
{
"path": "client/js/s3/uploader.js",
"chars": 1598,
"preview": "/*globals qq */\n/**\n * This defines FineUploader mode w/ support for uploading to S3, which provides all the basic\n * fu"
},
{
"path": "client/js/s3/util.js",
"chars": 21820,
"preview": "/*globals qq */\nqq.s3 = qq.s3 || {};\n\nqq.s3.util = qq.s3.util || (function() {\n \"use strict\";\n\n return {\n A"
},
{
"path": "client/js/session.ajax.requester.js",
"chars": 1953,
"preview": "/*globals qq, XMLHttpRequest*/\n/**\n * Thin module used to send GET requests to the server, expecting information about s"
},
{
"path": "client/js/session.js",
"chars": 2546,
"preview": "/* globals qq */\n/**\n * Module used to control populating the initial list of files.\n *\n * @constructor\n */\nqq.Session ="
},
{
"path": "client/js/templating.js",
"chars": 38472,
"preview": "/* globals qq */\n/* jshint -W065 */\n/**\n * Module responsible for rendering all Fine Uploader UI templates. This module"
},
{
"path": "client/js/third-party/ExifRestorer.js",
"chars": 5189,
"preview": "//Based on MinifyJpeg\n//http://elicon.blog57.fc2.com/blog-entry-206.html\n\nqq.ExifRestorer = (function()\n{\n \n\tvar ExifR"
},
{
"path": "client/js/third-party/crypto-js/core.js",
"chars": 20749,
"preview": "/*\nCryptoJS v3.1.2\ncode.google.com/p/crypto-js\n(c) 2009-2013 by Jeff Mott. All rights reserved.\ncode.google.com/p/crypto"
},
{
"path": "client/js/third-party/crypto-js/enc-base64.js",
"chars": 3341,
"preview": "/*\nCryptoJS v3.1.2\ncode.google.com/p/crypto-js\n(c) 2009-2013 by Jeff Mott. All rights reserved.\ncode.google.com/p/crypto"
},
{
"path": "client/js/third-party/crypto-js/hmac.js",
"chars": 3684,
"preview": "/*\nCryptoJS v3.1.2\ncode.google.com/p/crypto-js\n(c) 2009-2013 by Jeff Mott. All rights reserved.\ncode.google.com/p/crypto"
},
{
"path": "client/js/third-party/crypto-js/lib-typedarrays.js",
"chars": 1972,
"preview": "/*\r\nCryptoJS v3.1.2\r\ncode.google.com/p/crypto-js\r\n(c) 2009-2013 by Jeff Mott. All rights reserved.\r\ncode.google.com/p/cr"
},
{
"path": "client/js/third-party/crypto-js/sha1.js",
"chars": 3735,
"preview": "/*\nCryptoJS v3.1.2\ncode.google.com/p/crypto-js\n(c) 2009-2013 by Jeff Mott. All rights reserved.\ncode.google.com/p/crypto"
},
{
"path": "client/js/third-party/crypto-js/sha256.js",
"chars": 5355,
"preview": "/*\r\nCryptoJS v3.1.2\r\ncode.google.com/p/crypto-js\r\n(c) 2009-2013 by Jeff Mott. All rights reserved.\r\ncode.google.com/p/cr"
},
{
"path": "client/js/total-progress.js",
"chars": 4320,
"preview": "/* globals qq */\n/**\n * Keeps a running tally of total upload progress for a batch of files.\n *\n * @param callback Invok"
},
{
"path": "client/js/traditional/all-chunks-done.ajax.requester.js",
"chars": 2083,
"preview": "/*globals qq*/\n/**\n * Ajax requester used to send a POST to a traditional endpoint once all chunks for a specific file h"
},
{
"path": "client/js/traditional/traditional.form.upload.handler.js",
"chars": 3686,
"preview": "/*globals qq*/\n/**\n * Upload handler used that assumes the current user agent does not have any support for the\n * File "
},
{
"path": "client/js/traditional/traditional.xhr.upload.handler.js",
"chars": 10931,
"preview": "/*globals qq*/\n/**\n * Upload handler used to upload to traditional endpoints. It depends on File API support, and, ther"
},
{
"path": "client/js/ui.handler.click.filebuttons.js",
"chars": 1674,
"preview": "/* global qq */\nqq.FileButtonsClickHandler = function(s) {\n \"use strict\";\n\n var inheritedInternalApi = {},\n "
},
{
"path": "client/js/ui.handler.click.filename.js",
"chars": 1499,
"preview": "/*globals qq */\n// Child of FilenameEditHandler. Used to detect click events on filename display elements.\nqq.FilenameC"
},
{
"path": "client/js/ui.handler.edit.filename.js",
"chars": 2942,
"preview": "/*globals qq */\n// Handles edit-related events on a file item (FineUploader mode). This is meant to be a parent handler"
},
{
"path": "client/js/ui.handler.events.js",
"chars": 1514,
"preview": "/*globals qq */\n// Base handler for UI (FineUploader mode) events.\n// Some more specific handlers inherit from this one."
},
{
"path": "client/js/ui.handler.focus.filenameinput.js",
"chars": 499,
"preview": "/*globals qq */\n/**\n * Child of FilenameInputFocusInHandler. Used to detect focus events on file edit input elements. "
},
{
"path": "client/js/ui.handler.focusin.filenameinput.js",
"chars": 1213,
"preview": "/*globals qq */\n// Child of FilenameEditHandler. Used to detect focusin events on file edit input elements.\nqq.Filename"
},
{
"path": "client/js/upload-data.js",
"chars": 6307,
"preview": "/*globals qq */\nqq.UploadData = function(uploaderProxy) {\n \"use strict\";\n\n var data = [],\n byUuid = {},\n "
},
{
"path": "client/js/upload-handler/form.upload.handler.js",
"chars": 11378,
"preview": "/* globals qq */\n/**\n * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly"
},
{
"path": "client/js/upload-handler/upload.handler.controller.js",
"chars": 32761,
"preview": "/*globals qq*/\n/**\n * Base upload handler module. Controls more specific handlers.\n *\n * @param o Options. Passed alon"
},
{
"path": "client/js/upload-handler/upload.handler.js",
"chars": 1527,
"preview": "/* globals qq */\n/**\n * Common upload handler functions.\n *\n * @constructor\n */\nqq.UploadHandler = function(spec) {\n "
},
{
"path": "client/js/upload-handler/xhr.upload.handler.js",
"chars": 20779,
"preview": "/* globals qq */\n/**\n * Common API exposed to creators of XHR handlers. This is reused and possibly overriding in some "
},
{
"path": "client/js/uploader.api.js",
"chars": 26805,
"preview": "/*globals qq */\n/**\n * Defines the public API for FineUploader mode.\n */\n(function() {\n \"use strict\";\n\n qq.uiPubli"
},
{
"path": "client/js/uploader.basic.api.js",
"chars": 76191,
"preview": "/*globals qq*/\n/**\n * Defines the public API for FineUploaderBasic mode.\n */\n(function() {\n \"use strict\";\n\n qq.bas"
},
{
"path": "client/js/uploader.basic.js",
"chars": 12180,
"preview": "/*globals qq*/\n(function() {\n \"use strict\";\n\n qq.FineUploaderBasic = function(o) {\n var self = this;\n\n "
},
{
"path": "client/js/uploader.js",
"chars": 6427,
"preview": "/*globals qq */\n/**\n * This defines FineUploader mode, which is a default UI w/ drag & drop uploading.\n */\nqq.FineUpload"
},
{
"path": "client/js/uploadsuccess.ajax.requester.js",
"chars": 4286,
"preview": "/*globals qq, XMLHttpRequest*/\n/**\n * Sends a POST request to the server to notify it of a successful upload to an endpo"
},
{
"path": "client/js/util.js",
"chars": 28461,
"preview": "/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest, Blob, Storage, ActiveXObject */"
},
{
"path": "client/js/version.js",
"chars": 38,
"preview": "/*global qq */\nqq.version = \"5.16.2\";\n"
},
{
"path": "client/js/window.receive.message.js",
"chars": 980,
"preview": "/*globals qq */\n/*jshint -W117 */\nqq.WindowReceiveMessage = function(o) {\n \"use strict\";\n\n var options = {\n "
},
{
"path": "client/typescript/fine-uploader.d.ts",
"chars": 125664,
"preview": "// Type definitions for FineUploader 5.x.x\n// Project: http://fineuploader.com/\n// Definitions by: Sukhdeep Singh <https"
},
{
"path": "client/typescript/fine-uploader.test.ts",
"chars": 2599,
"preview": "import { FineUploader, UIOptions } from 'fine-uploader';\nimport { s3 } from 'fine-uploader/lib/s3';\nimport { azure } fro"
},
{
"path": "config/karma.conf.js",
"chars": 1369,
"preview": "/* jshint node: true */\nvar path = require(\"path\");\n\nmodule.exports = function(config, options) {\n \"use strict\";\n\n "
},
{
"path": "docs/_static/css/main.css",
"chars": 5775,
"preview": "\n/* ==========================================================================\n Author's custom styles\n ============"
},
{
"path": "docs/_static/css/pygments.css",
"chars": 3732,
"preview": ".hll { background-color: #ffffcc }\n.c { color: #8f5902; font-style: italic } /* Comment */\n.err { color: #a40000; border"
},
{
"path": "docs/_static/js/main.js",
"chars": 513,
"preview": "/**\n * Resize the dropdown-menu's to be 80% of the window height, and\n * add an overflow-y property so that all the elem"
},
{
"path": "docs/_static/js/navbar.js",
"chars": 295,
"preview": "(function() {\n document.querySelector('.tag-chooser').addEventListener('submit', function(event) {\n event.prev"
},
{
"path": "docs/_static/js/sidebar.js",
"chars": 2311,
"preview": "var renderSidebarNav = function(type, headers) {\n var $sidebar = $(\".sidebar .accordion\"),\n sidebarContents = "
},
{
"path": "docs/_templates/api.html",
"chars": 239,
"preview": "{% from \"_templates/macros/code.html\" import options_table, events_table, methods_table, code_table %}\n{% from \"_templat"
},
{
"path": "docs/_templates/base.html",
"chars": 367,
"preview": "{% from \"_templates/macros/code.html\" import options_table, events_table, methods_table, code_table, api_method, api_par"
},
{
"path": "docs/_templates/feature.html",
"chars": 241,
"preview": "{% from \"_templates/macros/code.html\" import options_table, events_table, methods_table, code_table %}\n{% from \"_templat"
},
{
"path": "docs/_templates/footer.html",
"chars": 0,
"preview": ""
},
{
"path": "docs/_templates/layout.html",
"chars": 4992,
"preview": "<!DOCTYPE html>\n<!--[if IE 8]> <html class=\"no-js lt-ie9\" lang=\"en\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html c"
},
{
"path": "docs/_templates/macros/alerts.html",
"chars": 1116,
"preview": "{% macro alert(content, type=\"info\", alert_header=\"Note\", close_button=False) -%}\n{# type can be success, error (or dang"
},
{
"path": "docs/_templates/macros/code.html",
"chars": 9979,
"preview": "{#\n Tables\n#}\n{% macro code_table(headings, rows, title=None) -%}\n{% if title %}\n<h2>{{ title }}</h2>\n{% endif %}\n<ta"
},
{
"path": "docs/_templates/macros/github.html",
"chars": 128,
"preview": "{% macro issue(num) -%}\n<a href=\"https://github.com/FineUploader/fine-uploader/issues/{{ num }}\">#{{ num }}</a>\n{%- endm"
},
{
"path": "docs/_templates/navbar.html",
"chars": 12000,
"preview": "<div class=\"navbar navbar-inverse navbar-fixed-top\">\n <div class=\"navbar-inner\">\n <div class=\"container\">\n\n "
},
{
"path": "docs/api/events-s3.jmd",
"chars": 1547,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"S3 Methods\" %}\n\n{% block sidebar %}\n<div id=\"sidebar-accordion"
},
{
"path": "docs/api/events.jmd",
"chars": 20243,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Events\" %}\n{% block title %}Events - Fine Uploader Documentati"
},
{
"path": "docs/api/methods-azure.jmd",
"chars": 3717,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Azure Methods\" %}\n\n{% block sidebar %}\n<div id=\"sidebar-accord"
},
{
"path": "docs/api/methods-s3.jmd",
"chars": 5263,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"S3 Methods\" %}\n\n{% block sidebar %}\n<div id=\"sidebar-accordion"
},
{
"path": "docs/api/methods.jmd",
"chars": 21983,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Methods\" %}\n\n{% block title %}Methods - Fine Uploader Document"
},
{
"path": "docs/api/options-azure.jmd",
"chars": 4753,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Azure Options\" %}\n\n{% block sidebar %}\n<div id=\"sidebar-accord"
},
{
"path": "docs/api/options-s3.jmd",
"chars": 8021,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"S3 Options\" %}\n\n{% block sidebar %}\n<div id=\"sidebar-accordion"
},
{
"path": "docs/api/options-ui.jmd",
"chars": 11043,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"UI Options\" %}\n\n{% block sidebar %}\n<div id=\"sidebar-accordion"
},
{
"path": "docs/api/options.jmd",
"chars": 24917,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Core Options\" %}\n\n{% block sidebar %}\n<div id=\"sidebar-accordi"
},
{
"path": "docs/api/qq.jmd",
"chars": 12195,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"qq API\" %}\n{% block content %}\n{% markdown %}\n\n# Utilities {: "
},
{
"path": "docs/browser-support.jmd",
"chars": 24528,
"preview": "{% extends \"_templates/base.html\" %}\n{% block content %}\n{% markdown %}\n\n# Browser Support {: .page-header }\n\nCurrently,"
},
{
"path": "docs/endpoint_handlers/amazon-s3.jmd",
"chars": 16566,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"S3 Endpoint\" %}\n{% block content %}\n{% markdown %}\n\n[s3-canoni"
},
{
"path": "docs/endpoint_handlers/azure.jmd",
"chars": 7829,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Azure Endpoint\" %}\n{% block content %}\n{% markdown %}\n\n[scalin"
},
{
"path": "docs/endpoint_handlers/traditional.jmd",
"chars": 9358,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Traditional Endpoint\" %}\n{% block content %}\n{% markdown %}\n\n["
},
{
"path": "docs/faq.jmd",
"chars": 6062,
"preview": "{% extends \"_templates/base.html\" %}\n{% block content %}\n{% markdown %}\n## Frequently Asked Questions (FAQ)\n\n**Q**: Are "
},
{
"path": "docs/features/CORS.jmd",
"chars": 4444,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"CORS\" %}\n{% block sidebar %}\n{{ api_links(options=['cors']) }}"
},
{
"path": "docs/features/async-tasks-and-promises.jmd",
"chars": 6736,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Async Tasks and Promises\" %}\n{% block content %}\n{% markdown %"
},
{
"path": "docs/features/azure.jmd",
"chars": 5113,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Uploading Directly to Azure Blob Storage\" %}\n{% block sidebar "
},
{
"path": "docs/features/cancellable-uploads.jmd",
"chars": 850,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Cancellable Uploads\" %}\n{% block sidebar %}\n{{ api_links(None,"
},
{
"path": "docs/features/chunking.jmd",
"chars": 4100,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Chunking\" %}\n{% block sidebar %}\n{{ api_links(['chunking'], No"
},
{
"path": "docs/features/concurrent-chunking.jmd",
"chars": 5017,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Concurrent Chunking\" %}\n{% block sidebar %}\n{{ api_links(['chu"
},
{
"path": "docs/features/delete.jmd",
"chars": 4466,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Deleting Files\" %}\n{% block sidebar %}\n{{ api_links(['deleteFi"
},
{
"path": "docs/features/drag-and-drop.jmd",
"chars": 5704,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Drag and Drop\" %}\n{% block sidebar %}\n{{ api_links(options=['d"
},
{
"path": "docs/features/extra-buttons.jmd",
"chars": 6806,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Multiple Upload Buttons\" %}\n{% block sidebar %}\n{{ api_links(o"
},
{
"path": "docs/features/filename-edit.jmd",
"chars": 4031,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Editing Filenames\" %}\n{% block sidebar %}\n{{ api_links(['getNa"
},
{
"path": "docs/features/forms.jmd",
"chars": 10181,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Support for Forms\" %}\n{% block sidebar %}\n{{ api_links(options"
},
{
"path": "docs/features/handling-errors.jmd",
"chars": 4123,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Handling Errors\" %}\n{% block sidebar %}\n{{ api_links(['message"
},
{
"path": "docs/features/modules.jmd",
"chars": 10936,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Importing Fine Uploader\" %}\n{% block content %}\n{% markdown %}"
},
{
"path": "docs/features/no-server-uploads.jmd",
"chars": 3158,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"No-Server Uploads\" %}\n{% block sidebar %}\n{{ api_links(options"
},
{
"path": "docs/features/paste-to-upload.jmd",
"chars": 3041,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Paste to Upload\" %}\n{% block sidebar %}\n{{ api_links(options=["
},
{
"path": "docs/features/pause.jmd",
"chars": 3579,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Pause In-Progress Uploads\" %}\n{% block sidebar %}\n{{ api_links"
},
{
"path": "docs/features/progress-bars.jmd",
"chars": 3321,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Progress Bars\" %}\n{% block sidebar %}\n{{ api_links(events=['pr"
},
{
"path": "docs/features/request-parameters.jmd",
"chars": 3949,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Request Parameters\" %}\n{% block sidebar %}\n{{ api_links(option"
},
{
"path": "docs/features/resume.jmd",
"chars": 3958,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Resume\" %}\n{% block sidebar %}\n{{ api_links(options=['resume']"
},
{
"path": "docs/features/retry.jmd",
"chars": 703,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Retrying Uploads\" %}\n{% block sidebar %}\n{{ api_links(options="
},
{
"path": "docs/features/s3.jmd",
"chars": 4713,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Uploading Directly to Amazon S3\" %}\n{% block sidebar %}\n{% end"
},
{
"path": "docs/features/scaling.jmd",
"chars": 12167,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Upload Scaled Images\" %}\n{% block sidebar %}\n{{ api_links(opti"
},
{
"path": "docs/features/session.jmd",
"chars": 4331,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Initial File List\" %}\n{% block sidebar %}\n{{ api_links(options"
},
{
"path": "docs/features/statistics-and-status-updates.jmd",
"chars": 5473,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Statistics and Status Updates\" %}\n{% block sidebar %}\n{{ api_l"
},
{
"path": "docs/features/styling.jmd",
"chars": 14417,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Styling\" %}\n{% block sidebar %}\n{{ api_links(options=['message"
},
{
"path": "docs/features/thumbnails.jmd",
"chars": 15026,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Previews & Thumbnails\" %}\n{% block sidebar %}\n{{ api_links(opt"
},
{
"path": "docs/features/upload-files.jmd",
"chars": 2418,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Upload Files\" %}\n{% block sidebar %}\n{{ api_links(options=['re"
},
{
"path": "docs/features/upload-from-mobile-camera.jmd",
"chars": 2417,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Upload From Mobile Camera\" %}\n{% block sidebar %}\n{{ api_links"
},
{
"path": "docs/features/validation.jmd",
"chars": 3170,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Validation\" %}\n{% block sidebar %}\n{{ api_links(options=['vali"
},
{
"path": "docs/index.jmd",
"chars": 3574,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Overview\" %}\n{% block content %}\n{% markdown %}\n\n{{ alert(\n\"\"\""
},
{
"path": "docs/integrating/jquery.jmd",
"chars": 6050,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"jQuery Plugin\" %}\n{% block content %}\n{% markdown %}\n\n[button]"
},
{
"path": "docs/modes/core.jmd",
"chars": 1091,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Core Mode\" %}\n{% block content %}\n{% markdown %}\n# Fine Upload"
},
{
"path": "docs/modes/ui.jmd",
"chars": 976,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"UI Mode\" %}\n{% block content %}\n{% markdown %}\n# Fine Uploader"
},
{
"path": "docs/quickstart/01-getting-started.jmd",
"chars": 43081,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Getting Started\" %}\n{% block content %}\n{% markdown %}\n# Getti"
},
{
"path": "docs/quickstart/02-setting_options-azure.jmd",
"chars": 8989,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Setting Options Azure\" %}\n{% block content %}\n{% markdown %}\n#"
},
{
"path": "docs/quickstart/02-setting_options-s3.jmd",
"chars": 8765,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Setting Options S3\" %}\n{% block content %}\n{% markdown %}\n# Se"
},
{
"path": "docs/quickstart/02-setting_options.jmd",
"chars": 8080,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Setting Options\" %}\n{% block content %}\n{% markdown %}\n# Setti"
},
{
"path": "docs/quickstart/03-setting_up_server-azure.jmd",
"chars": 592,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Server Set-Up Azure\" %}\n\n{% block content %}\n{% markdown %}\n# "
},
{
"path": "docs/quickstart/03-setting_up_server-s3.jmd",
"chars": 4729,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Server Set-Up S3\" %}\n\n{% block content %}\n{% markdown %}\n\n[blo"
},
{
"path": "docs/quickstart/03-setting_up_server.jmd",
"chars": 4312,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Server Set-Up\" %}\n\n{% block content %}\n{% markdown %}\n\n[compos"
},
{
"path": "docs/upgrading-to-4.jmd",
"chars": 8930,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Upgrading to 4.x\" %}\n{% block content %}\n{% markdown %}\n# Upgr"
},
{
"path": "docs/upgrading-to-5.jmd",
"chars": 5017,
"preview": "{% extends \"_templates/base.html\" %}\n{% set page_title = \"Upgrading to 5.x\" %}\n{% block content %}\n{% markdown %}\n# Upgr"
},
{
"path": "package.json",
"chars": 1590,
"preview": "{\n \"name\": \"fine-uploader\",\n \"title\": \"Fine Uploader\",\n \"main\": \"lib/traditional.js\",\n \"types\" : \"typescript/fine-up"
},
{
"path": "test/dev/devenv.js",
"chars": 8312,
"preview": "qq(window).attach(\"load\", function() {\n \"use strict\";\n\n var errorHandler = function(id, fileName, reason) {\n "
},
{
"path": "test/dev/handlers/composer.json",
"chars": 268,
"preview": "{\n \"minimum-stability\": \"alpha\",\n \"repositories\": [\n {\n \"type\": \"vcs\",\n \"url\": \"https://github.com/FineUp"
},
{
"path": "test/dev/handlers/php.ini",
"chars": 45,
"preview": "upload_max_filesize = 10M\npost_max_size = 10M"
},
{
"path": "test/dev/index.html",
"chars": 15606,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <!--GALLERY TEMPLATE-->\n <script type=\"text/template\" id=\"qq-template\">"
},
{
"path": "test/dev/styles.css",
"chars": 295,
"preview": "H1 {\n text-align: center;\n}\n\n#examples {\n padding-left: 10px;\n}\n\n.endingRemark {\n margin-top: 30px;\n}\n\nDIV.exam"
},
{
"path": "test/static/local/blob-maker.js",
"chars": 1835,
"preview": "/*globals qq, assert*/\nvar qqtest = qqtest || {};\n$.extend(qqtest, {\n canDownloadFileAsBlob: !qq.android() && qq.supp"
},
{
"path": "test/static/local/client.js",
"chars": 3696,
"preview": "/* globals mocha */\nfunction FancyJSON(runner) {\n \"use strict\";\n\n var root = null;\n var result = {};\n\n funct"
},
{
"path": "test/static/local/formdata.js",
"chars": 1524,
"preview": "/* globals assert, qq */\nfunction mockFormData() {\n \"use strict\";\n\n function FormData() {\n this.fake = true"
},
{
"path": "test/static/local/helpme.js",
"chars": 3287,
"preview": "/* global sinon:true */\n// The following is apparently required to mock XHR in some versions of IE\nfunction XMLHttpReque"
},
{
"path": "test/static/local/karma-runner.js",
"chars": 2189,
"preview": "/* globals assert, qq, before, beforeEach, afterEach */\nvar $fixture;\n\n(function() {\n \"use strict\";\n\n qq.override("
},
{
"path": "test/static/third-party/assert/assert.js",
"chars": 13312,
"preview": "// http://wiki.commonjs.org/wiki/Unit_Testing/1.0\n//\n// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!\n//\n// Copyrigh"
},
{
"path": "test/static/third-party/jquery/jquery.js",
"chars": 273808,
"preview": "/*!\n * jQuery JavaScript Library v1.10.0\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Co"
},
{
"path": "test/static/third-party/jquery.simulate/jquery.simulate.js",
"chars": 7937,
"preview": " /*!\n * jQuery Simulate v@VERSION - simulate browser mouse and keyboard events\n * https://github.com/jquery/jquery-simul"
},
{
"path": "test/static/third-party/json2/README",
"chars": 1653,
"preview": "JSON in JavaScript\n\n\nDouglas Crockford\ndouglas@crockford.com\n\n2010-11-18\n\n\nJSON is a light-weight, language independent,"
},
{
"path": "test/static/third-party/json2/cycle.js",
"chars": 6214,
"preview": "/*\n cycle.js\n 2013-02-19\n\n Public Domain.\n\n NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\n Thi"
},
{
"path": "test/static/third-party/json2/json.js",
"chars": 19728,
"preview": "/*\n json.js\n 2014-02-04\n\n Public Domain\n\n No warranty expressed or implied. Use at your own risk.\n\n This "
},
{
"path": "test/static/third-party/json2/json2.js",
"chars": 17569,
"preview": "/*\n json2.js\n 2014-02-04\n\n Public Domain.\n\n NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\n See"
},
{
"path": "test/static/third-party/json2/json_parse.js",
"chars": 9884,
"preview": "/*\n json_parse.js\n 2012-06-20\n\n Public Domain.\n\n NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\n "
},
{
"path": "test/static/third-party/json2/json_parse_state.js",
"chars": 13758,
"preview": "/*\n json_parse_state.js\n 2013-05-26\n\n Public Domain.\n\n NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RIS"
},
{
"path": "test/static/third-party/mocha/css/mocha.css",
"chars": 3813,
"preview": "@charset \"utf-8\";\n\nbody {\n margin:0;\n}\n\n#mocha {\n font: 20px/1.5 \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n mar"
}
]
// ... and 46 more files (download for full content)
About this extraction
This page contains the full source code of the FineUploader/fine-uploader GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 246 files (2.3 MB), approximately 625.1k tokens, and a symbol index with 567 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.