├── .gitignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── example └── index.html ├── images └── screenprint.png ├── package.json ├── src └── ngFileReader.js └── vendor ├── filereader.swf ├── jquery.FileReader.js ├── jquery.FileReader.position.ver.js └── swfobject.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.swp 3 | dist 4 | bower_components 5 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 2 | var path = require('path'); 3 | 4 | module.exports = function( grunt ) { 5 | 6 | require("matchdep").filterDev("grunt-*").forEach( grunt.loadNpmTasks ); 7 | 8 | grunt.initConfig({ 9 | pkg: grunt.file.readJSON('package.json'), 10 | uglify: { 11 | options: { 12 | banner: '/*! <%= pkg.name %> <%= pkg.version %> | Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %> | <%= pkg.license %> license*/\n' 13 | }, 14 | build: { 15 | src: '<%= pkg.main %>', 16 | dest: 'dist/<%= pkg.name %>.min.js' 17 | } 18 | }, 19 | express: { 20 | server: { 21 | options: { 22 | bases: __dirname 23 | } 24 | } 25 | }, 26 | open: { 27 | server:{ 28 | path: "http://localhost:<%= express.server.options.port %>/example/index.html" 29 | } 30 | } 31 | }); 32 | 33 | 34 | grunt.registerTask('build', ['uglify']); 35 | grunt.registerTask('default', ['build']); 36 | grunt.registerTask('server', ['express','open','express-keepalive']); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Sparrow.jang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ngFileReader 2 | ============= 3 | 4 | ![demo image](/images/screenprint.png) 5 | 6 | This is file reader component on angular. 7 | 8 | ## LiveDemo 9 | 10 | [demo](http://www.sparrowjang.com/ngFileReader/example/index.html) 11 | 12 | ## Support 13 | 14 | * IE8+ 15 | * chrome 16 | * firefox 17 | 18 | 19 | ## Dependency 20 | 21 | * angularjs 22 | * jQuery 23 | * [FileReader](https://github.com/Jahdrien/FileReader) 24 | 25 | You need load **jQuery** and **FileReader** if browser is not support `FileReader`. 26 | 27 | And The base64 size only limit 32kb if you use base64 to set image on IE8. 28 | 29 | You also use other [FileReader](https://github.com/Phlow2001/FileReader) version,if you don't want to use `fixed` position by flash. 30 | 31 | ## Install 32 | 33 | ```bash 34 | bower install ngFileReader 35 | ``` 36 | 37 | or 38 | 39 | ```bash 40 | npm install ngFileReader 41 | ``` 42 | 43 | ## Usage 44 | 45 | Set some attrs of element. 46 | 47 | ```html 48 |
49 | 50 | size:{{file.size | fileSize}} 51 | 52 | 53 | ``` 54 | 55 | Set a reader method. 56 | 57 | ```js 58 | $scope.readMethod = "readAsDataURL"; 59 | ``` 60 | 61 | Add a `on-readed` callback to set file size and img data. 62 | 63 | ```js 64 | $scope.onReaded = function( e, file ){ 65 | 66 | $scope.img = e.target.result; 67 | $scope.file = file; 68 | }; 69 | ``` 70 | 71 | You are able to follow this If you use browserfiy. 72 | 73 | ```js 74 | var app = angular.module('myApp', [require('ngFileReader')]); 75 | ``` 76 | 77 | ## Attribute 78 | 79 | ### filereader 80 | This is `swf` path, if you use ie8 ~ ie9. 81 | 82 | ### multiple 83 | Input multiple property. 84 | 85 | ### debug-mode 86 | Use `swf` only. 87 | 88 | **ex:** 89 | 90 | Set the attr on tag. 91 | 92 | ``` 93 | debug-mode="true" 94 | ``` 95 | 96 | ### accept 97 | accept file extensions. 98 | 99 | ##Parameter 100 | 101 | ### read-method 102 | 103 | This is file reader method,when you selected file to call `read-method` method. 104 | 105 | **ex:** `readAsDataURL`、`readAsText`、`readAsBinaryString` 106 | 107 | Set the attr. 108 | 109 | ```js 110 | read-method="readMethod" 111 | ``` 112 | 113 | Set a string value. 114 | 115 | ```js 116 | $scope.readMethod = "readAsDataURL" 117 | ``` 118 | 119 | ## Event 120 | 121 | ### on-selected `Event` 122 | It will trigger this event if you has selected. 123 | 124 | ### on-readed `Event` 125 | It will trigger this event When the selected file has readed by file reader. 126 | 127 | ## Filter 128 | 129 | ### fileSize 130 | 131 | Transfer file size from number to unit. 132 | 133 | ```html 134 | 135 | {{file.size | fileSize}} 136 | ``` 137 | 138 | You can write this if you need round off to the 2nd decimal place. 139 | 140 | ```html 141 | {{file.size | fileSize:2}} 142 | ``` 143 | 144 | ## Run 145 | 146 | run a server: 147 | 148 | ```bash 149 | grunt server 150 | ``` 151 | 152 | Finally,open your brower,enter [http://localhost:3000/example/index.html](http://localhost/example/index.html). 153 | 154 | 155 | ## Minification 156 | 157 | Just run `npm install` to install dependencies. Then run `grunt` for minification. 158 | 159 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngFileReader", 3 | "version": "0.0.8", 4 | "authors": [ 5 | "SparrowJang " 6 | ], 7 | "description": "This is file reader component on angular", 8 | "main": "src/ngFileReader.js", 9 | "keywords": [ 10 | "file", 11 | "reader", 12 | "html5", 13 | "flash" 14 | ], 15 | "dependencies": { 16 | "angular": "~1.5.0" 17 | }, 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "tests" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | size: 21 | 22 | {{file.size | fileSize}} 23 | 24 | 25 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /images/screenprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparrowJang/ngFileReader/37258289930b6dba8d93c5e80421c13d5f7d42e6/images/screenprint.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngFileReader", 3 | "version": "0.0.8", 4 | "description": "This is file reader component on angular.", 5 | "main": "src/ngFileReader.js", 6 | "keywords": [ 7 | "file", 8 | "reader", 9 | "html5", 10 | "flash" 11 | ], 12 | "devDependencies":{ 13 | "grunt": "~0.4.1", 14 | "grunt-open": "~0.2.0", 15 | "express":"~3.2.2", 16 | "grunt-contrib-uglify": "~0.2.4", 17 | "grunt-express":"~1.2.1", 18 | "matchdep": "~0.1.2" 19 | }, 20 | "author": "sparrow.jang", 21 | "license": "MIT" 22 | } 23 | -------------------------------------------------------------------------------- /src/ngFileReader.js: -------------------------------------------------------------------------------- 1 | 2 | (function( angular ){ 3 | 4 | 'use strict'; 5 | 6 | var APP_NAME = 'ngFileReader'; 7 | 8 | var app = angular.module( APP_NAME, [] ); 9 | 10 | app.directive( 'ngFileReader', function(){ 11 | 12 | /** 13 | * @param {Object} attrs 14 | * @return Object 15 | */ 16 | var parseParams_ = function( attrs ){ 17 | 18 | return { 19 | multiple:attrs.multiple != undefined 20 | }; 21 | }; 22 | 23 | /** 24 | * @param {jQuery|jqlite} $elem 25 | * @param {Object} inputParams 26 | */ 27 | var init_ = function( $elem, inputParams ){ 28 | 29 | var $input = $elem.find( 'input' ); 30 | 31 | if ( inputParams.multiple ) $input.attr( 'multiple', true ); 32 | 33 | }; 34 | 35 | var events = { 36 | 37 | /** 38 | * @param {Scope} scope 39 | * @param {FileList} files 40 | */ 41 | onSelected:function( scope, files ){ 42 | 43 | scope.onSelected( {files:files} ); 44 | }, 45 | 46 | /** 47 | * @param {Scope} scope 48 | * @param {FileList} files 49 | */ 50 | onReadered:function( scope, files ){ 51 | 52 | angular.forEach( files, function( file ){ 53 | 54 | var readMethod = scope.readMethod; 55 | 56 | if ( readMethod ) { 57 | 58 | var fileReader = new FileReader(); 59 | 60 | fileReader.addEventListener( 'loadend', function( e ){ 61 | 62 | scope.onReaded( {event:e,file:file} ); 63 | scope.$apply(); 64 | }); 65 | 66 | fileReader[ readMethod ] && fileReader[ readMethod ]( file, scope.readEncoding ); 67 | 68 | } 69 | }); 70 | 71 | } 72 | }; 73 | 74 | return { 75 | 76 | scope:{ 77 | onSelected:"&", 78 | onReaded:"&", 79 | readMethod:"=", 80 | readEncoding:"=", 81 | accept:"@", 82 | filereader:"@" 83 | }, 84 | 85 | template:"", 86 | 87 | /** 88 | * @param {Scope} scope 89 | * @param {jQuery|jqlite} $elem 90 | * @param {Object} attrs 91 | */ 92 | link:function( scope, $elem, attrs ){ 93 | 94 | var inputParams = parseParams_( attrs ); 95 | 96 | if ( window.File == undefined ) { 97 | 98 | var position = $elem.css('position'), 99 | 100 | initParams = { 101 | multiple:inputParams.multiple, 102 | debugMode:attrs.debugMode, 103 | filereader:scope.filereader, 104 | }; 105 | 106 | if ( position == "" || position == "static" ) { 107 | 108 | $elem.css( "position", "relative" ); 109 | 110 | $.extend( initParams,{ 111 | appendTo:$elem, 112 | position:"absolute", 113 | offsetCss:function(){ 114 | return {left:0,top:0}; 115 | } 116 | }); 117 | 118 | } 119 | 120 | $elem.fileReader( initParams ); 121 | 122 | 123 | } else { 124 | 125 | init_( $elem, inputParams ); 126 | 127 | var ignoreDrag = function( e ){ 128 | 129 | e.preventDefault(); 130 | }; 131 | 132 | $elem.on( "dragenter", ignoreDrag ); 133 | $elem.on( "dragover", ignoreDrag ); 134 | $elem.on( "drop", function( e ){ 135 | 136 | ignoreDrag( e ); 137 | 138 | //console.log( e.dataTransfer.files.length ); 139 | 140 | var originalEvent = e.originalEvent ? e.originalEvent : e, 141 | 142 | files = originalEvent.dataTransfer.files; 143 | 144 | //console.log( originalEvent ); 145 | 146 | events.onSelected( scope, files ); 147 | 148 | events.onReadered( scope, files ); 149 | 150 | }); 151 | 152 | } 153 | 154 | $elem.on( 'change', function( evt ){ 155 | 156 | var files = evt.target.files; 157 | 158 | events.onSelected( scope, files ); 159 | 160 | events.onReadered( scope, files ); 161 | 162 | $elem.find("input").val(''); 163 | //console.log( 'change' ); 164 | scope.$apply(); 165 | }); 166 | 167 | } 168 | }; 169 | 170 | }); 171 | 172 | app.filter( 'fileSize', function(){ 173 | 174 | return function( total, bit ){ 175 | 176 | if ( !total ) return ""; 177 | 178 | var size_types = ["k","m","g","t"], 179 | output = total, 180 | index = -1; 181 | 182 | while ( output >= 1024 ) { 183 | 184 | var output = output / 1024; 185 | 186 | index ++; 187 | 188 | if ( output < 1 || index == 3 ) { 189 | 190 | break; 191 | } 192 | 193 | } 194 | 195 | return output.toFixed( bit ? bit : 1 ) + " " + ( size_types[index]? size_types[index]:"" ); 196 | 197 | }; 198 | }); 199 | 200 | if ( typeof module !== "undefined" ) module.exports = APP_NAME; 201 | 202 | })( angular ); 203 | 204 | -------------------------------------------------------------------------------- /vendor/filereader.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparrowJang/ngFileReader/37258289930b6dba8d93c5e80421c13d5f7d42e6/vendor/filereader.swf -------------------------------------------------------------------------------- /vendor/jquery.FileReader.js: -------------------------------------------------------------------------------- 1 | (function( $ ){ 2 | var readyCallbacks = $.Callbacks('once unique memory'), 3 | inputsCount = 0, 4 | currentTarget = null; 5 | 6 | // if native FileReader support, then dont add the polyfill and make the plugin do nothing 7 | if (window.FileReader) { 8 | $.fn.fileReader = function () { return this; } 9 | return ; 10 | } 11 | 12 | /** 13 | * JQuery Plugin 14 | */ 15 | $.fn.fileReader = function( options ) { 16 | options = $.extend($.fn.fileReader.defaults, options); 17 | 18 | var self = this; 19 | readyCallbacks.add(function() { 20 | return main(self, options); 21 | }); 22 | if ($.isFunction(options.callback)) readyCallbacks.add(options.callback); 23 | 24 | if (!FileAPIProxy.ready) { 25 | FileAPIProxy.init(options); 26 | } 27 | return this; 28 | }; 29 | 30 | /** 31 | * Default options 32 | * allows user set default options 33 | */ 34 | $.fn.fileReader.defaults = { 35 | id : 'fileReaderSWFObject', // ID for the created swf object container, 36 | multiple : null, 37 | accept : null, 38 | label : null, 39 | extensions : null, 40 | filereader : 'files/filereader.swf', // The path to the filereader swf file 41 | expressInstall : null, // The path to the express install swf file 42 | debugMode : false, 43 | callback : false // Callback function when Filereader is ready 44 | }; 45 | 46 | /** 47 | * Plugin callback 48 | * adds an input to registry 49 | */ 50 | var main = function(el, options) { 51 | return el.each(function(i, input) { 52 | input = $(input); 53 | var inputId = input.attr('id'), 54 | label, 55 | clickableElement; 56 | 57 | if (!inputId) { 58 | inputId = 'flashFileInput' + inputsCount; 59 | inputsCount++; 60 | } 61 | label = input.parent('label'); 62 | clickableElement = label.length > 0 ? label : input; 63 | clickableElement.attr('id', clickableElement.attr('id') || inputId); 64 | 65 | 66 | options.multiple = !!(options.multiple === null ? input.attr('multiple') : options.multiple); 67 | options.accept = options.accept === null ? input.attr('accept') : options.accept; 68 | 69 | FileAPIProxy.inputs[inputId] = input; 70 | FileAPIProxy.swfObject.add(clickableElement.attr('id'), options.multiple, options.accept, options.label, options.extensions); 71 | 72 | 73 | clickableElement.css('z-index', 0) 74 | .mouseover(function (e) { 75 | if (inputId !== currentTarget) { 76 | e = e || window.event; 77 | currentTarget = inputId; 78 | FileAPIProxy.swfObject.mouseover(clickableElement.attr('id')); 79 | FileAPIProxy.container 80 | .height(clickableElement.outerHeight()) 81 | .width(clickableElement.outerWidth()) 82 | .css(clickableElement.offset()); 83 | } 84 | }) 85 | .click(function(e) { 86 | e.preventDefault(); 87 | e.stopPropagation(); 88 | e.stopImmediatePropagation(); 89 | return false; 90 | }); 91 | }); 92 | }; 93 | 94 | /** 95 | * Flash FileReader Proxy 96 | */ 97 | window.FileAPIProxy = { 98 | ready: false, 99 | init: function(o) { 100 | var self = this; 101 | this.debugMode = o.debugMode; 102 | this.container = $('
').attr('id', o.id) 103 | .wrap('
') 104 | .parent() 105 | .css({ 106 | position:'fixed', 107 | // top:'0px', 108 | width:'1px', 109 | height:'1px', 110 | display:'inline-block', 111 | background:'transparent', 112 | 'z-index':99999 113 | }) 114 | // Hands over mouse events to original input for css styles 115 | .on('mouseover mouseout mousedown mouseup', function(evt) { 116 | if(currentTarget) $('#' + currentTarget).trigger(evt.type); 117 | }) 118 | .appendTo('body'); 119 | 120 | swfobject.embedSWF(o.filereader, o.id, '100%', '100%', '10', o.expressInstall, {debugMode: o.debugMode ? true : ''}, {'wmode':'transparent','allowScriptAccess':'sameDomain'}, {}, function(e) { 121 | self.swfObject = e.ref; 122 | $(self.swfObject) 123 | .css({ 124 | display: 'block', 125 | outline: 0 126 | }) 127 | .attr('tabindex', 0); 128 | if (self.ready) { 129 | readyCallbacks.fire(); 130 | } 131 | self.ready = e.success && typeof e.ref.add === "function"; 132 | }); 133 | }, 134 | swfObject: null, 135 | container: null, 136 | // Inputs Registry 137 | inputs: {}, 138 | // Readers Registry 139 | readers: {}, 140 | // Receives FileInput events 141 | onFileInputEvent: function(evt) { 142 | if (this.debugMode) console.info('FileInput Event ', evt.type, evt); 143 | if (evt.target in this.inputs) { 144 | var el = this.inputs[evt.target]; 145 | evt.target = el[0]; 146 | if( evt.type === 'change') { 147 | evt.files = new FileList(evt.files); 148 | evt.target = {files: evt.files}; 149 | } 150 | el.trigger(evt); 151 | } 152 | window.focus(); 153 | }, 154 | // Receives FileReader ProgressEvents 155 | onFileReaderEvent: function(evt) { 156 | if (this.debugMode) console.info('FileReader Event ', evt.type, evt, evt.target in this.readers); 157 | if (evt.target in this.readers) { 158 | var reader = this.readers[evt.target]; 159 | evt.target = reader; 160 | reader._handleFlashEvent.call(reader, evt); 161 | } 162 | }, 163 | // Receives flash FileReader Error Events 164 | onFileReaderError: function(error) { 165 | if (this.debugMode) console.log(error); 166 | }, 167 | onSWFReady: function() { 168 | this.container.css({position: 'absolute'}); 169 | this.ready = typeof this.swfObject.add === "function"; 170 | if (this.ready) { 171 | readyCallbacks.fire(); 172 | } 173 | 174 | return true; 175 | } 176 | }; 177 | 178 | 179 | /** 180 | * Add FileReader to the window object 181 | */ 182 | window.FileReader = function () { 183 | // states 184 | this.EMPTY = 0; 185 | this.LOADING = 1; 186 | this.DONE = 2; 187 | 188 | this.readyState = 0; 189 | 190 | // File or Blob data 191 | this.result = null; 192 | 193 | this.error = null; 194 | 195 | // event handler attributes 196 | this.onloadstart = null; 197 | this.onprogress = null; 198 | this.onload = null; 199 | this.onabort = null; 200 | this.onerror = null; 201 | this.onloadend = null; 202 | 203 | // Event Listeners handling using JQuery Callbacks 204 | this._callbacks = { 205 | loadstart : $.Callbacks( "unique" ), 206 | progress : $.Callbacks( "unique" ), 207 | abort : $.Callbacks( "unique" ), 208 | error : $.Callbacks( "unique" ), 209 | load : $.Callbacks( "unique" ), 210 | loadend : $.Callbacks( "unique" ) 211 | }; 212 | 213 | // Custom properties 214 | this._id = null; 215 | }; 216 | 217 | window.FileReader.prototype = { 218 | // async read methods 219 | readAsBinaryString: function (file) { 220 | this._start(file); 221 | FileAPIProxy.swfObject.read(file.input, file.name, 'readAsBinaryString'); 222 | }, 223 | readAsText: function (file, encoding) { 224 | this._start(file); 225 | FileAPIProxy.swfObject.read(file.input, file.name, 'readAsText'); 226 | }, 227 | readAsDataURL: function (file) { 228 | this._start(file); 229 | FileAPIProxy.swfObject.read(file.input, file.name, 'readAsDataURL'); 230 | }, 231 | readAsArrayBuffer: function(file){ 232 | throw("Whoops FileReader.readAsArrayBuffer is unimplemented"); 233 | }, 234 | 235 | abort: function () { 236 | this.result = null; 237 | if (this.readyState === this.EMPTY || this.readyState === this.DONE) return; 238 | FileAPIProxy.swfObject.abort(this._id); 239 | }, 240 | 241 | // Event Target interface 242 | addEventListener: function (type, listener) { 243 | if (type in this._callbacks) this._callbacks[type].add(listener); 244 | }, 245 | removeEventListener: function (type, listener) { 246 | if (type in this._callbacks) this._callbacks[type].remove(listener); 247 | }, 248 | dispatchEvent: function (event) { 249 | event.target = this; 250 | if (event.type in this._callbacks) { 251 | var fn = this['on' + event.type]; 252 | if ($.isFunction(fn)) fn(event); 253 | this._callbacks[event.type].fire(event); 254 | } 255 | return true; 256 | }, 257 | 258 | // Custom private methods 259 | 260 | // Registers FileReader instance for flash callbacks 261 | _register: function(file) { 262 | this._id = file.input + '.' + file.name; 263 | FileAPIProxy.readers[this._id] = this; 264 | }, 265 | _start: function(file) { 266 | this._register(file); 267 | if (this.readyState === this.LOADING) throw {type: 'InvalidStateError', code: 11, message: 'The object is in an invalid state.'}; 268 | }, 269 | _handleFlashEvent: function(evt) { 270 | switch (evt.type) { 271 | case 'loadstart': 272 | this.readyState = this.LOADING; 273 | break; 274 | case 'loadend': 275 | this.readyState = this.DONE; 276 | break; 277 | case 'load': 278 | this.readyState = this.DONE; 279 | this.result = FileAPIProxy.swfObject.result(this._id); 280 | break; 281 | case 'error': 282 | this.result = null; 283 | this.error = { 284 | name: 'NotReadableError', 285 | message: 'The File cannot be read!' 286 | }; 287 | } 288 | this.dispatchEvent(new FileReaderEvent(evt)); 289 | } 290 | }; 291 | 292 | /** 293 | * FileReader ProgressEvent implenting Event interface 294 | */ 295 | FileReaderEvent = function (e) { 296 | this.initEvent(e); 297 | }; 298 | 299 | FileReaderEvent.prototype = { 300 | initEvent: function (event) { 301 | $.extend(this, { 302 | type: null, 303 | target: null, 304 | currentTarget: null, 305 | 306 | eventPhase: 2, 307 | 308 | bubbles: false, 309 | cancelable: false, 310 | 311 | defaultPrevented: false, 312 | 313 | isTrusted: false, 314 | timeStamp: new Date().getTime() 315 | }, event); 316 | }, 317 | stopPropagation: function (){ 318 | }, 319 | stopImmediatePropagation: function (){ 320 | }, 321 | preventDefault: function (){ 322 | } 323 | }; 324 | 325 | /** 326 | * FileList interface (Object with item function) 327 | */ 328 | FileList = function(array) { 329 | if (array) { 330 | for (var i = 0; i < array.length; i++) { 331 | this[i] = array[i]; 332 | } 333 | this.length = array.length; 334 | } else { 335 | this.length = 0; 336 | } 337 | }; 338 | 339 | FileList.prototype = { 340 | item: function(index) { 341 | if (index in this) return this[index]; 342 | return null; 343 | } 344 | }; 345 | 346 | })( jQuery ); 347 | -------------------------------------------------------------------------------- /vendor/jquery.FileReader.position.ver.js: -------------------------------------------------------------------------------- 1 | (function( $ ){ 2 | var readyCallbacks = $.Callbacks('once unique memory'), 3 | inputsCount = 0, 4 | currentTarget = null; 5 | 6 | // if native FileReader support, then dont add the polyfill and make the plugin do nothing 7 | if (window.FileReader) { 8 | $.fn.fileReader = function() { return this; }; 9 | return ; 10 | } 11 | 12 | /** 13 | * JQuery Plugin 14 | */ 15 | $.fn.fileReader = function( options ) { 16 | options = $.extend({}, $.fn.fileReader.defaults, options); 17 | 18 | var self = this; 19 | readyCallbacks.add(function() { 20 | return main(self, options); 21 | }); 22 | if ($.isFunction(options.callback)) readyCallbacks.add(options.callback); 23 | 24 | if (!FileAPIProxy.ready && !FileAPIProxy.hasInitialized) { 25 | FileAPIProxy.init(options); 26 | } 27 | return this; 28 | }; 29 | 30 | /** 31 | * Default options 32 | * allows user set default options 33 | */ 34 | $.fn.fileReader.defaults = { 35 | id : 'fileReaderSWFObject', // ID for the created swf object container, 36 | multiple : null, 37 | accept : null, 38 | label : null, 39 | extensions : null, 40 | filereader : 'files/filereader.swf', // The path to the filereader swf file 41 | expressInstall : null, // The path to the express install swf file 42 | debugMode : false, 43 | callback : false, // Callback function when Filereader is ready 44 | position : 'fixed', 45 | appendTo : 'body', 46 | offsetCss : function (trigger) { 47 | return trigger.offset(); 48 | } 49 | }; 50 | 51 | /** 52 | * Plugin callback 53 | * adds an input to registry 54 | */ 55 | var main = function(el, options) { 56 | return el.each(function(i, input) { 57 | var trigger = $(options.trigger || input); 58 | input = $(input); 59 | var id = input.attr('id'); 60 | if (!id) { 61 | id = 'flashFileInput' + inputsCount; 62 | input.attr('id', id); 63 | inputsCount++; 64 | } 65 | options.multiple = !!(options.multiple === null ? input.attr('multiple') : options.multiple); 66 | options.accept = options.accept === null ? input.attr('accept') : options.accept; 67 | 68 | FileAPIProxy.inputs[id] = input; 69 | FileAPIProxy.swfObject.add(id, options.multiple, options.accept, options.label, options.extensions); 70 | 71 | trigger.add(input) 72 | .css('z-index', 0) 73 | .mouseover(function (e) { 74 | if (id !== currentTarget) { 75 | e = e || window.event; 76 | currentTarget = id; 77 | FileAPIProxy.swfObject.mouseover(id); 78 | } 79 | 80 | FileAPIProxy.container 81 | .height(trigger.outerHeight()) 82 | .width(trigger.outerWidth()) 83 | .css(options.offsetCss(trigger)); 84 | }) 85 | .click(function(e) { 86 | e.preventDefault(); 87 | e.stopPropagation(); 88 | e.stopImmediatePropagation(); 89 | return false; 90 | }); 91 | }); 92 | }; 93 | 94 | /** 95 | * Flash FileReader Proxy 96 | */ 97 | window.FileAPIProxy = { 98 | ready: false, 99 | hasInitialized: false, 100 | init: function(o) { 101 | var self = this; 102 | this.hasInitialized = true; 103 | this.debugMode = o.debugMode; 104 | this.container = $('
').attr('id', o.id) 105 | .wrap('
') 106 | .parent() 107 | .css({ 108 | position: o.position, 109 | // top:'0px', 110 | width:'1px', 111 | height:'1px', 112 | display:'inline-block', 113 | background:'transparent', 114 | 'z-index':99999 115 | }) 116 | // Hands over mouse events to original input for css styles 117 | .on('mouseover mouseout mousedown mouseup', function(evt) { 118 | if(currentTarget) $('#' + currentTarget).trigger(evt.type); 119 | }) 120 | .appendTo(o.appendTo); 121 | 122 | function swfLoadEvent(e, fn) { 123 | var initialTimeout = setTimeout(function () { 124 | //Ensure Flash Player's PercentLoaded method is available and returns a value 125 | if (typeof e.ref.PercentLoaded !== 'undefined') { 126 | //Set up a timer to periodically check value of PercentLoaded 127 | var loadCheckInterval = setInterval(function () { 128 | if (self.debugMode) console.info('SWF Load Percentage: ', e.ref.PercentLoaded()); 129 | //Once value == 100 (fully loaded) we can do whatever we want 130 | if (e.ref.PercentLoaded() === 100) { 131 | fn(); 132 | clearInterval(loadCheckInterval); 133 | } 134 | }, 500); 135 | } 136 | }, 200); 137 | } 138 | 139 | swfobject.embedSWF(o.filereader, o.id, '100%', '100%', '10', o.expressInstall, {debugMode: o.debugMode ? true : ''}, {'wmode':'transparent','allowScriptAccess':'sameDomain'}, {}, function(e) { 140 | self.swfObject = e.ref; 141 | $(self.swfObject) 142 | .css({ 143 | display: 'block', 144 | outline: 0 145 | }) 146 | .attr('tabindex', 0); 147 | 148 | if (e.success) { 149 | swfLoadEvent(e, function () { 150 | if (self.ready) { 151 | readyCallbacks.fire(); 152 | } 153 | self.ready = $.isFunction(e.ref.add); 154 | }); 155 | } else { 156 | self.hasInitialized = false; 157 | } 158 | }); 159 | }, 160 | swfObject: null, 161 | container: null, 162 | // Inputs Registry 163 | inputs: {}, 164 | // Readers Registry 165 | readers: {}, 166 | // Receives FileInput events 167 | onFileInputEvent: function(evt) { 168 | if (this.debugMode) console.info('FileInput Event ', evt.type, evt); 169 | if (evt.target in this.inputs) { 170 | var el = this.inputs[evt.target]; 171 | evt.target = el[0]; 172 | if( evt.type === 'change') { 173 | evt.files = new FileList(evt.files); 174 | evt.target = {files: evt.files}; 175 | } 176 | el.trigger(evt); 177 | } 178 | window.focus(); 179 | }, 180 | // Receives FileReader ProgressEvents 181 | onFileReaderEvent: function(evt) { 182 | if (this.debugMode) console.info('FileReader Event ', evt.type, evt, evt.target in this.readers); 183 | if (evt.target in this.readers) { 184 | var reader = this.readers[evt.target]; 185 | evt.target = reader; 186 | reader._handleFlashEvent.call(reader, evt); 187 | } 188 | }, 189 | // Receives flash FileReader Error Events 190 | onFileReaderError: function(error) { 191 | if (this.debugMode) console.log(error); 192 | }, 193 | onSWFReady: function () { 194 | this.container.css({position: 'absolute'}); 195 | this.ready = $.isFunction(this.swfObject.add); 196 | if (this.ready) { 197 | readyCallbacks.fire(); 198 | } 199 | 200 | return true; 201 | } 202 | }; 203 | 204 | 205 | /** 206 | * Add FileReader to the window object 207 | */ 208 | window.FileReader = function () { 209 | // states 210 | this.EMPTY = 0; 211 | this.LOADING = 1; 212 | this.DONE = 2; 213 | 214 | this.readyState = 0; 215 | 216 | // File or Blob data 217 | this.result = null; 218 | 219 | this.error = null; 220 | 221 | // event handler attributes 222 | this.onloadstart = null; 223 | this.onprogress = null; 224 | this.onload = null; 225 | this.onabort = null; 226 | this.onerror = null; 227 | this.onloadend = null; 228 | 229 | // Event Listeners handling using JQuery Callbacks 230 | this._callbacks = { 231 | loadstart : $.Callbacks( "unique" ), 232 | progress : $.Callbacks( "unique" ), 233 | abort : $.Callbacks( "unique" ), 234 | error : $.Callbacks( "unique" ), 235 | load : $.Callbacks( "unique" ), 236 | loadend : $.Callbacks( "unique" ) 237 | }; 238 | 239 | // Custom properties 240 | this._id = null; 241 | }; 242 | 243 | window.FileReader.prototype = { 244 | // async read methods 245 | readAsBinaryString: function (file) { 246 | this._start(file); 247 | FileAPIProxy.swfObject.read(file.input, file.name, 'readAsBinaryString'); 248 | }, 249 | readAsText: function (file, encoding) { 250 | this._start(file); 251 | FileAPIProxy.swfObject.read(file.input, file.name, 'readAsText'); 252 | }, 253 | readAsDataURL: function (file) { 254 | this._start(file); 255 | FileAPIProxy.swfObject.read(file.input, file.name, 'readAsDataURL'); 256 | }, 257 | readAsArrayBuffer: function(file){ 258 | throw("Whoops FileReader.readAsArrayBuffer is unimplemented"); 259 | }, 260 | 261 | abort: function () { 262 | this.result = null; 263 | if (this.readyState === this.EMPTY || this.readyState === this.DONE) return; 264 | FileAPIProxy.swfObject.abort(this._id); 265 | }, 266 | 267 | // Event Target interface 268 | addEventListener: function (type, listener) { 269 | if (type in this._callbacks) this._callbacks[type].add(listener); 270 | }, 271 | removeEventListener: function (type, listener) { 272 | if (type in this._callbacks) this._callbacks[type].remove(listener); 273 | }, 274 | dispatchEvent: function (event) { 275 | event.target = this; 276 | if (event.type in this._callbacks) { 277 | var fn = this['on' + event.type]; 278 | if ($.isFunction(fn)) fn(event); 279 | this._callbacks[event.type].fire(event); 280 | } 281 | return true; 282 | }, 283 | 284 | // Custom private methods 285 | 286 | // Registers FileReader instance for flash callbacks 287 | _register: function(file) { 288 | this._id = file.input + '.' + file.name; 289 | FileAPIProxy.readers[this._id] = this; 290 | }, 291 | _start: function(file) { 292 | this._register(file); 293 | if (this.readyState === this.LOADING) throw {type: 'InvalidStateError', code: 11, message: 'The object is in an invalid state.'}; 294 | }, 295 | _handleFlashEvent: function(evt) { 296 | switch (evt.type) { 297 | case 'loadstart': 298 | this.readyState = this.LOADING; 299 | break; 300 | case 'loadend': 301 | this.readyState = this.DONE; 302 | break; 303 | case 'load': 304 | this.readyState = this.DONE; 305 | this.result = FileAPIProxy.swfObject.result(this._id); 306 | break; 307 | case 'error': 308 | this.result = null; 309 | this.error = { 310 | name: 'NotReadableError', 311 | message: 'The File cannot be read!' 312 | }; 313 | } 314 | this.dispatchEvent(new FileReaderEvent(evt)); 315 | } 316 | }; 317 | 318 | /** 319 | * FileReader ProgressEvent implenting Event interface 320 | */ 321 | FileReaderEvent = function (e) { 322 | this.initEvent(e); 323 | }; 324 | 325 | FileReaderEvent.prototype = { 326 | initEvent: function (event) { 327 | $.extend(this, { 328 | type: null, 329 | target: null, 330 | currentTarget: null, 331 | 332 | eventPhase: 2, 333 | 334 | bubbles: false, 335 | cancelable: false, 336 | 337 | defaultPrevented: false, 338 | 339 | isTrusted: false, 340 | timeStamp: new Date().getTime() 341 | }, event); 342 | }, 343 | stopPropagation: function (){ 344 | }, 345 | stopImmediatePropagation: function (){ 346 | }, 347 | preventDefault: function (){ 348 | } 349 | }; 350 | 351 | /** 352 | * FileList interface (Object with item function) 353 | */ 354 | FileList = function(array) { 355 | if (array) { 356 | for (var i = 0; i < array.length; i++) { 357 | this[i] = array[i]; 358 | } 359 | this.length = array.length; 360 | } else { 361 | this.length = 0; 362 | } 363 | }; 364 | 365 | FileList.prototype = { 366 | item: function(index) { 367 | if (index in this) return this[index]; 368 | return null; 369 | } 370 | }; 371 | 372 | })( jQuery ); 373 | -------------------------------------------------------------------------------- /vendor/swfobject.js: -------------------------------------------------------------------------------- 1 | /* SWFObject v2.2 2 | is released under the MIT License 3 | */ 4 | var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='"+af+"";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab