Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

* clean project

  • Loading branch information...
commit 76c6631510adfd59b9d1cc795d002a3518d92976 2 parents 3a5c7db + 469521b
@RubaXa RubaXa authored
Showing with 27,315 additions and 1,020 deletions.
  1. +1 −0  .gitignore
  2. +118 −0 Gruntfile.js
  3. +1,039 −500 README.md
  4. +1,166 −0 README.ru.md
  5. +2 −0  crossdomain.xml
  6. BIN  dist/FileAPI.flash.camera.swf
  7. BIN  dist/FileAPI.flash.image.swf
  8. BIN  dist/FileAPI.flash.swf
  9. +2,986 −0 dist/FileAPI.html5.js
  10. +2 −0  dist/FileAPI.html5.min.js
  11. +3,847 −0 dist/FileAPI.js
  12. +3 −0  dist/FileAPI.min.js
  13. +2 −0  dist/jquery.fileapi.min.js
  14. +275 −0 examples/caman.html
  15. +554 −0 examples/demo.html
  16. +26 −10 example.userpic.html → examples/userpic.html
  17. +261 −0 examples/watermark.html
  18. +128 −0 examples/webcam.html
  19. +19 −0 flash/.gitignore
  20. +3 −0  flash/camera/.settings/org.eclipse.core.resources.prefs
  21. +6 −0 flash/camera/html-template/history/history.css
  22. +678 −0 flash/camera/html-template/history/history.js
  23. +29 −0 flash/camera/html-template/history/historyFrame.html
  24. +108 −0 flash/camera/html-template/index.template.html
  25. BIN  flash/camera/html-template/playerProductInstall.swf
  26. +777 −0 flash/camera/html-template/swfobject.js
  27. +125 −0 flash/camera/src/FileAPI_flash_camera.as
  28. +3 −0  flash/core/.settings/org.eclipse.core.resources.prefs
  29. +6 −0 flash/core/html-template/history/history.css
  30. +678 −0 flash/core/html-template/history/history.js
  31. +29 −0 flash/core/html-template/history/historyFrame.html
  32. +108 −0 flash/core/html-template/index.template.html
  33. BIN  flash/core/html-template/playerProductInstall.swf
  34. +777 −0 flash/core/html-template/swfobject.js
  35. BIN  flash/core/lib/EnginesLibrary.swc
  36. BIN  flash/core/lib/blooddy_crypto.swc
  37. +69 −0 flash/core/src/FileAPI_flash.as
  38. +589 −0 flash/core/src/net/inspirit/MultipartURLLoader.as
  39. +27 −0 flash/core/src/net/inspirit/events/MultipartURLLoaderEvent.as
  40. +88 −0 flash/core/src/ru/mail/commands/AbstractUploadFileCommand.as
  41. +127 −0 flash/core/src/ru/mail/commands/DecodeBytesToBitmapCommand.as
  42. +117 −0 flash/core/src/ru/mail/commands/LoadFileCommand.as
  43. +281 −0 flash/core/src/ru/mail/commands/ResizeFileCommand.as
  44. +222 −0 flash/core/src/ru/mail/commands/UploadCommand.as
  45. +133 −0 flash/core/src/ru/mail/commands/UploadFileCommand.as
  46. +164 −0 flash/core/src/ru/mail/commands/UploadImageCommand.as
  47. +14 −0 flash/core/src/ru/mail/commands/graphicloader/IGraphicLoader.as
  48. +100 −0 flash/core/src/ru/mail/commands/graphicloader/SimpleGraphicLoader.as
  49. +40 −0 flash/core/src/ru/mail/commands/graphicloader/events/GraphicLoaderCompleteEvent.as
  50. +13 −0 flash/core/src/ru/mail/commands/textloader/ITextLoader.as
  51. +66 −0 flash/core/src/ru/mail/commands/textloader/SimpleTextLoader.as
  52. +29 −0 flash/core/src/ru/mail/commands/textloader/events/LoaderProgressEvent.as
  53. +38 −0 flash/core/src/ru/mail/commands/textloader/events/TextLoaderCompleteEvent.as
  54. +137 −0 flash/core/src/ru/mail/communication/JSCallbackPresenter.as
  55. +234 −0 flash/core/src/ru/mail/communication/JSCaller.as
  56. +765 −0 flash/core/src/ru/mail/controller/AppController.as
  57. +124 −0 flash/core/src/ru/mail/controller/CameraController.as
  58. +29 −0 flash/core/src/ru/mail/data/AbstractImageFactory.as
  59. +167 −0 flash/core/src/ru/mail/data/AttachmentsModel.as
  60. +28 −0 flash/core/src/ru/mail/data/IImageFactory.as
  61. +260 −0 flash/core/src/ru/mail/data/ImageFactory.as
  62. +206 −0 flash/core/src/ru/mail/data/builder/AbstractDataBuilder.as
  63. +110 −0 flash/core/src/ru/mail/data/builder/FilesDataBuilder.as
  64. +64 −0 flash/core/src/ru/mail/data/vo/BaseFileVO.as
  65. +51 −0 flash/core/src/ru/mail/data/vo/ErrorVO.as
  66. +63 −0 flash/core/src/ru/mail/data/vo/FakeFileVO.as
  67. +17 −0 flash/core/src/ru/mail/data/vo/FileStatesEnum.as
  68. +87 −0 flash/core/src/ru/mail/data/vo/FileVO.as
  69. +29 −0 flash/core/src/ru/mail/data/vo/IFileVO.as
  70. +70 −0 flash/core/src/ru/mail/data/vo/ImageTransformVO.as
  71. +55 −0 flash/core/src/ru/mail/data/vo/OverlayVO.as
  72. +61 −0 flash/core/src/ru/mail/data/vo/PhotoFileVO.as
  73. +47 −0 flash/core/src/ru/mail/engines/chain/AbstractModelJSEngine.as
  74. +42 −0 flash/core/src/ru/mail/engines/chain/EnginesFactory.as
  75. +15 −0 flash/core/src/ru/mail/engines/chain/IJsCallerHolder.as
  76. +15 −0 flash/core/src/ru/mail/engines/chain/IModelHolder.as
  77. +165 −0 flash/core/src/ru/mail/engines/chain/manage/SelectFilesEngine.as
  78. +105 −0 flash/core/src/ru/mail/engines/chain/presentation/MouseListenerEngine.as
  79. +36 −0 flash/core/src/ru/mail/engines/commands/MouseListenerEngineCommand.as
  80. +42 −0 flash/core/src/ru/mail/engines/commands/SelectFilesCommand.as
  81. +44 −0 flash/core/src/ru/mail/events/CompleteEvent.as
  82. +35 −0 flash/core/src/ru/mail/events/DecodeBytesToBitmapCompleteEvent.as
  83. +34 −0 flash/core/src/ru/mail/events/ImageTransformCompleteEvent.as
  84. +32 −0 flash/core/src/ru/mail/events/UploadCompleteEvent.as
  85. +564 −0 flash/core/src/ru/mail/utils/BMPDecoder.as
  86. +158 −0 flash/core/src/ru/mail/utils/ExifReader2.as
  87. +27 −0 flash/core/src/ru/mail/utils/LoggerJS.as
  88. +3 −0  flash/image/.settings/org.eclipse.core.resources.prefs
  89. +6 −0 flash/image/html-template/history/history.css
  90. +697 −0 flash/image/html-template/history/history.js
  91. +29 −0 flash/image/html-template/history/historyFrame.html
  92. +108 −0 flash/image/html-template/index.template.html
  93. BIN  flash/image/html-template/playerProductInstall.swf
  94. +777 −0 flash/image/html-template/swfobject.js
  95. BIN  flash/image/lib/blooddy_crypto.swc
  96. +76 −0 flash/image/src/Base64.as
  97. +95 −0 flash/image/src/FileAPI_flash_image.as
  98. +213 −510 index.html
  99. +244 −0 lib/FileAPI.Camera.js
  100. +860 −0 lib/FileAPI.Flash.js
  101. +214 −0 lib/FileAPI.Form.js
  102. +451 −0 lib/FileAPI.Image.js
  103. +313 −0 lib/FileAPI.XHR.js
  104. +1,668 −0 lib/FileAPI.core.js
  105. +86 −0 lib/canvas-to-blob.js
  106. +38 −0 package.json
  107. +59 −0 plugins/FileAPI.exif.js
  108. +67 −0 plugins/FileAPI.id3.js
  109. +217 −0 plugins/caman.full.min.js
  110. +174 −0 plugins/caman.min.js
  111. +966 −0 plugins/jquery.fileapi.js
  112. +84 −0 server/FileAPI.class.php
  113. +79 −0 server/ctrl.php
  114. BIN  statics/body.png
  115. BIN  statics/body__top.png
  116. BIN  statics/content.png
