From 184355a104c2d241ea79bfc1be9b6b1ee3e45b22 Mon Sep 17 00:00:00 2001 From: Artur Kyryliuk Date: Mon, 5 Oct 2026 01:29:19 +0200 Subject: [PATCH] fix(manager): removed flash based uploader --- .../Unit/Manager/KcfinderAclUiSourceTest.php | 25 +- .../browser/mcpuk/js/FileAPI/FileAPI.exif.js | 69 - .../mcpuk/js/FileAPI/FileAPI.flash.camera.swf | 7 - .../mcpuk/js/FileAPI/FileAPI.flash.image.swf | 10 - .../mcpuk/js/FileAPI/FileAPI.flash.swf | 143 - .../browser/mcpuk/js/FileAPI/FileAPI.html5.js | 3569 -------------- .../mcpuk/js/FileAPI/FileAPI.html5.min.js | 3 - .../media/browser/mcpuk/js/FileAPI/FileAPI.js | 4361 ----------------- .../browser/mcpuk/js/FileAPI/FileAPI.min.js | 3 - .../mcpuk/js/FileAPI/crossdomain.xml.example | 9 - .../mcpuk/js/FileAPI/jquery.fileapi.min.js | 2 - .../browser/mcpuk/js/browser/uploader.js | 307 +- .../browser/mcpuk/tpl/tpl_javascript.php | 2 - 13 files changed, 220 insertions(+), 8290 deletions(-) delete mode 100644 manager/media/browser/mcpuk/js/FileAPI/FileAPI.exif.js delete mode 100644 manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.camera.swf delete mode 100644 manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.image.swf delete mode 100644 manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.swf delete mode 100644 manager/media/browser/mcpuk/js/FileAPI/FileAPI.html5.js delete mode 100644 manager/media/browser/mcpuk/js/FileAPI/FileAPI.html5.min.js delete mode 100644 manager/media/browser/mcpuk/js/FileAPI/FileAPI.js delete mode 100644 manager/media/browser/mcpuk/js/FileAPI/FileAPI.min.js delete mode 100644 manager/media/browser/mcpuk/js/FileAPI/crossdomain.xml.example delete mode 100644 manager/media/browser/mcpuk/js/FileAPI/jquery.fileapi.min.js diff --git a/core/tests/Unit/Manager/KcfinderAclUiSourceTest.php b/core/tests/Unit/Manager/KcfinderAclUiSourceTest.php index 13678ee7a0..73bb7fe74d 100644 --- a/core/tests/Unit/Manager/KcfinderAclUiSourceTest.php +++ b/core/tests/Unit/Manager/KcfinderAclUiSourceTest.php @@ -46,15 +46,36 @@ public function testUploaderScriptUsesFilePaneDropzoneAndSkipsFolderTiles(): voi self::assertStringContainsString('browser.initFilesDropzone();', $source); self::assertStringContainsString("browser.bindDropListeners(document, '_filesDropGuardHandlers'", $source); self::assertStringContainsString("browser.bindDropListeners(filesPane, '_filesDropzoneHandlers'", $source); + self::assertStringContainsString('browser.prepareFiles(this.files);', $source); self::assertStringContainsString('browser.preventExternalFileDropDefault = function(evt)', $source); self::assertStringContainsString('browser.extractDroppedFiles = function(evt)', $source); - self::assertStringContainsString('var files = FileAPI.getFiles(evt) || [];', $source); - self::assertStringContainsString('return dataTransfer.files;', $source); + self::assertStringContainsString('dataTransfer.files', $source); self::assertStringContainsString("if (typeof types.contains === 'function')", $source); self::assertStringContainsString("browser.isFilesDropzoneElement = function(target)", $source); self::assertStringContainsString("browser.isFilesDropTarget = function(target)", $source); self::assertStringContainsString("$(target).closest('.file', '#files')", $source); self::assertStringContainsString("!file.length || !file.data('isDir')", $source); + self::assertStringContainsString('!browser.allowedExts.test(ext) || browser.deniedExts.test(ext)', $source); + self::assertStringContainsString('browser.maxFileSize <= file.size', $source); + self::assertStringNotContainsString('FileAPI', $source); + self::assertStringContainsString('new FormData()', $source); + self::assertStringContainsString('new XMLHttpRequest()', $source); + self::assertStringContainsString("data.append('file', blob, file.name);", $source); + self::assertStringContainsString("data.append('dir', browser.dir);", $source); + self::assertStringContainsString("browser.baseGetData('upload')", $source); + self::assertStringContainsString('window.createImageBitmap', $source); + self::assertStringContainsString('canvas.toBlob', $source); + } + + public function testUploaderLoadsWithoutTheLegacyFlashFileApiBundle(): void + { + $root = dirname(__DIR__, 4); + $template = (string) file_get_contents($root . '/manager/media/browser/mcpuk/tpl/tpl_javascript.php'); + + self::assertStringNotContainsString('js/FileAPI/', $template); + self::assertFileDoesNotExist($root . '/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.swf'); + self::assertFileDoesNotExist($root . '/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.image.swf'); + self::assertFileDoesNotExist($root . '/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.camera.swf'); } public function testFolderTileAssetsExistForBothThemes(): void diff --git a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.exif.js b/manager/media/browser/mcpuk/js/FileAPI/FileAPI.exif.js deleted file mode 100644 index 0dd92d00c2..0000000000 --- a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.exif.js +++ /dev/null @@ -1,69 +0,0 @@ -(function (){ -/**! - * Binary Ajax 0.1.10 - * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com, http://blog.nihilogic.dk/ - * Licensed under the MPL License [http://www.nihilogic.dk/licenses/mpl-license.txt] - * - * - * Javascript EXIF Reader 0.1.4 - * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com, http://blog.nihilogic.dk/ - * Licensed under the MPL License [http://www.nihilogic.dk/licenses/mpl-license.txt] - */ - - -var BinaryFile=function(j,k,l){var h=j,i=k||0,b=0;this.getRawData=function(){return h};"string"==typeof j&&(b=l||h.length,this.getByteAt=function(a){return h.charCodeAt(a+i)&255},this.getBytesAt=function(a,b){for(var c=[],f=0;fc&&(c+=65536);return c};this.getSShortAt=function(a,b){var c=this.getShortAt(a,b);return 32767c&&(c+=4294967296);return c};this.getSLongAt=function(a,b){var c=this.getLongAt(a,b);return 2147483647 128*1024) { - try { - var size = Math.min(blob.size, 128 * 1024); - blob = (blob.slice || blob.mozSlice || blob.webkitSlice).call(blob, 0, size); - } catch (e) { - FileAPI.log("exception "+ e); - } - } - - FileAPI.readAsBinaryString(blob, function (evt){ - if( evt.type == 'load' ){ - var binaryString = evt.result; - var oFile = new BinaryFile(binaryString, 0, blob.size); - var exif = EXIF.readFromBinaryFile(oFile); - - defer.resolve(false, { 'exif': exif || {} }); - } - else if( evt.type == 'error' ){ - defer.resolve('read_as_binary_string_exif'); - } - }); - } - - file.__exif.then(callback); -}); -})(); diff --git a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.camera.swf b/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.camera.swf deleted file mode 100644 index a750ddc2f9..0000000000 --- a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.camera.swf +++ /dev/null @@ -1,7 +0,0 @@ -ZWS² -  }ïÓËwñÒ.ã -Ì…Õ‰Þà÷Œ[a->WÛŒo‰8rë§4å©CbžäŠqèà(„qLn¶òühv§„=nþ¢R{¨fs -·7LêÕzò˜W‡¦A­àÁþ¾fð½¶¢o©Öb>d—ßËÃΚ)높}`Þý îšGÕ“œ½â _re¯hÑé’6uPŒÚ8gĈJ”oöµ`T\^|Û¸zl¼ ¿9�/S³®¾…ܼV1¨�­Ÿ¥(GP õÖþpß:ž3¡ ¶aá´pDÌ7�è`ûî¬X� ¿aׯ«_þ eæ¶?:Šs1j…�dLÙ–¡re§a¢ †Œä“lLYc=w¥R@âàÞ°'Q嵂­CÓy“<]¯—Â¥',Ñ8720SÙw*ŒÝÌYÅ\†åü)Æäxÿ u_«wå ˜Ä|Ê"ƒEH6›µŠhö[-6@ý?•PZ±©Ã2t�+üÅ’TÞAóúKbÞk3²!U!Ï€[Ö©wT»dù”^¨¨�sŒ�Ï�Ò™;Íœ}Ü â¡ª[–öõ'{îv£¯jÖ®GÃ/äŽÇpySïæs‡åðôÃÁø+höèGÄO£ÞÒÏ×î÷“ã2D‹á>ГH£4Éô�4PkÝð'®ÛbYdÜ‚%Ø_ÊÖ"ðýyMÎA­¨¬··bžÚH¡3‡;.R ú« Œ¬Û�ULËøÖŸúR†NÛ¬Lk 1 -ÒVLb|Ë!ÈuU�÷™p™™¹ û‰k²0|3 è2¹Êí ¡Î5cÔO¶Í!1�.™øÓp!3‡HÑóß?†*` ï¶é‚뎊¦º¾ÛöÏ6¢ÑEÛ8ØCÑêûŽÝUi,”`Ùãê‰ìŠHþy}icfàV±>œªŠÅ;¿dšä©vyÓý¯�C€ƒ¥Í$A‹© -|Wfc÷ñ Ú‚ás~>:ªCÀ±cërªk¨dÈmÄøÓvàØ9•(°ßhÀjþ¯„wRâ§÷ŸúÉÛf*�>þ�ú—GŽ_F±ÐG ÙÙ–~*4ÜÀQ1îÈÏä!Þ�õ%Ò�0º;ti÷ز>¿Ð‡–nhžˆ™_ª~¡Í§UÅ>VMM‘4«x/EÒ¯Rÿr@访µ.¢8›Ä®‹ó�|BŒW@Ý,÷sh1[h=ž%SV'G:�ÝLR} £Hxf(5Æ| -;�@…ј³�Æ9up˜9&GÁuC±GÙUY‘P4¤ÄÄûÎYr€|SäA\ýİ3÷ïŽ××Q88á~Üa¿(íXù `R õV·bW³,¥³˜ã9†­Û9 ¢êƒÙ#½Èt1�]³nøœ?)^íø<.cÇ jªIEðB¯z «fÚpȑ߹iÄáR2¾ì8ÈÃ^Q¨¡>;-3�´I‡Æ®Ó¤nNjl™±P«5}—ÁÎr%ŠØ0ýîRù &ŒÜÛÆAùÒÃeC•vGêž4ý*ÄÿÛbuv \ No newline at end of file diff --git a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.image.swf b/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.image.swf deleted file mode 100644 index 39663ac6ef..0000000000 --- a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.image.swf +++ /dev/null @@ -1,10 +0,0 @@ -CWS - $.¶æ&l{å²Þr[£QšX·Œ†[*UqR•JU~ÀþoyËÉk^ò�Tå%U›J œØyÎS~À>‡œ Ž7o1—>ý�ï|}Î鑨#Ê? iÿš� Ë‘s„�Ÿu| „Ì8kzmy%±W.UêÓ8ší/ºnm:•ÚÝÝÙ©:[©Ñ©©©Tz,566Œˆáú~Å5ö†+õ+ýsÁ2¯›Ž]síj%!ÆF¾ºíÎö÷·X æÒÚ¶Sò( fŠ—x™WÜzjtd‰ -æ´Uuʆ;gÔj%Û4]jo¸^¬š/v�>l•Œzq&u>®í–øÜB¡šç‰•ßKL$Nü=t"À…¡s§–iï³ZNÕœjaÛDMRyΧ]Em;_²ëEîÌmW^Tª»Í'V�1n¸Õ³ˆc›˜/•­mc‹Ïe>óæ>Œ=�†Ëçû‰Ññdb,=:Ñ”!¬3©�²Ý²`çÈrø_ò Y’ŽŽŽžè2VXÃS�¿Ìïøö›ß}—ÁŠÿM_±K|áÑês/�Ïí2&èü½NNË1Ê|”„ɈðzL”�ª]zؾ#ê¥fÄ�.V«%nT´u×±+[�&bÛµKuÿâ¾ËÇØïøD¬¶&²`×k%c_[¯9¶Ë}¦Q*å ó¸ê†]æäµEÛ-5§øÃj�ûøžaº+¶«ØÛU1Ÿ…}Z­xp¿ð_– Q(,µÈê¾:wW½ Õʺ‹÷5nÚ?áÚ¢Qç7'´lþGÜtn"ýRÑpêª'[kZÔºp #¡·âvÝåî´/,/g–ŸodŸ¯o,ÜÍt8¼\Ýág ÒÆÕ(Ù[Z©® ýJž×]úãm4ºûÚZf}õIF/U�wV+VU¯"í.GÞz/µºó¤3ÖÇScéôÍT~Û.¹v¥óL§›idg�ËÍ{s™KUܵ6Š»x´ZÁ°˜X{‡7�½ÿƒäüéF˜öÖ,æ ×ÄÞW]Q -‘5ÇUênµ¦­ñ­Ì^mèY« žŽ¬÷§#׫Ï÷§Ï­ÊÓ g�šý´04ÀÔ²àjo…ÙCi£É´<­–arEÔ[Í8NÕNíºWzp§Šßfn;ÆØ0œ-î*î~�k‹s(ELL†¨×‡ -ЖÅ'Šv© 5ç|KÙ‡�d62~Q-ÑØu™;Ž–÷:H÷:ä±]p‹ê®¸<Ã=no]­èÝBe©íLB#ÿ•þا«¦•xeË-ê&¶é6ç‚ëß%’b1ˆÉ1Ó{ü*鉫D%ÝàKÆýñáøH<OÇGã½±I•ÄãJ›~= ÛÚCáHÔçƒ@§N»¢ -)$(\¢p™£¡ÐOá:… -ƒ½@aœÂ…4p‹vLQ˜¦p›Â Õg©>Gá…y - þEð_ª/QX¦�¡°B•»îQX¥¨Wÿ…RøŒB–J�¨ò9UÖ¨²Naƒ~Ø+QøÂ—äu -ÜìÍIÖù†Õží•ÐI’e¿î6Ò›}Çæ>)O^1.àõªq¯×ŒD.޳—V':5r—­+É!‹EQÿñó/Øœd´Øæ‚hxw˜xóÕ`¿S“ðæ«(f¤qXô5²QÔ"[–Qp' -¶üɱ†ä–?{UÌ)²ä×ÏãÜJ„D#èzŒéó0×F•e=´ÖH?ü{šÃ¥_”%ýehX¾\òæ"¬\‡h!rh[�»YBiec™éƒô2øn0=T†>N—àD¦f‡’Ò0¿Ôpaš$éz0'Ânvd; ä&¬ÖÍ\ðWÅÀæ­\ { 6;³�b ~YÑCŸ –w¸„ÄËI¡ð Œ"7'ïO’æ¸$Y70ÿSó>Ì�溄Εs��n­âP¬â}kò]ˆÎÌÝ–f°'È‘&‰.a:DªÛ’Ñ7ƒQËÒ°;ѨHm ·f�¹æÃc…°§}WiNr±tn!�[Lç–Ò¹åtŽâß—¤Ï;ŠBƒ?�•_K�ô³nvôù̵îwØ»Án²[l’M±iv›Í°Ù�°„“˜Ì¦2�Qæc~¦³ ²6ÖÎB,Ì",Ê:X'ëb1ÖÍzع3þqÖËγ>v�]d v‰]fWcWÙ5ÖÏ®³6ȆX’ ³–bi6ÊÆØø‰÷/¡Ø�9iS°²ßaJyÇÈ{FLOO Ošx©š¾+S7©0mª÷U"Lá¸ññE@ü¹îƒ¼6øGS[Y�«GðÚº[—×òô·ÍÚ²£7‘á½7VXò}nïO¹½m¹½m¹ý•�¼ï�I¯Þ²ôk¦|ýMöx:ñ¶À¾e!$}…Æ™×Lú~rõ4¹*ÈÕÓäê1¹Ú"ïXd•_3íU^¼ßõ§!þÛ‚ïdUÃf_[,„�,‡ð ·*:9ö%ô»ÐÜÓ!~¼~ê§í<Úÿ¢“�# \ No newline at end of file diff --git a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.swf b/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.swf deleted file mode 100644 index 3169e97b71..0000000000 --- a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.flash.swf +++ /dev/null @@ -1,143 +0,0 @@ -CWS -7 -Û‚ËÛ´MÚhšÔ&eÑç{e_Á ADAQÄ}ÇTÚ²¹ïû¾ïÊÿ�¹7iRŠïï{çÌÌ™3Û™sΜ™œ%)ïKRò’ädRAÚ ’$ý7ãE&Ig7ÖørK Š\³êÁp.J£ÔE" ¹C‡Îœ93gæ)9¡ÆÚ¡ÃÏ<óÌ¡ÃF 1b8†„g#žYC‚á>F‹ -¼áêFCÄ -º¨ì© -5EF `öZSë´¡©1 º¬©ê xë½ÁHxèðœá訦:×j¬÷DF{þju7tÖ�p]¨úÒ™žÞ!¾€'\wöÐvFjñGÞÑy5¡*¯«(à�å:Õ•×Þ^p,Ä\Ó>ÑÑqËôPëœêPýІÆPMS5æäCW¢q|ꢡ©*à×yG7/ †fC´S‰§ºÑ뉄9¢4ªx‚µMžZïèÂÉ¢.VsôD¼£‡Ï6"gİá§“ ÚÙC;ÈÚ¤`ûFK©ŸÊgKùüèÑ£Úd쯠Hî3$ñ7_>¡µûýŠ­ÈðæM)®”žèò©LB…äkôÔ{‡K©RŽô$;[bÉŽ�\V¬©N×K7î°47ÿø™ÜÜÜü©ükfÙ�¤N¹S=º]^¶Ùqô)¹Ùµwù¦û•9¼yn³uHÏÈÍËÙžo7í°¼xí]l;ÿ´Ýrób>—}q§ãè¹¹÷Q6§÷Ü Ê¼ Êß ,‘ç<ËŸî¶^>ȾcîvÝ%7;çöž×»ù?÷ÝíhæÍ–fÛûY »7+O²'y³ü¤<7en·£GÙò-ê/®›{ÍÍ8ºC~5åùµOíµ.Ýyg]ÛâÛö*ÍÖƒsWîU~¼oõíÙµ«AhþSkþ[^<à6Wš=­ïÕÛô×õ÷õÏõïõßõ¹êÞ”9óó7\w »íýù#VmXpÖ†÷[¯‘çl\X¸qþž««oß³0åö�¯Ò殺ó>vý}¶°M/­}Šßu°å.ù�¯ß}Q~xáÊ-ÊsWcø½w´nQo{o¯úús+·Z>~å¶}–Ï?nݪýüõ{û´ß^{·uአ/Y—nzåv}õ=o?«ß¸ké:ÛíûnzÌvç�-«í;>;¼Ë¾û»�ÙŸ^´j›ã¹_qìÝ´ÿޤC÷¼ó\Òk»]ŸüÁ‹×ïNþ¤uó‘äï>Ú¿9姯Þy>å·ŸäÖ¾¹åöV¾ëË7Ÿ’úqùeÏòuO+/^÷òõÐÝo=­¾¶óª�–�^Z÷Œå³ƒ/oÔ~úò­g´ß~\²Ö:ÙM�Z¯Úr�¾ê®Ã;õë·|Pßðüµ÷ØîØ¿áeÛ–�^ÙdßõÕÛ{ìý´ôdzËn~Üñª­k’Üuä�¤#Û?9œôþó«îMþxÿÆýÉŸÓRþfÏÊ»ô÷ØWì5ý¯£vËÙͬ9yÉfÔð×§ÿ7ñ«±Fæ[3ýtŒ‘¾;fI^åG-½Œ©J=ÿÌ�/¼?æÅ�ßš5ô±1ŽÏÒ²sÌè¼¾[Ö<æÌ¡Ó7¿å«cq=Ååç¾7fohÒÊmŸüíÿ sÜ1ßx&lŸ2üç1[ÒßTµ|?æ¬'6?éïûÙ˜é[ßžzg+ñפîþ*o�URf„ü5a€9ÞäÕBJ’ R�?Üð̶”54ú#^‹»êouÄ2¹©¾ÊÛh)‹4úƒµ½›rê=þ -J~¨¾!à�xÅ j^c£g¶­Ü_ïmg´/o°Öô†c}vÍ« -G=Õ‘BQ‘o�3;²Ãu1«ÆJŸ¬ö4ÕÖE -CÆhÚ¸P(àõ“c݈æÝ‹ëáÿÊ=Á0ùö„^2¦6ÐÊhISCµ�ÞpX”tZ«È9¢ÝÂczRó"Ou�8d&…j¼�”øÚœ!Û8OØKqš[7dôFlSK'–z/kò†#J“3“ŸæN-#`w<‘j¸ú®Ç®Îã&'JÍ^Q‘WvJEEÎ oµe62ÔÞŽÝ4O*kIY¾'ð6¦t¦ß1{]Ûèi¨óW'lwÖxƒØÉŽÛË"žH“!©ôö΂‘Æ�—„ã2?V²âp»Û÷ÌnȦ)â„õq³#^¡B2d“š¸mÓÜ]¢«EZïì¤âø’Vl ‘Úq]'DÛûM\¦RÙÆù#õž†ìZ²!Ö°ÙYZq0â¥6þ^ÃPl“BMacá]¶»ªÉ€hR©ß0u5Î X‰@I”)õú¼�Þ`µW'ÑMÊ„òò)q2Ì€’äøƒá?ì3jm“šƒ§1í1ö@ðÚŠ<—šfŸRŠ„Œ¼«À[ …$Y†ËCÆêöÌ…ª#ÞÈÈÆë©×cý‹yOÁˆéeÞê&LevûŽYŒ.…³ªM5Þ|ì_8)áä·W´k@J…©Q¤°$ÅôG\ÇjJn¢¦TÔ“Mé—„ Åíbæª<Õ—N�mzik2 µN ©3üÞ™ÖŠ�ˆb¶ -a8¥¡PĆ%Ö̾I8¥��j‚ÂU#Jiô´Ï"5¿ÁJ“Ÿ†þÑWعWdÃÞHSC>�’ŽåøüµM�Þ‰þpÄô6†íF­è'­Ö) 5«ij“AsÀ«/-sçÃk5fV››TŒAüž€ÿr±CZM�[NAž—²¦é Eü¾Ù%eyC~¥´G(X[WJ(˜à`“BA([-4‘¦�Z¡°eˆ–¡5('8Õ$L¾|vé$«£”ßÔ5juþH9&�Š¡›¯Ñ‡“¥.‹ƒ¾P²?Á~mM1˳U{`ʪմt›ÀbÌîÿpúØ‹ÛÏ�ÿÀ—Çg%SËü$Þöšìê¡#sREò„˜…Xµ -ƒÍZQ^<©Ð=µÜZQ65?¿°¬L¯ˆîbf…§¦&fP1…èÖá˜È5O þ ¹¬Q»�Å ¢ã’2cŽƒÿy¡ ¼=:å)�¦j+¬À`Ïù'öÜcØí>ñã€Ð+üែKmÄ&¢AJ¦!»Pù°èyàê¨�Ï\žÅóyx&×ñ𙼦N®ñÖê´‡6kµËšà©"³µÐ o#Ë”zòSp$.†¼£Û¨JŠŽ%ÎzëÄPm­·±¤,3�œ%ŸÜi “Û‰ÇOòÄŸVaùõ5ƒ;�%s;‹%mع²¦jÚ =–ÃÖ¢9|i8´µgá±B�©‰éDr; l³* ¾òÐaK&™ ý„ãÖ8*ªÛ ö¸|ÊÄÄÆÕÑ“åv`ÐL%U(µÃÀ… -B5ï,œï¸Y£ëA(쵇‚Ôƒp*¶P0'ä¨è’dØ#1èÎM¨´T7Ö»O'Á·V�‘ C#9ñŸÔ M7²ñ–‘m!ÖÖ*¼ájyI$+ÞRr‚N»q2 ’•bŠÂY~ß Ký‡;ˆZA}*„²:Úcû%Bž¦¸Àb$ZEXLÚ6o‹Q¶›§}SC\I3O°®žNâè.�þøH{j|o'£s Õ:Í2<÷1¹©1�lLdJ(¡ÈW«óÒ™VS˜ˆŠ# í“EdTíÄat æ6{s7úa8ž€Å(s°šW+ B£ŠL|’ÈPø•ÍàÀðûüÞQCf88j•%T*z|'õ)ÇõÇo“ZQc^¾Já®°8n )™‰$zÉþÿîQætXQ-�ßè5�õpJ”b–{ çF™VÎkôN ú\Ú(Ž3ºÊ±YiÇîŽk$N£ó(!§ÁpÝ”3:‘Õéÿ»Yg"¶Ó ànŠ<µ -ÝRÂMUô Yå-÷4bEiMÁËí.#­jvNU ª©™�SÝ8»!²�ù�~jîÿ~É=΋ˆFÇ8Rk…™é™àG:>"$åM�X^QT<±¼°T<¨Ñ·Ýˆ“„+›wLG|AÇbÌÛr‰Á¹5Œ=ñžã�­WÔyÂFèËDã[=O0éºðgâ˜I/F"‹û],^Ï0�ðdrúÿC^�4S#¡ÌYðÕ˜!v�¥BP�y1 H¦Rî¤NëscõYÇD³ª½Æ1ó¼ÆP°6ÁJÉT±¼áÇo—Ûy»ô¸Ñ$>®£8–×Ü[s§ñ…ÌŽÎpp^¢Îjìÿë9'÷øÏ9Ý;÷®`1ÆÑÅ©þÄ-¹8aœ!ÿÌ�›È-Ž1“’a\ÆêGü�Þ:ib1{®€Ýçƨ›¡é4÷ «a³Øl6“ÕÉ�ˆ�B žjD»r¸±:™¤B�]šêOìlsÚ«{%š}'gm -¦_tÌ{Ü',¥gl— -ã$=(ò{5t°¥T$ž¼\H§yýt­ ;¢>IÄ”81Ä«ÂãlNqt´]Ú1cö>ÎùÇÒ%L ðÄ BÁö'/-VvLØÓþ²e¨µLŸÚ˜#ô9Î$ây,†AÙ ?Bç¿#þ�-ýØÇ5+îÂÂ$S;. #ºqO|;{Ìí„öñÖ‡U�5sŒèƒÉ¸Ùź™Ï£§ªz\¨¨�Üž%G{1/bÖá ÓM2Û‡ÅkŽpœŒ—ØfàŽV#²ý:�mÇgËT#¢m߇I…èKT»kpÄ+î ‰‘rB8).»BÊ5)þ°icF¹«q¹üyÁ³Îˆ‹£®k\¨]Ôª/ 55V{OŠßÐÜc7T¯¨‚Dj<�³“+f˜ÚOÖ¥ˆF€ÈFk¶¿¸¨ƒßRá ÏV«Ðêô -D èØ[“!¨çÑ�Xn›Å5©‚&ÞMC~º—& …3îþ¤ut~ÂÚÄ»lr¢±)¤d:øFCØÍqhÅtÝÄ… êµÛdqøÆ¬Øx;Ã�2�3Wªæ•]09ß:¥´pJ^ia��6£H|Ù6ØFKM¨Ì¬É„€ª6UG¢¶žGëH;†œ"&B9ã-¼½al*âÁ8F6‚wA¢–Ñe¡gi¦ªÁ�AJ…8píŒZ� -š_ RBÁ„÷hK44�!Z´ŽsO�\�Wz�>±xrá¸Ò¼s’Î�ê.Ï+/vOž”WzŽ­À=uÜÄ‚¼² Iô&–=1jH�N~]SðR*ö>VŸr<á¾ÃO‘�¯ˆÍ¢GJMÔÿÚã¼ëàNžõs�ó¬ï¨" 9ÏÐ[•ñŒMÚáFù¿žù“+jG�Q—”PJ3žgþÑ¡Ãb z½5Õ°ËØ}69Í ÓtІ٦ Û½AXTØéj\*6|Ä ‰?q5–zq#FâÑf$ˆ[ÃZ}™V@­GtX­ä•ç•_XX¦”ç�/£‡rb² ¦EJ¯¢Ó<�&¯Ý|g7O -g‹‹ -²:^B°“ÃñymUõ Fm£mܤ)fÖR!6-¥N 7TÃI4&UøÃåQJMfE(hðG+ã„I$ -O­<¡«nÇÜTrDlf/™R8¾Pˆ»Ñ1eòø§šg¢¬Ûçš>®¸|RÞ”Š …y…¥åL)äã&u3©¸…F«HÐQz¾»´Szñä"w<Ýšïž4¥¢tü8ÝÈL,Ë�š,rhYT\8± LAn8¡S �T©x:á§>e„*¤ª5x §ˆ—WÕ8L7.*â••­-õ6ÎðÖ oÏŽ°Ý>_•?Öƒôq‚-Áóü5‘:-8Á믭‹hÁ)\3ÃIAìqx -.'þYÞ€C¸!º£àD°©�Ø™¤àù¨×$/½A/ˆ+ÙÐ&jœÆ)gd‹ëB�O0b –Nò„/µÇÉ8JÔ`)¼¬/ð8�Á6K%.`0ͲkM&¦•^Sóq«‹+ÒòŒb¦ñ7»o''k^*œjt�IN1$k:Šáà€ž˜¥S!:lZ´”P7r\|ÝH£.Ùìåô„âˆSЧŒ0‹Â›ˆI� x½)±„K½8ü‚Pô.P”øF®ÃN™Bw@‰„\ àqifpn xƒµ‘:óÇTáÙØÏzk4þL6®ÕõlrÇšù{+õ0µ1f~clúÖ`w -U±l‚öGR‡V7†ÂášM,gV}€�Q&áŽaA¢±cµ'¢ÒçåRU\ ˆ±Á ?ÒÒÌè$¥ºý[m€ŒŒoµ�å!œ>IÑ·f±#©ÑoûÆÒs]–Romá¬V+Ÿ5(‹†T{ù UDîJCS¸ŽyeóôÉ!b<4’’‰_è$5…½4¨ñ‹ çÛ„ÙˆcÖ \`ãÄM5G�íu¹.ží²g»Œ/?®Q.Wܯ \Ѥٮ°ñ} êLÑs�è­O¤©š'ù,·O«7~`m0½­]ÄFÆEZ¡ÇÖ.´—áÍ�I…!^MWƒ”›¸&µ¦©¾~¶„±à†ØèŸÕÅà°U£kÔá›_`¢ó—‘²p7Ob—á]¡ Ë´ó.‚ÞaDgs؉rÓcóN�È㯯÷Öø!ºÀl¢®öÂ9Ác¥›í -¨PL×ð5zÚôLpKb—\V˜?µ´¸üÃ!Z‹ÝFÆVca}X®}DŠ ¹ëôù@Øsñ\×°¼:=]Ƴ® Î Š {>ä]¨‡Ëva�êüŸ¼5½†^qÌ®t q6›ë2mÙE¿Í@Ë\Wf´ktl0 rZÂ�Éè ±a€%?or~áDKUchfØk7qD*¾lv-†o¬õÜ ô@ä7á’òk›èS„qµŽû|`‰>ÕøÔ(>’Ñ NãCƒ«ýã;ÖB¿.0H•n¸F78sÜAG$T[ˆ~¢ˆòù|&cR¸ž´czÂÞ^©ôKÃz U3�x— “×NŠã˜™«d»êrºž:…zÝ»Â3}1ïaÁ9]>µ¬‹G|x‰rPW¹®~Çk”íjÿ}À(k¶1—Q²wFÄiþî-ǯ¹´MIüÑ…KÁ»)†©Áú&¨ƒÃ,N¢BÈ»ÑUã úqy ‡]7zìfþØ?69Ñ)‡?<Ù3™ ²Cx¡™â0I6wa#Å‘…fFü˜Ñ/W××ÐÃIô‡Ý‘w]v�ó€QËΈþš";ªœ¹.%ÒØäͬöƒ½¨o¯³ÐÌ"ª°\k½©?zLlí;®U5UïWâ§d�Øñw >ã�0¢`S ÐK(¦«ÏðaÃÎÌuÎÎEe”!G¯ˆ.@%ú ¹›âLÖ|Õüañë8Ö¨™_ mâì�ÂÍðZib6A¿.Ñ…÷ 7œÓ®ˆþê€l¶“_..lü7:'{M«ñ"® -„yèR»BÊÌOø"q_šGt_j1deülšÛ.ž¥Œ -ûÉpÅoÍqމ_t‘%$ƒ/6•ó¢œ"R‰‹rÂÒi¦ÿ®ð/Ê¡‰yüÕ >¹¯ZOO!é JøŸë‚ \¾xcž*8â2àLãÛ oÍøÄ.i{ÂÌ›¼ý†5[,•–dtåDd]ªqÑ} ÂVgЛ’^êž8±Â=­°Ô6É=µ¬°¢À}Þd«‘�:ÅjÔN-O‹û×B†uF£T£ä0â¿I8ág�Í—_PX4~BqÉ9'MvO9·´¬|ê´óοàBOUu�×W[ç¿äÒ@}0ÔpYc8Ò4cæ¬Ù—>â”SO;ýŒ‘gš$4djy‘¸JßkEÖ9©x2f8)ɤÂIîÒ p ™<¾|B²òf@)Éþ¤MÑöÍlìÿÿo4`Œ1�ܳÎeR%ÆeEµhVÝfw$%§¤¦¥gtéšÙÍy‚QŸÕ½GÏOrõêݧo¿þžÝ<Ùì¿ßñŸ˜®4C�\—³DݰÃl6„éøßÓ;®ï |ÁPŒ 7¢~úÜÁ¦Ìd³”&~ä÷‰¸ÑîFgþ �°%‰9ý¾„šO#®„‹t¸Á[í÷‘ÏŸ’W>á4“IP‘:è¤y6…‚HÓç2h]âã2ŽÀ Óœ1Ô -7Ÿ¦@�ËüTl`U^„`t�ŠF3ë¼Ôó1í“„AŠ ,Ðák Õçã ̇ì3b6^ÐþÁx\ñä¼Ò ”òÂóËõiy¥Åyã&–õ4/‘®X —°+£MÌßÒA}b̃ ¥G’!4׳\Ñoò£,…˜®'hW<¾¢prAqÞd‹WPúG;)?Ko®+® z°ÕÛVmN>/¢Ç‚ž!ÿ¿¶†Gìí(kªª÷G\ç6ygýÿ5%Å¥\ï¤Þg ×d�“ãOš\—†•Õá>$×ûƒ¥ÆçÓxLþʸL™Ú&¥X®÷ÌRŵ Å’=Ua¹:¶4†è§Nš—˜È$OCŠêÆÊÆLj¢e‹èå|#¹@±Œ½‹q™É#uVt!udŒ7Cl´<$x’Å£ØÛÛ°c×ÿ:æ!‹‘Îu ÿç¹ñ.K§—ÕoÎ=¹:ahkuÀß@Y¿c»4¾ÚD=£¸–¤ÆK‚ŒF‡¨½p -Þñ5nj0ì¯E�ôXü œ2�ÿÚ%Âøè‰¦“ZW€ö NíB“ÈU‰Ÿ&ÄSF(��ï5JG|ï…K Ô¤·SpRâŸÆÐ#§µ,ä‹ÌDÒ2¼ïñæÿé;ibqyùÄBÓ³¤ÄË�÷mÿޏQüNŠN�°«„š#Î==ºá´øæÂ¨m¾ØÇXÁf«cŸd�_`ÍþØ÷מ�� »§ï±rCh¦5l -¨3Öö 7,/ W5ùú:‚ô®-¾ÑOÙÅ?ˤ_6�MµÛR�Oåp$gdåž}FrŠgŽLNËìyÊySF§göYP_;ÉÙ猱çÖ]vÑð±“Ï«�=Ë;ᢊª†šÚê±iéÎ¡ÕøKïš5ŽRgÖHJª‡ŠÒÿþÃ=Pµ$§tïÁ-)5«ç ÙêH;áÄ“ëötçI³O³ets rêé]2{õÏ9匳»öî7tÄȳFõé;lø™¹£Ç¤¢&þÌ’Y¦JœÉ2WdUUIbW¦J2‹þ vâàŠ"+q0>ó ³ÞÈœkYæ:æ¼ç„¶e>œ�1çãT~ŠÐóÌù2¥¯z�Ð[ÔÃÇÌù¾$ôQæsçrŽÂ5ܹ†g^Ï�7¢”y+wÞFÔÛ í"ÊÃÜù(Ï|Œ;ŸäΧ‰º‡Ðó„^ ú}Üú2w¶Pù ¡·¸ómJßåÎÏ(ýŠÐ·ÄùwþÊ� dçR™Æ%ô¸ì|Zvî¡ì‹„Z½ ”ù‰ìüœ -w)Î{UÊZóhNô¿nÙÖҬï•,-s¡Úm6ªÿcý@EMï,’W·u,ëV–yýb «[÷¬m,óz rý³HZÝÎÈ"9e‘t²H H®áÝ®ÇÝN@~Ïú’e~cé¶”,Z^ÖA1~Ö»”§¥e}+ÝFeýJ¥¥r·x-+‹ÖÒí–EËÉ¢ådÑZº}"gÝ¥œÂN`v¦³1«ÝÉ’²”El1ë¶„-e˘ãX -K±÷`W±«Ù ‹™Ò}… ÚObö•ìZp�¸Êàrôc}¯c}Vƒ´†]Ï jRgDë£`‹Ø�,e1ë(úÉL¿™­×Àu(²Aú–}+KZÊmDHbªmÛÀÒ6‚2üvÑ Kcš>’%mbÄvÆ ÙÆ°ÍÏè;�í.¶…1;Í3+ ­w °BÛÄyÌz»‡mMô«0·mš˜Í½LŸzÛN]Ìv°�ì_‹Ùô]‚K¯d0�˜*vSýƒ¬†=dŒý°!!{Ä({�’.a�$ÿãQÒ,€²ãI–þ{Ú˜³AŠ£°t[ˆ=ì4Ãà³ÓeÈw¹tkxÎ`¹”ua¶™ìyc€/³œÍ^dƒö‚0kµº‚½dÔ_þ²Qÿ¶—½Â-fWî§â|ÆZØ¿[Áðß6ê•ͳjŒkðd²EcšÆPÔ5Å®1‡Æ“45E³¤i<]cšÖUÓ25ÞMãNÍš¥é=4Û‰;IÓ]ï¥ÙûhŽ~=O`N-i€ÆjɃ4>XK¢é9ª¥רT»4ýÍzªf=MÓO×ÒFjò™š=W“ÏÒøÙZúhÍ6Vãy§e€;CÓ 5½HÓÆk¶b­K‰ÆÏÑ䉛¬eºµÌ)Z×s5g™æ,לSµ¤išó<Íy¾æ¼@s^¨¥þKs^¤±éZÊÅš³BsVjN�æ¬ÒœÕš³Fsz5§OsÖjÎ:Íéל—hÎK5Мõ j,¤±�]¦±F�…5ÑX“Æfhl¦Æfi'\®eý[;áJýr¦õø¯Ö£ÉÀ\¦±k=æ!;Ù…€E€Å€%€¥€e€åL;éj¤+�^ƒt%àZÀ*ÀuL³¯fšëz¤70­×MHofú Œë«±K½Ë5Rï2 ¦¦õ¹…i}×ncZ¿ €z­ßF$·61m@¹6 Lpž6`3z¾p` *¶î܃ò½€û Òg‘î<Ç´a/ }é^¤û˜–öÓF¼ØÏ´á- µÚ Àdµ#L;}žúÓNÓ:Ó:ÓºðE®]¸—kÿz‰k½Àÿk?×_‚G¹ø¿ÚÅ0¹•kÃ@.&ËŰ�‹Û�ÂJôèòà0ààUÀk€×op­Ãêor­:ÄÞáZÍ{€÷@"ýð1à -GtŒAoCW¡|5` Sºl¥¬]v-`à:YK]�S¾l ÒëÐõËn@z#à&ÀÍ€µèsàÀ­€õ€Û í¶ xðàaÀ#€G�¡ï' x Ú/k³[m€€ƒ€C€Ã€#èæUÀk€×o€ö&º}KÖ®xGÖ½‹ô= X¸°p-`à:ÀjEck�^¸p#à&ÀÍ€µ€u€[ ð¸¢Í…' -‹‰º„ÐRBË-WµÅl*¯¬¢ÂuȬ¬\¯êý4ý•ú¼‘Øo"t3jÖn!öÛÝŽÒ&ªºƒÐfBw‚t`‹ªÉ[‘Þ ¸° p/1�?܉Â.*àÔYD[µçž~/³è÷¶îì „žKcÈí¥�˜/c€WT½’ÙÏ ½Ã(¿J•Ѐú‹Ðß„^SµÔ·¨òU‚(ò]U»Š½§bý:2$N ÃÞWµkÄž~ˆÂGÄò±ª_I£~F“ø\Õ]²ÞϦ÷á¸/ÀÇ ¶ï ìg~QµÕ8¯€~Eé7ˆÚ� Sõ[X’þ–’¬U“Á�¬oaÉúB@ ò+(oIÖw"¿KMÆž’–‚#d+,úŘøu–î)úV,�ØÇXt|¼3¨wì<ìÒqèy| ’eò1n»kïçKﮦω‹óC½ãzœ$å�%ë]q�-!2E;0ßÔCï&©}Æ�;K'nž$�“ò©º€¶µñ•ÃQ$I㥠0.KR‰tìl"“´I𥓙¤»™d›Â$û¹Lr”2)¹ŒI)åLJ�ʤ´iLJ?�Iç3©Ëpp2)ó_Lêv“œÓ™tÂÅLʪ`R�J&�èÁ6U1©o5“úÕ0©¿^có1éäÚzwV—£ùi&—�š_ -çÏ-‹”d·×3ih�IÃBL:-SÑ{J#µH”±Ë€2Ö( -a�#71éÌLÊuöÐO”Æh3q—FÍ ¾œK£¯`ÒØ3)ïJ&�û&2žÿ—K…ÿ•¥¢f†âD>T2ÛtÎ\Ü´{óyl>+³,`$Æ…¨s/DÝ”EŒd»ås£\º„Íez_išu)*z8Ë�$ÙlWö’Î[ΘtþU@\ tá - ]tQ‰¢÷—*l+E×׊W‘ J׉ý^ Ï ªë�ªo V•Ëk�d�‘Üb$·Éz#¹ÍHfA&0¶�J²¼‘‘�ÝN“µÛ7¡ßKï`Š>Xj�Æ)z¶æ›)Ö�¨‰Ø¹ž#ÍVï2V¶KŸ¹ù®Ìr7ò³î�§¹ÜÆõaÒÕmLHþ^Я¼ÏÈoGþ?ÄÓÌîg=ôáÒW±'Þ \ºšÑX×°”ǘ~*?IÓ�ž×*QµšuWô3¤™íitw{øfö,ðZ¶x{øö<ð­ìàõìEàÛØ^à lðF6 E?[z€9Z ‘´¢ê>`YÚÎÚˆô-c@»X–v°ƒŒlõ�À‡IÒ\>‚¤¿ô*ªw²×Àº‹½aŽ–b)o¾7Å2ßù·~Gàw�O–Hº é>"¤û({øqö>ðìà'Ù‡ÀO±�€÷°��Ÿc±ÈƒÌþ Æ{‘} -¼—}¼�}ü.Ó\z™} ü -û -x?°,µ°¯‘o–¥6ö òط̦çÑì¿[ö=ˆG„h^c?@íò1{õGTeI?aà·ØÏÀo³_€ßa¿¿ËÿÀô Sü ­>b¿ÃB‹¤Ï™õC{þdßþ…~?eaàÏ ð ö7Ú~ÉŽÅšq‰øšÍá -“¾…¯ãz±ô3³�öüÂær.ýÊ =¿±yœf8Ÿ“4pRªôú9Ò<ž¾�[¤E\ZÌÉr–pŠv—¢Ý_l1;˹0¦«¸Øã«¹˜Ø -püÍVà„9Êà›ù5\øÝÃw?Œ©Îå+1³ùüZà|ðB~ð"¾šs}ÆPÖ “eüzàåüNQò�ßÄ}Š„oæk¹^*­âÒ:nÓˤëá -hšÇ­h´†“¨oà® }*[Ï7pý6Nö·�SË�ÀkùíœÚn¾…ßÁ)œÛŒü­|3f¾žß‰üm¼'×Ï“6q!³;8Él3‡Ìîäw ™m'ÿV!³Ó2ô 0ÔV®ßM�9÷ éípÐ�w‹!ïCn]ß+¾�Ó�ÛÅ�÷ómÊ·›ó{!Š]ü>àøvÞCŸÎîç�p}§“c'ð.Žqxìæâô -”?ˆ�ñ‡€ç?�VLz–? -™UH/rÛcœ‚ØÇ~Bà'~Jˆöi‘F¨Á³1yùVàíòzàûåÛ€wÈ€wÊ�wÉ·? oÞ-ßü ¼ø!ùNà‡å»€‘· 'vH&�vØÐ ZøÇ2MùùÚ~*¿ -ü™üðçòëÀ_ÈoÈ8ʾ’¥7)ý‡-&|¥ô³|ö[²E²|)³·‘öQäw(Qåw)±ÈïQÂå÷)‘å(Ñä)±ÊÄ�)ÑåO(±ÉŸRb—?£Ä!NI’ü…˜ù—B˜¼Æ×bþ!‘Hß -ü�Àß üƒÀ?ÊtUÿIàŸå�ø7�µü§ ü%ð߸Y!V,M–¦²uŠ…YnaìbÉÏo¡äÒ7\úƒÃCŒfp¶ð„»0É®²¦þ"¼ Õ¼¢°Ý4L‹Â^2™[ÖJF'}(Cé­øù{#óƒ å^ªÈ‚Ñ*=ö–Æò–)P¬GÀp 4Iy™ë”Ç ¤ÕÊã¨]£<��½ -$?‰MnRžñfe¬Ì΂ `'‘Ô™}žÎj±‰g±LERò™S‘Ô ì?Šd™Äš™"iåPE²NgK�èu¬D‘lÖO‘ì—1\ò$G§HIW0»Â’ç0fS¤”e —3EJ]Ép½R¤4Ü>S–~;ÃeIʸ‹±ŠÔecÉŠÔ.4C‘2q?z¬Ý16P¡ª#ÊW¤p¯@Hϲpƒ¬HÝ¿aˆÕ©Ç�ŒBo©çïŒi -;q1géŠtÒUœ­Õµ’v\‘z!î½zï±÷(÷ÙÈ™K‘úÞÅYO…õÛÁÙiŠÔ‘Ý6T؃-G:p/gꤓ_æ q™4¨•³þŠ4ø5ÎNV¤lÄ- A¼pª"åüÎÙk(]"³‘[!³EŽÃð'G¼ ó·�ž2R‘N…/¡H§µÈìtE:ý ™=,+ÒÈ 'ƒ4þµé™ßÊ ŽXÊýQfpÄÒYð2pÄÒÙð*7*l“àGà¤Ñ7( A³NakQ3–| }mÒå–aã%ú° Û²[†µL—Kd©nTK±Tù´’n•¤÷h)5E’¦?£Trß³J‹o´û…£ W¸n›Ñ2lúžöš= -G»ÊçßóŠç…ò/*¾½ŠgŸÈ¿¤ø^V<ØôWÀ=Ê o™~r•û_‹Rr¯;›Ø¸¯õgûΧ‘¨®M©tøÚ…æè2Çìûµ óJ•ʰÊÃ*"ÉVy‰ŒÿŸ/õug�§¯>LQ�•ªŠ¬Z¾f´Ôñ}m%ãY]ÛR™î[ÌêÆ´Tv÷-duc[¦�k)ÇêòZZëò[ZÝç°–¶º‚Êî-m`¸])šÂ=·+•w°¶ìoßaeÍ÷mX‹oL[öÝeÏU•Ù?`Æc|Wñõî ¢Ö½’K-mîsÑìAj–î�¤ÊîfÁ³Il,ãÔtŸ1ˆ˜N6 -Ù?*w¯�êbSÜ’`þ‘óaF£ý$F;ÌŒÑÜ“À5™†+eX¶E᪥+VÝÚïS ÿwO”[²VÜQ¥&«ªeb˰VߥùUePµâ®–ª”!É}%÷k -¯RúJƒÜ¯S¦ ”7D怑ö•b™AFÆý¦‚PB²Ê�³§e˜«yð!W³ó°±‚´‰Xñà¢-Šd’[+—0ß:¥×mbj«+l«´ƒÐ⻀6ºµò÷øj_a›û -Öâ¢_¾ç/š¼.ce§A ¡ 6ßF´<�Z‚·Ùy(µ Zãé­¾ËAoMûäèQ4¶ÉôÏ}HJÐaI «+ÕÎÕr"äÑé.8rÀµuPšŠ]8�Ͷ¦#Nl›p`‚$98v�+{زÿRº¤bq؈¿•è~×�$’ \ËÖê{KiõÍj󽭸ߡylaé¨�þ®2èˆï]å©jå@•âyW±*V¹ò]ȳK?t7Æ·‚§Ãü*Çö�=Wu?ÇäT«(öGžOŸêž*¥ö' 3V )YÜ´Æ€²2B3Q(k®¤ëØ£GS…¥MÅZ>†³T¤OpþY¥wqþõ‘>Åù×Uú ç_­ôο.R -iÍPÒxëáÖì«Ô¨î¬”n1•g ï@öÕjÑç -Dz¸ j”ªB�² ¿–‹Ôš}�š½R­üB)úR‘оRp¤‘’ž /r#l-]ÁȧÃØ–A‡}žt¤í€g‚U¶ò¢gKÏ$¶·Ýc´ýV´Í�KÒ+,ªbÓ+¿S*�elœÔœE»SZðoFåTÚžamÃ.”4lp=ëi•Igœb'…V°.Q¥è+A T—:D칡5] ÙÔí–œrLR WÆCSh|÷•,µ�963Ç®;=ÓË1·ï©$“¹_`4�ñ{»ºžj×g߯®o»C6–E®ÚF£�iõ,'7Ø�œò&l”rP­tðÎÔå•|´èƒ2ææU.P+.ò}Íf¤O•¤ì�jŒà[¨fïŠ+.R§rtO]= R/•‹Õ¢—ér‡6]'G°[…Ë?¬TŽ­\¢8à~ÎNøz¡\E3$�h¶=`¤ÖB½Žõʨ67€|–P²¶z1ç eÉ~H]OJ!&O<Æ·” þŒ3£q@Nëb(òÃf›GTC›…BʾטÑ}@©ì±¨2™œjwé—û%µW–ª¤:KT\פª$gH‹UI õÄ!cÛÙ‰w‚¹¼•s@ØÏж*ìøë>1Éb±? «jÅ\¸b,\m_¸— ³J1ù4&Iãi™�Ë4$"±BUœÑö4W(Ϋô™8žû µL|Ë�ä*#¹ÚHVÉ5F²ÒH®5’UFr�ZiÝ‘žd:¼ëÔfkª=V˜†“@dW«%ýìÍýReIr5÷#§Ž$ƒ®RÈ¢«UÃãa)�«QŸ'–Ó©Tdz¾¿±¿„‰«Æ>­Á>)´[²Ø-Eì–:@:ÉŠÝÚÆ\ ‹-òÀ’}O±¢ëU)ûIqRe?¥Ý ²ìgŒÒ³Fi�QzÎ(=o”^¥‡Å^f¯`Ù›Xö›ˆw¿c•7ªSeÚ×Ô\ Á×�ý¢Zt“ÊúMŽ(±f Yö>SЖØ#FëÊ›U÷ƒŒN.—•[,®X‹—ÔìÝP©µjöHvË;øzqðÙ/¾Ý­S=7ª õ¶éû=²Ð+‹©Wˆ \ ê5*¼Îê­¢¤£dU -©U•Z¯ÒFì§íUL� -(éÿ%×W­Q~nµ5Õ#b *k•v¢è+¦¡¤™:Î9ß-ª©«‘XÒN4,²UM䉷Í�xnUGXµ´ŽµZ­Zjé”1Hv›Zô}´g²[TÂûiž–ìj6Ë>¨N•¦*SY3–D£R�uL]œHfÜD®B)ÁeÛ”JÀZ™B–r’i)ÖÊTßzu¬+ZÌ^ÊÆö2 ´(«çueu?À$S�-B�µ˜:ù¨³6ž�ú–ÿÈ×òÛT}ƒPç�B�oWéÇ­› ÎBµU¡Ú– éFUÒ,Òͪd}�Iw¨’.^-–.4âëªáÕ—ò6÷œð¾xØ�b¶}×ÿÙw¾qŒï„ç<ÄÒ»a ²•¯³EîÝL]†,dßÁvŽƒ¬òþxŽƒÌ¸ÅÍ0¢FÚ…5éƒ�ÑÞ4w( O߬Žíc0šgzÑf•.‚©'¬o«æƼLË4Žñ’løƒ;!À$›ÍpÜýè8‰¢× q Îloïû„7Ÿr¨¯t¤unµ’š¥®Rô_K›¯•õwWñŠœö)”W£‰ûkN&ÚŸ#rMç.îB--¾ã6: "®»TóöÞã|†»úIãéÉœÉ21 ¦ŸÕàО^ç:Ÿ×yAÉn¿Æ!£Ö§+kÜAâÎQp¯Æâ~ßâ»´/+Ïëü-ÓÏ(9Cª»„®ú-¾KÜ!,ÍO[‡«ðÏ%�bDHºRf©ý:]bR¦ -ß­ -rŠJYzÏ^äŽÙ=輋4L•Å-“ºD,Nѧ֊Žq*¶•h²‚§…Z©Oc�#”3Ì1Z‹¶E@Õ)ǯ:•ªºÑ«…�$Y²šss�ÓdoB À*¹ï^uìp÷}ªPÿÊ3}ÛÕ±#bÅ^¾ûÕ±§ÄŠÂ œJEHoØM:=ºË;ÛwYÆ.×bÄ3“c+Gr\_zBØ›Vwk/mu—™u0�©ªŠú/DââUÛ�åá#­t*í±ZiimëËÖ(z@åu�-­P¨RúÝJ‘W+"â&:g«”&ÁƹڕIûqYöêú_ãúì/) ¯Gy#C•§ï‹QÎWzÖe¢ÕÙí:9ŠAÛ-ÔÁL4+ÍFiL4¥EÖÍ÷X¢ ÆŠZº ˜¾–g¥–¬å 4Û•a§`}v«û -&n¡­u³Ñ$�n˜£[†U>¨Fïg‡+oÂ�ø˜j³óHª“^;|÷²¾Y]à=ÚЭà -tY³Ò#TÝâ<7V½ˆªKÛ«Qu•éÞÛZÌ̺ÅÌ|¡[H å]Ãô‡£Ówâÿç[éÙo.1Lå «[§€6�3ͪ£×ÊuJ11�'Ëšu$6¢r_Ô¼Žnsu� §ß̳¿VÛ|³Ögƒ»¤º¾äfÚž¶ÉW2x¾[¹{9ÁÒùŠbMºŽ'8‰e,�ôWéEÌ·œÏ0Oè!§eú#jÉ#ªT·”‰‡�éCK†R¡Å·”,îQ¸¢«˜q½„Ç@¸š™*OïBz�ŠGÔEÂ=®2 -�mhŒT‰ðéÕ½‡±–þuËXj¤ƒ‹B½é ž@�÷£Z’Éé˜%Jå“êšçôk؀ʥÌ} 6º„SÕSÇVu3«Öòt=Š«Ïs3»•.àüix«ô �8Ò -׬t*ôoõ=K±7±C�=-ŽÞ8®¤Éšf½€Î&×aWóÐj¥r�ZéÐ÷.“…N>½ÊR¥ö�ûR^¥ý€CÛuø@Y‹šö:Ž)‹U% ý®€ˆhä‹d(Þ ñtS­´µoÃ…·µï½› €8ˆ'€«‰8u ²ƒ®(³È÷œJ¥j(StgT¥¸W06ÝÞZbgÍöj®¸J5½ïtú7'A�Ÿ�S㹌à|]¼a/!¶‹Û]f‡'ÈÞ„Îê?�þµnUÔN2vôjHþ�j>›ú¿ö¾̪âJøVÝíõþz�Æ.tÓ¾  !æO‹=™¼I&‹ÉL3Ý÷™7/œ1CcLf’akQDÙºš­AE6A�µÁ%‘÷^Kã‚+¨$.qßåý眺Ûk^+fâüßÿÿòÑ÷U�ª[uêÔ©S§NU�«†h%hy ¨0´Tp¡V«áxeè Q æSd‘ýê�4(ÿÝfõÆÙa!K 2\Ñ„¶¤dSøÉݘ3#wÙ3rvy¬à?!­”‚Ð_¡„¶³Ø -eÂJ%´Y‰­DVÿÏUÔݸýó#)¶ŠÁ -ü0„–2 �. 3¶ YXÁÐŽ­ �ê�ÔØJiH‹5H÷@z¬V‡hYŒ[�Ø ˜šå¥fÅZYÜʉ­fVv‘Ž�ìpµü_8 ØâQ@îæ AÜŒÂÙßR¢�« ˆdô õú"*u»y²v7ô3ä�GW1Ò ,e!¼i)¨•î#ËÜD‡¬OÚdÍ)� øµHVÐ`&4+• ÍHËåÜ�$äßYVB±úf¥Ö³¸4ߪ„>Th ë"ñD{hI{y~*PÉ2ˆýk‡9 î)»öÜòØló¿{ÒoðEö�üó-(UȪ±µ¬þ”ºM Ÿ€9ði5t‡�®cágTîZŽý#n©FÒêY{Ä‘¨*:‚ÆÊsÀÙçK�£'dÁÙË´å ¾D&е,‰¯†ÿ�·2}4†àï$ü�‚¿Õpƒ¼ÕMI [,8ÃŽ×ÔIã½’B˵öðŒÚ©áˆü©¾F -~×W -•üO<8& ö²€×ËÁ6“JžI=s&õÖ™Tv*UžJ…R)ÈW 2}²Ãî§m†Ë+�]Lv=NR9Bu,šã¯P±%uu=ª«7¸ÑvŒþZ�t™Ð+;-å*„ÉzÜ6nGöý�Ê(µ.߯Wêÿ¨ÖÿI­ÍÁžÿ@=¼ØÙÌæðÿê|˜ösàÅÿD„^%Ië�0Ñ?¢ØØðšG§LdÕl_ÜÓ¾ñD>ž•]>Ž6"ß�êJïÒñ=¯¼/cTûOÝ S¡»´Ú> Ý­]Ë‚D€Þ£•èÝ P#J°Q -dDâJvQíwiΟڿ]$dßϽݶ€ØtRp³O7hþ®©SjX�»0Ö×ð…ayYÒiw”-·éïj’(–Ê N§%ì¢Tg -mèÑU\§|$6ª¨c»'¯æ Ÿ„5Íga�󉳹 ¢ˆ âôƒfìéôÃu©6't†ö5~È>Å·d›¯€¶6Kq4LJwG)6E•+Ù¼�¯çHTMõ ôª‘››"kýMRÒTMRiš&i¥Ò -&kjv swúº±¾CâÿЮi­¨ß¡˜Ä,¸ÖǪhW°šù+ª„Y„ì`�"ù8hú0‹ÕܬÉã)!>õÁ -(m5s¼šPðŠËc}Aض1Lj¹ž9Î÷xÅÕ%±J€mðO+¥bZi÷¦•GqZÙ˜aZy ÜäN+ù4­Åi%§•»hZÁÓ> µôy¥ç•|xùnæ­tî¡ù�jŒc�›~„‰4Ž5ÝëeHb†-¾ ḬÕ8Ž€môF¾qœÕáØÅÛÓ§¡.Én±IVV+†„ûH -ù,ëŒ.Ò¢·jx¶ª°À»MÀð¬NÒ`wÓù�cÈa‡á"§CK,¦UŽ¿Ö±^­‰¢ -d.·ÌÅš¯Êðó@™ÂnéáSŒc%÷‹J ‰÷“DÆ‹çHBᯫfB†ÝÄ_ „Å+�XHŸ -Až=L‘5íïÜÓ·ká%š8=�'Ÿbõwh$�,"XÔß©áq - Q_ØÇý^aô:ho) -aE&7']DR·AˆIpƒ{bðÏgŸÀØÃ|G0d÷†]ªÑÏ2ñ³\ü¬?+ÅO³øi?­âg•ø¹MóŽ``Ì=‚�û†]­u?‚q¥¤ÞA"¸ }•´Fà ìN˜À4i­†§'ö’‚;™Y[=íx° ø©3Ù¿éÆØAk•TÖGȼð$ð‰ +‹ðIê—}¤Ñ›ÂÈp„ŒˆuOp|1…Öˆ>ÍjŸàÊ”!Çâ‰ð‹dÚ�º‘ö5ñÖƒâ­8OÖWÌ‚e—ÿÅDmœ«S†�wÚo Ò�Á€g�Çðè‡Í9õë4›[2Ü…Ìë¶9”Ú�K¬@m÷ÍD:4pÀé\{¿ð Çc‡Äb�,9ÏÑ[xhàJ‰­ƒ"ö¯[ -pÝRà¬[ޏK„õš»néõIL}ЕôÇ\Iß ’¾w¬ -`]4íUÍ\.DýqOÔ¿‰rõqXíjz‰XÝ‹3ÉWq�oob©O »+=J}ƒa~<@ï<é,!ê68²>þ_}Jú7ðŧ|¢þ¬„¹³¾]»{±wHІߥ>xš„4Jòð{x†¡¥üZd< �hGm-íÞV»¡Ï;Ó�Xz)W÷)�½�äz�¦48®i²ûé$söÖ‹õÕzZ_­W �¢¾í-6JÖ+Nk­…÷_¤ ¼ÿ«›Ãjç FEHú1Ÿ?óâUcÏÊ 'ä …=­ä�Çë·jÑmZt»6e@D±5gX"„:µð�Yj"|ŸÆ: yucD3Æ5vvXÚáý�@«&¼ÍÒ )_ØFÑf)u4F z¨P¸HâW+`|gÕ$;µ#pLÄzwj¹ÀÖ*Â1ܦYjl»f|£1’E6F²iEie-l¬Žd�4‚mn0Ð¶Þ ¯¯†v­iå¹k�o¬‰9†&"AŠ`¨7„²/·² ‹®L�4ĺ¬Ã½z’!µãΰ‘meW¡B6+wŒ•e饿J¥,mRß|Iâùä¨k´$-h„�Å$Ä‚ò:Ci#,̬1x™—  ixgÓŠï‚u@]ÂÛ Â*Q#6W#òîÒjîר-’gM¢Yy0(ßfjc�YÐÑø—-:<’ yØçÔÖI�]¾~?îv»zBt»’?xÖZÁþV)ìë4¥{§aýfáH#»å¿€CðfÐs:6UGâä™Eë © -ñZ'¼U¿Œ×ïÖÌâð�[y”ËWòY&E¾„"³ÿúEæüõ‹ÌF…AÌ»f½ÀÒc0ÖÃ} àû6+×�WZZÑ -2R‘<܉;·Zq˜§ŠBö ÝõåWž •ÃÜ�1‚ÿ °/¹v¨¹ÇTê -¡|KÊ>…ÙG¶ò Å^>·7:ŒÃùì üåBÝ|‡”¬‚øðk„ŽsÞTœuße¾}¯¡Ã¼G+œÞŽŠjïtËú–õMøÒûžÍ:Zì?ðâ30þ¡oÂøGììý®þ€�e}ì*yAÉÛˆõâ*y…’·‘”¼� -Ä¡´O½Òç`ég¼ø|Œ§h#%ŸL óAi/¢¿S8ªky¨OßÊ¥x%¤t*w_^€/Oã¸Í…»iu5Ù¤êBXò.ÀìÓ¹ÙÑV…WsNh¡§5¼™›ÉãñèLþ#›ÍãuCk‡J±9•Ð�®úŒ½U¯¹…K¢òÜÖ ýÀ&«µœ Îy�Š)h¸¤‚µ;,œêÐBÏi¡çµš½·ShÍ}ôÊy,ö!ÒŠú�ö�Šè ¯ëc{`Ú‰>MÁ0ø ÷bðY -îƒQPšˆ>§Õ”2ŒïǤçµÉâh«Á&Ç ä-v+yØ�TOÚ“ê�òØnLy„ãÁŽ+@˜Þ¥„Þ`±»” w+¡JìneÂ=Jh�Ý£Lج„:”Øfe½J舻W™°E =¤Ä¶(¶*¡G”ØV”Á¿OŸÈÿàÖyÊ®³º<Ö�u>ê£äQ¢\_z)áœ/øØ=}uóÇIàãÔû.�ñ0¯}—¦Þw¶÷^´+¸°<6ò'}b©“ã}° � +rK¹^è$–BŽ ì“¯ÁL‘ ?J,ø÷n~ó…»|áã÷þ–н¿xÝ#¼ö�[óDEqˆ.OŠíâRÿ&àü3Ñ}IkxIÃ]¶SöfqEñ÷ñþ¥ˆý�ã«I|u„÷jgèqÎ8‰¯Ç~ϱÜxô¼îe­“`µ/ktsË=âîÞ=Hj9µ™#Ðîƒÿd�½ !�õpj`èE—ЗӤ×þ‘´ë?i’\–›û„;‘¼â�žŒž!€É“>Ò=…Xá®24ÇR,õ*:&�„?ÁÑôz5«¯}U‹G;mÃ* O=·Ê™ü3O ´XÜ‹¦ÅgI3Æ3|Gù`ÜŸ…*�žÏq à—ˆù©IOD;í}V áÅëX’#Ÿ†nd••°¶P±…ùó?éZK[?‰ú ¶Ð:k¦Þ…{¿‰úÑ[ðâ\h–N9gë4Sˆ)T´™ -ZÆ^ñê{ë{ÕWßã´O‘®y¾î¿w==n(´äbÜ#ð ¿7PSƾ¤áG§jŸÄòÞ¤Áw=Vx‚ÛAŸ³GÒ ]&Ûüÿ|L �Ò`b¤ÃÄ@8éÂ�çâ±Tý[Èšz/w3÷=-ü¾Æë!ç-2¶ïm®*zîîê0M ¦tÀs¼\÷4¯}$ò žÞœƒP:˜¡‰34ñ`†&Ì�º`ìNˆ Z“ý›p7ì·G5 æ´ðm2ÇMó'Ŧyýxy29�Á†r<ü,—bth—=ô!qDt‡2î-·vHLšægÉ�ÓåÀ3l6¿‰N±1qà®èš>�f¯c´í -ÓÓ“¯Eÿ‹¸ÝDT„& /\Ï®Ñh—.žN�Â~âé=O¥B<Ù]ä ©÷ýBjn&!õÌg -©þ:BêŸ�ú�„TÿLBê)îI¨�\ õqš„†ê lÛÇ> õ‰'1^D‰ñ)Åé„ÔK¼æZÞŸqLPñúOµúbÚ±~‰ ÝèE,0Eb¦X¼” ]ãDøMÎð@ÛÔTµ¿wëiËüÚ¥‰wFÏhÑK”àBÂŽCžd´‹‘™0¥a0œÒÈœao¥¿D'4÷ˆ­ô©2Ök#›€×Ñf)£q«Ä†‰;ÒñdÍk¤ýM§DºU+t�"…ÊyBÀ"gÈh# - tFênÛéŽ]ó¦¢áÙ„Áj¦èè°I �¾ ’èâ úXn“Œ4¬‰§ƒ -ƒm Θ¿ˆòû øš}þ@´øÑT -ƒ†Ôp•´™²k¸¡t¨a–Œw†Ø¾´ê¦êµSu©fš.Õ¿¢Ø.µp-\3]g5¯)Ø×³©k®‹GïC †ŽÞ„·¡C_o9è^V…op©!Á¨ë.öu]‚üXõ÷úûþJÒßKë·}¢ßæÈΚi†îj}Ã�=O!7Ý(ûNަš¹r÷�þ›`1 éጋk/–¦\Ü•¤�†Vž¬«6Xum5oXË“ @!Y78Y;˜5ÿìÂÙ…�¬)MI…­=·Ân–�ó‘MYNqü»úk8v‡âEÙº ‰û{\½OæO¤’öw‚œ©‡géä,éVÝuð4á^û@²ÃΟòÁõ³õð§œîPÔM‘+Q{ÃsQSdD‹dtˆu¬[©ôþ?HRý½®:Ý)Ö~f©¢3 !º–èF]™ºe;ª)usu€×ÎÕyø&]¶3“4·]�-Ñ×cuóôêãÑyúþjá>pžŽS‚ÁpÃQi7 ½„ñË,îÔ»;ºc`¯€…ÞoÝæLãÑù:ýܬ§7@ Üæ¤eËÐÊ^¨SS–ê¢ º¬»Lo¶cö�]§ÁËÿ‚߆ýX¯x»÷2\ �‡xmÒ9~O.� )qY¸ šÚ*câµï�`B~ŸGO³ÂÙ8Þßçõ[Š~-î`d:u)u’fÙ~] N<-Zw¯“«ö^Æ -AqD[&Û™S4FAÔéV-�’ƒÛîå²÷r«ØõE½Ð§ŒçàQ ž EËNÇ#–Ñ[t›å}äŒqXIŒ¢¹ëØÂx»Y·�`_�HÕOåvZÍ,… ÖÅñ -„V—™Mʉzý(lâ"Ù>ê§“' ,!íî±ð-Dw�ouÉÑÒ•@]‰ ±/!c3Äç²6%m‘¸Ã -J»ð+¥Àl]bƒ¤EºÄïeÒ<Ý<ÎÑ%e7—nÕ%µTºM—´Òb]Òã²t».6si1²YÎ-ÌÛŸ;( 6k¼VvX†Î¢ÿŒáÅurãwP®=(KvΉg…•ɨZ£×ü^fE‰F¥è2«)e�• “BjpÁ0ÀâNšh¾•�2íÝ($¤…A �XJÂ+ê5b—ìî¼Nd%öM?Á6XÄ¥Ô¦]Ô&ò¹KæöKŽ�¹ÓmÔÆ´F¹íX -íØ%KËäï.wµ–ežÖ2&æwQâ®�ñX'¬�'lSŒqƒ¦Z¶¡æ²’´™q–(ìu3äxÝL¹v¦,ÅfÉ6lºk’m‡MS�ÄH•fâÚŸ ªa{äMØZZÝ>5t—^»O¥yÞĘ ´˜-õA‘á÷v|&ã5ñýV�÷lØ,&Øo¢0ÅîÒ�cLâs8ÛEšóVV«Ý˦˜Ã¾˜Œ@Ñ9ηsdçÄÉ™Ê>™�½é~@v7Ýï×%[T“¡ãû§ôÓ:š:òvë«–öè‡ö> Krµ´W—”jiŸ.©ª´_—4U: Kº*Ô¥€*Ò¥,UêÐ¥lU:¬K9ªtD—rUéA]Ê«–—5Žê}ú¨QšÝy«Ê•3$‚h7à!]ìÕìÝ sœ¼WºÅõö¢ó…Ï#èhîå-ô»‡7|Õäà÷mÏ�™w{Yí´õë^˜SVËä`À.iŸ< ä¼&Žª‡ã,Qì>ÇlGx8j÷¸8¸™�¼>@Ô´@N‹ì ¹~�‡>¤¬ºšÞ<ÀkÒ»;뎺9ýíÝÇÑælwõDfw”]®^Aß0Ø¢“7%±ß`›îV(egRÂ6¼ßax¿Sø^¾’]~J9­ Ã!†ÿ=0|©ôà÷Ý\z^•ŽÃÃHРÝqàø‡t),T“ž ®^íûôÐ ö±[sX©”� ±ú§h®©+u4ˆkZkJñ“, Áuä9Ayð;-¢dh žAL²ç€s æÜšZ$v$¸hhRÇOT>Ù³¹ù)×ÜÜéi¿—€~¸ u¿>]ûiÙ=X|õËgd<K_è€%Êczý1½}1$*3Ôª_�å\E½Yö$›86¡5›Ú�‘ ‰Réå‹2¿ì†ƒ¾po|MÃIÀʘÓ_U¦y¬¦{Á€ô¸2’-H”‹$‘a)bÈÿ@¢±J|bi­†’w…$Á¸±”¢<4' ïùB_᎑€ -®S¾•í‹2~˜s>‰š¤\›”¥XBvïó<&ãWJKðÐ~©ô˜œælõ5Ý9èÒ X<&G“šm®:.‹c�& T�§Á„IÊ�“í�>!ÛÞ<^¢�©VælMu+½#CIjDX…‡^t¯3«¢˜¾bàƒ8ç[2¹_­@‚T )ÒÐ%ƒIåÊkI;c/Ëè1öÛÆÇdqÙ_ì”ÃOè´Ð'½™êI1S=ik¡ZŸþTèi¿ì÷Kovƒs`¥ëþ’”–CjýSú,Ñ‘�´àöÅ×Êq÷û|Ofš*{@ =v bå}.MPÓéte©ƒ˜ÔŽa"«íš³?Ê6sG—(‹…gÇB¬ýúkéC›¤ÛÛP:«WfG -•‰QŽ2ñª«L<ë)£ñÈ:–ögY½Œ±7G¹›„u…ø(ÂG1>JðQ -sWYU¤WU¤wU伪HŸªHߪH¿ªHyU¤UäüªHEU䂪ȀªÈÀªˆQT\©¬ŠTUE†TEª«"VEBU³*2´*2¬*2¼*òµªÈ(÷"ø»þFÂà¹þ.…¿Ñ èéüNÞ2^ÿœn–„ÞÐÃ{49 ‚ }^7KC;BýÞJðShídµë6@*£“ õ;ô\“§ê¬Y†wLŽòá�FKwf¢uwf¢¡3“^C•ËÌÞ@Aó?¬ÂÒ 0`~³çMŠ”™ã æ7A-°²¬¢ŽÑ“#½( 0 -d Æ CphXÐb‡‡ZUT…i ¶L Ç@ËäêÈ׬�SeTчœc­áÖP'1 ¢-íÆ�ë@–2¯(ýé™T�Ý5Îë.³Èë.ó[^w™_÷ºËü_^w™ßöºË¬ù?Þ]€fOÝeù» ðþò» åë. gZw�ówл+@ÝeŒsº«Øé®bCnëm^iZ'WWGF cèQm˜Š>Ó†6OždŽ·Š;F¼ír«Çp1”´7%]2©:r‘Uv8r±u a fÚ’(LhÁ‘“"#ƒßÅ:‚ëBodzöAl¹Ëi[É=˜c�˜Ë­D˜y!~ðݼÐʾÌÊyÉÆ>Y¹Vö˜®<<8Ò‚y¼÷ºT*x -2_e]ÜS*pŸ4k¡µ#q‚Eü¼ê‹¿”ê©¶ÿ‰ŠÐ ]1æ€ -A°ê¡�O� äzpú<+™%^,�%wI¥UbçÑ‹%þK¬Q‡«A+ -Üh\b(k@Ub‘KƒñÕBóo°™¥ÐÌÑ¢™¥v3Gÿ5š9Ú-šyàRëRkdÙM€Ð%FÁºÈ%з„¦Ó¿…ˆZvoZGéˆ9ý¥W$z ;©ì›g°?¿QŒný -=+üRÌ*›É3Çâ$œ�“ðwpþÛ¯&á¯&á¯&áÿáIø»_MÂ_MÂ_MÂÿŸNÂù&z¶ -¾š„¿š„¿š„¿š„¿š„¿š„¿š„ÿ‡'áaLGÓµRºâtJØÔÑh­–6A^)ˆ’kÖ) ~mðŒbmû!Pö×@¨Ì*„Ú€âaȘÁAõKªXÙC•ÃP�Ð#T�/I¯ËŽƒê×dÏAõrºƒê1å±§p£îm9kc'**f°¿Ê€�<|äã£àóöí#eøè…�Þø8}ðÑýðQŽ�þø8ø¸ )ão–•-> *"ø}·²êjîWX#¥ÌÐVf¶ù@�ø:›Pµw4³ñóºQ˜û ¨²Z›ké‡�ÕðPH¾•gä˜�*€ñ�gÈë 1(ææ+ÿr+?—�ÎÙƒ¥¯À¤Àã$V>+—n«’•_ //ÄÒ -ÆXùVnéiÓJÑ0]�+: ÏåëB—$û–H’Ò[’¾É¤.=È¥'e)ø††y\Á"м ËÀG¿µØ)>V«F6ŽÍ¥3Jùí�ÐWИ#V®p"o庻s Á”Ã#­Â1€fZù½^F5¢ÑÊ'äA¢t`SZ£sµ…8º Pß(°òJ[¡ý0E9;€V!4Ü€†ZƯþS@< ¯�àš´| ŒºCºgèÝ-CþBê€ÜÒ ¬‹Ío ;›Š B"†¥¸= j¨PéµÃÛ0Ó0µÄêÕ-µеJ­ÞÝÀ¥P¼Ô_:ߪè–z>`åµf²¿5c 5*¢5ÈšE?W¯í’wŒ<|�1���`��·7æ•3å½ðƒ1EâÿáG< ˆ�KC\þ‹û¹·†©;D«: ¶6SÇíÝdêÑÎ Y©—‚"t´=b[~îØöJöå-ÏÄ&}€ö‚W€UŠ :¬„jE�¨^Ð#ªÎÕŠ4T/ ¼2 – €Å{1ÕŸúFL×'©àOÕ/2]Þ*Iß`Ò³LÚÏ¥àùê¹ÍI'ÿâ9ÉE{‹ ÃZ)¸Jéyú �wòK›|\TùQ­T?�¿Àôrò¯9½dä€[ýøÅ -ÒÝŽçì(yN bˆ‹%u@î»?•â›R©©„âxAù@é]¹¶šÇ^“3}°)¸‚j�ø…çCÕẻF?€WOÊä™*|³b»ÝZ ìËó‰/üiOÍjgw3jØ;Ô°�©asù¹7ìíÿÓ £[/»4C)Èõ³Þ™žR=%LQz Ñ{ì#?�>A¯wÙÜëH(9ž—K.‡,9©4åXÄ=§C�qã|¬ -¼#�U“ÄåiCY ø”Ú¾ ºÊ�Ö¬ÙPZ' 'ïÊ‹&]˃Íäòa¢Jþ·mn„]À&‘„U¯qC¨xo’p±{­EÍxÍñm!7‹ËÓ¯"@1È—i˃­‹¾§‡ß'g;¤%®t›-.[�æIbh`;J�“W¾ß½�mH½ -s¦¾¹Ùí›ßÌqìí`¯�Ò‡ºÄJ‘Ç×�uI(}¢Kê -_ mnpƒÈ z§ÍŽDQxg?íÌqàR¯*ê�t›+~âp….PR}¬àp�j(kìÞwR¡Þ´ {ˆ0�–f`…ùg>�Fm—wÉÈ -úÙ¬p†XB(Á„­•"[èЭ -2Dëtü ºÛÎiÐý¤û Ë@^åóÈ«üämøü‘6ƒÏ>÷‘6UÁ©pñ¤U§�´Ý=Œ´±éH+}Í<Ìþ&ã0Ë0ÆÜæ]Ÿ=´.9{hU§ V§7i y”þ^g>œ¡3ÿùcåþ ÿ‚ceuéì Ž•/:P¢ç4Pz –úʼnµàs9ÿIÖÅΙó§“Hyù3Èä6õj*µç�±_G”ý�7vÏÈëâÑ©ÊÐzZãÑ@À`›HIaÊ4'¥ RmÍ"iŠIÓ�¤™Hõ¶æ¨óŸ¨S÷¹ÔéýûQGöSçc¢Î ¢Å™Ï …Ã,Š-XeàUÌ!~~QÓùEõñW‚_?¿(Ä/ª�_.ëÆ/˜ yÅùµ)¦8N z ÑÎ $ú¯Ï%Ñ÷žc§ˆDêÙ$ÖQˆu`´5ýwYç•ÿwXg¦‚ªöAòqwÆA4%ÐZ�OjÕú"X1ã§ú²âÕÇ … »Ɇ©J€˜x  º¨!Ÿ “ªIuŒ‹1„Ÿ½V\§7¯£Ó›9Šãq"e{œ¸¼<–DÕ� -~­2?>|Â}Šð_s}RFQYYÂÐmè5ùAçù ®ûyÂ`¹èk„5«¿OID§¦ èJ«õK•DÍn¼3ÞU¿S))Iv*âó3;€@zÍílÌŽ=�Û+bö@>Þ™ÄX'$Ò/Mp�øímEeŽMqjfЉ‚º©�xÍÔ èOFC#«–DMÂgcU�Ô†ñâÃwø5űBÎW<+äB%Ý -9¶3ofæö£!S(Ž‹!«tF§&C;aÌv\~@î4† ½%i.dˆ—‡àRc£Ð 3S¾¤e÷[˜¹ˆ™·2ó6f.fæíÌ\ÂÌ;˜y'3—2s3—3s3W2³™™-Ìleæ*f®ff3×0s-3×1s=370³�™™¹‰™w1ónfÞÃÌÍ̼—™[˜¹•™Û˜¹�™;˜yßgµÉÜÉü�z  r*އ[-}$v0Cž­Dž½È(´4ûÜ.°�neè -«ÙÅŒ¡çXO= 0) { - // Convert base64 to raw binary data held in a string: - byteString = atob(dataURI.split(',')[1]); - } else { - // Convert base64/URLEncoded data component to raw binary data: - byteString = decodeURIComponent(dataURI.split(',')[1]); - } - // Write the bytes of the string to an ArrayBuffer: - arrayBuffer = new ArrayBuffer(byteString.length); - intArray = new Uint8Array(arrayBuffer); - for (i = 0; i < byteString.length; i += 1) { - intArray[i] = byteString.charCodeAt(i); - } - // Separate out the mime component: - mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; - // Write the ArrayBuffer (or ArrayBufferView) to a blob: - if (hasBlobConstructor) { - return new Blob( - [hasArrayBufferViewSupport ? intArray : arrayBuffer], - {type: mimeString} - ); - } - bb = new BlobBuilder(); - bb.append(arrayBuffer); - return bb.getBlob(mimeString); - }; - if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) { - if (CanvasPrototype.mozGetAsFile) { - CanvasPrototype.toBlob = function (callback, type, quality) { - if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) { - callback(dataURLtoBlob(this.toDataURL(type, quality))); - } else { - callback(this.mozGetAsFile('blob', type)); - } - }; - } else if (CanvasPrototype.toDataURL && dataURLtoBlob) { - CanvasPrototype.toBlob = function (callback, type, quality) { - callback(dataURLtoBlob(this.toDataURL(type, quality))); - }; - } - } - window.dataURLtoBlob = dataURLtoBlob; -})(window); - -/*jslint evil: true */ -/*global window, URL, webkitURL, ActiveXObject */ - -(function (window, undef){ - 'use strict'; - - var - gid = 1, - noop = function (){}, - - document = window.document, - doctype = document.doctype || {}, - userAgent = window.navigator.userAgent, - safari = /safari\//i.test(userAgent) && !/chrome\//i.test(userAgent), - iemobile = /iemobile\//i.test(userAgent), - - // https://github.com/blueimp/JavaScript-Load-Image/blob/master/load-image.js#L48 - apiURL = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL), - - Blob = window.Blob, - File = window.File, - FileReader = window.FileReader, - FormData = window.FormData, - - - XMLHttpRequest = window.XMLHttpRequest, - jQuery = window.jQuery, - - html5 = !!(File && (FileReader && (window.Uint8Array || FormData || XMLHttpRequest.prototype.sendAsBinary))) - && !(safari && /windows/i.test(userAgent) && !iemobile), // BugFix: https://github.com/mailru/FileAPI/issues/25 - - cors = html5 && ('withCredentials' in (new XMLHttpRequest)), - - chunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice), - - normalize = ('' + ''.normalize).indexOf('[native code]') > 0, - - // https://github.com/blueimp/JavaScript-Canvas-to-Blob - dataURLtoBlob = window.dataURLtoBlob, - - - _rimg = /img/i, - _rcanvas = /canvas/i, - _rimgcanvas = /img|canvas/i, - _rinput = /input/i, - _rdata = /^data:[^,]+,/, - - _toString = {}.toString, - _supportConsoleLog, - _supportConsoleLogApply, - - - Math = window.Math, - - _SIZE_CONST = function (pow){ - pow = new window.Number(Math.pow(1024, pow)); - pow.from = function (sz){ return Math.round(sz * this); }; - return pow; - }, - - _elEvents = {}, // element event listeners - _infoReader = [], // list of file info processors - - _readerEvents = 'abort progress error load loadend', - _xhrPropsExport = 'status statusText readyState response responseXML responseText responseBody'.split(' '), - - currentTarget = 'currentTarget', // for minimize - preventDefault = 'preventDefault', // and this too - - _isArray = function (ar) { - return ar && ('length' in ar); - }, - - /** - * Iterate over a object or array - */ - _each = function (obj, fn, ctx){ - if( obj ){ - if( _isArray(obj) ){ - for( var i = 0, n = obj.length; i < n; i++ ){ - if( i in obj ){ - fn.call(ctx, obj[i], i, obj); - } - } - } - else { - for( var key in obj ){ - if( obj.hasOwnProperty(key) ){ - fn.call(ctx, obj[key], key, obj); - } - } - } - } - }, - - /** - * Merge the contents of two or more objects together into the first object - */ - _extend = function (dst){ - var args = arguments, i = 1, _ext = function (val, key){ dst[key] = val; }; - for( ; i < args.length; i++ ){ - _each(args[i], _ext); - } - return dst; - }, - - /** - * Add event listener - */ - _on = function (el, type, fn){ - if( el ){ - var uid = api.uid(el); - - if( !_elEvents[uid] ){ - _elEvents[uid] = {}; - } - - var isFileReader = (FileReader && el) && (el instanceof FileReader); - _each(type.split(/\s+/), function (type){ - if( jQuery && !isFileReader){ - jQuery.event.add(el, type, fn); - } else { - if( !_elEvents[uid][type] ){ - _elEvents[uid][type] = []; - } - - _elEvents[uid][type].push(fn); - - if( el.addEventListener ){ el.addEventListener(type, fn, false); } - else if( el.attachEvent ){ el.attachEvent('on'+type, fn); } - else { el['on'+type] = fn; } - } - }); - } - }, - - - /** - * Remove event listener - */ - _off = function (el, type, fn){ - if( el ){ - var uid = api.uid(el), events = _elEvents[uid] || {}; - - var isFileReader = (FileReader && el) && (el instanceof FileReader); - _each(type.split(/\s+/), function (type){ - if( jQuery && !isFileReader){ - jQuery.event.remove(el, type, fn); - } - else { - var fns = events[type] || [], i = fns.length; - - while( i-- ){ - if( fns[i] === fn ){ - fns.splice(i, 1); - break; - } - } - - if( el.addEventListener ){ el.removeEventListener(type, fn, false); } - else if( el.detachEvent ){ el.detachEvent('on'+type, fn); } - else { el['on'+type] = null; } - } - }); - } - }, - - - _one = function(el, type, fn){ - _on(el, type, function _(evt){ - _off(el, type, _); - fn(evt); - }); - }, - - - _fixEvent = function (evt){ - if( !evt.target ){ evt.target = window.event && window.event.srcElement || document; } - if( evt.target.nodeType === 3 ){ evt.target = evt.target.parentNode; } - return evt; - }, - - - _supportInputAttr = function (attr){ - var input = document.createElement('input'); - input.setAttribute('type', "file"); - return attr in input; - }, - - - /** - * FileAPI (core object) - */ - api = { - version: '2.0.19', - - cors: false, - html5: true, - media: false, - formData: true, - multiPassResize: true, - - debug: false, - pingUrl: false, - multiFlash: false, - flashAbortTimeout: 0, - withCredentials: true, - - staticPath: './dist/', - - flashUrl: 0, // @default: './FileAPI.flash.swf' - flashImageUrl: 0, // @default: './FileAPI.flash.image.swf' - - postNameConcat: function (name, idx){ - return name + (idx != null ? '['+ idx +']' : ''); - }, - - ext2mime: { - jpg: 'image/jpeg' - , tif: 'image/tiff' - , txt: 'text/plain' - }, - - // Fallback for flash - accept: { - 'image/*': 'art bm bmp dwg dxf cbr cbz fif fpx gif ico iefs jfif jpe jpeg jpg jps jut mcf nap nif pbm pcx pgm pict pm png pnm qif qtif ras rast rf rp svf tga tif tiff xbm xbm xpm xwd' - , 'audio/*': 'm4a flac aac rm mpa wav wma ogg mp3 mp2 m3u mod amf dmf dsm far gdm imf it m15 med okt s3m stm sfx ult uni xm sid ac3 dts cue aif aiff wpl ape mac mpc mpp shn wv nsf spc gym adplug adx dsp adp ymf ast afc hps xs' - , 'video/*': 'm4v 3gp nsv ts ty strm rm rmvb m3u ifo mov qt divx xvid bivx vob nrg img iso pva wmv asf asx ogm m2v avi bin dat dvr-ms mpg mpeg mp4 mkv avc vp3 svq3 nuv viv dv fli flv wpl' - }, - - uploadRetry : 0, - networkDownRetryTimeout : 5000, // milliseconds, don't flood when network is down - - chunkSize : 0, - chunkUploadRetry : 0, - chunkNetworkDownRetryTimeout : 2000, // milliseconds, don't flood when network is down - - KB: _SIZE_CONST(1), - MB: _SIZE_CONST(2), - GB: _SIZE_CONST(3), - TB: _SIZE_CONST(4), - - EMPTY_PNG: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII=', - - expando: 'fileapi' + (new Date).getTime(), - - uid: function (obj){ - return obj - ? (obj[api.expando] = obj[api.expando] || api.uid()) - : (++gid, api.expando + gid) - ; - }, - - log: function (){ - if( api.debug && _supportConsoleLog ){ - if( _supportConsoleLogApply ){ - console.log.apply(console, arguments); - } - else { - console.log([].join.call(arguments, ' ')); - } - } - }, - - /** - * Create new image - * - * @param {String} [src] - * @param {Function} [fn] 1. error -- boolean, 2. img -- Image element - * @returns {HTMLElement} - */ - newImage: function (src, fn){ - var img = document.createElement('img'); - if( fn ){ - api.event.one(img, 'error load', function (evt){ - fn(evt.type == 'error', img); - img = null; - }); - } - img.src = src; - return img; - }, - - /** - * Get XHR - * @returns {XMLHttpRequest} - */ - getXHR: function (){ - var xhr; - - if( XMLHttpRequest ){ - xhr = new XMLHttpRequest; - } - else if( window.ActiveXObject ){ - try { - xhr = new ActiveXObject('MSXML2.XMLHttp.3.0'); - } catch (e) { - xhr = new ActiveXObject('Microsoft.XMLHTTP'); - } - } - - return xhr; - }, - - isArray: _isArray, - - support: { - dnd: cors && ('ondrop' in document.createElement('div')), - cors: cors, - html5: html5, - chunked: chunked, - dataURI: true, - accept: _supportInputAttr('accept'), - multiple: _supportInputAttr('multiple') - }, - - event: { - on: _on - , off: _off - , one: _one - , fix: _fixEvent - }, - - - throttle: function(fn, delay) { - var id, args; - - return function _throttle(){ - args = arguments; - - if( !id ){ - fn.apply(window, args); - id = setTimeout(function (){ - id = 0; - fn.apply(window, args); - }, delay); - } - }; - }, - - - F: function (){}, - - - parseJSON: function (str){ - var json; - if( window.JSON && JSON.parse ){ - json = JSON.parse(str); - } - else { - json = (new Function('return ('+str.replace(/([\r\n])/g, '\\$1')+');'))(); - } - return json; - }, - - - trim: function (str){ - str = String(str); - return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); - }, - - /** - * Simple Defer - * @return {Object} - */ - defer: function (){ - var - list = [] - , result - , error - , defer = { - resolve: function (err, res){ - defer.resolve = noop; - error = err || false; - result = res; - - while( res = list.shift() ){ - res(error, result); - } - }, - - then: function (fn){ - if( error !== undef ){ - fn(error, result); - } else { - list.push(fn); - } - } - }; - - return defer; - }, - - queue: function (fn){ - var - _idx = 0 - , _length = 0 - , _fail = false - , _end = false - , queue = { - inc: function (){ - _length++; - }, - - next: function (){ - _idx++; - setTimeout(queue.check, 0); - }, - - check: function (){ - (_idx >= _length) && !_fail && queue.end(); - }, - - isFail: function (){ - return _fail; - }, - - fail: function (){ - !_fail && fn(_fail = true); - }, - - end: function (){ - if( !_end ){ - _end = true; - fn(); - } - } - } - ; - return queue; - }, - - - /** - * For each object - * - * @param {Object|Array} obj - * @param {Function} fn - * @param {*} [ctx] - */ - each: _each, - - - /** - * Async for - * @param {Array} array - * @param {Function} callback - */ - afor: function (array, callback){ - var i = 0, n = array.length; - - if( _isArray(array) && n-- ){ - (function _next(){ - callback(n != i && _next, array[i], i++); - })(); - } - else { - callback(false); - } - }, - - - /** - * Merge the contents of two or more objects together into the first object - * - * @param {Object} dst - * @return {Object} - */ - extend: _extend, - - - /** - * Is file? - * @param {File} file - * @return {Boolean} - */ - isFile: function (file){ - return _toString.call(file) === '[object File]'; - }, - - - /** - * Is blob? - * @param {Blob} blob - * @returns {Boolean} - */ - isBlob: function (blob) { - return this.isFile(blob) || (_toString.call(blob) === '[object Blob]'); - }, - - - /** - * Is canvas element - * - * @param {HTMLElement} el - * @return {Boolean} - */ - isCanvas: function (el){ - return el && _rcanvas.test(el.nodeName); - }, - - - getFilesFilter: function (filter){ - filter = typeof filter == 'string' ? filter : (filter.getAttribute && filter.getAttribute('accept') || ''); - return filter ? new RegExp('('+ filter.replace(/\./g, '\\.').replace(/,/g, '|') +')$', 'i') : /./; - }, - - - - /** - * Read as DataURL - * - * @param {File|Element} file - * @param {Function} fn - */ - readAsDataURL: function (file, fn){ - if( api.isCanvas(file) ){ - _emit(file, fn, 'load', api.toDataURL(file)); - } - else { - _readAs(file, fn, 'DataURL'); - } - }, - - - /** - * Read as Binary string - * - * @param {File} file - * @param {Function} fn - */ - readAsBinaryString: function (file, fn){ - if( _hasSupportReadAs('BinaryString') ){ - _readAs(file, fn, 'BinaryString'); - } else { - // Hello IE10! - _readAs(file, function (evt){ - if( evt.type == 'load' ){ - try { - // dataURL -> binaryString - evt.result = api.toBinaryString(evt.result); - } catch (e){ - evt.type = 'error'; - evt.message = e.toString(); - } - } - fn(evt); - }, 'DataURL'); - } - }, - - - /** - * Read as ArrayBuffer - * - * @param {File} file - * @param {Function} fn - */ - readAsArrayBuffer: function(file, fn){ - _readAs(file, fn, 'ArrayBuffer'); - }, - - - /** - * Read as text - * - * @param {File} file - * @param {String} encoding - * @param {Function} [fn] - */ - readAsText: function(file, encoding, fn){ - if( !fn ){ - fn = encoding; - encoding = 'utf-8'; - } - - _readAs(file, fn, 'Text', encoding); - }, - - - /** - * Convert image or canvas to DataURL - * - * @param {Element} el Image or Canvas element - * @param {String} [type] mime-type - * @return {String} - */ - toDataURL: function (el, type){ - if( typeof el == 'string' ){ - return el; - } - else if( el.toDataURL ){ - return el.toDataURL(type || 'image/png'); - } - }, - - - /** - * Canvert string, image or canvas to binary string - * - * @param {String|Element} val - * @return {String} - */ - toBinaryString: function (val){ - return window.atob(api.toDataURL(val).replace(_rdata, '')); - }, - - - /** - * Read file or DataURL as ImageElement - * - * @param {File|String} file - * @param {Function} fn - * @param {Boolean} [progress] - */ - readAsImage: function (file, fn, progress){ - if( api.isBlob(file) ){ - if( apiURL ){ - /** @namespace apiURL.createObjectURL */ - var data = apiURL.createObjectURL(file); - if( data === undef ){ - _emit(file, fn, 'error'); - } - else { - api.readAsImage(data, fn, progress); - } - } - else { - api.readAsDataURL(file, function (evt){ - if( evt.type == 'load' ){ - api.readAsImage(evt.result, fn, progress); - } - else if( progress || evt.type == 'error' ){ - _emit(file, fn, evt, null, { loaded: evt.loaded, total: evt.total }); - } - }); - } - } - else if( api.isCanvas(file) ){ - _emit(file, fn, 'load', file); - } - else if( _rimg.test(file.nodeName) ){ - if( file.complete ){ - _emit(file, fn, 'load', file); - } - else { - var events = 'error abort load'; - _one(file, events, function _fn(evt){ - if( evt.type == 'load' && apiURL ){ - /** @namespace apiURL.revokeObjectURL */ - apiURL.revokeObjectURL(file.src); - } - - _off(file, events, _fn); - _emit(file, fn, evt, file); - }); - } - } - else if( file.iframe ){ - _emit(file, fn, { type: 'error' }); - } - else { - // Created image - var img = api.newImage(file.dataURL || file); - api.readAsImage(img, fn, progress); - } - }, - - - /** - * Make file by name - * - * @param {String} name - * @return {Array} - */ - checkFileObj: function (name){ - var file = {}, accept = api.accept; - - if( typeof name == 'object' ){ - file = name; - } - else { - file.name = (name + '').split(/\\|\//g).pop(); - } - - if( file.type == null ){ - file.type = file.name.split('.').pop(); - } - - _each(accept, function (ext, type){ - ext = new RegExp(ext.replace(/\s/g, '|'), 'i'); - if( ext.test(file.type) || api.ext2mime[file.type] ){ - file.type = api.ext2mime[file.type] || (type.split('/')[0] +'/'+ file.type); - } - }); - - return file; - }, - - - /** - * Get drop files - * - * @param {Event} evt - * @param {Function} callback - */ - getDropFiles: function (evt, callback){ - var - files = [] - , all = [] - , items - , dataTransfer = _getDataTransfer(evt) - , transFiles = dataTransfer.files - , transItems = dataTransfer.items - , entrySupport = _isArray(transItems) && transItems[0] && _getAsEntry(transItems[0]) - , queue = api.queue(function (){ callback(files, all); }) - ; - - if( entrySupport ){ - if( normalize && transFiles ){ - var - i = transFiles.length - , file - , entry - ; - - items = new Array(i); - while( i-- ){ - file = transFiles[i]; - - try { - entry = _getAsEntry(transItems[i]); - } - catch( err ){ - api.log('[err] getDropFiles: ', err); - entry = null; - } - - if( _isEntry(entry) ){ - // OSX filesystems use Unicode Normalization Form D (NFD), - // and entry.file(…) can't read the files with the same names - if( entry.isDirectory || (entry.isFile && file.name == file.name.normalize('NFC')) ){ - items[i] = entry; - } - else { - items[i] = file; - } - } - else { - items[i] = file; - } - } - } - else { - items = transItems; - } - } - else { - items = transFiles; - } - - _each(items || [], function (item){ - queue.inc(); - - try { - if( entrySupport && _isEntry(item) ){ - _readEntryAsFiles(item, function (err, entryFiles, allEntries){ - if( err ){ - api.log('[err] getDropFiles:', err); - } else { - files.push.apply(files, entryFiles); - } - all.push.apply(all, allEntries); - - queue.next(); - }); - } - else { - _isRegularFile(item, function (yes, err){ - if( yes ){ - files.push(item); - } - else { - item.error = err; - } - all.push(item); - - queue.next(); - }); - } - } - catch( err ){ - queue.next(); - api.log('[err] getDropFiles: ', err); - } - }); - - queue.check(); - }, - - - /** - * Get file list - * - * @param {HTMLInputElement|Event} input - * @param {String|Function} [filter] - * @param {Function} [callback] - * @return {Array|Null} - */ - getFiles: function (input, filter, callback){ - var files = []; - - if( callback ){ - api.filterFiles(api.getFiles(input), filter, callback); - return null; - } - - if( input.jquery ){ - // jQuery object - input.each(function (){ - files = files.concat(api.getFiles(this)); - }); - input = files; - files = []; - } - - if( typeof filter == 'string' ){ - filter = api.getFilesFilter(filter); - } - - if( input.originalEvent ){ - // jQuery event - input = _fixEvent(input.originalEvent); - } - else if( input.srcElement ){ - // IE Event - input = _fixEvent(input); - } - - - if( input.dataTransfer ){ - // Drag'n'Drop - input = input.dataTransfer; - } - else if( input.target ){ - // Event - input = input.target; - } - - if( input.files ){ - // Input[type="file"] - files = input.files; - - if( !html5 ){ - // Partial support for file api - files[0].blob = input; - files[0].iframe = true; - } - } - else if( !html5 && isInputFile(input) ){ - if( api.trim(input.value) ){ - files = [api.checkFileObj(input.value)]; - files[0].blob = input; - files[0].iframe = true; - } - } - else if( _isArray(input) ){ - files = input; - } - - return api.filter(files, function (file){ return !filter || filter.test(file.name); }); - }, - - - /** - * Get total file size - * @param {Array} files - * @return {Number} - */ - getTotalSize: function (files){ - var size = 0, i = files && files.length; - while( i-- ){ - size += files[i].size; - } - return size; - }, - - - /** - * Get image information - * - * @param {File} file - * @param {Function} fn - */ - getInfo: function (file, fn){ - var info = {}, readers = _infoReader.concat(); - - if( api.isBlob(file) ){ - (function _next(){ - var reader = readers.shift(); - if( reader ){ - if( reader.test(file.type) ){ - reader(file, function (err, res){ - if( err ){ - fn(err); - } - else { - _extend(info, res); - _next(); - } - }); - } - else { - _next(); - } - } - else { - fn(false, info); - } - })(); - } - else { - fn('not_support_info', info); - } - }, - - - /** - * Add information reader - * - * @param {RegExp} mime - * @param {Function} fn - */ - addInfoReader: function (mime, fn){ - fn.test = function (type){ return mime.test(type); }; - _infoReader.push(fn); - }, - - - /** - * Filter of array - * - * @param {Array} input - * @param {Function} fn - * @return {Array} - */ - filter: function (input, fn){ - var result = [], i = 0, n = input.length, val; - - for( ; i < n; i++ ){ - if( i in input ){ - val = input[i]; - if( fn.call(val, val, i, input) ){ - result.push(val); - } - } - } - - return result; - }, - - - /** - * Filter files - * - * @param {Array} files - * @param {Function} eachFn - * @param {Function} resultFn - */ - filterFiles: function (files, eachFn, resultFn){ - if( files.length ){ - // HTML5 or Flash - var queue = files.concat(), file, result = [], deleted = []; - - (function _next(){ - if( queue.length ){ - file = queue.shift(); - api.getInfo(file, function (err, info){ - (eachFn(file, err ? false : info) ? result : deleted).push(file); - _next(); - }); - } - else { - resultFn(result, deleted); - } - })(); - } - else { - resultFn([], files); - } - }, - - - upload: function (options){ - options = _extend({ - jsonp: 'callback' - , prepare: api.F - , beforeupload: api.F - , upload: api.F - , fileupload: api.F - , fileprogress: api.F - , filecomplete: api.F - , progress: api.F - , complete: api.F - , pause: api.F - , imageOriginal: true - , chunkSize: api.chunkSize - , chunkUploadRetry: api.chunkUploadRetry - , uploadRetry: api.uploadRetry - }, options); - - - if( options.imageAutoOrientation && !options.imageTransform ){ - options.imageTransform = { rotate: 'auto' }; - } - - - var - proxyXHR = new api.XHR(options) - , dataArray = this._getFilesDataArray(options.files) - , _this = this - , _total = 0 - , _loaded = 0 - , _nextFile - , _complete = false - ; - - - // calc total size - _each(dataArray, function (data){ - _total += data.size; - }); - - // Array of files - proxyXHR.files = []; - _each(dataArray, function (data){ - proxyXHR.files.push(data.file); - }); - - // Set upload status props - proxyXHR.total = _total; - proxyXHR.loaded = 0; - proxyXHR.filesLeft = dataArray.length; - - // emit "beforeupload" event - options.beforeupload(proxyXHR, options); - - // Upload by file - _nextFile = function (){ - var - data = dataArray.shift() - , _file = data && data.file - , _fileLoaded = false - , _fileOptions = _simpleClone(options) - ; - - proxyXHR.filesLeft = dataArray.length; - - if( _file && _file.name === api.expando ){ - _file = null; - api.log('[warn] FileAPI.upload() — called without files'); - } - - if( ( proxyXHR.statusText != 'abort' || proxyXHR.current ) && data ){ - // Mark active job - _complete = false; - - // Set current upload file - proxyXHR.currentFile = _file; - - // Prepare file options - if (_file && options.prepare(_file, _fileOptions) === false) { - _nextFile.call(_this); - return; - } - _fileOptions.file = _file; - - _this._getFormData(_fileOptions, data, function (form){ - if( !_loaded ){ - // emit "upload" event - options.upload(proxyXHR, options); - } - - var xhr = new api.XHR(_extend({}, _fileOptions, { - - upload: _file ? function (){ - // emit "fileupload" event - options.fileupload(_file, xhr, _fileOptions); - } : noop, - - progress: _file ? function (evt){ - if( !_fileLoaded ){ - // For ignore the double calls. - _fileLoaded = (evt.loaded === evt.total); - - // emit "fileprogress" event - options.fileprogress({ - type: 'progress' - , total: data.total = evt.total - , loaded: data.loaded = evt.loaded - }, _file, xhr, _fileOptions); - - // emit "progress" event - options.progress({ - type: 'progress' - , total: _total - , loaded: proxyXHR.loaded = (_loaded + data.size * (evt.loaded/evt.total)) || 0 - }, _file, xhr, _fileOptions); - } - } : noop, - - complete: function (err){ - _each(_xhrPropsExport, function (name){ - proxyXHR[name] = xhr[name]; - }); - - if( _file ){ - data.total = (data.total || data.size); - data.loaded = data.total; - - if( !err ) { - // emulate 100% "progress" - this.progress(data); - - // fixed throttle event - _fileLoaded = true; - - // bytes loaded - _loaded += data.size; // data.size != data.total, it's desirable fix this - proxyXHR.loaded = _loaded; - } - - // emit "filecomplete" event - options.filecomplete(err, xhr, _file, _fileOptions); - } - - // upload next file - setTimeout(function () {_nextFile.call(_this);}, 0); - } - })); // xhr - - - // ... - proxyXHR.abort = function (current){ - if (!current) { dataArray.length = 0; } - this.current = current; - xhr.abort(); - }; - - // Start upload - xhr.send(form); - }); - } - else { - var successful = proxyXHR.status == 200 || proxyXHR.status == 201 || proxyXHR.status == 204; - options.complete(successful ? false : (proxyXHR.statusText || 'error'), proxyXHR, options); - // Mark done state - _complete = true; - } - }; - - - // Next tick - setTimeout(_nextFile, 0); - - - // Append more files to the existing request - // first - add them to the queue head/tail - proxyXHR.append = function (files, first) { - files = api._getFilesDataArray([].concat(files)); - - _each(files, function (data) { - _total += data.size; - proxyXHR.files.push(data.file); - if (first) { - dataArray.unshift(data); - } else { - dataArray.push(data); - } - }); - - proxyXHR.statusText = ""; - - if( _complete ){ - _nextFile.call(_this); - } - }; - - - // Removes file from queue by file reference and returns it - proxyXHR.remove = function (file) { - var i = dataArray.length, _file; - while( i-- ){ - if( dataArray[i].file == file ){ - _file = dataArray.splice(i, 1); - _total -= _file.size; - } - } - return _file; - }; - - return proxyXHR; - }, - - - _getFilesDataArray: function (data){ - var files = [], oFiles = {}; - - if( isInputFile(data) ){ - var tmp = api.getFiles(data); - oFiles[data.name || 'file'] = data.getAttribute('multiple') !== null ? tmp : tmp[0]; - } - else if( _isArray(data) && isInputFile(data[0]) ){ - _each(data, function (input){ - oFiles[input.name || 'file'] = api.getFiles(input); - }); - } - else { - oFiles = data; - } - - _each(oFiles, function add(file, name){ - if( _isArray(file) ){ - _each(file, function (file){ - add(file, name); - }); - } - else if( file && (file.name || file.image) ){ - files.push({ - name: name - , file: file - , size: file.size - , total: file.size - , loaded: 0 - }); - } - }); - - if( !files.length ){ - // Create fake `file` object - files.push({ file: { name: api.expando } }); - } - - return files; - }, - - - _getFormData: function (options, data, fn){ - var - file = data.file - , name = data.name - , filename = file.name - , filetype = file.type - , trans = api.support.transform && options.imageTransform - , Form = new api.Form - , queue = api.queue(function (){ fn(Form); }) - , isOrignTrans = trans && _isOriginTransform(trans) - , postNameConcat = api.postNameConcat - ; - - // Append data - _each(options.data, function add(val, name){ - if( typeof val == 'object' ){ - _each(val, function (v, i){ - add(v, postNameConcat(name, i)); - }); - } - else { - Form.append(name, val); - } - }); - - (function _addFile(file/**Object*/){ - if( file.image ){ // This is a FileAPI.Image - queue.inc(); - - file.toData(function (err, image){ - // @todo: требует рефакторинга и обработки ошибки - if (file.file) { - image.type = file.file.type; - image.quality = file.matrix.quality; - filename = file.file && file.file.name; - } - - filename = filename || (new Date).getTime()+'.png'; - - _addFile(image); - queue.next(); - }); - } - else if( api.Image && trans && (/^image/.test(file.type) || _rimgcanvas.test(file.nodeName)) ){ - queue.inc(); - - if( isOrignTrans ){ - // Convert to array for transform function - trans = [trans]; - } - - api.Image.transform(file, trans, options.imageAutoOrientation, function (err, images){ - if( isOrignTrans && !err ){ - if( !dataURLtoBlob && !api.flashEngine ){ - // Canvas.toBlob or Flash not supported, use multipart - Form.multipart = true; - } - - Form.append(name, images[0], filename, trans[0].type || filetype); - } - else { - var addOrigin = 0; - - if( !err ){ - _each(images, function (image, idx){ - if( !dataURLtoBlob && !api.flashEngine ){ - Form.multipart = true; - } - - if( !trans[idx].postName ){ - addOrigin = 1; - } - - Form.append(trans[idx].postName || postNameConcat(name, idx), image, filename, trans[idx].type || filetype); - }); - } - - if( err || options.imageOriginal ){ - Form.append(postNameConcat(name, (addOrigin ? 'original' : null)), file, filename, filetype); - } - } - - queue.next(); - }); - } - else if( filename !== api.expando ){ - Form.append(name, file, filename); - } - })(file); - - queue.check(); - }, - - - reset: function (inp, notRemove){ - var parent, clone; - - if( jQuery ){ - clone = jQuery(inp).clone(true).insertBefore(inp).val('')[0]; - if( !notRemove ){ - jQuery(inp).remove(); - } - } else { - parent = inp.parentNode; - clone = parent.insertBefore(inp.cloneNode(true), inp); - clone.value = ''; - - if( !notRemove ){ - parent.removeChild(inp); - } - - _each(_elEvents[api.uid(inp)], function (fns, type){ - _each(fns, function (fn){ - _off(inp, type, fn); - _on(clone, type, fn); - }); - }); - } - - return clone; - }, - - - /** - * Load remote file - * - * @param {String} url - * @param {Function} fn - * @return {XMLHttpRequest} - */ - load: function (url, fn){ - var xhr = api.getXHR(); - if( xhr ){ - xhr.open('GET', url, true); - - if( xhr.overrideMimeType ){ - xhr.overrideMimeType('text/plain; charset=x-user-defined'); - } - - _on(xhr, 'progress', function (/**Event*/evt){ - /** @namespace evt.lengthComputable */ - if( evt.lengthComputable ){ - fn({ type: evt.type, loaded: evt.loaded, total: evt.total }, xhr); - } - }); - - xhr.onreadystatechange = function(){ - if( xhr.readyState == 4 ){ - xhr.onreadystatechange = null; - if( xhr.status == 200 ){ - url = url.split('/'); - /** @namespace xhr.responseBody */ - var file = { - name: url[url.length-1] - , size: xhr.getResponseHeader('Content-Length') - , type: xhr.getResponseHeader('Content-Type') - }; - file.dataURL = 'data:'+file.type+';base64,' + api.encode64(xhr.responseBody || xhr.responseText); - fn({ type: 'load', result: file }, xhr); - } - else { - fn({ type: 'error' }, xhr); - } - } - }; - xhr.send(null); - } else { - fn({ type: 'error' }); - } - - return xhr; - }, - - encode64: function (str){ - var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', outStr = '', i = 0; - - if( typeof str !== 'string' ){ - str = String(str); - } - - while( i < str.length ){ - //all three "& 0xff" added below are there to fix a known bug - //with bytes returned by xhr.responseText - var - byte1 = str.charCodeAt(i++) & 0xff - , byte2 = str.charCodeAt(i++) & 0xff - , byte3 = str.charCodeAt(i++) & 0xff - , enc1 = byte1 >> 2 - , enc2 = ((byte1 & 3) << 4) | (byte2 >> 4) - , enc3, enc4 - ; - - if( isNaN(byte2) ){ - enc3 = enc4 = 64; - } else { - enc3 = ((byte2 & 15) << 2) | (byte3 >> 6); - enc4 = isNaN(byte3) ? 64 : byte3 & 63; - } - - outStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4); - } - - return outStr; - } - - } // api - ; - - - function _emit(target, fn, name, res, ext){ - var evt = { - type: name.type || name - , target: target - , result: res - }; - _extend(evt, ext); - fn(evt); - } - - - function _hasSupportReadAs(method){ - return FileReader && !!FileReader.prototype['readAs' + method]; - } - - - function _readAs(file, fn, method, encoding){ - if( api.isBlob(file) && _hasSupportReadAs(method) ){ - var Reader = new FileReader; - - // Add event listener - _on(Reader, _readerEvents, function _fn(evt){ - var type = evt.type; - if( type == 'progress' ){ - _emit(file, fn, evt, evt.target.result, { loaded: evt.loaded, total: evt.total }); - } - else if( type == 'loadend' ){ - _off(Reader, _readerEvents, _fn); - Reader = null; - } - else { - _emit(file, fn, evt, evt.target.result); - } - }); - - - try { - // ReadAs ... - if( encoding ){ - Reader['readAs' + method](file, encoding); - } - else { - Reader['readAs' + method](file); - } - } - catch (err){ - _emit(file, fn, 'error', undef, { error: err.toString() }); - } - } - else { - _emit(file, fn, 'error', undef, { error: 'filreader_not_support_' + method }); - } - } - - - function _isRegularFile(file, callback){ - // http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects - if( !file.type && (safari || ((file.size % 4096) === 0 && (file.size <= 102400))) ){ - if( FileReader ){ - try { - var reader = new FileReader(); - - _one(reader, _readerEvents, function (evt){ - var isFile = evt.type != 'error'; - if( isFile ){ - if ( reader.readyState == null || reader.readyState === reader.LOADING ) { - reader.abort(); - } - callback(isFile); - } - else { - callback(false, reader.error); - } - }); - - reader.readAsDataURL(file); - } catch( err ){ - callback(false, err); - } - } - else { - callback(null, new Error('FileReader is not supported')); - } - } - else { - callback(true); - } - } - - - function _isEntry(item){ - return item && (item.isFile || item.isDirectory); - } - - - function _getAsEntry(item){ - var entry; - if( item.getAsEntry ){ entry = item.getAsEntry(); } - else if( item.webkitGetAsEntry ){ entry = item.webkitGetAsEntry(); } - return entry; - } - - - function _readEntryAsFiles(entry, callback){ - if( !entry ){ - // error - var err = new Error('invalid entry'); - entry = new Object(entry); - entry.error = err; - callback(err.message, [], [entry]); - } - else if( entry.isFile ){ - // Read as file - entry.file(function (file){ - // success - file.fullPath = entry.fullPath; - callback(false, [file], [file]); - }, function (err){ - // error - entry.error = err; - callback('FileError.code: ' + err.code, [], [entry]); - }); - } - else if( entry.isDirectory ){ - var - reader = entry.createReader() - , firstAttempt = true - , files = [] - , all = [entry] - ; - - var onerror = function (err){ - // error - entry.error = err; - callback('DirectoryError.code: ' + err.code, files, all); - }; - var ondone = function ondone(entries){ - if( firstAttempt ){ - firstAttempt = false; - if( !entries.length ){ - entry.error = new Error('directory is empty'); - } - } - - // success - if( entries.length ){ - api.afor(entries, function (next, entry){ - _readEntryAsFiles(entry, function (err, entryFiles, allEntries){ - if( !err ){ - files = files.concat(entryFiles); - } - all = all.concat(allEntries); - - if( next ){ - next(); - } - else { - reader.readEntries(ondone, onerror); - } - }); - }); - } - else { - callback(false, files, all); - } - }; - - reader.readEntries(ondone, onerror); - } - else { - _readEntryAsFiles(_getAsEntry(entry), callback); - } - } - - - function _simpleClone(obj){ - var copy = {}; - _each(obj, function (val, key){ - if( val && (typeof val === 'object') && (val.nodeType === void 0) ){ - val = _extend({}, val); - } - copy[key] = val; - }); - return copy; - } - - - function isInputFile(el){ - return _rinput.test(el && el.tagName); - } - - - function _getDataTransfer(evt){ - return (evt.originalEvent || evt || '').dataTransfer || {}; - } - - - function _isOriginTransform(trans){ - var key; - for( key in trans ){ - if( trans.hasOwnProperty(key) ){ - if( !(trans[key] instanceof Object || key === 'overlay' || key === 'filter') ){ - return true; - } - } - } - return false; - } - - - // Add default image info reader - api.addInfoReader(/^image/, function (file/**File*/, callback/**Function*/){ - if( !file.__dimensions ){ - var defer = file.__dimensions = api.defer(); - - api.readAsImage(file, function (evt){ - var img = evt.target; - defer.resolve(evt.type == 'load' ? false : 'error', { - width: img.width - , height: img.height - }); - img.src = api.EMPTY_PNG; - img = null; - }); - } - - file.__dimensions.then(callback); - }); - - - /** - * Drag'n'Drop special event - * - * @param {HTMLElement} el - * @param {Function} onHover - * @param {Function} onDrop - */ - api.event.dnd = function (el, onHover, onDrop){ - var _id, _type; - - if( !onDrop ){ - onDrop = onHover; - onHover = api.F; - } - - if( FileReader ){ - // Hover - _on(el, 'dragenter dragleave dragover', onHover.ff = onHover.ff || function (evt){ - var - types = _getDataTransfer(evt).types - , i = types && types.length - , debounceTrigger = false - ; - - while( i-- ){ - if( ~types[i].indexOf('File') ){ - evt[preventDefault](); - - if( _type !== evt.type ){ - _type = evt.type; // Store current type of event - - if( _type != 'dragleave' ){ - onHover.call(evt[currentTarget], true, evt); - } - - debounceTrigger = true; - } - - break; // exit from "while" - } - } - - if( debounceTrigger ){ - clearTimeout(_id); - _id = setTimeout(function (){ - onHover.call(evt[currentTarget], _type != 'dragleave', evt); - }, 50); - } - }); - - - // Drop - _on(el, 'drop', onDrop.ff = onDrop.ff || function (evt){ - evt[preventDefault](); - - _type = 0; - onHover.call(evt[currentTarget], false, evt); - - api.getDropFiles(evt, function (files, all){ - onDrop.call(evt[currentTarget], files, all, evt); - }); - }); - } - else { - api.log("Drag'n'Drop -- not supported"); - } - }; - - - /** - * Remove drag'n'drop - * @param {HTMLElement} el - * @param {Function} onHover - * @param {Function} onDrop - */ - api.event.dnd.off = function (el, onHover, onDrop){ - _off(el, 'dragenter dragleave dragover', onHover.ff); - _off(el, 'drop', onDrop.ff); - }; - - - // Support jQuery - if( jQuery && !jQuery.fn.dnd ){ - jQuery.fn.dnd = function (onHover, onDrop){ - return this.each(function (){ - api.event.dnd(this, onHover, onDrop); - }); - }; - - jQuery.fn.offdnd = function (onHover, onDrop){ - return this.each(function (){ - api.event.dnd.off(this, onHover, onDrop); - }); - }; - } - - // @export - window.FileAPI = _extend(api, window.FileAPI); - - - // Debug info - api.log('FileAPI: ' + api.version); - api.log('protocol: ' + window.location.protocol); - api.log('doctype: [' + doctype.name + '] ' + doctype.publicId + ' ' + doctype.systemId); - - - // @detect 'x-ua-compatible' - _each(document.getElementsByTagName('meta'), function (meta){ - if( /x-ua-compatible/i.test(meta.getAttribute('http-equiv')) ){ - api.log('meta.http-equiv: ' + meta.getAttribute('content')); - } - }); - - - // Configuration - try { - _supportConsoleLog = !!console.log; - _supportConsoleLogApply = !!console.log.apply; - } - catch (err) {} - - if( !api.flashUrl ){ api.flashUrl = api.staticPath + 'FileAPI.flash.swf'; } - if( !api.flashImageUrl ){ api.flashImageUrl = api.staticPath + 'FileAPI.flash.image.swf'; } - if( !api.flashWebcamUrl ){ api.flashWebcamUrl = api.staticPath + 'FileAPI.flash.camera.swf'; } -})(window, void 0); - -/*global window, FileAPI, document */ - -(function (api, document, undef) { - 'use strict'; - - var - min = Math.min, - round = Math.round, - getCanvas = function () { return document.createElement('canvas'); }, - support = false, - exifOrientation = { - 8: 270 - , 3: 180 - , 6: 90 - , 7: 270 - , 4: 180 - , 5: 90 - } - ; - - try { - support = getCanvas().toDataURL('image/png').indexOf('data:image/png') > -1; - } - catch (e){} - - - function Image(file){ - if( file instanceof Image ){ - var img = new Image(file.file); - api.extend(img.matrix, file.matrix); - return img; - } - else if( !(this instanceof Image) ){ - return new Image(file); - } - - this.file = file; - this.size = file.size || 100; - - this.matrix = { - sx: 0, - sy: 0, - sw: 0, - sh: 0, - dx: 0, - dy: 0, - dw: 0, - dh: 0, - resize: 0, // min, max OR preview - deg: 0, - quality: 1, // jpeg quality - filter: 0 - }; - } - - - Image.prototype = { - image: true, - constructor: Image, - - set: function (attrs){ - api.extend(this.matrix, attrs); - return this; - }, - - crop: function (x, y, w, h){ - if( w === undef ){ - w = x; - h = y; - x = y = 0; - } - return this.set({ sx: x, sy: y, sw: w, sh: h || w }); - }, - - resize: function (w, h, strategy){ - if( /min|max|height|width/.test(h) ){ - strategy = h; - h = w; - } - - return this.set({ dw: w, dh: h || w, resize: strategy }); - }, - - preview: function (w, h){ - return this.resize(w, h || w, 'preview'); - }, - - rotate: function (deg){ - return this.set({ deg: deg }); - }, - - filter: function (filter){ - return this.set({ filter: filter }); - }, - - overlay: function (images){ - return this.set({ overlay: images }); - }, - - clone: function (){ - return new Image(this); - }, - - _load: function (image, fn){ - var self = this; - - if( /img|video/i.test(image.nodeName) ){ - fn.call(self, null, image); - } - else { - api.readAsImage(image, function (evt){ - fn.call(self, evt.type != 'load', evt.result); - }); - } - }, - - _apply: function (image, fn){ - var - canvas = getCanvas() - , m = this.getMatrix(image) - , ctx = canvas.getContext('2d') - , width = image.videoWidth || image.width - , height = image.videoHeight || image.height - , deg = m.deg - , dw = m.dw - , dh = m.dh - , w = width - , h = height - , filter = m.filter - , copy // canvas copy - , buffer = image - , overlay = m.overlay - , queue = api.queue(function (){ image.src = api.EMPTY_PNG; fn(false, canvas); }) - , renderImageToCanvas = api.renderImageToCanvas - ; - - // Normalize angle - deg = deg - Math.floor(deg/360)*360; - - // For `renderImageToCanvas` - image._type = this.file.type; - - while(m.multipass && min(w/dw, h/dh) > 2 ){ - w = (w/2 + 0.5)|0; - h = (h/2 + 0.5)|0; - - copy = getCanvas(); - copy.width = w; - copy.height = h; - - if( buffer !== image ){ - renderImageToCanvas(copy, buffer, 0, 0, buffer.width, buffer.height, 0, 0, w, h); - buffer = copy; - } - else { - buffer = copy; - renderImageToCanvas(buffer, image, m.sx, m.sy, m.sw, m.sh, 0, 0, w, h); - m.sx = m.sy = m.sw = m.sh = 0; - } - } - - - canvas.width = (deg % 180) ? dh : dw; - canvas.height = (deg % 180) ? dw : dh; - - canvas.type = m.type; - canvas.quality = m.quality; - - ctx.rotate(deg * Math.PI / 180); - renderImageToCanvas(ctx.canvas, buffer - , m.sx, m.sy - , m.sw || buffer.width - , m.sh || buffer.height - , (deg == 180 || deg == 270 ? -dw : 0) - , (deg == 90 || deg == 180 ? -dh : 0) - , dw, dh - ); - dw = canvas.width; - dh = canvas.height; - - // Apply overlay - overlay && api.each([].concat(overlay), function (over){ - queue.inc(); - // preload - var img = new window.Image, fn = function (){ - var - x = over.x|0 - , y = over.y|0 - , w = over.w || img.width - , h = over.h || img.height - , rel = over.rel - ; - - // center | right | left - x = (rel == 1 || rel == 4 || rel == 7) ? (dw - w + x)/2 : (rel == 2 || rel == 5 || rel == 8 ? dw - (w + x) : x); - - // center | bottom | top - y = (rel == 3 || rel == 4 || rel == 5) ? (dh - h + y)/2 : (rel >= 6 ? dh - (h + y) : y); - - api.event.off(img, 'error load abort', fn); - - try { - ctx.globalAlpha = over.opacity || 1; - ctx.drawImage(img, x, y, w, h); - } - catch (er){} - - queue.next(); - }; - - api.event.on(img, 'error load abort', fn); - img.src = over.src; - - if( img.complete ){ - fn(); - } - }); - - if( filter ){ - queue.inc(); - Image.applyFilter(canvas, filter, queue.next); - } - - queue.check(); - }, - - getMatrix: function (image){ - var - m = api.extend({}, this.matrix) - , sw = m.sw = m.sw || image.videoWidth || image.naturalWidth || image.width - , sh = m.sh = m.sh || image.videoHeight || image.naturalHeight || image.height - , dw = m.dw = m.dw || sw - , dh = m.dh = m.dh || sh - , sf = sw/sh, df = dw/dh - , strategy = m.resize - ; - - if( strategy == 'preview' ){ - if( dw != sw || dh != sh ){ - // Make preview - var w, h; - - if( df >= sf ){ - w = sw; - h = w / df; - } else { - h = sh; - w = h * df; - } - - if( w != sw || h != sh ){ - m.sx = ~~((sw - w)/2); - m.sy = ~~((sh - h)/2); - sw = w; - sh = h; - } - } - } - else if( strategy == 'height' ){ - dw = dh * sf; - } - else if( strategy == 'width' ){ - dh = dw / sf; - } - else if( strategy ){ - if( !(sw > dw || sh > dh) ){ - dw = sw; - dh = sh; - } - else if( strategy == 'min' ){ - dw = round(sf < df ? min(sw, dw) : dh*sf); - dh = round(sf < df ? dw/sf : min(sh, dh)); - } - else { - dw = round(sf >= df ? min(sw, dw) : dh*sf); - dh = round(sf >= df ? dw/sf : min(sh, dh)); - } - } - - m.sw = sw; - m.sh = sh; - m.dw = dw; - m.dh = dh; - m.multipass = api.multiPassResize; - return m; - }, - - _trans: function (fn){ - this._load(this.file, function (err, image){ - if( err ){ - fn(err); - } - else { - try { - this._apply(image, fn); - } catch (err){ - api.log('[err] FileAPI.Image.fn._apply:', err); - fn(err); - } - } - }); - }, - - - get: function (fn){ - if( api.support.transform ){ - var _this = this, matrix = _this.matrix; - - if( matrix.deg == 'auto' ){ - api.getInfo(_this.file, function (err, info){ - // rotate by exif orientation - matrix.deg = exifOrientation[info && info.exif && info.exif.Orientation] || 0; - _this._trans(fn); - }); - } - else { - _this._trans(fn); - } - } - else { - fn('not_support_transform'); - } - - return this; - }, - - - toData: function (fn){ - return this.get(fn); - } - - }; - - - Image.exifOrientation = exifOrientation; - - - Image.transform = function (file, transform, autoOrientation, fn){ - function _transform(err, img){ - // img -- info object - var - images = {} - , queue = api.queue(function (err){ - fn(err, images); - }) - ; - - if( !err ){ - api.each(transform, function (params, name){ - if( !queue.isFail() ){ - var ImgTrans = new Image(img.nodeType ? img : file), isFn = typeof params == 'function'; - - if( isFn ){ - params(img, ImgTrans); - } - else if( params.width ){ - ImgTrans[params.preview ? 'preview' : 'resize'](params.width, params.height, params.strategy); - } - else { - if( params.maxWidth && (img.width > params.maxWidth || img.height > params.maxHeight) ){ - ImgTrans.resize(params.maxWidth, params.maxHeight, 'max'); - } - } - - if( params.crop ){ - var crop = params.crop; - ImgTrans.crop(crop.x|0, crop.y|0, crop.w || crop.width, crop.h || crop.height); - } - - if( params.rotate === undef && autoOrientation ){ - params.rotate = 'auto'; - } - - ImgTrans.set({ type: ImgTrans.matrix.type || params.type || file.type || 'image/png' }); - - if( !isFn ){ - ImgTrans.set({ - deg: params.rotate - , overlay: params.overlay - , filter: params.filter - , quality: params.quality || 1 - }); - } - - queue.inc(); - ImgTrans.toData(function (err, image){ - if( err ){ - queue.fail(); - } - else { - images[name] = image; - queue.next(); - } - }); - } - }); - } - else { - queue.fail(); - } - } - - - // @todo: Оло-ло, нужно рефакторить Ñ�то меÑ�то - if( file.width ){ - _transform(false, file); - } else { - api.getInfo(file, _transform); - } - }; - - - // @const - api.each(['TOP', 'CENTER', 'BOTTOM'], function (x, i){ - api.each(['LEFT', 'CENTER', 'RIGHT'], function (y, j){ - Image[x+'_'+y] = i*3 + j; - Image[y+'_'+x] = i*3 + j; - }); - }); - - - /** - * Trabsform element to canvas - * - * @param {Image|HTMLVideoElement} el - * @returns {Canvas} - */ - Image.toCanvas = function(el){ - var canvas = document.createElement('canvas'); - canvas.width = el.videoWidth || el.width; - canvas.height = el.videoHeight || el.height; - canvas.getContext('2d').drawImage(el, 0, 0); - return canvas; - }; - - - /** - * Create image from DataURL - * @param {String} dataURL - * @param {Object} size - * @param {Function} callback - */ - Image.fromDataURL = function (dataURL, size, callback){ - var img = api.newImage(dataURL); - api.extend(img, size); - callback(img); - }; - - - /** - * Apply filter (caman.js) - * - * @param {Canvas|Image} canvas - * @param {String|Function} filter - * @param {Function} doneFn - */ - Image.applyFilter = function (canvas, filter, doneFn){ - if( typeof filter == 'function' ){ - filter(canvas, doneFn); - } - else if( window.Caman ){ - // http://camanjs.com/guides/ - window.Caman(canvas.tagName == 'IMG' ? Image.toCanvas(canvas) : canvas, function (){ - if( typeof filter == 'string' ){ - this[filter](); - } - else { - api.each(filter, function (val, method){ - this[method](val); - }, this); - } - this.render(doneFn); - }); - } - }; - - - /** - * For load-image-ios.js - */ - api.renderImageToCanvas = function (canvas, img, sx, sy, sw, sh, dx, dy, dw, dh){ - try { - return canvas.getContext('2d').drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh); - } catch (ex) { - api.log('renderImageToCanvas failed'); - throw ex; - } - }; - - - // @export - api.support.canvas = api.support.transform = support; - api.Image = Image; -})(FileAPI, document); - -/* - * JavaScript Load Image iOS scaling fixes 1.0.3 - * https://github.com/blueimp/JavaScript-Load-Image - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * iOS image scaling fixes based on - * https://github.com/stomita/ios-imagefile-megapixel - * - * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT - */ - -/*jslint nomen: true, bitwise: true */ -/*global FileAPI, window, document */ - -(function (factory) { - 'use strict'; - factory(FileAPI); -}(function (loadImage) { - 'use strict'; - - // Only apply fixes on the iOS platform: - if (!window.navigator || !window.navigator.platform || - !(/iP(hone|od|ad)/).test(window.navigator.platform)) { - return; - } - - var originalRenderMethod = loadImage.renderImageToCanvas; - - // Detects subsampling in JPEG images: - loadImage.detectSubsampling = function (img) { - var canvas, - context; - if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images - canvas = document.createElement('canvas'); - canvas.width = canvas.height = 1; - context = canvas.getContext('2d'); - context.drawImage(img, -img.width + 1, 0); - // subsampled image becomes half smaller in rendering size. - // check alpha channel value to confirm image is covering edge pixel or not. - // if alpha value is 0 image is not covering, hence subsampled. - return context.getImageData(0, 0, 1, 1).data[3] === 0; - } - return false; - }; - - // Detects vertical squash in JPEG images: - loadImage.detectVerticalSquash = function (img, subsampled) { - var naturalHeight = img.naturalHeight || img.height, - canvas = document.createElement('canvas'), - context = canvas.getContext('2d'), - data, - sy, - ey, - py, - alpha; - if (subsampled) { - naturalHeight /= 2; - } - canvas.width = 1; - canvas.height = naturalHeight; - context.drawImage(img, 0, 0); - data = context.getImageData(0, 0, 1, naturalHeight).data; - // search image edge pixel position in case it is squashed vertically: - sy = 0; - ey = naturalHeight; - py = naturalHeight; - while (py > sy) { - alpha = data[(py - 1) * 4 + 3]; - if (alpha === 0) { - ey = py; - } else { - sy = py; - } - py = (ey + sy) >> 1; - } - return (py / naturalHeight) || 1; - }; - - // Renders image to canvas while working around iOS image scaling bugs: - // https://github.com/blueimp/JavaScript-Load-Image/issues/13 - loadImage.renderImageToCanvas = function ( - canvas, - img, - sourceX, - sourceY, - sourceWidth, - sourceHeight, - destX, - destY, - destWidth, - destHeight - ) { - if (img._type === 'image/jpeg') { - var context = canvas.getContext('2d'), - tmpCanvas = document.createElement('canvas'), - tileSize = 1024, - tmpContext = tmpCanvas.getContext('2d'), - subsampled, - vertSquashRatio, - tileX, - tileY; - tmpCanvas.width = tileSize; - tmpCanvas.height = tileSize; - context.save(); - subsampled = loadImage.detectSubsampling(img); - if (subsampled) { - sourceX /= 2; - sourceY /= 2; - sourceWidth /= 2; - sourceHeight /= 2; - } - vertSquashRatio = loadImage.detectVerticalSquash(img, subsampled); - if (subsampled || vertSquashRatio !== 1) { - sourceY *= vertSquashRatio; - destWidth = Math.ceil(tileSize * destWidth / sourceWidth); - destHeight = Math.ceil( - tileSize * destHeight / sourceHeight / vertSquashRatio - ); - destY = 0; - tileY = 0; - while (tileY < sourceHeight) { - destX = 0; - tileX = 0; - while (tileX < sourceWidth) { - tmpContext.clearRect(0, 0, tileSize, tileSize); - tmpContext.drawImage( - img, - sourceX, - sourceY, - sourceWidth, - sourceHeight, - -tileX, - -tileY, - sourceWidth, - sourceHeight - ); - context.drawImage( - tmpCanvas, - 0, - 0, - tileSize, - tileSize, - destX, - destY, - destWidth, - destHeight - ); - tileX += tileSize; - destX += destWidth; - } - tileY += tileSize; - destY += destHeight; - } - context.restore(); - return canvas; - } - } - return originalRenderMethod( - canvas, - img, - sourceX, - sourceY, - sourceWidth, - sourceHeight, - destX, - destY, - destWidth, - destHeight - ); - }; - -})); - -/*global window, FileAPI */ - -(function (api, window){ - "use strict"; - - var - document = window.document - , FormData = window.FormData - , Form = function (){ this.items = []; } - , encodeURIComponent = window.encodeURIComponent - ; - - - Form.prototype = { - - append: function (name, blob, file, type){ - this.items.push({ - name: name - , blob: blob && blob.blob || (blob == void 0 ? '' : blob) - , file: blob && (file || blob.name) - , type: blob && (type || blob.type) - }); - }, - - each: function (fn){ - var i = 0, n = this.items.length; - for( ; i < n; i++ ){ - fn.call(this, this.items[i]); - } - }, - - toData: function (fn, options){ - // allow chunked transfer if we have only one file to send - // flag is used below and in XHR._send - options._chunked = api.support.chunked && options.chunkSize > 0 && api.filter(this.items, function (item){ return item.file; }).length == 1; - - if( !api.support.html5 ){ - api.log('FileAPI.Form.toHtmlData'); - this.toHtmlData(fn); - } - else if( !api.formData || this.multipart || !FormData ){ - api.log('FileAPI.Form.toMultipartData'); - this.toMultipartData(fn); - } - else if( options._chunked ){ - api.log('FileAPI.Form.toPlainData'); - this.toPlainData(fn); - } - else { - api.log('FileAPI.Form.toFormData'); - this.toFormData(fn); - } - }, - - _to: function (data, complete, next, arg){ - var queue = api.queue(function (){ - complete(data); - }); - - this.each(function (file){ - try{ - next(file, data, queue, arg); - } - catch( err ){ - api.log('FileAPI.Form._to: ' + err.message); - complete(err); - } - }); - - queue.check(); - }, - - - toHtmlData: function (fn){ - this._to(document.createDocumentFragment(), fn, function (file, data/**DocumentFragment*/){ - var blob = file.blob, hidden; - - if( file.file ){ - api.reset(blob, true); - // set new name - blob.name = file.name; - blob.disabled = false; - data.appendChild(blob); - } - else { - hidden = document.createElement('input'); - hidden.name = file.name; - hidden.type = 'hidden'; - hidden.value = blob; - data.appendChild(hidden); - } - }); - }, - - toPlainData: function (fn){ - this._to({}, fn, function (file, data, queue){ - if( file.file ){ - data.type = file.file; - } - - if( file.blob.toBlob ){ - // canvas - queue.inc(); - _convertFile(file, function (file, blob){ - data.name = file.name; - data.file = blob; - data.size = blob.length; - data.type = file.type; - queue.next(); - }); - } - else if( file.file ){ - // file - data.name = file.blob.name; - data.file = file.blob; - data.size = file.blob.size; - data.type = file.type; - } - else { - // additional data - if( !data.params ){ - data.params = []; - } - data.params.push(encodeURIComponent(file.name) +"="+ encodeURIComponent(file.blob)); - } - - data.start = -1; - data.end = data.file && data.file.FileAPIReadPosition || -1; - data.retry = 0; - }); - }, - - toFormData: function (fn){ - this._to(new FormData, fn, function (file, data, queue){ - if( file.blob && file.blob.toBlob ){ - queue.inc(); - _convertFile(file, function (file, blob){ - data.append(file.name, blob, file.file); - queue.next(); - }); - } - else if( file.file ){ - data.append(file.name, file.blob, file.file); - } - else { - data.append(file.name, file.blob); - } - - if( file.file ){ - data.append('_'+file.name, file.file); - } - }); - }, - - - toMultipartData: function (fn){ - this._to([], fn, function (file, data, queue, boundary){ - queue.inc(); - _convertFile(file, function (file, blob){ - data.push( - '--_' + boundary + ('\r\nContent-Disposition: form-data; name="'+ file.name +'"'+ (file.file ? '; filename="'+ encodeURIComponent(file.file) +'"' : '') - + (file.file ? '\r\nContent-Type: '+ (file.type || 'application/octet-stream') : '') - + '\r\n' - + '\r\n'+ (file.file ? blob : encodeURIComponent(blob)) - + '\r\n') - ); - queue.next(); - }, true); - }, api.expando); - } - }; - - - function _convertFile(file, fn, useBinaryString){ - var blob = file.blob, filename = file.file; - - if( filename ){ - if( !blob.toDataURL ){ - // The Blob is not an image. - api.readAsBinaryString(blob, function (evt){ - if( evt.type == 'load' ){ - fn(file, evt.result); - } - }); - return; - } - - var - mime = { 'image/jpeg': '.jpe?g', 'image/png': '.png' } - , type = mime[file.type] ? file.type : 'image/png' - , ext = mime[type] || '.png' - , quality = blob.quality || 1 - ; - - if( !filename.match(new RegExp(ext+'$', 'i')) ){ - // Does not change the current extension, but add a new one. - filename += ext.replace('?', ''); - } - - file.file = filename; - file.type = type; - - if( !useBinaryString && blob.toBlob ){ - blob.toBlob(function (blob){ - fn(file, blob); - }, type, quality); - } - else { - fn(file, api.toBinaryString(blob.toDataURL(type, quality))); - } - } - else { - fn(file, blob); - } - } - - - // @export - api.Form = Form; -})(FileAPI, window); - -/*global window, FileAPI, Uint8Array */ - -(function (window, api){ - "use strict"; - - var - noop = function (){} - , document = window.document - - , XHR = function (options){ - this.uid = api.uid(); - this.xhr = { - abort: noop - , getResponseHeader: noop - , getAllResponseHeaders: noop - }; - this.options = options; - }, - - _xhrResponsePostfix = { '': 1, XML: 1, Text: 1, Body: 1 } - ; - - - XHR.prototype = { - status: 0, - statusText: '', - constructor: XHR, - - getResponseHeader: function (name){ - return this.xhr.getResponseHeader(name); - }, - - getAllResponseHeaders: function (){ - return this.xhr.getAllResponseHeaders() || {}; - }, - - end: function (status, statusText){ - var _this = this, options = _this.options; - - _this.end = - _this.abort = noop; - _this.status = status; - - if( statusText ){ - _this.statusText = statusText; - } - - api.log('xhr.end:', status, statusText); - options.complete(status == 200 || status == 201 ? false : _this.statusText || 'unknown', _this); - - if( _this.xhr && _this.xhr.node ){ - setTimeout(function (){ - var node = _this.xhr.node; - try { node.parentNode.removeChild(node); } catch (e){} - try { delete window[_this.uid]; } catch (e){} - window[_this.uid] = _this.xhr.node = null; - }, 9); - } - }, - - abort: function (){ - this.end(0, 'abort'); - - if( this.xhr ){ - this.xhr.aborted = true; - this.xhr.abort(); - } - }, - - send: function (FormData){ - var _this = this, options = this.options; - - FormData.toData(function (data){ - if( data instanceof Error ){ - _this.end(0, data.message); - } - else{ - // Start uploading - options.upload(options, _this); - _this._send.call(_this, options, data); - } - }, options); - }, - - _send: function (options, data){ - var _this = this, xhr, uid = _this.uid, onLoadFnName = _this.uid + "Load", url = options.url; - - api.log('XHR._send:', data); - - if( !options.cache ){ - // No cache - url += (~url.indexOf('?') ? '&' : '?') + api.uid(); - } - - if( data.nodeName ){ - var jsonp = options.jsonp; - - // prepare callback in GET - url = url.replace(/([a-z]+)=(\?)/i, '$1='+uid); - - // legacy - options.upload(options, _this); - - var - onPostMessage = function (evt){ - if( ~url.indexOf(evt.origin) ){ - try { - var result = api.parseJSON(evt.data); - if( result.id == uid ){ - complete(result.status, result.statusText, result.response); - } - } catch( err ){ - complete(0, err.message); - } - } - }, - - // jsonp-callack - complete = window[uid] = function (status, statusText, response){ - _this.readyState = 4; - _this.responseText = response; - _this.end(status, statusText); - - api.event.off(window, 'message', onPostMessage); - window[uid] = xhr = transport = window[onLoadFnName] = null; - } - ; - - _this.xhr.abort = function (){ - try { - if( transport.stop ){ transport.stop(); } - else if( transport.contentWindow.stop ){ transport.contentWindow.stop(); } - else { transport.contentWindow.document.execCommand('Stop'); } - } - catch (er) {} - complete(0, "abort"); - }; - - api.event.on(window, 'message', onPostMessage); - - window[onLoadFnName] = function (){ - try { - var - win = transport.contentWindow - , doc = win.document - , result = win.result || api.parseJSON(doc.body.innerHTML) - ; - complete(result.status, result.statusText, result.response); - } catch (e){ - api.log('[transport.onload]', e); - } - }; - - xhr = document.createElement('div'); - xhr.innerHTML = '
' - + '' - + (jsonp && (options.url.indexOf('=?') < 0) ? '' : '') - + '
' - ; - - // get form-data & transport - var - form = xhr.getElementsByTagName('form')[0] - , transport = xhr.getElementsByTagName('iframe')[0] - ; - - form.appendChild(data); - - api.log(form.parentNode.innerHTML); - - // append to DOM - document.body.appendChild(xhr); - - // keep a reference to node-transport - _this.xhr.node = xhr; - - // send - _this.readyState = 2; // loaded - try { - form.submit(); - } catch (err) { - api.log('iframe.error: ' + err); - } - form = null; - } - else { - // Clean url - url = url.replace(/([a-z]+)=(\?)&?/i, ''); - - // html5 - if (this.xhr && this.xhr.aborted) { - api.log("Error: already aborted"); - return; - } - xhr = _this.xhr = api.getXHR(); - - if (data.params) { - url += (url.indexOf('?') < 0 ? "?" : "&") + data.params.join("&"); - } - - xhr.open('POST', url, true); - - if( api.withCredentials ){ - xhr.withCredentials = "true"; - } - - if( !options.headers || !options.headers['X-Requested-With'] ){ - xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - } - - api.each(options.headers, function (val, key){ - xhr.setRequestHeader(key, val); - }); - - - if ( options._chunked ) { - // chunked upload - if( xhr.upload ){ - xhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){ - if (!data.retry) { - // show progress only for correct chunk uploads - options.progress({ - type: evt.type - , total: data.size - , loaded: data.start + evt.loaded - , totalSize: data.size - }, _this, options); - } - }, 100), false); - } - - xhr.onreadystatechange = function (){ - var lkb = parseInt(xhr.getResponseHeader('X-Last-Known-Byte'), 10); - - _this.status = xhr.status; - _this.statusText = xhr.statusText; - _this.readyState = xhr.readyState; - - if( xhr.readyState == 4 ){ - for( var k in _xhrResponsePostfix ){ - _this['response'+k] = xhr['response'+k]; - } - xhr.onreadystatechange = null; - - if (!xhr.status || xhr.status - 201 > 0) { - api.log("Error: " + xhr.status); - // some kind of error - // 0 - connection fail or timeout, if xhr.aborted is true, then it's not recoverable user action - // up - server error - if (((!xhr.status && !xhr.aborted) || 500 == xhr.status || 416 == xhr.status) && ++data.retry <= options.chunkUploadRetry) { - // let's try again the same chunk - // only applicable for recoverable error codes 500 && 416 - var delay = xhr.status ? 0 : api.chunkNetworkDownRetryTimeout; - - // inform about recoverable problems - options.pause(data.file, options); - - // smart restart if server reports about the last known byte - api.log("X-Last-Known-Byte: " + lkb); - if (lkb) { - data.end = lkb; - } else { - data.end = data.start - 1; - if (416 == xhr.status) { - data.end = data.end - options.chunkSize; - } - } - - setTimeout(function () { - _this._send(options, data); - }, delay); - } else { - // no mo retries - _this.end(xhr.status); - } - } else { - // success - data.retry = 0; - - if (data.end == data.size - 1) { - // finished - _this.end(xhr.status); - } else { - // next chunk - - // shift position if server reports about the last known byte - api.log("X-Last-Known-Byte: " + lkb); - if (lkb) { - data.end = lkb; - } - data.file.FileAPIReadPosition = data.end; - - setTimeout(function () { - _this._send(options, data); - }, 0); - } - } - - xhr = null; - } - }; - - data.start = data.end + 1; - data.end = Math.max(Math.min(data.start + options.chunkSize, data.size) - 1, data.start); - - // Retrieve a slice of file - var - file = data.file - , slice = (file.slice || file.mozSlice || file.webkitSlice).call(file, data.start, data.end + 1) - ; - - if( data.size && !slice.size ){ - setTimeout(function (){ - _this.end(-1); - }); - } else { - xhr.setRequestHeader("Content-Range", "bytes " + data.start + "-" + data.end + "/" + data.size); - xhr.setRequestHeader("Content-Disposition", 'attachment; filename=' + encodeURIComponent(data.name)); - xhr.setRequestHeader("Content-Type", data.type || "application/octet-stream"); - - xhr.send(slice); - } - - file = slice = null; - } else { - // single piece upload - if( xhr.upload ){ - // https://github.com/blueimp/jQuery-File-Upload/wiki/Fixing-Safari-hanging-on-very-high-speed-connections-%281Gbps%29 - xhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){ - options.progress(evt, _this, options); - }, 100), false); - } - - xhr.onreadystatechange = function (){ - _this.status = xhr.status; - _this.statusText = xhr.statusText; - _this.readyState = xhr.readyState; - - if( xhr.readyState == 4 ){ - for( var k in _xhrResponsePostfix ){ - _this['response'+k] = xhr['response'+k]; - } - xhr.onreadystatechange = null; - - if (!xhr.status || xhr.status > 201) { - api.log("Error: " + xhr.status); - if (((!xhr.status && !xhr.aborted) || 500 == xhr.status) && (options.retry || 0) < options.uploadRetry) { - options.retry = (options.retry || 0) + 1; - var delay = api.networkDownRetryTimeout; - - // inform about recoverable problems - options.pause(options.file, options); - - setTimeout(function () { - _this._send(options, data); - }, delay); - } else { - //success - _this.end(xhr.status); - } - } else { - //success - _this.end(xhr.status); - } - - xhr = null; - } - }; - - if( api.isArray(data) ){ - // multipart - xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=_'+api.expando); - var rawData = data.join('') +'--_'+ api.expando +'--'; - - /** @namespace xhr.sendAsBinary https://developer.mozilla.org/ru/XMLHttpRequest#Sending_binary_content */ - if( xhr.sendAsBinary ){ - xhr.sendAsBinary(rawData); - } - else { - var bytes = Array.prototype.map.call(rawData, function(c){ return c.charCodeAt(0) & 0xff; }); - xhr.send(new Uint8Array(bytes).buffer); - - } - } else { - // FormData - xhr.send(data); - } - } - } - } - }; - - - // @export - api.XHR = XHR; -})(window, FileAPI); - -/** - * @class FileAPI.Camera - * @author RubaXa - * @support Chrome 21+, FF 18+, Opera 12+ - */ - -/*global window, FileAPI, jQuery */ -/** @namespace LocalMediaStream -- https://developer.mozilla.org/en-US/docs/WebRTC/MediaStream_API#LocalMediaStream */ -(function (window, api){ - "use strict"; - - var - URL = window.URL || window.webkitURL, - - document = window.document, - navigator = window.navigator, - - getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia, - - html5 = !!getMedia - ; - - - // Support "media" - api.support.media = html5; - - - var Camera = function (video){ - this.video = video; - }; - - - Camera.prototype = { - isActive: function (){ - return !!this._active; - }, - - - /** - * Start camera streaming - * @param {Function} callback - */ - start: function (callback){ - var - _this = this - , video = _this.video - , _successId - , _failId - , _complete = function (err){ - _this._active = !err; - clearTimeout(_failId); - clearTimeout(_successId); -// api.event.off(video, 'loadedmetadata', _complete); - callback && callback(err, _this); - } - ; - - getMedia.call(navigator, { video: true }, function (stream/**LocalMediaStream*/){ - // Success - _this.stream = stream; - -// api.event.on(video, 'loadedmetadata', function (){ -// _complete(null); -// }); - - // Set camera stream - video.src = URL.createObjectURL(stream); - - // Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia. - // See crbug.com/110938. - _successId = setInterval(function (){ - if( _detectVideoSignal(video) ){ - _complete(null); - } - }, 1000); - - _failId = setTimeout(function (){ - _complete('timeout'); - }, 5000); - - // Go-go-go! - video.play(); - }, _complete/*error*/); - }, - - - /** - * Stop camera streaming - */ - stop: function (){ - try { - this._active = false; - this.video.pause(); - - try { - this.stream.stop(); - } catch (err) { - api.each(this.stream.getTracks(), function (track) { - track.stop(); - }); - } - - this.stream = null; - } catch( err ){ - api.log('[FileAPI.Camera] stop:', err); - } - }, - - - /** - * Create screenshot - * @return {FileAPI.Camera.Shot} - */ - shot: function (){ - return new Shot(this.video); - } - }; - - - /** - * Get camera element from container - * - * @static - * @param {HTMLElement} el - * @return {Camera} - */ - Camera.get = function (el){ - return new Camera(el.firstChild); - }; - - - /** - * Publish camera element into container - * - * @static - * @param {HTMLElement} el - * @param {Object} options - * @param {Function} [callback] - */ - Camera.publish = function (el, options, callback){ - if( typeof options == 'function' ){ - callback = options; - options = {}; - } - - // Dimensions of "camera" - options = api.extend({}, { - width: '100%' - , height: '100%' - , start: true - }, options); - - - if( el.jquery ){ - // Extract first element, from jQuery collection - el = el[0]; - } - - - var doneFn = function (err){ - if( err ){ - callback(err); - } - else { - // Get camera - var cam = Camera.get(el); - if( options.start ){ - cam.start(callback); - } - else { - callback(null, cam); - } - } - }; - - - el.style.width = _px(options.width); - el.style.height = _px(options.height); - - - if( api.html5 && html5 ){ - // Create video element - var video = document.createElement('video'); - - // Set dimensions - video.style.width = _px(options.width); - video.style.height = _px(options.height); - - // Clean container - if( window.jQuery ){ - jQuery(el).empty(); - } else { - el.innerHTML = ''; - } - - // Add "camera" to container - el.appendChild(video); - - // end - doneFn(); - } - else { - Camera.fallback(el, options, doneFn); - } - }; - - - Camera.fallback = function (el, options, callback){ - callback('not_support_camera'); - }; - - - /** - * @class FileAPI.Camera.Shot - */ - var Shot = function (video){ - var canvas = video.nodeName ? api.Image.toCanvas(video) : video; - var shot = api.Image(canvas); - shot.type = 'image/png'; - shot.width = canvas.width; - shot.height = canvas.height; - shot.size = canvas.width * canvas.height * 4; - return shot; - }; - - - /** - * Add "px" postfix, if value is a number - * - * @private - * @param {*} val - * @return {String} - */ - function _px(val){ - return val >= 0 ? val + 'px' : val; - } - - - /** - * @private - * @param {HTMLVideoElement} video - * @return {Boolean} - */ - function _detectVideoSignal(video){ - var canvas = document.createElement('canvas'), ctx, res = false; - try { - ctx = canvas.getContext('2d'); - ctx.drawImage(video, 0, 0, 1, 1); - res = ctx.getImageData(0, 0, 1, 1).data[4] != 255; - } - catch( err ){ - api.log('[FileAPI.Camera] detectVideoSignal:', err); - } - return res; - } - - - // @export - Camera.Shot = Shot; - api.Camera = Camera; -})(window, FileAPI); - -/** - * FileAPI fallback to Flash - * - * @flash-developer "Vladimir Demidov" - */ - -/*global window, FileAPI */ -(function (window, jQuery, api) { - "use strict"; - - var _each = api.each, - _cameraQueue = []; - - if (api.support.flash && (api.media && (!api.support.media || !api.html5))) { - (function () { - function _wrap(fn) { - var id = fn.wid = api.uid(); - api.Flash._fn[id] = fn; - return 'FileAPI.Flash._fn.' + id; - } - - - function _unwrap(fn) { - try { - api.Flash._fn[fn.wid] = null; - delete api.Flash._fn[fn.wid]; - } catch (e) { - } - } - - var flash = api.Flash; - api.extend(api.Flash, { - - patchCamera: function () { - api.Camera.fallback = function (el, options, callback) { - var camId = api.uid(); - api.log('FlashAPI.Camera.publish: ' + camId); - flash.publish(el, camId, api.extend(options, { - camera: true, - onEvent: _wrap(function _(evt) { - if (evt.type === 'camera') { - _unwrap(_); - - if (evt.error) { - api.log('FlashAPI.Camera.publish.error: ' + evt.error); - callback(evt.error); - } else { - api.log('FlashAPI.Camera.publish.success: ' + camId); - callback(null); - } - } - }) - })); - }; - // Run - _each(_cameraQueue, function (args) { - api.Camera.fallback.apply(api.Camera, args); - }); - _cameraQueue = []; - - - // FileAPI.Camera:proto - api.extend(api.Camera.prototype, { - _id: function () { - return this.video.id; - }, - - start: function (callback) { - var _this = this; - flash.cmd(this._id(), 'camera.on', { - callback: _wrap(function _(evt) { - _unwrap(_); - - if (evt.error) { - api.log('FlashAPI.camera.on.error: ' + evt.error); - callback(evt.error, _this); - } else { - api.log('FlashAPI.camera.on.success: ' + _this._id()); - _this._active = true; - callback(null, _this); - } - }) - }); - }, - - stop: function () { - this._active = false; - flash.cmd(this._id(), 'camera.off'); - }, - - shot: function () { - api.log('FlashAPI.Camera.shot:', this._id()); - - var shot = api.Flash.cmd(this._id(), 'shot', {}); - shot.type = 'image/png'; - shot.flashId = this._id(); - shot.isShot = true; - - return new api.Camera.Shot(shot); - } - }); - } - }); - - api.Camera.fallback = function () { - _cameraQueue.push(arguments); - }; - - }()); - } -}(window, window.jQuery, FileAPI)); -if( typeof define === "function" && define.amd ){ define("FileAPI", [], function (){ return FileAPI; }); } \ No newline at end of file diff --git a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.html5.min.js b/manager/media/browser/mcpuk/js/FileAPI/FileAPI.html5.min.js deleted file mode 100644 index d3a8e21162..0000000000 --- a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.html5.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! FileAPI 2.0.19 - BSD | git://github.com/mailru/FileAPI.git */ -!function(a){"use strict";var b=a.HTMLCanvasElement&&a.HTMLCanvasElement.prototype,c=a.Blob&&function(){try{return Boolean(new Blob)}catch(a){return!1}}(),d=c&&a.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(a){return!1}}(),e=a.BlobBuilder||a.WebKitBlobBuilder||a.MozBlobBuilder||a.MSBlobBuilder,f=(c||e)&&a.atob&&a.ArrayBuffer&&a.Uint8Array&&function(a){var b,f,g,h,i,j;for(b=a.split(",")[0].indexOf("base64")>=0?atob(a.split(",")[1]):decodeURIComponent(a.split(",")[1]),f=new ArrayBuffer(b.length),g=new Uint8Array(f),h=0;h0,H=a.dataURLtoBlob,I=/img/i,J=/canvas/i,K=/img|canvas/i,L=/input/i,M=/^data:[^,]+,/,N={}.toString,O=a.Math,P=function(b){return b=new a.Number(O.pow(1024,b)),b.from=function(a){return O.round(a*this)},b},Q={},R=[],S="abort progress error load loadend",T="status statusText readyState response responseXML responseText responseBody".split(" "),U="currentTarget",V="preventDefault",W=function(a){return a&&"length"in a},X=function(a,b,c){if(a)if(W(a))for(var d=0,e=a.length;e>d;d++)d in a&&b.call(c,a[d],d,a);else for(var f in a)a.hasOwnProperty(f)&&b.call(c,a[f],f,a)},Y=function(a){for(var b=arguments,c=1,d=function(b,c){a[c]=b};c=c&&!d&&f.end()},isFail:function(){return d},fail:function(){!d&&a(d=!0)},end:function(){e||(e=!0,a())}};return f},each:X,afor:function(a,b){var c=0,d=a.length;W(a)&&d--?!function e(){b(d!=c&&e,a[c],c++)}():b(!1)},extend:Y,isFile:function(a){return"[object File]"===N.call(a)},isBlob:function(a){return this.isFile(a)||"[object Blob]"===N.call(a)},isCanvas:function(a){return a&&J.test(a.nodeName)},getFilesFilter:function(a){return a="string"==typeof a?a:a.getAttribute&&a.getAttribute("accept")||"",a?new RegExp("("+a.replace(/\./g,"\\.").replace(/,/g,"|")+")$","i"):/./},readAsDataURL:function(a,b){ca.isCanvas(a)?c(a,b,"load",ca.toDataURL(a)):e(a,b,"DataURL")},readAsBinaryString:function(a,b){d("BinaryString")?e(a,b,"BinaryString"):e(a,function(a){if("load"==a.type)try{a.result=ca.toBinaryString(a.result)}catch(c){a.type="error",a.message=c.toString()}b(a)},"DataURL")},readAsArrayBuffer:function(a,b){e(a,b,"ArrayBuffer")},readAsText:function(a,b,c){c||(c=b,b="utf-8"),e(a,c,"Text",b)},toDataURL:function(a,b){return"string"==typeof a?a:a.toDataURL?a.toDataURL(b||"image/png"):void 0},toBinaryString:function(b){return a.atob(ca.toDataURL(b).replace(M,""))},readAsImage:function(a,d,e){if(ca.isBlob(a))if(w){var f=w.createObjectURL(a);f===b?c(a,d,"error"):ca.readAsImage(f,d,e)}else ca.readAsDataURL(a,function(b){"load"==b.type?ca.readAsImage(b.result,d,e):(e||"error"==b.type)&&c(a,d,b,null,{loaded:b.loaded,total:b.total})});else if(ca.isCanvas(a))c(a,d,"load",a);else if(I.test(a.nodeName))if(a.complete)c(a,d,"load",a);else{var g="error abort load";_(a,g,function i(b){"load"==b.type&&w&&w.revokeObjectURL(a.src),$(a,g,i),c(a,d,b,a)})}else if(a.iframe)c(a,d,{type:"error"});else{var h=ca.newImage(a.dataURL||a);ca.readAsImage(h,d,e)}},checkFileObj:function(a){var b={},c=ca.accept;return"object"==typeof a?b=a:b.name=(a+"").split(/\\|\//g).pop(),null==b.type&&(b.type=b.name.split(".").pop()),X(c,function(a,c){a=new RegExp(a.replace(/\s/g,"|"),"i"),(a.test(b.type)||ca.ext2mime[b.type])&&(b.type=ca.ext2mime[b.type]||c.split("/")[0]+"/"+b.type)}),b},getDropFiles:function(a,b){var c,d=[],e=[],j=l(a),k=j.files,m=j.items,n=W(m)&&m[0]&&h(m[0]),o=ca.queue(function(){b(d,e)});if(n)if(G&&k){var p,q,r=k.length;for(c=new Array(r);r--;){p=k[r];try{q=h(m[r])}catch(s){ca.log("[err] getDropFiles: ",s),q=null}g(q)&&(q.isDirectory||q.isFile&&p.name==p.name.normalize("NFC"))?c[r]=q:c[r]=p}}else c=m;else c=k;X(c||[],function(a){o.inc();try{n&&g(a)?i(a,function(a,b,c){a?ca.log("[err] getDropFiles:",a):d.push.apply(d,b),e.push.apply(e,c),o.next()}):f(a,function(b,c){b?d.push(a):a.error=c,e.push(a),o.next()})}catch(b){o.next(),ca.log("[err] getDropFiles: ",b)}}),o.check()},getFiles:function(a,b,c){var d=[];return c?(ca.filterFiles(ca.getFiles(a),b,c),null):(a.jquery&&(a.each(function(){d=d.concat(ca.getFiles(this))}),a=d,d=[]),"string"==typeof b&&(b=ca.getFilesFilter(b)),a.originalEvent?a=aa(a.originalEvent):a.srcElement&&(a=aa(a)),a.dataTransfer?a=a.dataTransfer:a.target&&(a=a.target),a.files?(d=a.files,D||(d[0].blob=a,d[0].iframe=!0)):!D&&k(a)?ca.trim(a.value)&&(d=[ca.checkFileObj(a.value)],d[0].blob=a,d[0].iframe=!0):W(a)&&(d=a),ca.filter(d,function(a){return!b||b.test(a.name)}))},getTotalSize:function(a){for(var b=0,c=a&&a.length;c--;)b+=a[c].size;return b},getInfo:function(a,b){var c={},d=R.concat();ca.isBlob(a)?!function e(){var f=d.shift();f?f.test(a.type)?f(a,function(a,d){a?b(a):(Y(c,d),e())}):e():b(!1,c)}():b("not_support_info",c)},addInfoReader:function(a,b){b.test=function(b){return a.test(b)},R.push(b)},filter:function(a,b){for(var c,d=[],e=0,f=a.length;f>e;e++)e in a&&(c=a[e],b.call(c,c,e,a)&&d.push(c));return d},filterFiles:function(a,b,c){if(a.length){var d,e=a.concat(),f=[],g=[];!function h(){e.length?(d=e.shift(),ca.getInfo(d,function(a,c){(b(d,a?!1:c)?f:g).push(d),h()})):c(f,g)}()}else c([],a)},upload:function(a){a=Y({jsonp:"callback",prepare:ca.F,beforeupload:ca.F,upload:ca.F,fileupload:ca.F,fileprogress:ca.F,filecomplete:ca.F,progress:ca.F,complete:ca.F,pause:ca.F,imageOriginal:!0,chunkSize:ca.chunkSize,chunkUploadRetry:ca.chunkUploadRetry,uploadRetry:ca.uploadRetry},a),a.imageAutoOrientation&&!a.imageTransform&&(a.imageTransform={rotate:"auto"});var b,c=new ca.XHR(a),d=this._getFilesDataArray(a.files),e=this,f=0,g=0,h=!1;return X(d,function(a){f+=a.size}),c.files=[],X(d,function(a){c.files.push(a.file)}),c.total=f,c.loaded=0,c.filesLeft=d.length,a.beforeupload(c,a),b=function(){var i=d.shift(),k=i&&i.file,l=!1,m=j(a);if(c.filesLeft=d.length,k&&k.name===ca.expando&&(k=null,ca.log("[warn] FileAPI.upload() — called without files")),("abort"!=c.statusText||c.current)&&i){if(h=!1,c.currentFile=k,k&&a.prepare(k,m)===!1)return void b.call(e);m.file=k,e._getFormData(m,i,function(h){g||a.upload(c,a);var j=new ca.XHR(Y({},m,{upload:k?function(){a.fileupload(k,j,m)}:q,progress:k?function(b){l||(l=b.loaded===b.total,a.fileprogress({type:"progress",total:i.total=b.total,loaded:i.loaded=b.loaded},k,j,m),a.progress({type:"progress",total:f,loaded:c.loaded=g+i.size*(b.loaded/b.total)||0},k,j,m))}:q,complete:function(d){X(T,function(a){c[a]=j[a]}),k&&(i.total=i.total||i.size,i.loaded=i.total,d||(this.progress(i),l=!0,g+=i.size,c.loaded=g),a.filecomplete(d,j,k,m)),setTimeout(function(){b.call(e)},0)}}));c.abort=function(a){a||(d.length=0),this.current=a,j.abort()},j.send(h)})}else{var n=200==c.status||201==c.status||204==c.status;a.complete(n?!1:c.statusText||"error",c,a),h=!0}},setTimeout(b,0),c.append=function(a,g){a=ca._getFilesDataArray([].concat(a)),X(a,function(a){f+=a.size,c.files.push(a.file),g?d.unshift(a):d.push(a)}),c.statusText="",h&&b.call(e)},c.remove=function(a){for(var b,c=d.length;c--;)d[c].file==a&&(b=d.splice(c,1),f-=b.size);return b},c},_getFilesDataArray:function(a){var b=[],c={};if(k(a)){var d=ca.getFiles(a);c[a.name||"file"]=null!==a.getAttribute("multiple")?d:d[0]}else W(a)&&k(a[0])?X(a,function(a){c[a.name||"file"]=ca.getFiles(a)}):c=a;return X(c,function e(a,c){W(a)?X(a,function(a){e(a,c)}):a&&(a.name||a.image)&&b.push({name:c,file:a,size:a.size,total:a.size,loaded:0})}),b.length||b.push({file:{name:ca.expando}}),b},_getFormData:function(a,b,c){var d=b.file,e=b.name,f=d.name,g=d.type,h=ca.support.transform&&a.imageTransform,i=new ca.Form,j=ca.queue(function(){c(i)}),k=h&&m(h),l=ca.postNameConcat;X(a.data,function n(a,b){"object"==typeof a?X(a,function(a,c){n(a,l(b,c))}):i.append(b,a)}),function o(b){b.image?(j.inc(),b.toData(function(a,c){b.file&&(c.type=b.file.type,c.quality=b.matrix.quality,f=b.file&&b.file.name),f=f||(new Date).getTime()+".png",o(c),j.next()})):ca.Image&&h&&(/^image/.test(b.type)||K.test(b.nodeName))?(j.inc(),k&&(h=[h]),ca.Image.transform(b,h,a.imageAutoOrientation,function(c,d){if(k&&!c)H||ca.flashEngine||(i.multipart=!0),i.append(e,d[0],f,h[0].type||g);else{var m=0;c||X(d,function(a,b){H||ca.flashEngine||(i.multipart=!0),h[b].postName||(m=1),i.append(h[b].postName||l(e,b),a,f,h[b].type||g)}),(c||a.imageOriginal)&&i.append(l(e,m?"original":null),b,f,g)}j.next()})):f!==ca.expando&&i.append(e,b,f)}(d),j.check()},reset:function(a,b){var c,d;return C?(d=C(a).clone(!0).insertBefore(a).val("")[0],b||C(a).remove()):(c=a.parentNode,d=c.insertBefore(a.cloneNode(!0),a),d.value="",b||c.removeChild(a),X(Q[ca.uid(a)],function(b,c){X(b,function(b){$(a,c,b),Z(d,c,b)})})),d},load:function(a,b){var c=ca.getXHR();return c?(c.open("GET",a,!0),c.overrideMimeType&&c.overrideMimeType("text/plain; charset=x-user-defined"),Z(c,"progress",function(a){a.lengthComputable&&b({type:a.type,loaded:a.loaded,total:a.total},c)}),c.onreadystatechange=function(){if(4==c.readyState)if(c.onreadystatechange=null,200==c.status){a=a.split("/");var d={name:a[a.length-1],size:c.getResponseHeader("Content-Length"),type:c.getResponseHeader("Content-Type")};d.dataURL="data:"+d.type+";base64,"+ca.encode64(c.responseBody||c.responseText),b({type:"load",result:d},c)}else b({type:"error"},c)},c.send(null)):b({type:"error"}),c},encode64:function(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",c="",d=0;for("string"!=typeof a&&(a=String(a));d>2,k=(3&g)<<4|h>>4;isNaN(h)?e=f=64:(e=(15&h)<<2|i>>6,f=isNaN(i)?64:63&i),c+=b.charAt(j)+b.charAt(k)+b.charAt(e)+b.charAt(f)}return c}};ca.addInfoReader(/^image/,function(a,b){if(!a.__dimensions){var c=a.__dimensions=ca.defer();ca.readAsImage(a,function(a){var b=a.target;c.resolve("load"==a.type?!1:"error",{width:b.width,height:b.height}),b.src=ca.EMPTY_PNG,b=null})}a.__dimensions.then(b)}),ca.event.dnd=function(a,b,c){var d,e;c||(c=b,b=ca.F),z?(Z(a,"dragenter dragleave dragover",b.ff=b.ff||function(a){for(var c=l(a).types,f=c&&c.length,g=!1;f--;)if(~c[f].indexOf("File")){a[V](),e!==a.type&&(e=a.type,"dragleave"!=e&&b.call(a[U],!0,a),g=!0);break}g&&(clearTimeout(d),d=setTimeout(function(){b.call(a[U],"dragleave"!=e,a)},50))}),Z(a,"drop",c.ff=c.ff||function(a){a[V](),e=0,b.call(a[U],!1,a),ca.getDropFiles(a,function(b,d){c.call(a[U],b,d,a)})})):ca.log("Drag'n'Drop -- not supported")},ca.event.dnd.off=function(a,b,c){$(a,"dragenter dragleave dragover",b.ff),$(a,"drop",c.ff)},C&&!C.fn.dnd&&(C.fn.dnd=function(a,b){return this.each(function(){ca.event.dnd(this,a,b)})},C.fn.offdnd=function(a,b){return this.each(function(){ca.event.dnd.off(this,a,b)})}),a.FileAPI=Y(ca,a.FileAPI),ca.log("FileAPI: "+ca.version),ca.log("protocol: "+a.location.protocol),ca.log("doctype: ["+s.name+"] "+s.publicId+" "+s.systemId),X(r.getElementsByTagName("meta"),function(a){/x-ua-compatible/i.test(a.getAttribute("http-equiv"))&&ca.log("meta.http-equiv: "+a.getAttribute("content"))});try{n=!!console.log,o=!!console.log.apply}catch(da){}ca.flashUrl||(ca.flashUrl=ca.staticPath+"FileAPI.flash.swf"),ca.flashImageUrl||(ca.flashImageUrl=ca.staticPath+"FileAPI.flash.image.swf"),ca.flashWebcamUrl||(ca.flashWebcamUrl=ca.staticPath+"FileAPI.flash.camera.swf")}(window,void 0),function(a,b,c){"use strict";function d(b){if(b instanceof d){var c=new d(b.file);return a.extend(c.matrix,b.matrix),c}return this instanceof d?(this.file=b,this.size=b.size||100,void(this.matrix={sx:0,sy:0,sw:0,sh:0,dx:0,dy:0,dw:0,dh:0,resize:0,deg:0,quality:1,filter:0})):new d(b)}var e=Math.min,f=Math.round,g=function(){return b.createElement("canvas")},h=!1,i={8:270,3:180,6:90,7:270,4:180,5:90};try{h=g().toDataURL("image/png").indexOf("data:image/png")>-1}catch(j){}d.prototype={image:!0,constructor:d,set:function(b){return a.extend(this.matrix,b),this},crop:function(a,b,d,e){return d===c&&(d=a,e=b,a=b=0),this.set({sx:a,sy:b,sw:d,sh:e||d})},resize:function(a,b,c){return/min|max|height|width/.test(b)&&(c=b,b=a),this.set({dw:a,dh:b||a,resize:c})},preview:function(a,b){return this.resize(a,b||a,"preview")},rotate:function(a){return this.set({deg:a})},filter:function(a){return this.set({filter:a})},overlay:function(a){return this.set({overlay:a})},clone:function(){return new d(this)},_load:function(b,c){var d=this;/img|video/i.test(b.nodeName)?c.call(d,null,b):a.readAsImage(b,function(a){c.call(d,"load"!=a.type,a.result)})},_apply:function(b,c){var f,h=g(),i=this.getMatrix(b),j=h.getContext("2d"),k=b.videoWidth||b.width,l=b.videoHeight||b.height,m=i.deg,n=i.dw,o=i.dh,p=k,q=l,r=i.filter,s=b,t=i.overlay,u=a.queue(function(){b.src=a.EMPTY_PNG,c(!1,h)}),v=a.renderImageToCanvas;for(m-=360*Math.floor(m/360),b._type=this.file.type;i.multipass&&e(p/n,q/o)>2;)p=p/2+.5|0,q=q/2+.5|0,f=g(),f.width=p,f.height=q,s!==b?(v(f,s,0,0,s.width,s.height,0,0,p,q),s=f):(s=f,v(s,b,i.sx,i.sy,i.sw,i.sh,0,0,p,q),i.sx=i.sy=i.sw=i.sh=0);h.width=m%180?o:n,h.height=m%180?n:o,h.type=i.type,h.quality=i.quality,j.rotate(m*Math.PI/180),v(j.canvas,s,i.sx,i.sy,i.sw||s.width,i.sh||s.height,180==m||270==m?-n:0,90==m||180==m?-o:0,n,o),n=h.width,o=h.height,t&&a.each([].concat(t),function(b){u.inc();var c=new window.Image,d=function(){var e=0|b.x,f=0|b.y,g=b.w||c.width,h=b.h||c.height,i=b.rel;e=1==i||4==i||7==i?(n-g+e)/2:2==i||5==i||8==i?n-(g+e):e,f=3==i||4==i||5==i?(o-h+f)/2:i>=6?o-(h+f):f,a.event.off(c,"error load abort",d);try{j.globalAlpha=b.opacity||1,j.drawImage(c,e,f,g,h)}catch(k){}u.next()};a.event.on(c,"error load abort",d),c.src=b.src,c.complete&&d()}),r&&(u.inc(),d.applyFilter(h,r,u.next)),u.check()},getMatrix:function(b){var c=a.extend({},this.matrix),d=c.sw=c.sw||b.videoWidth||b.naturalWidth||b.width,g=c.sh=c.sh||b.videoHeight||b.naturalHeight||b.height,h=c.dw=c.dw||d,i=c.dh=c.dh||g,j=d/g,k=h/i,l=c.resize;if("preview"==l){if(h!=d||i!=g){var m,n;k>=j?(m=d,n=m/k):(n=g,m=n*k),(m!=d||n!=g)&&(c.sx=~~((d-m)/2),c.sy=~~((g-n)/2),d=m,g=n)}}else"height"==l?h=i*j:"width"==l?i=h/j:l&&(d>h||g>i?"min"==l?(h=f(k>j?e(d,h):i*j),i=f(k>j?h/j:e(g,i))):(h=f(j>=k?e(d,h):i*j),i=f(j>=k?h/j:e(g,i))):(h=d,i=g));return c.sw=d,c.sh=g,c.dw=h,c.dh=i,c.multipass=a.multiPassResize,c},_trans:function(b){this._load(this.file,function(c,d){if(c)b(c);else try{this._apply(d,b)}catch(c){a.log("[err] FileAPI.Image.fn._apply:",c),b(c)}})},get:function(b){if(a.support.transform){var c=this,d=c.matrix;"auto"==d.deg?a.getInfo(c.file,function(a,e){d.deg=i[e&&e.exif&&e.exif.Orientation]||0,c._trans(b)}):c._trans(b)}else b("not_support_transform");return this},toData:function(a){return this.get(a)}},d.exifOrientation=i,d.transform=function(b,e,f,g){function h(h,i){var j={},k=a.queue(function(a){g(a,j)});h?k.fail():a.each(e,function(a,e){if(!k.isFail()){var g=new d(i.nodeType?i:b),h="function"==typeof a;if(h?a(i,g):a.width?g[a.preview?"preview":"resize"](a.width,a.height,a.strategy):a.maxWidth&&(i.width>a.maxWidth||i.height>a.maxHeight)&&g.resize(a.maxWidth,a.maxHeight,"max"),a.crop){var l=a.crop;g.crop(0|l.x,0|l.y,l.w||l.width,l.h||l.height)}a.rotate===c&&f&&(a.rotate="auto"),g.set({type:g.matrix.type||a.type||b.type||"image/png"}),h||g.set({deg:a.rotate,overlay:a.overlay,filter:a.filter,quality:a.quality||1}),k.inc(),g.toData(function(a,b){a?k.fail():(j[e]=b,k.next())})}})}b.width?h(!1,b):a.getInfo(b,h)},a.each(["TOP","CENTER","BOTTOM"],function(b,c){a.each(["LEFT","CENTER","RIGHT"],function(a,e){d[b+"_"+a]=3*c+e,d[a+"_"+b]=3*c+e})}),d.toCanvas=function(a){var c=b.createElement("canvas");return c.width=a.videoWidth||a.width,c.height=a.videoHeight||a.height,c.getContext("2d").drawImage(a,0,0),c},d.fromDataURL=function(b,c,d){var e=a.newImage(b);a.extend(e,c),d(e)},d.applyFilter=function(b,c,e){"function"==typeof c?c(b,e):window.Caman&&window.Caman("IMG"==b.tagName?d.toCanvas(b):b,function(){"string"==typeof c?this[c]():a.each(c,function(a,b){this[b](a)},this),this.render(e)})},a.renderImageToCanvas=function(b,c,d,e,f,g,h,i,j,k){try{return b.getContext("2d").drawImage(c,d,e,f,g,h,i,j,k)}catch(l){throw a.log("renderImageToCanvas failed"),l}},a.support.canvas=a.support.transform=h,a.Image=d}(FileAPI,document),function(a){"use strict";a(FileAPI)}(function(a){"use strict";if(window.navigator&&window.navigator.platform&&/iP(hone|od|ad)/.test(window.navigator.platform)){var b=a.renderImageToCanvas;a.detectSubsampling=function(a){var b,c;return a.width*a.height>1048576?(b=document.createElement("canvas"),b.width=b.height=1,c=b.getContext("2d"),c.drawImage(a,-a.width+1,0),0===c.getImageData(0,0,1,1).data[3]):!1},a.detectVerticalSquash=function(a,b){var c,d,e,f,g,h=a.naturalHeight||a.height,i=document.createElement("canvas"),j=i.getContext("2d");for(b&&(h/=2),i.width=1,i.height=h,j.drawImage(a,0,0),c=j.getImageData(0,0,1,h).data,d=0,e=h,f=h;f>d;)g=c[4*(f-1)+3],0===g?e=f:d=f,f=e+d>>1;return f/h||1},a.renderImageToCanvas=function(c,d,e,f,g,h,i,j,k,l){if("image/jpeg"===d._type){var m,n,o,p,q=c.getContext("2d"),r=document.createElement("canvas"),s=1024,t=r.getContext("2d");if(r.width=s,r.height=s,q.save(),m=a.detectSubsampling(d),m&&(e/=2,f/=2,g/=2,h/=2),n=a.detectVerticalSquash(d,m),m||1!==n){for(f*=n,k=Math.ceil(s*k/g),l=Math.ceil(s*l/h/n),j=0,p=0;h>p;){for(i=0,o=0;g>o;)t.clearRect(0,0,s,s),t.drawImage(d,e,f,g,h,-o,-p,g,h),q.drawImage(r,0,0,s,s,i,j,k,l),o+=s,i+=k;p+=s,j+=l}return q.restore(),c}}return b(c,d,e,f,g,h,i,j,k,l)}}}),function(a,b){"use strict";function c(b,c,d){var e=b.blob,f=b.file;if(f){if(!e.toDataURL)return void a.readAsBinaryString(e,function(a){"load"==a.type&&c(b,a.result)});var g={"image/jpeg":".jpe?g","image/png":".png"},h=g[b.type]?b.type:"image/png",i=g[h]||".png",j=e.quality||1;f.match(new RegExp(i+"$","i"))||(f+=i.replace("?","")),b.file=f,b.type=h,!d&&e.toBlob?e.toBlob(function(a){c(b,a)},h,j):c(b,a.toBinaryString(e.toDataURL(h,j)))}else c(b,e)}var d=b.document,e=b.FormData,f=function(){this.items=[]},g=b.encodeURIComponent;f.prototype={append:function(a,b,c,d){this.items.push({name:a,blob:b&&b.blob||(void 0==b?"":b),file:b&&(c||b.name),type:b&&(d||b.type)})},each:function(a){for(var b=0,c=this.items.length;c>b;b++)a.call(this,this.items[b])},toData:function(b,c){c._chunked=a.support.chunked&&c.chunkSize>0&&1==a.filter(this.items,function(a){return a.file}).length,a.support.html5?a.formData&&!this.multipart&&e?c._chunked?(a.log("FileAPI.Form.toPlainData"),this.toPlainData(b)):(a.log("FileAPI.Form.toFormData"),this.toFormData(b)):(a.log("FileAPI.Form.toMultipartData"),this.toMultipartData(b)):(a.log("FileAPI.Form.toHtmlData"),this.toHtmlData(b))},_to:function(b,c,d,e){var f=a.queue(function(){c(b)});this.each(function(g){try{d(g,b,f,e)}catch(h){a.log("FileAPI.Form._to: "+h.message),c(h)}}),f.check()},toHtmlData:function(b){this._to(d.createDocumentFragment(),b,function(b,c){var e,f=b.blob;b.file?(a.reset(f,!0),f.name=b.name,f.disabled=!1,c.appendChild(f)):(e=d.createElement("input"),e.name=b.name,e.type="hidden",e.value=f,c.appendChild(e))})},toPlainData:function(a){this._to({},a,function(a,b,d){a.file&&(b.type=a.file),a.blob.toBlob?(d.inc(),c(a,function(a,c){b.name=a.name,b.file=c,b.size=c.length,b.type=a.type,d.next()})):a.file?(b.name=a.blob.name,b.file=a.blob,b.size=a.blob.size,b.type=a.type):(b.params||(b.params=[]),b.params.push(g(a.name)+"="+g(a.blob))),b.start=-1,b.end=b.file&&b.file.FileAPIReadPosition||-1,b.retry=0})},toFormData:function(a){this._to(new e,a,function(a,b,d){a.blob&&a.blob.toBlob?(d.inc(),c(a,function(a,c){b.append(a.name,c,a.file),d.next()})):a.file?b.append(a.name,a.blob,a.file):b.append(a.name,a.blob),a.file&&b.append("_"+a.name,a.file)})},toMultipartData:function(b){this._to([],b,function(a,b,d,e){d.inc(),c(a,function(a,c){b.push("--_"+e+('\r\nContent-Disposition: form-data; name="'+a.name+'"'+(a.file?'; filename="'+g(a.file)+'"':"")+(a.file?"\r\nContent-Type: "+(a.type||"application/octet-stream"):"")+"\r\n\r\n"+(a.file?c:g(c))+"\r\n")),d.next()},!0)},a.expando)}},a.Form=f}(FileAPI,window),function(a,b){"use strict";var c=function(){},d=a.document,e=function(a){this.uid=b.uid(),this.xhr={abort:c,getResponseHeader:c,getAllResponseHeaders:c},this.options=a},f={"":1,XML:1,Text:1,Body:1};e.prototype={status:0,statusText:"",constructor:e,getResponseHeader:function(a){return this.xhr.getResponseHeader(a)},getAllResponseHeaders:function(){return this.xhr.getAllResponseHeaders()||{}},end:function(d,e){var f=this,g=f.options;f.end=f.abort=c,f.status=d,e&&(f.statusText=e),b.log("xhr.end:",d,e),g.complete(200==d||201==d?!1:f.statusText||"unknown",f),f.xhr&&f.xhr.node&&setTimeout(function(){var b=f.xhr.node;try{b.parentNode.removeChild(b)}catch(c){}try{delete a[f.uid]}catch(c){}a[f.uid]=f.xhr.node=null},9)},abort:function(){this.end(0,"abort"),this.xhr&&(this.xhr.aborted=!0,this.xhr.abort())},send:function(a){var b=this,c=this.options;a.toData(function(a){a instanceof Error?b.end(0,a.message):(c.upload(c,b),b._send.call(b,c,a))},c)},_send:function(c,e){var g,h=this,i=h.uid,j=h.uid+"Load",k=c.url;if(b.log("XHR._send:",e),c.cache||(k+=(~k.indexOf("?")?"&":"?")+b.uid()),e.nodeName){var l=c.jsonp;k=k.replace(/([a-z]+)=(\?)/i,"$1="+i),c.upload(c,h);var m=function(a){if(~k.indexOf(a.origin))try{var c=b.parseJSON(a.data);c.id==i&&n(c.status,c.statusText,c.response)}catch(d){n(0,d.message)}},n=a[i]=function(c,d,e){h.readyState=4,h.responseText=e,h.end(c,d),b.event.off(a,"message",m),a[i]=g=p=a[j]=null};h.xhr.abort=function(){try{p.stop?p.stop():p.contentWindow.stop?p.contentWindow.stop():p.contentWindow.document.execCommand("Stop")}catch(a){}n(0,"abort")},b.event.on(a,"message",m),a[j]=function(){try{var a=p.contentWindow,c=a.document,d=a.result||b.parseJSON(c.body.innerHTML);n(d.status,d.statusText,d.response)}catch(e){b.log("[transport.onload]",e)}},g=d.createElement("div"),g.innerHTML='
'+(l&&c.url.indexOf("=?")<0?'':"")+"
";var o=g.getElementsByTagName("form")[0],p=g.getElementsByTagName("iframe")[0];o.appendChild(e),b.log(o.parentNode.innerHTML),d.body.appendChild(g),h.xhr.node=g,h.readyState=2;try{o.submit()}catch(q){b.log("iframe.error: "+q)}o=null}else{if(k=k.replace(/([a-z]+)=(\?)&?/i,""),this.xhr&&this.xhr.aborted)return void b.log("Error: already aborted");if(g=h.xhr=b.getXHR(),e.params&&(k+=(k.indexOf("?")<0?"?":"&")+e.params.join("&")),g.open("POST",k,!0),b.withCredentials&&(g.withCredentials="true"),c.headers&&c.headers["X-Requested-With"]||g.setRequestHeader("X-Requested-With","XMLHttpRequest"),b.each(c.headers,function(a,b){g.setRequestHeader(b,a)}),c._chunked){g.upload&&g.upload.addEventListener("progress",b.throttle(function(a){e.retry||c.progress({type:a.type,total:e.size,loaded:e.start+a.loaded,totalSize:e.size},h,c)},100),!1),g.onreadystatechange=function(){var a=parseInt(g.getResponseHeader("X-Last-Known-Byte"),10);if(h.status=g.status,h.statusText=g.statusText,h.readyState=g.readyState,4==g.readyState){for(var d in f)h["response"+d]=g["response"+d];if(g.onreadystatechange=null,!g.status||g.status-201>0)if(b.log("Error: "+g.status),(!g.status&&!g.aborted||500==g.status||416==g.status)&&++e.retry<=c.chunkUploadRetry){var i=g.status?0:b.chunkNetworkDownRetryTimeout;c.pause(e.file,c),b.log("X-Last-Known-Byte: "+a),a?e.end=a:(e.end=e.start-1,416==g.status&&(e.end=e.end-c.chunkSize)),setTimeout(function(){h._send(c,e)},i)}else h.end(g.status);else e.retry=0,e.end==e.size-1?h.end(g.status):(b.log("X-Last-Known-Byte: "+a),a&&(e.end=a),e.file.FileAPIReadPosition=e.end,setTimeout(function(){h._send(c,e)},0));g=null}},e.start=e.end+1,e.end=Math.max(Math.min(e.start+c.chunkSize,e.size)-1,e.start);var r=e.file,s=(r.slice||r.mozSlice||r.webkitSlice).call(r,e.start,e.end+1);e.size&&!s.size?setTimeout(function(){h.end(-1)}):(g.setRequestHeader("Content-Range","bytes "+e.start+"-"+e.end+"/"+e.size),g.setRequestHeader("Content-Disposition","attachment; filename="+encodeURIComponent(e.name)),g.setRequestHeader("Content-Type",e.type||"application/octet-stream"),g.send(s)),r=s=null}else if(g.upload&&g.upload.addEventListener("progress",b.throttle(function(a){c.progress(a,h,c)},100),!1),g.onreadystatechange=function(){if(h.status=g.status,h.statusText=g.statusText,h.readyState=g.readyState,4==g.readyState){for(var a in f)h["response"+a]=g["response"+a];if(g.onreadystatechange=null,!g.status||g.status>201)if(b.log("Error: "+g.status),(!g.status&&!g.aborted||500==g.status)&&(c.retry||0)=0?a+"px":a}function d(a){var c,d=f.createElement("canvas"),e=!1;try{c=d.getContext("2d"),c.drawImage(a,0,0,1,1),e=255!=c.getImageData(0,0,1,1).data[4]}catch(g){b.log("[FileAPI.Camera] detectVideoSignal:",g)}return e}var e=a.URL||a.webkitURL,f=a.document,g=a.navigator,h=g.getUserMedia||g.webkitGetUserMedia||g.mozGetUserMedia||g.msGetUserMedia,i=!!h;b.support.media=i;var j=function(a){this.video=a};j.prototype={isActive:function(){return!!this._active},start:function(a){var b,c,f=this,i=f.video,j=function(d){f._active=!d,clearTimeout(c),clearTimeout(b),a&&a(d,f)};h.call(g,{video:!0},function(a){f.stream=a,i.src=e.createObjectURL(a),b=setInterval(function(){d(i)&&j(null)},1e3),c=setTimeout(function(){j("timeout"); -},5e3),i.play()},j)},stop:function(){try{this._active=!1,this.video.pause();try{this.stream.stop()}catch(a){b.each(this.stream.getTracks(),function(a){a.stop()})}this.stream=null}catch(a){b.log("[FileAPI.Camera] stop:",a)}},shot:function(){return new k(this.video)}},j.get=function(a){return new j(a.firstChild)},j.publish=function(d,e,g){"function"==typeof e&&(g=e,e={}),e=b.extend({},{width:"100%",height:"100%",start:!0},e),d.jquery&&(d=d[0]);var h=function(a){if(a)g(a);else{var b=j.get(d);e.start?b.start(g):g(null,b)}};if(d.style.width=c(e.width),d.style.height=c(e.height),b.html5&&i){var k=f.createElement("video");k.style.width=c(e.width),k.style.height=c(e.height),a.jQuery?jQuery(d).empty():d.innerHTML="",d.appendChild(k),h()}else j.fallback(d,e,h)},j.fallback=function(a,b,c){c("not_support_camera")};var k=function(a){var c=a.nodeName?b.Image.toCanvas(a):a,d=b.Image(c);return d.type="image/png",d.width=c.width,d.height=c.height,d.size=c.width*c.height*4,d};j.Shot=k,b.Camera=j}(window,FileAPI),function(a,b,c){"use strict";var d=c.each,e=[];!c.support.flash||!c.media||c.support.media&&c.html5||!function(){function a(a){var b=a.wid=c.uid();return c.Flash._fn[b]=a,"FileAPI.Flash._fn."+b}function b(a){try{c.Flash._fn[a.wid]=null,delete c.Flash._fn[a.wid]}catch(b){}}var f=c.Flash;c.extend(c.Flash,{patchCamera:function(){c.Camera.fallback=function(d,e,g){var h=c.uid();c.log("FlashAPI.Camera.publish: "+h),f.publish(d,h,c.extend(e,{camera:!0,onEvent:a(function i(a){"camera"===a.type&&(b(i),a.error?(c.log("FlashAPI.Camera.publish.error: "+a.error),g(a.error)):(c.log("FlashAPI.Camera.publish.success: "+h),g(null)))})}))},d(e,function(a){c.Camera.fallback.apply(c.Camera,a)}),e=[],c.extend(c.Camera.prototype,{_id:function(){return this.video.id},start:function(d){var e=this;f.cmd(this._id(),"camera.on",{callback:a(function g(a){b(g),a.error?(c.log("FlashAPI.camera.on.error: "+a.error),d(a.error,e)):(c.log("FlashAPI.camera.on.success: "+e._id()),e._active=!0,d(null,e))})})},stop:function(){this._active=!1,f.cmd(this._id(),"camera.off")},shot:function(){c.log("FlashAPI.Camera.shot:",this._id());var a=c.Flash.cmd(this._id(),"shot",{});return a.type="image/png",a.flashId=this._id(),a.isShot=!0,new c.Camera.Shot(a)}})}}),c.Camera.fallback=function(){e.push(arguments)}}()}(window,window.jQuery,FileAPI),"function"==typeof define&&define.amd&&define("FileAPI",[],function(){return FileAPI}); \ No newline at end of file diff --git a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.js b/manager/media/browser/mcpuk/js/FileAPI/FileAPI.js deleted file mode 100644 index 6b2e14b72d..0000000000 --- a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.js +++ /dev/null @@ -1,4361 +0,0 @@ -/*! FileAPI 2.0.19 - BSD | git://github.com/mailru/FileAPI.git - * FileAPI — a set of javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF. - */ - -/* - * JavaScript Canvas to Blob 2.0.5 - * https://github.com/blueimp/JavaScript-Canvas-to-Blob - * - * Copyright 2012, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT - * - * Based on stackoverflow user Stoive's code snippet: - * http://stackoverflow.com/q/4998908 - */ - -/*jslint nomen: true, regexp: true */ -/*global window, atob, Blob, ArrayBuffer, Uint8Array */ - -(function (window) { - 'use strict'; - var CanvasPrototype = window.HTMLCanvasElement && - window.HTMLCanvasElement.prototype, - hasBlobConstructor = window.Blob && (function () { - try { - return Boolean(new Blob()); - } catch (e) { - return false; - } - }()), - hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && - (function () { - try { - return new Blob([new Uint8Array(100)]).size === 100; - } catch (e) { - return false; - } - }()), - BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || - window.MozBlobBuilder || window.MSBlobBuilder, - dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob && - window.ArrayBuffer && window.Uint8Array && function (dataURI) { - var byteString, - arrayBuffer, - intArray, - i, - mimeString, - bb; - if (dataURI.split(',')[0].indexOf('base64') >= 0) { - // Convert base64 to raw binary data held in a string: - byteString = atob(dataURI.split(',')[1]); - } else { - // Convert base64/URLEncoded data component to raw binary data: - byteString = decodeURIComponent(dataURI.split(',')[1]); - } - // Write the bytes of the string to an ArrayBuffer: - arrayBuffer = new ArrayBuffer(byteString.length); - intArray = new Uint8Array(arrayBuffer); - for (i = 0; i < byteString.length; i += 1) { - intArray[i] = byteString.charCodeAt(i); - } - // Separate out the mime component: - mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; - // Write the ArrayBuffer (or ArrayBufferView) to a blob: - if (hasBlobConstructor) { - return new Blob( - [hasArrayBufferViewSupport ? intArray : arrayBuffer], - {type: mimeString} - ); - } - bb = new BlobBuilder(); - bb.append(arrayBuffer); - return bb.getBlob(mimeString); - }; - if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) { - if (CanvasPrototype.mozGetAsFile) { - CanvasPrototype.toBlob = function (callback, type, quality) { - if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) { - callback(dataURLtoBlob(this.toDataURL(type, quality))); - } else { - callback(this.mozGetAsFile('blob', type)); - } - }; - } else if (CanvasPrototype.toDataURL && dataURLtoBlob) { - CanvasPrototype.toBlob = function (callback, type, quality) { - callback(dataURLtoBlob(this.toDataURL(type, quality))); - }; - } - } - window.dataURLtoBlob = dataURLtoBlob; -})(window); - -/*jslint evil: true */ -/*global window, URL, webkitURL, ActiveXObject */ - -(function (window, undef){ - 'use strict'; - - var - gid = 1, - noop = function (){}, - - document = window.document, - doctype = document.doctype || {}, - userAgent = window.navigator.userAgent, - safari = /safari\//i.test(userAgent) && !/chrome\//i.test(userAgent), - iemobile = /iemobile\//i.test(userAgent), - - // https://github.com/blueimp/JavaScript-Load-Image/blob/master/load-image.js#L48 - apiURL = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL), - - Blob = window.Blob, - File = window.File, - FileReader = window.FileReader, - FormData = window.FormData, - - - XMLHttpRequest = window.XMLHttpRequest, - jQuery = window.jQuery, - - html5 = !!(File && (FileReader && (window.Uint8Array || FormData || XMLHttpRequest.prototype.sendAsBinary))) - && !(safari && /windows/i.test(userAgent) && !iemobile), // BugFix: https://github.com/mailru/FileAPI/issues/25 - - cors = html5 && ('withCredentials' in (new XMLHttpRequest)), - - chunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice), - - normalize = ('' + ''.normalize).indexOf('[native code]') > 0, - - // https://github.com/blueimp/JavaScript-Canvas-to-Blob - dataURLtoBlob = window.dataURLtoBlob, - - - _rimg = /img/i, - _rcanvas = /canvas/i, - _rimgcanvas = /img|canvas/i, - _rinput = /input/i, - _rdata = /^data:[^,]+,/, - - _toString = {}.toString, - _supportConsoleLog, - _supportConsoleLogApply, - - - Math = window.Math, - - _SIZE_CONST = function (pow){ - pow = new window.Number(Math.pow(1024, pow)); - pow.from = function (sz){ return Math.round(sz * this); }; - return pow; - }, - - _elEvents = {}, // element event listeners - _infoReader = [], // list of file info processors - - _readerEvents = 'abort progress error load loadend', - _xhrPropsExport = 'status statusText readyState response responseXML responseText responseBody'.split(' '), - - currentTarget = 'currentTarget', // for minimize - preventDefault = 'preventDefault', // and this too - - _isArray = function (ar) { - return ar && ('length' in ar); - }, - - /** - * Iterate over a object or array - */ - _each = function (obj, fn, ctx){ - if( obj ){ - if( _isArray(obj) ){ - for( var i = 0, n = obj.length; i < n; i++ ){ - if( i in obj ){ - fn.call(ctx, obj[i], i, obj); - } - } - } - else { - for( var key in obj ){ - if( obj.hasOwnProperty(key) ){ - fn.call(ctx, obj[key], key, obj); - } - } - } - } - }, - - /** - * Merge the contents of two or more objects together into the first object - */ - _extend = function (dst){ - var args = arguments, i = 1, _ext = function (val, key){ dst[key] = val; }; - for( ; i < args.length; i++ ){ - _each(args[i], _ext); - } - return dst; - }, - - /** - * Add event listener - */ - _on = function (el, type, fn){ - if( el ){ - var uid = api.uid(el); - - if( !_elEvents[uid] ){ - _elEvents[uid] = {}; - } - - var isFileReader = (FileReader && el) && (el instanceof FileReader); - _each(type.split(/\s+/), function (type){ - if( jQuery && !isFileReader){ - jQuery.event.add(el, type, fn); - } else { - if( !_elEvents[uid][type] ){ - _elEvents[uid][type] = []; - } - - _elEvents[uid][type].push(fn); - - if( el.addEventListener ){ el.addEventListener(type, fn, false); } - else if( el.attachEvent ){ el.attachEvent('on'+type, fn); } - else { el['on'+type] = fn; } - } - }); - } - }, - - - /** - * Remove event listener - */ - _off = function (el, type, fn){ - if( el ){ - var uid = api.uid(el), events = _elEvents[uid] || {}; - - var isFileReader = (FileReader && el) && (el instanceof FileReader); - _each(type.split(/\s+/), function (type){ - if( jQuery && !isFileReader){ - jQuery.event.remove(el, type, fn); - } - else { - var fns = events[type] || [], i = fns.length; - - while( i-- ){ - if( fns[i] === fn ){ - fns.splice(i, 1); - break; - } - } - - if( el.addEventListener ){ el.removeEventListener(type, fn, false); } - else if( el.detachEvent ){ el.detachEvent('on'+type, fn); } - else { el['on'+type] = null; } - } - }); - } - }, - - - _one = function(el, type, fn){ - _on(el, type, function _(evt){ - _off(el, type, _); - fn(evt); - }); - }, - - - _fixEvent = function (evt){ - if( !evt.target ){ evt.target = window.event && window.event.srcElement || document; } - if( evt.target.nodeType === 3 ){ evt.target = evt.target.parentNode; } - return evt; - }, - - - _supportInputAttr = function (attr){ - var input = document.createElement('input'); - input.setAttribute('type', "file"); - return attr in input; - }, - - - /** - * FileAPI (core object) - */ - api = { - version: '2.0.19', - - cors: false, - html5: true, - media: false, - formData: true, - multiPassResize: true, - - debug: false, - pingUrl: false, - multiFlash: false, - flashAbortTimeout: 0, - withCredentials: true, - - staticPath: './dist/', - - flashUrl: 0, // @default: './FileAPI.flash.swf' - flashImageUrl: 0, // @default: './FileAPI.flash.image.swf' - - postNameConcat: function (name, idx){ - return name + (idx != null ? '['+ idx +']' : ''); - }, - - ext2mime: { - jpg: 'image/jpeg' - , tif: 'image/tiff' - , txt: 'text/plain' - }, - - // Fallback for flash - accept: { - 'image/*': 'art bm bmp dwg dxf cbr cbz fif fpx gif ico iefs jfif jpe jpeg jpg jps jut mcf nap nif pbm pcx pgm pict pm png pnm qif qtif ras rast rf rp svf tga tif tiff xbm xbm xpm xwd' - , 'audio/*': 'm4a flac aac rm mpa wav wma ogg mp3 mp2 m3u mod amf dmf dsm far gdm imf it m15 med okt s3m stm sfx ult uni xm sid ac3 dts cue aif aiff wpl ape mac mpc mpp shn wv nsf spc gym adplug adx dsp adp ymf ast afc hps xs' - , 'video/*': 'm4v 3gp nsv ts ty strm rm rmvb m3u ifo mov qt divx xvid bivx vob nrg img iso pva wmv asf asx ogm m2v avi bin dat dvr-ms mpg mpeg mp4 mkv avc vp3 svq3 nuv viv dv fli flv wpl' - }, - - uploadRetry : 0, - networkDownRetryTimeout : 5000, // milliseconds, don't flood when network is down - - chunkSize : 0, - chunkUploadRetry : 0, - chunkNetworkDownRetryTimeout : 2000, // milliseconds, don't flood when network is down - - KB: _SIZE_CONST(1), - MB: _SIZE_CONST(2), - GB: _SIZE_CONST(3), - TB: _SIZE_CONST(4), - - EMPTY_PNG: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII=', - - expando: 'fileapi' + (new Date).getTime(), - - uid: function (obj){ - return obj - ? (obj[api.expando] = obj[api.expando] || api.uid()) - : (++gid, api.expando + gid) - ; - }, - - log: function (){ - if( api.debug && _supportConsoleLog ){ - if( _supportConsoleLogApply ){ - console.log.apply(console, arguments); - } - else { - console.log([].join.call(arguments, ' ')); - } - } - }, - - /** - * Create new image - * - * @param {String} [src] - * @param {Function} [fn] 1. error -- boolean, 2. img -- Image element - * @returns {HTMLElement} - */ - newImage: function (src, fn){ - var img = document.createElement('img'); - if( fn ){ - api.event.one(img, 'error load', function (evt){ - fn(evt.type == 'error', img); - img = null; - }); - } - img.src = src; - return img; - }, - - /** - * Get XHR - * @returns {XMLHttpRequest} - */ - getXHR: function (){ - var xhr; - - if( XMLHttpRequest ){ - xhr = new XMLHttpRequest; - } - else if( window.ActiveXObject ){ - try { - xhr = new ActiveXObject('MSXML2.XMLHttp.3.0'); - } catch (e) { - xhr = new ActiveXObject('Microsoft.XMLHTTP'); - } - } - - return xhr; - }, - - isArray: _isArray, - - support: { - dnd: cors && ('ondrop' in document.createElement('div')), - cors: cors, - html5: html5, - chunked: chunked, - dataURI: true, - accept: _supportInputAttr('accept'), - multiple: _supportInputAttr('multiple') - }, - - event: { - on: _on - , off: _off - , one: _one - , fix: _fixEvent - }, - - - throttle: function(fn, delay) { - var id, args; - - return function _throttle(){ - args = arguments; - - if( !id ){ - fn.apply(window, args); - id = setTimeout(function (){ - id = 0; - fn.apply(window, args); - }, delay); - } - }; - }, - - - F: function (){}, - - - parseJSON: function (str){ - var json; - if( window.JSON && JSON.parse ){ - json = JSON.parse(str); - } - else { - json = (new Function('return ('+str.replace(/([\r\n])/g, '\\$1')+');'))(); - } - return json; - }, - - - trim: function (str){ - str = String(str); - return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); - }, - - /** - * Simple Defer - * @return {Object} - */ - defer: function (){ - var - list = [] - , result - , error - , defer = { - resolve: function (err, res){ - defer.resolve = noop; - error = err || false; - result = res; - - while( res = list.shift() ){ - res(error, result); - } - }, - - then: function (fn){ - if( error !== undef ){ - fn(error, result); - } else { - list.push(fn); - } - } - }; - - return defer; - }, - - queue: function (fn){ - var - _idx = 0 - , _length = 0 - , _fail = false - , _end = false - , queue = { - inc: function (){ - _length++; - }, - - next: function (){ - _idx++; - setTimeout(queue.check, 0); - }, - - check: function (){ - (_idx >= _length) && !_fail && queue.end(); - }, - - isFail: function (){ - return _fail; - }, - - fail: function (){ - !_fail && fn(_fail = true); - }, - - end: function (){ - if( !_end ){ - _end = true; - fn(); - } - } - } - ; - return queue; - }, - - - /** - * For each object - * - * @param {Object|Array} obj - * @param {Function} fn - * @param {*} [ctx] - */ - each: _each, - - - /** - * Async for - * @param {Array} array - * @param {Function} callback - */ - afor: function (array, callback){ - var i = 0, n = array.length; - - if( _isArray(array) && n-- ){ - (function _next(){ - callback(n != i && _next, array[i], i++); - })(); - } - else { - callback(false); - } - }, - - - /** - * Merge the contents of two or more objects together into the first object - * - * @param {Object} dst - * @return {Object} - */ - extend: _extend, - - - /** - * Is file? - * @param {File} file - * @return {Boolean} - */ - isFile: function (file){ - return _toString.call(file) === '[object File]'; - }, - - - /** - * Is blob? - * @param {Blob} blob - * @returns {Boolean} - */ - isBlob: function (blob) { - return this.isFile(blob) || (_toString.call(blob) === '[object Blob]'); - }, - - - /** - * Is canvas element - * - * @param {HTMLElement} el - * @return {Boolean} - */ - isCanvas: function (el){ - return el && _rcanvas.test(el.nodeName); - }, - - - getFilesFilter: function (filter){ - filter = typeof filter == 'string' ? filter : (filter.getAttribute && filter.getAttribute('accept') || ''); - return filter ? new RegExp('('+ filter.replace(/\./g, '\\.').replace(/,/g, '|') +')$', 'i') : /./; - }, - - - - /** - * Read as DataURL - * - * @param {File|Element} file - * @param {Function} fn - */ - readAsDataURL: function (file, fn){ - if( api.isCanvas(file) ){ - _emit(file, fn, 'load', api.toDataURL(file)); - } - else { - _readAs(file, fn, 'DataURL'); - } - }, - - - /** - * Read as Binary string - * - * @param {File} file - * @param {Function} fn - */ - readAsBinaryString: function (file, fn){ - if( _hasSupportReadAs('BinaryString') ){ - _readAs(file, fn, 'BinaryString'); - } else { - // Hello IE10! - _readAs(file, function (evt){ - if( evt.type == 'load' ){ - try { - // dataURL -> binaryString - evt.result = api.toBinaryString(evt.result); - } catch (e){ - evt.type = 'error'; - evt.message = e.toString(); - } - } - fn(evt); - }, 'DataURL'); - } - }, - - - /** - * Read as ArrayBuffer - * - * @param {File} file - * @param {Function} fn - */ - readAsArrayBuffer: function(file, fn){ - _readAs(file, fn, 'ArrayBuffer'); - }, - - - /** - * Read as text - * - * @param {File} file - * @param {String} encoding - * @param {Function} [fn] - */ - readAsText: function(file, encoding, fn){ - if( !fn ){ - fn = encoding; - encoding = 'utf-8'; - } - - _readAs(file, fn, 'Text', encoding); - }, - - - /** - * Convert image or canvas to DataURL - * - * @param {Element} el Image or Canvas element - * @param {String} [type] mime-type - * @return {String} - */ - toDataURL: function (el, type){ - if( typeof el == 'string' ){ - return el; - } - else if( el.toDataURL ){ - return el.toDataURL(type || 'image/png'); - } - }, - - - /** - * Canvert string, image or canvas to binary string - * - * @param {String|Element} val - * @return {String} - */ - toBinaryString: function (val){ - return window.atob(api.toDataURL(val).replace(_rdata, '')); - }, - - - /** - * Read file or DataURL as ImageElement - * - * @param {File|String} file - * @param {Function} fn - * @param {Boolean} [progress] - */ - readAsImage: function (file, fn, progress){ - if( api.isBlob(file) ){ - if( apiURL ){ - /** @namespace apiURL.createObjectURL */ - var data = apiURL.createObjectURL(file); - if( data === undef ){ - _emit(file, fn, 'error'); - } - else { - api.readAsImage(data, fn, progress); - } - } - else { - api.readAsDataURL(file, function (evt){ - if( evt.type == 'load' ){ - api.readAsImage(evt.result, fn, progress); - } - else if( progress || evt.type == 'error' ){ - _emit(file, fn, evt, null, { loaded: evt.loaded, total: evt.total }); - } - }); - } - } - else if( api.isCanvas(file) ){ - _emit(file, fn, 'load', file); - } - else if( _rimg.test(file.nodeName) ){ - if( file.complete ){ - _emit(file, fn, 'load', file); - } - else { - var events = 'error abort load'; - _one(file, events, function _fn(evt){ - if( evt.type == 'load' && apiURL ){ - /** @namespace apiURL.revokeObjectURL */ - apiURL.revokeObjectURL(file.src); - } - - _off(file, events, _fn); - _emit(file, fn, evt, file); - }); - } - } - else if( file.iframe ){ - _emit(file, fn, { type: 'error' }); - } - else { - // Created image - var img = api.newImage(file.dataURL || file); - api.readAsImage(img, fn, progress); - } - }, - - - /** - * Make file by name - * - * @param {String} name - * @return {Array} - */ - checkFileObj: function (name){ - var file = {}, accept = api.accept; - - if( typeof name == 'object' ){ - file = name; - } - else { - file.name = (name + '').split(/\\|\//g).pop(); - } - - if( file.type == null ){ - file.type = file.name.split('.').pop(); - } - - _each(accept, function (ext, type){ - ext = new RegExp(ext.replace(/\s/g, '|'), 'i'); - if( ext.test(file.type) || api.ext2mime[file.type] ){ - file.type = api.ext2mime[file.type] || (type.split('/')[0] +'/'+ file.type); - } - }); - - return file; - }, - - - /** - * Get drop files - * - * @param {Event} evt - * @param {Function} callback - */ - getDropFiles: function (evt, callback){ - var - files = [] - , all = [] - , items - , dataTransfer = _getDataTransfer(evt) - , transFiles = dataTransfer.files - , transItems = dataTransfer.items - , entrySupport = _isArray(transItems) && transItems[0] && _getAsEntry(transItems[0]) - , queue = api.queue(function (){ callback(files, all); }) - ; - - if( entrySupport ){ - if( normalize && transFiles ){ - var - i = transFiles.length - , file - , entry - ; - - items = new Array(i); - while( i-- ){ - file = transFiles[i]; - - try { - entry = _getAsEntry(transItems[i]); - } - catch( err ){ - api.log('[err] getDropFiles: ', err); - entry = null; - } - - if( _isEntry(entry) ){ - // OSX filesystems use Unicode Normalization Form D (NFD), - // and entry.file(…) can't read the files with the same names - if( entry.isDirectory || (entry.isFile && file.name == file.name.normalize('NFC')) ){ - items[i] = entry; - } - else { - items[i] = file; - } - } - else { - items[i] = file; - } - } - } - else { - items = transItems; - } - } - else { - items = transFiles; - } - - _each(items || [], function (item){ - queue.inc(); - - try { - if( entrySupport && _isEntry(item) ){ - _readEntryAsFiles(item, function (err, entryFiles, allEntries){ - if( err ){ - api.log('[err] getDropFiles:', err); - } else { - files.push.apply(files, entryFiles); - } - all.push.apply(all, allEntries); - - queue.next(); - }); - } - else { - _isRegularFile(item, function (yes, err){ - if( yes ){ - files.push(item); - } - else { - item.error = err; - } - all.push(item); - - queue.next(); - }); - } - } - catch( err ){ - queue.next(); - api.log('[err] getDropFiles: ', err); - } - }); - - queue.check(); - }, - - - /** - * Get file list - * - * @param {HTMLInputElement|Event} input - * @param {String|Function} [filter] - * @param {Function} [callback] - * @return {Array|Null} - */ - getFiles: function (input, filter, callback){ - var files = []; - - if( callback ){ - api.filterFiles(api.getFiles(input), filter, callback); - return null; - } - - if( input.jquery ){ - // jQuery object - input.each(function (){ - files = files.concat(api.getFiles(this)); - }); - input = files; - files = []; - } - - if( typeof filter == 'string' ){ - filter = api.getFilesFilter(filter); - } - - if( input.originalEvent ){ - // jQuery event - input = _fixEvent(input.originalEvent); - } - else if( input.srcElement ){ - // IE Event - input = _fixEvent(input); - } - - - if( input.dataTransfer ){ - // Drag'n'Drop - input = input.dataTransfer; - } - else if( input.target ){ - // Event - input = input.target; - } - - if( input.files ){ - // Input[type="file"] - files = input.files; - - if( !html5 ){ - // Partial support for file api - files[0].blob = input; - files[0].iframe = true; - } - } - else if( !html5 && isInputFile(input) ){ - if( api.trim(input.value) ){ - files = [api.checkFileObj(input.value)]; - files[0].blob = input; - files[0].iframe = true; - } - } - else if( _isArray(input) ){ - files = input; - } - - return api.filter(files, function (file){ return !filter || filter.test(file.name); }); - }, - - - /** - * Get total file size - * @param {Array} files - * @return {Number} - */ - getTotalSize: function (files){ - var size = 0, i = files && files.length; - while( i-- ){ - size += files[i].size; - } - return size; - }, - - - /** - * Get image information - * - * @param {File} file - * @param {Function} fn - */ - getInfo: function (file, fn){ - var info = {}, readers = _infoReader.concat(); - - if( api.isBlob(file) ){ - (function _next(){ - var reader = readers.shift(); - if( reader ){ - if( reader.test(file.type) ){ - reader(file, function (err, res){ - if( err ){ - fn(err); - } - else { - _extend(info, res); - _next(); - } - }); - } - else { - _next(); - } - } - else { - fn(false, info); - } - })(); - } - else { - fn('not_support_info', info); - } - }, - - - /** - * Add information reader - * - * @param {RegExp} mime - * @param {Function} fn - */ - addInfoReader: function (mime, fn){ - fn.test = function (type){ return mime.test(type); }; - _infoReader.push(fn); - }, - - - /** - * Filter of array - * - * @param {Array} input - * @param {Function} fn - * @return {Array} - */ - filter: function (input, fn){ - var result = [], i = 0, n = input.length, val; - - for( ; i < n; i++ ){ - if( i in input ){ - val = input[i]; - if( fn.call(val, val, i, input) ){ - result.push(val); - } - } - } - - return result; - }, - - - /** - * Filter files - * - * @param {Array} files - * @param {Function} eachFn - * @param {Function} resultFn - */ - filterFiles: function (files, eachFn, resultFn){ - if( files.length ){ - // HTML5 or Flash - var queue = files.concat(), file, result = [], deleted = []; - - (function _next(){ - if( queue.length ){ - file = queue.shift(); - api.getInfo(file, function (err, info){ - (eachFn(file, err ? false : info) ? result : deleted).push(file); - _next(); - }); - } - else { - resultFn(result, deleted); - } - })(); - } - else { - resultFn([], files); - } - }, - - - upload: function (options){ - options = _extend({ - jsonp: 'callback' - , prepare: api.F - , beforeupload: api.F - , upload: api.F - , fileupload: api.F - , fileprogress: api.F - , filecomplete: api.F - , progress: api.F - , complete: api.F - , pause: api.F - , imageOriginal: true - , chunkSize: api.chunkSize - , chunkUploadRetry: api.chunkUploadRetry - , uploadRetry: api.uploadRetry - }, options); - - - if( options.imageAutoOrientation && !options.imageTransform ){ - options.imageTransform = { rotate: 'auto' }; - } - - - var - proxyXHR = new api.XHR(options) - , dataArray = this._getFilesDataArray(options.files) - , _this = this - , _total = 0 - , _loaded = 0 - , _nextFile - , _complete = false - ; - - - // calc total size - _each(dataArray, function (data){ - _total += data.size; - }); - - // Array of files - proxyXHR.files = []; - _each(dataArray, function (data){ - proxyXHR.files.push(data.file); - }); - - // Set upload status props - proxyXHR.total = _total; - proxyXHR.loaded = 0; - proxyXHR.filesLeft = dataArray.length; - - // emit "beforeupload" event - options.beforeupload(proxyXHR, options); - - // Upload by file - _nextFile = function (){ - var - data = dataArray.shift() - , _file = data && data.file - , _fileLoaded = false - , _fileOptions = _simpleClone(options) - ; - - proxyXHR.filesLeft = dataArray.length; - - if( _file && _file.name === api.expando ){ - _file = null; - api.log('[warn] FileAPI.upload() — called without files'); - } - - if( ( proxyXHR.statusText != 'abort' || proxyXHR.current ) && data ){ - // Mark active job - _complete = false; - - // Set current upload file - proxyXHR.currentFile = _file; - - // Prepare file options - if (_file && options.prepare(_file, _fileOptions) === false) { - _nextFile.call(_this); - return; - } - _fileOptions.file = _file; - - _this._getFormData(_fileOptions, data, function (form){ - if( !_loaded ){ - // emit "upload" event - options.upload(proxyXHR, options); - } - - var xhr = new api.XHR(_extend({}, _fileOptions, { - - upload: _file ? function (){ - // emit "fileupload" event - options.fileupload(_file, xhr, _fileOptions); - } : noop, - - progress: _file ? function (evt){ - if( !_fileLoaded ){ - // For ignore the double calls. - _fileLoaded = (evt.loaded === evt.total); - - // emit "fileprogress" event - options.fileprogress({ - type: 'progress' - , total: data.total = evt.total - , loaded: data.loaded = evt.loaded - }, _file, xhr, _fileOptions); - - // emit "progress" event - options.progress({ - type: 'progress' - , total: _total - , loaded: proxyXHR.loaded = (_loaded + data.size * (evt.loaded/evt.total)) || 0 - }, _file, xhr, _fileOptions); - } - } : noop, - - complete: function (err){ - _each(_xhrPropsExport, function (name){ - proxyXHR[name] = xhr[name]; - }); - - if( _file ){ - data.total = (data.total || data.size); - data.loaded = data.total; - - if( !err ) { - // emulate 100% "progress" - this.progress(data); - - // fixed throttle event - _fileLoaded = true; - - // bytes loaded - _loaded += data.size; // data.size != data.total, it's desirable fix this - proxyXHR.loaded = _loaded; - } - - // emit "filecomplete" event - options.filecomplete(err, xhr, _file, _fileOptions); - } - - // upload next file - setTimeout(function () {_nextFile.call(_this);}, 0); - } - })); // xhr - - - // ... - proxyXHR.abort = function (current){ - if (!current) { dataArray.length = 0; } - this.current = current; - xhr.abort(); - }; - - // Start upload - xhr.send(form); - }); - } - else { - var successful = proxyXHR.status == 200 || proxyXHR.status == 201 || proxyXHR.status == 204; - options.complete(successful ? false : (proxyXHR.statusText || 'error'), proxyXHR, options); - // Mark done state - _complete = true; - } - }; - - - // Next tick - setTimeout(_nextFile, 0); - - - // Append more files to the existing request - // first - add them to the queue head/tail - proxyXHR.append = function (files, first) { - files = api._getFilesDataArray([].concat(files)); - - _each(files, function (data) { - _total += data.size; - proxyXHR.files.push(data.file); - if (first) { - dataArray.unshift(data); - } else { - dataArray.push(data); - } - }); - - proxyXHR.statusText = ""; - - if( _complete ){ - _nextFile.call(_this); - } - }; - - - // Removes file from queue by file reference and returns it - proxyXHR.remove = function (file) { - var i = dataArray.length, _file; - while( i-- ){ - if( dataArray[i].file == file ){ - _file = dataArray.splice(i, 1); - _total -= _file.size; - } - } - return _file; - }; - - return proxyXHR; - }, - - - _getFilesDataArray: function (data){ - var files = [], oFiles = {}; - - if( isInputFile(data) ){ - var tmp = api.getFiles(data); - oFiles[data.name || 'file'] = data.getAttribute('multiple') !== null ? tmp : tmp[0]; - } - else if( _isArray(data) && isInputFile(data[0]) ){ - _each(data, function (input){ - oFiles[input.name || 'file'] = api.getFiles(input); - }); - } - else { - oFiles = data; - } - - _each(oFiles, function add(file, name){ - if( _isArray(file) ){ - _each(file, function (file){ - add(file, name); - }); - } - else if( file && (file.name || file.image) ){ - files.push({ - name: name - , file: file - , size: file.size - , total: file.size - , loaded: 0 - }); - } - }); - - if( !files.length ){ - // Create fake `file` object - files.push({ file: { name: api.expando } }); - } - - return files; - }, - - - _getFormData: function (options, data, fn){ - var - file = data.file - , name = data.name - , filename = file.name - , filetype = file.type - , trans = api.support.transform && options.imageTransform - , Form = new api.Form - , queue = api.queue(function (){ fn(Form); }) - , isOrignTrans = trans && _isOriginTransform(trans) - , postNameConcat = api.postNameConcat - ; - - // Append data - _each(options.data, function add(val, name){ - if( typeof val == 'object' ){ - _each(val, function (v, i){ - add(v, postNameConcat(name, i)); - }); - } - else { - Form.append(name, val); - } - }); - - (function _addFile(file/**Object*/){ - if( file.image ){ // This is a FileAPI.Image - queue.inc(); - - file.toData(function (err, image){ - // @todo: требует рефакторинга и обработки ошибки - if (file.file) { - image.type = file.file.type; - image.quality = file.matrix.quality; - filename = file.file && file.file.name; - } - - filename = filename || (new Date).getTime()+'.png'; - - _addFile(image); - queue.next(); - }); - } - else if( api.Image && trans && (/^image/.test(file.type) || _rimgcanvas.test(file.nodeName)) ){ - queue.inc(); - - if( isOrignTrans ){ - // Convert to array for transform function - trans = [trans]; - } - - api.Image.transform(file, trans, options.imageAutoOrientation, function (err, images){ - if( isOrignTrans && !err ){ - if( !dataURLtoBlob && !api.flashEngine ){ - // Canvas.toBlob or Flash not supported, use multipart - Form.multipart = true; - } - - Form.append(name, images[0], filename, trans[0].type || filetype); - } - else { - var addOrigin = 0; - - if( !err ){ - _each(images, function (image, idx){ - if( !dataURLtoBlob && !api.flashEngine ){ - Form.multipart = true; - } - - if( !trans[idx].postName ){ - addOrigin = 1; - } - - Form.append(trans[idx].postName || postNameConcat(name, idx), image, filename, trans[idx].type || filetype); - }); - } - - if( err || options.imageOriginal ){ - Form.append(postNameConcat(name, (addOrigin ? 'original' : null)), file, filename, filetype); - } - } - - queue.next(); - }); - } - else if( filename !== api.expando ){ - Form.append(name, file, filename); - } - })(file); - - queue.check(); - }, - - - reset: function (inp, notRemove){ - var parent, clone; - - if( jQuery ){ - clone = jQuery(inp).clone(true).insertBefore(inp).val('')[0]; - if( !notRemove ){ - jQuery(inp).remove(); - } - } else { - parent = inp.parentNode; - clone = parent.insertBefore(inp.cloneNode(true), inp); - clone.value = ''; - - if( !notRemove ){ - parent.removeChild(inp); - } - - _each(_elEvents[api.uid(inp)], function (fns, type){ - _each(fns, function (fn){ - _off(inp, type, fn); - _on(clone, type, fn); - }); - }); - } - - return clone; - }, - - - /** - * Load remote file - * - * @param {String} url - * @param {Function} fn - * @return {XMLHttpRequest} - */ - load: function (url, fn){ - var xhr = api.getXHR(); - if( xhr ){ - xhr.open('GET', url, true); - - if( xhr.overrideMimeType ){ - xhr.overrideMimeType('text/plain; charset=x-user-defined'); - } - - _on(xhr, 'progress', function (/**Event*/evt){ - /** @namespace evt.lengthComputable */ - if( evt.lengthComputable ){ - fn({ type: evt.type, loaded: evt.loaded, total: evt.total }, xhr); - } - }); - - xhr.onreadystatechange = function(){ - if( xhr.readyState == 4 ){ - xhr.onreadystatechange = null; - if( xhr.status == 200 ){ - url = url.split('/'); - /** @namespace xhr.responseBody */ - var file = { - name: url[url.length-1] - , size: xhr.getResponseHeader('Content-Length') - , type: xhr.getResponseHeader('Content-Type') - }; - file.dataURL = 'data:'+file.type+';base64,' + api.encode64(xhr.responseBody || xhr.responseText); - fn({ type: 'load', result: file }, xhr); - } - else { - fn({ type: 'error' }, xhr); - } - } - }; - xhr.send(null); - } else { - fn({ type: 'error' }); - } - - return xhr; - }, - - encode64: function (str){ - var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', outStr = '', i = 0; - - if( typeof str !== 'string' ){ - str = String(str); - } - - while( i < str.length ){ - //all three "& 0xff" added below are there to fix a known bug - //with bytes returned by xhr.responseText - var - byte1 = str.charCodeAt(i++) & 0xff - , byte2 = str.charCodeAt(i++) & 0xff - , byte3 = str.charCodeAt(i++) & 0xff - , enc1 = byte1 >> 2 - , enc2 = ((byte1 & 3) << 4) | (byte2 >> 4) - , enc3, enc4 - ; - - if( isNaN(byte2) ){ - enc3 = enc4 = 64; - } else { - enc3 = ((byte2 & 15) << 2) | (byte3 >> 6); - enc4 = isNaN(byte3) ? 64 : byte3 & 63; - } - - outStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4); - } - - return outStr; - } - - } // api - ; - - - function _emit(target, fn, name, res, ext){ - var evt = { - type: name.type || name - , target: target - , result: res - }; - _extend(evt, ext); - fn(evt); - } - - - function _hasSupportReadAs(method){ - return FileReader && !!FileReader.prototype['readAs' + method]; - } - - - function _readAs(file, fn, method, encoding){ - if( api.isBlob(file) && _hasSupportReadAs(method) ){ - var Reader = new FileReader; - - // Add event listener - _on(Reader, _readerEvents, function _fn(evt){ - var type = evt.type; - if( type == 'progress' ){ - _emit(file, fn, evt, evt.target.result, { loaded: evt.loaded, total: evt.total }); - } - else if( type == 'loadend' ){ - _off(Reader, _readerEvents, _fn); - Reader = null; - } - else { - _emit(file, fn, evt, evt.target.result); - } - }); - - - try { - // ReadAs ... - if( encoding ){ - Reader['readAs' + method](file, encoding); - } - else { - Reader['readAs' + method](file); - } - } - catch (err){ - _emit(file, fn, 'error', undef, { error: err.toString() }); - } - } - else { - _emit(file, fn, 'error', undef, { error: 'filreader_not_support_' + method }); - } - } - - - function _isRegularFile(file, callback){ - // http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects - if( !file.type && (safari || ((file.size % 4096) === 0 && (file.size <= 102400))) ){ - if( FileReader ){ - try { - var reader = new FileReader(); - - _one(reader, _readerEvents, function (evt){ - var isFile = evt.type != 'error'; - if( isFile ){ - if ( reader.readyState == null || reader.readyState === reader.LOADING ) { - reader.abort(); - } - callback(isFile); - } - else { - callback(false, reader.error); - } - }); - - reader.readAsDataURL(file); - } catch( err ){ - callback(false, err); - } - } - else { - callback(null, new Error('FileReader is not supported')); - } - } - else { - callback(true); - } - } - - - function _isEntry(item){ - return item && (item.isFile || item.isDirectory); - } - - - function _getAsEntry(item){ - var entry; - if( item.getAsEntry ){ entry = item.getAsEntry(); } - else if( item.webkitGetAsEntry ){ entry = item.webkitGetAsEntry(); } - return entry; - } - - - function _readEntryAsFiles(entry, callback){ - if( !entry ){ - // error - var err = new Error('invalid entry'); - entry = new Object(entry); - entry.error = err; - callback(err.message, [], [entry]); - } - else if( entry.isFile ){ - // Read as file - entry.file(function (file){ - // success - file.fullPath = entry.fullPath; - callback(false, [file], [file]); - }, function (err){ - // error - entry.error = err; - callback('FileError.code: ' + err.code, [], [entry]); - }); - } - else if( entry.isDirectory ){ - var - reader = entry.createReader() - , firstAttempt = true - , files = [] - , all = [entry] - ; - - var onerror = function (err){ - // error - entry.error = err; - callback('DirectoryError.code: ' + err.code, files, all); - }; - var ondone = function ondone(entries){ - if( firstAttempt ){ - firstAttempt = false; - if( !entries.length ){ - entry.error = new Error('directory is empty'); - } - } - - // success - if( entries.length ){ - api.afor(entries, function (next, entry){ - _readEntryAsFiles(entry, function (err, entryFiles, allEntries){ - if( !err ){ - files = files.concat(entryFiles); - } - all = all.concat(allEntries); - - if( next ){ - next(); - } - else { - reader.readEntries(ondone, onerror); - } - }); - }); - } - else { - callback(false, files, all); - } - }; - - reader.readEntries(ondone, onerror); - } - else { - _readEntryAsFiles(_getAsEntry(entry), callback); - } - } - - - function _simpleClone(obj){ - var copy = {}; - _each(obj, function (val, key){ - if( val && (typeof val === 'object') && (val.nodeType === void 0) ){ - val = _extend({}, val); - } - copy[key] = val; - }); - return copy; - } - - - function isInputFile(el){ - return _rinput.test(el && el.tagName); - } - - - function _getDataTransfer(evt){ - return (evt.originalEvent || evt || '').dataTransfer || {}; - } - - - function _isOriginTransform(trans){ - var key; - for( key in trans ){ - if( trans.hasOwnProperty(key) ){ - if( !(trans[key] instanceof Object || key === 'overlay' || key === 'filter') ){ - return true; - } - } - } - return false; - } - - - // Add default image info reader - api.addInfoReader(/^image/, function (file/**File*/, callback/**Function*/){ - if( !file.__dimensions ){ - var defer = file.__dimensions = api.defer(); - - api.readAsImage(file, function (evt){ - var img = evt.target; - defer.resolve(evt.type == 'load' ? false : 'error', { - width: img.width - , height: img.height - }); - img.src = api.EMPTY_PNG; - img = null; - }); - } - - file.__dimensions.then(callback); - }); - - - /** - * Drag'n'Drop special event - * - * @param {HTMLElement} el - * @param {Function} onHover - * @param {Function} onDrop - */ - api.event.dnd = function (el, onHover, onDrop){ - var _id, _type; - - if( !onDrop ){ - onDrop = onHover; - onHover = api.F; - } - - if( FileReader ){ - // Hover - _on(el, 'dragenter dragleave dragover', onHover.ff = onHover.ff || function (evt){ - var - types = _getDataTransfer(evt).types - , i = types && types.length - , debounceTrigger = false - ; - - while( i-- ){ - if( ~types[i].indexOf('File') ){ - evt[preventDefault](); - - if( _type !== evt.type ){ - _type = evt.type; // Store current type of event - - if( _type != 'dragleave' ){ - onHover.call(evt[currentTarget], true, evt); - } - - debounceTrigger = true; - } - - break; // exit from "while" - } - } - - if( debounceTrigger ){ - clearTimeout(_id); - _id = setTimeout(function (){ - onHover.call(evt[currentTarget], _type != 'dragleave', evt); - }, 50); - } - }); - - - // Drop - _on(el, 'drop', onDrop.ff = onDrop.ff || function (evt){ - evt[preventDefault](); - - _type = 0; - onHover.call(evt[currentTarget], false, evt); - - api.getDropFiles(evt, function (files, all){ - onDrop.call(evt[currentTarget], files, all, evt); - }); - }); - } - else { - api.log("Drag'n'Drop -- not supported"); - } - }; - - - /** - * Remove drag'n'drop - * @param {HTMLElement} el - * @param {Function} onHover - * @param {Function} onDrop - */ - api.event.dnd.off = function (el, onHover, onDrop){ - _off(el, 'dragenter dragleave dragover', onHover.ff); - _off(el, 'drop', onDrop.ff); - }; - - - // Support jQuery - if( jQuery && !jQuery.fn.dnd ){ - jQuery.fn.dnd = function (onHover, onDrop){ - return this.each(function (){ - api.event.dnd(this, onHover, onDrop); - }); - }; - - jQuery.fn.offdnd = function (onHover, onDrop){ - return this.each(function (){ - api.event.dnd.off(this, onHover, onDrop); - }); - }; - } - - // @export - window.FileAPI = _extend(api, window.FileAPI); - - - // Debug info - api.log('FileAPI: ' + api.version); - api.log('protocol: ' + window.location.protocol); - api.log('doctype: [' + doctype.name + '] ' + doctype.publicId + ' ' + doctype.systemId); - - - // @detect 'x-ua-compatible' - _each(document.getElementsByTagName('meta'), function (meta){ - if( /x-ua-compatible/i.test(meta.getAttribute('http-equiv')) ){ - api.log('meta.http-equiv: ' + meta.getAttribute('content')); - } - }); - - - // Configuration - try { - _supportConsoleLog = !!console.log; - _supportConsoleLogApply = !!console.log.apply; - } - catch (err) {} - - if( !api.flashUrl ){ api.flashUrl = api.staticPath + 'FileAPI.flash.swf'; } - if( !api.flashImageUrl ){ api.flashImageUrl = api.staticPath + 'FileAPI.flash.image.swf'; } - if( !api.flashWebcamUrl ){ api.flashWebcamUrl = api.staticPath + 'FileAPI.flash.camera.swf'; } -})(window, void 0); - -/*global window, FileAPI, document */ - -(function (api, document, undef) { - 'use strict'; - - var - min = Math.min, - round = Math.round, - getCanvas = function () { return document.createElement('canvas'); }, - support = false, - exifOrientation = { - 8: 270 - , 3: 180 - , 6: 90 - , 7: 270 - , 4: 180 - , 5: 90 - } - ; - - try { - support = getCanvas().toDataURL('image/png').indexOf('data:image/png') > -1; - } - catch (e){} - - - function Image(file){ - if( file instanceof Image ){ - var img = new Image(file.file); - api.extend(img.matrix, file.matrix); - return img; - } - else if( !(this instanceof Image) ){ - return new Image(file); - } - - this.file = file; - this.size = file.size || 100; - - this.matrix = { - sx: 0, - sy: 0, - sw: 0, - sh: 0, - dx: 0, - dy: 0, - dw: 0, - dh: 0, - resize: 0, // min, max OR preview - deg: 0, - quality: 1, // jpeg quality - filter: 0 - }; - } - - - Image.prototype = { - image: true, - constructor: Image, - - set: function (attrs){ - api.extend(this.matrix, attrs); - return this; - }, - - crop: function (x, y, w, h){ - if( w === undef ){ - w = x; - h = y; - x = y = 0; - } - return this.set({ sx: x, sy: y, sw: w, sh: h || w }); - }, - - resize: function (w, h, strategy){ - if( /min|max|height|width/.test(h) ){ - strategy = h; - h = w; - } - - return this.set({ dw: w, dh: h || w, resize: strategy }); - }, - - preview: function (w, h){ - return this.resize(w, h || w, 'preview'); - }, - - rotate: function (deg){ - return this.set({ deg: deg }); - }, - - filter: function (filter){ - return this.set({ filter: filter }); - }, - - overlay: function (images){ - return this.set({ overlay: images }); - }, - - clone: function (){ - return new Image(this); - }, - - _load: function (image, fn){ - var self = this; - - if( /img|video/i.test(image.nodeName) ){ - fn.call(self, null, image); - } - else { - api.readAsImage(image, function (evt){ - fn.call(self, evt.type != 'load', evt.result); - }); - } - }, - - _apply: function (image, fn){ - var - canvas = getCanvas() - , m = this.getMatrix(image) - , ctx = canvas.getContext('2d') - , width = image.videoWidth || image.width - , height = image.videoHeight || image.height - , deg = m.deg - , dw = m.dw - , dh = m.dh - , w = width - , h = height - , filter = m.filter - , copy // canvas copy - , buffer = image - , overlay = m.overlay - , queue = api.queue(function (){ image.src = api.EMPTY_PNG; fn(false, canvas); }) - , renderImageToCanvas = api.renderImageToCanvas - ; - - // Normalize angle - deg = deg - Math.floor(deg/360)*360; - - // For `renderImageToCanvas` - image._type = this.file.type; - - while(m.multipass && min(w/dw, h/dh) > 2 ){ - w = (w/2 + 0.5)|0; - h = (h/2 + 0.5)|0; - - copy = getCanvas(); - copy.width = w; - copy.height = h; - - if( buffer !== image ){ - renderImageToCanvas(copy, buffer, 0, 0, buffer.width, buffer.height, 0, 0, w, h); - buffer = copy; - } - else { - buffer = copy; - renderImageToCanvas(buffer, image, m.sx, m.sy, m.sw, m.sh, 0, 0, w, h); - m.sx = m.sy = m.sw = m.sh = 0; - } - } - - - canvas.width = (deg % 180) ? dh : dw; - canvas.height = (deg % 180) ? dw : dh; - - canvas.type = m.type; - canvas.quality = m.quality; - - ctx.rotate(deg * Math.PI / 180); - renderImageToCanvas(ctx.canvas, buffer - , m.sx, m.sy - , m.sw || buffer.width - , m.sh || buffer.height - , (deg == 180 || deg == 270 ? -dw : 0) - , (deg == 90 || deg == 180 ? -dh : 0) - , dw, dh - ); - dw = canvas.width; - dh = canvas.height; - - // Apply overlay - overlay && api.each([].concat(overlay), function (over){ - queue.inc(); - // preload - var img = new window.Image, fn = function (){ - var - x = over.x|0 - , y = over.y|0 - , w = over.w || img.width - , h = over.h || img.height - , rel = over.rel - ; - - // center | right | left - x = (rel == 1 || rel == 4 || rel == 7) ? (dw - w + x)/2 : (rel == 2 || rel == 5 || rel == 8 ? dw - (w + x) : x); - - // center | bottom | top - y = (rel == 3 || rel == 4 || rel == 5) ? (dh - h + y)/2 : (rel >= 6 ? dh - (h + y) : y); - - api.event.off(img, 'error load abort', fn); - - try { - ctx.globalAlpha = over.opacity || 1; - ctx.drawImage(img, x, y, w, h); - } - catch (er){} - - queue.next(); - }; - - api.event.on(img, 'error load abort', fn); - img.src = over.src; - - if( img.complete ){ - fn(); - } - }); - - if( filter ){ - queue.inc(); - Image.applyFilter(canvas, filter, queue.next); - } - - queue.check(); - }, - - getMatrix: function (image){ - var - m = api.extend({}, this.matrix) - , sw = m.sw = m.sw || image.videoWidth || image.naturalWidth || image.width - , sh = m.sh = m.sh || image.videoHeight || image.naturalHeight || image.height - , dw = m.dw = m.dw || sw - , dh = m.dh = m.dh || sh - , sf = sw/sh, df = dw/dh - , strategy = m.resize - ; - - if( strategy == 'preview' ){ - if( dw != sw || dh != sh ){ - // Make preview - var w, h; - - if( df >= sf ){ - w = sw; - h = w / df; - } else { - h = sh; - w = h * df; - } - - if( w != sw || h != sh ){ - m.sx = ~~((sw - w)/2); - m.sy = ~~((sh - h)/2); - sw = w; - sh = h; - } - } - } - else if( strategy == 'height' ){ - dw = dh * sf; - } - else if( strategy == 'width' ){ - dh = dw / sf; - } - else if( strategy ){ - if( !(sw > dw || sh > dh) ){ - dw = sw; - dh = sh; - } - else if( strategy == 'min' ){ - dw = round(sf < df ? min(sw, dw) : dh*sf); - dh = round(sf < df ? dw/sf : min(sh, dh)); - } - else { - dw = round(sf >= df ? min(sw, dw) : dh*sf); - dh = round(sf >= df ? dw/sf : min(sh, dh)); - } - } - - m.sw = sw; - m.sh = sh; - m.dw = dw; - m.dh = dh; - m.multipass = api.multiPassResize; - return m; - }, - - _trans: function (fn){ - this._load(this.file, function (err, image){ - if( err ){ - fn(err); - } - else { - try { - this._apply(image, fn); - } catch (err){ - api.log('[err] FileAPI.Image.fn._apply:', err); - fn(err); - } - } - }); - }, - - - get: function (fn){ - if( api.support.transform ){ - var _this = this, matrix = _this.matrix; - - if( matrix.deg == 'auto' ){ - api.getInfo(_this.file, function (err, info){ - // rotate by exif orientation - matrix.deg = exifOrientation[info && info.exif && info.exif.Orientation] || 0; - _this._trans(fn); - }); - } - else { - _this._trans(fn); - } - } - else { - fn('not_support_transform'); - } - - return this; - }, - - - toData: function (fn){ - return this.get(fn); - } - - }; - - - Image.exifOrientation = exifOrientation; - - - Image.transform = function (file, transform, autoOrientation, fn){ - function _transform(err, img){ - // img -- info object - var - images = {} - , queue = api.queue(function (err){ - fn(err, images); - }) - ; - - if( !err ){ - api.each(transform, function (params, name){ - if( !queue.isFail() ){ - var ImgTrans = new Image(img.nodeType ? img : file), isFn = typeof params == 'function'; - - if( isFn ){ - params(img, ImgTrans); - } - else if( params.width ){ - ImgTrans[params.preview ? 'preview' : 'resize'](params.width, params.height, params.strategy); - } - else { - if( params.maxWidth && (img.width > params.maxWidth || img.height > params.maxHeight) ){ - ImgTrans.resize(params.maxWidth, params.maxHeight, 'max'); - } - } - - if( params.crop ){ - var crop = params.crop; - ImgTrans.crop(crop.x|0, crop.y|0, crop.w || crop.width, crop.h || crop.height); - } - - if( params.rotate === undef && autoOrientation ){ - params.rotate = 'auto'; - } - - ImgTrans.set({ type: ImgTrans.matrix.type || params.type || file.type || 'image/png' }); - - if( !isFn ){ - ImgTrans.set({ - deg: params.rotate - , overlay: params.overlay - , filter: params.filter - , quality: params.quality || 1 - }); - } - - queue.inc(); - ImgTrans.toData(function (err, image){ - if( err ){ - queue.fail(); - } - else { - images[name] = image; - queue.next(); - } - }); - } - }); - } - else { - queue.fail(); - } - } - - - // @todo: Оло-ло, нужно рефакторить �то ме�то - if( file.width ){ - _transform(false, file); - } else { - api.getInfo(file, _transform); - } - }; - - - // @const - api.each(['TOP', 'CENTER', 'BOTTOM'], function (x, i){ - api.each(['LEFT', 'CENTER', 'RIGHT'], function (y, j){ - Image[x+'_'+y] = i*3 + j; - Image[y+'_'+x] = i*3 + j; - }); - }); - - - /** - * Trabsform element to canvas - * - * @param {Image|HTMLVideoElement} el - * @returns {Canvas} - */ - Image.toCanvas = function(el){ - var canvas = document.createElement('canvas'); - canvas.width = el.videoWidth || el.width; - canvas.height = el.videoHeight || el.height; - canvas.getContext('2d').drawImage(el, 0, 0); - return canvas; - }; - - - /** - * Create image from DataURL - * @param {String} dataURL - * @param {Object} size - * @param {Function} callback - */ - Image.fromDataURL = function (dataURL, size, callback){ - var img = api.newImage(dataURL); - api.extend(img, size); - callback(img); - }; - - - /** - * Apply filter (caman.js) - * - * @param {Canvas|Image} canvas - * @param {String|Function} filter - * @param {Function} doneFn - */ - Image.applyFilter = function (canvas, filter, doneFn){ - if( typeof filter == 'function' ){ - filter(canvas, doneFn); - } - else if( window.Caman ){ - // http://camanjs.com/guides/ - window.Caman(canvas.tagName == 'IMG' ? Image.toCanvas(canvas) : canvas, function (){ - if( typeof filter == 'string' ){ - this[filter](); - } - else { - api.each(filter, function (val, method){ - this[method](val); - }, this); - } - this.render(doneFn); - }); - } - }; - - - /** - * For load-image-ios.js - */ - api.renderImageToCanvas = function (canvas, img, sx, sy, sw, sh, dx, dy, dw, dh){ - try { - return canvas.getContext('2d').drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh); - } catch (ex) { - api.log('renderImageToCanvas failed'); - throw ex; - } - }; - - - // @export - api.support.canvas = api.support.transform = support; - api.Image = Image; -})(FileAPI, document); - -/* - * JavaScript Load Image iOS scaling fixes 1.0.3 - * https://github.com/blueimp/JavaScript-Load-Image - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * iOS image scaling fixes based on - * https://github.com/stomita/ios-imagefile-megapixel - * - * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT - */ - -/*jslint nomen: true, bitwise: true */ -/*global FileAPI, window, document */ - -(function (factory) { - 'use strict'; - factory(FileAPI); -}(function (loadImage) { - 'use strict'; - - // Only apply fixes on the iOS platform: - if (!window.navigator || !window.navigator.platform || - !(/iP(hone|od|ad)/).test(window.navigator.platform)) { - return; - } - - var originalRenderMethod = loadImage.renderImageToCanvas; - - // Detects subsampling in JPEG images: - loadImage.detectSubsampling = function (img) { - var canvas, - context; - if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images - canvas = document.createElement('canvas'); - canvas.width = canvas.height = 1; - context = canvas.getContext('2d'); - context.drawImage(img, -img.width + 1, 0); - // subsampled image becomes half smaller in rendering size. - // check alpha channel value to confirm image is covering edge pixel or not. - // if alpha value is 0 image is not covering, hence subsampled. - return context.getImageData(0, 0, 1, 1).data[3] === 0; - } - return false; - }; - - // Detects vertical squash in JPEG images: - loadImage.detectVerticalSquash = function (img, subsampled) { - var naturalHeight = img.naturalHeight || img.height, - canvas = document.createElement('canvas'), - context = canvas.getContext('2d'), - data, - sy, - ey, - py, - alpha; - if (subsampled) { - naturalHeight /= 2; - } - canvas.width = 1; - canvas.height = naturalHeight; - context.drawImage(img, 0, 0); - data = context.getImageData(0, 0, 1, naturalHeight).data; - // search image edge pixel position in case it is squashed vertically: - sy = 0; - ey = naturalHeight; - py = naturalHeight; - while (py > sy) { - alpha = data[(py - 1) * 4 + 3]; - if (alpha === 0) { - ey = py; - } else { - sy = py; - } - py = (ey + sy) >> 1; - } - return (py / naturalHeight) || 1; - }; - - // Renders image to canvas while working around iOS image scaling bugs: - // https://github.com/blueimp/JavaScript-Load-Image/issues/13 - loadImage.renderImageToCanvas = function ( - canvas, - img, - sourceX, - sourceY, - sourceWidth, - sourceHeight, - destX, - destY, - destWidth, - destHeight - ) { - if (img._type === 'image/jpeg') { - var context = canvas.getContext('2d'), - tmpCanvas = document.createElement('canvas'), - tileSize = 1024, - tmpContext = tmpCanvas.getContext('2d'), - subsampled, - vertSquashRatio, - tileX, - tileY; - tmpCanvas.width = tileSize; - tmpCanvas.height = tileSize; - context.save(); - subsampled = loadImage.detectSubsampling(img); - if (subsampled) { - sourceX /= 2; - sourceY /= 2; - sourceWidth /= 2; - sourceHeight /= 2; - } - vertSquashRatio = loadImage.detectVerticalSquash(img, subsampled); - if (subsampled || vertSquashRatio !== 1) { - sourceY *= vertSquashRatio; - destWidth = Math.ceil(tileSize * destWidth / sourceWidth); - destHeight = Math.ceil( - tileSize * destHeight / sourceHeight / vertSquashRatio - ); - destY = 0; - tileY = 0; - while (tileY < sourceHeight) { - destX = 0; - tileX = 0; - while (tileX < sourceWidth) { - tmpContext.clearRect(0, 0, tileSize, tileSize); - tmpContext.drawImage( - img, - sourceX, - sourceY, - sourceWidth, - sourceHeight, - -tileX, - -tileY, - sourceWidth, - sourceHeight - ); - context.drawImage( - tmpCanvas, - 0, - 0, - tileSize, - tileSize, - destX, - destY, - destWidth, - destHeight - ); - tileX += tileSize; - destX += destWidth; - } - tileY += tileSize; - destY += destHeight; - } - context.restore(); - return canvas; - } - } - return originalRenderMethod( - canvas, - img, - sourceX, - sourceY, - sourceWidth, - sourceHeight, - destX, - destY, - destWidth, - destHeight - ); - }; - -})); - -/*global window, FileAPI */ - -(function (api, window){ - "use strict"; - - var - document = window.document - , FormData = window.FormData - , Form = function (){ this.items = []; } - , encodeURIComponent = window.encodeURIComponent - ; - - - Form.prototype = { - - append: function (name, blob, file, type){ - this.items.push({ - name: name - , blob: blob && blob.blob || (blob == void 0 ? '' : blob) - , file: blob && (file || blob.name) - , type: blob && (type || blob.type) - }); - }, - - each: function (fn){ - var i = 0, n = this.items.length; - for( ; i < n; i++ ){ - fn.call(this, this.items[i]); - } - }, - - toData: function (fn, options){ - // allow chunked transfer if we have only one file to send - // flag is used below and in XHR._send - options._chunked = api.support.chunked && options.chunkSize > 0 && api.filter(this.items, function (item){ return item.file; }).length == 1; - - if( !api.support.html5 ){ - api.log('FileAPI.Form.toHtmlData'); - this.toHtmlData(fn); - } - else if( !api.formData || this.multipart || !FormData ){ - api.log('FileAPI.Form.toMultipartData'); - this.toMultipartData(fn); - } - else if( options._chunked ){ - api.log('FileAPI.Form.toPlainData'); - this.toPlainData(fn); - } - else { - api.log('FileAPI.Form.toFormData'); - this.toFormData(fn); - } - }, - - _to: function (data, complete, next, arg){ - var queue = api.queue(function (){ - complete(data); - }); - - this.each(function (file){ - try{ - next(file, data, queue, arg); - } - catch( err ){ - api.log('FileAPI.Form._to: ' + err.message); - complete(err); - } - }); - - queue.check(); - }, - - - toHtmlData: function (fn){ - this._to(document.createDocumentFragment(), fn, function (file, data/**DocumentFragment*/){ - var blob = file.blob, hidden; - - if( file.file ){ - api.reset(blob, true); - // set new name - blob.name = file.name; - blob.disabled = false; - data.appendChild(blob); - } - else { - hidden = document.createElement('input'); - hidden.name = file.name; - hidden.type = 'hidden'; - hidden.value = blob; - data.appendChild(hidden); - } - }); - }, - - toPlainData: function (fn){ - this._to({}, fn, function (file, data, queue){ - if( file.file ){ - data.type = file.file; - } - - if( file.blob.toBlob ){ - // canvas - queue.inc(); - _convertFile(file, function (file, blob){ - data.name = file.name; - data.file = blob; - data.size = blob.length; - data.type = file.type; - queue.next(); - }); - } - else if( file.file ){ - // file - data.name = file.blob.name; - data.file = file.blob; - data.size = file.blob.size; - data.type = file.type; - } - else { - // additional data - if( !data.params ){ - data.params = []; - } - data.params.push(encodeURIComponent(file.name) +"="+ encodeURIComponent(file.blob)); - } - - data.start = -1; - data.end = data.file && data.file.FileAPIReadPosition || -1; - data.retry = 0; - }); - }, - - toFormData: function (fn){ - this._to(new FormData, fn, function (file, data, queue){ - if( file.blob && file.blob.toBlob ){ - queue.inc(); - _convertFile(file, function (file, blob){ - data.append(file.name, blob, file.file); - queue.next(); - }); - } - else if( file.file ){ - data.append(file.name, file.blob, file.file); - } - else { - data.append(file.name, file.blob); - } - - if( file.file ){ - data.append('_'+file.name, file.file); - } - }); - }, - - - toMultipartData: function (fn){ - this._to([], fn, function (file, data, queue, boundary){ - queue.inc(); - _convertFile(file, function (file, blob){ - data.push( - '--_' + boundary + ('\r\nContent-Disposition: form-data; name="'+ file.name +'"'+ (file.file ? '; filename="'+ encodeURIComponent(file.file) +'"' : '') - + (file.file ? '\r\nContent-Type: '+ (file.type || 'application/octet-stream') : '') - + '\r\n' - + '\r\n'+ (file.file ? blob : encodeURIComponent(blob)) - + '\r\n') - ); - queue.next(); - }, true); - }, api.expando); - } - }; - - - function _convertFile(file, fn, useBinaryString){ - var blob = file.blob, filename = file.file; - - if( filename ){ - if( !blob.toDataURL ){ - // The Blob is not an image. - api.readAsBinaryString(blob, function (evt){ - if( evt.type == 'load' ){ - fn(file, evt.result); - } - }); - return; - } - - var - mime = { 'image/jpeg': '.jpe?g', 'image/png': '.png' } - , type = mime[file.type] ? file.type : 'image/png' - , ext = mime[type] || '.png' - , quality = blob.quality || 1 - ; - - if( !filename.match(new RegExp(ext+'$', 'i')) ){ - // Does not change the current extension, but add a new one. - filename += ext.replace('?', ''); - } - - file.file = filename; - file.type = type; - - if( !useBinaryString && blob.toBlob ){ - blob.toBlob(function (blob){ - fn(file, blob); - }, type, quality); - } - else { - fn(file, api.toBinaryString(blob.toDataURL(type, quality))); - } - } - else { - fn(file, blob); - } - } - - - // @export - api.Form = Form; -})(FileAPI, window); - -/*global window, FileAPI, Uint8Array */ - -(function (window, api){ - "use strict"; - - var - noop = function (){} - , document = window.document - - , XHR = function (options){ - this.uid = api.uid(); - this.xhr = { - abort: noop - , getResponseHeader: noop - , getAllResponseHeaders: noop - }; - this.options = options; - }, - - _xhrResponsePostfix = { '': 1, XML: 1, Text: 1, Body: 1 } - ; - - - XHR.prototype = { - status: 0, - statusText: '', - constructor: XHR, - - getResponseHeader: function (name){ - return this.xhr.getResponseHeader(name); - }, - - getAllResponseHeaders: function (){ - return this.xhr.getAllResponseHeaders() || {}; - }, - - end: function (status, statusText){ - var _this = this, options = _this.options; - - _this.end = - _this.abort = noop; - _this.status = status; - - if( statusText ){ - _this.statusText = statusText; - } - - api.log('xhr.end:', status, statusText); - options.complete(status == 200 || status == 201 ? false : _this.statusText || 'unknown', _this); - - if( _this.xhr && _this.xhr.node ){ - setTimeout(function (){ - var node = _this.xhr.node; - try { node.parentNode.removeChild(node); } catch (e){} - try { delete window[_this.uid]; } catch (e){} - window[_this.uid] = _this.xhr.node = null; - }, 9); - } - }, - - abort: function (){ - this.end(0, 'abort'); - - if( this.xhr ){ - this.xhr.aborted = true; - this.xhr.abort(); - } - }, - - send: function (FormData){ - var _this = this, options = this.options; - - FormData.toData(function (data){ - if( data instanceof Error ){ - _this.end(0, data.message); - } - else{ - // Start uploading - options.upload(options, _this); - _this._send.call(_this, options, data); - } - }, options); - }, - - _send: function (options, data){ - var _this = this, xhr, uid = _this.uid, onLoadFnName = _this.uid + "Load", url = options.url; - - api.log('XHR._send:', data); - - if( !options.cache ){ - // No cache - url += (~url.indexOf('?') ? '&' : '?') + api.uid(); - } - - if( data.nodeName ){ - var jsonp = options.jsonp; - - // prepare callback in GET - url = url.replace(/([a-z]+)=(\?)/i, '$1='+uid); - - // legacy - options.upload(options, _this); - - var - onPostMessage = function (evt){ - if( ~url.indexOf(evt.origin) ){ - try { - var result = api.parseJSON(evt.data); - if( result.id == uid ){ - complete(result.status, result.statusText, result.response); - } - } catch( err ){ - complete(0, err.message); - } - } - }, - - // jsonp-callack - complete = window[uid] = function (status, statusText, response){ - _this.readyState = 4; - _this.responseText = response; - _this.end(status, statusText); - - api.event.off(window, 'message', onPostMessage); - window[uid] = xhr = transport = window[onLoadFnName] = null; - } - ; - - _this.xhr.abort = function (){ - try { - if( transport.stop ){ transport.stop(); } - else if( transport.contentWindow.stop ){ transport.contentWindow.stop(); } - else { transport.contentWindow.document.execCommand('Stop'); } - } - catch (er) {} - complete(0, "abort"); - }; - - api.event.on(window, 'message', onPostMessage); - - window[onLoadFnName] = function (){ - try { - var - win = transport.contentWindow - , doc = win.document - , result = win.result || api.parseJSON(doc.body.innerHTML) - ; - complete(result.status, result.statusText, result.response); - } catch (e){ - api.log('[transport.onload]', e); - } - }; - - xhr = document.createElement('div'); - xhr.innerHTML = '
' - + '' - + (jsonp && (options.url.indexOf('=?') < 0) ? '' : '') - + '
' - ; - - // get form-data & transport - var - form = xhr.getElementsByTagName('form')[0] - , transport = xhr.getElementsByTagName('iframe')[0] - ; - - form.appendChild(data); - - api.log(form.parentNode.innerHTML); - - // append to DOM - document.body.appendChild(xhr); - - // keep a reference to node-transport - _this.xhr.node = xhr; - - // send - _this.readyState = 2; // loaded - try { - form.submit(); - } catch (err) { - api.log('iframe.error: ' + err); - } - form = null; - } - else { - // Clean url - url = url.replace(/([a-z]+)=(\?)&?/i, ''); - - // html5 - if (this.xhr && this.xhr.aborted) { - api.log("Error: already aborted"); - return; - } - xhr = _this.xhr = api.getXHR(); - - if (data.params) { - url += (url.indexOf('?') < 0 ? "?" : "&") + data.params.join("&"); - } - - xhr.open('POST', url, true); - - if( api.withCredentials ){ - xhr.withCredentials = "true"; - } - - if( !options.headers || !options.headers['X-Requested-With'] ){ - xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - } - - api.each(options.headers, function (val, key){ - xhr.setRequestHeader(key, val); - }); - - - if ( options._chunked ) { - // chunked upload - if( xhr.upload ){ - xhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){ - if (!data.retry) { - // show progress only for correct chunk uploads - options.progress({ - type: evt.type - , total: data.size - , loaded: data.start + evt.loaded - , totalSize: data.size - }, _this, options); - } - }, 100), false); - } - - xhr.onreadystatechange = function (){ - var lkb = parseInt(xhr.getResponseHeader('X-Last-Known-Byte'), 10); - - _this.status = xhr.status; - _this.statusText = xhr.statusText; - _this.readyState = xhr.readyState; - - if( xhr.readyState == 4 ){ - for( var k in _xhrResponsePostfix ){ - _this['response'+k] = xhr['response'+k]; - } - xhr.onreadystatechange = null; - - if (!xhr.status || xhr.status - 201 > 0) { - api.log("Error: " + xhr.status); - // some kind of error - // 0 - connection fail or timeout, if xhr.aborted is true, then it's not recoverable user action - // up - server error - if (((!xhr.status && !xhr.aborted) || 500 == xhr.status || 416 == xhr.status) && ++data.retry <= options.chunkUploadRetry) { - // let's try again the same chunk - // only applicable for recoverable error codes 500 && 416 - var delay = xhr.status ? 0 : api.chunkNetworkDownRetryTimeout; - - // inform about recoverable problems - options.pause(data.file, options); - - // smart restart if server reports about the last known byte - api.log("X-Last-Known-Byte: " + lkb); - if (lkb) { - data.end = lkb; - } else { - data.end = data.start - 1; - if (416 == xhr.status) { - data.end = data.end - options.chunkSize; - } - } - - setTimeout(function () { - _this._send(options, data); - }, delay); - } else { - // no mo retries - _this.end(xhr.status); - } - } else { - // success - data.retry = 0; - - if (data.end == data.size - 1) { - // finished - _this.end(xhr.status); - } else { - // next chunk - - // shift position if server reports about the last known byte - api.log("X-Last-Known-Byte: " + lkb); - if (lkb) { - data.end = lkb; - } - data.file.FileAPIReadPosition = data.end; - - setTimeout(function () { - _this._send(options, data); - }, 0); - } - } - - xhr = null; - } - }; - - data.start = data.end + 1; - data.end = Math.max(Math.min(data.start + options.chunkSize, data.size) - 1, data.start); - - // Retrieve a slice of file - var - file = data.file - , slice = (file.slice || file.mozSlice || file.webkitSlice).call(file, data.start, data.end + 1) - ; - - if( data.size && !slice.size ){ - setTimeout(function (){ - _this.end(-1); - }); - } else { - xhr.setRequestHeader("Content-Range", "bytes " + data.start + "-" + data.end + "/" + data.size); - xhr.setRequestHeader("Content-Disposition", 'attachment; filename=' + encodeURIComponent(data.name)); - xhr.setRequestHeader("Content-Type", data.type || "application/octet-stream"); - - xhr.send(slice); - } - - file = slice = null; - } else { - // single piece upload - if( xhr.upload ){ - // https://github.com/blueimp/jQuery-File-Upload/wiki/Fixing-Safari-hanging-on-very-high-speed-connections-%281Gbps%29 - xhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){ - options.progress(evt, _this, options); - }, 100), false); - } - - xhr.onreadystatechange = function (){ - _this.status = xhr.status; - _this.statusText = xhr.statusText; - _this.readyState = xhr.readyState; - - if( xhr.readyState == 4 ){ - for( var k in _xhrResponsePostfix ){ - _this['response'+k] = xhr['response'+k]; - } - xhr.onreadystatechange = null; - - if (!xhr.status || xhr.status > 201) { - api.log("Error: " + xhr.status); - if (((!xhr.status && !xhr.aborted) || 500 == xhr.status) && (options.retry || 0) < options.uploadRetry) { - options.retry = (options.retry || 0) + 1; - var delay = api.networkDownRetryTimeout; - - // inform about recoverable problems - options.pause(options.file, options); - - setTimeout(function () { - _this._send(options, data); - }, delay); - } else { - //success - _this.end(xhr.status); - } - } else { - //success - _this.end(xhr.status); - } - - xhr = null; - } - }; - - if( api.isArray(data) ){ - // multipart - xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=_'+api.expando); - var rawData = data.join('') +'--_'+ api.expando +'--'; - - /** @namespace xhr.sendAsBinary https://developer.mozilla.org/ru/XMLHttpRequest#Sending_binary_content */ - if( xhr.sendAsBinary ){ - xhr.sendAsBinary(rawData); - } - else { - var bytes = Array.prototype.map.call(rawData, function(c){ return c.charCodeAt(0) & 0xff; }); - xhr.send(new Uint8Array(bytes).buffer); - - } - } else { - // FormData - xhr.send(data); - } - } - } - } - }; - - - // @export - api.XHR = XHR; -})(window, FileAPI); - -/** - * @class FileAPI.Camera - * @author RubaXa - * @support Chrome 21+, FF 18+, Opera 12+ - */ - -/*global window, FileAPI, jQuery */ -/** @namespace LocalMediaStream -- https://developer.mozilla.org/en-US/docs/WebRTC/MediaStream_API#LocalMediaStream */ -(function (window, api){ - "use strict"; - - var - URL = window.URL || window.webkitURL, - - document = window.document, - navigator = window.navigator, - - getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia, - - html5 = !!getMedia - ; - - - // Support "media" - api.support.media = html5; - - - var Camera = function (video){ - this.video = video; - }; - - - Camera.prototype = { - isActive: function (){ - return !!this._active; - }, - - - /** - * Start camera streaming - * @param {Function} callback - */ - start: function (callback){ - var - _this = this - , video = _this.video - , _successId - , _failId - , _complete = function (err){ - _this._active = !err; - clearTimeout(_failId); - clearTimeout(_successId); -// api.event.off(video, 'loadedmetadata', _complete); - callback && callback(err, _this); - } - ; - - getMedia.call(navigator, { video: true }, function (stream/**LocalMediaStream*/){ - // Success - _this.stream = stream; - -// api.event.on(video, 'loadedmetadata', function (){ -// _complete(null); -// }); - - // Set camera stream - video.src = URL.createObjectURL(stream); - - // Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia. - // See crbug.com/110938. - _successId = setInterval(function (){ - if( _detectVideoSignal(video) ){ - _complete(null); - } - }, 1000); - - _failId = setTimeout(function (){ - _complete('timeout'); - }, 5000); - - // Go-go-go! - video.play(); - }, _complete/*error*/); - }, - - - /** - * Stop camera streaming - */ - stop: function (){ - try { - this._active = false; - this.video.pause(); - - try { - this.stream.stop(); - } catch (err) { - api.each(this.stream.getTracks(), function (track) { - track.stop(); - }); - } - - this.stream = null; - } catch( err ){ - api.log('[FileAPI.Camera] stop:', err); - } - }, - - - /** - * Create screenshot - * @return {FileAPI.Camera.Shot} - */ - shot: function (){ - return new Shot(this.video); - } - }; - - - /** - * Get camera element from container - * - * @static - * @param {HTMLElement} el - * @return {Camera} - */ - Camera.get = function (el){ - return new Camera(el.firstChild); - }; - - - /** - * Publish camera element into container - * - * @static - * @param {HTMLElement} el - * @param {Object} options - * @param {Function} [callback] - */ - Camera.publish = function (el, options, callback){ - if( typeof options == 'function' ){ - callback = options; - options = {}; - } - - // Dimensions of "camera" - options = api.extend({}, { - width: '100%' - , height: '100%' - , start: true - }, options); - - - if( el.jquery ){ - // Extract first element, from jQuery collection - el = el[0]; - } - - - var doneFn = function (err){ - if( err ){ - callback(err); - } - else { - // Get camera - var cam = Camera.get(el); - if( options.start ){ - cam.start(callback); - } - else { - callback(null, cam); - } - } - }; - - - el.style.width = _px(options.width); - el.style.height = _px(options.height); - - - if( api.html5 && html5 ){ - // Create video element - var video = document.createElement('video'); - - // Set dimensions - video.style.width = _px(options.width); - video.style.height = _px(options.height); - - // Clean container - if( window.jQuery ){ - jQuery(el).empty(); - } else { - el.innerHTML = ''; - } - - // Add "camera" to container - el.appendChild(video); - - // end - doneFn(); - } - else { - Camera.fallback(el, options, doneFn); - } - }; - - - Camera.fallback = function (el, options, callback){ - callback('not_support_camera'); - }; - - - /** - * @class FileAPI.Camera.Shot - */ - var Shot = function (video){ - var canvas = video.nodeName ? api.Image.toCanvas(video) : video; - var shot = api.Image(canvas); - shot.type = 'image/png'; - shot.width = canvas.width; - shot.height = canvas.height; - shot.size = canvas.width * canvas.height * 4; - return shot; - }; - - - /** - * Add "px" postfix, if value is a number - * - * @private - * @param {*} val - * @return {String} - */ - function _px(val){ - return val >= 0 ? val + 'px' : val; - } - - - /** - * @private - * @param {HTMLVideoElement} video - * @return {Boolean} - */ - function _detectVideoSignal(video){ - var canvas = document.createElement('canvas'), ctx, res = false; - try { - ctx = canvas.getContext('2d'); - ctx.drawImage(video, 0, 0, 1, 1); - res = ctx.getImageData(0, 0, 1, 1).data[4] != 255; - } - catch( err ){ - api.log('[FileAPI.Camera] detectVideoSignal:', err); - } - return res; - } - - - // @export - Camera.Shot = Shot; - api.Camera = Camera; -})(window, FileAPI); - -/** - * FileAPI fallback to Flash - * - * @flash-developer "Vladimir Demidov" - */ - -/*global window, ActiveXObject, FileAPI */ -(function (window, jQuery, api) { - "use strict"; - - var - document = window.document - , location = window.location - , navigator = window.navigator - , _each = api.each - ; - - - api.support.flash = (function (){ - var mime = navigator.mimeTypes, has = false; - - if( navigator.plugins && typeof navigator.plugins['Shockwave Flash'] == 'object' ){ - has = navigator.plugins['Shockwave Flash'].description && !(mime && mime['application/x-shockwave-flash'] && !mime['application/x-shockwave-flash'].enabledPlugin); - } - else { - try { - has = !!(window.ActiveXObject && new ActiveXObject('ShockwaveFlash.ShockwaveFlash')); - } - catch(er){ - api.log('Flash -- does not supported.'); - } - } - - if( has && /^file:/i.test(location) ){ - api.log('[warn] Flash does not work on `file:` protocol.'); - } - - return has; - })(); - - - api.support.flash - && (0 - || !api.html5 || !api.support.html5 - || (api.cors && !api.support.cors) - || (api.media && !api.support.media) - ) - && (function (){ - var - _attr = api.uid() - , _retry = 0 - , _files = {} - , _rhttp = /^https?:/i - - , flash = { - _fn: {}, - - - /** - * Initialization & preload flash object - */ - init: function (){ - var child = document.body && document.body.firstChild; - - if( child ){ - do { - if( child.nodeType == 1 ){ - api.log('FlashAPI.state: awaiting'); - - var dummy = document.createElement('div'); - - dummy.id = '_' + _attr; - - _css(dummy, { - top: 1 - , right: 1 - , width: 5 - , height: 5 - , position: 'absolute' - , zIndex: 2147483647+'' // set max zIndex - }); - - child.parentNode.insertBefore(dummy, child); - flash.publish(dummy, _attr); - - return; - } - } - while( child = child.nextSibling ); - } - - if( _retry < 10 ){ - setTimeout(flash.init, ++_retry*50); - } - }, - - - /** - * Publish flash-object - * - * @param {HTMLElement} el - * @param {String} id - * @param {Object} [opts] - */ - publish: function (el, id, opts){ - opts = opts || {}; - el.innerHTML = _makeFlashHTML({ - id: id - , src: _getUrl(api.flashUrl, 'r=' + api.version) -// , src: _getUrl('http://v.demidov.boom.corp.mail.ru/uploaderfileapi/FlashFileAPI.swf?1') - , wmode: opts.camera ? '' : 'transparent' - , flashvars: 'callback=' + (opts.onEvent || 'FileAPI.Flash.onEvent') - + '&flashId='+ id - + '&storeKey='+ navigator.userAgent.match(/\d/ig).join('') +'_'+ api.version - + (flash.isReady || (api.pingUrl ? '&ping='+api.pingUrl : '')) - + '&timeout='+api.flashAbortTimeout - + (opts.camera ? '&useCamera=' + _getUrl(api.flashWebcamUrl) : '') - + '&debug='+(api.debug?"1":"") - }, opts); - }, - - - ready: function (){ - api.log('FlashAPI.state: ready'); - - flash.ready = api.F; - flash.isReady = true; - flash.patch(); - flash.patchCamera && flash.patchCamera(); - api.event.on(document, 'mouseover', flash.mouseover); - api.event.on(document, 'click', function (evt){ - if( flash.mouseover(evt) ){ - evt.preventDefault - ? evt.preventDefault() - : (evt.returnValue = true) - ; - } - }); - }, - - - getEl: function (){ - return document.getElementById('_'+_attr); - }, - - - getWrapper: function (node){ - do { - if( /js-fileapi-wrapper/.test(node.className) ){ - return node; - } - } - while( (node = node.parentNode) && (node !== document.body) ); - }, - - - mouseover: function (evt){ - var target = api.event.fix(evt).target; - - if( /input/i.test(target.nodeName) && target.type == 'file' && !target.disabled ){ - var - state = target.getAttribute(_attr) - , wrapper = flash.getWrapper(target) - ; - - if( api.multiFlash ){ - // check state: - // p — published - // i — initialization - // r — ready - if( state == 'i' || state == 'r' ){ - // publish fail - return false; - } - else if( state != 'p' ){ - // set "init" state - target.setAttribute(_attr, 'i'); - - var dummy = document.createElement('div'); - - if( !wrapper ){ - api.log('[err] FlashAPI.mouseover: js-fileapi-wrapper not found'); - return; - } - - _css(dummy, { - top: 0 - , left: 0 - , width: target.offsetWidth - , height: target.offsetHeight - , zIndex: 2147483647+'' // set max zIndex - , position: 'absolute' - }); - - wrapper.appendChild(dummy); - flash.publish(dummy, api.uid()); - - // set "publish" state - target.setAttribute(_attr, 'p'); - } - - return true; - } - else if( wrapper ){ - // Use one flash element - var box = _getDimensions(wrapper); - - _css(flash.getEl(), box); - - // Set current input - flash.curInp = target; - } - } - else if( !/object|embed/i.test(target.nodeName) ){ - _css(flash.getEl(), { top: 1, left: 1, width: 5, height: 5 }); - } - }, - - onEvent: function (evt){ - var type = evt.type; - - if( type == 'ready' ){ - try { - // set "ready" state - flash.getInput(evt.flashId).setAttribute(_attr, 'r'); - } catch (e){ - } - - flash.ready(); - setTimeout(function (){ flash.mouseenter(evt); }, 50); - return true; - } - else if( type === 'ping' ){ - api.log('(flash -> js).ping:', [evt.status, evt.savedStatus], evt.error); - } - else if( type === 'log' ){ - api.log('(flash -> js).log:', evt.target); - } - else if( type in flash ){ - setTimeout(function (){ - api.log('FlashAPI.event.'+evt.type+':', evt); - flash[type](evt); - }, 1); - } - }, - - - mouseenter: function (evt){ - var node = flash.getInput(evt.flashId); - - if( node ){ - // Set multiple mode - flash.cmd(evt, 'multiple', node.getAttribute('multiple') != null); - - - // Set files filter - var accept = [], exts = {}; - - _each((node.getAttribute('accept') || '').split(/,\s*/), function (mime){ - api.accept[mime] && _each(api.accept[mime].split(' '), function (ext){ - exts[ext] = 1; - }); - }); - - _each(exts, function (i, ext){ - accept.push( ext ); - }); - - flash.cmd(evt, 'accept', accept.length ? accept.join(',')+','+accept.join(',').toUpperCase() : '*'); - } - }, - - - get: function (id){ - return document[id] || window[id] || document.embeds[id]; - }, - - - getInput: function (id){ - if( api.multiFlash ){ - try { - var node = flash.getWrapper(flash.get(id)); - if( node ){ - return node.getElementsByTagName('input')[0]; - } - } catch (e){ - api.log('[err] Can not find "input" by flashId:', id, e); - } - } else { - return flash.curInp; - } - }, - - - select: function (evt){ - var - inp = flash.getInput(evt.flashId) - , uid = api.uid(inp) - , files = evt.target.files - , event - ; - - _each(files, function (file){ - api.checkFileObj(file); - }); - - _files[uid] = files; - - if( document.createEvent ){ - event = document.createEvent('Event'); - event.files = files; - event.initEvent('change', true, true); - inp.dispatchEvent(event); - } - else if( jQuery ){ - jQuery(inp).trigger({ type: 'change', files: files }); - } - else { - event = document.createEventObject(); - event.files = files; - inp.fireEvent('onchange', event); - } - }, - - - cmd: function (id, name, data, last){ - try { - api.log('(js -> flash).'+name+':', data); - return flash.get(id.flashId || id).cmd(name, data); - } catch (err){ - api.log('(js -> flash).onError:', err.toString()); - if( !last ){ - // try again - setTimeout(function (){ flash.cmd(id, name, data, true); }, 50); - } - } - }, - - - patch: function (){ - api.flashEngine = true; - - // FileAPI - _inherit(api, { - getFiles: function (input, filter, callback){ - if( callback ){ - api.filterFiles(api.getFiles(input), filter, callback); - return null; - } - - var files = api.isArray(input) ? input : _files[api.uid(input.target || input.srcElement || input)]; - - - if( !files ){ - // Файлов нету, вызываем родитель�кий метод - return this.parent.apply(this, arguments); - } - - - if( filter ){ - filter = api.getFilesFilter(filter); - files = api.filter(files, function (file){ return filter.test(file.name); }); - } - - return files; - }, - - - getInfo: function (file, fn){ - if( _isHtmlFile(file) ){ - this.parent.apply(this, arguments); - } - else if( file.isShot ){ - fn(null, file.info = { - width: file.width, - height: file.height - }); - } - else { - if( !file.__info ){ - var defer = file.__info = api.defer(); - - flash.cmd(file, 'getFileInfo', { - id: file.id - , callback: _wrap(function _(err, info){ - _unwrap(_); - defer.resolve(err, file.info = info); - }) - }); - } - - file.__info.then(fn); - } - } - }); - - - // FileAPI.Image - api.support.transform = true; - api.Image && _inherit(api.Image.prototype, { - get: function (fn, scaleMode){ - this.set({ scaleMode: scaleMode || 'noScale' }); // noScale, exactFit - return this.parent(fn); - }, - - _load: function (file, fn){ - api.log('FlashAPI.Image._load:', file); - - if( _isHtmlFile(file) ){ - this.parent.apply(this, arguments); - } - else { - var _this = this; - api.getInfo(file, function (err){ - fn.call(_this, err, file); - }); - } - }, - - _apply: function (file, fn){ - api.log('FlashAPI.Image._apply:', file); - - if( _isHtmlFile(file) ){ - this.parent.apply(this, arguments); - } - else { - var m = this.getMatrix(file.info), doneFn = fn; - - flash.cmd(file, 'imageTransform', { - id: file.id - , matrix: m - , callback: _wrap(function _(err, base64){ - api.log('FlashAPI.Image._apply.callback:', err); - _unwrap(_); - - if( err ){ - doneFn(err); - } - else if( !api.support.html5 && (!api.support.dataURI || base64.length > 3e4) ){ - _makeFlashImage({ - width: (m.deg % 180) ? m.dh : m.dw - , height: (m.deg % 180) ? m.dw : m.dh - , scale: m.scaleMode - }, base64, doneFn); - } - else { - if( m.filter ){ - doneFn = function (err, img){ - if( err ){ - fn(err); - } - else { - api.Image.applyFilter(img, m.filter, function (){ - fn(err, this.canvas); - }); - } - }; - } - - api.newImage('data:'+ file.type +';base64,'+ base64, doneFn); - } - }) - }); - } - }, - - toData: function (fn){ - var - file = this.file - , info = file.info - , matrix = this.getMatrix(info) - ; - api.log('FlashAPI.Image.toData'); - - if( _isHtmlFile(file) ){ - this.parent.apply(this, arguments); - } - else { - if( matrix.deg == 'auto' ){ - matrix.deg = api.Image.exifOrientation[info && info.exif && info.exif.Orientation] || 0; - } - - fn.call(this, !file.info, { - id: file.id - , flashId: file.flashId - , name: file.name - , type: file.type - , matrix: matrix - }); - } - } - }); - - - api.Image && _inherit(api.Image, { - fromDataURL: function (dataURL, size, callback){ - if( !api.support.dataURI || dataURL.length > 3e4 ){ - _makeFlashImage( - api.extend({ scale: 'exactFit' }, size) - , dataURL.replace(/^data:[^,]+,/, '') - , function (err, el){ callback(el); } - ); - } - else { - this.parent(dataURL, size, callback); - } - } - }); - - // FileAPI.Form - _inherit(api.Form.prototype, { - toData: function (fn){ - var items = this.items, i = items.length; - - for( ; i--; ){ - if( items[i].file && _isHtmlFile(items[i].blob) ){ - return this.parent.apply(this, arguments); - } - } - - api.log('FlashAPI.Form.toData'); - fn(items); - } - }); - - - // FileAPI.XHR - _inherit(api.XHR.prototype, { - _send: function (options, formData){ - if( - formData.nodeName - || formData.append && api.support.html5 - || api.isArray(formData) && (typeof formData[0] === 'string') - ){ - // HTML5, Multipart or IFrame - return this.parent.apply(this, arguments); - } - - - var - data = {} - , files = {} - , _this = this - , flashId - , fileId - ; - - _each(formData, function (item){ - if( item.file ){ - files[item.name] = item = _getFileDescr(item.blob); - fileId = item.id; - flashId = item.flashId; - } - else { - data[item.name] = item.blob; - } - }); - - if( !fileId ){ - flashId = _attr; - } - - if( !flashId ){ - api.log('[err] FlashAPI._send: flashId -- undefined'); - return this.parent.apply(this, arguments); - } - else { - api.log('FlashAPI.XHR._send: '+ flashId +' -> '+ fileId); - } - - _this.xhr = { - headers: {}, - abort: function (){ flash.cmd(flashId, 'abort', { id: fileId }); }, - getResponseHeader: function (name){ return this.headers[name]; }, - getAllResponseHeaders: function (){ return this.headers; } - }; - - var queue = api.queue(function (){ - flash.cmd(flashId, 'upload', { - url: _getUrl(options.url.replace(/([a-z]+)=(\?)&?/i, '')) - , data: data - , files: fileId ? files : null - , headers: options.headers || {} - , callback: _wrap(function upload(evt){ - var type = evt.type, result = evt.result; - - api.log('FlashAPI.upload.'+type); - - if( type == 'progress' ){ - evt.loaded = Math.min(evt.loaded, evt.total); // @todo fixme - evt.lengthComputable = true; - options.progress(evt); - } - else if( type == 'complete' ){ - _unwrap(upload); - - if( typeof result == 'string' ){ - _this.responseText = result.replace(/%22/g, "\"").replace(/%5c/g, "\\").replace(/%26/g, "&").replace(/%25/g, "%"); - } - - _this.end(evt.status || 200); - } - else if( type == 'abort' || type == 'error' ){ - _this.end(evt.status || 0, evt.message); - _unwrap(upload); - } - }) - }); - }); - - - // #2174: FileReference.load() call while FileReference.upload() or vice versa - _each(files, function (file){ - queue.inc(); - api.getInfo(file, queue.next); - }); - - queue.check(); - } - }); - } - } - ; - - - function _makeFlashHTML(opts){ - return ('' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '').replace(/#(\w+)#/ig, function (a, name){ return opts[name]; }) - ; - } - - - function _css(el, css){ - if( el && el.style ){ - var key, val; - for( key in css ){ - val = css[key]; - if( typeof val == 'number' ){ - val += 'px'; - } - try { el.style[key] = val; } catch (e) {} - } - } - } - - - function _inherit(obj, methods){ - _each(methods, function (fn, name){ - var prev = obj[name]; - obj[name] = function (){ - this.parent = prev; - return fn.apply(this, arguments); - }; - }); - } - - function _isHtmlFile(file){ - return file && !file.flashId; - } - - function _wrap(fn){ - var id = fn.wid = api.uid(); - flash._fn[id] = fn; - return 'FileAPI.Flash._fn.'+id; - } - - - function _unwrap(fn){ - try { - flash._fn[fn.wid] = null; - delete flash._fn[fn.wid]; - } - catch(e){} - } - - - function _getUrl(url, params){ - if( !_rhttp.test(url) ){ - if( /^\.\//.test(url) || '/' != url.charAt(0) ){ - var path = location.pathname; - path = path.substr(0, path.lastIndexOf('/')); - url = (path +'/'+ url).replace('/./', '/'); - } - - if( '//' != url.substr(0, 2) ){ - url = '//' + location.host + url; - } - - if( !_rhttp.test(url) ){ - url = location.protocol + url; - } - } - - if( params ){ - url += (/\?/.test(url) ? '&' : '?') + params; - } - - return url; - } - - - function _makeFlashImage(opts, base64, fn){ - var - key - , flashId = api.uid() - , el = document.createElement('div') - , attempts = 10 - ; - - for( key in opts ){ - el.setAttribute(key, opts[key]); - el[key] = opts[key]; - } - - _css(el, opts); - - opts.width = '100%'; - opts.height = '100%'; - - el.innerHTML = _makeFlashHTML(api.extend({ - id: flashId - , src: _getUrl(api.flashImageUrl, 'r='+ api.uid()) - , wmode: 'opaque' - , flashvars: 'scale='+ opts.scale +'&callback='+_wrap(function _(){ - _unwrap(_); - if( --attempts > 0 ){ - _setImage(); - } - return true; - }) - }, opts)); - - function _setImage(){ - try { - // Get flash-object by id - var img = flash.get(flashId); - img.setImage(base64); - } catch (e){ - api.log('[err] FlashAPI.Preview.setImage -- can not set "base64":', e); - } - } - - fn(false, el); - el = null; - } - - - function _getFileDescr(file){ - return { - id: file.id - , name: file.name - , matrix: file.matrix - , flashId: file.flashId - }; - } - - - function _getDimensions(el){ - var - box = el.getBoundingClientRect() - , body = document.body - , docEl = (el && el.ownerDocument).documentElement - ; - - return { - top: box.top + (window.pageYOffset || docEl.scrollTop) - (docEl.clientTop || body.clientTop || 0) - , left: box.left + (window.pageXOffset || docEl.scrollLeft) - (docEl.clientLeft || body.clientLeft || 0) - , width: box.right - box.left - , height: box.bottom - box.top - }; - } - - // @export - api.Flash = flash; - - - // Check dataURI support - api.newImage('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==', function (err, img){ - api.support.dataURI = !(img.width != 1 || img.height != 1); - flash.init(); - }); - })(); -})(window, window.jQuery, FileAPI); - -/** - * FileAPI fallback to Flash - * - * @flash-developer "Vladimir Demidov" - */ - -/*global window, FileAPI */ -(function (window, jQuery, api) { - "use strict"; - - var _each = api.each, - _cameraQueue = []; - - if (api.support.flash && (api.media && (!api.support.media || !api.html5))) { - (function () { - function _wrap(fn) { - var id = fn.wid = api.uid(); - api.Flash._fn[id] = fn; - return 'FileAPI.Flash._fn.' + id; - } - - - function _unwrap(fn) { - try { - api.Flash._fn[fn.wid] = null; - delete api.Flash._fn[fn.wid]; - } catch (e) { - } - } - - var flash = api.Flash; - api.extend(api.Flash, { - - patchCamera: function () { - api.Camera.fallback = function (el, options, callback) { - var camId = api.uid(); - api.log('FlashAPI.Camera.publish: ' + camId); - flash.publish(el, camId, api.extend(options, { - camera: true, - onEvent: _wrap(function _(evt) { - if (evt.type === 'camera') { - _unwrap(_); - - if (evt.error) { - api.log('FlashAPI.Camera.publish.error: ' + evt.error); - callback(evt.error); - } else { - api.log('FlashAPI.Camera.publish.success: ' + camId); - callback(null); - } - } - }) - })); - }; - // Run - _each(_cameraQueue, function (args) { - api.Camera.fallback.apply(api.Camera, args); - }); - _cameraQueue = []; - - - // FileAPI.Camera:proto - api.extend(api.Camera.prototype, { - _id: function () { - return this.video.id; - }, - - start: function (callback) { - var _this = this; - flash.cmd(this._id(), 'camera.on', { - callback: _wrap(function _(evt) { - _unwrap(_); - - if (evt.error) { - api.log('FlashAPI.camera.on.error: ' + evt.error); - callback(evt.error, _this); - } else { - api.log('FlashAPI.camera.on.success: ' + _this._id()); - _this._active = true; - callback(null, _this); - } - }) - }); - }, - - stop: function () { - this._active = false; - flash.cmd(this._id(), 'camera.off'); - }, - - shot: function () { - api.log('FlashAPI.Camera.shot:', this._id()); - - var shot = api.Flash.cmd(this._id(), 'shot', {}); - shot.type = 'image/png'; - shot.flashId = this._id(); - shot.isShot = true; - - return new api.Camera.Shot(shot); - } - }); - } - }); - - api.Camera.fallback = function () { - _cameraQueue.push(arguments); - }; - - }()); - } -}(window, window.jQuery, FileAPI)); -if( typeof define === "function" && define.amd ){ define("FileAPI", [], function (){ return FileAPI; }); } \ No newline at end of file diff --git a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.min.js b/manager/media/browser/mcpuk/js/FileAPI/FileAPI.min.js deleted file mode 100644 index 01020adec0..0000000000 --- a/manager/media/browser/mcpuk/js/FileAPI/FileAPI.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! FileAPI 2.0.19 - BSD | git://github.com/mailru/FileAPI.git */ -!function(a){"use strict";var b=a.HTMLCanvasElement&&a.HTMLCanvasElement.prototype,c=a.Blob&&function(){try{return Boolean(new Blob)}catch(a){return!1}}(),d=c&&a.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(a){return!1}}(),e=a.BlobBuilder||a.WebKitBlobBuilder||a.MozBlobBuilder||a.MSBlobBuilder,f=(c||e)&&a.atob&&a.ArrayBuffer&&a.Uint8Array&&function(a){var b,f,g,h,i,j;for(b=a.split(",")[0].indexOf("base64")>=0?atob(a.split(",")[1]):decodeURIComponent(a.split(",")[1]),f=new ArrayBuffer(b.length),g=new Uint8Array(f),h=0;h0,H=a.dataURLtoBlob,I=/img/i,J=/canvas/i,K=/img|canvas/i,L=/input/i,M=/^data:[^,]+,/,N={}.toString,O=a.Math,P=function(b){return b=new a.Number(O.pow(1024,b)),b.from=function(a){return O.round(a*this)},b},Q={},R=[],S="abort progress error load loadend",T="status statusText readyState response responseXML responseText responseBody".split(" "),U="currentTarget",V="preventDefault",W=function(a){return a&&"length"in a},X=function(a,b,c){if(a)if(W(a))for(var d=0,e=a.length;e>d;d++)d in a&&b.call(c,a[d],d,a);else for(var f in a)a.hasOwnProperty(f)&&b.call(c,a[f],f,a)},Y=function(a){for(var b=arguments,c=1,d=function(b,c){a[c]=b};c=c&&!d&&f.end()},isFail:function(){return d},fail:function(){!d&&a(d=!0)},end:function(){e||(e=!0,a())}};return f},each:X,afor:function(a,b){var c=0,d=a.length;W(a)&&d--?!function e(){b(d!=c&&e,a[c],c++)}():b(!1)},extend:Y,isFile:function(a){return"[object File]"===N.call(a)},isBlob:function(a){return this.isFile(a)||"[object Blob]"===N.call(a)},isCanvas:function(a){return a&&J.test(a.nodeName)},getFilesFilter:function(a){return a="string"==typeof a?a:a.getAttribute&&a.getAttribute("accept")||"",a?new RegExp("("+a.replace(/\./g,"\\.").replace(/,/g,"|")+")$","i"):/./},readAsDataURL:function(a,b){ca.isCanvas(a)?c(a,b,"load",ca.toDataURL(a)):e(a,b,"DataURL")},readAsBinaryString:function(a,b){d("BinaryString")?e(a,b,"BinaryString"):e(a,function(a){if("load"==a.type)try{a.result=ca.toBinaryString(a.result)}catch(c){a.type="error",a.message=c.toString()}b(a)},"DataURL")},readAsArrayBuffer:function(a,b){e(a,b,"ArrayBuffer")},readAsText:function(a,b,c){c||(c=b,b="utf-8"),e(a,c,"Text",b)},toDataURL:function(a,b){return"string"==typeof a?a:a.toDataURL?a.toDataURL(b||"image/png"):void 0},toBinaryString:function(b){return a.atob(ca.toDataURL(b).replace(M,""))},readAsImage:function(a,d,e){if(ca.isBlob(a))if(w){var f=w.createObjectURL(a);f===b?c(a,d,"error"):ca.readAsImage(f,d,e)}else ca.readAsDataURL(a,function(b){"load"==b.type?ca.readAsImage(b.result,d,e):(e||"error"==b.type)&&c(a,d,b,null,{loaded:b.loaded,total:b.total})});else if(ca.isCanvas(a))c(a,d,"load",a);else if(I.test(a.nodeName))if(a.complete)c(a,d,"load",a);else{var g="error abort load";_(a,g,function i(b){"load"==b.type&&w&&w.revokeObjectURL(a.src),$(a,g,i),c(a,d,b,a)})}else if(a.iframe)c(a,d,{type:"error"});else{var h=ca.newImage(a.dataURL||a);ca.readAsImage(h,d,e)}},checkFileObj:function(a){var b={},c=ca.accept;return"object"==typeof a?b=a:b.name=(a+"").split(/\\|\//g).pop(),null==b.type&&(b.type=b.name.split(".").pop()),X(c,function(a,c){a=new RegExp(a.replace(/\s/g,"|"),"i"),(a.test(b.type)||ca.ext2mime[b.type])&&(b.type=ca.ext2mime[b.type]||c.split("/")[0]+"/"+b.type)}),b},getDropFiles:function(a,b){var c,d=[],e=[],j=l(a),k=j.files,m=j.items,n=W(m)&&m[0]&&h(m[0]),o=ca.queue(function(){b(d,e)});if(n)if(G&&k){var p,q,r=k.length;for(c=new Array(r);r--;){p=k[r];try{q=h(m[r])}catch(s){ca.log("[err] getDropFiles: ",s),q=null}g(q)&&(q.isDirectory||q.isFile&&p.name==p.name.normalize("NFC"))?c[r]=q:c[r]=p}}else c=m;else c=k;X(c||[],function(a){o.inc();try{n&&g(a)?i(a,function(a,b,c){a?ca.log("[err] getDropFiles:",a):d.push.apply(d,b),e.push.apply(e,c),o.next()}):f(a,function(b,c){b?d.push(a):a.error=c,e.push(a),o.next()})}catch(b){o.next(),ca.log("[err] getDropFiles: ",b)}}),o.check()},getFiles:function(a,b,c){var d=[];return c?(ca.filterFiles(ca.getFiles(a),b,c),null):(a.jquery&&(a.each(function(){d=d.concat(ca.getFiles(this))}),a=d,d=[]),"string"==typeof b&&(b=ca.getFilesFilter(b)),a.originalEvent?a=aa(a.originalEvent):a.srcElement&&(a=aa(a)),a.dataTransfer?a=a.dataTransfer:a.target&&(a=a.target),a.files?(d=a.files,D||(d[0].blob=a,d[0].iframe=!0)):!D&&k(a)?ca.trim(a.value)&&(d=[ca.checkFileObj(a.value)],d[0].blob=a,d[0].iframe=!0):W(a)&&(d=a),ca.filter(d,function(a){return!b||b.test(a.name)}))},getTotalSize:function(a){for(var b=0,c=a&&a.length;c--;)b+=a[c].size;return b},getInfo:function(a,b){var c={},d=R.concat();ca.isBlob(a)?!function e(){var f=d.shift();f?f.test(a.type)?f(a,function(a,d){a?b(a):(Y(c,d),e())}):e():b(!1,c)}():b("not_support_info",c)},addInfoReader:function(a,b){b.test=function(b){return a.test(b)},R.push(b)},filter:function(a,b){for(var c,d=[],e=0,f=a.length;f>e;e++)e in a&&(c=a[e],b.call(c,c,e,a)&&d.push(c));return d},filterFiles:function(a,b,c){if(a.length){var d,e=a.concat(),f=[],g=[];!function h(){e.length?(d=e.shift(),ca.getInfo(d,function(a,c){(b(d,a?!1:c)?f:g).push(d),h()})):c(f,g)}()}else c([],a)},upload:function(a){a=Y({jsonp:"callback",prepare:ca.F,beforeupload:ca.F,upload:ca.F,fileupload:ca.F,fileprogress:ca.F,filecomplete:ca.F,progress:ca.F,complete:ca.F,pause:ca.F,imageOriginal:!0,chunkSize:ca.chunkSize,chunkUploadRetry:ca.chunkUploadRetry,uploadRetry:ca.uploadRetry},a),a.imageAutoOrientation&&!a.imageTransform&&(a.imageTransform={rotate:"auto"});var b,c=new ca.XHR(a),d=this._getFilesDataArray(a.files),e=this,f=0,g=0,h=!1;return X(d,function(a){f+=a.size}),c.files=[],X(d,function(a){c.files.push(a.file)}),c.total=f,c.loaded=0,c.filesLeft=d.length,a.beforeupload(c,a),b=function(){var i=d.shift(),k=i&&i.file,l=!1,m=j(a);if(c.filesLeft=d.length,k&&k.name===ca.expando&&(k=null,ca.log("[warn] FileAPI.upload() — called without files")),("abort"!=c.statusText||c.current)&&i){if(h=!1,c.currentFile=k,k&&a.prepare(k,m)===!1)return void b.call(e);m.file=k,e._getFormData(m,i,function(h){g||a.upload(c,a);var j=new ca.XHR(Y({},m,{upload:k?function(){a.fileupload(k,j,m)}:q,progress:k?function(b){l||(l=b.loaded===b.total,a.fileprogress({type:"progress",total:i.total=b.total,loaded:i.loaded=b.loaded},k,j,m),a.progress({type:"progress",total:f,loaded:c.loaded=g+i.size*(b.loaded/b.total)||0},k,j,m))}:q,complete:function(d){X(T,function(a){c[a]=j[a]}),k&&(i.total=i.total||i.size,i.loaded=i.total,d||(this.progress(i),l=!0,g+=i.size,c.loaded=g),a.filecomplete(d,j,k,m)),setTimeout(function(){b.call(e)},0)}}));c.abort=function(a){a||(d.length=0),this.current=a,j.abort()},j.send(h)})}else{var n=200==c.status||201==c.status||204==c.status;a.complete(n?!1:c.statusText||"error",c,a),h=!0}},setTimeout(b,0),c.append=function(a,g){a=ca._getFilesDataArray([].concat(a)),X(a,function(a){f+=a.size,c.files.push(a.file),g?d.unshift(a):d.push(a)}),c.statusText="",h&&b.call(e)},c.remove=function(a){for(var b,c=d.length;c--;)d[c].file==a&&(b=d.splice(c,1),f-=b.size);return b},c},_getFilesDataArray:function(a){var b=[],c={};if(k(a)){var d=ca.getFiles(a);c[a.name||"file"]=null!==a.getAttribute("multiple")?d:d[0]}else W(a)&&k(a[0])?X(a,function(a){c[a.name||"file"]=ca.getFiles(a)}):c=a;return X(c,function e(a,c){W(a)?X(a,function(a){e(a,c)}):a&&(a.name||a.image)&&b.push({name:c,file:a,size:a.size,total:a.size,loaded:0})}),b.length||b.push({file:{name:ca.expando}}),b},_getFormData:function(a,b,c){var d=b.file,e=b.name,f=d.name,g=d.type,h=ca.support.transform&&a.imageTransform,i=new ca.Form,j=ca.queue(function(){c(i)}),k=h&&m(h),l=ca.postNameConcat;X(a.data,function n(a,b){"object"==typeof a?X(a,function(a,c){n(a,l(b,c))}):i.append(b,a)}),function o(b){b.image?(j.inc(),b.toData(function(a,c){b.file&&(c.type=b.file.type,c.quality=b.matrix.quality,f=b.file&&b.file.name),f=f||(new Date).getTime()+".png",o(c),j.next()})):ca.Image&&h&&(/^image/.test(b.type)||K.test(b.nodeName))?(j.inc(),k&&(h=[h]),ca.Image.transform(b,h,a.imageAutoOrientation,function(c,d){if(k&&!c)H||ca.flashEngine||(i.multipart=!0),i.append(e,d[0],f,h[0].type||g);else{var m=0;c||X(d,function(a,b){H||ca.flashEngine||(i.multipart=!0),h[b].postName||(m=1),i.append(h[b].postName||l(e,b),a,f,h[b].type||g)}),(c||a.imageOriginal)&&i.append(l(e,m?"original":null),b,f,g)}j.next()})):f!==ca.expando&&i.append(e,b,f)}(d),j.check()},reset:function(a,b){var c,d;return C?(d=C(a).clone(!0).insertBefore(a).val("")[0],b||C(a).remove()):(c=a.parentNode,d=c.insertBefore(a.cloneNode(!0),a),d.value="",b||c.removeChild(a),X(Q[ca.uid(a)],function(b,c){X(b,function(b){$(a,c,b),Z(d,c,b)})})),d},load:function(a,b){var c=ca.getXHR();return c?(c.open("GET",a,!0),c.overrideMimeType&&c.overrideMimeType("text/plain; charset=x-user-defined"),Z(c,"progress",function(a){a.lengthComputable&&b({type:a.type,loaded:a.loaded,total:a.total},c)}),c.onreadystatechange=function(){if(4==c.readyState)if(c.onreadystatechange=null,200==c.status){a=a.split("/");var d={name:a[a.length-1],size:c.getResponseHeader("Content-Length"),type:c.getResponseHeader("Content-Type")};d.dataURL="data:"+d.type+";base64,"+ca.encode64(c.responseBody||c.responseText),b({type:"load",result:d},c)}else b({type:"error"},c)},c.send(null)):b({type:"error"}),c},encode64:function(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",c="",d=0;for("string"!=typeof a&&(a=String(a));d>2,k=(3&g)<<4|h>>4;isNaN(h)?e=f=64:(e=(15&h)<<2|i>>6,f=isNaN(i)?64:63&i),c+=b.charAt(j)+b.charAt(k)+b.charAt(e)+b.charAt(f)}return c}};ca.addInfoReader(/^image/,function(a,b){if(!a.__dimensions){var c=a.__dimensions=ca.defer();ca.readAsImage(a,function(a){var b=a.target;c.resolve("load"==a.type?!1:"error",{width:b.width,height:b.height}),b.src=ca.EMPTY_PNG,b=null})}a.__dimensions.then(b)}),ca.event.dnd=function(a,b,c){var d,e;c||(c=b,b=ca.F),z?(Z(a,"dragenter dragleave dragover",b.ff=b.ff||function(a){for(var c=l(a).types,f=c&&c.length,g=!1;f--;)if(~c[f].indexOf("File")){a[V](),e!==a.type&&(e=a.type,"dragleave"!=e&&b.call(a[U],!0,a),g=!0);break}g&&(clearTimeout(d),d=setTimeout(function(){b.call(a[U],"dragleave"!=e,a)},50))}),Z(a,"drop",c.ff=c.ff||function(a){a[V](),e=0,b.call(a[U],!1,a),ca.getDropFiles(a,function(b,d){c.call(a[U],b,d,a)})})):ca.log("Drag'n'Drop -- not supported")},ca.event.dnd.off=function(a,b,c){$(a,"dragenter dragleave dragover",b.ff),$(a,"drop",c.ff)},C&&!C.fn.dnd&&(C.fn.dnd=function(a,b){return this.each(function(){ca.event.dnd(this,a,b)})},C.fn.offdnd=function(a,b){return this.each(function(){ca.event.dnd.off(this,a,b)})}),a.FileAPI=Y(ca,a.FileAPI),ca.log("FileAPI: "+ca.version),ca.log("protocol: "+a.location.protocol),ca.log("doctype: ["+s.name+"] "+s.publicId+" "+s.systemId),X(r.getElementsByTagName("meta"),function(a){/x-ua-compatible/i.test(a.getAttribute("http-equiv"))&&ca.log("meta.http-equiv: "+a.getAttribute("content"))});try{n=!!console.log,o=!!console.log.apply}catch(da){}ca.flashUrl||(ca.flashUrl=ca.staticPath+"FileAPI.flash.swf"),ca.flashImageUrl||(ca.flashImageUrl=ca.staticPath+"FileAPI.flash.image.swf"),ca.flashWebcamUrl||(ca.flashWebcamUrl=ca.staticPath+"FileAPI.flash.camera.swf")}(window,void 0),function(a,b,c){"use strict";function d(b){if(b instanceof d){var c=new d(b.file);return a.extend(c.matrix,b.matrix),c}return this instanceof d?(this.file=b,this.size=b.size||100,void(this.matrix={sx:0,sy:0,sw:0,sh:0,dx:0,dy:0,dw:0,dh:0,resize:0,deg:0,quality:1,filter:0})):new d(b)}var e=Math.min,f=Math.round,g=function(){return b.createElement("canvas")},h=!1,i={8:270,3:180,6:90,7:270,4:180,5:90};try{h=g().toDataURL("image/png").indexOf("data:image/png")>-1}catch(j){}d.prototype={image:!0,constructor:d,set:function(b){return a.extend(this.matrix,b),this},crop:function(a,b,d,e){return d===c&&(d=a,e=b,a=b=0),this.set({sx:a,sy:b,sw:d,sh:e||d})},resize:function(a,b,c){return/min|max|height|width/.test(b)&&(c=b,b=a),this.set({dw:a,dh:b||a,resize:c})},preview:function(a,b){return this.resize(a,b||a,"preview")},rotate:function(a){return this.set({deg:a})},filter:function(a){return this.set({filter:a})},overlay:function(a){return this.set({overlay:a})},clone:function(){return new d(this)},_load:function(b,c){var d=this;/img|video/i.test(b.nodeName)?c.call(d,null,b):a.readAsImage(b,function(a){c.call(d,"load"!=a.type,a.result)})},_apply:function(b,c){var f,h=g(),i=this.getMatrix(b),j=h.getContext("2d"),k=b.videoWidth||b.width,l=b.videoHeight||b.height,m=i.deg,n=i.dw,o=i.dh,p=k,q=l,r=i.filter,s=b,t=i.overlay,u=a.queue(function(){b.src=a.EMPTY_PNG,c(!1,h)}),v=a.renderImageToCanvas;for(m-=360*Math.floor(m/360),b._type=this.file.type;i.multipass&&e(p/n,q/o)>2;)p=p/2+.5|0,q=q/2+.5|0,f=g(),f.width=p,f.height=q,s!==b?(v(f,s,0,0,s.width,s.height,0,0,p,q),s=f):(s=f,v(s,b,i.sx,i.sy,i.sw,i.sh,0,0,p,q),i.sx=i.sy=i.sw=i.sh=0);h.width=m%180?o:n,h.height=m%180?n:o,h.type=i.type,h.quality=i.quality,j.rotate(m*Math.PI/180),v(j.canvas,s,i.sx,i.sy,i.sw||s.width,i.sh||s.height,180==m||270==m?-n:0,90==m||180==m?-o:0,n,o),n=h.width,o=h.height,t&&a.each([].concat(t),function(b){u.inc();var c=new window.Image,d=function(){var e=0|b.x,f=0|b.y,g=b.w||c.width,h=b.h||c.height,i=b.rel;e=1==i||4==i||7==i?(n-g+e)/2:2==i||5==i||8==i?n-(g+e):e,f=3==i||4==i||5==i?(o-h+f)/2:i>=6?o-(h+f):f,a.event.off(c,"error load abort",d);try{j.globalAlpha=b.opacity||1,j.drawImage(c,e,f,g,h)}catch(k){}u.next()};a.event.on(c,"error load abort",d),c.src=b.src,c.complete&&d()}),r&&(u.inc(),d.applyFilter(h,r,u.next)),u.check()},getMatrix:function(b){var c=a.extend({},this.matrix),d=c.sw=c.sw||b.videoWidth||b.naturalWidth||b.width,g=c.sh=c.sh||b.videoHeight||b.naturalHeight||b.height,h=c.dw=c.dw||d,i=c.dh=c.dh||g,j=d/g,k=h/i,l=c.resize;if("preview"==l){if(h!=d||i!=g){var m,n;k>=j?(m=d,n=m/k):(n=g,m=n*k),(m!=d||n!=g)&&(c.sx=~~((d-m)/2),c.sy=~~((g-n)/2),d=m,g=n)}}else"height"==l?h=i*j:"width"==l?i=h/j:l&&(d>h||g>i?"min"==l?(h=f(k>j?e(d,h):i*j),i=f(k>j?h/j:e(g,i))):(h=f(j>=k?e(d,h):i*j),i=f(j>=k?h/j:e(g,i))):(h=d,i=g));return c.sw=d,c.sh=g,c.dw=h,c.dh=i,c.multipass=a.multiPassResize,c},_trans:function(b){this._load(this.file,function(c,d){if(c)b(c);else try{this._apply(d,b)}catch(c){a.log("[err] FileAPI.Image.fn._apply:",c),b(c)}})},get:function(b){if(a.support.transform){var c=this,d=c.matrix;"auto"==d.deg?a.getInfo(c.file,function(a,e){d.deg=i[e&&e.exif&&e.exif.Orientation]||0,c._trans(b)}):c._trans(b)}else b("not_support_transform");return this},toData:function(a){return this.get(a)}},d.exifOrientation=i,d.transform=function(b,e,f,g){function h(h,i){var j={},k=a.queue(function(a){g(a,j)});h?k.fail():a.each(e,function(a,e){if(!k.isFail()){var g=new d(i.nodeType?i:b),h="function"==typeof a;if(h?a(i,g):a.width?g[a.preview?"preview":"resize"](a.width,a.height,a.strategy):a.maxWidth&&(i.width>a.maxWidth||i.height>a.maxHeight)&&g.resize(a.maxWidth,a.maxHeight,"max"),a.crop){var l=a.crop;g.crop(0|l.x,0|l.y,l.w||l.width,l.h||l.height)}a.rotate===c&&f&&(a.rotate="auto"),g.set({type:g.matrix.type||a.type||b.type||"image/png"}),h||g.set({deg:a.rotate,overlay:a.overlay,filter:a.filter,quality:a.quality||1}),k.inc(),g.toData(function(a,b){a?k.fail():(j[e]=b,k.next())})}})}b.width?h(!1,b):a.getInfo(b,h)},a.each(["TOP","CENTER","BOTTOM"],function(b,c){a.each(["LEFT","CENTER","RIGHT"],function(a,e){d[b+"_"+a]=3*c+e,d[a+"_"+b]=3*c+e})}),d.toCanvas=function(a){var c=b.createElement("canvas");return c.width=a.videoWidth||a.width,c.height=a.videoHeight||a.height,c.getContext("2d").drawImage(a,0,0),c},d.fromDataURL=function(b,c,d){var e=a.newImage(b);a.extend(e,c),d(e)},d.applyFilter=function(b,c,e){"function"==typeof c?c(b,e):window.Caman&&window.Caman("IMG"==b.tagName?d.toCanvas(b):b,function(){"string"==typeof c?this[c]():a.each(c,function(a,b){this[b](a)},this),this.render(e)})},a.renderImageToCanvas=function(b,c,d,e,f,g,h,i,j,k){try{return b.getContext("2d").drawImage(c,d,e,f,g,h,i,j,k)}catch(l){throw a.log("renderImageToCanvas failed"),l}},a.support.canvas=a.support.transform=h,a.Image=d}(FileAPI,document),function(a){"use strict";a(FileAPI)}(function(a){"use strict";if(window.navigator&&window.navigator.platform&&/iP(hone|od|ad)/.test(window.navigator.platform)){var b=a.renderImageToCanvas;a.detectSubsampling=function(a){var b,c;return a.width*a.height>1048576?(b=document.createElement("canvas"),b.width=b.height=1,c=b.getContext("2d"),c.drawImage(a,-a.width+1,0),0===c.getImageData(0,0,1,1).data[3]):!1},a.detectVerticalSquash=function(a,b){var c,d,e,f,g,h=a.naturalHeight||a.height,i=document.createElement("canvas"),j=i.getContext("2d");for(b&&(h/=2),i.width=1,i.height=h,j.drawImage(a,0,0),c=j.getImageData(0,0,1,h).data,d=0,e=h,f=h;f>d;)g=c[4*(f-1)+3],0===g?e=f:d=f,f=e+d>>1;return f/h||1},a.renderImageToCanvas=function(c,d,e,f,g,h,i,j,k,l){if("image/jpeg"===d._type){var m,n,o,p,q=c.getContext("2d"),r=document.createElement("canvas"),s=1024,t=r.getContext("2d");if(r.width=s,r.height=s,q.save(),m=a.detectSubsampling(d),m&&(e/=2,f/=2,g/=2,h/=2),n=a.detectVerticalSquash(d,m),m||1!==n){for(f*=n,k=Math.ceil(s*k/g),l=Math.ceil(s*l/h/n),j=0,p=0;h>p;){for(i=0,o=0;g>o;)t.clearRect(0,0,s,s),t.drawImage(d,e,f,g,h,-o,-p,g,h),q.drawImage(r,0,0,s,s,i,j,k,l),o+=s,i+=k;p+=s,j+=l}return q.restore(),c}}return b(c,d,e,f,g,h,i,j,k,l)}}}),function(a,b){"use strict";function c(b,c,d){var e=b.blob,f=b.file;if(f){if(!e.toDataURL)return void a.readAsBinaryString(e,function(a){"load"==a.type&&c(b,a.result)});var g={"image/jpeg":".jpe?g","image/png":".png"},h=g[b.type]?b.type:"image/png",i=g[h]||".png",j=e.quality||1;f.match(new RegExp(i+"$","i"))||(f+=i.replace("?","")),b.file=f,b.type=h,!d&&e.toBlob?e.toBlob(function(a){c(b,a)},h,j):c(b,a.toBinaryString(e.toDataURL(h,j)))}else c(b,e)}var d=b.document,e=b.FormData,f=function(){this.items=[]},g=b.encodeURIComponent;f.prototype={append:function(a,b,c,d){this.items.push({name:a,blob:b&&b.blob||(void 0==b?"":b),file:b&&(c||b.name),type:b&&(d||b.type)})},each:function(a){for(var b=0,c=this.items.length;c>b;b++)a.call(this,this.items[b])},toData:function(b,c){c._chunked=a.support.chunked&&c.chunkSize>0&&1==a.filter(this.items,function(a){return a.file}).length,a.support.html5?a.formData&&!this.multipart&&e?c._chunked?(a.log("FileAPI.Form.toPlainData"),this.toPlainData(b)):(a.log("FileAPI.Form.toFormData"),this.toFormData(b)):(a.log("FileAPI.Form.toMultipartData"),this.toMultipartData(b)):(a.log("FileAPI.Form.toHtmlData"),this.toHtmlData(b))},_to:function(b,c,d,e){var f=a.queue(function(){c(b)});this.each(function(g){try{d(g,b,f,e)}catch(h){a.log("FileAPI.Form._to: "+h.message),c(h)}}),f.check()},toHtmlData:function(b){this._to(d.createDocumentFragment(),b,function(b,c){var e,f=b.blob;b.file?(a.reset(f,!0),f.name=b.name,f.disabled=!1,c.appendChild(f)):(e=d.createElement("input"),e.name=b.name,e.type="hidden",e.value=f,c.appendChild(e))})},toPlainData:function(a){this._to({},a,function(a,b,d){a.file&&(b.type=a.file),a.blob.toBlob?(d.inc(),c(a,function(a,c){b.name=a.name,b.file=c,b.size=c.length,b.type=a.type,d.next()})):a.file?(b.name=a.blob.name,b.file=a.blob,b.size=a.blob.size,b.type=a.type):(b.params||(b.params=[]),b.params.push(g(a.name)+"="+g(a.blob))),b.start=-1,b.end=b.file&&b.file.FileAPIReadPosition||-1,b.retry=0})},toFormData:function(a){this._to(new e,a,function(a,b,d){a.blob&&a.blob.toBlob?(d.inc(),c(a,function(a,c){b.append(a.name,c,a.file),d.next()})):a.file?b.append(a.name,a.blob,a.file):b.append(a.name,a.blob),a.file&&b.append("_"+a.name,a.file)})},toMultipartData:function(b){this._to([],b,function(a,b,d,e){d.inc(),c(a,function(a,c){b.push("--_"+e+('\r\nContent-Disposition: form-data; name="'+a.name+'"'+(a.file?'; filename="'+g(a.file)+'"':"")+(a.file?"\r\nContent-Type: "+(a.type||"application/octet-stream"):"")+"\r\n\r\n"+(a.file?c:g(c))+"\r\n")),d.next()},!0)},a.expando)}},a.Form=f}(FileAPI,window),function(a,b){"use strict";var c=function(){},d=a.document,e=function(a){this.uid=b.uid(),this.xhr={abort:c,getResponseHeader:c,getAllResponseHeaders:c},this.options=a},f={"":1,XML:1,Text:1,Body:1};e.prototype={status:0,statusText:"",constructor:e,getResponseHeader:function(a){return this.xhr.getResponseHeader(a)},getAllResponseHeaders:function(){return this.xhr.getAllResponseHeaders()||{}},end:function(d,e){var f=this,g=f.options;f.end=f.abort=c,f.status=d,e&&(f.statusText=e),b.log("xhr.end:",d,e),g.complete(200==d||201==d?!1:f.statusText||"unknown",f),f.xhr&&f.xhr.node&&setTimeout(function(){var b=f.xhr.node;try{b.parentNode.removeChild(b)}catch(c){}try{delete a[f.uid]}catch(c){}a[f.uid]=f.xhr.node=null},9)},abort:function(){this.end(0,"abort"),this.xhr&&(this.xhr.aborted=!0,this.xhr.abort())},send:function(a){var b=this,c=this.options;a.toData(function(a){a instanceof Error?b.end(0,a.message):(c.upload(c,b),b._send.call(b,c,a))},c)},_send:function(c,e){var g,h=this,i=h.uid,j=h.uid+"Load",k=c.url;if(b.log("XHR._send:",e),c.cache||(k+=(~k.indexOf("?")?"&":"?")+b.uid()),e.nodeName){var l=c.jsonp;k=k.replace(/([a-z]+)=(\?)/i,"$1="+i),c.upload(c,h);var m=function(a){if(~k.indexOf(a.origin))try{var c=b.parseJSON(a.data);c.id==i&&n(c.status,c.statusText,c.response)}catch(d){n(0,d.message)}},n=a[i]=function(c,d,e){h.readyState=4,h.responseText=e,h.end(c,d),b.event.off(a,"message",m),a[i]=g=p=a[j]=null};h.xhr.abort=function(){try{p.stop?p.stop():p.contentWindow.stop?p.contentWindow.stop():p.contentWindow.document.execCommand("Stop")}catch(a){}n(0,"abort")},b.event.on(a,"message",m),a[j]=function(){try{var a=p.contentWindow,c=a.document,d=a.result||b.parseJSON(c.body.innerHTML);n(d.status,d.statusText,d.response)}catch(e){b.log("[transport.onload]",e)}},g=d.createElement("div"),g.innerHTML='
'+(l&&c.url.indexOf("=?")<0?'':"")+"
";var o=g.getElementsByTagName("form")[0],p=g.getElementsByTagName("iframe")[0];o.appendChild(e),b.log(o.parentNode.innerHTML),d.body.appendChild(g),h.xhr.node=g,h.readyState=2;try{o.submit()}catch(q){b.log("iframe.error: "+q)}o=null}else{if(k=k.replace(/([a-z]+)=(\?)&?/i,""),this.xhr&&this.xhr.aborted)return void b.log("Error: already aborted");if(g=h.xhr=b.getXHR(),e.params&&(k+=(k.indexOf("?")<0?"?":"&")+e.params.join("&")),g.open("POST",k,!0),b.withCredentials&&(g.withCredentials="true"),c.headers&&c.headers["X-Requested-With"]||g.setRequestHeader("X-Requested-With","XMLHttpRequest"),b.each(c.headers,function(a,b){g.setRequestHeader(b,a)}),c._chunked){g.upload&&g.upload.addEventListener("progress",b.throttle(function(a){e.retry||c.progress({type:a.type,total:e.size,loaded:e.start+a.loaded,totalSize:e.size},h,c)},100),!1),g.onreadystatechange=function(){var a=parseInt(g.getResponseHeader("X-Last-Known-Byte"),10);if(h.status=g.status,h.statusText=g.statusText,h.readyState=g.readyState,4==g.readyState){for(var d in f)h["response"+d]=g["response"+d];if(g.onreadystatechange=null,!g.status||g.status-201>0)if(b.log("Error: "+g.status),(!g.status&&!g.aborted||500==g.status||416==g.status)&&++e.retry<=c.chunkUploadRetry){var i=g.status?0:b.chunkNetworkDownRetryTimeout;c.pause(e.file,c),b.log("X-Last-Known-Byte: "+a),a?e.end=a:(e.end=e.start-1,416==g.status&&(e.end=e.end-c.chunkSize)),setTimeout(function(){h._send(c,e)},i)}else h.end(g.status);else e.retry=0,e.end==e.size-1?h.end(g.status):(b.log("X-Last-Known-Byte: "+a),a&&(e.end=a),e.file.FileAPIReadPosition=e.end,setTimeout(function(){h._send(c,e)},0));g=null}},e.start=e.end+1,e.end=Math.max(Math.min(e.start+c.chunkSize,e.size)-1,e.start);var r=e.file,s=(r.slice||r.mozSlice||r.webkitSlice).call(r,e.start,e.end+1);e.size&&!s.size?setTimeout(function(){h.end(-1)}):(g.setRequestHeader("Content-Range","bytes "+e.start+"-"+e.end+"/"+e.size),g.setRequestHeader("Content-Disposition","attachment; filename="+encodeURIComponent(e.name)),g.setRequestHeader("Content-Type",e.type||"application/octet-stream"),g.send(s)),r=s=null}else if(g.upload&&g.upload.addEventListener("progress",b.throttle(function(a){c.progress(a,h,c)},100),!1),g.onreadystatechange=function(){if(h.status=g.status,h.statusText=g.statusText,h.readyState=g.readyState,4==g.readyState){for(var a in f)h["response"+a]=g["response"+a];if(g.onreadystatechange=null,!g.status||g.status>201)if(b.log("Error: "+g.status),(!g.status&&!g.aborted||500==g.status)&&(c.retry||0)=0?a+"px":a}function d(a){var c,d=f.createElement("canvas"),e=!1;try{c=d.getContext("2d"),c.drawImage(a,0,0,1,1),e=255!=c.getImageData(0,0,1,1).data[4]}catch(g){b.log("[FileAPI.Camera] detectVideoSignal:",g)}return e}var e=a.URL||a.webkitURL,f=a.document,g=a.navigator,h=g.getUserMedia||g.webkitGetUserMedia||g.mozGetUserMedia||g.msGetUserMedia,i=!!h;b.support.media=i;var j=function(a){this.video=a};j.prototype={isActive:function(){return!!this._active},start:function(a){var b,c,f=this,i=f.video,j=function(d){f._active=!d,clearTimeout(c),clearTimeout(b),a&&a(d,f)};h.call(g,{video:!0},function(a){f.stream=a,i.src=e.createObjectURL(a),b=setInterval(function(){d(i)&&j(null)},1e3),c=setTimeout(function(){j("timeout"); -},5e3),i.play()},j)},stop:function(){try{this._active=!1,this.video.pause();try{this.stream.stop()}catch(a){b.each(this.stream.getTracks(),function(a){a.stop()})}this.stream=null}catch(a){b.log("[FileAPI.Camera] stop:",a)}},shot:function(){return new k(this.video)}},j.get=function(a){return new j(a.firstChild)},j.publish=function(d,e,g){"function"==typeof e&&(g=e,e={}),e=b.extend({},{width:"100%",height:"100%",start:!0},e),d.jquery&&(d=d[0]);var h=function(a){if(a)g(a);else{var b=j.get(d);e.start?b.start(g):g(null,b)}};if(d.style.width=c(e.width),d.style.height=c(e.height),b.html5&&i){var k=f.createElement("video");k.style.width=c(e.width),k.style.height=c(e.height),a.jQuery?jQuery(d).empty():d.innerHTML="",d.appendChild(k),h()}else j.fallback(d,e,h)},j.fallback=function(a,b,c){c("not_support_camera")};var k=function(a){var c=a.nodeName?b.Image.toCanvas(a):a,d=b.Image(c);return d.type="image/png",d.width=c.width,d.height=c.height,d.size=c.width*c.height*4,d};j.Shot=k,b.Camera=j}(window,FileAPI),function(a,b,c){"use strict";var d=a.document,e=a.location,f=a.navigator,g=c.each;c.support.flash=function(){var b=f.mimeTypes,d=!1;if(f.plugins&&"object"==typeof f.plugins["Shockwave Flash"])d=f.plugins["Shockwave Flash"].description&&!(b&&b["application/x-shockwave-flash"]&&!b["application/x-shockwave-flash"].enabledPlugin);else try{d=!(!a.ActiveXObject||!new ActiveXObject("ShockwaveFlash.ShockwaveFlash"))}catch(g){c.log("Flash -- does not supported.")}return d&&/^file:/i.test(e)&&c.log("[warn] Flash does not work on `file:` protocol."),d}(),c.support.flash&&(!c.html5||!c.support.html5||c.cors&&!c.support.cors||c.media&&!c.support.media)&&function(){function h(a){return('').replace(/#(\w+)#/gi,function(b,c){return a[c]})}function i(a,b){if(a&&a.style){var c,d;for(c in b){d=b[c],"number"==typeof d&&(d+="px");try{a.style[c]=d}catch(e){}}}}function j(a,b){g(b,function(b,c){var d=a[c];a[c]=function(){return this.parent=d,b.apply(this,arguments)}})}function k(a){return a&&!a.flashId}function l(a){var b=a.wid=c.uid();return v._fn[b]=a,"FileAPI.Flash._fn."+b}function m(a){try{v._fn[a.wid]=null,delete v._fn[a.wid]}catch(b){}}function n(a,b){if(!u.test(a)){if(/^\.\//.test(a)||"/"!=a.charAt(0)){var c=e.pathname;c=c.substr(0,c.lastIndexOf("/")),a=(c+"/"+a).replace("/./","/")}"//"!=a.substr(0,2)&&(a="//"+e.host+a),u.test(a)||(a=e.protocol+a)}return b&&(a+=(/\?/.test(a)?"&":"?")+b),a}function o(a,b,e){function f(){try{var a=v.get(j);a.setImage(b)}catch(d){c.log('[err] FlashAPI.Preview.setImage -- can not set "base64":',d)}}var g,j=c.uid(),k=d.createElement("div"),o=10;for(g in a)k.setAttribute(g,a[g]),k[g]=a[g];i(k,a),a.width="100%",a.height="100%",k.innerHTML=h(c.extend({id:j,src:n(c.flashImageUrl,"r="+c.uid()),wmode:"opaque",flashvars:"scale="+a.scale+"&callback="+l(function p(){return m(p),--o>0&&f(),!0})},a)),e(!1,k),k=null}function p(a){return{id:a.id,name:a.name,matrix:a.matrix,flashId:a.flashId}}function q(b){var c=b.getBoundingClientRect(),e=d.body,f=(b&&b.ownerDocument).documentElement;return{top:c.top+(a.pageYOffset||f.scrollTop)-(f.clientTop||e.clientTop||0),left:c.left+(a.pageXOffset||f.scrollLeft)-(f.clientLeft||e.clientLeft||0),width:c.right-c.left,height:c.bottom-c.top}}var r=c.uid(),s=0,t={},u=/^https?:/i,v={_fn:{},init:function(){var a=d.body&&d.body.firstChild;if(a)do if(1==a.nodeType){c.log("FlashAPI.state: awaiting");var b=d.createElement("div");return b.id="_"+r,i(b,{top:1,right:1,width:5,height:5,position:"absolute",zIndex:"2147483647"}),a.parentNode.insertBefore(b,a),void v.publish(b,r)}while(a=a.nextSibling);10>s&&setTimeout(v.init,50*++s)},publish:function(a,b,d){d=d||{},a.innerHTML=h({id:b,src:n(c.flashUrl,"r="+c.version),wmode:d.camera?"":"transparent",flashvars:"callback="+(d.onEvent||"FileAPI.Flash.onEvent")+"&flashId="+b+"&storeKey="+f.userAgent.match(/\d/gi).join("")+"_"+c.version+(v.isReady||(c.pingUrl?"&ping="+c.pingUrl:""))+"&timeout="+c.flashAbortTimeout+(d.camera?"&useCamera="+n(c.flashWebcamUrl):"")+"&debug="+(c.debug?"1":"")},d)},ready:function(){c.log("FlashAPI.state: ready"),v.ready=c.F,v.isReady=!0,v.patch(),v.patchCamera&&v.patchCamera(),c.event.on(d,"mouseover",v.mouseover),c.event.on(d,"click",function(a){v.mouseover(a)&&(a.preventDefault?a.preventDefault():a.returnValue=!0)})},getEl:function(){return d.getElementById("_"+r)},getWrapper:function(a){do if(/js-fileapi-wrapper/.test(a.className))return a;while((a=a.parentNode)&&a!==d.body)},mouseover:function(a){var b=c.event.fix(a).target;if(/input/i.test(b.nodeName)&&"file"==b.type&&!b.disabled){var e=b.getAttribute(r),f=v.getWrapper(b);if(c.multiFlash){if("i"==e||"r"==e)return!1;if("p"!=e){b.setAttribute(r,"i");var g=d.createElement("div");if(!f)return void c.log("[err] FlashAPI.mouseover: js-fileapi-wrapper not found");i(g,{top:0,left:0,width:b.offsetWidth,height:b.offsetHeight,zIndex:"2147483647",position:"absolute"}),f.appendChild(g),v.publish(g,c.uid()),b.setAttribute(r,"p")}return!0}if(f){var h=q(f);i(v.getEl(),h),v.curInp=b}}else/object|embed/i.test(b.nodeName)||i(v.getEl(),{top:1,left:1,width:5,height:5})},onEvent:function(a){var b=a.type;if("ready"==b){try{v.getInput(a.flashId).setAttribute(r,"r")}catch(d){}return v.ready(),setTimeout(function(){v.mouseenter(a)},50),!0}"ping"===b?c.log("(flash -> js).ping:",[a.status,a.savedStatus],a.error):"log"===b?c.log("(flash -> js).log:",a.target):b in v&&setTimeout(function(){c.log("FlashAPI.event."+a.type+":",a),v[b](a)},1)},mouseenter:function(a){var b=v.getInput(a.flashId);if(b){v.cmd(a,"multiple",null!=b.getAttribute("multiple"));var d=[],e={};g((b.getAttribute("accept")||"").split(/,\s*/),function(a){c.accept[a]&&g(c.accept[a].split(" "),function(a){e[a]=1})}),g(e,function(a,b){d.push(b)}),v.cmd(a,"accept",d.length?d.join(",")+","+d.join(",").toUpperCase():"*")}},get:function(b){return d[b]||a[b]||d.embeds[b]},getInput:function(a){if(!c.multiFlash)return v.curInp;try{var b=v.getWrapper(v.get(a));if(b)return b.getElementsByTagName("input")[0]}catch(d){c.log('[err] Can not find "input" by flashId:',a,d)}},select:function(a){var e,f=v.getInput(a.flashId),h=c.uid(f),i=a.target.files;g(i,function(a){c.checkFileObj(a)}),t[h]=i,d.createEvent?(e=d.createEvent("Event"),e.files=i,e.initEvent("change",!0,!0),f.dispatchEvent(e)):b?b(f).trigger({type:"change",files:i}):(e=d.createEventObject(),e.files=i,f.fireEvent("onchange",e))},cmd:function(a,b,d,e){try{return c.log("(js -> flash)."+b+":",d),v.get(a.flashId||a).cmd(b,d)}catch(f){c.log("(js -> flash).onError:",f.toString()),e||setTimeout(function(){v.cmd(a,b,d,!0)},50)}},patch:function(){c.flashEngine=!0,j(c,{getFiles:function(a,b,d){if(d)return c.filterFiles(c.getFiles(a),b,d),null;var e=c.isArray(a)?a:t[c.uid(a.target||a.srcElement||a)];return e?(b&&(b=c.getFilesFilter(b),e=c.filter(e,function(a){return b.test(a.name)})),e):this.parent.apply(this,arguments)},getInfo:function(a,b){if(k(a))this.parent.apply(this,arguments);else if(a.isShot)b(null,a.info={width:a.width,height:a.height});else{if(!a.__info){var d=a.__info=c.defer();v.cmd(a,"getFileInfo",{id:a.id,callback:l(function e(b,c){m(e),d.resolve(b,a.info=c)})})}a.__info.then(b)}}}),c.support.transform=!0,c.Image&&j(c.Image.prototype,{get:function(a,b){return this.set({scaleMode:b||"noScale"}),this.parent(a)},_load:function(a,b){if(c.log("FlashAPI.Image._load:",a),k(a))this.parent.apply(this,arguments);else{var d=this;c.getInfo(a,function(c){b.call(d,c,a)})}},_apply:function(a,b){if(c.log("FlashAPI.Image._apply:",a),k(a))this.parent.apply(this,arguments);else{var d=this.getMatrix(a.info),e=b;v.cmd(a,"imageTransform",{id:a.id,matrix:d,callback:l(function f(g,h){c.log("FlashAPI.Image._apply.callback:",g),m(f),g?e(g):c.support.html5||c.support.dataURI&&!(h.length>3e4)?(d.filter&&(e=function(a,e){a?b(a):c.Image.applyFilter(e,d.filter,function(){b(a,this.canvas)})}),c.newImage("data:"+a.type+";base64,"+h,e)):o({width:d.deg%180?d.dh:d.dw,height:d.deg%180?d.dw:d.dh,scale:d.scaleMode},h,e)})})}},toData:function(a){var b=this.file,d=b.info,e=this.getMatrix(d);c.log("FlashAPI.Image.toData"),k(b)?this.parent.apply(this,arguments):("auto"==e.deg&&(e.deg=c.Image.exifOrientation[d&&d.exif&&d.exif.Orientation]||0),a.call(this,!b.info,{id:b.id,flashId:b.flashId,name:b.name,type:b.type,matrix:e}))}}),c.Image&&j(c.Image,{fromDataURL:function(a,b,d){!c.support.dataURI||a.length>3e4?o(c.extend({scale:"exactFit"},b),a.replace(/^data:[^,]+,/,""),function(a,b){d(b)}):this.parent(a,b,d)}}),j(c.Form.prototype,{toData:function(a){for(var b=this.items,d=b.length;d--;)if(b[d].file&&k(b[d].blob))return this.parent.apply(this,arguments);c.log("FlashAPI.Form.toData"),a(b)}}),j(c.XHR.prototype,{_send:function(a,b){if(b.nodeName||b.append&&c.support.html5||c.isArray(b)&&"string"==typeof b[0])return this.parent.apply(this,arguments);var d,e,f={},h={},i=this;if(g(b,function(a){a.file?(h[a.name]=a=p(a.blob),e=a.id,d=a.flashId):f[a.name]=a.blob}),e||(d=r),!d)return c.log("[err] FlashAPI._send: flashId -- undefined"),this.parent.apply(this,arguments);c.log("FlashAPI.XHR._send: "+d+" -> "+e),i.xhr={headers:{},abort:function(){v.cmd(d,"abort",{id:e})},getResponseHeader:function(a){return this.headers[a]},getAllResponseHeaders:function(){return this.headers}};var j=c.queue(function(){v.cmd(d,"upload",{url:n(a.url.replace(/([a-z]+)=(\?)&?/i,"")),data:f,files:e?h:null,headers:a.headers||{},callback:l(function b(d){var e=d.type,f=d.result;c.log("FlashAPI.upload."+e),"progress"==e?(d.loaded=Math.min(d.loaded,d.total),d.lengthComputable=!0,a.progress(d)):"complete"==e?(m(b),"string"==typeof f&&(i.responseText=f.replace(/%22/g,'"').replace(/%5c/g,"\\").replace(/%26/g,"&").replace(/%25/g,"%")),i.end(d.status||200)):("abort"==e||"error"==e)&&(i.end(d.status||0,d.message),m(b))})})});g(h,function(a){j.inc(),c.getInfo(a,j.next)}),j.check()}})}};c.Flash=v,c.newImage("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==",function(a,b){c.support.dataURI=!(1!=b.width||1!=b.height),v.init()})}()}(window,window.jQuery,FileAPI),function(a,b,c){"use strict";var d=c.each,e=[];!c.support.flash||!c.media||c.support.media&&c.html5||!function(){function a(a){var b=a.wid=c.uid();return c.Flash._fn[b]=a,"FileAPI.Flash._fn."+b}function b(a){try{c.Flash._fn[a.wid]=null,delete c.Flash._fn[a.wid]}catch(b){}}var f=c.Flash;c.extend(c.Flash,{patchCamera:function(){c.Camera.fallback=function(d,e,g){var h=c.uid();c.log("FlashAPI.Camera.publish: "+h),f.publish(d,h,c.extend(e,{camera:!0,onEvent:a(function i(a){"camera"===a.type&&(b(i),a.error?(c.log("FlashAPI.Camera.publish.error: "+a.error),g(a.error)):(c.log("FlashAPI.Camera.publish.success: "+h),g(null)))})}))},d(e,function(a){c.Camera.fallback.apply(c.Camera,a)}),e=[],c.extend(c.Camera.prototype,{_id:function(){return this.video.id},start:function(d){var e=this;f.cmd(this._id(),"camera.on",{callback:a(function g(a){b(g),a.error?(c.log("FlashAPI.camera.on.error: "+a.error),d(a.error,e)):(c.log("FlashAPI.camera.on.success: "+e._id()),e._active=!0,d(null,e))})})},stop:function(){this._active=!1,f.cmd(this._id(),"camera.off")},shot:function(){c.log("FlashAPI.Camera.shot:",this._id());var a=c.Flash.cmd(this._id(),"shot",{});return a.type="image/png",a.flashId=this._id(),a.isShot=!0,new c.Camera.Shot(a)}})}}),c.Camera.fallback=function(){e.push(arguments)}}()}(window,window.jQuery,FileAPI),"function"==typeof define&&define.amd&&define("FileAPI",[],function(){return FileAPI}); \ No newline at end of file diff --git a/manager/media/browser/mcpuk/js/FileAPI/crossdomain.xml.example b/manager/media/browser/mcpuk/js/FileAPI/crossdomain.xml.example deleted file mode 100644 index 32920c4f07..0000000000 --- a/manager/media/browser/mcpuk/js/FileAPI/crossdomain.xml.example +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/manager/media/browser/mcpuk/js/FileAPI/jquery.fileapi.min.js b/manager/media/browser/mcpuk/js/FileAPI/jquery.fileapi.min.js deleted file mode 100644 index ec7369ec59..0000000000 --- a/manager/media/browser/mcpuk/js/FileAPI/jquery.fileapi.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! fileapi 2.0.1 - BSD | git://github.com/mailru/FileAPI.git */ -(function(e,t){"use strict";var n=e.noop,i=!e.fn.prop,a=i?"attr":"prop",r="data-fileapi",o="data-fileapi-id",s=function(i,a){if(this.$el=i=e(i).on("change.fileapi",e.proxy(this,"_onSelect")),this.el=i[0],this._options={},this.options=a=e.extend({url:0,data:{},accept:0,multiple:!1,paramName:0,dataType:"json",duplicate:!1,chunkSize:0,chunkUploadRetry:3,maxSize:0,maxFiles:0,imageSize:0,sortFn:0,filterFn:0,autoUpload:!1,lang:{B:"bytes",KB:"KB",MB:"MB",GB:"GB",TB:"TB"},sizeFormat:"0.00",imageTransform:0,elements:{ctrl:{upload:'[data-fileapi="ctrl.upload"]',reset:'[data-fileapi="ctrl.reset"]',abort:'[data-fileapi="ctrl.abort"]'},empty:{show:'[data-fileapi="empty.show"]',hide:'[data-fileapi="empty.hide"]'},emptyQueue:{show:'[data-fileapi="emptyQueue.show"]',hide:'[data-fileapi="emptyQueue.hide"]'},active:{show:'[data-fileapi="active.show"]',hide:'[data-fileapi="active.hide"]'},size:'[data-fileapi="size"]',name:'[data-fileapi="name"]',progress:'[data-fileapi="progress"]',file:{tpl:'[data-fileapi="file.tpl"]',progress:'[data-fileapi="file.progress"]',active:{show:'[data-fileapi="active.show"]',hide:'[data-fileapi="active.hide"]'},preview:{el:0,get:0,width:0,height:0,processing:0}},dnd:{el:'[data-fileapi="dnd"]',hover:"dnd_hover"}},onDrop:n,onDropHover:n,onSelect:n,onUpload:n,onProgress:n,onComplete:n,onFileUpload:n,onFileProgress:n,onFileComplete:n},a),!a.url){var o=this.$el.attr("action")||this.$el.find("form").attr("action");o?a.url=o:this._throw("url — is not defined")}this.$files=this.elem("list"),this.itemTplFn=e.fn.fileapi.tpl(e("
").append(this.elem("file.tpl")).html()),t.each(a,function(e,t){this._setOption(t,e)},this),this.$el.on("reset.fileapi",e.proxy(this,"_onReset")).on("submit.fileapi",e.proxy(this,"_onSubmit")).on("upload.fileapi progress.fileapi complete.fileapi",e.proxy(this,"_onUploadEvent")).on("fileupload.fileapi fileprogress.fileapi filecomplete.fileapi",e.proxy(this,"_onFileUploadEvent")).on("click","["+r+"]",e.proxy(this,"_onActionClick"));var s=a.elements.ctrl;s&&(s.reset&&this.$el.on("click.fileapi",s.reset,e.proxy(this,"_onReset")),s.upload&&this.$el.on("click.fileapi",s.upload,e.proxy(this,"_onSubmit"))),this.elem("dnd.el",!0).dnd(e.proxy(this,"_onDropHover"),e.proxy(this,"_onDrop")),this.$progress=this.elem("progress"),this._crop={},this._rotate={},this.files=[],this.uploaded=[],this.clear()};s.prototype={constructor:s,_throw:function(e){throw"jquery.fileapi: "+e},_getFiles:function(e,n){var i=this.options,a=i.maxSize,r=i.filterFn,o=t.getFiles(e),s={all:o,files:[],other:[],duplicate:i.duplicate?[]:this._extractDuplicateFiles(o)},l=i.imageSize,u=this;l||r?t.filterFiles(o,function(e,t){var n=!0;return t&&l&&(n=(!l.minWidth||t.width>=l.minWidth)&&(!l.minHeight||t.height>=l.minHeight)&&(!l.maxWidth||t.height<=l.maxWidth)&&(!l.maxHeight||t.height<=l.maxHeight)),n&&(!a||a>=e.size)&&(!r||r(e,t))},function(e,t){s.files=e,s.other=t,n.call(u,s)}):(t.each(o,function(e){s[!a||a>=e.size?"files":"other"].push(e)}),n.call(u,s))},_extractDuplicateFiles:function(e){for(var t,n=[],i=e.length,a=this.files;i--;)for(t=a.length;t--;)if(this._fileCompare(e[i],a[t])){n.push(e.splice(i,1));break}return n},_fileCompare:function(e,t){return e.size==t.size&&e.name==t.name},_getFormatedSize:function(e){var n=this.options,i="B";return e>=t.TB?e/=t[i="TB"]:e>=t.GB?e/=t[i="GB"]:e>=t.MB?e/=t[i="MB"]:e>=t.KB&&(e/=t[i="KB"]),n.sizeFormat.replace(/^\d+([^\d]+)(\d*)/,function(t,a,r){return e=e.toFixed(r.length),(e+"").replace(".",a)+" "+n.lang[i]})},_onSelect:function(t){this._getFiles(t,e.proxy(function(e){e.all.length&&this.emit("select",e)!==!1&&this.add(e.files)},this))},_onActionClick:function(n){var i=n.currentTarget,a=e.attr(i,r),s=e(i).closest("["+o+"]",this.$el),l=s.attr(o),u=!0;"remove"==a?(s.remove(),this.queue=t.filter(this.queue,function(e){return t.uid(e)!=l}),this.files=t.filter(this.files,function(e){return t.uid(e)!=l}),this._redraw()):/^rotate/.test(a)?this.rotate(l,/ccw/.test(a)?"-=90":"+=90"):u=!1,u&&n.preventDefault()},_onSubmit:function(e){this.upload(),e.preventDefault()},_onReset:function(e){this.clear(),e.preventDefault()},_onDrop:function(e){this._getFiles(e,function(e){this.emit("drop",e)!==!1&&this.add(e.files)})},_onDropHover:function(t,n){if(this.emit("dropHover",{state:t,event:n})!==!1){var i=this.option("elements.dnd.hover");i&&e(n.currentTarget).toggleClass(i,t)}},_getUploadEvent:function(t){var n=this.xhr,i={xhr:n,file:n.currentFile,files:n.files,widget:this};return e.extend(i,t)},_emitUploadEvent:function(e){var t=this._getUploadEvent();this.emit(e+"upload",t)},_emitProgressEvent:function(e,t){var n=this._getUploadEvent(t);this.emit(e+"progress",n)},_emitCompleteEvent:function(t,n){var i=this.xhr,a=this._getUploadEvent({error:n,status:i.status,statusText:i.statusText,result:i.responseText});"json"==this.options.dataType&&(a.result=e.parseJSON(a.result)),this.emit(t+"complete",a)},_onUploadEvent:function(e,t){var n=this,i=this.$progress,a=e.type;if("progress"==a)i.stop().animate({width:100*(t.loaded/t.total)+"%"},300);else if("upload"==a)i.width(0);else{var r=function(){i.dequeue(),n.clear()};this.xhr=null,this.active=!1,i.length?i.queue(r):r()}},_onFileUploadPrepare:function(n,i){var a=t.uid(n),r=this._rotate[a],o=this._crop[a];if(r||o){var s=i.imageTransform=i.imageTransform||{};e.isEmptyObject(s)||parseInt(s.maxWidth||s.minWidth||s.width,10)>0||s.type||s.quality?(s.crop=o,s.rotate=r):t.each(s,function(e){e.crop=o,e.rotate=r})}},_onFileUploadEvent:function(e,n){var i=this,a=e.type.substr(4),o=t.uid(n.file),s=this.fileElem(o),l=this._$fileprogress;if(this.__fileId!==o&&(this.__fileId=o,this._$fileprogress=l=s.find(this.option("elements.file.progress"))),"progress"==a)l.stop().animate({width:100*(n.loaded/n.total)+"%"},300);else if("upload"==a||"complete"==a){var u=function(){var e="elements.file."+a;"upload"==a&&(s.find("["+r+'="remove"]').hide(),l.width(0)),l.dequeue(),s.find(i.option(e+".show")).show(),s.find(i.option(e+".hide")).hide()};l.length?l.queue(u):u(),"complete"==a&&(this.uploaded.push(n.file),delete this._rotate[o])}},_redraw:function(){var n=!!this.active,i=this.files,r=!i.length&&!n,s=!this.queue.length&&!n,l=[],u=0,c=this.$files,f=c.children().length,d=this.option("elements.file.preview");t.each(i,function(n,i){var a=t.uid(n);if(l.push(n.name),u+=n.size,c.length&&!this.fileElem(a).length){var r=this.itemTplFn({$idx:f+i,uid:n.uid,name:n.name,type:n.type,size:n.size,sizeText:this._getFormatedSize(n.size)});c.append(e(r).attr(o,a)),d.el&&this._makeFilePreview(a,n,d)}},this),this.elem("name").text(l.join(", ")),this.elem("size").text(this._getFormatedSize(u)),this.__empty!==r&&(this.__empty=r,this.elem("empty.show").toggle(r),this.elem("empty.hide").toggle(!r)),this.__emptyQueue!==s&&(this.__emptyQueue=r,this.elem("emptyQueue.show").toggle(s),this.elem("emptyQueue.hide").toggle(!s)),this.__active!==n&&(this.__active=n,this.elem("active.show").toggle(n),this.elem("active.hide").toggle(!n),this.$(".js-fileapi-wrapper,:file")[n?"attr":"removeAttr"]("aria-disabled",n)[a]("disabled",n)),this.elem("ctrl.upload").add(this.elem("ctrl.reset"))[r||n?"attr":"removeAttr"]("aria-disabled",r||n)[a]("disabled",r||n)},_makeFilePreview:function(e,n,i,a){var r=this,o=a?r.$(i.el):r.fileElem(e).find(i.el);if(/^image/.test(n.type)){t.log("_makeFilePreview:",e,n);var s=t.Image(n),l=function(){s.get(function(t,a){r._crop[e]||(t?(i.get&&i.get(o,n),r.emit("filePreviewError",{error:t,file:n})):o.html(a))})};i.width&&s.preview(i.width,i.height),i.rotate&&s.rotate(i.rotate),i.processing?i.processing(n,s,l):l()}else i.get&&i.get(o,n)},emit:function(t,n){var i,a=this.options,r=e.Event(t);return r.widget=this,t=e.camelCase("on-"+t.replace(/(file)(upload)/,"$1-$2")),e.isFunction(a[t])&&(i=a[t].call(this.el,r,n)),i!==!1&&this.$el.triggerHandler(r,n)},add:function(e){if(e.length){var n=this.options,i=n.sortFn,a=n.elements.preview;i&&e.sort(i),a&&a.el&&t.each(e,function(e){this._makeFilePreview(t.uid(e),e,a,!0)},this),this.xhr&&this.xhr.append(e),this.queue=this.queue.concat(e),this.files=this.files.concat(e),this.options.autoUpload?this.upload():this._redraw()}},$:function(t,n){return"string"==typeof t&&(t=/^#/.test(t)?t:(n?e(n):this.$el).find(t)),e(t)},elem:function(t,n){var i=this.option("elements."+t);return void 0===i&&n&&(i=this.option("elements."+t.substr(0,t.lastIndexOf(".")))),this.$("string"!=e.type(i)&&e.isEmptyObject(i)?[]:i)},fileElem:function(e){return this.$("["+o+'="'+e+'"]')},option:function(n,i){if(void 0!==i&&e.isPlainObject(i))return t.each(i,function(e,t){this.option(n+"."+t,e)},this),this;var a,r,o=this.options,s=o[n],l=0;if(-1!=n.indexOf("."))for(s=o,n=n.split("."),a=n.length;a>l;l++){if(r=n[l],void 0!==i&&1===a-l){s[r]=i;break}void 0===s[r]&&(s[r]={}),s=s[r]}else void 0!==i&&(o[n]=i);return void 0!==i&&(this._setOption(n,i,this._options[n]),this._options[n]=i),void 0!==i?i:s},_setOption:function(e,t){switch(e){case"accept":case"multiple":case"paramName":"paramName"==e&&(e="name"),t&&this.$(":file")[a](e,t)}},serialize:function(){var t,n={};return this.$el.find(":input").each(function(i,a){(i=a.name)&&!a.disabled&&(a.checked||/select|textarea|input/i.test(a.nodeName)&&/checkbox|radio/i.test(a.type))&&(t=e(a).val(),void 0!==n[i]?(n[i].push||(n[i]=[n[i]]),n[i].push(t)):n[i]=t)}),n},upload:function(){if(!this.active){this.active=!0;var n=this.$el,i=this.options,a={},r={url:i.url,data:e.extend({},this.serialize(),i.data),files:a,chunkSize:0|i.chunkSize,chunkUploadRetry:0|i.chunkUploadRetry,prepare:e.proxy(this,"_onFileUploadPrepare"),imageTransform:i.imageTransform};a[n.find(":file").attr("name")||"files[]"]=this.queue,t.each(["upload","progress","complete"],function(t){r[t]=e.proxy(this,e.camelCase("_emit-"+t+"Event"),""),r["file"+t]=e.proxy(this,e.camelCase("_emit-"+t+"Event"),"file")},this),this.xhr=t.upload(r),this._redraw()}},crop:function(n,i){var a=t.uid(n),r=this.options,o=r.multiple?this.option("elements.file.preview"):r.elements.preview,s=(r.multiple?this.fileElem(a):this.$el).find(o&&o.el);s.length&&t.getInfo(n,e.proxy(function(a,r){if(!a){s.find("div>div").length||s.html(e("
").css(o).css("overflow","hidden")),this.__cropFile!==n&&(this.__cropFile=n,t.Image(n).get(function(t,n){s.find(">div>div").html(e(n).width("100%").height("100%"))},"exactFit"));var l=o.width/i.w,u=o.height/i.h;s.find(">div>div").css({width:Math.round(l*r.width),height:Math.round(u*r.height),marginLeft:-Math.round(l*i.x),marginTop:-Math.round(u*i.y)})}},this)),this._crop[a]=i},rotate:function(e,n){var i="object"==typeof e?t.uid(e):e,a=this.options,r=a.multiple?this.option("elements.file.preview"):a.elements.preview,o=(a.multiple?this.fileElem(i):this.$el).find(r&&r.el),s=this._rotate;/([+-])=/.test(n)?n=s[i]=(s[i]||0)+("+"==RegExp.$1?1:-1)*n.substr(2):s[i]=n,o.css({"-webkit-transform":"rotate("+n+"deg)","-moz-transform":"rotate("+n+"deg)",transform:"rotate("+n+"deg)"})},clear:function(){this.queue=[],this._redraw()},widget:function(){return this},destroy:function(){this.$el.off(".fileapi").removeData("fileapi")}},e.fn.fileapi=function(t,n){var i=this.data("fileapi");if(i){if("widget"===t)return i;if("string"==typeof t){var a,r=i[t];return e.isFunction(r)?a=r.call(i,n,arguments[2]):void 0===r&&(a=this.option(t,n)),void 0===a?this:a}}else this.data("fileapi",new s(this,t));return this},e.fn.fileapi.version="0.1.0",e.fn.fileapi.tpl=function(e){var t=0,n="__b+='";return e.replace(/(?:<|<)%([-=])?([\s\S]+?)%(?:>|>)|$/g,function(i,a,r,o){return n+=e.slice(t,o).replace(/[\r\n"']/g,function(e){return"\\"+e}),r&&(n+=a?"'+\n((__x=("+r+"))==null?'':"+("-"==a?"__esc(__x)":"__x")+")\n+'":"';\n"+r+"\n__b+='"),t=o+i.length,i}),Function("ctx","var __x,__b='',__esc=function(val){return typeof val=='string'?val.replace(/ @@ -23,9 +23,8 @@ browser.initUploader = function() { browser.clearUpload(); upload.trigger('click'); }); - FileAPI.event.on(upload.get(0), 'change', function (evt){ - var files = FileAPI.getFiles(evt); // Retrieve file list - browser.prepareFiles(files); + upload.on('change', function () { + browser.prepareFiles(this.files); }); browser.initFilesDropGuards(); browser.initFilesDropzone(); @@ -149,18 +148,13 @@ browser.preventExternalFileDropDefault = function(evt) { }; browser.extractDroppedFiles = function(evt) { - var files = FileAPI.getFiles(evt) || []; var event = evt && (evt.originalEvent || evt); var dataTransfer = event && event.dataTransfer; var items = dataTransfer && dataTransfer.items; var i; - if (files.length) { - return files; - } - if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { - return dataTransfer.files; + return Array.prototype.slice.call(dataTransfer.files); } if (!items || !items.length) { @@ -222,115 +216,208 @@ browser.clearUpload = function() { upload.unwrap(); }; browser.prepareFiles = function(files) { - FileAPI.filterFiles( - files, - function(file) { - var ext = file.name.split('.').pop().toLowerCase(); - var result = browser.allowedExts.test(ext) && !browser.deniedExts.test(ext); - if (!result) { - file.message = browser.label("Denied file extension."); - } - if (result) { - result = browser.maxFileSize > file.size; - if (!result) { - file.message = browser.label("The uploaded file exceeds {size} bytes.", {size: browser.maxFileSize}); - } - } - return result; - }, function (files, rejected) { - if (rejected.length > 0) { - var messages = []; - $.each(rejected, function(i, file) { - messages.push(file.name + ': ' +file.message); - }); - browser.alert(messages.join('
'), true, function(){browser.uploadFiles(files)}); - } else { - browser.uploadFiles(files); - } + var accepted = [], + rejected = [], + selected = Array.prototype.slice.call(files || []); + + $.each(selected, function(i, file) { + var ext = file.name.split('.').pop().toLowerCase(); + var message = ''; + + if (!browser.allowedExts.test(ext) || browser.deniedExts.test(ext)) { + message = browser.label("Denied file extension."); + } else if (browser.maxFileSize <= file.size) { + message = browser.label("The uploaded file exceeds {size} bytes.", {size: browser.maxFileSize}); + } + + if (message) { + rejected.push(file.name + ': ' + message); + } else { + accepted.push(file); } - ); + }); + + if (rejected.length) { + browser.alert(rejected.join('
'), true, function() { + browser.uploadFiles(accepted); + }); + } else { + browser.uploadFiles(accepted); + } }; -browser.uploadFiles = function(files) { - if (!this.dirWritable) { - browser.alert(this.label("Cannot write to upload folder.")); - return; +browser.resizeImageForUpload = function(file) { + var resize = browser.clientResize || {}, + maxWidth = Number(resize.maxWidth), + maxHeight = Number(resize.maxHeight), + quality = Number(resize.quality); + + if (maxWidth <= 0 || maxHeight <= 0 || (file.type !== 'image/jpeg' && file.type !== 'image/png')) { + return Promise.resolve(file); } - var uploadInProgress = false, - filesCount = 0, - errors = [], - uploaded = 0; - if( files.length ){ - filesCount = files.length; - var options = { - url: browser.baseGetData('upload'), - files: { file: files }, - data: { - dir: browser.dir - }, - imageAutoOrientation: false, - prepare: function (file/**Object*/, options/**Object*/){ - if (file.type !== 'image/jpeg' && file.type !== 'image/png') { - options.imageTransform = false; - } - }, - upload: function() { - $('#loading').html(browser.label("Uploading file {number} of {count}... {progress}", { - number: uploaded++, - count: filesCount, - progress: "" - })); - uploadInProgress = true; - $('#loading').show(); - browser.fadeFiles(); - }, - progress: function (evt){ - var progress = Math.round((evt.loaded * 100) / evt.total) + '%'; + + quality = isFinite(quality) ? Math.max(0, Math.min(1, quality)) : 1; + + function makeBlob(image) { + var width = image.width || image.naturalWidth, + height = image.height || image.naturalHeight, + scale = Math.min(1, maxWidth / width, maxHeight / height); + + if (!width || !height || scale >= 1) { + return Promise.resolve(file); + } + + var canvas = document.createElement('canvas'); + canvas.width = Math.max(1, Math.round(width * scale)); + canvas.height = Math.max(1, Math.round(height * scale)); + var context = canvas.getContext('2d'); + + if (!context || !canvas.toBlob) { + return Promise.resolve(file); + } + + try { + context.drawImage(image, 0, 0, canvas.width, canvas.height); + } catch (error) { + return Promise.resolve(file); + } + + return new Promise(function(resolve) { + canvas.toBlob(function(blob) { + resolve(blob || file); + }, file.type, quality); + }); + } + + if (window.createImageBitmap) { + return Promise.resolve().then(function() { + return window.createImageBitmap(file, {imageOrientation: 'from-image'}); + }).catch(function() { + return window.createImageBitmap(file); + }).then(function(bitmap) { + return makeBlob(bitmap).then(function(blob) { + if (bitmap.close) bitmap.close(); + return blob; + }).catch(function() { + if (bitmap.close) bitmap.close(); + return file; + }); + }).catch(function() { + return file; + }); + } + + if (!window.URL || !window.URL.createObjectURL) { + return Promise.resolve(file); + } + + return new Promise(function(resolve) { + var image = new Image(), + url = window.URL.createObjectURL(file); + + image.onload = function() { + window.URL.revokeObjectURL(url); + makeBlob(image).then(resolve); + }; + image.onerror = function() { + window.URL.revokeObjectURL(url); + resolve(file); + }; + image.src = url; + }); +}; + +browser.uploadFile = function(file, index, count) { + return browser.resizeImageForUpload(file).then(function(blob) { + return new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(), + data = new FormData(); + + data.append('file', blob, file.name); + data.append('dir', browser.dir); + xhr.open('POST', browser.baseGetData('upload'), true); + xhr.upload.addEventListener('progress', function(evt) { + var loaded = evt.lengthComputable ? evt.loaded : file.size, + total = evt.lengthComputable ? evt.total : file.size, + progress = total ? Math.round((loaded * 100) / total) + '%' : '0%'; + $('#loading').html(browser.label("Uploading file {number} of {count}... {progress}", { - number: uploaded, - count: filesCount, + number: index + 1, + count: count, progress: progress })); - }, - filecomplete:function(err, xhr, file) { - if(err === false) { - var response; - try { - response = $.parseJSON(xhr.response); - } catch (error) { - response = { - success:false, - message:browser.label("Unable to process server response") - } - } - if (!response.success) { - if (typeof response.message === 'object') { - response.message = response.message.join('; '); - }; - errors.push(file.name + ': ' + response.message); - } - } else { - errors.push(file.name + ': ' + browser.label("Server error") + ' ' + err); + }); + xhr.onload = function() { + var response; + + try { + response = $.parseJSON(xhr.responseText); + } catch (error) { + reject(browser.label("Unable to process server response")); + return; } - uploaded++; - }, - complete: function (err, xhr){ - uploadInProgress = false; - $('#loading').hide(); - browser.refresh(); - browser.clearUpload(); - if (errors.length > 0) { - browser.alert(errors.join('
'), false); + + if (xhr.status < 200 || xhr.status >= 300) { + reject(browser.label("Server error") + ' ' + xhr.status); + } else { + resolve(response); } - } - }; - if (Object.keys(browser.clientResize).length) { - options.imageTransform = { - maxWidth: browser.clientResize.maxWidth, - maxHeight: browser.clientResize.maxHeight, - quality: browser.clientResize.quality }; - options.imageAutoOrientation = true; + xhr.onerror = function() { + reject(browser.label("Server error")); + }; + xhr.send(data); + }); + }); +}; + +browser.uploadFiles = function(files) { + if (!this.dirWritable) { + browser.alert(this.label("Cannot write to upload folder.")); + return; + } + + files = Array.prototype.slice.call(files || []); + if (!files.length) return; + + var errors = [], + index = 0; + + $('#loading').show(); + browser.fadeFiles(); + + function uploadNext() { + if (index >= files.length) { + $('#loading').hide(); + browser.refresh(); + browser.clearUpload(); + if (errors.length) { + browser.alert(errors.join('
'), false); + } + return; } - FileAPI.upload(options); + + var file = files[index]; + $('#loading').html(browser.label("Uploading file {number} of {count}... {progress}", { + number: index + 1, + count: files.length, + progress: "" + })); + + Promise.resolve().then(function() { + return browser.uploadFile(file, index, files.length); + }).then(function(response) { + if (!response || !response.success) { + var message = response && response.message ? response.message : browser.label("Server error"); + if (typeof message === 'object') message = message.join('; '); + errors.push(file.name + ': ' + message); + } + }).catch(function(error) { + errors.push(file.name + ': ' + error); + }).then(function() { + index++; + uploadNext(); + }); } + + uploadNext(); }; diff --git a/manager/media/browser/mcpuk/tpl/tpl_javascript.php b/manager/media/browser/mcpuk/tpl/tpl_javascript.php index a532d3f192..28c4ee621b 100755 --- a/manager/media/browser/mcpuk/tpl/tpl_javascript.php +++ b/manager/media/browser/mcpuk/tpl/tpl_javascript.php @@ -3,8 +3,6 @@ - - opener['TinyMCE']) && $this->opener['TinyMCE']): ?>