2014-07-17 16:45:12 +02:00
/ * *
* mOxie - multi - runtime File API & XMLHttpRequest L2 Polyfill
* v1 . 2.1
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
*
* Date : 2014 - 05 - 14
* /
/ * *
* Compiled inline version . ( Library mode )
* /
/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */
/*globals $code */
( function ( exports , undefined ) {
"use strict" ;
var modules = { } ;
function require ( ids , callback ) {
var module , defs = [ ] ;
for ( var i = 0 ; i < ids . length ; ++ i ) {
module = modules [ ids [ i ] ] || resolve ( ids [ i ] ) ;
if ( ! module ) {
throw 'module definition dependecy not found: ' + ids [ i ] ;
}
defs . push ( module ) ;
}
callback . apply ( null , defs ) ;
}
function define ( id , dependencies , definition ) {
if ( typeof id !== 'string' ) {
throw 'invalid module definition, module id must be defined and be a string' ;
}
if ( dependencies === undefined ) {
throw 'invalid module definition, dependencies must be specified' ;
}
if ( definition === undefined ) {
throw 'invalid module definition, definition function must be specified' ;
}
require ( dependencies , function ( ) {
modules [ id ] = definition . apply ( null , arguments ) ;
} ) ;
}
function defined ( id ) {
return ! ! modules [ id ] ;
}
function resolve ( id ) {
var target = exports ;
var fragments = id . split ( /[.\/]/ ) ;
for ( var fi = 0 ; fi < fragments . length ; ++ fi ) {
if ( ! target [ fragments [ fi ] ] ) {
return ;
}
target = target [ fragments [ fi ] ] ;
}
return target ;
}
function expose ( ids ) {
for ( var i = 0 ; i < ids . length ; i ++ ) {
var target = exports ;
var id = ids [ i ] ;
var fragments = id . split ( /[.\/]/ ) ;
for ( var fi = 0 ; fi < fragments . length - 1 ; ++ fi ) {
if ( target [ fragments [ fi ] ] === undefined ) {
target [ fragments [ fi ] ] = { } ;
}
target = target [ fragments [ fi ] ] ;
}
target [ fragments [ fragments . length - 1 ] ] = modules [ id ] ;
}
}
// Included from: src/javascript/core/utils/Basic.js
/ * *
* Basic . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/core/utils/Basic' , [ ] , function ( ) {
/ * *
Gets the true type of the built - in object ( better version of typeof ) .
@ author Angus Croll ( http : //javascriptweblog.wordpress.com/)
@ method typeOf
@ for Utils
@ static
@ param { Object } o Object to check .
@ return { String } Object [ [ Class ] ]
* /
var typeOf = function ( o ) {
var undef ;
if ( o === undef ) {
return 'undefined' ;
} else if ( o === null ) {
return 'null' ;
} else if ( o . nodeType ) {
return 'node' ;
}
// the snippet below is awesome, however it fails to detect null, undefined and arguments types in IE lte 8
return ( { } ) . toString . call ( o ) . match ( /\s([a-z|A-Z]+)/ ) [ 1 ] . toLowerCase ( ) ;
} ;
/ * *
Extends the specified object with another object .
@ method extend
@ static
@ param { Object } target Object to extend .
@ param { Object } [ obj ] * Multiple objects to extend with .
@ return { Object } Same as target , the extended object .
* /
var extend = function ( target ) {
var undef ;
each ( arguments , function ( arg , i ) {
if ( i > 0 ) {
each ( arg , function ( value , key ) {
if ( value !== undef ) {
if ( typeOf ( target [ key ] ) === typeOf ( value ) && ! ! ~ inArray ( typeOf ( value ) , [ 'array' , 'object' ] ) ) {
extend ( target [ key ] , value ) ;
} else {
target [ key ] = value ;
}
}
} ) ;
}
} ) ;
return target ;
} ;
/ * *
Executes the callback function for each item in array / object . If you return false in the
callback it will break the loop .
@ method each
@ static
@ param { Object } obj Object to iterate .
@ param { function } callback Callback function to execute for each item .
* /
var each = function ( obj , callback ) {
var length , key , i , undef ;
if ( obj ) {
try {
length = obj . length ;
} catch ( ex ) {
length = undef ;
}
if ( length === undef ) {
// Loop object items
for ( key in obj ) {
if ( obj . hasOwnProperty ( key ) ) {
if ( callback ( obj [ key ] , key ) === false ) {
return ;
}
}
}
} else {
// Loop array items
for ( i = 0 ; i < length ; i ++ ) {
if ( callback ( obj [ i ] , i ) === false ) {
return ;
}
}
}
}
} ;
/ * *
Checks if object is empty .
@ method isEmptyObj
@ static
@ param { Object } o Object to check .
@ return { Boolean }
* /
var isEmptyObj = function ( obj ) {
var prop ;
if ( ! obj || typeOf ( obj ) !== 'object' ) {
return true ;
}
for ( prop in obj ) {
return false ;
}
return true ;
} ;
/ * *
Recieve an array of functions ( usually async ) to call in sequence , each function
receives a callback as first argument that it should call , when it completes . Finally ,
after everything is complete , main callback is called . Passing truthy value to the
callback as a first argument will interrupt the sequence and invoke main callback
immediately .
@ method inSeries
@ static
@ param { Array } queue Array of functions to call in sequence
@ param { Function } cb Main callback that is called in the end , or in case of error
* /
var inSeries = function ( queue , cb ) {
var i = 0 , length = queue . length ;
if ( typeOf ( cb ) !== 'function' ) {
cb = function ( ) { } ;
}
if ( ! queue || ! queue . length ) {
cb ( ) ;
}
function callNext ( i ) {
if ( typeOf ( queue [ i ] ) === 'function' ) {
queue [ i ] ( function ( error ) {
/*jshint expr:true */
++ i < length && ! error ? callNext ( i ) : cb ( error ) ;
} ) ;
}
}
callNext ( i ) ;
} ;
/ * *
Recieve an array of functions ( usually async ) to call in parallel , each function
receives a callback as first argument that it should call , when it completes . After
everything is complete , main callback is called . Passing truthy value to the
callback as a first argument will interrupt the process and invoke main callback
immediately .
@ method inParallel
@ static
@ param { Array } queue Array of functions to call in sequence
@ param { Function } cb Main callback that is called in the end , or in case of erro
* /
var inParallel = function ( queue , cb ) {
var count = 0 , num = queue . length , cbArgs = new Array ( num ) ;
each ( queue , function ( fn , i ) {
fn ( function ( error ) {
if ( error ) {
return cb ( error ) ;
}
var args = [ ] . slice . call ( arguments ) ;
args . shift ( ) ; // strip error - undefined or not
cbArgs [ i ] = args ;
count ++ ;
if ( count === num ) {
cbArgs . unshift ( null ) ;
cb . apply ( this , cbArgs ) ;
}
} ) ;
} ) ;
} ;
/ * *
Find an element in array and return it ' s index if present , otherwise return - 1.
@ method inArray
@ static
@ param { Mixed } needle Element to find
@ param { Array } array
@ return { Int } Index of the element , or - 1 if not found
* /
var inArray = function ( needle , array ) {
if ( array ) {
if ( Array . prototype . indexOf ) {
return Array . prototype . indexOf . call ( array , needle ) ;
}
for ( var i = 0 , length = array . length ; i < length ; i ++ ) {
if ( array [ i ] === needle ) {
return i ;
}
}
}
return - 1 ;
} ;
/ * *
Returns elements of first array if they are not present in second . And false - otherwise .
@ private
@ method arrayDiff
@ param { Array } needles
@ param { Array } array
@ return { Array | Boolean }
* /
var arrayDiff = function ( needles , array ) {
var diff = [ ] ;
if ( typeOf ( needles ) !== 'array' ) {
needles = [ needles ] ;
}
if ( typeOf ( array ) !== 'array' ) {
array = [ array ] ;
}
for ( var i in needles ) {
if ( inArray ( needles [ i ] , array ) === - 1 ) {
diff . push ( needles [ i ] ) ;
}
}
return diff . length ? diff : false ;
} ;
/ * *
Find intersection of two arrays .
@ private
@ method arrayIntersect
@ param { Array } array1
@ param { Array } array2
@ return { Array } Intersection of two arrays or null if there is none
* /
var arrayIntersect = function ( array1 , array2 ) {
var result = [ ] ;
each ( array1 , function ( item ) {
if ( inArray ( item , array2 ) !== - 1 ) {
result . push ( item ) ;
}
} ) ;
return result . length ? result : null ;
} ;
/ * *
Forces anything into an array .
@ method toArray
@ static
@ param { Object } obj Object with length field .
@ return { Array } Array object containing all items .
* /
var toArray = function ( obj ) {
var i , arr = [ ] ;
for ( i = 0 ; i < obj . length ; i ++ ) {
arr [ i ] = obj [ i ] ;
}
return arr ;
} ;
/ * *
Generates an unique ID . This is 99.99 % unique since it takes the current time and 5 random numbers .
The only way a user would be able to get the same ID is if the two persons at the same exact milisecond manages
to get 5 the same random numbers between 0 - 65535 it also uses a counter so each call will be guaranteed to be page unique .
It ' s more probable for the earth to be hit with an ansteriod . Y
@ method guid
@ static
@ param { String } prefix to prepend ( by default 'o' will be prepended ) .
@ method guid
@ return { String } Virtually unique id .
* /
var guid = ( function ( ) {
var counter = 0 ;
return function ( prefix ) {
var guid = new Date ( ) . getTime ( ) . toString ( 32 ) , i ;
for ( i = 0 ; i < 5 ; i ++ ) {
guid += Math . floor ( Math . random ( ) * 65535 ) . toString ( 32 ) ;
}
return ( prefix || 'o_' ) + guid + ( counter ++ ) . toString ( 32 ) ;
} ;
} ( ) ) ;
/ * *
Trims white spaces around the string
@ method trim
@ static
@ param { String } str
@ return { String }
* /
var trim = function ( str ) {
if ( ! str ) {
return str ;
}
return String . prototype . trim ? String . prototype . trim . call ( str ) : str . toString ( ) . replace ( /^\s*/ , '' ) . replace ( /\s*$/ , '' ) ;
} ;
/ * *
Parses the specified size string into a byte value . For example 10 kb becomes 10240.
@ method parseSizeStr
@ static
@ param { String / Number } size String to parse or number to just pass through .
@ return { Number } Size in bytes .
* /
var parseSizeStr = function ( size ) {
if ( typeof ( size ) !== 'string' ) {
return size ;
}
var muls = {
t : 1099511627776 ,
g : 1073741824 ,
m : 1048576 ,
k : 1024
} ,
mul ;
size = /^([0-9]+)([mgk]?)$/ . exec ( size . toLowerCase ( ) . replace ( /[^0-9mkg]/g , '' ) ) ;
mul = size [ 2 ] ;
size = + size [ 1 ] ;
if ( muls . hasOwnProperty ( mul ) ) {
size *= muls [ mul ] ;
}
return size ;
} ;
return {
guid : guid ,
typeOf : typeOf ,
extend : extend ,
each : each ,
isEmptyObj : isEmptyObj ,
inSeries : inSeries ,
inParallel : inParallel ,
inArray : inArray ,
arrayDiff : arrayDiff ,
arrayIntersect : arrayIntersect ,
toArray : toArray ,
trim : trim ,
parseSizeStr : parseSizeStr
} ;
} ) ;
// Included from: src/javascript/core/I18n.js
/ * *
* I18n . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( "moxie/core/I18n" , [
"moxie/core/utils/Basic"
] , function ( Basic ) {
var i18n = { } ;
return {
/ * *
* Extends the language pack object with new items .
*
* @ param { Object } pack Language pack items to add .
* @ return { Object } Extended language pack object .
* /
addI18n : function ( pack ) {
return Basic . extend ( i18n , pack ) ;
} ,
/ * *
* Translates the specified string by checking for the english string in the language pack lookup .
*
* @ param { String } str String to look for .
* @ return { String } Translated string or the input string if it wasn ' t found .
* /
translate : function ( str ) {
return i18n [ str ] || str ;
} ,
/ * *
* Shortcut for translate function
*
* @ param { String } str String to look for .
* @ return { String } Translated string or the input string if it wasn ' t found .
* /
_ : function ( str ) {
return this . translate ( str ) ;
} ,
/ * *
* Pseudo sprintf implementation - simple way to replace tokens with specified values .
*
* @ param { String } str String with tokens
* @ return { String } String with replaced tokens
* /
sprintf : function ( str ) {
var args = [ ] . slice . call ( arguments , 1 ) ;
return str . replace ( /%[a-z]/g , function ( ) {
var value = args . shift ( ) ;
return Basic . typeOf ( value ) !== 'undefined' ? value : '' ;
} ) ;
}
} ;
} ) ;
// Included from: src/javascript/core/utils/Mime.js
/ * *
* Mime . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( "moxie/core/utils/Mime" , [
"moxie/core/utils/Basic" ,
"moxie/core/I18n"
] , function ( Basic , I18n ) {
var mimeData = "" +
"application/msword,doc dot," +
"application/pdf,pdf," +
"application/pgp-signature,pgp," +
"application/postscript,ps ai eps," +
"application/rtf,rtf," +
"application/vnd.ms-excel,xls xlb," +
"application/vnd.ms-powerpoint,ppt pps pot," +
"application/zip,zip," +
"application/x-shockwave-flash,swf swfl," +
"application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx," +
"application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx," +
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx," +
"application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx," +
"application/vnd.openxmlformats-officedocument.presentationml.template,potx," +
"application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx," +
"application/x-javascript,js," +
"application/json,json," +
"audio/mpeg,mp3 mpga mpega mp2," +
"audio/x-wav,wav," +
"audio/x-m4a,m4a," +
"audio/ogg,oga ogg," +
"audio/aiff,aiff aif," +
"audio/flac,flac," +
"audio/aac,aac," +
"audio/ac3,ac3," +
"audio/x-ms-wma,wma," +
"image/bmp,bmp," +
"image/gif,gif," +
"image/jpeg,jpg jpeg jpe," +
"image/photoshop,psd," +
"image/png,png," +
"image/svg+xml,svg svgz," +
"image/tiff,tiff tif," +
"text/plain,asc txt text diff log," +
"text/html,htm html xhtml," +
"text/css,css," +
"text/csv,csv," +
"text/rtf,rtf," +
"video/mpeg,mpeg mpg mpe m2v," +
"video/quicktime,qt mov," +
"video/mp4,mp4," +
"video/x-m4v,m4v," +
"video/x-flv,flv," +
"video/x-ms-wmv,wmv," +
"video/avi,avi," +
"video/webm,webm," +
"video/3gpp,3gpp 3gp," +
"video/3gpp2,3g2," +
"video/vnd.rn-realvideo,rv," +
"video/ogg,ogv," +
"video/x-matroska,mkv," +
"application/vnd.oasis.opendocument.formula-template,otf," +
"application/octet-stream,exe" ;
var Mime = {
mimes : { } ,
extensions : { } ,
// Parses the default mime types string into a mimes and extensions lookup maps
addMimeType : function ( mimeData ) {
var items = mimeData . split ( /,/ ) , i , ii , ext ;
for ( i = 0 ; i < items . length ; i += 2 ) {
ext = items [ i + 1 ] . split ( / / ) ;
// extension to mime lookup
for ( ii = 0 ; ii < ext . length ; ii ++ ) {
this . mimes [ ext [ ii ] ] = items [ i ] ;
}
// mime to extension lookup
this . extensions [ items [ i ] ] = ext ;
}
} ,
extList2mimes : function ( filters , addMissingExtensions ) {
var self = this , ext , i , ii , type , mimes = [ ] ;
// convert extensions to mime types list
for ( i = 0 ; i < filters . length ; i ++ ) {
ext = filters [ i ] . extensions . split ( /\s*,\s*/ ) ;
for ( ii = 0 ; ii < ext . length ; ii ++ ) {
// if there's an asterisk in the list, then accept attribute is not required
if ( ext [ ii ] === '*' ) {
return [ ] ;
}
type = self . mimes [ ext [ ii ] ] ;
if ( ! type ) {
if ( addMissingExtensions && /^\w+$/ . test ( ext [ ii ] ) ) {
mimes . push ( '.' + ext [ ii ] ) ;
} else {
return [ ] ; // accept all
}
} else if ( Basic . inArray ( type , mimes ) === - 1 ) {
mimes . push ( type ) ;
}
}
}
return mimes ;
} ,
mimes2exts : function ( mimes ) {
var self = this , exts = [ ] ;
Basic . each ( mimes , function ( mime ) {
if ( mime === '*' ) {
exts = [ ] ;
return false ;
}
// check if this thing looks like mime type
var m = mime . match ( /^(\w+)\/(\*|\w+)$/ ) ;
if ( m ) {
if ( m [ 2 ] === '*' ) {
// wildcard mime type detected
Basic . each ( self . extensions , function ( arr , mime ) {
if ( ( new RegExp ( '^' + m [ 1 ] + '/' ) ) . test ( mime ) ) {
[ ] . push . apply ( exts , self . extensions [ mime ] ) ;
}
} ) ;
} else if ( self . extensions [ mime ] ) {
[ ] . push . apply ( exts , self . extensions [ mime ] ) ;
}
}
} ) ;
return exts ;
} ,
mimes2extList : function ( mimes ) {
var accept = [ ] , exts = [ ] ;
if ( Basic . typeOf ( mimes ) === 'string' ) {
mimes = Basic . trim ( mimes ) . split ( /\s*,\s*/ ) ;
}
exts = this . mimes2exts ( mimes ) ;
accept . push ( {
title : I18n . translate ( 'Files' ) ,
extensions : exts . length ? exts . join ( ',' ) : '*'
} ) ;
// save original mimes string
accept . mimes = mimes ;
return accept ;
} ,
getFileExtension : function ( fileName ) {
var matches = fileName && fileName . match ( /\.([^.]+)$/ ) ;
if ( matches ) {
return matches [ 1 ] . toLowerCase ( ) ;
}
return '' ;
} ,
getFileMime : function ( fileName ) {
return this . mimes [ this . getFileExtension ( fileName ) ] || '' ;
}
} ;
Mime . addMimeType ( mimeData ) ;
return Mime ;
} ) ;
// Included from: src/javascript/core/utils/Env.js
/ * *
* Env . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( "moxie/core/utils/Env" , [
"moxie/core/utils/Basic"
] , function ( Basic ) {
// UAParser.js v0.6.2
// Lightweight JavaScript-based User-Agent string parser
// https://github.com/faisalman/ua-parser-js
//
// Copyright © 2012-2013 Faisalman <fyzlman@gmail.com>
// Dual licensed under GPLv2 & MIT
var UAParser = ( function ( undefined ) {
//////////////
// Constants
/////////////
var EMPTY = '' ,
UNKNOWN = '?' ,
FUNC _TYPE = 'function' ,
UNDEF _TYPE = 'undefined' ,
OBJ _TYPE = 'object' ,
MAJOR = 'major' ,
MODEL = 'model' ,
NAME = 'name' ,
TYPE = 'type' ,
VENDOR = 'vendor' ,
VERSION = 'version' ,
ARCHITECTURE = 'architecture' ,
CONSOLE = 'console' ,
MOBILE = 'mobile' ,
TABLET = 'tablet' ;
///////////
// Helper
//////////
var util = {
has : function ( str1 , str2 ) {
return str2 . toLowerCase ( ) . indexOf ( str1 . toLowerCase ( ) ) !== - 1 ;
} ,
lowerize : function ( str ) {
return str . toLowerCase ( ) ;
}
} ;
///////////////
// Map helper
//////////////
var mapper = {
rgx : function ( ) {
// loop through all regexes maps
for ( var result , i = 0 , j , k , p , q , matches , match , args = arguments ; i < args . length ; i += 2 ) {
var regex = args [ i ] , // even sequence (0,2,4,..)
props = args [ i + 1 ] ; // odd sequence (1,3,5,..)
// construct object barebones
if ( typeof ( result ) === UNDEF _TYPE ) {
result = { } ;
for ( p in props ) {
q = props [ p ] ;
if ( typeof ( q ) === OBJ _TYPE ) {
result [ q [ 0 ] ] = undefined ;
} else {
result [ q ] = undefined ;
}
}
}
// try matching uastring with regexes
for ( j = k = 0 ; j < regex . length ; j ++ ) {
matches = regex [ j ] . exec ( this . getUA ( ) ) ;
if ( ! ! matches ) {
for ( p = 0 ; p < props . length ; p ++ ) {
match = matches [ ++ k ] ;
q = props [ p ] ;
// check if given property is actually array
if ( typeof ( q ) === OBJ _TYPE && q . length > 0 ) {
if ( q . length == 2 ) {
if ( typeof ( q [ 1 ] ) == FUNC _TYPE ) {
// assign modified match
result [ q [ 0 ] ] = q [ 1 ] . call ( this , match ) ;
} else {
// assign given value, ignore regex match
result [ q [ 0 ] ] = q [ 1 ] ;
}
} else if ( q . length == 3 ) {
// check whether function or regex
if ( typeof ( q [ 1 ] ) === FUNC _TYPE && ! ( q [ 1 ] . exec && q [ 1 ] . test ) ) {
// call function (usually string mapper)
result [ q [ 0 ] ] = match ? q [ 1 ] . call ( this , match , q [ 2 ] ) : undefined ;
} else {
// sanitize match using given regex
result [ q [ 0 ] ] = match ? match . replace ( q [ 1 ] , q [ 2 ] ) : undefined ;
}
} else if ( q . length == 4 ) {
result [ q [ 0 ] ] = match ? q [ 3 ] . call ( this , match . replace ( q [ 1 ] , q [ 2 ] ) ) : undefined ;
}
} else {
result [ q ] = match ? match : undefined ;
}
}
break ;
}
}
if ( ! ! matches ) break ; // break the loop immediately if match found
}
return result ;
} ,
str : function ( str , map ) {
for ( var i in map ) {
// check if array
if ( typeof ( map [ i ] ) === OBJ _TYPE && map [ i ] . length > 0 ) {
for ( var j = 0 ; j < map [ i ] . length ; j ++ ) {
if ( util . has ( map [ i ] [ j ] , str ) ) {
return ( i === UNKNOWN ) ? undefined : i ;
}
}
} else if ( util . has ( map [ i ] , str ) ) {
return ( i === UNKNOWN ) ? undefined : i ;
}
}
return str ;
}
} ;
///////////////
// String map
//////////////
var maps = {
browser : {
oldsafari : {
major : {
'1' : [ '/8' , '/1' , '/3' ] ,
'2' : '/4' ,
'?' : '/'
} ,
version : {
'1.0' : '/8' ,
'1.2' : '/1' ,
'1.3' : '/3' ,
'2.0' : '/412' ,
'2.0.2' : '/416' ,
'2.0.3' : '/417' ,
'2.0.4' : '/419' ,
'?' : '/'
}
}
} ,
device : {
sprint : {
model : {
'Evo Shift 4G' : '7373KT'
} ,
vendor : {
'HTC' : 'APA' ,
'Sprint' : 'Sprint'
}
}
} ,
os : {
windows : {
version : {
'ME' : '4.90' ,
'NT 3.11' : 'NT3.51' ,
'NT 4.0' : 'NT4.0' ,
'2000' : 'NT 5.0' ,
'XP' : [ 'NT 5.1' , 'NT 5.2' ] ,
'Vista' : 'NT 6.0' ,
'7' : 'NT 6.1' ,
'8' : 'NT 6.2' ,
'8.1' : 'NT 6.3' ,
'RT' : 'ARM'
}
}
}
} ;
//////////////
// Regex map
/////////////
var regexes = {
browser : [ [
// Presto based
/(opera\smini)\/((\d+)?[\w\.-]+)/i , // Opera Mini
/(opera\s[mobiletab]+).+version\/((\d+)?[\w\.-]+)/i , // Opera Mobi/Tablet
/(opera).+version\/((\d+)?[\w\.]+)/i , // Opera > 9.80
/(opera)[\/\s]+((\d+)?[\w\.]+)/i // Opera < 9.80
] , [ NAME , VERSION , MAJOR ] , [
/\s(opr)\/((\d+)?[\w\.]+)/i // Opera Webkit
] , [ [ NAME , 'Opera' ] , VERSION , MAJOR ] , [
// Mixed
/(kindle)\/((\d+)?[\w\.]+)/i , // Kindle
/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)*/i ,
// Lunascape/Maxthon/Netfront/Jasmine/Blazer
// Trident based
/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?((\d+)?[\w\.]*)/i ,
// Avant/IEMobile/SlimBrowser/Baidu
/(?:ms|\()(ie)\s((\d+)?[\w\.]+)/i , // Internet Explorer
// Webkit/KHTML based
/(rekonq)((?:\/)[\w\.]+)*/i , // Rekonq
/(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron)\/((\d+)?[\w\.-]+)/i
// Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron
] , [ NAME , VERSION , MAJOR ] , [
/(trident).+rv[:\s]((\d+)?[\w\.]+).+like\sgecko/i // IE11
] , [ [ NAME , 'IE' ] , VERSION , MAJOR ] , [
/(yabrowser)\/((\d+)?[\w\.]+)/i // Yandex
] , [ [ NAME , 'Yandex' ] , VERSION , MAJOR ] , [
/(comodo_dragon)\/((\d+)?[\w\.]+)/i // Comodo Dragon
] , [ [ NAME , /_/g , ' ' ] , VERSION , MAJOR ] , [
/(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?((\d+)?[\w\.]+)/i
// Chrome/OmniWeb/Arora/Tizen/Nokia
] , [ NAME , VERSION , MAJOR ] , [
/(dolfin)\/((\d+)?[\w\.]+)/i // Dolphin
] , [ [ NAME , 'Dolphin' ] , VERSION , MAJOR ] , [
/((?:android.+)crmo|crios)\/((\d+)?[\w\.]+)/i // Chrome for Android/iOS
] , [ [ NAME , 'Chrome' ] , VERSION , MAJOR ] , [
/((?:android.+))version\/((\d+)?[\w\.]+)\smobile\ssafari/i // Android Browser
] , [ [ NAME , 'Android Browser' ] , VERSION , MAJOR ] , [
/version\/((\d+)?[\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari
] , [ VERSION , MAJOR , [ NAME , 'Mobile Safari' ] ] , [
/version\/((\d+)?[\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile
] , [ VERSION , MAJOR , NAME ] , [
/webkit.+?(mobile\s?safari|safari)((\/[\w\.]+))/i // Safari < 3.0
] , [ NAME , [ MAJOR , mapper . str , maps . browser . oldsafari . major ] , [ VERSION , mapper . str , maps . browser . oldsafari . version ] ] , [
/(konqueror)\/((\d+)?[\w\.]+)/i , // Konqueror
/(webkit|khtml)\/((\d+)?[\w\.]+)/i
] , [ NAME , VERSION , MAJOR ] , [
// Gecko based
/(navigator|netscape)\/((\d+)?[\w\.-]+)/i // Netscape
] , [ [ NAME , 'Netscape' ] , VERSION , MAJOR ] , [
/(swiftfox)/i , // Swiftfox
/(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?((\d+)?[\w\.\+]+)/i ,
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
/(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/((\d+)?[\w\.-]+)/i ,
// Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
/(mozilla)\/((\d+)?[\w\.]+).+rv\:.+gecko\/\d+/i , // Mozilla
// Other
/(uc\s?browser|polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|qqbrowser)[\/\s]?((\d+)?[\w\.]+)/i ,
// UCBrowser/Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/QQBrowser
/(links)\s\(((\d+)?[\w\.]+)/i , // Links
/(gobrowser)\/?((\d+)?[\w\.]+)*/i , // GoBrowser
/(ice\s?browser)\/v?((\d+)?[\w\._]+)/i , // ICE Browser
/(mosaic)[\/\s]((\d+)?[\w\.]+)/i // Mosaic
] , [ NAME , VERSION , MAJOR ]
] ,
engine : [ [
/(presto)\/([\w\.]+)/i , // Presto
/(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i , // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m
/(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i , // KHTML/Tasman/Links
/(icab)[\/\s]([23]\.[\d\.]+)/i // iCab
] , [ NAME , VERSION ] , [
/rv\:([\w\.]+).*(gecko)/i // Gecko
] , [ VERSION , NAME ]
] ,
os : [ [
// Windows based
/(windows)\snt\s6\.2;\s(arm)/i , // Windows RT
/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i
] , [ NAME , [ VERSION , mapper . str , maps . os . windows . version ] ] , [
/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i
] , [ [ NAME , 'Windows' ] , [ VERSION , mapper . str , maps . os . windows . version ] ] , [
// Mobile/Embedded OS
/\((bb)(10);/i // BlackBerry 10
] , [ [ NAME , 'BlackBerry' ] , VERSION ] , [
/(blackberry)\w*\/?([\w\.]+)*/i , // Blackberry
/(tizen)\/([\w\.]+)/i , // Tizen
/(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego)[\/\s-]?([\w\.]+)*/i
// Android/WebOS/Palm/QNX/Bada/RIM/MeeGo
] , [ NAME , VERSION ] , [
/(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i // Symbian
] , [ [ NAME , 'Symbian' ] , VERSION ] , [
/mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS
] , [ [ NAME , 'Firefox OS' ] , VERSION ] , [
// Console
/(nintendo|playstation)\s([wids3portablevu]+)/i , // Nintendo/Playstation
// GNU/Linux based
/(mint)[\/\s\(]?(\w+)*/i , // Mint
/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk)[\/\s-]?([\w\.-]+)*/i ,
// Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware
// Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk
/(hurd|linux)\s?([\w\.]+)*/i , // Hurd/Linux
/(gnu)\s?([\w\.]+)*/i // GNU
] , [ NAME , VERSION ] , [
/(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS
] , [ [ NAME , 'Chromium OS' ] , VERSION ] , [
// Solaris
/(sunos)\s?([\w\.]+\d)*/i // Solaris
] , [ [ NAME , 'Solaris' ] , VERSION ] , [
// BSD based
/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly
] , [ NAME , VERSION ] , [
/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i // iOS
] , [ [ NAME , 'iOS' ] , [ VERSION , /_/g , '.' ] ] , [
/(mac\sos\sx)\s?([\w\s\.]+\w)*/i // Mac OS
] , [ NAME , [ VERSION , /_/g , '.' ] ] , [
// Other
/(haiku)\s(\w+)/i , // Haiku
/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i , // AIX
/(macintosh|mac(?=_powerpc)|plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos)/i ,
// Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS
/(unix)\s?([\w\.]+)*/i // UNIX
] , [ NAME , VERSION ]
]
} ;
/////////////////
// Constructor
////////////////
var UAParser = function ( uastring ) {
var ua = uastring || ( ( window && window . navigator && window . navigator . userAgent ) ? window . navigator . userAgent : EMPTY ) ;
this . getBrowser = function ( ) {
return mapper . rgx . apply ( this , regexes . browser ) ;
} ;
this . getEngine = function ( ) {
return mapper . rgx . apply ( this , regexes . engine ) ;
} ;
this . getOS = function ( ) {
return mapper . rgx . apply ( this , regexes . os ) ;
} ;
this . getResult = function ( ) {
return {
ua : this . getUA ( ) ,
browser : this . getBrowser ( ) ,
engine : this . getEngine ( ) ,
os : this . getOS ( )
} ;
} ;
this . getUA = function ( ) {
return ua ;
} ;
this . setUA = function ( uastring ) {
ua = uastring ;
return this ;
} ;
this . setUA ( ua ) ;
} ;
return new UAParser ( ) . getResult ( ) ;
} ) ( ) ;
function version _compare ( v1 , v2 , operator ) {
// From: http://phpjs.org/functions
// + original by: Philippe Jausions (http://pear.php.net/user/jausions)
// + original by: Aidan Lister (http://aidanlister.com/)
// + reimplemented by: Kankrelune (http://www.webfaktory.info/)
// + improved by: Brett Zamir (http://brett-zamir.me)
// + improved by: Scott Baker
// + improved by: Theriault
// * example 1: version_compare('8.2.5rc', '8.2.5a');
// * returns 1: 1
// * example 2: version_compare('8.2.50', '8.2.52', '<');
// * returns 2: true
// * example 3: version_compare('5.3.0-dev', '5.3.0');
// * returns 3: -1
// * example 4: version_compare('4.1.0.52','4.01.0.51');
// * returns 4: 1
// Important: compare must be initialized at 0.
var i = 0 ,
x = 0 ,
compare = 0 ,
// vm maps textual PHP versions to negatives so they're less than 0.
// PHP currently defines these as CASE-SENSITIVE. It is important to
// leave these as negatives so that they can come before numerical versions
// and as if no letters were there to begin with.
// (1alpha is < 1 and < 1.1 but > 1dev1)
// If a non-numerical value can't be mapped to this table, it receives
// -7 as its value.
vm = {
'dev' : - 6 ,
'alpha' : - 5 ,
'a' : - 5 ,
'beta' : - 4 ,
'b' : - 4 ,
'RC' : - 3 ,
'rc' : - 3 ,
'#' : - 2 ,
'p' : 1 ,
'pl' : 1
} ,
// This function will be called to prepare each version argument.
// It replaces every _, -, and + with a dot.
// It surrounds any nonsequence of numbers/dots with dots.
// It replaces sequences of dots with a single dot.
// version_compare('4..0', '4.0') == 0
// Important: A string of 0 length needs to be converted into a value
// even less than an unexisting value in vm (-7), hence [-8].
// It's also important to not strip spaces because of this.
// version_compare('', ' ') == 1
prepVersion = function ( v ) {
v = ( '' + v ) . replace ( /[_\-+]/g , '.' ) ;
v = v . replace ( /([^.\d]+)/g , '.$1.' ) . replace ( /\.{2,}/g , '.' ) ;
return ( ! v . length ? [ - 8 ] : v . split ( '.' ) ) ;
} ,
// This converts a version component to a number.
// Empty component becomes 0.
// Non-numerical component becomes a negative number.
// Numerical component becomes itself as an integer.
numVersion = function ( v ) {
return ! v ? 0 : ( isNaN ( v ) ? vm [ v ] || - 7 : parseInt ( v , 10 ) ) ;
} ;
v1 = prepVersion ( v1 ) ;
v2 = prepVersion ( v2 ) ;
x = Math . max ( v1 . length , v2 . length ) ;
for ( i = 0 ; i < x ; i ++ ) {
if ( v1 [ i ] == v2 [ i ] ) {
continue ;
}
v1 [ i ] = numVersion ( v1 [ i ] ) ;
v2 [ i ] = numVersion ( v2 [ i ] ) ;
if ( v1 [ i ] < v2 [ i ] ) {
compare = - 1 ;
break ;
} else if ( v1 [ i ] > v2 [ i ] ) {
compare = 1 ;
break ;
}
}
if ( ! operator ) {
return compare ;
}
// Important: operator is CASE-SENSITIVE.
// "No operator" seems to be treated as "<."
// Any other values seem to make the function return null.
switch ( operator ) {
case '>' :
case 'gt' :
return ( compare > 0 ) ;
case '>=' :
case 'ge' :
return ( compare >= 0 ) ;
case '<=' :
case 'le' :
return ( compare <= 0 ) ;
case '==' :
case '=' :
case 'eq' :
return ( compare === 0 ) ;
case '<>' :
case '!=' :
case 'ne' :
return ( compare !== 0 ) ;
case '' :
case '<' :
case 'lt' :
return ( compare < 0 ) ;
default :
return null ;
}
}
var can = ( function ( ) {
var caps = {
define _property : ( function ( ) {
/* / / currently too much extra code required , not exactly worth it
try { // as of IE8, getters/setters are supported only on DOM elements
var obj = { } ;
if ( Object . defineProperty ) {
Object . defineProperty ( obj , 'prop' , {
enumerable : true ,
configurable : true
} ) ;
return true ;
}
} catch ( ex ) { }
if ( Object . prototype . _ _defineGetter _ _ && Object . prototype . _ _defineSetter _ _ ) {
return true ;
} * /
return false ;
} ( ) ) ,
create _canvas : ( function ( ) {
// On the S60 and BB Storm, getContext exists, but always returns undefined
// so we actually have to call getContext() to verify
// github.com/Modernizr/Modernizr/issues/issue/97/
var el = document . createElement ( 'canvas' ) ;
return ! ! ( el . getContext && el . getContext ( '2d' ) ) ;
} ( ) ) ,
return _response _type : function ( responseType ) {
try {
if ( Basic . inArray ( responseType , [ '' , 'text' , 'document' ] ) !== - 1 ) {
return true ;
} else if ( window . XMLHttpRequest ) {
var xhr = new XMLHttpRequest ( ) ;
xhr . open ( 'get' , '/' ) ; // otherwise Gecko throws an exception
if ( 'responseType' in xhr ) {
xhr . responseType = responseType ;
// as of 23.0.1271.64, Chrome switched from throwing exception to merely logging it to the console (why? o why?)
if ( xhr . responseType !== responseType ) {
return false ;
}
return true ;
}
}
} catch ( ex ) { }
return false ;
} ,
// ideas for this heavily come from Modernizr (http://modernizr.com/)
use _data _uri : ( function ( ) {
var du = new Image ( ) ;
du . onload = function ( ) {
caps . use _data _uri = ( du . width === 1 && du . height === 1 ) ;
} ;
setTimeout ( function ( ) {
du . src = "data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" ;
} , 1 ) ;
return false ;
} ( ) ) ,
use _data _uri _over32kb : function ( ) { // IE8
return caps . use _data _uri && ( Env . browser !== 'IE' || Env . version >= 9 ) ;
} ,
use _data _uri _of : function ( bytes ) {
return ( caps . use _data _uri && bytes < 33000 || caps . use _data _uri _over32kb ( ) ) ;
} ,
use _fileinput : function ( ) {
var el = document . createElement ( 'input' ) ;
el . setAttribute ( 'type' , 'file' ) ;
return ! el . disabled ;
}
} ;
return function ( cap ) {
var args = [ ] . slice . call ( arguments ) ;
args . shift ( ) ; // shift of cap
return Basic . typeOf ( caps [ cap ] ) === 'function' ? caps [ cap ] . apply ( this , args ) : ! ! caps [ cap ] ;
} ;
} ( ) ) ;
var Env = {
can : can ,
browser : UAParser . browser . name ,
version : parseFloat ( UAParser . browser . major ) ,
os : UAParser . os . name , // everybody intuitively types it in a lowercase for some reason
osVersion : UAParser . os . version ,
verComp : version _compare ,
swf _url : "../flash/Moxie.swf" ,
xap _url : "../silverlight/Moxie.xap" ,
global _event _dispatcher : "moxie.core.EventTarget.instance.dispatchEvent"
} ;
// for backward compatibility
// @deprecated Use `Env.os` instead
Env . OS = Env . os ;
return Env ;
} ) ;
// Included from: src/javascript/core/utils/Dom.js
/ * *
* Dom . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/core/utils/Dom' , [ 'moxie/core/utils/Env' ] , function ( Env ) {
/ * *
Get DOM Element by it ' s id .
@ method get
@ for Utils
@ param { String } id Identifier of the DOM Element
@ return { DOMElement }
* /
var get = function ( id ) {
if ( typeof id !== 'string' ) {
return id ;
}
return document . getElementById ( id ) ;
} ;
/ * *
Checks if specified DOM element has specified class .
@ method hasClass
@ static
@ param { Object } obj DOM element like object to add handler to .
@ param { String } name Class name
* /
var hasClass = function ( obj , name ) {
if ( ! obj . className ) {
return false ;
}
var regExp = new RegExp ( "(^|\\s+)" + name + "(\\s+|$)" ) ;
return regExp . test ( obj . className ) ;
} ;
/ * *
Adds specified className to specified DOM element .
@ method addClass
@ static
@ param { Object } obj DOM element like object to add handler to .
@ param { String } name Class name
* /
var addClass = function ( obj , name ) {
if ( ! hasClass ( obj , name ) ) {
obj . className = ! obj . className ? name : obj . className . replace ( /\s+$/ , '' ) + ' ' + name ;
}
} ;
/ * *
Removes specified className from specified DOM element .
@ method removeClass
@ static
@ param { Object } obj DOM element like object to add handler to .
@ param { String } name Class name
* /
var removeClass = function ( obj , name ) {
if ( obj . className ) {
var regExp = new RegExp ( "(^|\\s+)" + name + "(\\s+|$)" ) ;
obj . className = obj . className . replace ( regExp , function ( $0 , $1 , $2 ) {
return $1 === ' ' && $2 === ' ' ? ' ' : '' ;
} ) ;
}
} ;
/ * *
Returns a given computed style of a DOM element .
@ method getStyle
@ static
@ param { Object } obj DOM element like object .
@ param { String } name Style you want to get from the DOM element
* /
var getStyle = function ( obj , name ) {
if ( obj . currentStyle ) {
return obj . currentStyle [ name ] ;
} else if ( window . getComputedStyle ) {
return window . getComputedStyle ( obj , null ) [ name ] ;
}
} ;
/ * *
Returns the absolute x , y position of an Element . The position will be returned in a object with x , y fields .
@ method getPos
@ static
@ param { Element } node HTML element or element id to get x , y position from .
@ param { Element } root Optional root element to stop calculations at .
@ return { object } Absolute position of the specified element object with x , y fields .
* /
var getPos = function ( node , root ) {
var x = 0 , y = 0 , parent , doc = document , nodeRect , rootRect ;
node = node ;
root = root || doc . body ;
// Returns the x, y cordinate for an element on IE 6 and IE 7
function getIEPos ( node ) {
var bodyElm , rect , x = 0 , y = 0 ;
if ( node ) {
rect = node . getBoundingClientRect ( ) ;
bodyElm = doc . compatMode === "CSS1Compat" ? doc . documentElement : doc . body ;
x = rect . left + bodyElm . scrollLeft ;
y = rect . top + bodyElm . scrollTop ;
}
return {
x : x ,
y : y
} ;
}
// Use getBoundingClientRect on IE 6 and IE 7 but not on IE 8 in standards mode
if ( node && node . getBoundingClientRect && Env . browser === 'IE' && ( ! doc . documentMode || doc . documentMode < 8 ) ) {
nodeRect = getIEPos ( node ) ;
rootRect = getIEPos ( root ) ;
return {
x : nodeRect . x - rootRect . x ,
y : nodeRect . y - rootRect . y
} ;
}
parent = node ;
while ( parent && parent != root && parent . nodeType ) {
x += parent . offsetLeft || 0 ;
y += parent . offsetTop || 0 ;
parent = parent . offsetParent ;
}
parent = node . parentNode ;
while ( parent && parent != root && parent . nodeType ) {
x -= parent . scrollLeft || 0 ;
y -= parent . scrollTop || 0 ;
parent = parent . parentNode ;
}
return {
x : x ,
y : y
} ;
} ;
/ * *
Returns the size of the specified node in pixels .
@ method getSize
@ static
@ param { Node } node Node to get the size of .
@ return { Object } Object with a w and h property .
* /
var getSize = function ( node ) {
return {
w : node . offsetWidth || node . clientWidth ,
h : node . offsetHeight || node . clientHeight
} ;
} ;
return {
get : get ,
hasClass : hasClass ,
addClass : addClass ,
removeClass : removeClass ,
getStyle : getStyle ,
getPos : getPos ,
getSize : getSize
} ;
} ) ;
// Included from: src/javascript/core/Exceptions.js
/ * *
* Exceptions . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/core/Exceptions' , [
'moxie/core/utils/Basic'
] , function ( Basic ) {
function _findKey ( obj , value ) {
var key ;
for ( key in obj ) {
if ( obj [ key ] === value ) {
return key ;
}
}
return null ;
}
return {
RuntimeError : ( function ( ) {
var namecodes = {
NOT _INIT _ERR : 1 ,
NOT _SUPPORTED _ERR : 9 ,
JS _ERR : 4
} ;
function RuntimeError ( code ) {
this . code = code ;
this . name = _findKey ( namecodes , code ) ;
this . message = this . name + ": RuntimeError " + this . code ;
}
Basic . extend ( RuntimeError , namecodes ) ;
RuntimeError . prototype = Error . prototype ;
return RuntimeError ;
} ( ) ) ,
OperationNotAllowedException : ( function ( ) {
function OperationNotAllowedException ( code ) {
this . code = code ;
this . name = 'OperationNotAllowedException' ;
}
Basic . extend ( OperationNotAllowedException , {
NOT _ALLOWED _ERR : 1
} ) ;
OperationNotAllowedException . prototype = Error . prototype ;
return OperationNotAllowedException ;
} ( ) ) ,
ImageError : ( function ( ) {
var namecodes = {
WRONG _FORMAT : 1 ,
MAX _RESOLUTION _ERR : 2
} ;
function ImageError ( code ) {
this . code = code ;
this . name = _findKey ( namecodes , code ) ;
this . message = this . name + ": ImageError " + this . code ;
}
Basic . extend ( ImageError , namecodes ) ;
ImageError . prototype = Error . prototype ;
return ImageError ;
} ( ) ) ,
FileException : ( function ( ) {
var namecodes = {
NOT _FOUND _ERR : 1 ,
SECURITY _ERR : 2 ,
ABORT _ERR : 3 ,
NOT _READABLE _ERR : 4 ,
ENCODING _ERR : 5 ,
NO _MODIFICATION _ALLOWED _ERR : 6 ,
INVALID _STATE _ERR : 7 ,
SYNTAX _ERR : 8
} ;
function FileException ( code ) {
this . code = code ;
this . name = _findKey ( namecodes , code ) ;
this . message = this . name + ": FileException " + this . code ;
}
Basic . extend ( FileException , namecodes ) ;
FileException . prototype = Error . prototype ;
return FileException ;
} ( ) ) ,
DOMException : ( function ( ) {
var namecodes = {
INDEX _SIZE _ERR : 1 ,
DOMSTRING _SIZE _ERR : 2 ,
HIERARCHY _REQUEST _ERR : 3 ,
WRONG _DOCUMENT _ERR : 4 ,
INVALID _CHARACTER _ERR : 5 ,
NO _DATA _ALLOWED _ERR : 6 ,
NO _MODIFICATION _ALLOWED _ERR : 7 ,
NOT _FOUND _ERR : 8 ,
NOT _SUPPORTED _ERR : 9 ,
INUSE _ATTRIBUTE _ERR : 10 ,
INVALID _STATE _ERR : 11 ,
SYNTAX _ERR : 12 ,
INVALID _MODIFICATION _ERR : 13 ,
NAMESPACE _ERR : 14 ,
INVALID _ACCESS _ERR : 15 ,
VALIDATION _ERR : 16 ,
TYPE _MISMATCH _ERR : 17 ,
SECURITY _ERR : 18 ,
NETWORK _ERR : 19 ,
ABORT _ERR : 20 ,
URL _MISMATCH _ERR : 21 ,
QUOTA _EXCEEDED _ERR : 22 ,
TIMEOUT _ERR : 23 ,
INVALID _NODE _TYPE _ERR : 24 ,
DATA _CLONE _ERR : 25
} ;
function DOMException ( code ) {
this . code = code ;
this . name = _findKey ( namecodes , code ) ;
this . message = this . name + ": DOMException " + this . code ;
}
Basic . extend ( DOMException , namecodes ) ;
DOMException . prototype = Error . prototype ;
return DOMException ;
} ( ) ) ,
EventException : ( function ( ) {
function EventException ( code ) {
this . code = code ;
this . name = 'EventException' ;
}
Basic . extend ( EventException , {
UNSPECIFIED _EVENT _TYPE _ERR : 0
} ) ;
EventException . prototype = Error . prototype ;
return EventException ;
} ( ) )
} ;
} ) ;
// Included from: src/javascript/core/EventTarget.js
/ * *
* EventTarget . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/core/EventTarget' , [
'moxie/core/Exceptions' ,
'moxie/core/utils/Basic'
] , function ( x , Basic ) {
/ * *
Parent object for all event dispatching components and objects
@ class EventTarget
@ constructor EventTarget
* /
function EventTarget ( ) {
// hash of event listeners by object uid
var eventpool = { } ;
Basic . extend ( this , {
/ * *
Unique id of the event dispatcher , usually overriden by children
@ property uid
@ type String
* /
uid : null ,
/ * *
Can be called from within a child in order to acquire uniqie id in automated manner
@ method init
* /
init : function ( ) {
if ( ! this . uid ) {
this . uid = Basic . guid ( 'uid_' ) ;
}
} ,
/ * *
Register a handler to a specific event dispatched by the object
@ method addEventListener
@ param { String } type Type or basically a name of the event to subscribe to
@ param { Function } fn Callback function that will be called when event happens
@ param { Number } [ priority = 0 ] Priority of the event handler - handlers with higher priorities will be called first
@ param { Object } [ scope = this ] A scope to invoke event handler in
* /
addEventListener : function ( type , fn , priority , scope ) {
var self = this , list ;
type = Basic . trim ( type ) ;
if ( /\s/ . test ( type ) ) {
// multiple event types were passed for one handler
Basic . each ( type . split ( /\s+/ ) , function ( type ) {
self . addEventListener ( type , fn , priority , scope ) ;
} ) ;
return ;
}
type = type . toLowerCase ( ) ;
priority = parseInt ( priority , 10 ) || 0 ;
list = eventpool [ this . uid ] && eventpool [ this . uid ] [ type ] || [ ] ;
list . push ( { fn : fn , priority : priority , scope : scope || this } ) ;
if ( ! eventpool [ this . uid ] ) {
eventpool [ this . uid ] = { } ;
}
eventpool [ this . uid ] [ type ] = list ;
} ,
/ * *
Check if any handlers were registered to the specified event
@ method hasEventListener
@ param { String } type Type or basically a name of the event to check
@ return { Mixed } Returns a handler if it was found and false , if - not
* /
hasEventListener : function ( type ) {
return type ? ! ! ( eventpool [ this . uid ] && eventpool [ this . uid ] [ type ] ) : ! ! eventpool [ this . uid ] ;
} ,
/ * *
Unregister the handler from the event , or if former was not specified - unregister all handlers
@ method removeEventListener
@ param { String } type Type or basically a name of the event
@ param { Function } [ fn ] Handler to unregister
* /
removeEventListener : function ( type , fn ) {
type = type . toLowerCase ( ) ;
var list = eventpool [ this . uid ] && eventpool [ this . uid ] [ type ] , i ;
if ( list ) {
if ( fn ) {
for ( i = list . length - 1 ; i >= 0 ; i -- ) {
if ( list [ i ] . fn === fn ) {
list . splice ( i , 1 ) ;
break ;
}
}
} else {
list = [ ] ;
}
// delete event list if it has become empty
if ( ! list . length ) {
delete eventpool [ this . uid ] [ type ] ;
// and object specific entry in a hash if it has no more listeners attached
if ( Basic . isEmptyObj ( eventpool [ this . uid ] ) ) {
delete eventpool [ this . uid ] ;
}
}
}
} ,
/ * *
Remove all event handlers from the object
@ method removeAllEventListeners
* /
removeAllEventListeners : function ( ) {
if ( eventpool [ this . uid ] ) {
delete eventpool [ this . uid ] ;
}
} ,
/ * *
Dispatch the event
@ method dispatchEvent
@ param { String / Object } Type of event or event object to dispatch
@ param { Mixed } [ ... ] Variable number of arguments to be passed to a handlers
@ return { Boolean } true by default and false if any handler returned false
* /
dispatchEvent : function ( type ) {
var uid , list , args , tmpEvt , evt = { } , result = true , undef ;
if ( Basic . typeOf ( type ) !== 'string' ) {
// we can't use original object directly (because of Silverlight)
tmpEvt = type ;
if ( Basic . typeOf ( tmpEvt . type ) === 'string' ) {
type = tmpEvt . type ;
if ( tmpEvt . total !== undef && tmpEvt . loaded !== undef ) { // progress event
evt . total = tmpEvt . total ;
evt . loaded = tmpEvt . loaded ;
}
evt . async = tmpEvt . async || false ;
} else {
throw new x . EventException ( x . EventException . UNSPECIFIED _EVENT _TYPE _ERR ) ;
}
}
// check if event is meant to be dispatched on an object having specific uid
if ( type . indexOf ( '::' ) !== - 1 ) {
( function ( arr ) {
uid = arr [ 0 ] ;
type = arr [ 1 ] ;
} ( type . split ( '::' ) ) ) ;
} else {
uid = this . uid ;
}
type = type . toLowerCase ( ) ;
list = eventpool [ uid ] && eventpool [ uid ] [ type ] ;
if ( list ) {
// sort event list by prority
list . sort ( function ( a , b ) { return b . priority - a . priority ; } ) ;
args = [ ] . slice . call ( arguments ) ;
// first argument will be pseudo-event object
args . shift ( ) ;
evt . type = type ;
args . unshift ( evt ) ;
// Dispatch event to all listeners
var queue = [ ] ;
Basic . each ( list , function ( handler ) {
// explicitly set the target, otherwise events fired from shims do not get it
args [ 0 ] . target = handler . scope ;
// if event is marked as async, detach the handler
if ( evt . async ) {
queue . push ( function ( cb ) {
setTimeout ( function ( ) {
cb ( handler . fn . apply ( handler . scope , args ) === false ) ;
} , 1 ) ;
} ) ;
} else {
queue . push ( function ( cb ) {
cb ( handler . fn . apply ( handler . scope , args ) === false ) ; // if handler returns false stop propagation
} ) ;
}
} ) ;
if ( queue . length ) {
Basic . inSeries ( queue , function ( err ) {
result = ! err ;
} ) ;
}
}
return result ;
} ,
/ * *
Alias for addEventListener
@ method bind
@ protected
* /
bind : function ( ) {
this . addEventListener . apply ( this , arguments ) ;
} ,
/ * *
Alias for removeEventListener
@ method unbind
@ protected
* /
unbind : function ( ) {
this . removeEventListener . apply ( this , arguments ) ;
} ,
/ * *
Alias for removeAllEventListeners
@ method unbindAll
@ protected
* /
unbindAll : function ( ) {
this . removeAllEventListeners . apply ( this , arguments ) ;
} ,
/ * *
Alias for dispatchEvent
@ method trigger
@ protected
* /
trigger : function ( ) {
return this . dispatchEvent . apply ( this , arguments ) ;
} ,
/ * *
Converts properties of on [ event ] type to corresponding event handlers ,
is used to avoid extra hassle around the process of calling them back
@ method convertEventPropsToHandlers
@ private
* /
convertEventPropsToHandlers : function ( handlers ) {
var h ;
if ( Basic . typeOf ( handlers ) !== 'array' ) {
handlers = [ handlers ] ;
}
for ( var i = 0 ; i < handlers . length ; i ++ ) {
h = 'on' + handlers [ i ] ;
if ( Basic . typeOf ( this [ h ] ) === 'function' ) {
this . addEventListener ( handlers [ i ] , this [ h ] ) ;
} else if ( Basic . typeOf ( this [ h ] ) === 'undefined' ) {
this [ h ] = null ; // object must have defined event properties, even if it doesn't make use of them
}
}
}
} ) ;
}
EventTarget . instance = new EventTarget ( ) ;
return EventTarget ;
} ) ;
// Included from: src/javascript/core/utils/Encode.js
/ * *
* Encode . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/core/utils/Encode' , [ ] , function ( ) {
/ * *
Encode string with UTF - 8
@ method utf8 _encode
@ for Utils
@ static
@ param { String } str String to encode
@ return { String } UTF - 8 encoded string
* /
var utf8 _encode = function ( str ) {
return unescape ( encodeURIComponent ( str ) ) ;
} ;
/ * *
Decode UTF - 8 encoded string
@ method utf8 _decode
@ static
@ param { String } str String to decode
@ return { String } Decoded string
* /
var utf8 _decode = function ( str _data ) {
return decodeURIComponent ( escape ( str _data ) ) ;
} ;
/ * *
Decode Base64 encoded string ( uses browser ' s default method if available ) ,
from : https : //raw.github.com/kvz/phpjs/master/functions/url/base64_decode.js
@ method atob
@ static
@ param { String } data String to decode
@ return { String } Decoded string
* /
var atob = function ( data , utf8 ) {
if ( typeof ( window . atob ) === 'function' ) {
return utf8 ? utf8 _decode ( window . atob ( data ) ) : window . atob ( data ) ;
}
// http://kevin.vanzonneveld.net
// + original by: Tyler Akins (http://rumkin.com)
// + improved by: Thunder.m
// + input by: Aman Gupta
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + bugfixed by: Onno Marsman
// + bugfixed by: Pellentesque Malesuada
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + input by: Brett Zamir (http://brett-zamir.me)
// + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
// * returns 1: 'Kevin van Zonneveld'
// mozilla has this native
// - but breaks in 2.0.0.12!
//if (typeof this.window.atob == 'function') {
// return atob(data);
//}
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" ;
var o1 , o2 , o3 , h1 , h2 , h3 , h4 , bits , i = 0 ,
ac = 0 ,
dec = "" ,
tmp _arr = [ ] ;
if ( ! data ) {
return data ;
}
data += '' ;
do { // unpack four hexets into three octets using index points in b64
h1 = b64 . indexOf ( data . charAt ( i ++ ) ) ;
h2 = b64 . indexOf ( data . charAt ( i ++ ) ) ;
h3 = b64 . indexOf ( data . charAt ( i ++ ) ) ;
h4 = b64 . indexOf ( data . charAt ( i ++ ) ) ;
bits = h1 << 18 | h2 << 12 | h3 << 6 | h4 ;
o1 = bits >> 16 & 0xff ;
o2 = bits >> 8 & 0xff ;
o3 = bits & 0xff ;
if ( h3 == 64 ) {
tmp _arr [ ac ++ ] = String . fromCharCode ( o1 ) ;
} else if ( h4 == 64 ) {
tmp _arr [ ac ++ ] = String . fromCharCode ( o1 , o2 ) ;
} else {
tmp _arr [ ac ++ ] = String . fromCharCode ( o1 , o2 , o3 ) ;
}
} while ( i < data . length ) ;
dec = tmp _arr . join ( '' ) ;
return utf8 ? utf8 _decode ( dec ) : dec ;
} ;
/ * *
Base64 encode string ( uses browser ' s default method if available ) ,
from : https : //raw.github.com/kvz/phpjs/master/functions/url/base64_encode.js
@ method btoa
@ static
@ param { String } data String to encode
@ return { String } Base64 encoded string
* /
var btoa = function ( data , utf8 ) {
if ( utf8 ) {
utf8 _encode ( data ) ;
}
if ( typeof ( window . btoa ) === 'function' ) {
return window . btoa ( data ) ;
}
// http://kevin.vanzonneveld.net
// + original by: Tyler Akins (http://rumkin.com)
// + improved by: Bayron Guevara
// + improved by: Thunder.m
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + bugfixed by: Pellentesque Malesuada
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + improved by: Rafał Kukawski (http://kukawski.pl)
// * example 1: base64_encode('Kevin van Zonneveld');
// * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
// mozilla has this native
// - but breaks in 2.0.0.12!
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" ;
var o1 , o2 , o3 , h1 , h2 , h3 , h4 , bits , i = 0 ,
ac = 0 ,
enc = "" ,
tmp _arr = [ ] ;
if ( ! data ) {
return data ;
}
do { // pack three octets into four hexets
o1 = data . charCodeAt ( i ++ ) ;
o2 = data . charCodeAt ( i ++ ) ;
o3 = data . charCodeAt ( i ++ ) ;
bits = o1 << 16 | o2 << 8 | o3 ;
h1 = bits >> 18 & 0x3f ;
h2 = bits >> 12 & 0x3f ;
h3 = bits >> 6 & 0x3f ;
h4 = bits & 0x3f ;
// use hexets to index into b64, and append result to encoded string
tmp _arr [ ac ++ ] = b64 . charAt ( h1 ) + b64 . charAt ( h2 ) + b64 . charAt ( h3 ) + b64 . charAt ( h4 ) ;
} while ( i < data . length ) ;
enc = tmp _arr . join ( '' ) ;
var r = data . length % 3 ;
return ( r ? enc . slice ( 0 , r - 3 ) : enc ) + '===' . slice ( r || 3 ) ;
} ;
return {
utf8 _encode : utf8 _encode ,
utf8 _decode : utf8 _decode ,
atob : atob ,
btoa : btoa
} ;
} ) ;
// Included from: src/javascript/runtime/Runtime.js
/ * *
* Runtime . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/runtime/Runtime' , [
"moxie/core/utils/Basic" ,
"moxie/core/utils/Dom" ,
"moxie/core/EventTarget"
] , function ( Basic , Dom , EventTarget ) {
var runtimeConstructors = { } , runtimes = { } ;
/ * *
Common set of methods and properties for every runtime instance
@ class Runtime
@ param { Object } options
@ param { String } type Sanitized name of the runtime
@ param { Object } [ caps ] Set of capabilities that differentiate specified runtime
@ param { Object } [ modeCaps ] Set of capabilities that do require specific operational mode
@ param { String } [ preferredMode = 'browser' ] Preferred operational mode to choose if no required capabilities were requested
* /
function Runtime ( options , type , caps , modeCaps , preferredMode ) {
/ * *
Dispatched when runtime is initialized and ready .
Results in RuntimeInit on a connected component .
@ event Init
* /
/ * *
Dispatched when runtime fails to initialize .
Results in RuntimeError on a connected component .
@ event Error
* /
var self = this
, _shim
, _uid = Basic . guid ( type + '_' )
, defaultMode = preferredMode || 'browser'
;
options = options || { } ;
// register runtime in private hash
runtimes [ _uid ] = this ;
/ * *
Default set of capabilities , which can be redifined later by specific runtime
@ private
@ property caps
@ type Object
* /
caps = Basic . extend ( {
// Runtime can:
// provide access to raw binary data of the file
access _binary : false ,
// provide access to raw binary data of the image (image extension is optional)
access _image _binary : false ,
// display binary data as thumbs for example
display _media : false ,
// make cross-domain requests
do _cors : false ,
// accept files dragged and dropped from the desktop
drag _and _drop : false ,
// filter files in selection dialog by their extensions
filter _by _extension : true ,
// resize image (and manipulate it raw data of any file in general)
resize _image : false ,
// periodically report how many bytes of total in the file were uploaded (loaded)
report _upload _progress : false ,
// provide access to the headers of http response
return _response _headers : false ,
// support response of specific type, which should be passed as an argument
// e.g. runtime.can('return_response_type', 'blob')
return _response _type : false ,
// return http status code of the response
return _status _code : true ,
// send custom http header with the request
send _custom _headers : false ,
// pick up the files from a dialog
select _file : false ,
// select whole folder in file browse dialog
select _folder : false ,
// select multiple files at once in file browse dialog
select _multiple : true ,
// send raw binary data, that is generated after image resizing or manipulation of other kind
send _binary _string : false ,
// send cookies with http request and therefore retain session
send _browser _cookies : true ,
// send data formatted as multipart/form-data
send _multipart : true ,
// slice the file or blob to smaller parts
slice _blob : false ,
// upload file without preloading it to memory, stream it out directly from disk
stream _upload : false ,
// programmatically trigger file browse dialog
summon _file _dialog : false ,
// upload file of specific size, size should be passed as argument
// e.g. runtime.can('upload_filesize', '500mb')
upload _filesize : true ,
// initiate http request with specific http method, method should be passed as argument
// e.g. runtime.can('use_http_method', 'put')
use _http _method : true
} , caps ) ;
// default to the mode that is compatible with preferred caps
if ( options . preferred _caps ) {
defaultMode = Runtime . getMode ( modeCaps , options . preferred _caps , defaultMode ) ;
}
// small extension factory here (is meant to be extended with actual extensions constructors)
_shim = ( function ( ) {
var objpool = { } ;
return {
exec : function ( uid , comp , fn , args ) {
if ( _shim [ comp ] ) {
if ( ! objpool [ uid ] ) {
objpool [ uid ] = {
context : this ,
instance : new _shim [ comp ] ( )
} ;
}
if ( objpool [ uid ] . instance [ fn ] ) {
return objpool [ uid ] . instance [ fn ] . apply ( this , args ) ;
}
}
} ,
removeInstance : function ( uid ) {
delete objpool [ uid ] ;
} ,
removeAllInstances : function ( ) {
var self = this ;
Basic . each ( objpool , function ( obj , uid ) {
if ( Basic . typeOf ( obj . instance . destroy ) === 'function' ) {
obj . instance . destroy . call ( obj . context ) ;
}
self . removeInstance ( uid ) ;
} ) ;
}
} ;
} ( ) ) ;
// public methods
Basic . extend ( this , {
/ * *
Specifies whether runtime instance was initialized or not
@ property initialized
@ type { Boolean }
@ default false
* /
initialized : false , // shims require this flag to stop initialization retries
/ * *
Unique ID of the runtime
@ property uid
@ type { String }
* /
uid : _uid ,
/ * *
Runtime type ( e . g . flash , html5 , etc )
@ property type
@ type { String }
* /
type : type ,
/ * *
Runtime ( not native one ) may operate in browser or client mode .
@ property mode
@ private
@ type { String | Boolean } current mode or false , if none possible
* /
mode : Runtime . getMode ( modeCaps , ( options . required _caps ) , defaultMode ) ,
/ * *
id of the DOM container for the runtime ( if available )
@ property shimid
@ type { String }
* /
shimid : _uid + '_container' ,
/ * *
Number of connected clients . If equal to zero , runtime can be destroyed
@ property clients
@ type { Number }
* /
clients : 0 ,
/ * *
Runtime initialization options
@ property options
@ type { Object }
* /
options : options ,
/ * *
Checks if the runtime has specific capability
@ method can
@ param { String } cap Name of capability to check
@ param { Mixed } [ value ] If passed , capability should somehow correlate to the value
@ param { Object } [ refCaps ] Set of capabilities to check the specified cap against ( defaults to internal set )
@ return { Boolean } true if runtime has such capability and false , if - not
* /
can : function ( cap , value ) {
var refCaps = arguments [ 2 ] || caps ;
// if cap var is a comma-separated list of caps, convert it to object (key/value)
if ( Basic . typeOf ( cap ) === 'string' && Basic . typeOf ( value ) === 'undefined' ) {
cap = Runtime . parseCaps ( cap ) ;
}
if ( Basic . typeOf ( cap ) === 'object' ) {
for ( var key in cap ) {
if ( ! this . can ( key , cap [ key ] , refCaps ) ) {
return false ;
}
}
return true ;
}
// check the individual cap
if ( Basic . typeOf ( refCaps [ cap ] ) === 'function' ) {
return refCaps [ cap ] . call ( this , value ) ;
} else {
return ( value === refCaps [ cap ] ) ;
}
} ,
/ * *
Returns container for the runtime as DOM element
@ method getShimContainer
@ return { DOMElement }
* /
getShimContainer : function ( ) {
var container , shimContainer = Dom . get ( this . shimid ) ;
// if no container for shim, create one
if ( ! shimContainer ) {
container = this . options . container ? Dom . get ( this . options . container ) : document . body ;
// create shim container and insert it at an absolute position into the outer container
shimContainer = document . createElement ( 'div' ) ;
shimContainer . id = this . shimid ;
shimContainer . className = 'moxie-shim moxie-shim-' + this . type ;
Basic . extend ( shimContainer . style , {
position : 'absolute' ,
top : '0px' ,
left : '0px' ,
width : '1px' ,
height : '1px' ,
overflow : 'hidden'
} ) ;
container . appendChild ( shimContainer ) ;
container = null ;
}
return shimContainer ;
} ,
/ * *
Returns runtime as DOM element ( if appropriate )
@ method getShim
@ return { DOMElement }
* /
getShim : function ( ) {
return _shim ;
} ,
/ * *
Invokes a method within the runtime itself ( might differ across the runtimes )
@ method shimExec
@ param { Mixed } [ ]
@ protected
@ return { Mixed } Depends on the action and component
* /
shimExec : function ( component , action ) {
var args = [ ] . slice . call ( arguments , 2 ) ;
return self . getShim ( ) . exec . call ( this , this . uid , component , action , args ) ;
} ,
/ * *
Operaional interface that is used by components to invoke specific actions on the runtime
( is invoked in the scope of component )
@ method exec
@ param { Mixed } [ ] *
@ protected
@ return { Mixed } Depends on the action and component
* /
exec : function ( component , action ) { // this is called in the context of component, not runtime
var args = [ ] . slice . call ( arguments , 2 ) ;
if ( self [ component ] && self [ component ] [ action ] ) {
return self [ component ] [ action ] . apply ( this , args ) ;
}
return self . shimExec . apply ( this , arguments ) ;
} ,
/ * *
Destroys the runtime ( removes all events and deletes DOM structures )
@ method destroy
* /
destroy : function ( ) {
if ( ! self ) {
return ; // obviously already destroyed
}
var shimContainer = Dom . get ( this . shimid ) ;
if ( shimContainer ) {
shimContainer . parentNode . removeChild ( shimContainer ) ;
}
if ( _shim ) {
_shim . removeAllInstances ( ) ;
}
this . unbindAll ( ) ;
delete runtimes [ this . uid ] ;
this . uid = null ; // mark this runtime as destroyed
_uid = self = _shim = shimContainer = null ;
}
} ) ;
// once we got the mode, test against all caps
if ( this . mode && options . required _caps && ! this . can ( options . required _caps ) ) {
this . mode = false ;
}
}
/ * *
Default order to try different runtime types
@ property order
@ type String
@ static
* /
Runtime . order = 'html5,flash,silverlight,html4' ;
/ * *
Retrieves runtime from private hash by it ' s uid
@ method getRuntime
@ private
@ static
@ param { String } uid Unique identifier of the runtime
@ return { Runtime | Boolean } Returns runtime , if it exists and false , if - not
* /
Runtime . getRuntime = function ( uid ) {
return runtimes [ uid ] ? runtimes [ uid ] : false ;
} ;
/ * *
Register constructor for the Runtime of new ( or perhaps modified ) type
@ method addConstructor
@ static
@ param { String } type Runtime type ( e . g . flash , html5 , etc )
@ param { Function } construct Constructor for the Runtime type
* /
Runtime . addConstructor = function ( type , constructor ) {
constructor . prototype = EventTarget . instance ;
runtimeConstructors [ type ] = constructor ;
} ;
/ * *
Get the constructor for the specified type .
method getConstructor
@ static
@ param { String } type Runtime type ( e . g . flash , html5 , etc )
@ return { Function } Constructor for the Runtime type
* /
Runtime . getConstructor = function ( type ) {
return runtimeConstructors [ type ] || null ;
} ;
/ * *
Get info about the runtime ( uid , type , capabilities )
@ method getInfo
@ static
@ param { String } uid Unique identifier of the runtime
@ return { Mixed } Info object or null if runtime doesn ' t exist
* /
Runtime . getInfo = function ( uid ) {
var runtime = Runtime . getRuntime ( uid ) ;
if ( runtime ) {
return {
uid : runtime . uid ,
type : runtime . type ,
mode : runtime . mode ,
can : function ( ) {
return runtime . can . apply ( runtime , arguments ) ;
}
} ;
}
return null ;
} ;
/ * *
Convert caps represented by a comma - separated string to the object representation .
@ method parseCaps
@ static
@ param { String } capStr Comma - separated list of capabilities
@ return { Object }
* /
Runtime . parseCaps = function ( capStr ) {
var capObj = { } ;
if ( Basic . typeOf ( capStr ) !== 'string' ) {
return capStr || { } ;
}
Basic . each ( capStr . split ( ',' ) , function ( key ) {
capObj [ key ] = true ; // we assume it to be - true
} ) ;
return capObj ;
} ;
/ * *
Test the specified runtime for specific capabilities .
@ method can
@ static
@ param { String } type Runtime type ( e . g . flash , html5 , etc )
@ param { String | Object } caps Set of capabilities to check
@ return { Boolean } Result of the test
* /
Runtime . can = function ( type , caps ) {
var runtime
, constructor = Runtime . getConstructor ( type )
, mode
;
if ( constructor ) {
runtime = new constructor ( {
required _caps : caps
} ) ;
mode = runtime . mode ;
runtime . destroy ( ) ;
return ! ! mode ;
}
return false ;
} ;
/ * *
Figure out a runtime that supports specified capabilities .
@ method thatCan
@ static
@ param { String | Object } caps Set of capabilities to check
@ param { String } [ runtimeOrder ] Comma - separated list of runtimes to check against
@ return { String } Usable runtime identifier or null
* /
Runtime . thatCan = function ( caps , runtimeOrder ) {
var types = ( runtimeOrder || Runtime . order ) . split ( /\s*,\s*/ ) ;
for ( var i in types ) {
if ( Runtime . can ( types [ i ] , caps ) ) {
return types [ i ] ;
}
}
return null ;
} ;
/ * *
Figure out an operational mode for the specified set of capabilities .
@ method getMode
@ static
@ param { Object } modeCaps Set of capabilities that depend on particular runtime mode
@ param { Object } [ requiredCaps ] Supplied set of capabilities to find operational mode for
@ param { String | Boolean } [ defaultMode = 'browser' ] Default mode to use
@ return { String | Boolean } Compatible operational mode
* /
Runtime . getMode = function ( modeCaps , requiredCaps , defaultMode ) {
var mode = null ;
if ( Basic . typeOf ( defaultMode ) === 'undefined' ) { // only if not specified
defaultMode = 'browser' ;
}
if ( requiredCaps && ! Basic . isEmptyObj ( modeCaps ) ) {
// loop over required caps and check if they do require the same mode
Basic . each ( requiredCaps , function ( value , cap ) {
if ( modeCaps . hasOwnProperty ( cap ) ) {
var capMode = modeCaps [ cap ] ( value ) ;
// make sure we always have an array
if ( typeof ( capMode ) === 'string' ) {
capMode = [ capMode ] ;
}
if ( ! mode ) {
mode = capMode ;
} else if ( ! ( mode = Basic . arrayIntersect ( mode , capMode ) ) ) {
// if cap requires conflicting mode - runtime cannot fulfill required caps
return ( mode = false ) ;
}
}
} ) ;
if ( mode ) {
return Basic . inArray ( defaultMode , mode ) !== - 1 ? defaultMode : mode [ 0 ] ;
} else if ( mode === false ) {
return false ;
}
}
return defaultMode ;
} ;
/ * *
Capability check that always returns true
@ private
@ static
@ return { True }
* /
Runtime . capTrue = function ( ) {
return true ;
} ;
/ * *
Capability check that always returns false
@ private
@ static
@ return { False }
* /
Runtime . capFalse = function ( ) {
return false ;
} ;
/ * *
Evaluate the expression to boolean value and create a function that always returns it .
@ private
@ static
@ param { Mixed } expr Expression to evaluate
@ return { Function } Function returning the result of evaluation
* /
Runtime . capTest = function ( expr ) {
return function ( ) {
return ! ! expr ;
} ;
} ;
return Runtime ;
} ) ;
// Included from: src/javascript/runtime/RuntimeClient.js
/ * *
* RuntimeClient . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/runtime/RuntimeClient' , [
'moxie/core/Exceptions' ,
'moxie/core/utils/Basic' ,
'moxie/runtime/Runtime'
] , function ( x , Basic , Runtime ) {
/ * *
Set of methods and properties , required by a component to acquire ability to connect to a runtime
@ class RuntimeClient
* /
return function RuntimeClient ( ) {
var runtime ;
Basic . extend ( this , {
/ * *
Connects to the runtime specified by the options . Will either connect to existing runtime or create a new one .
Increments number of clients connected to the specified runtime .
@ method connectRuntime
@ param { Mixed } options Can be a runtme uid or a set of key - value pairs defining requirements and pre - requisites
* /
connectRuntime : function ( options ) {
var comp = this , ruid ;
function initialize ( items ) {
var type , constructor ;
// if we ran out of runtimes
if ( ! items . length ) {
comp . trigger ( 'RuntimeError' , new x . RuntimeError ( x . RuntimeError . NOT _INIT _ERR ) ) ;
runtime = null ;
return ;
}
type = items . shift ( ) ;
constructor = Runtime . getConstructor ( type ) ;
if ( ! constructor ) {
initialize ( items ) ;
return ;
}
// try initializing the runtime
runtime = new constructor ( options ) ;
runtime . bind ( 'Init' , function ( ) {
// mark runtime as initialized
runtime . initialized = true ;
// jailbreak ...
setTimeout ( function ( ) {
runtime . clients ++ ;
// this will be triggered on component
comp . trigger ( 'RuntimeInit' , runtime ) ;
} , 1 ) ;
} ) ;
runtime . bind ( 'Error' , function ( ) {
runtime . destroy ( ) ; // runtime cannot destroy itself from inside at a right moment, thus we do it here
initialize ( items ) ;
} ) ;
/*runtime.bind('Exception', function() { });*/
// check if runtime managed to pick-up operational mode
if ( ! runtime . mode ) {
runtime . trigger ( 'Error' ) ;
return ;
}
runtime . init ( ) ;
}
// check if a particular runtime was requested
if ( Basic . typeOf ( options ) === 'string' ) {
ruid = options ;
} else if ( Basic . typeOf ( options . ruid ) === 'string' ) {
ruid = options . ruid ;
}
if ( ruid ) {
runtime = Runtime . getRuntime ( ruid ) ;
if ( runtime ) {
runtime . clients ++ ;
return runtime ;
} else {
// there should be a runtime and there's none - weird case
throw new x . RuntimeError ( x . RuntimeError . NOT _INIT _ERR ) ;
}
}
// initialize a fresh one, that fits runtime list and required features best
initialize ( ( options . runtime _order || Runtime . order ) . split ( /\s*,\s*/ ) ) ;
} ,
/ * *
Returns the runtime to which the client is currently connected .
@ method getRuntime
@ return { Runtime } Runtime or null if client is not connected
* /
getRuntime : function ( ) {
if ( runtime && runtime . uid ) {
return runtime ;
}
runtime = null ; // make sure we do not leave zombies rambling around
return null ;
} ,
/ * *
Disconnects from the runtime . Decrements number of clients connected to the specified runtime .
@ method disconnectRuntime
* /
disconnectRuntime : function ( ) {
if ( runtime && -- runtime . clients <= 0 ) {
runtime . destroy ( ) ;
runtime = null ;
}
}
} ) ;
} ;
} ) ;
// Included from: src/javascript/file/Blob.js
/ * *
* Blob . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/file/Blob' , [
'moxie/core/utils/Basic' ,
'moxie/core/utils/Encode' ,
'moxie/runtime/RuntimeClient'
] , function ( Basic , Encode , RuntimeClient ) {
var blobpool = { } ;
/ * *
@ class Blob
@ constructor
@ param { String } ruid Unique id of the runtime , to which this blob belongs to
@ param { Object } blob Object "Native" blob object , as it is represented in the runtime
* /
function Blob ( ruid , blob ) {
function _sliceDetached ( start , end , type ) {
var blob , data = blobpool [ this . uid ] ;
if ( Basic . typeOf ( data ) !== 'string' || ! data . length ) {
return null ; // or throw exception
}
blob = new Blob ( null , {
type : type ,
size : end - start
} ) ;
blob . detach ( data . substr ( start , blob . size ) ) ;
return blob ;
}
RuntimeClient . call ( this ) ;
if ( ruid ) {
this . connectRuntime ( ruid ) ;
}
if ( ! blob ) {
blob = { } ;
} else if ( Basic . typeOf ( blob ) === 'string' ) { // dataUrl or binary string
blob = { data : blob } ;
}
Basic . extend ( this , {
/ * *
Unique id of the component
@ property uid
@ type { String }
* /
uid : blob . uid || Basic . guid ( 'uid_' ) ,
/ * *
Unique id of the connected runtime , if falsy , then runtime will have to be initialized
before this Blob can be used , modified or sent
@ property ruid
@ type { String }
* /
ruid : ruid ,
/ * *
Size of blob
@ property size
@ type { Number }
@ default 0
* /
size : blob . size || 0 ,
/ * *
Mime type of blob
@ property type
@ type { String }
@ default ''
* /
type : blob . type || '' ,
/ * *
@ method slice
@ param { Number } [ start = 0 ]
* /
slice : function ( start , end , type ) {
if ( this . isDetached ( ) ) {
return _sliceDetached . apply ( this , arguments ) ;
}
return this . getRuntime ( ) . exec . call ( this , 'Blob' , 'slice' , this . getSource ( ) , start , end , type ) ;
} ,
/ * *
Returns "native" blob object ( as it is represented in connected runtime ) or null if not found
@ method getSource
@ return { Blob } Returns "native" blob object or null if not found
* /
getSource : function ( ) {
if ( ! blobpool [ this . uid ] ) {
return null ;
}
return blobpool [ this . uid ] ;
} ,
/ * *
Detaches blob from any runtime that it depends on and initialize with standalone value
@ method detach
@ protected
@ param { DOMString } [ data = '' ] Standalone value
* /
detach : function ( data ) {
if ( this . ruid ) {
this . getRuntime ( ) . exec . call ( this , 'Blob' , 'destroy' ) ;
this . disconnectRuntime ( ) ;
this . ruid = null ;
}
data = data || '' ;
// if dataUrl, convert to binary string
var matches = data . match ( /^data:([^;]*);base64,/ ) ;
if ( matches ) {
this . type = matches [ 1 ] ;
data = Encode . atob ( data . substring ( data . indexOf ( 'base64,' ) + 7 ) ) ;
}
this . size = data . length ;
blobpool [ this . uid ] = data ;
} ,
/ * *
Checks if blob is standalone ( detached of any runtime )
@ method isDetached
@ protected
@ return { Boolean }
* /
isDetached : function ( ) {
return ! this . ruid && Basic . typeOf ( blobpool [ this . uid ] ) === 'string' ;
} ,
/ * *
Destroy Blob and free any resources it was using
@ method destroy
* /
destroy : function ( ) {
this . detach ( ) ;
delete blobpool [ this . uid ] ;
}
} ) ;
if ( blob . data ) {
this . detach ( blob . data ) ; // auto-detach if payload has been passed
} else {
blobpool [ this . uid ] = blob ;
}
}
return Blob ;
} ) ;
// Included from: src/javascript/file/File.js
/ * *
* File . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/file/File' , [
'moxie/core/utils/Basic' ,
'moxie/core/utils/Mime' ,
'moxie/file/Blob'
] , function ( Basic , Mime , Blob ) {
/ * *
@ class File
@ extends Blob
@ constructor
@ param { String } ruid Unique id of the runtime , to which this blob belongs to
@ param { Object } file Object "Native" file object , as it is represented in the runtime
* /
function File ( ruid , file ) {
var name , type ;
if ( ! file ) { // avoid extra errors in case we overlooked something
file = { } ;
}
// figure out the type
if ( file . type && file . type !== '' ) {
type = file . type ;
} else {
type = Mime . getFileMime ( file . name ) ;
}
// sanitize file name or generate new one
if ( file . name ) {
name = file . name . replace ( /\\/g , '/' ) ;
name = name . substr ( name . lastIndexOf ( '/' ) + 1 ) ;
} else {
var prefix = type . split ( '/' ) [ 0 ] ;
name = Basic . guid ( ( prefix !== '' ? prefix : 'file' ) + '_' ) ;
if ( Mime . extensions [ type ] ) {
name += '.' + Mime . extensions [ type ] [ 0 ] ; // append proper extension if possible
}
}
Blob . apply ( this , arguments ) ;
Basic . extend ( this , {
/ * *
File mime type
@ property type
@ type { String }
@ default ''
* /
type : type || '' ,
/ * *
File name
@ property name
@ type { String }
@ default UID
* /
name : name || Basic . guid ( 'file_' ) ,
/ * *
Relative path to the file inside a directory
@ property relativePath
@ type { String }
@ default ''
* /
relativePath : '' ,
/ * *
Date of last modification
@ property lastModifiedDate
@ type { String }
@ default now
* /
lastModifiedDate : file . lastModifiedDate || ( new Date ( ) ) . toLocaleString ( ) // Thu Aug 23 2012 19:40:00 GMT+0400 (GET)
} ) ;
}
File . prototype = Blob . prototype ;
return File ;
} ) ;
// Included from: src/javascript/file/FileInput.js
/ * *
* FileInput . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/file/FileInput' , [
'moxie/core/utils/Basic' ,
'moxie/core/utils/Mime' ,
'moxie/core/utils/Dom' ,
'moxie/core/Exceptions' ,
'moxie/core/EventTarget' ,
'moxie/core/I18n' ,
'moxie/file/File' ,
'moxie/runtime/Runtime' ,
'moxie/runtime/RuntimeClient'
] , function ( Basic , Mime , Dom , x , EventTarget , I18n , File , Runtime , RuntimeClient ) {
/ * *
Provides a convenient way to create cross - browser file - picker . Generates file selection dialog on click ,
converts selected files to _File _ objects , to be used in conjunction with _Image _ , preloaded in memory
with _FileReader _ or uploaded to a server through _XMLHttpRequest _ .
@ class FileInput
@ constructor
@ extends EventTarget
@ uses RuntimeClient
@ param { Object | String | DOMElement } options If options is string or node , argument is considered as _browse \ _button _ .
@ param { String | DOMElement } options . browse _button DOM Element to turn into file picker .
@ param { Array } [ options . accept ] Array of mime types to accept . By default accepts all .
@ param { String } [ options . file = 'file' ] Name of the file field ( not the filename ) .
@ param { Boolean } [ options . multiple = false ] Enable selection of multiple files .
@ param { Boolean } [ options . directory = false ] Turn file input into the folder input ( cannot be both at the same time ) .
@ param { String | DOMElement } [ options . container ] DOM Element to use as a container for file - picker . Defaults to parentNode
for _browse \ _button _ .
@ param { Object | String } [ options . required _caps ] Set of required capabilities , that chosen runtime must support .
@ example
< div id = "container" >
< a id = "file-picker" href = "javascript:;" > Browse ... < / a >
< / d i v >
< script >
var fileInput = new mOxie . FileInput ( {
browse _button : 'file-picker' , // or document.getElementById('file-picker')
container : 'container' ,
accept : [
{ title : "Image files" , extensions : "jpg,gif,png" } // accept only images
] ,
multiple : true // allow multiple file selection
} ) ;
fileInput . onchange = function ( e ) {
// do something to files array
console . info ( e . target . files ) ; // or this.files or fileInput.files
} ;
fileInput . init ( ) ; // initialize
< / s c r i p t >
* /
var dispatches = [
/ * *
Dispatched when runtime is connected and file - picker is ready to be used .
@ event ready
@ param { Object } event
* /
'ready' ,
/ * *
Dispatched right after [ ready ] ( # event _ready ) event , and whenever [ refresh ( ) ] ( # method _refresh ) is invoked .
Check [ corresponding documentation entry ] ( # method _refresh ) for more info .
@ event refresh
@ param { Object } event
* /
/ * *
Dispatched when selection of files in the dialog is complete .
@ event change
@ param { Object } event
* /
'change' ,
'cancel' , // TODO: might be useful
/ * *
Dispatched when mouse cursor enters file - picker area . Can be used to style element
accordingly .
@ event mouseenter
@ param { Object } event
* /
'mouseenter' ,
/ * *
Dispatched when mouse cursor leaves file - picker area . Can be used to style element
accordingly .
@ event mouseleave
@ param { Object } event
* /
'mouseleave' ,
/ * *
Dispatched when functional mouse button is pressed on top of file - picker area .
@ event mousedown
@ param { Object } event
* /
'mousedown' ,
/ * *
Dispatched when functional mouse button is released on top of file - picker area .
@ event mouseup
@ param { Object } event
* /
'mouseup'
] ;
function FileInput ( options ) {
var self = this ,
container , browseButton , defaults ;
// if flat argument passed it should be browse_button id
if ( Basic . inArray ( Basic . typeOf ( options ) , [ 'string' , 'node' ] ) !== - 1 ) {
options = { browse _button : options } ;
}
// this will help us to find proper default container
browseButton = Dom . get ( options . browse _button ) ;
if ( ! browseButton ) {
// browse button is required
throw new x . DOMException ( x . DOMException . NOT _FOUND _ERR ) ;
}
// figure out the options
defaults = {
accept : [ {
title : I18n . translate ( 'All Files' ) ,
extensions : '*'
} ] ,
name : 'file' ,
multiple : false ,
required _caps : false ,
container : browseButton . parentNode || document . body
} ;
options = Basic . extend ( { } , defaults , options ) ;
// convert to object representation
if ( typeof ( options . required _caps ) === 'string' ) {
options . required _caps = Runtime . parseCaps ( options . required _caps ) ;
}
// normalize accept option (could be list of mime types or array of title/extensions pairs)
if ( typeof ( options . accept ) === 'string' ) {
options . accept = Mime . mimes2extList ( options . accept ) ;
}
container = Dom . get ( options . container ) ;
// make sure we have container
if ( ! container ) {
container = document . body ;
}
// make container relative, if it's not
if ( Dom . getStyle ( container , 'position' ) === 'static' ) {
container . style . position = 'relative' ;
}
container = browseButton = null ; // IE
RuntimeClient . call ( self ) ;
Basic . extend ( self , {
/ * *
Unique id of the component
@ property uid
@ protected
@ readOnly
@ type { String }
@ default UID
* /
uid : Basic . guid ( 'uid_' ) ,
/ * *
Unique id of the connected runtime , if any .
@ property ruid
@ protected
@ type { String }
* /
ruid : null ,
/ * *
Unique id of the runtime container . Useful to get hold of it for various manipulations .
@ property shimid
@ protected
@ type { String }
* /
shimid : null ,
/ * *
Array of selected mOxie . File objects
@ property files
@ type { Array }
@ default null
* /
files : null ,
/ * *
Initializes the file - picker , connects it to runtime and dispatches event ready when done .
@ method init
* /
init : function ( ) {
self . convertEventPropsToHandlers ( dispatches ) ;
self . bind ( 'RuntimeInit' , function ( e , runtime ) {
self . ruid = runtime . uid ;
self . shimid = runtime . shimid ;
self . bind ( "Ready" , function ( ) {
self . trigger ( "Refresh" ) ;
} , 999 ) ;
self . bind ( "Change" , function ( ) {
var files = runtime . exec . call ( self , 'FileInput' , 'getFiles' ) ;
self . files = [ ] ;
Basic . each ( files , function ( file ) {
// ignore empty files (IE10 for example hangs if you try to send them via XHR)
if ( file . size === 0 ) {
return true ;
}
self . files . push ( new File ( self . ruid , file ) ) ;
} ) ;
} , 999 ) ;
// re-position and resize shim container
self . bind ( 'Refresh' , function ( ) {
var pos , size , browseButton , shimContainer ;
browseButton = Dom . get ( options . browse _button ) ;
shimContainer = Dom . get ( runtime . shimid ) ; // do not use runtime.getShimContainer(), since it will create container if it doesn't exist
if ( browseButton ) {
pos = Dom . getPos ( browseButton , Dom . get ( options . container ) ) ;
size = Dom . getSize ( browseButton ) ;
if ( shimContainer ) {
Basic . extend ( shimContainer . style , {
top : pos . y + 'px' ,
left : pos . x + 'px' ,
width : size . w + 'px' ,
height : size . h + 'px'
} ) ;
}
}
shimContainer = browseButton = null ;
} ) ;
runtime . exec . call ( self , 'FileInput' , 'init' , options ) ;
} ) ;
// runtime needs: options.required_features, options.runtime_order and options.container
self . connectRuntime ( Basic . extend ( { } , options , {
required _caps : {
select _file : true
}
} ) ) ;
} ,
/ * *
Disables file - picker element , so that it doesn ' t react to mouse clicks .
@ method disable
@ param { Boolean } [ state = true ] Disable component if - true , enable if - false
* /
disable : function ( state ) {
var runtime = this . getRuntime ( ) ;
if ( runtime ) {
runtime . exec . call ( this , 'FileInput' , 'disable' , Basic . typeOf ( state ) === 'undefined' ? true : state ) ;
}
} ,
/ * *
Reposition and resize dialog trigger to match the position and size of browse _button element .
@ method refresh
* /
refresh : function ( ) {
self . trigger ( "Refresh" ) ;
} ,
/ * *
Destroy component .
@ method destroy
* /
destroy : function ( ) {
var runtime = this . getRuntime ( ) ;
if ( runtime ) {
runtime . exec . call ( this , 'FileInput' , 'destroy' ) ;
this . disconnectRuntime ( ) ;
}
if ( Basic . typeOf ( this . files ) === 'array' ) {
// no sense in leaving associated files behind
Basic . each ( this . files , function ( file ) {
file . destroy ( ) ;
} ) ;
}
this . files = null ;
}
} ) ;
}
FileInput . prototype = EventTarget . instance ;
return FileInput ;
} ) ;
// Included from: src/javascript/runtime/RuntimeTarget.js
/ * *
* RuntimeTarget . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/runtime/RuntimeTarget' , [
'moxie/core/utils/Basic' ,
'moxie/runtime/RuntimeClient' ,
"moxie/core/EventTarget"
] , function ( Basic , RuntimeClient , EventTarget ) {
/ * *
Instance of this class can be used as a target for the events dispatched by shims ,
when allowing them onto components is for either reason inappropriate
@ class RuntimeTarget
@ constructor
@ protected
@ extends EventTarget
* /
function RuntimeTarget ( ) {
this . uid = Basic . guid ( 'uid_' ) ;
RuntimeClient . call ( this ) ;
this . destroy = function ( ) {
this . disconnectRuntime ( ) ;
this . unbindAll ( ) ;
} ;
}
RuntimeTarget . prototype = EventTarget . instance ;
return RuntimeTarget ;
} ) ;
// Included from: src/javascript/file/FileReader.js
/ * *
* FileReader . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/file/FileReader' , [
'moxie/core/utils/Basic' ,
'moxie/core/utils/Encode' ,
'moxie/core/Exceptions' ,
'moxie/core/EventTarget' ,
'moxie/file/Blob' ,
'moxie/file/File' ,
'moxie/runtime/RuntimeTarget'
] , function ( Basic , Encode , x , EventTarget , Blob , File , RuntimeTarget ) {
/ * *
Utility for preloading o . Blob / o . File objects in memory . By design closely follows [ W3C FileReader ] ( http : //www.w3.org/TR/FileAPI/#dfn-filereader)
interface . Where possible uses native FileReader , where - not falls back to shims .
@ class FileReader
@ constructor FileReader
@ extends EventTarget
@ uses RuntimeClient
* /
var dispatches = [
/ * *
Dispatched when the read starts .
@ event loadstart
@ param { Object } event
* /
'loadstart' ,
/ * *
Dispatched while reading ( and decoding ) blob , and reporting partial Blob data ( progess . loaded / progress . total ) .
@ event progress
@ param { Object } event
* /
'progress' ,
/ * *
Dispatched when the read has successfully completed .
@ event load
@ param { Object } event
* /
'load' ,
/ * *
Dispatched when the read has been aborted . For instance , by invoking the abort ( ) method .
@ event abort
@ param { Object } event
* /
'abort' ,
/ * *
Dispatched when the read has failed .
@ event error
@ param { Object } event
* /
'error' ,
/ * *
Dispatched when the request has completed ( either in success or failure ) .
@ event loadend
@ param { Object } event
* /
'loadend'
] ;
function FileReader ( ) {
var self = this , _fr ;
Basic . extend ( this , {
/ * *
UID of the component instance .
@ property uid
@ type { String }
* /
uid : Basic . guid ( 'uid_' ) ,
/ * *
Contains current state of FileReader object . Can take values of FileReader . EMPTY , FileReader . LOADING
and FileReader . DONE .
@ property readyState
@ type { Number }
@ default FileReader . EMPTY
* /
readyState : FileReader . EMPTY ,
/ * *
Result of the successful read operation .
@ property result
@ type { String }
* /
result : null ,
/ * *
Stores the error of failed asynchronous read operation .
@ property error
@ type { DOMError }
* /
error : null ,
/ * *
Initiates reading of File / Blob object contents to binary string .
@ method readAsBinaryString
@ param { Blob | File } blob Object to preload
* /
readAsBinaryString : function ( blob ) {
_read . call ( this , 'readAsBinaryString' , blob ) ;
} ,
/ * *
Initiates reading of File / Blob object contents to dataURL string .
@ method readAsDataURL
@ param { Blob | File } blob Object to preload
* /
readAsDataURL : function ( blob ) {
_read . call ( this , 'readAsDataURL' , blob ) ;
} ,
/ * *
Initiates reading of File / Blob object contents to string .
@ method readAsText
@ param { Blob | File } blob Object to preload
* /
readAsText : function ( blob ) {
_read . call ( this , 'readAsText' , blob ) ;
} ,
/ * *
Aborts preloading process .
@ method abort
* /
abort : function ( ) {
this . result = null ;
if ( Basic . inArray ( this . readyState , [ FileReader . EMPTY , FileReader . DONE ] ) !== - 1 ) {
return ;
} else if ( this . readyState === FileReader . LOADING ) {
this . readyState = FileReader . DONE ;
}
if ( _fr ) {
_fr . getRuntime ( ) . exec . call ( this , 'FileReader' , 'abort' ) ;
}
this . trigger ( 'abort' ) ;
this . trigger ( 'loadend' ) ;
} ,
/ * *
Destroy component and release resources .
@ method destroy
* /
destroy : function ( ) {
this . abort ( ) ;
if ( _fr ) {
_fr . getRuntime ( ) . exec . call ( this , 'FileReader' , 'destroy' ) ;
_fr . disconnectRuntime ( ) ;
}
self = _fr = null ;
}
} ) ;
function _read ( op , blob ) {
_fr = new RuntimeTarget ( ) ;
function error ( err ) {
self . readyState = FileReader . DONE ;
self . error = err ;
self . trigger ( 'error' ) ;
loadEnd ( ) ;
}
function loadEnd ( ) {
_fr . destroy ( ) ;
_fr = null ;
self . trigger ( 'loadend' ) ;
}
function exec ( runtime ) {
_fr . bind ( 'Error' , function ( e , err ) {
error ( err ) ;
} ) ;
_fr . bind ( 'Progress' , function ( e ) {
self . result = runtime . exec . call ( _fr , 'FileReader' , 'getResult' ) ;
self . trigger ( e ) ;
} ) ;
_fr . bind ( 'Load' , function ( e ) {
self . readyState = FileReader . DONE ;
self . result = runtime . exec . call ( _fr , 'FileReader' , 'getResult' ) ;
self . trigger ( e ) ;
loadEnd ( ) ;
} ) ;
runtime . exec . call ( _fr , 'FileReader' , 'read' , op , blob ) ;
}
this . convertEventPropsToHandlers ( dispatches ) ;
if ( this . readyState === FileReader . LOADING ) {
return error ( new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ) ;
}
this . readyState = FileReader . LOADING ;
this . trigger ( 'loadstart' ) ;
// if source is o.Blob/o.File
if ( blob instanceof Blob ) {
if ( blob . isDetached ( ) ) {
var src = blob . getSource ( ) ;
switch ( op ) {
case 'readAsText' :
case 'readAsBinaryString' :
this . result = src ;
break ;
case 'readAsDataURL' :
this . result = 'data:' + blob . type + ';base64,' + Encode . btoa ( src ) ;
break ;
}
this . readyState = FileReader . DONE ;
this . trigger ( 'load' ) ;
loadEnd ( ) ;
} else {
exec ( _fr . connectRuntime ( blob . ruid ) ) ;
}
} else {
error ( new x . DOMException ( x . DOMException . NOT _FOUND _ERR ) ) ;
}
}
}
/ * *
Initial FileReader state
@ property EMPTY
@ type { Number }
@ final
@ static
@ default 0
* /
FileReader . EMPTY = 0 ;
/ * *
FileReader switches to this state when it is preloading the source
@ property LOADING
@ type { Number }
@ final
@ static
@ default 1
* /
FileReader . LOADING = 1 ;
/ * *
Preloading is complete , this is a final state
@ property DONE
@ type { Number }
@ final
@ static
@ default 2
* /
FileReader . DONE = 2 ;
FileReader . prototype = EventTarget . instance ;
return FileReader ;
} ) ;
// Included from: src/javascript/core/utils/Url.js
/ * *
* Url . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/core/utils/Url' , [ ] , function ( ) {
/ * *
Parse url into separate components and fill in absent parts with parts from current url ,
based on https : //raw.github.com/kvz/phpjs/master/functions/url/parse_url.js
@ method parseUrl
@ for Utils
@ static
@ param { String } url Url to parse ( defaults to empty string if undefined )
@ return { Object } Hash containing extracted uri components
* /
var parseUrl = function ( url , currentUrl ) {
var key = [ 'source' , 'scheme' , 'authority' , 'userInfo' , 'user' , 'pass' , 'host' , 'port' , 'relative' , 'path' , 'directory' , 'file' , 'query' , 'fragment' ]
, i = key . length
, ports = {
http : 80 ,
https : 443
}
, uri = { }
, regex = /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/
, m = regex . exec ( url || '' )
;
while ( i -- ) {
if ( m [ i ] ) {
uri [ key [ i ] ] = m [ i ] ;
}
}
// when url is relative, we set the origin and the path ourselves
if ( ! uri . scheme ) {
// come up with defaults
if ( ! currentUrl || typeof ( currentUrl ) === 'string' ) {
currentUrl = parseUrl ( currentUrl || document . location . href ) ;
}
uri . scheme = currentUrl . scheme ;
uri . host = currentUrl . host ;
uri . port = currentUrl . port ;
var path = '' ;
// for urls without trailing slash we need to figure out the path
if ( /^[^\/]/ . test ( uri . path ) ) {
path = currentUrl . path ;
// if path ends with a filename, strip it
if ( ! /(\/|\/[^\.]+)$/ . test ( path ) ) {
path = path . replace ( /\/[^\/]+$/ , '/' ) ;
} else {
path += '/' ;
}
}
uri . path = path + ( uri . path || '' ) ; // site may reside at domain.com or domain.com/subdir
}
if ( ! uri . port ) {
uri . port = ports [ uri . scheme ] || 80 ;
}
uri . port = parseInt ( uri . port , 10 ) ;
if ( ! uri . path ) {
uri . path = "/" ;
}
delete uri . source ;
return uri ;
} ;
/ * *
Resolve url - among other things will turn relative url to absolute
@ method resolveUrl
@ static
@ param { String } url Either absolute or relative
@ return { String } Resolved , absolute url
* /
var resolveUrl = function ( url ) {
var ports = { // we ignore default ports
http : 80 ,
https : 443
}
, urlp = parseUrl ( url )
;
return urlp . scheme + '://' + urlp . host + ( urlp . port !== ports [ urlp . scheme ] ? ':' + urlp . port : '' ) + urlp . path + ( urlp . query ? urlp . query : '' ) ;
} ;
/ * *
Check if specified url has the same origin as the current document
@ method hasSameOrigin
@ param { String | Object } url
@ return { Boolean }
* /
var hasSameOrigin = function ( url ) {
function origin ( url ) {
return [ url . scheme , url . host , url . port ] . join ( '/' ) ;
}
if ( typeof url === 'string' ) {
url = parseUrl ( url ) ;
}
return origin ( parseUrl ( ) ) === origin ( url ) ;
} ;
return {
parseUrl : parseUrl ,
resolveUrl : resolveUrl ,
hasSameOrigin : hasSameOrigin
} ;
} ) ;
// Included from: src/javascript/file/FileReaderSync.js
/ * *
* FileReaderSync . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/file/FileReaderSync' , [
'moxie/core/utils/Basic' ,
'moxie/runtime/RuntimeClient' ,
'moxie/core/utils/Encode'
] , function ( Basic , RuntimeClient , Encode ) {
/ * *
Synchronous FileReader implementation . Something like this is available in WebWorkers environment , here
it can be used to read only preloaded blobs / files and only below certain size ( not yet sure what that ' d be ,
but probably < 1 mb ) . Not meant to be used directly by user .
@ class FileReaderSync
@ private
@ constructor
* /
return function ( ) {
RuntimeClient . call ( this ) ;
Basic . extend ( this , {
uid : Basic . guid ( 'uid_' ) ,
readAsBinaryString : function ( blob ) {
return _read . call ( this , 'readAsBinaryString' , blob ) ;
} ,
readAsDataURL : function ( blob ) {
return _read . call ( this , 'readAsDataURL' , blob ) ;
} ,
/ * r e a d A s A r r a y B u f f e r : f u n c t i o n ( b l o b ) {
return _read . call ( this , 'readAsArrayBuffer' , blob ) ;
} , * /
readAsText : function ( blob ) {
return _read . call ( this , 'readAsText' , blob ) ;
}
} ) ;
function _read ( op , blob ) {
if ( blob . isDetached ( ) ) {
var src = blob . getSource ( ) ;
switch ( op ) {
case 'readAsBinaryString' :
return src ;
case 'readAsDataURL' :
return 'data:' + blob . type + ';base64,' + Encode . btoa ( src ) ;
case 'readAsText' :
var txt = '' ;
for ( var i = 0 , length = src . length ; i < length ; i ++ ) {
txt += String . fromCharCode ( src [ i ] ) ;
}
return txt ;
}
} else {
var result = this . connectRuntime ( blob . ruid ) . exec . call ( this , 'FileReaderSync' , 'read' , op , blob ) ;
this . disconnectRuntime ( ) ;
return result ;
}
}
} ;
} ) ;
// Included from: src/javascript/xhr/FormData.js
/ * *
* FormData . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( "moxie/xhr/FormData" , [
"moxie/core/Exceptions" ,
"moxie/core/utils/Basic" ,
"moxie/file/Blob"
] , function ( x , Basic , Blob ) {
/ * *
FormData
@ class FormData
@ constructor
* /
function FormData ( ) {
var _blob , _fields = [ ] ;
Basic . extend ( this , {
/ * *
Append another key - value pair to the FormData object
@ method append
@ param { String } name Name for the new field
@ param { String | Blob | Array | Object } value Value for the field
* /
append : function ( name , value ) {
var self = this , valueType = Basic . typeOf ( value ) ;
// according to specs value might be either Blob or String
if ( value instanceof Blob ) {
_blob = {
name : name ,
value : value // unfortunately we can only send single Blob in one FormData
} ;
} else if ( 'array' === valueType ) {
name += '[]' ;
Basic . each ( value , function ( value ) {
self . append ( name , value ) ;
} ) ;
} else if ( 'object' === valueType ) {
Basic . each ( value , function ( value , key ) {
self . append ( name + '[' + key + ']' , value ) ;
} ) ;
} else if ( 'null' === valueType || 'undefined' === valueType || 'number' === valueType && isNaN ( value ) ) {
self . append ( name , "false" ) ;
} else {
_fields . push ( {
name : name ,
value : value . toString ( )
} ) ;
}
} ,
/ * *
Checks if FormData contains Blob .
@ method hasBlob
@ return { Boolean }
* /
hasBlob : function ( ) {
return ! ! this . getBlob ( ) ;
} ,
/ * *
Retrieves blob .
@ method getBlob
@ return { Object } Either Blob if found or null
* /
getBlob : function ( ) {
return _blob && _blob . value || null ;
} ,
/ * *
Retrieves blob field name .
@ method getBlobName
@ return { String } Either Blob field name or null
* /
getBlobName : function ( ) {
return _blob && _blob . name || null ;
} ,
/ * *
Loop over the fields in FormData and invoke the callback for each of them .
@ method each
@ param { Function } cb Callback to call for each field
* /
each : function ( cb ) {
Basic . each ( _fields , function ( field ) {
cb ( field . value , field . name ) ;
} ) ;
if ( _blob ) {
cb ( _blob . value , _blob . name ) ;
}
} ,
destroy : function ( ) {
_blob = null ;
_fields = [ ] ;
}
} ) ;
}
return FormData ;
} ) ;
// Included from: src/javascript/xhr/XMLHttpRequest.js
/ * *
* XMLHttpRequest . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( "moxie/xhr/XMLHttpRequest" , [
"moxie/core/utils/Basic" ,
"moxie/core/Exceptions" ,
"moxie/core/EventTarget" ,
"moxie/core/utils/Encode" ,
"moxie/core/utils/Url" ,
"moxie/runtime/Runtime" ,
"moxie/runtime/RuntimeTarget" ,
"moxie/file/Blob" ,
"moxie/file/FileReaderSync" ,
"moxie/xhr/FormData" ,
"moxie/core/utils/Env" ,
"moxie/core/utils/Mime"
] , function ( Basic , x , EventTarget , Encode , Url , Runtime , RuntimeTarget , Blob , FileReaderSync , FormData , Env , Mime ) {
var httpCode = {
100 : 'Continue' ,
101 : 'Switching Protocols' ,
102 : 'Processing' ,
200 : 'OK' ,
201 : 'Created' ,
202 : 'Accepted' ,
203 : 'Non-Authoritative Information' ,
204 : 'No Content' ,
205 : 'Reset Content' ,
206 : 'Partial Content' ,
207 : 'Multi-Status' ,
226 : 'IM Used' ,
300 : 'Multiple Choices' ,
301 : 'Moved Permanently' ,
302 : 'Found' ,
303 : 'See Other' ,
304 : 'Not Modified' ,
305 : 'Use Proxy' ,
306 : 'Reserved' ,
307 : 'Temporary Redirect' ,
400 : 'Bad Request' ,
401 : 'Unauthorized' ,
402 : 'Payment Required' ,
403 : 'Forbidden' ,
404 : 'Not Found' ,
405 : 'Method Not Allowed' ,
406 : 'Not Acceptable' ,
407 : 'Proxy Authentication Required' ,
408 : 'Request Timeout' ,
409 : 'Conflict' ,
410 : 'Gone' ,
411 : 'Length Required' ,
412 : 'Precondition Failed' ,
413 : 'Request Entity Too Large' ,
414 : 'Request-URI Too Long' ,
415 : 'Unsupported Media Type' ,
416 : 'Requested Range Not Satisfiable' ,
417 : 'Expectation Failed' ,
422 : 'Unprocessable Entity' ,
423 : 'Locked' ,
424 : 'Failed Dependency' ,
426 : 'Upgrade Required' ,
500 : 'Internal Server Error' ,
501 : 'Not Implemented' ,
502 : 'Bad Gateway' ,
503 : 'Service Unavailable' ,
504 : 'Gateway Timeout' ,
505 : 'HTTP Version Not Supported' ,
506 : 'Variant Also Negotiates' ,
507 : 'Insufficient Storage' ,
510 : 'Not Extended'
} ;
function XMLHttpRequestUpload ( ) {
this . uid = Basic . guid ( 'uid_' ) ;
}
XMLHttpRequestUpload . prototype = EventTarget . instance ;
/ * *
Implementation of XMLHttpRequest
@ class XMLHttpRequest
@ constructor
@ uses RuntimeClient
@ extends EventTarget
* /
var dispatches = [ 'loadstart' , 'progress' , 'abort' , 'error' , 'load' , 'timeout' , 'loadend' ] ; // & readystatechange (for historical reasons)
var NATIVE = 1 , RUNTIME = 2 ;
function XMLHttpRequest ( ) {
var self = this ,
// this (together with _p() @see below) is here to gracefully upgrade to setter/getter syntax where possible
props = {
/ * *
The amount of milliseconds a request can take before being terminated . Initially zero . Zero means there is no timeout .
@ property timeout
@ type Number
@ default 0
* /
timeout : 0 ,
/ * *
Current state , can take following values :
UNSENT ( numeric value 0 )
The object has been constructed .
OPENED ( numeric value 1 )
The open ( ) method has been successfully invoked . During this state request headers can be set using setRequestHeader ( ) and the request can be made using the send ( ) method .
HEADERS _RECEIVED ( numeric value 2 )
All redirects ( if any ) have been followed and all HTTP headers of the final response have been received . Several response members of the object are now available .
LOADING ( numeric value 3 )
The response entity body is being received .
DONE ( numeric value 4 )
@ property readyState
@ type Number
@ default 0 ( UNSENT )
* /
readyState : XMLHttpRequest . UNSENT ,
/ * *
True when user credentials are to be included in a cross - origin request . False when they are to be excluded
in a cross - origin request and when cookies are to be ignored in its response . Initially false .
@ property withCredentials
@ type Boolean
@ default false
* /
withCredentials : false ,
/ * *
Returns the HTTP status code .
@ property status
@ type Number
@ default 0
* /
status : 0 ,
/ * *
Returns the HTTP status text .
@ property statusText
@ type String
* /
statusText : "" ,
/ * *
Returns the response type . Can be set to change the response type . Values are :
the empty string ( default ) , "arraybuffer" , "blob" , "document" , "json" , and "text" .
@ property responseType
@ type String
* /
responseType : "" ,
/ * *
Returns the document response entity body .
Throws an "InvalidStateError" exception if responseType is not the empty string or "document" .
@ property responseXML
@ type Document
* /
responseXML : null ,
/ * *
Returns the text response entity body .
Throws an "InvalidStateError" exception if responseType is not the empty string or "text" .
@ property responseText
@ type String
* /
responseText : null ,
/ * *
Returns the response entity body ( http : //www.w3.org/TR/XMLHttpRequest/#response-entity-body).
Can become : ArrayBuffer , Blob , Document , JSON , Text
@ property response
@ type Mixed
* /
response : null
} ,
_async = true ,
_url ,
_method ,
_headers = { } ,
_user ,
_password ,
_encoding = null ,
_mimeType = null ,
// flags
_sync _flag = false ,
_send _flag = false ,
_upload _events _flag = false ,
_upload _complete _flag = false ,
_error _flag = false ,
_same _origin _flag = false ,
// times
_start _time ,
_timeoutset _time ,
_finalMime = null ,
_finalCharset = null ,
_options = { } ,
_xhr ,
_responseHeaders = '' ,
_responseHeadersBag
;
Basic . extend ( this , props , {
/ * *
Unique id of the component
@ property uid
@ type String
* /
uid : Basic . guid ( 'uid_' ) ,
/ * *
Target for Upload events
@ property upload
@ type XMLHttpRequestUpload
* /
upload : new XMLHttpRequestUpload ( ) ,
/ * *
Sets the request method , request URL , synchronous flag , request username , and request password .
Throws a "SyntaxError" exception if one of the following is true :
method is not a valid HTTP method .
url cannot be resolved .
url contains the "user:password" format in the userinfo production .
Throws a "SecurityError" exception if method is a case - insensitive match for CONNECT , TRACE or TRACK .
Throws an "InvalidAccessError" exception if one of the following is true :
Either user or password is passed as argument and the origin of url does not match the XMLHttpRequest origin .
There is an associated XMLHttpRequest document and either the timeout attribute is not zero ,
the withCredentials attribute is true , or the responseType attribute is not the empty string .
@ method open
@ param { String } method HTTP method to use on request
@ param { String } url URL to request
@ param { Boolean } [ async = true ] If false request will be done in synchronous manner . Asynchronous by default .
@ param { String } [ user ] Username to use in HTTP authentication process on server - side
@ param { String } [ password ] Password to use in HTTP authentication process on server - side
* /
open : function ( method , url , async , user , password ) {
var urlp ;
// first two arguments are required
if ( ! method || ! url ) {
throw new x . DOMException ( x . DOMException . SYNTAX _ERR ) ;
}
// 2 - check if any code point in method is higher than U+00FF or after deflating method it does not match the method
if ( /[\u0100-\uffff]/ . test ( method ) || Encode . utf8 _encode ( method ) !== method ) {
throw new x . DOMException ( x . DOMException . SYNTAX _ERR ) ;
}
// 3
if ( ! ! ~ Basic . inArray ( method . toUpperCase ( ) , [ 'CONNECT' , 'DELETE' , 'GET' , 'HEAD' , 'OPTIONS' , 'POST' , 'PUT' , 'TRACE' , 'TRACK' ] ) ) {
_method = method . toUpperCase ( ) ;
}
// 4 - allowing these methods poses a security risk
if ( ! ! ~ Basic . inArray ( _method , [ 'CONNECT' , 'TRACE' , 'TRACK' ] ) ) {
throw new x . DOMException ( x . DOMException . SECURITY _ERR ) ;
}
// 5
url = Encode . utf8 _encode ( url ) ;
// 6 - Resolve url relative to the XMLHttpRequest base URL. If the algorithm returns an error, throw a "SyntaxError".
urlp = Url . parseUrl ( url ) ;
_same _origin _flag = Url . hasSameOrigin ( urlp ) ;
// 7 - manually build up absolute url
_url = Url . resolveUrl ( url ) ;
// 9-10, 12-13
if ( ( user || password ) && ! _same _origin _flag ) {
throw new x . DOMException ( x . DOMException . INVALID _ACCESS _ERR ) ;
}
_user = user || urlp . user ;
_password = password || urlp . pass ;
// 11
_async = async || true ;
if ( _async === false && ( _p ( 'timeout' ) || _p ( 'withCredentials' ) || _p ( 'responseType' ) !== "" ) ) {
throw new x . DOMException ( x . DOMException . INVALID _ACCESS _ERR ) ;
}
// 14 - terminate abort()
// 15 - terminate send()
// 18
_sync _flag = ! _async ;
_send _flag = false ;
_headers = { } ;
_reset . call ( this ) ;
// 19
_p ( 'readyState' , XMLHttpRequest . OPENED ) ;
// 20
this . convertEventPropsToHandlers ( [ 'readystatechange' ] ) ; // unify event handlers
this . dispatchEvent ( 'readystatechange' ) ;
} ,
/ * *
Appends an header to the list of author request headers , or if header is already
in the list of author request headers , combines its value with value .
Throws an "InvalidStateError" exception if the state is not OPENED or if the send ( ) flag is set .
Throws a "SyntaxError" exception if header is not a valid HTTP header field name or if value
is not a valid HTTP header field value .
@ method setRequestHeader
@ param { String } header
@ param { String | Number } value
* /
setRequestHeader : function ( header , value ) {
var uaHeaders = [ // these headers are controlled by the user agent
"accept-charset" ,
"accept-encoding" ,
"access-control-request-headers" ,
"access-control-request-method" ,
"connection" ,
"content-length" ,
"cookie" ,
"cookie2" ,
"content-transfer-encoding" ,
"date" ,
"expect" ,
"host" ,
"keep-alive" ,
"origin" ,
"referer" ,
"te" ,
"trailer" ,
"transfer-encoding" ,
"upgrade" ,
"user-agent" ,
"via"
] ;
// 1-2
if ( _p ( 'readyState' ) !== XMLHttpRequest . OPENED || _send _flag ) {
throw new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ;
}
// 3
if ( /[\u0100-\uffff]/ . test ( header ) || Encode . utf8 _encode ( header ) !== header ) {
throw new x . DOMException ( x . DOMException . SYNTAX _ERR ) ;
}
// 4
/ * t h i s s t e p i s s e e m i n g l y b y p a s s e d i n b r o w s e r s , p r o b a b l y t o a l l o w v a r i o u s u n i c o d e c h a r a c t e r s i n h e a d e r v a l u e s
if ( /[\u0100-\uffff]/ . test ( value ) || Encode . utf8 _encode ( value ) !== value ) {
throw new x . DOMException ( x . DOMException . SYNTAX _ERR ) ;
} * /
header = Basic . trim ( header ) . toLowerCase ( ) ;
// setting of proxy-* and sec-* headers is prohibited by spec
if ( ! ! ~ Basic . inArray ( header , uaHeaders ) || /^(proxy\-|sec\-)/ . test ( header ) ) {
return false ;
}
// camelize
// browsers lowercase header names (at least for custom ones)
// header = header.replace(/\b\w/g, function($1) { return $1.toUpperCase(); });
if ( ! _headers [ header ] ) {
_headers [ header ] = value ;
} else {
// http://tools.ietf.org/html/rfc2616#section-4.2 (last paragraph)
_headers [ header ] += ', ' + value ;
}
return true ;
} ,
/ * *
Returns all headers from the response , with the exception of those whose field name is Set - Cookie or Set - Cookie2 .
@ method getAllResponseHeaders
@ return { String } reponse headers or empty string
* /
getAllResponseHeaders : function ( ) {
return _responseHeaders || '' ;
} ,
/ * *
Returns the header field value from the response of which the field name matches header ,
unless the field name is Set - Cookie or Set - Cookie2 .
@ method getResponseHeader
@ param { String } header
@ return { String } value ( s ) for the specified header or null
* /
getResponseHeader : function ( header ) {
header = header . toLowerCase ( ) ;
if ( _error _flag || ! ! ~ Basic . inArray ( header , [ 'set-cookie' , 'set-cookie2' ] ) ) {
return null ;
}
if ( _responseHeaders && _responseHeaders !== '' ) {
// if we didn't parse response headers until now, do it and keep for later
if ( ! _responseHeadersBag ) {
_responseHeadersBag = { } ;
Basic . each ( _responseHeaders . split ( /\r\n/ ) , function ( line ) {
var pair = line . split ( /:\s+/ ) ;
if ( pair . length === 2 ) { // last line might be empty, omit
pair [ 0 ] = Basic . trim ( pair [ 0 ] ) ; // just in case
_responseHeadersBag [ pair [ 0 ] . toLowerCase ( ) ] = { // simply to retain header name in original form
header : pair [ 0 ] ,
value : Basic . trim ( pair [ 1 ] )
} ;
}
} ) ;
}
if ( _responseHeadersBag . hasOwnProperty ( header ) ) {
return _responseHeadersBag [ header ] . header + ': ' + _responseHeadersBag [ header ] . value ;
}
}
return null ;
} ,
/ * *
Sets the Content - Type header for the response to mime .
Throws an "InvalidStateError" exception if the state is LOADING or DONE .
Throws a "SyntaxError" exception if mime is not a valid media type .
@ method overrideMimeType
@ param String mime Mime type to set
* /
overrideMimeType : function ( mime ) {
var matches , charset ;
// 1
if ( ! ! ~ Basic . inArray ( _p ( 'readyState' ) , [ XMLHttpRequest . LOADING , XMLHttpRequest . DONE ] ) ) {
throw new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ;
}
// 2
mime = Basic . trim ( mime . toLowerCase ( ) ) ;
if ( /;/ . test ( mime ) && ( matches = mime . match ( /^([^;]+)(?:;\scharset\=)?(.*)$/ ) ) ) {
mime = matches [ 1 ] ;
if ( matches [ 2 ] ) {
charset = matches [ 2 ] ;
}
}
if ( ! Mime . mimes [ mime ] ) {
throw new x . DOMException ( x . DOMException . SYNTAX _ERR ) ;
}
// 3-4
_finalMime = mime ;
_finalCharset = charset ;
} ,
/ * *
Initiates the request . The optional argument provides the request entity body .
The argument is ignored if request method is GET or HEAD .
Throws an "InvalidStateError" exception if the state is not OPENED or if the send ( ) flag is set .
@ method send
@ param { Blob | Document | String | FormData } [ data ] Request entity body
@ param { Object } [ options ] Set of requirements and pre - requisities for runtime initialization
* /
send : function ( data , options ) {
if ( Basic . typeOf ( options ) === 'string' ) {
_options = { ruid : options } ;
} else if ( ! options ) {
_options = { } ;
} else {
_options = options ;
}
this . convertEventPropsToHandlers ( dispatches ) ;
this . upload . convertEventPropsToHandlers ( dispatches ) ;
// 1-2
if ( this . readyState !== XMLHttpRequest . OPENED || _send _flag ) {
throw new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ;
}
// 3
// sending Blob
if ( data instanceof Blob ) {
_options . ruid = data . ruid ;
_mimeType = data . type || 'application/octet-stream' ;
}
// FormData
else if ( data instanceof FormData ) {
if ( data . hasBlob ( ) ) {
var blob = data . getBlob ( ) ;
_options . ruid = blob . ruid ;
_mimeType = blob . type || 'application/octet-stream' ;
}
}
// DOMString
else if ( typeof data === 'string' ) {
_encoding = 'UTF-8' ;
_mimeType = 'text/plain;charset=UTF-8' ;
// data should be converted to Unicode and encoded as UTF-8
data = Encode . utf8 _encode ( data ) ;
}
// if withCredentials not set, but requested, set it automatically
if ( ! this . withCredentials ) {
this . withCredentials = ( _options . required _caps && _options . required _caps . send _browser _cookies ) && ! _same _origin _flag ;
}
// 4 - storage mutex
// 5
_upload _events _flag = ( ! _sync _flag && this . upload . hasEventListener ( ) ) ; // DSAP
// 6
_error _flag = false ;
// 7
_upload _complete _flag = ! data ;
// 8 - Asynchronous steps
if ( ! _sync _flag ) {
// 8.1
_send _flag = true ;
// 8.2
// this.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr
// 8.3
//if (!_upload_complete_flag) {
// this.upload.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr
//}
}
// 8.5 - Return the send() method call, but continue running the steps in this algorithm.
_doXHR . call ( this , data ) ;
} ,
/ * *
Cancels any network activity .
@ method abort
* /
abort : function ( ) {
_error _flag = true ;
_sync _flag = false ;
if ( ! ~ Basic . inArray ( _p ( 'readyState' ) , [ XMLHttpRequest . UNSENT , XMLHttpRequest . OPENED , XMLHttpRequest . DONE ] ) ) {
_p ( 'readyState' , XMLHttpRequest . DONE ) ;
_send _flag = false ;
if ( _xhr ) {
_xhr . getRuntime ( ) . exec . call ( _xhr , 'XMLHttpRequest' , 'abort' , _upload _complete _flag ) ;
} else {
throw new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ;
}
_upload _complete _flag = true ;
} else {
_p ( 'readyState' , XMLHttpRequest . UNSENT ) ;
}
} ,
destroy : function ( ) {
if ( _xhr ) {
if ( Basic . typeOf ( _xhr . destroy ) === 'function' ) {
_xhr . destroy ( ) ;
}
_xhr = null ;
}
this . unbindAll ( ) ;
if ( this . upload ) {
this . upload . unbindAll ( ) ;
this . upload = null ;
}
}
} ) ;
/ * t h i s i s n i c e , b u t m a y b e t o o l e n g t h y
// if supported by JS version, set getters/setters for specific properties
o . defineProperty ( this , 'readyState' , {
configurable : false ,
get : function ( ) {
return _p ( 'readyState' ) ;
}
} ) ;
o . defineProperty ( this , 'timeout' , {
configurable : false ,
get : function ( ) {
return _p ( 'timeout' ) ;
} ,
set : function ( value ) {
if ( _sync _flag ) {
throw new x . DOMException ( x . DOMException . INVALID _ACCESS _ERR ) ;
}
// timeout still should be measured relative to the start time of request
_timeoutset _time = ( new Date ) . getTime ( ) ;
_p ( 'timeout' , value ) ;
}
} ) ;
// the withCredentials attribute has no effect when fetching same-origin resources
o . defineProperty ( this , 'withCredentials' , {
configurable : false ,
get : function ( ) {
return _p ( 'withCredentials' ) ;
} ,
set : function ( value ) {
// 1-2
if ( ! ~ o . inArray ( _p ( 'readyState' ) , [ XMLHttpRequest . UNSENT , XMLHttpRequest . OPENED ] ) || _send _flag ) {
throw new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ;
}
// 3-4
if ( _anonymous _flag || _sync _flag ) {
throw new x . DOMException ( x . DOMException . INVALID _ACCESS _ERR ) ;
}
// 5
_p ( 'withCredentials' , value ) ;
}
} ) ;
o . defineProperty ( this , 'status' , {
configurable : false ,
get : function ( ) {
return _p ( 'status' ) ;
}
} ) ;
o . defineProperty ( this , 'statusText' , {
configurable : false ,
get : function ( ) {
return _p ( 'statusText' ) ;
}
} ) ;
o . defineProperty ( this , 'responseType' , {
configurable : false ,
get : function ( ) {
return _p ( 'responseType' ) ;
} ,
set : function ( value ) {
// 1
if ( ! ! ~ o . inArray ( _p ( 'readyState' ) , [ XMLHttpRequest . LOADING , XMLHttpRequest . DONE ] ) ) {
throw new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ;
}
// 2
if ( _sync _flag ) {
throw new x . DOMException ( x . DOMException . INVALID _ACCESS _ERR ) ;
}
// 3
_p ( 'responseType' , value . toLowerCase ( ) ) ;
}
} ) ;
o . defineProperty ( this , 'responseText' , {
configurable : false ,
get : function ( ) {
// 1
if ( ! ~ o . inArray ( _p ( 'responseType' ) , [ '' , 'text' ] ) ) {
throw new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ;
}
// 2-3
if ( _p ( 'readyState' ) !== XMLHttpRequest . DONE && _p ( 'readyState' ) !== XMLHttpRequest . LOADING || _error _flag ) {
throw new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ;
}
return _p ( 'responseText' ) ;
}
} ) ;
o . defineProperty ( this , 'responseXML' , {
configurable : false ,
get : function ( ) {
// 1
if ( ! ~ o . inArray ( _p ( 'responseType' ) , [ '' , 'document' ] ) ) {
throw new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ;
}
// 2-3
if ( _p ( 'readyState' ) !== XMLHttpRequest . DONE || _error _flag ) {
throw new x . DOMException ( x . DOMException . INVALID _STATE _ERR ) ;
}
return _p ( 'responseXML' ) ;
}
} ) ;
o . defineProperty ( this , 'response' , {
configurable : false ,
get : function ( ) {
if ( ! ! ~ o . inArray ( _p ( 'responseType' ) , [ '' , 'text' ] ) ) {
if ( _p ( 'readyState' ) !== XMLHttpRequest . DONE && _p ( 'readyState' ) !== XMLHttpRequest . LOADING || _error _flag ) {
return '' ;
}
}
if ( _p ( 'readyState' ) !== XMLHttpRequest . DONE || _error _flag ) {
return null ;
}
return _p ( 'response' ) ;
}
} ) ;
* /
function _p ( prop , value ) {
if ( ! props . hasOwnProperty ( prop ) ) {
return ;
}
if ( arguments . length === 1 ) { // get
return Env . can ( 'define_property' ) ? props [ prop ] : self [ prop ] ;
} else { // set
if ( Env . can ( 'define_property' ) ) {
props [ prop ] = value ;
} else {
self [ prop ] = value ;
}
}
}
/ *
function _toASCII ( str , AllowUnassigned , UseSTD3ASCIIRules ) {
// TODO: http://tools.ietf.org/html/rfc3490#section-4.1
return str . toLowerCase ( ) ;
}
* /
function _doXHR ( data ) {
var self = this ;
_start _time = new Date ( ) . getTime ( ) ;
_xhr = new RuntimeTarget ( ) ;
function loadEnd ( ) {
if ( _xhr ) { // it could have been destroyed by now
_xhr . destroy ( ) ;
_xhr = null ;
}
self . dispatchEvent ( 'loadend' ) ;
self = null ;
}
function exec ( runtime ) {
_xhr . bind ( 'LoadStart' , function ( e ) {
_p ( 'readyState' , XMLHttpRequest . LOADING ) ;
self . dispatchEvent ( 'readystatechange' ) ;
self . dispatchEvent ( e ) ;
if ( _upload _events _flag ) {
self . upload . dispatchEvent ( e ) ;
}
} ) ;
_xhr . bind ( 'Progress' , function ( e ) {
if ( _p ( 'readyState' ) !== XMLHttpRequest . LOADING ) {
_p ( 'readyState' , XMLHttpRequest . LOADING ) ; // LoadStart unreliable (in Flash for example)
self . dispatchEvent ( 'readystatechange' ) ;
}
self . dispatchEvent ( e ) ;
} ) ;
_xhr . bind ( 'UploadProgress' , function ( e ) {
if ( _upload _events _flag ) {
self . upload . dispatchEvent ( {
type : 'progress' ,
lengthComputable : false ,
total : e . total ,
loaded : e . loaded
} ) ;
}
} ) ;
_xhr . bind ( 'Load' , function ( e ) {
_p ( 'readyState' , XMLHttpRequest . DONE ) ;
_p ( 'status' , Number ( runtime . exec . call ( _xhr , 'XMLHttpRequest' , 'getStatus' ) || 0 ) ) ;
_p ( 'statusText' , httpCode [ _p ( 'status' ) ] || "" ) ;
_p ( 'response' , runtime . exec . call ( _xhr , 'XMLHttpRequest' , 'getResponse' , _p ( 'responseType' ) ) ) ;
if ( ! ! ~ Basic . inArray ( _p ( 'responseType' ) , [ 'text' , '' ] ) ) {
_p ( 'responseText' , _p ( 'response' ) ) ;
} else if ( _p ( 'responseType' ) === 'document' ) {
_p ( 'responseXML' , _p ( 'response' ) ) ;
}
_responseHeaders = runtime . exec . call ( _xhr , 'XMLHttpRequest' , 'getAllResponseHeaders' ) ;
self . dispatchEvent ( 'readystatechange' ) ;
if ( _p ( 'status' ) > 0 ) { // status 0 usually means that server is unreachable
if ( _upload _events _flag ) {
self . upload . dispatchEvent ( e ) ;
}
self . dispatchEvent ( e ) ;
} else {
_error _flag = true ;
self . dispatchEvent ( 'error' ) ;
}
loadEnd ( ) ;
} ) ;
_xhr . bind ( 'Abort' , function ( e ) {
self . dispatchEvent ( e ) ;
loadEnd ( ) ;
} ) ;
_xhr . bind ( 'Error' , function ( e ) {
_error _flag = true ;
_p ( 'readyState' , XMLHttpRequest . DONE ) ;
self . dispatchEvent ( 'readystatechange' ) ;
_upload _complete _flag = true ;
self . dispatchEvent ( e ) ;
loadEnd ( ) ;
} ) ;
runtime . exec . call ( _xhr , 'XMLHttpRequest' , 'send' , {
url : _url ,
method : _method ,
async : _async ,
user : _user ,
password : _password ,
headers : _headers ,
mimeType : _mimeType ,
encoding : _encoding ,
responseType : self . responseType ,
withCredentials : self . withCredentials ,
options : _options
} , data ) ;
}
// clarify our requirements
if ( typeof ( _options . required _caps ) === 'string' ) {
_options . required _caps = Runtime . parseCaps ( _options . required _caps ) ;
}
_options . required _caps = Basic . extend ( { } , _options . required _caps , {
return _response _type : self . responseType
} ) ;
if ( data instanceof FormData ) {
_options . required _caps . send _multipart = true ;
}
if ( ! _same _origin _flag ) {
_options . required _caps . do _cors = true ;
}
if ( _options . ruid ) { // we do not need to wait if we can connect directly
exec ( _xhr . connectRuntime ( _options ) ) ;
} else {
_xhr . bind ( 'RuntimeInit' , function ( e , runtime ) {
exec ( runtime ) ;
} ) ;
_xhr . bind ( 'RuntimeError' , function ( e , err ) {
self . dispatchEvent ( 'RuntimeError' , err ) ;
} ) ;
_xhr . connectRuntime ( _options ) ;
}
}
function _reset ( ) {
_p ( 'responseText' , "" ) ;
_p ( 'responseXML' , null ) ;
_p ( 'response' , null ) ;
_p ( 'status' , 0 ) ;
_p ( 'statusText' , "" ) ;
_start _time = _timeoutset _time = null ;
}
}
XMLHttpRequest . UNSENT = 0 ;
XMLHttpRequest . OPENED = 1 ;
XMLHttpRequest . HEADERS _RECEIVED = 2 ;
XMLHttpRequest . LOADING = 3 ;
XMLHttpRequest . DONE = 4 ;
XMLHttpRequest . prototype = EventTarget . instance ;
return XMLHttpRequest ;
} ) ;
// Included from: src/javascript/runtime/flash/Runtime.js
/ * *
* Runtime . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/*global ActiveXObject:true */
/ * *
Defines constructor for Flash runtime .
@ class moxie / runtime / flash / Runtime
@ private
* /
define ( "moxie/runtime/flash/Runtime" , [
"moxie/core/utils/Basic" ,
"moxie/core/utils/Env" ,
"moxie/core/utils/Dom" ,
"moxie/core/Exceptions" ,
"moxie/runtime/Runtime"
] , function ( Basic , Env , Dom , x , Runtime ) {
var type = 'flash' , extensions = { } ;
/ * *
Get the version of the Flash Player
@ method getShimVersion
@ private
@ return { Number } Flash Player version
* /
function getShimVersion ( ) {
var version ;
try {
version = navigator . plugins [ 'Shockwave Flash' ] ;
version = version . description ;
} catch ( e1 ) {
try {
version = new ActiveXObject ( 'ShockwaveFlash.ShockwaveFlash' ) . GetVariable ( '$version' ) ;
} catch ( e2 ) {
version = '0.0' ;
}
}
version = version . match ( /\d+/g ) ;
return parseFloat ( version [ 0 ] + '.' + version [ 1 ] ) ;
}
/ * *
Constructor for the Flash Runtime
@ class FlashRuntime
@ extends Runtime
* /
function FlashRuntime ( options ) {
var I = this , initTimer ;
options = Basic . extend ( { swf _url : Env . swf _url } , options ) ;
Runtime . call ( this , options , type , {
access _binary : function ( value ) {
return value && I . mode === 'browser' ;
} ,
access _image _binary : function ( value ) {
return value && I . mode === 'browser' ;
} ,
display _media : Runtime . capTrue ,
do _cors : Runtime . capTrue ,
drag _and _drop : false ,
report _upload _progress : function ( ) {
return I . mode === 'client' ;
} ,
resize _image : Runtime . capTrue ,
return _response _headers : false ,
return _response _type : function ( responseType ) {
if ( responseType === 'json' && ! ! window . JSON ) {
return true ;
}
return ! Basic . arrayDiff ( responseType , [ '' , 'text' , 'document' ] ) || I . mode === 'browser' ;
} ,
return _status _code : function ( code ) {
return I . mode === 'browser' || ! Basic . arrayDiff ( code , [ 200 , 404 ] ) ;
} ,
select _file : Runtime . capTrue ,
select _multiple : Runtime . capTrue ,
send _binary _string : function ( value ) {
return value && I . mode === 'browser' ;
} ,
send _browser _cookies : function ( value ) {
return value && I . mode === 'browser' ;
} ,
send _custom _headers : function ( value ) {
return value && I . mode === 'browser' ;
} ,
send _multipart : Runtime . capTrue ,
slice _blob : function ( value ) {
return value && I . mode === 'browser' ;
} ,
stream _upload : function ( value ) {
return value && I . mode === 'browser' ;
} ,
summon _file _dialog : false ,
upload _filesize : function ( size ) {
return Basic . parseSizeStr ( size ) <= 2097152 || I . mode === 'client' ;
} ,
use _http _method : function ( methods ) {
return ! Basic . arrayDiff ( methods , [ 'GET' , 'POST' ] ) ;
}
} , {
// capabilities that require specific mode
access _binary : function ( value ) {
return value ? 'browser' : 'client' ;
} ,
access _image _binary : function ( value ) {
return value ? 'browser' : 'client' ;
} ,
report _upload _progress : function ( value ) {
return value ? 'browser' : 'client' ;
} ,
return _response _type : function ( responseType ) {
return Basic . arrayDiff ( responseType , [ '' , 'text' , 'json' , 'document' ] ) ? 'browser' : [ 'client' , 'browser' ] ;
} ,
return _status _code : function ( code ) {
return Basic . arrayDiff ( code , [ 200 , 404 ] ) ? 'browser' : [ 'client' , 'browser' ] ;
} ,
send _binary _string : function ( value ) {
return value ? 'browser' : 'client' ;
} ,
send _browser _cookies : function ( value ) {
return value ? 'browser' : 'client' ;
} ,
send _custom _headers : function ( value ) {
return value ? 'browser' : 'client' ;
} ,
stream _upload : function ( value ) {
return value ? 'client' : 'browser' ;
} ,
upload _filesize : function ( size ) {
return Basic . parseSizeStr ( size ) >= 2097152 ? 'client' : 'browser' ;
}
} , 'client' ) ;
// minimal requirement for Flash Player version
if ( getShimVersion ( ) < 10 ) {
this . mode = false ; // with falsy mode, runtime won't operable, no matter what the mode was before
}
Basic . extend ( this , {
getShim : function ( ) {
return Dom . get ( this . uid ) ;
} ,
shimExec : function ( component , action ) {
var args = [ ] . slice . call ( arguments , 2 ) ;
return I . getShim ( ) . exec ( this . uid , component , action , args ) ;
} ,
init : function ( ) {
var html , el , container ;
container = this . getShimContainer ( ) ;
// if not the minimal height, shims are not initialized in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)
Basic . extend ( container . style , {
position : 'absolute' ,
top : '-8px' ,
left : '-8px' ,
width : '9px' ,
height : '9px' ,
overflow : 'hidden'
} ) ;
// insert flash object
html = '<object id="' + this . uid + '" type="application/x-shockwave-flash" data="' + options . swf _url + '" ' ;
if ( Env . browser === 'IE' ) {
html += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ' ;
}
html += 'width="100%" height="100%" style="outline:0">' +
'<param name="movie" value="' + options . swf _url + '" />' +
'<param name="flashvars" value="uid=' + escape ( this . uid ) + '&target=' + Env . global _event _dispatcher + '" />' +
'<param name="wmode" value="transparent" />' +
'<param name="allowscriptaccess" value="always" />' +
'</object>' ;
if ( Env . browser === 'IE' ) {
el = document . createElement ( 'div' ) ;
container . appendChild ( el ) ;
el . outerHTML = html ;
el = container = null ; // just in case
} else {
container . innerHTML = html ;
}
// Init is dispatched by the shim
initTimer = setTimeout ( function ( ) {
if ( I && ! I . initialized ) { // runtime might be already destroyed by this moment
I . trigger ( "Error" , new x . RuntimeError ( x . RuntimeError . NOT _INIT _ERR ) ) ;
}
} , 5000 ) ;
} ,
destroy : ( function ( destroy ) { // extend default destroy method
return function ( ) {
destroy . call ( I ) ;
clearTimeout ( initTimer ) ; // initialization check might be still onwait
options = initTimer = destroy = I = null ;
} ;
} ( this . destroy ) )
} , extensions ) ;
}
Runtime . addConstructor ( type , FlashRuntime ) ;
return extensions ;
} ) ;
// Included from: src/javascript/runtime/flash/file/Blob.js
/ * *
* Blob . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / flash / file / Blob
@ private
* /
define ( "moxie/runtime/flash/file/Blob" , [
"moxie/runtime/flash/Runtime" ,
"moxie/file/Blob"
] , function ( extensions , Blob ) {
var FlashBlob = {
slice : function ( blob , start , end , type ) {
var self = this . getRuntime ( ) ;
if ( start < 0 ) {
start = Math . max ( blob . size + start , 0 ) ;
} else if ( start > 0 ) {
start = Math . min ( start , blob . size ) ;
}
if ( end < 0 ) {
end = Math . max ( blob . size + end , 0 ) ;
} else if ( end > 0 ) {
end = Math . min ( end , blob . size ) ;
}
blob = self . shimExec . call ( this , 'Blob' , 'slice' , start , end , type || '' ) ;
if ( blob ) {
blob = new Blob ( self . uid , blob ) ;
}
return blob ;
}
} ;
return ( extensions . Blob = FlashBlob ) ;
} ) ;
// Included from: src/javascript/runtime/flash/file/FileInput.js
/ * *
* FileInput . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / flash / file / FileInput
@ private
* /
define ( "moxie/runtime/flash/file/FileInput" , [
"moxie/runtime/flash/Runtime"
] , function ( extensions ) {
var FileInput = {
init : function ( options ) {
this . getRuntime ( ) . shimExec . call ( this , 'FileInput' , 'init' , {
name : options . name ,
accept : options . accept ,
multiple : options . multiple
} ) ;
this . trigger ( 'ready' ) ;
}
} ;
return ( extensions . FileInput = FileInput ) ;
} ) ;
// Included from: src/javascript/runtime/flash/file/FileReader.js
/ * *
* FileReader . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / flash / file / FileReader
@ private
* /
define ( "moxie/runtime/flash/file/FileReader" , [
"moxie/runtime/flash/Runtime" ,
"moxie/core/utils/Encode"
] , function ( extensions , Encode ) {
var _result = '' ;
function _formatData ( data , op ) {
switch ( op ) {
case 'readAsText' :
return Encode . atob ( data , 'utf8' ) ;
case 'readAsBinaryString' :
return Encode . atob ( data ) ;
case 'readAsDataURL' :
return data ;
}
return null ;
}
var FileReader = {
read : function ( op , blob ) {
var target = this , self = target . getRuntime ( ) ;
// special prefix for DataURL read mode
if ( op === 'readAsDataURL' ) {
_result = 'data:' + ( blob . type || '' ) + ';base64,' ;
}
target . bind ( 'Progress' , function ( e , data ) {
if ( data ) {
_result += _formatData ( data , op ) ;
}
} ) ;
return self . shimExec . call ( this , 'FileReader' , 'readAsBase64' , blob . uid ) ;
} ,
getResult : function ( ) {
return _result ;
} ,
destroy : function ( ) {
_result = null ;
}
} ;
return ( extensions . FileReader = FileReader ) ;
} ) ;
// Included from: src/javascript/runtime/flash/file/FileReaderSync.js
/ * *
* FileReaderSync . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / flash / file / FileReaderSync
@ private
* /
define ( "moxie/runtime/flash/file/FileReaderSync" , [
"moxie/runtime/flash/Runtime" ,
"moxie/core/utils/Encode"
] , function ( extensions , Encode ) {
function _formatData ( data , op ) {
switch ( op ) {
case 'readAsText' :
return Encode . atob ( data , 'utf8' ) ;
case 'readAsBinaryString' :
return Encode . atob ( data ) ;
case 'readAsDataURL' :
return data ;
}
return null ;
}
var FileReaderSync = {
read : function ( op , blob ) {
var result , self = this . getRuntime ( ) ;
result = self . shimExec . call ( this , 'FileReaderSync' , 'readAsBase64' , blob . uid ) ;
if ( ! result ) {
return null ; // or throw ex
}
// special prefix for DataURL read mode
if ( op === 'readAsDataURL' ) {
result = 'data:' + ( blob . type || '' ) + ';base64,' + result ;
}
return _formatData ( result , op , blob . type ) ;
}
} ;
return ( extensions . FileReaderSync = FileReaderSync ) ;
} ) ;
// Included from: src/javascript/runtime/Transporter.js
/ * *
* Transporter . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( "moxie/runtime/Transporter" , [
"moxie/core/utils/Basic" ,
"moxie/core/utils/Encode" ,
"moxie/runtime/RuntimeClient" ,
"moxie/core/EventTarget"
] , function ( Basic , Encode , RuntimeClient , EventTarget ) {
function Transporter ( ) {
var mod , _runtime , _data , _size , _pos , _chunk _size ;
RuntimeClient . call ( this ) ;
Basic . extend ( this , {
uid : Basic . guid ( 'uid_' ) ,
state : Transporter . IDLE ,
result : null ,
transport : function ( data , type , options ) {
var self = this ;
options = Basic . extend ( {
chunk _size : 204798
} , options ) ;
// should divide by three, base64 requires this
if ( ( mod = options . chunk _size % 3 ) ) {
options . chunk _size += 3 - mod ;
}
_chunk _size = options . chunk _size ;
_reset . call ( this ) ;
_data = data ;
_size = data . length ;
if ( Basic . typeOf ( options ) === 'string' || options . ruid ) {
_run . call ( self , type , this . connectRuntime ( options ) ) ;
} else {
// we require this to run only once
var cb = function ( e , runtime ) {
self . unbind ( "RuntimeInit" , cb ) ;
_run . call ( self , type , runtime ) ;
} ;
this . bind ( "RuntimeInit" , cb ) ;
this . connectRuntime ( options ) ;
}
} ,
abort : function ( ) {
var self = this ;
self . state = Transporter . IDLE ;
if ( _runtime ) {
_runtime . exec . call ( self , 'Transporter' , 'clear' ) ;
self . trigger ( "TransportingAborted" ) ;
}
_reset . call ( self ) ;
} ,
destroy : function ( ) {
this . unbindAll ( ) ;
_runtime = null ;
this . disconnectRuntime ( ) ;
_reset . call ( this ) ;
}
} ) ;
function _reset ( ) {
_size = _pos = 0 ;
_data = this . result = null ;
}
function _run ( type , runtime ) {
var self = this ;
_runtime = runtime ;
//self.unbind("RuntimeInit");
self . bind ( "TransportingProgress" , function ( e ) {
_pos = e . loaded ;
if ( _pos < _size && Basic . inArray ( self . state , [ Transporter . IDLE , Transporter . DONE ] ) === - 1 ) {
_transport . call ( self ) ;
}
} , 999 ) ;
self . bind ( "TransportingComplete" , function ( ) {
_pos = _size ;
self . state = Transporter . DONE ;
_data = null ; // clean a bit
self . result = _runtime . exec . call ( self , 'Transporter' , 'getAsBlob' , type || '' ) ;
} , 999 ) ;
self . state = Transporter . BUSY ;
self . trigger ( "TransportingStarted" ) ;
_transport . call ( self ) ;
}
function _transport ( ) {
var self = this ,
chunk ,
bytesLeft = _size - _pos ;
if ( _chunk _size > bytesLeft ) {
_chunk _size = bytesLeft ;
}
chunk = Encode . btoa ( _data . substr ( _pos , _chunk _size ) ) ;
_runtime . exec . call ( self , 'Transporter' , 'receive' , chunk , _size ) ;
}
}
Transporter . IDLE = 0 ;
Transporter . BUSY = 1 ;
Transporter . DONE = 2 ;
Transporter . prototype = EventTarget . instance ;
return Transporter ;
} ) ;
// Included from: src/javascript/runtime/flash/xhr/XMLHttpRequest.js
/ * *
* XMLHttpRequest . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / flash / xhr / XMLHttpRequest
@ private
* /
define ( "moxie/runtime/flash/xhr/XMLHttpRequest" , [
"moxie/runtime/flash/Runtime" ,
"moxie/core/utils/Basic" ,
"moxie/file/Blob" ,
"moxie/file/File" ,
"moxie/file/FileReaderSync" ,
"moxie/xhr/FormData" ,
"moxie/runtime/Transporter"
] , function ( extensions , Basic , Blob , File , FileReaderSync , FormData , Transporter ) {
var XMLHttpRequest = {
send : function ( meta , data ) {
var target = this , self = target . getRuntime ( ) ;
function send ( ) {
meta . transport = self . mode ;
self . shimExec . call ( target , 'XMLHttpRequest' , 'send' , meta , data ) ;
}
function appendBlob ( name , blob ) {
self . shimExec . call ( target , 'XMLHttpRequest' , 'appendBlob' , name , blob . uid ) ;
data = null ;
send ( ) ;
}
function attachBlob ( blob , cb ) {
var tr = new Transporter ( ) ;
tr . bind ( "TransportingComplete" , function ( ) {
cb ( this . result ) ;
} ) ;
tr . transport ( blob . getSource ( ) , blob . type , {
ruid : self . uid
} ) ;
}
// copy over the headers if any
if ( ! Basic . isEmptyObj ( meta . headers ) ) {
Basic . each ( meta . headers , function ( value , header ) {
self . shimExec . call ( target , 'XMLHttpRequest' , 'setRequestHeader' , header , value . toString ( ) ) ; // Silverlight doesn't accept integers into the arguments of type object
} ) ;
}
// transfer over multipart params and blob itself
if ( data instanceof FormData ) {
var blobField ;
data . each ( function ( value , name ) {
if ( value instanceof Blob ) {
blobField = name ;
} else {
self . shimExec . call ( target , 'XMLHttpRequest' , 'append' , name , value ) ;
}
} ) ;
if ( ! data . hasBlob ( ) ) {
data = null ;
send ( ) ;
} else {
var blob = data . getBlob ( ) ;
if ( blob . isDetached ( ) ) {
attachBlob ( blob , function ( attachedBlob ) {
blob . destroy ( ) ;
appendBlob ( blobField , attachedBlob ) ;
} ) ;
} else {
appendBlob ( blobField , blob ) ;
}
}
} else if ( data instanceof Blob ) {
if ( data . isDetached ( ) ) {
attachBlob ( data , function ( attachedBlob ) {
data . destroy ( ) ;
data = attachedBlob . uid ;
send ( ) ;
} ) ;
} else {
data = data . uid ;
send ( ) ;
}
} else {
send ( ) ;
}
} ,
getResponse : function ( responseType ) {
var frs , blob , self = this . getRuntime ( ) ;
blob = self . shimExec . call ( this , 'XMLHttpRequest' , 'getResponseAsBlob' ) ;
if ( blob ) {
blob = new File ( self . uid , blob ) ;
if ( 'blob' === responseType ) {
return blob ;
}
try {
frs = new FileReaderSync ( ) ;
if ( ! ! ~ Basic . inArray ( responseType , [ "" , "text" ] ) ) {
return frs . readAsText ( blob ) ;
} else if ( 'json' === responseType && ! ! window . JSON ) {
return JSON . parse ( frs . readAsText ( blob ) ) ;
}
} finally {
blob . destroy ( ) ;
}
}
return null ;
} ,
abort : function ( upload _complete _flag ) {
var self = this . getRuntime ( ) ;
self . shimExec . call ( this , 'XMLHttpRequest' , 'abort' ) ;
this . dispatchEvent ( 'readystatechange' ) ;
// this.dispatchEvent('progress');
this . dispatchEvent ( 'abort' ) ;
//if (!upload_complete_flag) {
// this.dispatchEvent('uploadprogress');
//}
}
} ;
return ( extensions . XMLHttpRequest = XMLHttpRequest ) ;
} ) ;
// Included from: src/javascript/runtime/html4/Runtime.js
/ * *
* Runtime . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/*global File:true */
/ * *
Defines constructor for HTML4 runtime .
@ class moxie / runtime / html4 / Runtime
@ private
* /
define ( "moxie/runtime/html4/Runtime" , [
"moxie/core/utils/Basic" ,
"moxie/core/Exceptions" ,
"moxie/runtime/Runtime" ,
"moxie/core/utils/Env"
] , function ( Basic , x , Runtime , Env ) {
var type = 'html4' , extensions = { } ;
function Html4Runtime ( options ) {
var I = this
, Test = Runtime . capTest
, True = Runtime . capTrue
;
Runtime . call ( this , options , type , {
access _binary : Test ( window . FileReader || window . File && File . getAsDataURL ) ,
access _image _binary : false ,
display _media : Test ( extensions . Image && ( Env . can ( 'create_canvas' ) || Env . can ( 'use_data_uri_over32kb' ) ) ) ,
do _cors : false ,
drag _and _drop : false ,
filter _by _extension : Test ( function ( ) { // if you know how to feature-detect this, please suggest
return ( Env . browser === 'Chrome' && Env . version >= 28 ) || ( Env . browser === 'IE' && Env . version >= 10 ) ;
} ( ) ) ,
resize _image : function ( ) {
return extensions . Image && I . can ( 'access_binary' ) && Env . can ( 'create_canvas' ) ;
} ,
report _upload _progress : false ,
return _response _headers : false ,
return _response _type : function ( responseType ) {
if ( responseType === 'json' && ! ! window . JSON ) {
return true ;
}
return ! ! ~ Basic . inArray ( responseType , [ 'text' , 'document' , '' ] ) ;
} ,
return _status _code : function ( code ) {
return ! Basic . arrayDiff ( code , [ 200 , 404 ] ) ;
} ,
select _file : function ( ) {
return Env . can ( 'use_fileinput' ) ;
} ,
select _multiple : false ,
send _binary _string : false ,
send _custom _headers : false ,
send _multipart : true ,
slice _blob : false ,
stream _upload : function ( ) {
return I . can ( 'select_file' ) ;
} ,
summon _file _dialog : Test ( function ( ) { // yeah... some dirty sniffing here...
return ( Env . browser === 'Firefox' && Env . version >= 4 ) ||
( Env . browser === 'Opera' && Env . version >= 12 ) ||
! ! ~ Basic . inArray ( Env . browser , [ 'Chrome' , 'Safari' ] ) ;
} ( ) ) ,
upload _filesize : True ,
use _http _method : function ( methods ) {
return ! Basic . arrayDiff ( methods , [ 'GET' , 'POST' ] ) ;
}
} ) ;
Basic . extend ( this , {
init : function ( ) {
this . trigger ( "Init" ) ;
} ,
destroy : ( function ( destroy ) { // extend default destroy method
return function ( ) {
destroy . call ( I ) ;
destroy = I = null ;
} ;
} ( this . destroy ) )
} ) ;
Basic . extend ( this . getShim ( ) , extensions ) ;
}
Runtime . addConstructor ( type , Html4Runtime ) ;
return extensions ;
} ) ;
// Included from: src/javascript/core/utils/Events.js
/ * *
* Events . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
define ( 'moxie/core/utils/Events' , [
'moxie/core/utils/Basic'
] , function ( Basic ) {
var eventhash = { } , uid = 'moxie_' + Basic . guid ( ) ;
// IE W3C like event funcs
function preventDefault ( ) {
this . returnValue = false ;
}
function stopPropagation ( ) {
this . cancelBubble = true ;
}
/ * *
Adds an event handler to the specified object and store reference to the handler
in objects internal Plupload registry ( @ see removeEvent ) .
@ method addEvent
@ for Utils
@ static
@ param { Object } obj DOM element like object to add handler to .
@ param { String } name Name to add event listener to .
@ param { Function } callback Function to call when event occurs .
@ param { String } [ key ] that might be used to add specifity to the event record .
* /
var addEvent = function ( obj , name , callback , key ) {
var func , events ;
name = name . toLowerCase ( ) ;
// Add event listener
if ( obj . addEventListener ) {
func = callback ;
obj . addEventListener ( name , func , false ) ;
} else if ( obj . attachEvent ) {
func = function ( ) {
var evt = window . event ;
if ( ! evt . target ) {
evt . target = evt . srcElement ;
}
evt . preventDefault = preventDefault ;
evt . stopPropagation = stopPropagation ;
callback ( evt ) ;
} ;
obj . attachEvent ( 'on' + name , func ) ;
}
// Log event handler to objects internal mOxie registry
if ( ! obj [ uid ] ) {
obj [ uid ] = Basic . guid ( ) ;
}
if ( ! eventhash . hasOwnProperty ( obj [ uid ] ) ) {
eventhash [ obj [ uid ] ] = { } ;
}
events = eventhash [ obj [ uid ] ] ;
if ( ! events . hasOwnProperty ( name ) ) {
events [ name ] = [ ] ;
}
events [ name ] . push ( {
func : func ,
orig : callback , // store original callback for IE
key : key
} ) ;
} ;
/ * *
Remove event handler from the specified object . If third argument ( callback )
is not specified remove all events with the specified name .
@ method removeEvent
@ static
@ param { Object } obj DOM element to remove event listener ( s ) from .
@ param { String } name Name of event listener to remove .
@ param { Function | String } [ callback ] might be a callback or unique key to match .
* /
var removeEvent = function ( obj , name , callback ) {
var type , undef ;
name = name . toLowerCase ( ) ;
if ( obj [ uid ] && eventhash [ obj [ uid ] ] && eventhash [ obj [ uid ] ] [ name ] ) {
type = eventhash [ obj [ uid ] ] [ name ] ;
} else {
return ;
}
for ( var i = type . length - 1 ; i >= 0 ; i -- ) {
// undefined or not, key should match
if ( type [ i ] . orig === callback || type [ i ] . key === callback ) {
if ( obj . removeEventListener ) {
obj . removeEventListener ( name , type [ i ] . func , false ) ;
} else if ( obj . detachEvent ) {
obj . detachEvent ( 'on' + name , type [ i ] . func ) ;
}
type [ i ] . orig = null ;
type [ i ] . func = null ;
type . splice ( i , 1 ) ;
// If callback was passed we are done here, otherwise proceed
if ( callback !== undef ) {
break ;
}
}
}
// If event array got empty, remove it
if ( ! type . length ) {
delete eventhash [ obj [ uid ] ] [ name ] ;
}
// If mOxie registry has become empty, remove it
if ( Basic . isEmptyObj ( eventhash [ obj [ uid ] ] ) ) {
delete eventhash [ obj [ uid ] ] ;
// IE doesn't let you remove DOM object property with - delete
try {
delete obj [ uid ] ;
} catch ( e ) {
obj [ uid ] = undef ;
}
}
} ;
/ * *
Remove all kind of events from the specified object
@ method removeAllEvents
@ static
@ param { Object } obj DOM element to remove event listeners from .
@ param { String } [ key ] unique key to match , when removing events .
* /
var removeAllEvents = function ( obj , key ) {
if ( ! obj || ! obj [ uid ] ) {
return ;
}
Basic . each ( eventhash [ obj [ uid ] ] , function ( events , name ) {
removeEvent ( obj , name , key ) ;
} ) ;
} ;
return {
addEvent : addEvent ,
removeEvent : removeEvent ,
removeAllEvents : removeAllEvents
} ;
} ) ;
// Included from: src/javascript/runtime/html4/file/FileInput.js
/ * *
* FileInput . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / html4 / file / FileInput
@ private
* /
define ( "moxie/runtime/html4/file/FileInput" , [
"moxie/runtime/html4/Runtime" ,
"moxie/core/utils/Basic" ,
"moxie/core/utils/Dom" ,
"moxie/core/utils/Events" ,
"moxie/core/utils/Mime" ,
"moxie/core/utils/Env"
] , function ( extensions , Basic , Dom , Events , Mime , Env ) {
function FileInput ( ) {
var _uid , _files = [ ] , _mimes = [ ] , _options ;
function addInput ( ) {
var comp = this , I = comp . getRuntime ( ) , shimContainer , browseButton , currForm , form , input , uid ;
uid = Basic . guid ( 'uid_' ) ;
shimContainer = I . getShimContainer ( ) ; // we get new ref everytime to avoid memory leaks in IE
if ( _uid ) { // move previous form out of the view
currForm = Dom . get ( _uid + '_form' ) ;
if ( currForm ) {
Basic . extend ( currForm . style , { top : '100%' } ) ;
}
}
// build form in DOM, since innerHTML version not able to submit file for some reason
form = document . createElement ( 'form' ) ;
form . setAttribute ( 'id' , uid + '_form' ) ;
form . setAttribute ( 'method' , 'post' ) ;
form . setAttribute ( 'enctype' , 'multipart/form-data' ) ;
form . setAttribute ( 'encoding' , 'multipart/form-data' ) ;
Basic . extend ( form . style , {
overflow : 'hidden' ,
position : 'absolute' ,
top : 0 ,
left : 0 ,
width : '100%' ,
height : '100%'
} ) ;
input = document . createElement ( 'input' ) ;
input . setAttribute ( 'id' , uid ) ;
input . setAttribute ( 'type' , 'file' ) ;
input . setAttribute ( 'name' , _options . name || 'Filedata' ) ;
input . setAttribute ( 'accept' , _mimes . join ( ',' ) ) ;
Basic . extend ( input . style , {
fontSize : '999px' ,
opacity : 0
} ) ;
form . appendChild ( input ) ;
shimContainer . appendChild ( form ) ;
// prepare file input to be placed underneath the browse_button element
Basic . extend ( input . style , {
position : 'absolute' ,
top : 0 ,
left : 0 ,
width : '100%' ,
height : '100%'
} ) ;
if ( Env . browser === 'IE' && Env . version < 10 ) {
Basic . extend ( input . style , {
filter : "progid:DXImageTransform.Microsoft.Alpha(opacity=0)"
} ) ;
}
input . onchange = function ( ) { // there should be only one handler for this
var file ;
if ( ! this . value ) {
return ;
}
if ( this . files ) {
file = this . files [ 0 ] ;
} else {
file = {
name : this . value
} ;
}
_files = [ file ] ;
this . onchange = function ( ) { } ; // clear event handler
addInput . call ( comp ) ;
// after file is initialized as o.File, we need to update form and input ids
comp . bind ( 'change' , function onChange ( ) {
var input = Dom . get ( uid ) , form = Dom . get ( uid + '_form' ) , file ;
comp . unbind ( 'change' , onChange ) ;
if ( comp . files . length && input && form ) {
file = comp . files [ 0 ] ;
input . setAttribute ( 'id' , file . uid ) ;
form . setAttribute ( 'id' , file . uid + '_form' ) ;
// set upload target
form . setAttribute ( 'target' , file . uid + '_iframe' ) ;
}
input = form = null ;
} , 998 ) ;
input = form = null ;
comp . trigger ( 'change' ) ;
} ;
// route click event to the input
if ( I . can ( 'summon_file_dialog' ) ) {
browseButton = Dom . get ( _options . browse _button ) ;
Events . removeEvent ( browseButton , 'click' , comp . uid ) ;
Events . addEvent ( browseButton , 'click' , function ( e ) {
if ( input && ! input . disabled ) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
input . click ( ) ;
}
e . preventDefault ( ) ;
} , comp . uid ) ;
}
_uid = uid ;
shimContainer = currForm = browseButton = null ;
}
Basic . extend ( this , {
init : function ( options ) {
var comp = this , I = comp . getRuntime ( ) , shimContainer ;
// figure out accept string
_options = options ;
_mimes = options . accept . mimes || Mime . extList2mimes ( options . accept , I . can ( 'filter_by_extension' ) ) ;
shimContainer = I . getShimContainer ( ) ;
( function ( ) {
var browseButton , zIndex , top ;
browseButton = Dom . get ( options . browse _button ) ;
// Route click event to the input[type=file] element for browsers that support such behavior
if ( I . can ( 'summon_file_dialog' ) ) {
if ( Dom . getStyle ( browseButton , 'position' ) === 'static' ) {
browseButton . style . position = 'relative' ;
}
zIndex = parseInt ( Dom . getStyle ( browseButton , 'z-index' ) , 10 ) || 1 ;
browseButton . style . zIndex = zIndex ;
shimContainer . style . zIndex = zIndex - 1 ;
}
/ * S i n c e w e h a v e t o p l a c e i n p u t [ t y p e = f i l e ] o n t o p o f t h e b r o w s e _ b u t t o n f o r s o m e b r o w s e r s ,
browse _button loses interactivity , so we restore it here * /
top = I . can ( 'summon_file_dialog' ) ? browseButton : shimContainer ;
Events . addEvent ( top , 'mouseover' , function ( ) {
comp . trigger ( 'mouseenter' ) ;
} , comp . uid ) ;
Events . addEvent ( top , 'mouseout' , function ( ) {
comp . trigger ( 'mouseleave' ) ;
} , comp . uid ) ;
Events . addEvent ( top , 'mousedown' , function ( ) {
comp . trigger ( 'mousedown' ) ;
} , comp . uid ) ;
Events . addEvent ( Dom . get ( options . container ) , 'mouseup' , function ( ) {
comp . trigger ( 'mouseup' ) ;
} , comp . uid ) ;
browseButton = null ;
} ( ) ) ;
addInput . call ( this ) ;
shimContainer = null ;
// trigger ready event asynchronously
comp . trigger ( {
type : 'ready' ,
async : true
} ) ;
} ,
getFiles : function ( ) {
return _files ;
} ,
disable : function ( state ) {
var input ;
if ( ( input = Dom . get ( _uid ) ) ) {
input . disabled = ! ! state ;
}
} ,
destroy : function ( ) {
var I = this . getRuntime ( )
, shim = I . getShim ( )
, shimContainer = I . getShimContainer ( )
;
Events . removeAllEvents ( shimContainer , this . uid ) ;
Events . removeAllEvents ( _options && Dom . get ( _options . container ) , this . uid ) ;
Events . removeAllEvents ( _options && Dom . get ( _options . browse _button ) , this . uid ) ;
if ( shimContainer ) {
shimContainer . innerHTML = '' ;
}
shim . removeInstance ( this . uid ) ;
_uid = _files = _mimes = _options = shimContainer = shim = null ;
}
} ) ;
}
return ( extensions . FileInput = FileInput ) ;
} ) ;
// Included from: src/javascript/runtime/html5/Runtime.js
/ * *
* Runtime . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/*global File:true */
/ * *
Defines constructor for HTML5 runtime .
@ class moxie / runtime / html5 / Runtime
@ private
* /
define ( "moxie/runtime/html5/Runtime" , [
"moxie/core/utils/Basic" ,
"moxie/core/Exceptions" ,
"moxie/runtime/Runtime" ,
"moxie/core/utils/Env"
] , function ( Basic , x , Runtime , Env ) {
var type = "html5" , extensions = { } ;
function Html5Runtime ( options ) {
var I = this
, Test = Runtime . capTest
, True = Runtime . capTrue
;
var caps = Basic . extend ( {
access _binary : Test ( window . FileReader || window . File && window . File . getAsDataURL ) ,
access _image _binary : function ( ) {
return I . can ( 'access_binary' ) && ! ! extensions . Image ;
} ,
display _media : Test ( Env . can ( 'create_canvas' ) || Env . can ( 'use_data_uri_over32kb' ) ) ,
do _cors : Test ( window . XMLHttpRequest && 'withCredentials' in new XMLHttpRequest ( ) ) ,
drag _and _drop : Test ( function ( ) {
// this comes directly from Modernizr: http://www.modernizr.com/
var div = document . createElement ( 'div' ) ;
// IE has support for drag and drop since version 5, but doesn't support dropping files from desktop
return ( ( 'draggable' in div ) || ( 'ondragstart' in div && 'ondrop' in div ) ) && ( Env . browser !== 'IE' || Env . version > 9 ) ;
} ( ) ) ,
filter _by _extension : Test ( function ( ) { // if you know how to feature-detect this, please suggest
return ( Env . browser === 'Chrome' && Env . version >= 28 ) || ( Env . browser === 'IE' && Env . version >= 10 ) ;
} ( ) ) ,
return _response _headers : True ,
return _response _type : function ( responseType ) {
if ( responseType === 'json' && ! ! window . JSON ) { // we can fake this one even if it's not supported
return true ;
}
return Env . can ( 'return_response_type' , responseType ) ;
} ,
return _status _code : True ,
report _upload _progress : Test ( window . XMLHttpRequest && new XMLHttpRequest ( ) . upload ) ,
resize _image : function ( ) {
return I . can ( 'access_binary' ) && Env . can ( 'create_canvas' ) ;
} ,
select _file : function ( ) {
return Env . can ( 'use_fileinput' ) && window . File ;
} ,
select _folder : function ( ) {
return I . can ( 'select_file' ) && Env . browser === 'Chrome' && Env . version >= 21 ;
} ,
select _multiple : function ( ) {
// it is buggy on Safari Windows and iOS
return I . can ( 'select_file' ) &&
! ( Env . browser === 'Safari' && Env . os === 'Windows' ) &&
! ( Env . os === 'iOS' && Env . verComp ( Env . osVersion , "7.0.4" , '<' ) ) ;
} ,
send _binary _string : Test ( window . XMLHttpRequest && ( new XMLHttpRequest ( ) . sendAsBinary || ( window . Uint8Array && window . ArrayBuffer ) ) ) ,
send _custom _headers : Test ( window . XMLHttpRequest ) ,
send _multipart : function ( ) {
return ! ! ( window . XMLHttpRequest && new XMLHttpRequest ( ) . upload && window . FormData ) || I . can ( 'send_binary_string' ) ;
} ,
slice _blob : Test ( window . File && ( File . prototype . mozSlice || File . prototype . webkitSlice || File . prototype . slice ) ) ,
stream _upload : function ( ) {
return I . can ( 'slice_blob' ) && I . can ( 'send_multipart' ) ;
} ,
summon _file _dialog : Test ( function ( ) { // yeah... some dirty sniffing here...
return ( Env . browser === 'Firefox' && Env . version >= 4 ) ||
( Env . browser === 'Opera' && Env . version >= 12 ) ||
( Env . browser === 'IE' && Env . version >= 10 ) ||
! ! ~ Basic . inArray ( Env . browser , [ 'Chrome' , 'Safari' ] ) ;
} ( ) ) ,
upload _filesize : True
} ,
arguments [ 2 ]
) ;
Runtime . call ( this , options , ( arguments [ 1 ] || type ) , caps ) ;
Basic . extend ( this , {
init : function ( ) {
this . trigger ( "Init" ) ;
} ,
destroy : ( function ( destroy ) { // extend default destroy method
return function ( ) {
destroy . call ( I ) ;
destroy = I = null ;
} ;
} ( this . destroy ) )
} ) ;
Basic . extend ( this . getShim ( ) , extensions ) ;
}
Runtime . addConstructor ( type , Html5Runtime ) ;
return extensions ;
} ) ;
// Included from: src/javascript/runtime/html5/file/FileReader.js
/ * *
* FileReader . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / html5 / file / FileReader
@ private
* /
define ( "moxie/runtime/html5/file/FileReader" , [
"moxie/runtime/html5/Runtime" ,
"moxie/core/utils/Encode" ,
"moxie/core/utils/Basic"
] , function ( extensions , Encode , Basic ) {
function FileReader ( ) {
var _fr , _convertToBinary = false ;
Basic . extend ( this , {
read : function ( op , blob ) {
var target = this ;
_fr = new window . FileReader ( ) ;
_fr . addEventListener ( 'progress' , function ( e ) {
target . trigger ( e ) ;
} ) ;
_fr . addEventListener ( 'load' , function ( e ) {
target . trigger ( e ) ;
} ) ;
_fr . addEventListener ( 'error' , function ( e ) {
target . trigger ( e , _fr . error ) ;
} ) ;
_fr . addEventListener ( 'loadend' , function ( ) {
_fr = null ;
} ) ;
if ( Basic . typeOf ( _fr [ op ] ) === 'function' ) {
_convertToBinary = false ;
_fr [ op ] ( blob . getSource ( ) ) ;
} else if ( op === 'readAsBinaryString' ) { // readAsBinaryString is depricated in general and never existed in IE10+
_convertToBinary = true ;
_fr . readAsDataURL ( blob . getSource ( ) ) ;
}
} ,
getResult : function ( ) {
return _fr && _fr . result ? ( _convertToBinary ? _toBinary ( _fr . result ) : _fr . result ) : null ;
} ,
abort : function ( ) {
if ( _fr ) {
_fr . abort ( ) ;
}
} ,
destroy : function ( ) {
_fr = null ;
}
} ) ;
function _toBinary ( str ) {
return Encode . atob ( str . substring ( str . indexOf ( 'base64,' ) + 7 ) ) ;
}
}
return ( extensions . FileReader = FileReader ) ;
} ) ;
// Included from: src/javascript/runtime/html4/file/FileReader.js
/ * *
* FileReader . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / html4 / file / FileReader
@ private
* /
define ( "moxie/runtime/html4/file/FileReader" , [
"moxie/runtime/html4/Runtime" ,
"moxie/runtime/html5/file/FileReader"
] , function ( extensions , FileReader ) {
return ( extensions . FileReader = FileReader ) ;
} ) ;
// Included from: src/javascript/runtime/html4/xhr/XMLHttpRequest.js
/ * *
* XMLHttpRequest . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / html4 / xhr / XMLHttpRequest
@ private
* /
define ( "moxie/runtime/html4/xhr/XMLHttpRequest" , [
"moxie/runtime/html4/Runtime" ,
"moxie/core/utils/Basic" ,
"moxie/core/utils/Dom" ,
"moxie/core/utils/Url" ,
"moxie/core/Exceptions" ,
"moxie/core/utils/Events" ,
"moxie/file/Blob" ,
"moxie/xhr/FormData"
] , function ( extensions , Basic , Dom , Url , x , Events , Blob , FormData ) {
function XMLHttpRequest ( ) {
var _status , _response , _iframe ;
function cleanup ( cb ) {
var target = this , uid , form , inputs , i , hasFile = false ;
if ( ! _iframe ) {
return ;
}
uid = _iframe . id . replace ( /_iframe$/ , '' ) ;
form = Dom . get ( uid + '_form' ) ;
if ( form ) {
inputs = form . getElementsByTagName ( 'input' ) ;
i = inputs . length ;
while ( i -- ) {
switch ( inputs [ i ] . getAttribute ( 'type' ) ) {
case 'hidden' :
inputs [ i ] . parentNode . removeChild ( inputs [ i ] ) ;
break ;
case 'file' :
hasFile = true ; // flag the case for later
break ;
}
}
inputs = [ ] ;
if ( ! hasFile ) { // we need to keep the form for sake of possible retries
form . parentNode . removeChild ( form ) ;
}
form = null ;
}
// without timeout, request is marked as canceled (in console)
setTimeout ( function ( ) {
Events . removeEvent ( _iframe , 'load' , target . uid ) ;
if ( _iframe . parentNode ) { // #382
_iframe . parentNode . removeChild ( _iframe ) ;
}
// check if shim container has any other children, if - not, remove it as well
var shimContainer = target . getRuntime ( ) . getShimContainer ( ) ;
if ( ! shimContainer . children . length ) {
shimContainer . parentNode . removeChild ( shimContainer ) ;
}
shimContainer = _iframe = null ;
cb ( ) ;
} , 1 ) ;
}
Basic . extend ( this , {
send : function ( meta , data ) {
var target = this , I = target . getRuntime ( ) , uid , form , input , blob ;
_status = _response = null ;
function createIframe ( ) {
var container = I . getShimContainer ( ) || document . body
, temp = document . createElement ( 'div' )
;
// IE 6 won't be able to set the name using setAttribute or iframe.name
temp . innerHTML = '<iframe id="' + uid + '_iframe" name="' + uid + '_iframe" src="javascript:""" style="display:none"></iframe>' ;
_iframe = temp . firstChild ;
container . appendChild ( _iframe ) ;
/ * _ i f r a m e . o n r e a d y s t a t e c h a n g e = f u n c t i o n ( ) {
console . info ( _iframe . readyState ) ;
} ; * /
Events . addEvent ( _iframe , 'load' , function ( ) { // _iframe.onload doesn't work in IE lte 8
var el ;
try {
el = _iframe . contentWindow . document || _iframe . contentDocument || window . frames [ _iframe . id ] . document ;
// try to detect some standard error pages
if ( /^4(0[0-9]|1[0-7]|2[2346])\s/ . test ( el . title ) ) { // test if title starts with 4xx HTTP error
_status = el . title . replace ( /^(\d+).*$/ , '$1' ) ;
} else {
_status = 200 ;
// get result
_response = Basic . trim ( el . body . innerHTML ) ;
// we need to fire these at least once
target . trigger ( {
type : 'progress' ,
loaded : _response . length ,
total : _response . length
} ) ;
if ( blob ) { // if we were uploading a file
target . trigger ( {
type : 'uploadprogress' ,
loaded : blob . size || 1025 ,
total : blob . size || 1025
} ) ;
}
}
} catch ( ex ) {
if ( Url . hasSameOrigin ( meta . url ) ) {
// if response is sent with error code, iframe in IE gets redirected to res://ieframe.dll/http_x.htm
// which obviously results to cross domain error (wtf?)
_status = 404 ;
} else {
cleanup . call ( target , function ( ) {
target . trigger ( 'error' ) ;
} ) ;
return ;
}
}
cleanup . call ( target , function ( ) {
target . trigger ( 'load' ) ;
} ) ;
} , target . uid ) ;
} // end createIframe
// prepare data to be sent and convert if required
if ( data instanceof FormData && data . hasBlob ( ) ) {
blob = data . getBlob ( ) ;
uid = blob . uid ;
input = Dom . get ( uid ) ;
form = Dom . get ( uid + '_form' ) ;
if ( ! form ) {
throw new x . DOMException ( x . DOMException . NOT _FOUND _ERR ) ;
}
} else {
uid = Basic . guid ( 'uid_' ) ;
form = document . createElement ( 'form' ) ;
form . setAttribute ( 'id' , uid + '_form' ) ;
form . setAttribute ( 'method' , meta . method ) ;
form . setAttribute ( 'enctype' , 'multipart/form-data' ) ;
form . setAttribute ( 'encoding' , 'multipart/form-data' ) ;
form . setAttribute ( 'target' , uid + '_iframe' ) ;
I . getShimContainer ( ) . appendChild ( form ) ;
}
if ( data instanceof FormData ) {
data . each ( function ( value , name ) {
if ( value instanceof Blob ) {
if ( input ) {
input . setAttribute ( 'name' , name ) ;
}
} else {
var hidden = document . createElement ( 'input' ) ;
Basic . extend ( hidden , {
type : 'hidden' ,
name : name ,
value : value
} ) ;
// make sure that input[type="file"], if it's there, comes last
if ( input ) {
form . insertBefore ( hidden , input ) ;
} else {
form . appendChild ( hidden ) ;
}
}
} ) ;
}
// set destination url
form . setAttribute ( "action" , meta . url ) ;
createIframe ( ) ;
form . submit ( ) ;
target . trigger ( 'loadstart' ) ;
} ,
getStatus : function ( ) {
return _status ;
} ,
getResponse : function ( responseType ) {
if ( 'json' === responseType ) {
// strip off <pre>..</pre> tags that might be enclosing the response
if ( Basic . typeOf ( _response ) === 'string' && ! ! window . JSON ) {
try {
return JSON . parse ( _response . replace ( /^\s*<pre[^>]*>/ , '' ) . replace ( /<\/pre>\s*$/ , '' ) ) ;
} catch ( ex ) {
return null ;
}
}
} else if ( 'document' === responseType ) {
}
return _response ;
} ,
abort : function ( ) {
var target = this ;
if ( _iframe && _iframe . contentWindow ) {
if ( _iframe . contentWindow . stop ) { // FireFox/Safari/Chrome
_iframe . contentWindow . stop ( ) ;
} else if ( _iframe . contentWindow . document . execCommand ) { // IE
_iframe . contentWindow . document . execCommand ( 'Stop' ) ;
} else {
_iframe . src = "about:blank" ;
}
}
cleanup . call ( this , function ( ) {
// target.dispatchEvent('readystatechange');
target . dispatchEvent ( 'abort' ) ;
} ) ;
}
} ) ;
}
return ( extensions . XMLHttpRequest = XMLHttpRequest ) ;
} ) ;
// Included from: src/javascript/runtime/silverlight/Runtime.js
/ * *
* RunTime . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/*global ActiveXObject:true */
/ * *
Defines constructor for Silverlight runtime .
@ class moxie / runtime / silverlight / Runtime
@ private
* /
define ( "moxie/runtime/silverlight/Runtime" , [
"moxie/core/utils/Basic" ,
"moxie/core/utils/Env" ,
"moxie/core/utils/Dom" ,
"moxie/core/Exceptions" ,
"moxie/runtime/Runtime"
] , function ( Basic , Env , Dom , x , Runtime ) {
var type = "silverlight" , extensions = { } ;
function isInstalled ( version ) {
var isVersionSupported = false , control = null , actualVer ,
actualVerArray , reqVerArray , requiredVersionPart , actualVersionPart , index = 0 ;
try {
try {
control = new ActiveXObject ( 'AgControl.AgControl' ) ;
if ( control . IsVersionSupported ( version ) ) {
isVersionSupported = true ;
}
control = null ;
} catch ( e ) {
var plugin = navigator . plugins [ "Silverlight Plug-In" ] ;
if ( plugin ) {
actualVer = plugin . description ;
if ( actualVer === "1.0.30226.2" ) {
actualVer = "2.0.30226.2" ;
}
actualVerArray = actualVer . split ( "." ) ;
while ( actualVerArray . length > 3 ) {
actualVerArray . pop ( ) ;
}
while ( actualVerArray . length < 4 ) {
actualVerArray . push ( 0 ) ;
}
reqVerArray = version . split ( "." ) ;
while ( reqVerArray . length > 4 ) {
reqVerArray . pop ( ) ;
}
do {
requiredVersionPart = parseInt ( reqVerArray [ index ] , 10 ) ;
actualVersionPart = parseInt ( actualVerArray [ index ] , 10 ) ;
index ++ ;
} while ( index < reqVerArray . length && requiredVersionPart === actualVersionPart ) ;
if ( requiredVersionPart <= actualVersionPart && ! isNaN ( requiredVersionPart ) ) {
isVersionSupported = true ;
}
}
}
} catch ( e2 ) {
isVersionSupported = false ;
}
return isVersionSupported ;
}
/ * *
Constructor for the Silverlight Runtime
@ class SilverlightRuntime
@ extends Runtime
* /
function SilverlightRuntime ( options ) {
var I = this , initTimer ;
options = Basic . extend ( { xap _url : Env . xap _url } , options ) ;
Runtime . call ( this , options , type , {
access _binary : Runtime . capTrue ,
access _image _binary : Runtime . capTrue ,
display _media : Runtime . capTrue ,
do _cors : Runtime . capTrue ,
drag _and _drop : false ,
report _upload _progress : Runtime . capTrue ,
resize _image : Runtime . capTrue ,
return _response _headers : function ( value ) {
return value && I . mode === 'client' ;
} ,
return _response _type : function ( responseType ) {
if ( responseType !== 'json' ) {
return true ;
} else {
return ! ! window . JSON ;
}
} ,
return _status _code : function ( code ) {
return I . mode === 'client' || ! Basic . arrayDiff ( code , [ 200 , 404 ] ) ;
} ,
select _file : Runtime . capTrue ,
select _multiple : Runtime . capTrue ,
send _binary _string : Runtime . capTrue ,
send _browser _cookies : function ( value ) {
return value && I . mode === 'browser' ;
} ,
send _custom _headers : function ( value ) {
return value && I . mode === 'client' ;
} ,
send _multipart : Runtime . capTrue ,
slice _blob : Runtime . capTrue ,
stream _upload : true ,
summon _file _dialog : false ,
upload _filesize : Runtime . capTrue ,
use _http _method : function ( methods ) {
return I . mode === 'client' || ! Basic . arrayDiff ( methods , [ 'GET' , 'POST' ] ) ;
}
} , {
// capabilities that require specific mode
return _response _headers : function ( value ) {
return value ? 'client' : 'browser' ;
} ,
return _status _code : function ( code ) {
return Basic . arrayDiff ( code , [ 200 , 404 ] ) ? 'client' : [ 'client' , 'browser' ] ;
} ,
send _browser _cookies : function ( value ) {
return value ? 'browser' : 'client' ;
} ,
send _custom _headers : function ( value ) {
return value ? 'client' : 'browser' ;
} ,
use _http _method : function ( methods ) {
return Basic . arrayDiff ( methods , [ 'GET' , 'POST' ] ) ? 'client' : [ 'client' , 'browser' ] ;
}
} ) ;
// minimal requirement
if ( ! isInstalled ( '2.0.31005.0' ) || Env . browser === 'Opera' ) {
this . mode = false ;
}
Basic . extend ( this , {
getShim : function ( ) {
return Dom . get ( this . uid ) . content . Moxie ;
} ,
shimExec : function ( component , action ) {
var args = [ ] . slice . call ( arguments , 2 ) ;
return I . getShim ( ) . exec ( this . uid , component , action , args ) ;
} ,
init : function ( ) {
var container ;
container = this . getShimContainer ( ) ;
container . innerHTML = '<object id="' + this . uid + '" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;">' +
'<param name="source" value="' + options . xap _url + '"/>' +
'<param name="background" value="Transparent"/>' +
'<param name="windowless" value="true"/>' +
'<param name="enablehtmlaccess" value="true"/>' +
'<param name="initParams" value="uid=' + this . uid + ',target=' + Env . global _event _dispatcher + '"/>' +
'</object>' ;
// Init is dispatched by the shim
initTimer = setTimeout ( function ( ) {
if ( I && ! I . initialized ) { // runtime might be already destroyed by this moment
I . trigger ( "Error" , new x . RuntimeError ( x . RuntimeError . NOT _INIT _ERR ) ) ;
}
} , Env . OS !== 'Windows' ? 10000 : 5000 ) ; // give it more time to initialize in non Windows OS (like Mac)
} ,
destroy : ( function ( destroy ) { // extend default destroy method
return function ( ) {
destroy . call ( I ) ;
clearTimeout ( initTimer ) ; // initialization check might be still onwait
options = initTimer = destroy = I = null ;
} ;
} ( this . destroy ) )
} , extensions ) ;
}
Runtime . addConstructor ( type , SilverlightRuntime ) ;
return extensions ;
} ) ;
// Included from: src/javascript/runtime/silverlight/file/Blob.js
/ * *
* Blob . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / silverlight / file / Blob
@ private
* /
define ( "moxie/runtime/silverlight/file/Blob" , [
"moxie/runtime/silverlight/Runtime" ,
"moxie/core/utils/Basic" ,
"moxie/runtime/flash/file/Blob"
] , function ( extensions , Basic , Blob ) {
return ( extensions . Blob = Basic . extend ( { } , Blob ) ) ;
} ) ;
// Included from: src/javascript/runtime/silverlight/file/FileInput.js
/ * *
* FileInput . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / silverlight / file / FileInput
@ private
* /
define ( "moxie/runtime/silverlight/file/FileInput" , [
"moxie/runtime/silverlight/Runtime"
] , function ( extensions ) {
var FileInput = {
init : function ( options ) {
function toFilters ( accept ) {
var filter = '' ;
for ( var i = 0 ; i < accept . length ; i ++ ) {
filter += ( filter !== '' ? '|' : '' ) + accept [ i ] . title + " | *." + accept [ i ] . extensions . replace ( /,/g , ';*.' ) ;
}
return filter ;
}
this . getRuntime ( ) . shimExec . call ( this , 'FileInput' , 'init' , toFilters ( options . accept ) , options . name , options . multiple ) ;
this . trigger ( 'ready' ) ;
}
} ;
return ( extensions . FileInput = FileInput ) ;
} ) ;
// Included from: src/javascript/runtime/silverlight/file/FileReader.js
/ * *
* FileReader . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / silverlight / file / FileReader
@ private
* /
define ( "moxie/runtime/silverlight/file/FileReader" , [
"moxie/runtime/silverlight/Runtime" ,
"moxie/core/utils/Basic" ,
"moxie/runtime/flash/file/FileReader"
] , function ( extensions , Basic , FileReader ) {
return ( extensions . FileReader = Basic . extend ( { } , FileReader ) ) ;
} ) ;
// Included from: src/javascript/runtime/silverlight/file/FileReaderSync.js
/ * *
* FileReaderSync . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / silverlight / file / FileReaderSync
@ private
* /
define ( "moxie/runtime/silverlight/file/FileReaderSync" , [
"moxie/runtime/silverlight/Runtime" ,
"moxie/core/utils/Basic" ,
"moxie/runtime/flash/file/FileReaderSync"
] , function ( extensions , Basic , FileReaderSync ) {
return ( extensions . FileReaderSync = Basic . extend ( { } , FileReaderSync ) ) ;
} ) ;
// Included from: src/javascript/runtime/silverlight/xhr/XMLHttpRequest.js
/ * *
* XMLHttpRequest . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/ * *
@ class moxie / runtime / silverlight / xhr / XMLHttpRequest
@ private
* /
define ( "moxie/runtime/silverlight/xhr/XMLHttpRequest" , [
"moxie/runtime/silverlight/Runtime" ,
"moxie/core/utils/Basic" ,
"moxie/runtime/flash/xhr/XMLHttpRequest"
] , function ( extensions , Basic , XMLHttpRequest ) {
return ( extensions . XMLHttpRequest = Basic . extend ( { } , XMLHttpRequest ) ) ;
} ) ;
expose ( [ "moxie/core/utils/Basic" , "moxie/core/I18n" , "moxie/core/utils/Mime" , "moxie/core/utils/Env" , "moxie/core/utils/Dom" , "moxie/core/Exceptions" , "moxie/core/EventTarget" , "moxie/core/utils/Encode" , "moxie/runtime/Runtime" , "moxie/runtime/RuntimeClient" , "moxie/file/Blob" , "moxie/file/File" , "moxie/file/FileInput" , "moxie/runtime/RuntimeTarget" , "moxie/file/FileReader" , "moxie/core/utils/Url" , "moxie/file/FileReaderSync" , "moxie/xhr/FormData" , "moxie/xhr/XMLHttpRequest" , "moxie/runtime/Transporter" , "moxie/core/utils/Events" ] ) ;
} ) ( this ) ; / * *
* o . js
*
* Copyright 2013 , Moxiecode Systems AB
* Released under GPL License .
*
* License : http : //www.plupload.com/license
* Contributing : http : //www.plupload.com/contributing
* /
/*global moxie:true */
/ * *
Globally exposed namespace with the most frequently used public classes and handy methods .
@ class o
@ static
@ private
* /
( function ( exports ) {
"use strict" ;
var o = { } , inArray = exports . moxie . core . utils . Basic . inArray ;
// directly add some public classes
// (we do it dynamically here, since for custom builds we cannot know beforehand what modules were included)
( function addAlias ( ns ) {
var name , itemType ;
for ( name in ns ) {
itemType = typeof ( ns [ name ] ) ;
if ( itemType === 'object' && ! ~ inArray ( name , [ 'Exceptions' , 'Env' , 'Mime' ] ) ) {
addAlias ( ns [ name ] ) ;
} else if ( itemType === 'function' ) {
o [ name ] = ns [ name ] ;
}
}
} ) ( exports . moxie ) ;
// add some manually
o . Env = exports . moxie . core . utils . Env ;
o . Mime = exports . moxie . core . utils . Mime ;
o . Exceptions = exports . moxie . core . Exceptions ;
// expose globally
exports . mOxie = o ;
if ( ! exports . o ) {
exports . o = o ;
}
return o ;
} ) ( this ) ;
; webshim . register ( 'filereader' , function ( $ , webshim , window , document , undefined , featureOptions ) {
"use strict" ;
var mOxie , moxie , hasXDomain ;
var FormData = $ . noop ;
var sel = 'input[type="file"].ws-filereader' ;
var loadMoxie = function ( ) {
webshim . loader . loadList ( [ 'moxie' ] ) ;
} ;
var _createFilePicker = function ( ) {
var $input , picker , $parent , onReset ;
var input = this ;
if ( webshim . implement ( input , 'filepicker' ) ) {
input = this ;
$input = $ ( this ) ;
$parent = $input . parent ( ) ;
onReset = function ( ) {
if ( ! input . value ) {
$input . prop ( 'value' , '' ) ;
}
} ;
$input . attr ( 'tabindex' , '-1' ) . on ( 'mousedown.filereaderwaiting click.filereaderwaiting' , false ) ;
$parent . addClass ( 'ws-loading' ) ;
picker = new mOxie . FileInput ( {
browse _button : this ,
accept : $ . prop ( this , 'accept' ) ,
multiple : $ . prop ( this , 'multiple' )
} ) ;
$input . jProp ( 'form' ) . on ( 'reset' , function ( ) {
setTimeout ( onReset ) ;
} ) ;
picker . onready = function ( ) {
$input . off ( '.fileraderwaiting' ) ;
$parent . removeClass ( 'ws-waiting' ) ;
} ;
picker . onchange = function ( e ) {
webshim . data ( input , 'fileList' , e . target . files ) ;
$input . trigger ( 'change' ) ;
} ;
picker . onmouseenter = function ( ) {
$input . trigger ( 'mouseover' ) ;
$parent . addClass ( 'ws-mouseenter' ) ;
} ;
picker . onmouseleave = function ( ) {
$input . trigger ( 'mouseout' ) ;
$parent . removeClass ( 'ws-mouseenter' ) ;
} ;
picker . onmousedown = function ( ) {
$input . trigger ( 'mousedown' ) ;
$parent . addClass ( 'ws-active' ) ;
} ;
picker . onmouseup = function ( ) {
$input . trigger ( 'mouseup' ) ;
$parent . removeClass ( 'ws-active' ) ;
} ;
webshim . data ( input , 'filePicker' , picker ) ;
webshim . ready ( 'WINDOWLOAD' , function ( ) {
var lastWidth ;
$input . onWSOff ( 'updateshadowdom' , function ( ) {
var curWitdth = input . offsetWidth ;
if ( curWitdth && lastWidth != curWitdth ) {
lastWidth = curWitdth ;
picker . refresh ( ) ;
}
} ) ;
} ) ;
webshim . addShadowDom ( ) ;
picker . init ( ) ;
if ( input . disabled ) {
picker . disable ( true ) ;
}
}
} ;
var getFileNames = function ( file ) {
return file . name ;
} ;
var createFilePicker = function ( ) {
var elem = this ;
loadMoxie ( ) ;
$ ( elem )
. on ( 'mousedown.filereaderwaiting click.filereaderwaiting' , false )
. parent ( )
. addClass ( 'ws-loading' )
;
webshim . ready ( 'moxie' , function ( ) {
createFilePicker . call ( elem ) ;
} ) ;
} ;
var noxhr = /^(?:script|jsonp)$/i ;
var notReadyYet = function ( ) {
loadMoxie ( ) ;
webshim . error ( 'filereader/formdata not ready yet. please wait for moxie to load `webshim.ready("moxie", callbackFn);`` or wait for the first change event on input[type="file"].ws-filereader.' )
} ;
var inputValueDesc = webshim . defineNodeNameProperty ( 'input' , 'value' , {
prop : {
get : function ( ) {
var fileList = webshim . data ( this , 'fileList' ) ;
if ( fileList && fileList . map ) {
return fileList . map ( getFileNames ) . join ( ', ' ) ;
}
return inputValueDesc . prop . _supget . call ( this ) ;
}
}
}
) ;
var shimMoxiePath = webshim . cfg . basePath + 'moxie/' ;
var crossXMLMessage = 'You nedd a crossdomain.xml to get all "filereader" / "XHR2" / "CORS" features to work. Or host moxie.swf/moxie.xap on your server an configure filereader options: "swfpath"/"xappath"' ;
var testMoxie = function ( options ) {
return ( options . wsType == 'moxie' || ( options . data && options . data instanceof mOxie . FormData ) || ( options . crossDomain && $ . support . cors !== false && hasXDomain != 'no' && ! noxhr . test ( options . dataType || '' ) ) ) ;
} ;
var createMoxieTransport = function ( options ) {
if ( testMoxie ( options ) ) {
var ajax ;
webshim . info ( 'moxie transfer used for $.ajax' ) ;
if ( hasXDomain == 'no' ) {
webshim . error ( crossXMLMessage ) ;
}
return {
send : function ( headers , completeCallback ) {
var proressEvent = function ( obj , name ) {
if ( options [ name ] ) {
var called = false ;
ajax . addEventListener ( 'load' , function ( e ) {
if ( ! called ) {
options [ name ] ( { type : 'progress' , lengthComputable : true , total : 1 , loaded : 1 } ) ;
} else if ( called . lengthComputable && called . total > called . loaded ) {
options [ name ] ( { type : 'progress' , lengthComputable : true , total : called . total , loaded : called . total } ) ;
}
} ) ;
obj . addEventListener ( 'progress' , function ( e ) {
called = e ;
options [ name ] ( e ) ;
} ) ;
}
} ;
ajax = new moxie . xhr . XMLHttpRequest ( ) ;
ajax . open ( options . type , options . url , options . async , options . username , options . password ) ;
proressEvent ( ajax . upload , featureOptions . uploadprogress ) ;
proressEvent ( ajax . upload , featureOptions . progress ) ;
ajax . addEventListener ( 'load' , function ( e ) {
var responses = {
text : ajax . responseText ,
xml : ajax . responseXML
} ;
completeCallback ( ajax . status , ajax . statusText , responses , ajax . getAllResponseHeaders ( ) ) ;
} ) ;
if ( options . xhrFields && options . xhrFields . withCredentials ) {
ajax . withCredentials = true ;
}
if ( options . timeout ) {
ajax . timeout = options . timeout ;
}
$ . each ( headers , function ( name , value ) {
ajax . setRequestHeader ( name , value ) ;
} ) ;
ajax . send ( options . data ) ;
} ,
abort : function ( ) {
if ( ajax ) {
ajax . abort ( ) ;
}
}
} ;
}
} ;
var transports = {
//based on script: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest
xdomain : ( function ( ) {
var httpRegEx = /^https?:\/\//i ;
var getOrPostRegEx = /^get|post$/i ;
var sameSchemeRegEx = new RegExp ( '^' + location . protocol , 'i' ) ;
return function ( options , userOptions , jqXHR ) {
// Only continue if the request is: asynchronous, uses GET or POST method, has HTTP or HTTPS protocol, and has the same scheme as the calling page
if ( ! options . crossDomain || options . username || ( options . xhrFields && options . xhrFields . withCredentials ) || ! options . async || ! getOrPostRegEx . test ( options . type ) || ! httpRegEx . test ( options . url ) || ! sameSchemeRegEx . test ( options . url ) || ( options . data && options . data instanceof mOxie . FormData ) || noxhr . test ( options . dataType || '' ) ) {
return ;
}
var xdr = null ;
webshim . info ( 'xdomain transport used.' ) ;
return {
send : function ( headers , complete ) {
var postData = '' ;
var userType = ( userOptions . dataType || '' ) . toLowerCase ( ) ;
xdr = new XDomainRequest ( ) ;
if ( /^\d+$/ . test ( userOptions . timeout ) ) {
xdr . timeout = userOptions . timeout ;
}
xdr . ontimeout = function ( ) {
complete ( 500 , 'timeout' ) ;
} ;
xdr . onload = function ( ) {
var allResponseHeaders = 'Content-Length: ' + xdr . responseText . length + '\r\nContent-Type: ' + xdr . contentType ;
var status = {
code : xdr . status || 200 ,
message : xdr . statusText || 'OK'
} ;
var responses = {
text : xdr . responseText ,
xml : xdr . responseXML
} ;
try {
if ( userType === 'html' || /text\/html/i . test ( xdr . contentType ) ) {
responses . html = xdr . responseText ;
} else if ( userType === 'json' || ( userType !== 'text' && /\/json/i . test ( xdr . contentType ) ) ) {
try {
responses . json = $ . parseJSON ( xdr . responseText ) ;
} catch ( e ) {
}
} else if ( userType === 'xml' && ! xdr . responseXML ) {
var doc ;
try {
doc = new ActiveXObject ( 'Microsoft.XMLDOM' ) ;
doc . async = false ;
doc . loadXML ( xdr . responseText ) ;
} catch ( e ) {
}
responses . xml = doc ;
}
} catch ( parseMessage ) { }
complete ( status . code , status . message , responses , allResponseHeaders ) ;
} ;
// set an empty handler for 'onprogress' so requests don't get aborted
xdr . onprogress = function ( ) { } ;
xdr . onerror = function ( ) {
complete ( 500 , 'error' , {
text : xdr . responseText
} ) ;
} ;
if ( userOptions . data ) {
postData = ( $ . type ( userOptions . data ) === 'string' ) ? userOptions . data : $ . param ( userOptions . data ) ;
}
xdr . open ( options . type , options . url ) ;
xdr . send ( postData ) ;
} ,
abort : function ( ) {
if ( xdr ) {
xdr . abort ( ) ;
}
}
} ;
} ;
} ) ( ) ,
moxie : function ( options , originalOptions , jqXHR ) {
if ( testMoxie ( options ) ) {
loadMoxie ( options ) ;
var ajax ;
var tmpTransport = {
send : function ( headers , completeCallback ) {
ajax = true ;
webshim . ready ( 'moxie' , function ( ) {
if ( ajax ) {
ajax = createMoxieTransport ( options , originalOptions , jqXHR ) ;
tmpTransport . send = ajax . send ;
tmpTransport . abort = ajax . abort ;
ajax . send ( headers , completeCallback ) ;
}
} ) ;
} ,
abort : function ( ) {
ajax = false ;
}
} ;
return tmpTransport ;
}
}
} ;
if ( ! featureOptions . progress ) {
featureOptions . progress = 'onprogress' ;
}
if ( ! featureOptions . uploadprogress ) {
featureOptions . uploadprogress = 'onuploadprogress' ;
}
if ( ! featureOptions . swfpath ) {
featureOptions . swfpath = shimMoxiePath + 'flash/Moxie.min.swf' ;
}
if ( ! featureOptions . xappath ) {
featureOptions . xappath = shimMoxiePath + 'silverlight/Moxie.min.xap' ;
}
if ( $ . support . cors !== false || ! window . XDomainRequest ) {
delete transports . xdomain ;
}
$ . ajaxTransport ( "+*" , function ( options , originalOptions , jqXHR ) {
var ajax , type ;
if ( options . wsType || transports [ transports ] ) {
ajax = transports [ transports ] ( options , originalOptions , jqXHR ) ;
}
if ( ! ajax ) {
for ( type in transports ) {
ajax = transports [ type ] ( options , originalOptions , jqXHR ) ;
if ( ajax ) { break ; }
}
}
return ajax ;
} ) ;
webshim . defineNodeNameProperty ( 'input' , 'files' , {
prop : {
writeable : false ,
get : function ( ) {
if ( this . type != 'file' ) { return null ; }
2014-07-20 02:43:13 +02:00
if ( ! $ ( this ) . hasClass ( 'ws-filereader' ) ) {
2014-07-17 16:45:12 +02:00
webshim . info ( "please add the 'ws-filereader' class to your input[type='file'] to implement files-property" ) ;
}
return webshim . data ( this , 'fileList' ) || [ ] ;
}
}
}
) ;
webshim . reflectProperties ( [ 'input' ] , [ 'accept' ] ) ;
if ( $ ( '<input />' ) . prop ( 'multiple' ) == null ) {
webshim . defineNodeNamesBooleanProperty ( [ 'input' ] , [ 'multiple' ] ) ;
}
webshim . onNodeNamesPropertyModify ( 'input' , 'disabled' , function ( value , boolVal , type ) {
var picker = webshim . data ( this , 'filePicker' ) ;
if ( picker ) {
picker . disable ( boolVal ) ;
}
} ) ;
webshim . onNodeNamesPropertyModify ( 'input' , 'value' , function ( value , boolVal , type ) {
if ( value === '' && this . type == 'file' && $ ( this ) . hasClass ( 'ws-filereader' ) ) {
webshim . data ( this , 'fileList' , [ ] ) ;
}
} ) ;
window . FileReader = notReadyYet ;
window . FormData = notReadyYet ;
webshim . ready ( 'moxie' , function ( ) {
var wsMimes = 'application/xml,xml' ;
moxie = window . moxie ;
mOxie = window . mOxie ;
mOxie . Env . swf _url = featureOptions . swfpath ;
mOxie . Env . xap _url = featureOptions . xappath ;
window . FileReader = mOxie . FileReader ;
window . FormData = function ( form ) {
var appendData , i , len , files , fileI , fileLen , inputName ;
var moxieData = new mOxie . FormData ( ) ;
if ( form && $ . nodeName ( form , 'form' ) ) {
appendData = $ ( form ) . serializeArray ( ) ;
for ( i = 0 ; i < appendData . length ; i ++ ) {
if ( Array . isArray ( appendData [ i ] . value ) ) {
appendData [ i ] . value . forEach ( function ( val ) {
moxieData . append ( appendData [ i ] . name , val ) ;
} ) ;
} else {
moxieData . append ( appendData [ i ] . name , appendData [ i ] . value ) ;
}
}
appendData = form . querySelectorAll ( 'input[type="file"][name]' ) ;
for ( i = 0 , len = appendData . length ; i < appendData . length ; i ++ ) {
inputName = appendData [ i ] . name ;
if ( inputName && ! $ ( appendData [ i ] ) . is ( ':disabled' ) ) {
files = $ . prop ( appendData [ i ] , 'files' ) || [ ] ;
if ( files . length ) {
if ( files . length > 1 || ( moxieData . hasBlob && moxieData . hasBlob ( ) ) ) {
webshim . error ( 'FormData shim can only handle one file per ajax. Use multiple ajax request. One per file.' ) ;
}
for ( fileI = 0 , fileLen = files . length ; fileI < fileLen ; fileI ++ ) {
moxieData . append ( inputName , files [ fileI ] ) ;
}
}
}
}
}
return moxieData ;
} ;
FormData = window . FormData ;
createFilePicker = _createFilePicker ;
transports . moxie = createMoxieTransport ;
featureOptions . mimeTypes = ( featureOptions . mimeTypes ) ? wsMimes + ',' + featureOptions . mimeTypes : wsMimes ;
try {
mOxie . Mime . addMimeType ( featureOptions . mimeTypes ) ;
} catch ( e ) {
webshim . warn ( 'mimetype to moxie error: ' + e ) ;
}
} ) ;
webshim . addReady ( function ( context , contextElem ) {
$ ( context . querySelectorAll ( sel ) ) . add ( contextElem . filter ( sel ) ) . each ( createFilePicker ) ;
} ) ;
webshim . ready ( 'WINDOWLOAD' , loadMoxie ) ;
if ( webshim . cfg . debug !== false && featureOptions . swfpath . indexOf ( ( location . protocol + '//' + location . hostname ) ) && featureOptions . swfpath . indexOf ( ( 'https://' + location . hostname ) ) ) {
webshim . ready ( 'WINDOWLOAD' , function ( ) {
var printMessage = function ( ) {
if ( hasXDomain == 'no' ) {
webshim . error ( crossXMLMessage ) ;
}
} ;
try {
hasXDomain = sessionStorage . getItem ( 'wsXdomain.xml' ) ;
} catch ( e ) { }
printMessage ( ) ;
if ( hasXDomain == null ) {
$ . ajax ( {
url : 'crossdomain.xml' ,
type : 'HEAD' ,
dataType : 'xml' ,
success : function ( ) {
hasXDomain = 'yes' ;
} ,
error : function ( ) {
hasXDomain = 'no' ;
} ,
complete : function ( ) {
try {
sessionStorage . setItem ( 'wsXdomain.xml' , hasXDomain ) ;
} catch ( e ) { }
printMessage ( ) ;
}
} ) ;
}
} ) ;
}
} ) ;