Sorry, we could not display the entire diff because it was too big.
View
1  .gitignore
@@ -0,0 +1 @@
+node_modules
View
118 Gruntfile.js
@@ -0,0 +1,118 @@
+'use strict';
+
+module.exports = function (grunt){
+ // Project configuration.
+ grunt.initConfig({
+ pkg: grunt.file.readJSON('package.json'),
+
+ jshint: {
+ all: [
+ 'Gruntfile.js'
+ , 'lib/**/*.js'
+ , 'plugins/jquery.fileapi.js'
+ ],
+
+ options: {
+ curly: true // + "Expected '{' and instead saw 'XXXX'."
+ , immed: true
+ , latedef: true
+ , newcap: true // "Tolerate uncapitalized constructors"
+ , noarg: true
+ , sub: true
+ , undef: true
+ , unused: true
+ , boss: true
+ , eqnull: true
+
+ , node: true
+ , es5: true
+ , expr: true // - "Expected an assignment or function call and instead saw an expression."
+ , supernew: true // - "Missing '()' invoking a constructor."
+ , laxcomma: true
+ , laxbreak: true
+ , smarttabs: true
+ }
+ },
+
+ qunit: {
+ options: {
+ files: {
+ '1px.gif': ['tests/files/1px.gif']
+ , 'hello.txt': ['tests/files/hello.txt']
+ , 'image.jpg': ['tests/files/image.jpg']
+ , 'dino.png': ['tests/files/dino.png']
+ , 'multiple': ['tests/files/1px.gif', 'tests/files/hello.txt', 'tests/files/image.jpg', 'tests/files/dino.png', 'tests/files/lebowski.json']
+ }
+ },
+ all: ['tests/*.html']
+ },
+
+ concat: {
+ options: {
+ banner: '/*! <%= pkg.name %> <%= pkg.version %> - <%= pkg.license %> | <%= pkg.repository.url %>\n' +
+ ' * <%= pkg.description %>\n' +
+ ' */\n\n',
+
+ footer: 'if( typeof define === "function" && define.amd ){ define("FileAPI", [], function (){ return FileAPI; }); }'
+ },
+
+ all: {
+ src: [
+ 'lib/canvas-to-blob.js'
+ , 'lib/FileAPI.core.js'
+ , 'lib/FileAPI.Image.js'
+ , 'lib/FileAPI.Form.js'
+ , 'lib/FileAPI.XHR.js'
+ , 'lib/FileAPI.Camera.js'
+ , 'lib/FileAPI.Flash.js'
+ ],
+ dest: 'dist/<%= pkg.name %>.js'
+ },
+
+ html5: {
+ src: [
+ 'lib/canvas-to-blob.js'
+ , 'lib/FileAPI.core.js'
+ , 'lib/FileAPI.Image.js'
+ , 'lib/FileAPI.Form.js'
+ , 'lib/FileAPI.XHR.js'
+ , 'lib/FileAPI.Camera.js'
+ ],
+ dest: 'dist/<%= pkg.name %>.html5.js'
+ }
+ },
+
+ uglify: {
+ options: { banner: '/*! <%= pkg.name %> <%= pkg.version %> - <%= pkg.license %> | <%= pkg.repository.url %> */\n' },
+ dist: {
+ files: {
+ 'dist/<%= pkg.name %>.min.js': ['<%= concat.all.dest %>']
+ , 'dist/<%= pkg.name %>.html5.min.js': ['<%= concat.html5.dest %>']
+ , 'dist/jquery.fileapi.min.js': ['plugins/jquery.fileapi.js']
+ }
+ }
+ },
+
+ watch: {
+ scripts: {
+ files: 'lib/**/*.js',
+ tasks: ['concat'],
+ options: { interrupt: true }
+ }
+ }
+ });
+
+
+ // These plugins provide necessary tasks.
+ grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.loadNpmTasks('grunt-contrib-concat');
+ grunt.loadNpmTasks('grunt-contrib-uglify');
+ grunt.loadNpmTasks('grunt-contrib-watch');
+
+ // Load custom QUnit task, based on grunt-contrib-qunit, but support "files" option.
+ grunt.loadTasks('./tests/grunt-task/');
+
+ // "npm build" runs these tasks
+ grunt.registerTask('build', ['concat', 'uglify', 'qunit']);
+ grunt.registerTask('default', ['jshint', 'build']);
+};
View
1,539 README.md
@@ -1,236 +1,181 @@
-# FileAPI — a set of tools for working with files.
+<a name="install" data-name="Installation"></a>
+## Installation, testing, assembling
+`npm install fileapi`<br/>
+`cd fileapi`<br/>
+`npm install`<br/>
+`grunt`
-<p align="center">
- ~~~ <a href="http://mailru.github.com/FileAPI/">DEMO</a>
- ~~~ <a href="http://mailru.github.com/FileAPI/example.userpic.html">user pic</a>
- ~~~
-</p>
-
+---
-## Support
- * Multiupload: all browsers that support HTML5 or [Flash](#flash-settings)
- * Drag'n'Drop upload: files (HTML5) & directories (Chrome 21+)
- * [Chunked](#chunked) file upload (HTML5)
- * Upload one file: all browsers
- * Working with [Images](#images): IE6+, FF 3.6+, Chrome 10+, Opera 11.1+, Safari 5.4+
- + crop, resize, preview & rotate (HTML5 or Flash)
- + auto orientation by exif (HTML5, if include FileAPI.exif.js or Flash)
+<a name="FileAPI"></a>
+## FileAPI
+A set of javascript tools for working with files.
+<a name="FileAPI.setup"></a>
+### Setup
+Connecting the library to your project.
+If you need a CORS, then edit the `crossdomain.xml` and put it in the root of remote domain.
-## Example
```html
-<span class="js-fileapi-wrapper" style="position: relative;">
- <input id="user-files" type="file" multiple />
-</span>
-
-<div id="preview-list">
-</div>
-```
-```js
-var input = document.getElementById('user-files');
-var previewNode = document.getElementById('preview-list');
-
-// Drag'n'Drop
-FileAPI.event.dnd(previewNode, function (over){
- $(this).css('background', over ? 'red' : '');
-}, function (files){
- // ..
-});
-
-
+ <script>
+ window.FileAPI = {
+ debug: false // debug mode, see Console
+ , cors: true // if used CORS
+ , staticPath: '/js/FileAPI/dist/' // path to '*.swf'
+ };
+ </script>
+ <script src="/js/FileAPI/dist/FileAPI.min.js"></script>
-FileAPI.event.on(input, 'change', function (evt){
- var files = FileAPI.getFiles(evt.target); // or FileAPI.getFiles(evt)
+ <!-- OR -->
- // filtering
- FileAPI.filterFiles(files, function (file, info){
- if( /image/.test(file.type) && info ){
- return info.width >= 320 && info.height >= 240;
- }
- else {
- return file.size > 128;
- }
- }, function (fileList, ignor){
- if( ignor.length ){
+ <script>
+ window.FileAPI = { /* options */ };
+ require(['FileAPI'], function (FileAPI){
// ...
- }
+ });
+ </script>
+```
- if( !fileList.length ){
- // empty file list
- return;
- }
+---
- // do preview
- var imageList = FileAPI.filter(fileList, function (file){ return /image/.test(file.type); });
- FileAPI.each(imageList, function (imageFile){
- FileAPI.Image(imageFile)
- .preview(100, 120)
- .get(function (err, image){
- if( err ){
- // ...
- }
- else {
- previewNode.appendChild(image);
- }
- })
- ;
- });
+<a name="FileAPI.getFiles"></a>
+### getFiles(input`:HTMLInputElement|Event|$.Event`)`:Array`
+Get files from `input` element or `event` object, also support `jQuery`.
+* input — `HTMLInputElement`, `change` and `drop` event, `jQuery` collection or `jQuery.Event`
- // upload on server
- var xhr = FileAPI.upload({
- url: '...',
- data: { foo: 'bar' }, // POST-data (iframe, flash, html5)
- headers: { 'x-header': '...' }, // request headers (html5)
- files: {
- files: FileAPI.filter(fileList, function (file){ return !/image/.test(file.type); }),
- pictures: imageList
- },
- imageTransform: {
- maxWidth: 1024,
- maxHeight: 768
- },
- imageAutoOrientation: true,
- fileprogress: function (evt){ // (flash, html5)
- var percent = evt.loaded/evt.total*100;
- // ...
- },
- progress: function (evt){ // (flash, html5)
- var percent = evt.loaded/evt.total*100;
- // ...
- },
- complete: function (err, xhr){
- // ...
- }
- });
- });
+```js
+var el = document.getElement('my-input');
+FileAPI.event.on(el, function (evt/**Event*/){
+ // Get files from input
+ var files = FileAPI.getFiles(el);
+
+ // or event
+ var files = FileAPI.getFiles(evt);
});
```
-### HTML structure (templates)
- * [Default](#html-default)
- * [Button](#html-button)
- * [Link](#html-link)
+---
-### API
-* FileAPI.[getFiles](#getFiles)(`source:HTMLInput|Event`)`:Array`
-* FileAPI.[getDropFiles](#getDropFiles)(`files:Array`, `callback:Function`)
-* FileAPI.[filterFiles](#filterFiles)(`files:Array`, `iterator:Function`, `complete:Function`)
-* FileAPI.[upload](#upload)(`options:Object`)`:XMLHttpRequest`
-* FileAPI.[getInfo](#getInfo)(`file:File`, `callback:Function`)
-* FileAPI.[readAsImage](#readAs)(`file:File`, `callback:function`)
-* FileAPI.[readAsDataURL](#readAs)(`file:File`, `callback:function`)
-* FileAPI.[readAsBinaryString](#readAs)(`file:File`, `callback:function`)
-* FileAPI.[readAsArrayBuffer](#readAs)(`file:File`, `callback:function`)
-* FileAPI.[readAsText](#readAs)(`file:File`, `callback:function`)
-* FileAPI.[readAsText](#readAs)(`file:File`, `encoding:String`, `callback:function`)
+<a name="FileAPI.getInfo"></a>
+### getInfo(file`:Object`, callback`:Function`)`:void`
+Get info of file (see also: FileAPI.addInfoReader).
+* file — file object (https://developer.mozilla.org/en-US/docs/DOM/File)
+* callback — function, called after collected info of file
-### Events
-* FileAPI.event.on(`el:HTMLElement`, `eventType:String`, `fn:Function`)
-* FileAPI.event.off(`el:HTMLElement`, `eventType:String`, `fn:Function`)
-* FileAPI.event.one(`el:HTMLElement`, `eventType:String`, `fn:Function`)
-* FileAPI.event.dnd(`el:HTMLElement`, `onHover:Function`, `onDrop:Function`)
-* jQuery('#el').dnd(onHover, onDrop)
+```js
+// Get info of image file (FileAPI.exif.js included)
+FileAPI.getInfo(file, function (err/**String*/, info/**Object*/){
+ if( !err ){
+ console.log(info); // { width: 800, height: 600, exif: {..} }
+ }
+});
+// Get info of mp3 file (FileAPI.id3.js included)
+FileAPI.getInfo(file, function (err/**String*/, info/**Object*/){
+ if( !err ){
+ console.log(info); // { title: "...", album: "...", artists: "...", ... }
+ }
+});
+```
-<a name="images"></a>
-### FileAPI.Image
-* .crop(width[, height])
-* .crop(x, y, width[, height])
-* .resize(width[, height])
-* .resize(width, height, `type:Enum(min,max,preview)`)
-* .preview(width[, height])
-* .rotate(deg)
-* .get(`fn:Function`)
+---
+<a name="FileAPI.filterFiles"></a>
+### filterFiles(files`:Array`, filter`:Function`, callback`:Function`)`:void`
+Filtering the list of files, with additional information about files.
+See also: FileAPI.getInfo and FileAPI.addInfoReader.
+* files — original list of files
+* filter — function, takes two arguments: `file` — the file itself, `info` — additional information.
+* callback — function: `list` — files that match the condition, `other` — all the rest.
-### Utils
-* FileAPI.KB
-* FileAPI.MB
-* FileAPI.GB
-* FileAPI.TB
-* FileAPI.support.`html5:Boolean`
-* FileAPI.support.`cors:Boolean`
-* FileAPI.support.`dnd:Boolean`
-* FileAPI.support.`flash:Boolean`
-* FileAPI.support.`canvas:Boolean`
-* FileAPI.support.`dataURI:Boolean`
-* FileAPI.support.`chunked:Boolean`
-* FileAPI.each(`obj:Object|Array`, `fn:function`, `context:Mixed`)
-* FileAPI.extend(`dst:Object`, `src:Object`)`:Object`
-* FileAPI.filter(`list:Array`, `iterator:Function`)`:Array`
-* FileAPI.isFile(`file:Mixed`)`:Boolean`
-* FileAPI.toBinaryString(`str:Base64`)`:String`
+```js
+// Get list of file
+var files = FileAPI.getFiles(input);
+// Filter the List
+FileAPI.filterFiles(files, function (file/**Object*/, info/**Object*/){
+ if( /^image/.test(file.type) && info ){
+ return info.width > 320 && info.height > 240;
+ } else {
+ return file.size < 20 * FileAPI.MB;
+ }
+}, function (list/**Array*/, other/**Array*/){
+ if( list.length ){
+ // ..
+ }
+});
+```
+---
----------------------------------------
+<a name="FileAPI.getDropFiles"></a>
+### getDropFiles(evt`:Event|$.Event`, callback`:Function`)`:void`
+Get a list of files, including directories.
+* evt — `drop` event
+* callback — function, takes one argument, a list of files
-<a name="getFiles"></a>
-### FileAPI.getFiles
```js
-FileAPI.event.on('#my-file-1', 'change', onSelect);
+FileAPI.event.on(document, 'drop', function (evt/**Event*/){
+ evt.preventDefault();
-// or jQuery
-$('#my-file-2').on('change', onSelect);
+ // Get a list of files
+ FileAPI.getDropFiles(evt, function (files/**Array*/){
+ // ...
+ });
+});
+```
-function onSelect(evt/**Event*/){
- // (1) extract fileList from event
- var files = FileAPI.getFiles(evt);
+---
- // (2) or so
- var files = FileAPI.getFiles(evt.target);
-}
-```
+<a name="FileAPI.upload"></a>
+### upload(opts`:Object`)`:XmlHttpRequest`
+Uploading files to the server. Returns XHR-like object.
+It is important to remember to correctly worked flash-transport server response body must not be empty,
+for example, you can pass, just text "ok".
+* opts — options object, see [Upload options](#options)
-<a name="getDropFiles"></a>
-### FileAPI.getDropFiles
```js
-function onDrop(evt){
- FileAPI.getDropFiles(evt, function (files){
- if( files.length ){
- // ...
+var el = document.getElementById('my-input');
+FileAPI.event.on(el, 'change', function (evt/**Event*/){
+ var files = FileAPI.getFiles(evt);
+ var xhr = FileAPI.upload({
+ url: 'http://rubaxa.org/FileAPI/server/ctrl.php',
+ files: { file: files[0] },
+ complete: function (err, xhr){
+ if( !err ){
+ var result = xhr.responseText;
+ // ...
+ }
}
});
-}
-
-// OR
-
-var el = document.getElementById('el');
-FileAPI.event.dnd(el, function (over/**Boolean*/, evt/**Event*/){
- el.style.background = over ? 'red' : '';
-}, function (files/**Array*/, evt/**Event*/){
- // ...
});
```
+---
-<a name="getInfo"></a>
-### FileAPI.getInfo
-```js
-FileAPI.getInfo(imageFile/**File*/, function (err/**Boolean*/, info/**Object*/){
- if( !err ){
- switch( info.exif.Orientation ){
- // ...
- }
- }
-});
+<a name="FileAPI.addInfoReader"></a>
+### addInfoReader(mime`:RegExp`, handler`:Function`)`:void`
+Adds a handler for the collection of information about a file.
+See also: FileAPI.getInfo and FileAPI.filterFiles.
-// ...
+* mime — pattern of mime-type
+* handler — takes two arguments: `file` object and `complete` function callback
+```js
FileAPI.addInfoReader(/^image/, function (file/**File*/, callback/**Function*/){
// http://www.nihilogic.dk/labs/exif/exif.js
// http://www.nihilogic.dk/labs/binaryajax/binaryajax.js
- FileAPI.readAsBinaryString(file, function (evt){
+ FileAPI.readAsBinaryString(file, function (evt/**Object*/){
if( evt.type == 'load' ){
var binaryString = evt.result;
var oFile = new BinaryFile(binaryString, 0, file.size);
@@ -247,429 +192,987 @@ FileAPI.addInfoReader(/^image/, function (file/**File*/, callback/**Function*/){
});
```
+---
+
+<a name="FileAPI.readAsDataURL"></a>
+### readAsDataURL(file`:Object`, callback`:Function`)`:void`
+Reading the contents of the specified `File` as `dataURL`.
+
+* file — file object
+* callback — function, receives a result
-<a name="filterFiles"></a>
-### FileAPI.filterFiles
```js
-FileAPI.filterFiles(files, function (file, info){
- if( /image/.test(file.type) && info ){
- return info.width > 320 && info.height > 240;
+FileAPI.readAsDataURL(file, function (evt/**Object*/){
+ if( evt.type == 'load' ){
+ // Success
+ var dataURL = evt.result;
+ } else if( evt.type =='progress' ){
+ var pr = evt.loaded/evt.total * 100;
+ } else {
+ // Error
}
- return file.size < 10 * FileAPI.MB;
-}, function (result, ignor){
- // ...
-});
+})
```
+---
+
+<a name="FileAPI.readAsBinaryString"></a>
+### readAsBinaryString(file`:Object`, callback`:Function`)`:void`
+Reading the contents of the specified `File` as `BinaryString`.
+
+* file — file object
+* callback — function, receives a result
-<a name="readAs"></a>
-### FileAPI.readAsImage, FileAPI.readAsDataURL (FileAPI.readAsBinaryString)
```js
-FileAPI.readAsImage(file, function (evt){
+FileAPI.readAsBinaryString(file, function (evt/**Object*/){
if( evt.type == 'load' ){
- var images = document.getElementById('images');
- images.appendChild(evt.result);
- }
- else {
- // ...
+ // Success
+ var binaryString = evt.result;
+ } else if( evt.type =='progress' ){
+ var pr = evt.loaded/evt.total * 100;
+ } else {
+ // Error
}
-});
+})
+```
+
+---
+<a name="FileAPI.readAsArrayBuffer"></a>
+### readAsBinaryString(file`:Object`, callback`:Function`)`:void`
+Reading the contents of the specified `File` as `ArrayBuffer`.
-FileAPI.readAsDataURL(file, function (evt){
+* file — file object
+* callback — function, receives a result
+
+```js
+FileAPI.readAsArrayBuffer(file, function (evt/**Object*/){
if( evt.type == 'load' ){
- // success
- var result = evt.result;
+ // Success
+ var arrayBuffer = evt.result;
+ } else if( evt.type =='progress' ){
+ var pr = evt.loaded/evt.total * 100;
+ } else {
+ // Error
}
- else if( evt.type == 'progress' ){
+})
+```
+
+---
+
+<a name="FileAPI.readAsText"></a>
+### readAsText(file`:Object`, callback`:Function`)`:void`
+Reading the contents of the specified `File` as `text`.
+
+* file — file object
+* callback — function, receives a result
+
+```js
+FileAPI.readAsText(file, function (evt/**Object*/){
+ if( evt.type == 'load' ){
+ // Success
+ var text = evt.result;
+ } else if( evt.type =='progress' ){
var pr = evt.loaded/evt.total * 100;
+ } else {
+ // Error
}
- else {
- // error
+})
+```
+
+---
+
+<a name="FileAPI.readAsText-encoding"></a>
+### readAsText(file`:Object`, encoding`:String`, callback`:Function`)`:void`
+Reading the contents of the specified `File` as `text`.
+
+* encoding — a string indicating the encoding to use for the returned data. By default, UTF-8.
+
+```js
+FileAPI.readAsText(file, "utf-8", function (evt/**Object*/){
+ if( evt.type == 'load' ){
+ // Success
+ var text = evt.result;
+ } else if( evt.type =='progress' ){
+ var pr = evt.loaded/evt.total * 100;
+ } else {
+ // Error
}
+})
+```
+
+---
+
+
+<a name="options" data-name="Upload options"></a>
+## Upload options
+
+<a name="options.url"></a>
+### url`:String`
+A string containing the URL to which the request is sent.
+
+---
+
+<a name="options.data"></a>
+### data`:Object`
+Additional post data to be sent along with the file uploads.
+
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ data: { 'session-id': 123 },
+ files: { ... },
});
```
+---
+
+<a name="options.headers"></a>
+### headers`:Object`
+Additional request headers, HTML5 only.
-<a name="upload"></a>
-### FileAPI.upload
```js
var xhr = FileAPI.upload({
url: '...',
- data: { foo: 'bar' },
- headers: { 'x-header': '...' },
- files: {
- images: FileAPI.filter(files, function (file){ return /image/.test(file.type); }),
- customFile: { file: 'generate.txt', blob: customFileBlob }
- },
+ headers: { 'x-upload': 'fileapi' },
+ files: { .. },
+});
+```
- chunkSize: 0, // or chunk size in bytes, eg: FileAPI.MB*.5 (html5)
- chunkUploadRetry: 0, // number of retries during upload chunks (html5)
+---
- imageTransform: {
- maxWidth: 1024,
- maxHeight: 768
- },
- imageAutoOrientation: true,
- prepare: function (file, options){
- // prepare options for current file
- options.data.filename = file.name;
- },
- upload: function (xhr, options){
- // start uploading
- },
- fileupload: function (xhr, options){
- // start file uploading
- },
- fileprogress: function (evt){
- // progress file uploading
- var filePercent = evt.loaded/evt.total*100;
- },
- filecomplete: function (err, xhr){
- if( !err ){
- var response = xhr.responseText;
- }
- },
- progress: function (evt){
- // total progress uploading
- var totalPercent = evt.loaded/evt.total*100;
- },
- complete: function (err, xhr){
- if( !err ){
- // Congratulations, the uploading was successful!
- }
- }
+<a name="options.chunkSize"></a>
+### chunkSize`:Number`
+Chunk size in bytes, HTML5 only.
+
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { images: fileList },
+ chunkSize: 0.5 * FileAPI.MB
});
```
+---
+
+<a name="options.chunkUploadRetry"></a>
+### chunkUploadRetry`:Number`
+Number of retries during upload chunks, HTML5 only.
-<a href="imageTransform"></a>
-### imageTransform
- * width`:Number`
- * height`:Number`
- * preview`:Boolean`
- * maxWidth`:Number`
- * maxHeight`:Number`
- * rotate`:Number`
```js
-FileAPI.upload({
- // ..
- imageOriginal: false, // don't send original on server
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { images: fileList },
+ chunkSize: 0.5 * FileAPI.MB,
+ chunkUploadRetry: 3
+});
+```
+
+--
+
+<a name="options.imageTransform"></a>
+### imageTransform`:Object`
+Rules of changes the original image on the client.
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { image: imageFiles },
+ // Changes the original image
imageTransform: {
- // (1) Resize to 120x200
- resize: { width: 120, height: 200 }
+ // resize by max side
+ maxWidth: 800,
+ maxHeight: 600,
+ // Add watermark
+ overlay: [{ x: 10, y: 10, src: '/i/watemark.png', rel: FileAPI.Image.RIGHT_BOTTOM }]
+ }
+});
+```
- // (2) create preview 320x240
- thumb: { width: 320, height: 240, preview: true }
+--
- // (3) Resize by max side
- max: { maxWidth: 800, maxHeight: 600 }
+<a name="options.imageTransform-multi"></a>
+### imageTransform`:Object`
+Rules of image transformation on the client, for more images.
- // (4) Custom resize
- custom: function (info, transform){
- return transform
- .crop(100, 100, 300, 200)
- .resize(100, 50)
- ;
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { image: imageFiles },
+ imageTransform: {
+ // resize by max side
+ 'huge': { maxWidth: 800, maxHeight: 600 },
+ // crop & resize
+ 'medium': { width: 320, height: 240, preview: true },
+ // crop & resize + watemark
+ 'small': {
+ width: 100, height: 100,
+ // Add watermark
+ overlay: [{ x: 5, y: 5, src: '/i/watemark.png', rel: FileAPI.Image.RIGHT_BOTTOM }]
}
}
});
```
+--
+
+<a name="options.imageTransform-jpeg"></a>
+### imageTransform`:Object`
+Convert all images to jpeg or png.
-<a name="imageAutoOrientation"></a>
-### imageAutoOrientation
```js
-// (1) all images
-FileAPI.upload({
- // ..
- imageAutoOrientation: true
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { image: imageFiles },
+ imageTransform: {
+ type: 'image/jpeg',
+ quality: 0.86 // jpeg quality
+ }
});
+```
+
+
+<a name="options.imageOriginal"></a>
+### imageOriginal`:Boolean`
+Sent to the server the original image or not, if defined imageTransform option.
+
+--
-// (2) or so
-FileAPI.upload({
- // ..
- imageAutoOrientation: true,
- imageTransform: { width: .., height: .. }
+<a name="options.imageAutoOrientation"></a>
+### imageAutoOrientation`:Boolean`
+Auto-rotate images on the basis of EXIF.
+
+--
+
+<a name="options.prepare"></a>
+### prepare`:Function`
+Prepare options upload for a particular file.
+
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { .. }
+ prepare: function (file/**Object*/, options/**Object*/){
+ options.data.secret = utils.getSecretKey(file.name);
+ }
});
+```
+
+--
-// (3) or so
-FileAPI.upload({
- // ..
- imageTransform: { rotate: 'auto' }
+<a name="options.upload"></a>
+### upload`:Function`
+Start uploading.
+
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { .. }
+ upload: function (xhr/**Object*/, options/**Object*/){
+ // ...
+ }
});
+```
-// (4) only "800x600", original not modified
-FileAPI.upload({
- // ..
- imageTransform: {
- "800x600": { width: 800, height: 600, rotate: 'auto' }
+--
+
+<a name="options.fileupload"></a>
+### fileupload`:Function`
+Start file uploading.
+
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { .. }
+ uploadfile: function (file/**Object*/, xhr/**Object*/, options/**Object*/){
+ // ...
}
});
```
+--
------
+<a name="options.progress"></a>
+### progress`:Function`
+Callback for upload progress events.
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { .. }
+ progress: function (evt/**Object*/, file/**Object*/, xhr/**Object*/, options/**Object*/){
+ var pr = evt.loaded/evt.total * 100;
+ }
+});
+```
-<a name="flash-settings"></a>
-### Flash settings
-```html
- <script>
- var FileAPI = {
- // @required
- staticPath: '/js/' // @default: "./"
+--
- // @optional
- , flashUrl: '/js/FileAPI.flash.swf' // @default: FileAPI.staticPath + "FileAPI.flash.swf"
- , flashImageUrl: '/js/FileAPI.flash.image.swf' // @default: FileAPI.staticPath + "FileAPI.flash.image.swf"
- };
- </script>
- <script src="/js/FileAPI.min.js"></script>
+<a name="options.fileprogress"></a>
+### fileprogress`:Function`
+Callback for upload file progress events.
+
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { .. }
+ fileprogress: function (evt/**Object*/, file/**Object*/, xhr/**Object*/, options/**Object*/){
+ var pr = evt.loaded/evt.total * 100;
+ }
+});
```
-#### Flash-request ([FileReference](http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html))
-The following sample HTTP POST request is sent from Flash Player to a server-side script if no parameters are specified:
+--
+
+<a name="options.complete"></a>
+### complete`:Function`
+Callback for end upload requests.
+
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { .. }
+ complete: function (err/**String*/, xhr/**Object*/, file/**Object/, options/**Object*/){
+ if( !err ){
+ // All files successfully uploaded.
+ }
+ }
+});
+```
+
+--
+
+<a name="options.filecomplete"></a>
+### filecomplete`:Function`
+Callback for end upload requests.
+
+```js
+var xhr = FileAPI.upload({
+ url: '...',
+ files: { .. }
+ filecomplete: function (err/**String*/, xhr/**Object*/, file/**Object/, options/**Object*/){
+ if( !err ){
+ // File successfully uploaded
+ var result = xhr.responseText;
+ }
+ }
+});
```
- POST /handler.cfm HTTP/1.1
- Accept: text/*
- Content-Type: multipart/form-data;
- boundary=----------Ij5ae0ae0KM7GI3KM7
- User-Agent: Shockwave Flash
- Host: www.example.com
- Content-Length: 421
- Connection: Keep-Alive
- Cache-Control: no-cache
- ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
- Content-Disposition: form-data; name="Filename"
+---
+
+<a name="File"></a>
+## File object
+
+<a name="File.name"></a>
+### name
+The name of the file referenced by the File object.
+
+<a name="File.type"></a>
+### type
+The type (MIME type) of the file referenced by the File object.
+
+<a name="File.size"></a>
+### size
+The size (in bytes) of the file referenced by the File object.
+
+
+---
+
+
+<a name="FileAPI.event"></a>
+## FileAPI.event
+
+<a name="FileAPI.event.on"></a>
+### on(el`:HTMLElement`, events`:String`, handler`:Function`)`:void`
+Attach an event handler function.
+
+* el — DOM element
+* events — one or more space-separated event types.
+* handler — A function to execute when the event is triggered.
+
+---
+
+<a name="FileAPI.event.off"></a>
+### off(el`:HTMLElement`, events`:String`, handler`:Function`)`:void`
+Remove an event handler.
+
+* el — DOM element
+* events — one or more space-separated event types.
+* handler — a handler function previously attached for the event(s).
+
+---
- MyFile.jpg
- ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
- Content-Disposition: form-data; name="Filedata"; filename="MyFile.jpg"
- Content-Type: application/octet-stream
+<a name="FileAPI.event.one"></a>
+### one(el`:HTMLElement`, events`:String`, handler`:Function`)`:void`
+Attach an event handler function. The handler is executed at most once.
- FileDataHere
- ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
- Content-Disposition: form-data; name="Upload"
+* el — DOM element
+* events — one or more space-separated event types.
+* handler — a function to execute when the event is triggered.
- Submit Query
- ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7--
+---
+
+<a name="FileAPI.event.dnd"></a>
+### dnd(el`:HTMLElement`, hover`:Function`, handler`:Function`)`:void`
+Attach an drag and drop event handler function.
+
+* el — drop zone
+* hover — `dragenter` and `dragleave` listener
+* handler — `drop` event handler.
+
+```js
+var el = document.getElementById('dropzone');
+FileAPI.event.dnd(el, function (over){
+ el.style.backgroundColor = over ? '#f60': '';
+}, function (files){
+ if( files.length ){
+ // Upload their.
+ }
+});
+
+// or jQuery
+$('#dropzone').dnd(hoverFn, dropFn);
```
+---
+<a name="FileAPI.event.dnd.off"></a>
+### dnd.off(el`:HTMLElement`, hover`:Function`, handler`:Function`)`:void`
+Remove an drag and drop event handler function.
------
+* el — drop zone
+* hover — `dragenter` and `dragleave` listener
+* handler — `drop` event handler.
+```js
+// Native
+FileAPI.event.dnd.off(el, hoverFn, dropFn);
+// jQuery
+$('#dropzone').dndoff(hoverFn, dropFn);
+```
+
+--
+
+<a name="FileAPI.Image"></a>
+## FileAPI.Image
+Class for working with images
+
+### constructor(file`:Object`)`:void`
+The constructor takes a single argument, the `File` object.
+
+* file — the `File` object
-<a name="chunked"></a>
-### Chunked file upload (html5)
```js
-FileAPI.upload({
- url: '...'
- , files: fileList
- , chunkSize: .5 * FileAPI.MB // 512KB
- , chunkUploadRetry: 1
- , complete: function (err, xhr){}
+FileAPI.Image(imageFile).get(function (err/**String*/, img/**HTMLElement*/){
+ if( !err ){
+ document.body.appendChild( img );
+ }
});
```
-Client and server communicate to each other using the following HTTP headers and status codes.
+---
-Client explicitly sets the following headers:
-* [Content-Range](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16): bytes \<start-offset\>-\<end-offset\>/\<total\>
-* [Content-Disposition](http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1): attachment; filename=\<file-name\>
+### crop(width`:Number`, height`:Number`)`:FileAPI.Image`
+Crop image by width and height.
-Any other headers are set by a target browser and are not used by client.
-Library does not provide any facilities to track a file uniqueness across requests, it's left on developer's consideration.
+* width — new image width
+* height — new image height
-Response codes:
-* 200 - last chunk is uploaded
-* 201 - chunk is successfully saved
-* 416 - range is not acceptable error, recoverable
-* 500 - server error, recoverable
+```js
+FileAPI.Image(imageFile)
+ .crop(640, 480)
+ .get(function (err/**String*/, img/**HTMLElement*/){
-For recoverable errors server tries to resend chunk 'chunkUploadRetry' times then fails.
+ })
+;
+```
-Response headers:
-* X-Last-Known-Byte: int, library tries to resend chunk from the given offset. Applicable to response codes 200 and 416
+### crop(x`:Number`, y`:Number`, width`:Number`, height`:Number`)`:FileAPI.Image`
+Crop image by x, y, width and height.
-All the other codes - fatal error, user's involvement is recommend.
+* x — offset from the top corner
+* y — offset from the left corner
+```js
+FileAPI.Image(imageFile)
+ .crop(100, 50, 320, 240)
+ .get(function (err/**String*/, img/**HTMLElement*/){
+
+ })
+;
+```
------
+---
+### resize(width`:Number`, height`:Number`[, type`:String`])`:FileAPI.Image`
+Resize image.
+* width — new image width
+* height — new image height
+* type — enum: `min`, `max`, `preview`. By default `undefined`.
-### File object (https://developer.mozilla.org/en/DOM/File)
```js
-{
- name: 'fileName',
- type: 'mime-type',
- size: 'fileSize'
-}
+FileAPI.Image(imageFile)
+ .resize(320, 240)
+ .get(function (err/**String*/, img/**HTMLElement*/){
+
+ })
+;
+
+// Resize image on by max side.
+FileAPI.Image(imageFile)
+ .resize(320, 240, 'max')
+ .get(function (err/**String*/, img/**HTMLElement*/){
+
+ })
+;
```
+---
+
+### preview(width`:Number`[, height`:Number`])`:FileAPI.Image`
+Crop and resize image.
+
+* width — new image width
+* height — new image height
-### XMLHttpRequest
```js
-{
- status: Number,
- statusText: Number,
- readyState: Number,
- response: Blob,
- responseXML: XML,
- responseText: String,
- responseBody: String,
- getResponseHeader: function (name/**String*/)/**String*/{},
- getAllResponseHeaders: function ()/**Object*/{},
- abort: function (){}
-}
+FileAPI.Image(imageFile)
+ .preview(100, 100)
+ .get(function (err/**String*/, img/**HTMLElement*/){
+
+ })
+;
```
+---
-### Cross-Domain upload-controller headers
-```php
-<?
- header('Access-Control-Allow-Methods: POST, OPTIONS');
- header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type'); // and other custom headers
- header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); // a comma-separated list of domains
- header('Access-Control-Allow-Credentials: true');
+### rotate(deg`:Number`)`:FileAPI.Image`
+Rotate image.
- if( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ){
- exit;
- }
+* deg — rotation angle in degrees
- if( $_SERVER['REQUEST_METHOD'] == 'POST' ){
- // ...
- }
-?>
+```js
+FileAPI.Image(imageFile)
+ .rotate(90)
+ .get(function (err/**String*/, img/**HTMLElement*/){
+
+ })
+;
```
+---
+
+### filter(callback`:Function`)`:FileAPI.Image`
+Apply filter function. Only `HTML5`.
-### iframe
-#### POST-query
+* callback — takes two arguments, `canvas` element and `done` method.
+
+```js
+FileAPI.Image(imageFile)
+ .filter(function (canvas/**HTMLCanvasElement*/, doneFn/**Function*/){
+ // bla-bla-lba
+ doneFn();
+ })
+ .get(function (err/**String*/, img/**HTMLElement*/){
+
+ })
+;
```
-/controller.php
- ?foo=bar
- &images=...
- &callback=...
+
+
+---
+
+### filter(name`:String`)`:FileAPI.Image`
+Uses [CamanJS](http://camanjs.com/), include it before FileAPI library.
+
+* name — CamanJS filter name (custom or preset)
+
+```js
+Caman.Filter.register("my-funky-filter", function () {
+ // http://camanjs.com/guides/#Extending
+});
+
+FileAPI.Image(imageFile)
+ .filter("my-funky-filter") // or .filter("vintage")
+ .get(function (err/**String*/, img/**HTMLElement*/){
+
+ })
+;
```
+---
-#### POST-response
-```php
-<script type="text/javascript">
-(function (ctx, jsonp){
- if( ctx && ctx[jsonp] ){
- ctx[jsonp](<?=$statusCode/*200 — OK*/?>, "<?=addslashes($statusText)?>", "<?=addslashes($response)?>");
- }
-})(this.parent, "<?=htmlspecialchars($_POST['callback'])?>");
+### overlay(images`:Array`)`:FileAPI.Image`
+Add overlay images, eg: watermark.
+
+* images — array of overlays
+
+```js
+FileAPI.Image(imageFile)
+ .overlay([
+ // Left corner.
+ { x: 10, y: 10, w: 100, h: 10, src: '/i/watermark.png' },
+
+ // Right bottom corner.
+ { x: 10, y: 10, src: '/i/watermark.png', rel: FileAPI.Image.RIGHT_BOTTOM }
+ ])
+ .get(function (err/**String*/, img/**HTMLElement*/){
+
+ })
+;
+```
+
+---
+
+### get(fn`:Function`)`:FileAPI.Image`
+Get the final image.
+
+* fn — complete callback
+
+---
+
+
+<a name="const" data-name="Сonst"></a>
+## Сonstants
+
+<a name="FileAPI.KB"></a>
+### FileAPI.KB`:Number`
+1024 bytes
+
+<a name="FileAPI.MB"></a>
+### FileAPI.MB`:Number`
+1048576 bytes
+
+<a name="FileAPI.GB"></a>
+### FileAPI.GB`:Number`
+1073741824 bytes
+
+<a name="FileAPI.TB"></a>
+### FileAPI.TB`:Number`
+1.0995116e+12 bytes
+
+---
+
+<a name="FileAPI.utils"></a>
+## Utils
+
+<a name="FileAPI.each"></a>
+### FileAPI.each(obj`:Object|Array`, callback`:Function`[, thisObject`:Mixed`])`:void`
+Iterate over a object or array, executing a function for each matched element.
+
+* obj — array or object
+* callback — a function to execute for each element.
+* thisObject — object to use as `this` when executing `callback`.
+
+--
+
+<a name="FileAPI.extend"></a>
+### FileAPI.extend(dst`:Object`, src`:Object`)`:Object`
+Merge the contents of two objects together into the first object.
+
+* dst — an object that will receive the new properties
+* src — an object containing additional properties to merge in.
+
+--
+
+<a name="FileAPI.filter"></a>
+### FileAPI.filter(array`:Array`, callback`:Function`[, thisObject`:Mixed`)`:Object`
+Creates a new array with all elements that pass the test implemented by the provided function.
+
+* array — original Array
+* callback — Function to test each element of the array.
+* thisObject — object to use as `this` when executing `callback`.
+
+---
+
+<a name="support"><a/>
+## Support
+<ul>
+ <li>Multiupload: all browsers that support HTML5 or Flash</li>
+ <li>Drag'n'Drop upload: files (HTML5) & directories (Chrome 21+)</li>
+ <li>Chunked file upload (HTML5)</li>
+ <li>Upload one file: all browsers</li>
+ <li>
+ Working with Images: IE6+, FF 3.6+, Chrome 10+, Opera 11.1+, Safari 5.4+
+ <ul>
+ <li>crop, resize, preview & rotate (HTML5 or Flash)</li>
+ <li>auto orientation by exif (HTML5, if include FileAPI.exif.js or Flash)</li>
+ </ul>
+ </li>
+</ul>
+
+<a name="FileAPI.support.html5"></a>
+### FileAPI.support.html5`:Boolean`
+HTML5 borwser support
+
+<a name="FileAPI.support.cors"></a>
+### FileAPI.support.cors`:Boolean`
+This cross-origin resource sharing is used to enable cross-site HTTP requests.
+
+<a name="FileAPI.support.dnd"></a>
+### FileAPI.support.dnd`:Boolean`
+Drag'n'drop events support.
+
+<a name="FileAPI.support.flash"></a>
+### FileAPI.support.flash`:Boolean`
+Availability Flash plugin.
+
+<a name="FileAPI.support.canvas"></a>
+### FileAPI.support.canvas`:Boolean`
+Canvas support.
+
+<a name="FileAPI.support.dataURI"></a>
+### FileAPI.support.dataURI`:Boolean`
+Support dataURI as src for image.
+
+<a name="FileAPI.support.chunked"></a>
+### FileAPI.support.chunked`:Boolean`
+Support chuncked upload.
+
+---
+
+<a name="flash"></a>
+## Flash
+
+<a name="flash.settings"></a>
+### Settings
+Flash settings.
+It is advisable to place flash on the same server where the files will be uploaded.
+
+```html
+<script>
+ var FileAPI = {
+ // @default: "./dist/"
+ staticPath: '/js/',
+
+ // @default: FileAPI.staticPath + "FileAPI.flash.swf"
+ flashUrl: '/statics/FileAPI.flash.swf',
+
+ // @default: FileAPI.staticPath + "FileAPI.flash.image.swf"
+ flashImageUrl: '/statics/FileAPI.flash.image.swf'
+ };
</script>
+<script src="/js/FileAPI.min.js"></script>
```
+---
+<a name="crossdomain.xml"></a>
+### crossdomain.xml
+Necessarily make this file on the server.
+Do not forget to replace `youdomain.com` on the name of your domain.
+
+```xml
+<?xml version="1.0"?>
+<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
+<cross-domain-policy>
+ <site-control permitted-cross-domain-policies="all"/>
+ <allow-access-from domain="youdomain.com" secure="false"/>
+ <allow-access-from domain="*.youdomain.com" secure="false"/>
+ <allow-http-request-headers-from domain="*" headers="*" secure="false"/>
+</cross-domain-policy>
+```
---
+<a name="flash.request"></a>
+### request
+The following sample HTTP POST request is sent from Flash Player to a server-side script if no parameters are specified:
+
+```xml
+POST /server/ctrl.php HTTP/1.1
+Accept: text/*
+Content-Type: multipart/form-data;
+boundary=----------Ij5ae0ae0KM7GI3KM7
+User-Agent: Shockwave Flash
+Host: www.youdomain.com
+Content-Length: 421
+Connection: Keep-Alive
+Cache-Control: no-cache
+
+------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
+Content-Disposition: form-data; name="Filename"
+
+MyFile.jpg
+------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
+Content-Disposition: form-data; name="Filedata"; filename="MyFile.jpg"
+Content-Type: application/octet-stream
+
+[[..FILE_DATA_HERE..]]
+------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
+Content-Disposition: form-data; name="Upload"
+
+Submit Query
+------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7--
+```
+---
+
+<a name="server"></a>
+## Server settings
-### HTML structure (templates)
+<a name="server.CORS"></a>
+### CORS
+Enable CORS.
+
+```php
+<?
+ // Permitted types of request
+ header('Access-Control-Allow-Methods: POST, OPTIONS');
+
+ // Describe custom headers
+ header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type');
+
+ // A comma-separated list of domains
+ header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
+
+ // Allow cookie
+ header('Access-Control-Allow-Credentials: true');
+
+ if( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ){
+ exit;
+ }
+
+ if( $_SERVER['REQUEST_METHOD'] == 'POST' ){
+ // ...
+ }
+```
+
+---
+
+<a name="server.chunked"></a>
+### Chunked file upload
+Client and server communicate to each other using the following HTTP headers and status codes.<br/>
+Client explicitly sets the following headers:<br/>
+<ul>
+ <li>Content-Range: bytes &lt;start-offset&gt;-&lt;end-offset&gt;/&lt;total&gt;</li>
+ <li>Content-Disposition: attachment; filename=&lt;file-name&gt;</li>
+</ul>
+Any other headers are set by a target browser and are not used by client. Library does not provide any facilities to track a file uniqueness across requests, it's left on developer's consideration.<br/>
+Response codes:
+<ul>
+ <li>200 - last chunk is uploaded</li>
+ <li>201 - chunk is successfully saved</li>
+ <li>416 - range is not acceptable error, recoverable</li>
+ <li>500 - server error, recoverable</li>
+</ul>
+For recoverable errors server tries to resend chunk `chunkUploadRetry` times then fails.<br/
+Response headers:
+<ul>
+ <li>X-Last-Known-Byte: int, library tries to resend chunk from the given offset. Applicable to response codes 200 and 416</li>
+</ul>
+All the other codes - fatal error, user's involvement is recommend.
+
+---
+
+<a name="buttons.examples"></a>
+## Buttons examples
+
+<a name="buttons.examples.base"></a>
+### Base
+Simple input[type="file"]
-<a name="html-default"></a>
-### Default
```html
<span class="js-fileapi-wrapper" style="position: relative; display: inline-block;">
- <input name="files" type="file" multiple />
+ <input name="files" type="file" multiple/>
</span>
```
+---
-<a name="html-button"></a>
+<a name="buttons.examples.button"></a>
### Button
+Stylized button.
+
```html
<style>
.upload-btn {
- width: 130px;
- height: 25px;
- overflow: hidden;
- position: relative;
- border: 3px solid #06c;
- border-radius: 5px;
- background: #0cf;
+ width: 130px;
+ height: 25px;
+ overflow: hidden;
+ position: relative;
+ border: 3px solid #06c;
+ border-radius: 5px;
+ background: #0cf;
}
- .upload-btn:hover {
- background: #09f;
- }
- .upload-btn__txt {
- z-index: 1;
- position: relative;
- color: #fff;
- font-size: 18px;
- font-family: "Helvetica Neue";
- line-height: 24px;
- text-align: center;
- text-shadow: 0 1px 1px #000;
- }
- .upload-btn__inp {
- top: -10px;
- right: -40px;
- z-index: 2;
- position: absolute;
- cursor: pointer;
- opacity: 0;
- filter: alpha(opacity=0);
- font-size: 50px;
- }
+ .upload-btn:hover {
+ background: #09f;
+ }
+ .upload-btn__txt {
+ z-index: 1;
+ position: relative;
+ color: #fff;
+ font-size: 18px;
+ font-family: "Helvetica Neue";
+ line-height: 24px;
+ text-align: center;
+ text-shadow: 0 1px 1px #000;
+ }
+ .upload-btn input {
+ top: -10px;
+ right: -40px;
+ z-index: 2;
+ position: absolute;
+ cursor: pointer;
+ opacity: 0;
+ filter: alpha(opacity=0);
+ font-size: 50px;
+ }
</style>
<div class="upload-btn js-fileapi-wrapper">
- <div class="upload-btn__txt">Upload files</div>
- <input class="upload-btn__inp" name="files" type="file" multiple />
+ <div class="upload-btn__txt">Upload files</div>
+ <input name="files" type="file" multiple />
</div>
```
-<a name="html-link"></a>
+---
+
+
+<a name="buttons.examples.link"></a>
### Link
+Button like link.
+
```html
<style>
.upload-link {
- color: #36c;
- display: inline-block;
- *zoom: 1;
- *display: inline;
- overflow: hidden;
- position: relative;
- padding-bottom: 2px;
- text-decoration: none;
+ color: #36c;
+ display: inline-block;
+ *zoom: 1;
+ *display: inline;
+ overflow: hidden;
+ position: relative;
+ padding-bottom: 2px;
+ text-decoration: none;
}
- .upload-link__txt {
- z-index: 1;
- position: relative;
- border-bottom: 1px dotted #36c;
- }
- .upload-link:hover .upload-link__txt {
- color: #f00;
- border-bottom-color: #f00;
- }
-
- .upload-link__inp {
- top: -10px;
- right: -40px;
- z-index: 2;
- position: absolute;
- cursor: pointer;
- opacity: 0;
- filter: alpha(opacity=0);
- font-size: 50px;
- }
+ .upload-link__txt {
+ z-index: 1;
+ position: relative;
+ border-bottom: 1px dotted #36c;
+ }
+ .upload-link:hover .upload-link__txt {
+ color: #f00;
+ border-bottom-color: #f00;
+ }
+
+ .upload-link input {
+ top: -10px;
+ right: -40px;
+ z-index: 2;
+ position: absolute;
+ cursor: pointer;
+ opacity: 0;
+ filter: alpha(opacity=0);
+ font-size: 50px;
+ }
</style>
<a class="upload-link js-fileapi-wrapper">
- <span class="upload-link__txt">Upload photo</span>
- <input class="upload-link__inp" name="photo" type="file" accept=".jpg,.jpeg,.gif" />
+ <span class="upload-link__txt">Upload photo</span>
+ <input name="photo" type="file" accept="image/*" />
</a>
```
@@ -677,64 +1180,100 @@ All the other codes - fatal error, user's involvement is recommend.
---
+<a name="Changelog"></a>
## Changelog
+
+### 2.0.0
+<ul>
+ <li>+ FileAPI.Camera (HTML5 and Flash fallback)</li>
+ <li>+ jquery.fileapi.js, see <a href="http://rubaxa.github.io/jquery.fileapi/">demo</a></li>
+ <li>+ npm support</li>
+ <li>+ grunt support</li>
+ <li>+ requirejs support</li>
+ <li>+ [#80](https://https://github.com/mailru/FileAPI/issues/80): FileAPI.Image.fn.overlay</li>
+ <li>`imageTransform` — now supports: `crop`, `type`, `quality` and `overlay` properties.</li>
+ <li>Improved the documentation</li>
+ <li>[#121](https://github.com/mailru/FileAPI/issues/121): + FileAPI.`postNameConcat:Function(name, idx)`</li>
+ <li>[#116](https://github.com/mailru/FileAPI/issues/116): + `cache:false` option for FileAPI.upload</li>
+</ul>
+
+
### 1.2.6
- * [#91](https://github.com/mailru/FileAPI/issues/91): replace `new Image` to `FileAPI.newImage`
- * + FileAPI.withCredentials: true
- * [#90](https://github.com/mailru/FileAPI/issues/90): Fixed `progress` event
- * [#105](https://github.com/mailru/FileAPI/issues/105): Fixed `image/jpg` -> `image/jpeg`
- * [#108](https://github.com/mailru/FileAPI/issues/108): Check width/height before resize by type(min/max)
+<ul>
+ <li>[#91](https://github.com/mailru/FileAPI/issues/91): replace `new Image` to `FileAPI.newImage`</li>
+ <li>+ FileAPI.withCredentials: true</li>
+ <li>[#90](https://github.com/mailru/FileAPI/issues/90): Fixed `progress` event</li>
+ <li>[#105](https://github.com/mailru/FileAPI/issues/105): Fixed `image/jpg` -> `image/jpeg`</li>
+ <li>[#108](https://github.com/mailru/FileAPI/issues/108): Check width/height before resize by type(min/max)</li>
+</ul>
### 1.2.5
- * [#86](https://github.com/mailru/FileAPI/issues/86): Smarter upload recovery
- * [#87](https://github.com/mailru/FileAPI/issues/87): Fixed upload files into browsers that do not support FormData
- * Fixed support "accept" attribute for Flash.
- * Fixed detection of HTML5 support for FireFox 3.6
- * + FileAPI.html5 option, default "true"
+<ul>
+ <li>[#86](https://github.com/mailru/FileAPI/issues/86): Smarter upload recovery</li>
+ <li>[#87](https://github.com/mailru/FileAPI/issues/87): Fixed upload files into browsers that do not support FormData</li>
+ <li>Fixed support "accept" attribute for Flash.</li>
+ <li>Fixed detection of HTML5 support for FireFox 3.6</li>
+ <li> + FileAPI.html5 option, default "true"</li>
+</ul>
### 1.2.4
- * Fixed auto orientation image by EXIF (Flash)
- * Fixed image dimensions after rotate (Flash)
- * [#82](https://github.com/mailru/FileAPI/issues/82): "undefined" data-fields cause exceptions
- * [#83](https://github.com/mailru/FileAPI/issues/83): Allow requests without files
- * [#84](https://github.com/mailru/FileAPI/pull/84): Fixed connection abort when waiting for connection recovery
+<ul>
+ <li>Fixed auto orientation image by EXIF (Flash)</li>
+ <li>Fixed image dimensions after rotate (Flash)</li>
+ <li>[#82](https://github.com/mailru/FileAPI/issues/82): "undefined" data-fields cause exceptions</li>
+ <li>[#83](https://github.com/mailru/FileAPI/issues/83): Allow requests without files</li>
+ <li>[#84](https://github.com/mailru/FileAPI/pull/84): Fixed connection abort when waiting for connection recovery</li>
+</ul>
### 1.2.3
- * [#77](https://github.com/mailru/FileAPI/pull/77): Fixed flash.abort(), [#75](https://github.com/mailru/FileAPI/issues/75)
- * - `FileAPI.addMime`
- * + `FileAPI.accept` — fallback for flash.
+<ul>
+ <li>[#77](https://github.com/mailru/FileAPI/pull/77): Fixed flash.abort(), [#75](https://github.com/mailru/FileAPI/issues/75)</li>
+ <li>- `FileAPI.addMime`</li>
+ <li>+ `FileAPI.accept` — fallback for flash.</li>
+</ul>
### 1.2.2
- * [#67](https://github.com/mailru/FileAPI/pull/67): Added correct httpStatus for upload fail, [#62](https://github.com/mailru/FileAPI/pull/68)
- * [#68](https://github.com/mailru/FileAPI/pull/68) Added "Content-Type" for chunked upload, [#65](https://github.com/mailru/FileAPI/pull/65)
- * [#69](https://github.com/mailru/FileAPI/issues/69): Fixed network down recovery
- * Fixed progress event, [#66](https://github.com/mailru/FileAPI/issues/66)
- * Increase flash stage size, [#73](https://github.com/mailru/FileAPI/pull/73)
- * - array index from POST-param "name", [#72](https://github.com/mailru/FileAPI/issues/72)
- * - dependency on FileAPI.Image for FileAPI.Flash
+<ul>
+ <li>[#67](https://github.com/mailru/FileAPI/pull/67): Added correct httpStatus for upload fail, [#62](https://github.com/mailru/FileAPI/pull/68)</li>
+ <li>[#68](https://github.com/mailru/FileAPI/pull/68) Added "Content-Type" for chunked upload, [#65](https://github.com/mailru/FileAPI/pull/65)</li>
+ <li>[#69](https://github.com/mailru/FileAPI/issues/69): Fixed network down recovery</li>
+ <li>Fixed progress event, [#66](https://github.com/mailru/FileAPI/issues/66)</li>
+ <li>Increase flash stage size, [#73](https://github.com/mailru/FileAPI/pull/73)</li>
+ <li>- array index from POST-param "name", [#72](https://github.com/mailru/FileAPI/issues/72)</li>
+ <li>- dependency on FileAPI.Image for FileAPI.Flash</li>
+</ul>
### 1.2.1
- * [#64](https://github.com/mailru/FileAPI/issues/64): Bufixed for [#63](https://github.com/mailru/FileAPI/issues/63)
-
+<ul>
+ <li>[#64](https://github.com/mailru/FileAPI/issues/64): Bufixed for [#63](https://github.com/mailru/FileAPI/issues/63)</li>
+</ul>
### 1.2.0
- * [#57](https://github.com/mailru/FileAPI/issues/57): Chunked file upload
+<ul>
+ <li>[#57](https://github.com/mailru/FileAPI/issues/57): Chunked file upload</li>
+</ul>
### 1.1.0
- * [#54](https://github.com/mailru/FileAPI/issues/54): added `FileAPI.flashUrl` and `FileAPI.flashImageUrl`
+<ul>
+ <li>[#54](https://github.com/mailru/FileAPI/issues/54): added `FileAPI.flashUrl` and `FileAPI.flashImageUrl`</li>
+</ul>
### 1.0.1
- * [#51](https://github.com/mailru/FileAPI/issues/51): remove circular references from `file-objects` (Flash transport)
- * added `changelog`
+<ul>
+ <li>[#51](https://github.com/mailru/FileAPI/issues/51): remove circular references from `file-objects` (Flash transport)</li>
+ <li>added `changelog`</li>
+</ul>
### 1.0.0
- * first release
+<ul>
+ <li>first release</li>
+</ul>
View
1,166 README.ru.md
@@ -0,0 +1,1166 @@
+<a name="install" data-name="Installation"></a>
+## Installation, testing, assembling
+`npm install fileapi`<br/>
+`cd fileapi`<br/>
+`npm install`<br/>
+`grunt`
+
+
+---
+
+
+<a name="FileAPI"></a>
+## FileAPI
+Набор JavaScript инструментов для работы с файлами.
+
+
+<a name="FileAPI.setup"></a>
+### Setup
+Подключение библиотеки к проекту.
+Если вы собираетесь использовать CORS, то отредактируйте файл `crossdomain.xml` и
+разместите в коре удаленного домена.
+
+```html
+ <script>
+ window.FileAPI = {
+ debug: false // дебаг режим, смотрите Console
+ , cors: true // если используете CORS
+ , staticPath: '/js/FileAPI/dist/' // путь к '*.swf'
+ };
+ </script>
+ <script src="/js/FileAPI/dist/FileAPI.min.js"></script>
+
+ <!-- ИЛИ -->
+
+ <script>
+ window.FileAPI = { /* etc. */ };
+ require(['FileAPI'], function (FileAPI){
+ // ...
+ });
+ </script>
+```
+
+---
+
+
+<a name="FileAPI.getFiles"></a>
+### getFiles(input`:HTMLInputElement|Event|$.Event`)`:Array`
+Получить список файлов из `input` элемента, или `event`, также поддерживается `jQuery`.
+
+* input — `HTMLInputElement`, `change` и `drop` события, `jQuery` коллекция или `jQuery.Event`
+
+```js
+var el = document.getElement('my-input');
+FileAPI.event.on(el, function (evt/**Event*/){
+ // Получить список файлов из `input`
+ var files = FileAPI.getFiles(el);
+
+ // или события
+ var files = FileAPI.getFiles(evt);
+});
+```
+
+---
+
+<a name="FileAPI.getInfo"></a>
+### getInfo(file`:Object`, callback`:Function`)`:void`
+Получить информацию о файле (см. FileAPI.addInfoReader).
+
+* file — объект файла (https://developer.mozilla.org/en-US/docs/DOM/File)
+* callback — функция, вызывается по завершению сбора информации
+
+```js
+// Получить информацию о изображении (FileAPI.exif.js подключен)
+FileAPI.getInfo(file, function (err/**String*/, info/**Object*/){
+ if( !err ){
+ console.log(info); // { width: 800, height: 600, exif: {..} }
+ }
+});
+
+// Получить информацию о mp3 файле (FileAPI.id3.js included)
+FileAPI.getInfo(file, function (err/**String*/, info/**Object*/){
+ if( !err ){
+ console.log(info); // { title: "...", album: "...", artists: "...", ... }
+ }
+});
+```
+
+---
+
+<a name="FileAPI.filterFiles"></a>
+### filterFiles(files`:Array`, filter`:Function`, callback`:Function`)`:void`
+Отфильтровать список файлов, используя дополнительную информацию о них.
+см. FileAPI.getInfo или FileAPI.addInfoReader.
+
+* files — оригинальный список файлов
+* filter — функция, принимает два аргумента: `file` — сам файл, `info` — дополнительная информация
+* callback — функция: `list` — список файлов, подошедшие под условия, `other` — все остальные.
+
+```js
+// Получаем список файлов
+var files = FileAPI.getFiles(input);
+
+// Фильтруем список
+FileAPI.filterFiles(files, function (file/**Object*/, info/**Object*/){
+ if( /^image/.test(file.type) && info ){
+ return info.width > 320 && info.height > 240;
+ } else {
+ return file.size < 20 * FileAPI.MB;
+ }
+}, function (list/**Array*/, other/**Array*/){
+ if( list.length ){
+ // ..
+ }
+});
+```
+
+---
+
+<a name="FileAPI.getDropFiles"></a>
+### getDropFiles(evt`:Event|$.Event`, callback`:Function`)`:void`
+Получить весь список файлов, включая директории.
+
+* evt — `drop` event
+* callback — фнукция, принимает один аргумент — список файлов
+
+```js
+FileAPI.event.on(document, 'drop', function (evt/**Event*/){
+ evt.preventDefault();
+
+ // Получаем все файлы
+ FileAPI.getDropFiles(evt, function (files/**Array*/){
+ // ...
+ });
+});
+```
+
+---
+
+<a name="FileAPI.upload"></a>
+### upload(opts`:Object`)`:XmlHttpRequest`
+Загрузка файлов на сервер. Возвращает XHR-подобный объект.
+Помните, для корректной работы flash-транспорта, тело ответа сервера не должно быть пустым,
+например можно ответить простым текстом "ok".
+
+* opts — объект настрое, см. раздел [Upload options](#options)
+
+```js
+var el = document.getElementById('my-input');
+FileAPI.event.on(el, 'change', function (evt/**Event*/){
+ var files = FileAPI.getFiles(evt);
+ var xhr = FileAPI.upload({
+ url: 'http://rubaxa.org/FileAPI/server/ctrl.php',
+ files: { file: files[0] },
+ complete: function (err, xhr){
+ if( !err ){
+ var result = xhr.responseText;
+ // ...
+ }
+ }
+ });
+});
+```
+
+---
+
+<a name="FileAPI.addInfoReader"></a>
+### addInfoReader(mime`:RegExp`, handler`:Function`)`:void`
+Добавить обработчик, для сбора информации о файле.
+см. также: FileAPI.getInfo и FileAPI.filterFiles.
+
+* mime — маска mime-type
+* handler — функция, принимает два аргумента: `file` объект и `complete` функция обратного вызова
+
+```js
+FileAPI.addInfoReader(/^image/, function (file/**File*/, callback/**Function*/){
+ // http://www.nihilogic.dk/labs/exif/exif.js
+ // http://www.nihilogic.dk/labs/binaryajax/binaryajax.js
+ FileAPI.readAsBinaryString(file, function (evt/**Object*/){
+ if( evt.type == 'load' ){
+ var binaryString = evt.result;
+ var oFile = new BinaryFile(binaryString, 0, file.size);
+ var exif = EXIF.readFromBinaryFile(oFile);
+ callback(false, { 'exif': exif || {} });
+ }
+ else if( evt.type == 'error' ){
+ callback('read_as_binary_string');
+ }
+ else if( evt.type == 'progress' ){
+ // ...
+ }
+ });
+});
+```
+
+---
+
+<a name="FileAPI.readAsDataURL"></a>
+### readAsDataURL(file`:Object`, callback`:Function`)`:void`
+Чтение содержимого указанного файла как dataURL.
+
+* file — файл для чтения
+* callback — функция обработчик
+
+```js
+FileAPI.readAsDataURL(file, function (evt/**Object*/){
+ if( evt.type == 'load' ){
+ // Всё хорошо
+ var dataURL = evt.result;
+ } else if( evt.type =='progress' ){
+ var pr = evt.loaded/evt.total * 100;
+ } else {
+ // Ошибка
+ }
+})
+```
+
+---
+
+<a name="FileAPI.readAsBinaryString"></a>
+### readAsBinaryString(file`:Object`, callback`:Function`)`:void`
+Чтение содержимого указанного файла как `BinaryString`.
+
+* file — файл для чтения
+* callback — функция обработчик
+
+```js
+FileAPI.readAsBinaryString(file, function (evt/**Object*/){
+ if( evt.type == 'load' ){
+ // Всё хорошо
+ var binaryString = evt.result;
+ } else if( evt.type =='progress' ){
+ var pr = evt.loaded/evt.total * 100;
+ } else {
+ // Ошибка
+ }
+})
+```
+
+---
+
+<a name="FileAPI.readAsArrayBuffer"></a>
+### readAsBinaryString(file`:Object`, callback`:Function`)`:void`
+Чтение содержимого указанного файла как `ArrayBuffer`.
+
+* file — файл для чтения
+* callback — функция обработчик
+
+```js
+FileAPI.readAsArrayBuffer(file, function (evt/**Object*/){
+ if( evt.type == 'load' ){
+ // Всё хорошо
+ var arrayBuffer = evt.result;
+ } else if( evt.type =='progress' ){
+ var pr = evt.loaded/evt.total * 100;
+ } else {
+ // Ошибка
+ }
+})
+```
+
+---
+
+<a name="FileAPI.readAsText"></a>
+### readAsText(file`:Object`, callback`:Function`)`:void`
+Чтение содержимого указанного файла как `text`.
+
+* file — файл для чтения
+* callback — функция обработчик
+
+```js
+FileAPI.readAsText(file, function (evt/**Object*/){
+ if( evt.type == 'load' ){
+ // Всё хорошо
+ var text = evt.result;
+ } else if( evt.type =='progress' ){
+ var pr = evt.loaded/evt.total * 100;
+ } else {
+ // Ошибка
+ }
+})
+```
+
+---