����JFIFXX�����    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222����"��4�� ���,�PG"Z_�4�˷����kjز�Z�,F+��_z�,�© �����zh6�٨�ic�fu���#ډb���_�N�?��wQ���5-�~�I���8����TK<5o�Iv-�����k�_U_�����~b�M��d����Ӝ�U�Hh��?]��E�w��Q���k�{��_}qFW7HTՑ��Y��F�?_�'ϔ��_�Ջt��=||I ��6�έ"�����D���/[�k�9���Y�8ds|\���Ҿp6�Ҵ���]��.����6�z<�v��@]�i%��$j��~�g��J>��no����pM[me�i$[����s�o�ᘨ�˸ nɜG-�ĨU�ycP�3.DB�li�;��hj���x7Z^�N�h������N3u{�:j�x�힞��#M&��jL P@_���� P��&��o8������9�����@Sz6�t7#O�ߋ �s}Yf�T���lmr����Z)'N��k�۞p����w\�Tȯ?�8`�O��i{wﭹW�[�r�� ��Q4F�׊���3m&L�=��h3����z~��#�\�l :�F,j@�� ʱ�wQT����8�"kJO���6�֚l����}���R�>ډK���]��y����&����p�}b��;N�1�m�r$�|��7�>e�@B�TM*-iH��g�D�)� E�m�|�ؘbҗ�a��Ҿ����t4���o���G��*oCN�rP���Q��@z,|?W[0�����:�n,jWiE��W��$~/�hp\��?��{(�0���+�Y8rΟ�+����>S-S����VN;�}�s?.����� w�9��˟<���Mq4�Wv'��{)0�1mB��V����W[�����8�/<� �%���wT^�5���b��)iM� pg�N�&ݝ��VO~�q���u���9� ����!��J27����$O-���! �:�%H��� ـ����y�ΠM=t{!S�� oK8������t<����è:a������[�����ա�H���~��w��Qz`�po�^ ����Q��n� �,uu�C�$ ^���,������8�#��:�6��e�|~���!�3�3.�\0��q��o�4`.|� ����y�Q�`~;�d�ׯ,��O�Zw�������`73�v�܋�<���Ȏ�� ـ4k��5�K�a�u�=9Yd��$>x�A�&�� j0� ���vF��� Y�|�y��� ~�6�@c��1vOp�Ig����4��l�OD���L����� R���c���j�_�uX6��3?nk��Wy�f;^*B� ��@�~a�`��Eu������+���6�L��.ü>��}y���}_�O�6�͐�:�YrG�X��kG�����l^w���~㒶sy��Iu�!� W ��X��N�7BV��O��!X�2����wvG�R�f�T#�����t�/?���%8�^�W�aT��G�cL�M���I��(J����1~�8�?aT ���]����AS�E��(��*E}� 2��#I/�׍qz��^t�̔���b�Yz4x���t�){ OH��+(E��A&�N�������XT��o��"�XC��'���)}�J�z�p� ��~5�}�^����+�6����w��c��Q�|Lp�d�H��}�(�.|����k��c4^�"�����Z?ȕ ��a<�L�!039C� �Eu�C�F�Ew�ç ;�n?�*o���B�8�bʝ���'#Rqf���M}7����]����s2tcS{�\icTx;�\��7K���P���ʇ Z O-��~��c>"��?�������P��E��O�8��@�8��G��Q�g�a�Վ���󁶠�䧘��_%#r�>�1�z�a��eb��qcPѵ��n���#L��� =��׀t� L�7�`��V���A{�C:�g���e@�w1 Xp3�c3�ġ����p��M"'-�@n4���fG��B3�DJ�8[Jo�ߐ���gK)ƛ��$���� ���8�3�����+���� �����6�ʻ���� ���S�kI�*KZlT _`���?��K����QK�d����B`�s}�>���`��*�>��,*@J�d�oF*����弝��O}�k��s��]��y�ߘ��c1G�V���<=�7��7����6�q�PT��tXԀ�!9*4�4Tހ3XΛex�46���Y��D ����� �BdemDa����\�_l,��G�/���֌7���Y�](�xTt^%�GE�����4�}bT���ڹ�����;Y)���B�Q��u��>J/J �⮶.�XԄ��j�ݳ�+E��d ��r�5�_D�1 ��o�� �B�x�΢�#���<��W�����8���R6�@g�M�.��� dr�D��>(otU��@x=��~v���2� ӣ�d�oBd��3�eO�6�㣷�����ݜ6��6Y��Qz`��S��{���\P�~z m5{J/L��1������<�e�ͅPu�b�]�ϔ���'������f�b� Zpw��c`"��i���BD@:)ִ�:�]��hv�E�w���T�l��P���"Ju�}��وV J��G6��. J/�Qgl߭�e�����@�z�Zev2u�)]կ�����7x���s�M�-<ɯ�c��r�v�����@��$�ޮ}lk���a���'����>x��O\�ZFu>�����ck#��&:��`�$�ai�>2Δ����l���oF[h��lE�ܺ�Πk:)���`�� $[6�����9�����kOw�\|���8}������ބ:��񶐕��I�A1/�=�2[�,�!��.}gN#�u����b��� ~��݊��}34q����d�E��Lc��$��"�[q�U�硬g^��%B �z���r�pJ�ru%v\h1Y�ne`ǥ:g���pQM~�^�Xi� ��`S�:V29.�P���V�?B�k�� AEvw%�_�9C�Q����wKekPؠ�\�;Io d�{ ߞo�c1eP����\� `����E=���@K<�Y���eڼ�J���w����{av�F�'�M�@/J��+9p���|]�����Iw &`��8���&M�hg��[�{��Xj��%��Ӓ�$��(����ʹN���<>�I���RY���K2�NPlL�ɀ)��&e����B+ь����( � �JTx���_?EZ� }@ 6�U���뙢ط�z��dWI�n` D����噥�[��uV��"�G&Ú����2g�}&m��?ċ�"����Om#��������� ��{�ON��"S�X��Ne��ysQ���@Fn��Vg���dX�~nj�]J�<�K]:��FW��b�������62�=��5f����JKw��bf�X�55��~J �%^����:�-�QIE��P��v�nZum� z � ~ə ���� ���ة����;�f��\v���g�8�1��f24;�V���ǔ�)����9���1\��c��v�/'Ƞ�w�������$�4�R-��t���� e�6�/�ġ �̕Ecy�J���u�B���<�W�ַ~�w[B1L۲�-JS΂�{���΃������A��20�c#��@ 0!1@AP"#2Q`$3V�%45a6�FRUq��� ����^7ׅ,$n�������+��F�`��2X'��0vM��p�L=������5��8������u�p~���.�`r�����\���O��,ư�0oS ��_�M�����l���4�kv\JSd���x���SW�<��Ae�IX����������$I���w�:S���y���›R��9�Q[���,�5�;�@]�%���u�@ *ro�lbI �� ��+���%m:�͇ZV�����u�̉����θau<�fc�.����{�4Ա� �Q����*�Sm��8\ujqs]{kN���)qO�y�_*dJ�b�7���yQqI&9�ԌK!�M}�R�;������S�T���1���i[U�ɵz�]��U)V�S6���3$K{�ߊ<�(� E]Զ[ǼENg�����'�\?#)Dkf��J���o��v���'�%ƞ�&K�u�!��b�35LX�Ϸ��63$K�a�;�9>,R��W��3�3� d�JeTYE.Mϧ��-�o�j3+y��y^�c�������VO�9NV\nd�1 ��!͕_)a�v;����թ�M�lWR1��)El��P;��yوÏ�u 3�k�5Pr6<�⒲l�!˞*��u־�n�!�l:����UNW ��%��Chx8vL'��X�@��*��)���̮��ˍ��� ���D-M�+J�U�kvK����+�x8��cY������?�Ԡ��~3mo��|�u@[XeY�C�\Kp�x8�oC�C�&����N�~3-H���� ��MX�s�u<`���~"WL��$8ξ��3���a�)|:@�m�\���^�`�@ҷ)�5p+��6���p�%i)P M���ngc�����#0Aruz���RL+xSS?���ʮ}()#�t��mˇ!��0}}y����<�e� �-ή�Ԩ��X������ MF���ԙ~l L.3���}�V뽺�v�����멬��Nl�)�2����^�Iq��a��M��qG��T�����c3#������3U�Ǎ���}��לS�|qa��ڃ�+���-��2�f����/��bz��ڐ�� �ݼ[2�ç����k�X�2�* �Z�d���J�G����M*9W���s{��w���T��x��y,�in�O�v��]���n����P�$�JB@=4�OTI�n��e�22a\����q�d���%�$��(���:���: /*�K[PR�fr\nڙdN���F�n�$�4�[�� U�zƶ����� �mʋ���,�ao�u 3�z� �x��Kn����\[��VFmbE;�_U��&V�Gg�]L�۪&#n%�$ɯ�dG���D�TI=�%+AB�Ru#��b4�1�»x�cs�YzڙJG��f��Il��d�eF'T� iA��T���uC�$����Y��H?����[!G`}���ͪ� �纤Hv\������j�Ex�K���!���OiƸ�Yj�+u-<���'q����uN�*�r\��+�]���<�wOZ.fp�ێ��,-*)V?j-kÊ#�`�r��dV����(�ݽBk�����G�ƛk�QmUڗe��Z���f}|����8�8��a���i��3'J�����~G_�^���d�8w������ R�`(�~�.��u���l�s+g�bv���W���lGc}��u���afE~1�Ue������Z�0�8�=e�� f@/�jqEKQQ�J��oN��J���W5~M>$6�Lt�;$ʳ{���^��6�{����v6���ķܰg�V�cnn �~z�x�«�,2�u�?cE+Ș�H؎�%�Za�)���X>uW�Tz�Nyo����s���FQƤ��$��*�&�LLXL)�1�" L��eO��ɟ�9=���:t��Z���c��Ž���Y?�ӭV�wv�~,Y��r�ۗ�|�y��GaF�����C�����.�+� ���v1���fήJ�����]�S��T��B��n5sW}y�$��~z�'�c ��8 ��� ,! �p��VN�S��N�N�q��y8z˱�A��4��*��'������2n<�s���^ǧ˭P�Jޮɏ�U�G�L�J�*#��<�V��t7�8����TĜ>��i}K%,���)[��z�21z ?�N�i�n1?T�I�R#��m-�����������������1����lA�`��fT5+��ܐ�c�q՝��ʐ��,���3�f2U�եmab��#ŠdQ�y>\��)�SLY����w#��.���ʑ�f��� ,"+�w�~�N�'�c�O�3F�������N<���)j��&��,-� �љ���֊�_�zS���TǦ����w�>��?�������n��U仆�V���e�����0���$�C�d���rP �m�׈e�Xm�Vu� �L��.�bֹ��� �[Դaզ���*��\y�8�Է:�Ez\�0�Kq�C b��̘��cө���Q��=0Y��s�N��S.���3.���O�o:���#���v7�[#߫ ��5�܎�L���Er4���9n��COWlG�^��0k�%<���ZB���aB_���������'=��{i�v�l�$�uC���mƎҝ{�c㱼�y]���W�i ��ߧc��m�H� m�"�"�����;Y�ߝ�Z�Ǔ�����:S#��|}�y�,/k�Ld� TA�(�AI$+I3��;Y*���Z��}|��ӧO��d�v��..#:n��f>�>���ȶI�TX��� 8��y����"d�R�|�)0���=���n4��6ⲑ�+��r<�O�܂~zh�z����7ܓ�HH�Ga롏���nCo�>������a ���~]���R���̲c?�6(�q�;5%� |�uj�~z8R=X��I�V=�|{v�Gj\gc��q����z�؋%M�ߍ����1y��#��@f^���^�>N�����#x#۹��6�Y~�?�dfPO��{��P�4��V��u1E1J �*|���%���JN��`eWu�zk M6���q t[�� ��g�G���v��WIG��u_ft����5�j�"�Y�:T��ɐ���*�;� e5���4����q$C��2d�}���� _S�L#m�Yp��O�.�C�;��c����Hi#֩%+) �Ӎ��ƲV���SYź��g |���tj��3�8���r|���V��1#;.SQ�A[���S������#���`n�+���$��$I �P\[�@�s��(�ED�z���P��])8�G#��0B��[ى��X�II�q<��9�~[Z멜�Z�⊔IWU&A>�P~�#��dp<�?����7���c��'~���5 ��+$���lx@�M�dm��n<=e�dyX��?{�|Aef ,|n3�<~z�ƃ�uۧ�����P��Y,�ӥQ�*g�#먙R�\���;T��i,��[9Qi歉����c>]9�� ��"�c��P�� �Md?٥��If�ت�u��k��/����F��9�c*9��Ǎ:�ØF���z�n*�@|I�ށ9����N3{'��[�'ͬ�Ҳ4��#}��!�V� Fu��,�,mTIk���v C�7v���B�6k�T9��1�*l� '~��ƞF��lU��'�M ����][ΩũJ_�{�i�I�n��$���L�� j��O�dx�����kza۪��#�E��Cl����x˘�o�����V���ɞ�ljr��)�/,�߬h�L��#��^��L�ф�,íMƁe�̩�NB�L�����iL����q�}��(��q��6IçJ$�W�E$��:������=#����(�K�B����zђ <��K(�N�۫K�w��^O{!����)�H���>x�������lx�?>Պ�+�>�W���,Ly!_�D���Ō�l���Q�!�[ �S����J��1��Ɛ�Y}��b,+�Lo�x�ɓ)����=�y�oh�@�꥟/��I��ѭ=��P�y9��� �ۍYӘ�e+�p�Jnϱ?V\SO%�(�t� ���=?MR�[Ș�����d�/ ��n�l��B�7j� ��!�;ӥ�/�[-���A�>�dN�sLj ��,ɪv��=1c�.SQ�O3�U���ƀ�ܽ�E����������̻��9G�ϷD�7(�}��Ävӌ\�y�_0[w ���<΍>����a_��[0+�L��F.�޺��f�>oN�T����q;���y\��bՃ��y�jH�<|q-eɏ�_?_9+P���Hp$�����[ux�K w�Mw��N�ی'$Y2�=��q���KB��P��~������Yul:�[<����F1�2�O���5=d����]Y�sw:���Ϯ���E��j,_Q��X��z`H1,#II ��d�wr��P˂@�ZJV����y$�\y�{}��^~���[:N����ߌ�U�������O��d�����ؾe��${p>G��3c���Ė�lʌ�� ת��[��`ϱ�-W����dg�I��ig2��� ��}s ��ؤ(%#sS@���~���3�X�nRG�~\jc3�v��ӍL��M[JB�T��s3}��j�Nʖ��W����;7��ç?=X�F=-�=����q�ߚ���#���='�c��7���ڑW�I(O+=:uxq�������������e2�zi+�kuG�R��������0�&e�n���iT^J����~\jy���p'dtG��s����O��3����9* �b#Ɋ�� p������[Bws�T�>d4�ۧs���nv�n���U���_�~,�v����ƜJ1��s�� �QIz��)�(lv8M���U=�;����56��G���s#�K���MP�=��LvyGd��}�VwWBF�'�à �?MH�U�g2�� ����!�p�7Q��j��ڴ����=��j�u��� Jn�A s���uM������e��Ɔ�Ҕ�!)'��8Ϣ�ٔ��ޝ(��Vp���צ֖d=�IC�J�Ǡ{q������kԭ�߸���i��@K����u�|�p=..�*+����x�����z[Aqġ#s2a�Ɗ���RR�)*HRsi�~�a &f��M��P����-K�L@��Z��Xy�'x�{}��Zm+���:�)�) IJ�-i�u���� ���ܒH��'�L(7�y�GӜq���� j��� 6ߌg1�g�o���,kر���tY�?W,���p���e���f�OQS��!K�۟cҒA�|ս�j�>��=⬒��˧L[�� �߿2JaB~R��u�:��Q�] �0H~���]�7��Ƽ�I���(}��cq '�ήET���q�?f�ab���ӥvr� �)o��-Q��_'����ᴎo��K������;��V���o��%���~OK ����*��b�f:���-ťIR��`B�5!RB@���ï�� �u �̯e\�_U�_������� g�ES��3�������QT��a����x����U<~�c?�*�#]�MW,[8O�a�x��]�1bC|踤�P��lw5V%�)�{t�<��d��5���0i�XSU��m:��Z�┵�i�"��1�^B�-��P�hJ��&)O��*�D��c�W��vM��)����}���P��ܗ-q����\mmζZ-l@�}��a��E�6��F�@��&Sg@���ݚ�M����� ȹ 4����#p�\H����dYDo�H���"��\��..R�B�H�z_�/5˘����6��KhJR��P�mƶi�m���3�,#c�co��q�a)*Pt����R�m�k�7x�D�E�\Y�閣_X�<���~�)���c[[�BP����6�Yq���S��0����%_����;��Àv�~�| VS؇ ��'O0��F0��\���U�-�d@�����7�SJ*z��3n��y��P����O���������m�~�P�3|Y��ʉr#�C�<�G~�.,! ���bqx���h~0=��!ǫ�jy����l�O,�[B��~��|9��ٱ����Xly�#�i�B��g%�S��������tˋ���e���ې��\[d�t)��.+u�|1 ������#�~Oj����hS�%��i.�~X���I�H�m��0n���c�1uE�q��cF�RF�o���7� �O�ꮧ� ���ۛ{��ʛi5�rw?׌#Qn�TW��~?y$��m\�\o����%W� ?=>S�N@�� �Ʈ���R����N�)�r"C�:��:����� �����#��qb��Y�. �6[��2K����2u�Ǧ�HYR��Q�MV��� �G�$��Q+.>�����nNH��q�^��� ����q��mM��V��D�+�-�#*�U�̒ ���p욳��u:�������IB���m���PV@O���r[b= �� ��1U�E��_Nm�yKbN�O���U�}�the�`�|6֮P>�\2�P�V���I�D�i�P�O;�9�r�mAHG�W�S]��J*�_�G��+kP�2����Ka�Z���H�'K�x�W�MZ%�O�YD�Rc+o��?�q��Ghm��d�S�oh�\�D�|:W������UA�Qc yT�q������~^�H��/��#p�CZ���T�I�1�ӏT����4��"�ČZ�����}��`w�#�*,ʹ�� ��0�i��課�Om�*�da��^gJ݅{���l�e9uF#T�ֲ��̲�ٞC"�q���ߍ ոޑ�o#�XZTp����@ o�8��(jd��xw�]�,f���`~�|,s��^����f�1���t��|��m�򸄭/ctr��5s��7�9Q�4�H1꠲BB@l9@���C�����+�wp�xu�£Yc�9��?`@#�o�mH�s2��)�=��2�.�l����jg�9$�Y�S�%*L������R�Y������7Z���,*=�䷘$�������arm�o�ϰ���UW.|�r�uf����IGw�t����Zwo��~5 ��YյhO+=8fF�)�W�7�L9lM�̘·Y���֘YLf�큹�pRF���99.A �"wz��=E\Z���'a� 2��Ǚ�#;�'}�G���*��l��^"q��+2FQ� hj��kŦ��${���ޮ-�T�٭cf�|�3#~�RJ����t��$b�(R��(����r���dx� >U b�&9,>���%E\� Ά�e�$��'�q't��*�א���ެ�b��-|d���SB�O�O��$�R+�H�)�܎�K��1m`;�J�2�Y~9��O�g8=vqD`K[�F)k�[���1m޼c��n���]s�k�z$@��)!I �x՝"v��9=�ZA=`Ɠi �:�E��)`7��vI��}d�YI�_ �o�:ob���o ���3Q��&D&�2=�� �Ά��;>�h����y.*ⅥS������Ӭ�+q&����j|UƧ����}���J0��WW< ۋS�)jQR�j���Ư��rN)�Gű�4Ѷ(�S)Ǣ�8��i��W52���No˓� ۍ%�5brOn�L�;�n��\G����=�^U�dI���8$�&���h��'���+�(������cȁ߫k�l��S^���cƗjԌE�ꭔ��gF���Ȓ��@���}O���*;e�v�WV���YJ\�]X'5��ղ�k�F��b 6R�o՜m��i N�i����>J����?��lPm�U��}>_Z&�KK��q�r��I�D�Չ~�q�3fL�:S�e>���E���-G���{L�6p�e,8��������QI��h��a�Xa��U�A'���ʂ���s�+טIjP�-��y�8ۈZ?J$��W�P� ��R�s�]��|�l(�ԓ��sƊi��o(��S0��Y� 8�T97.�����WiL��c�~�dxc�E|�2!�X�K�Ƙਫ਼�$((�6�~|d9u+�qd�^3�89��Y�6L�.I�����?���iI�q���9�)O/뚅����O���X��X�V��ZF[�یgQ�L��K1���RҖr@v�#��X�l��F���Нy�S�8�7�kF!A��sM���^rkp�jP�DyS$N���q��nxҍ!U�f�!eh�i�2�m���`�Y�I�9r�6� �TF���C}/�y�^���Η���5d�'��9A-��J��>{�_l+�`��A���[�'��յ�ϛ#w:݅�%��X�}�&�PSt�Q�"�-��\縵�/����$Ɨh�Xb�*�y��BS����;W�ջ_mc�����vt?2}1�;qS�d�d~u:2k5�2�R�~�z+|HE!)�Ǟl��7`��0�<�,�2*���Hl-��x�^����'_TV�gZA�'j� ^�2Ϊ��N7t�����?w�� �x1��f��Iz�C-Ȗ��K�^q�;���-W�DvT�7��8�Z�������� hK�(P:��Q- �8�n�Z���܃e貾�<�1�YT<�,�����"�6{/ �?�͟��|1�:�#g��W�>$����d��J��d�B��=��jf[��%rE^��il:��B���x���Sּ�1հ��,�=��*�7 fcG��#q� �eh?��2�7�����,�!7x��6�n�LC�4x��},Geǝ�tC.��vS �F�43��zz\��;QYC,6����~;RYS/6���|2���5���v��T��i����������mlv��������&� �nRh^ejR�LG�f���? �ۉҬܦƩ��|��Ȱ����>3����!v��i�ʯ�>�v��オ�X3e���_1z�Kȗ\<������!�8���V��]��?b�k41�Re��T�q��mz��TiOʦ�Z��Xq���L������q"+���2ۨ��8}�&N7XU7Ap�d�X��~�׿��&4e�o�F��� �H����O���č�c�� 懴�6���͉��+)��v;j��ݷ�� �UV�� i��� j���Y9GdÒJ1��詞�����V?h��l����l�cGs�ځ�������y�Ac�����\V3�? �� ܙg�>qH�S,�E�W�[�㺨�uch�⍸�O�}���a��>�q�6�n6����N6�q������N ! 1AQaq�0@����"2BRb�#Pr���3C`��Scst���$4D���%Td�� ?���N����a��3��m���C���w��������xA�m�q�m���m������$����4n淿t'��C"w��zU=D�\R+w�p+Y�T�&�պ@��ƃ��3ޯ?�Aﶂ��aŘ���@-�����Q�=���9D��ռ�ѻ@��M�V��P��܅�G5�f�Y<�u=,EC)�<�Fy'�"�&�չ�X~f��l�KԆV��?�� �W�N����=(� �;���{�r����ٌ�Y���h{�١������jW����P���Tc�����X�K�r��}���w�R��%��?���E��m�� �Y�q|����\lEE4���r���}�lsI�Y������f�$�=�d�yO����p�����yBj8jU�o�/�S��?�U��*������ˍ�0������u�q�m [�?f����a�� )Q�>����6#������� ?����0UQ����,IX���(6ڵ[�DI�MNލ�c&���υ�j\��X�R|,4��� j������T�hA�e��^���d���b<����n�� �즇�=!���3�^�`j�h�ȓr��jẕ�c�,ٞX����-����a�ﶔ���#�$��]w�O��Ӫ�1y%��L�Y<�wg#�ǝ�̗`�x�xa�t�w��»1���o7o5��>�m뭛C���Uƃߜ}�C���y1Xνm�F8�jI���]����H���ۺиE@I�i;r�8ӭ����V�F�Շ| ��&?�3|x�B�MuS�Ge�=Ӕ�#BE5G�����Y!z��_e��q�р/W>|-�Ci߇�t�1ޯќd�R3�u��g�=0 5��[?�#͏��q�cf���H��{ ?u�=?�?ǯ���}Z��z���hmΔ�BFTW�����<�q�(v� ��!��z���iW]*�J�V�z��gX֧A�q�&��/w���u�gYӘa���; �i=����g:��?2�dž6�ى�k�4�>�Pxs����}������G�9��3 ���)gG�R<>r h�$��'nc�h�P��Bj��J�ҧH� -��N1���N��?��~��}-q!=��_2hc�M��l�vY%UE�@|�v����M2�.Y[|y�"Eï��K�ZF,�ɯ?,q�?v�M 80jx�"�;�9vk�����+ ֧�� �ȺU��?�%�vcV��mA�6��Qg^M����A}�3�nl� QRN�l8�kkn�'�����(��M�7m9و�q���%ޟ���*h$Zk"��$�9��: �?U8�Sl��,,|ɒ��xH(ѷ����Gn�/Q�4�P��G�%��Ա8�N��!� �&�7�;���eKM7�4��9R/%����l�c>�x;������>��C�:�����t��h?aKX�bhe�ᜋ^�$�Iհ �hr7%F$�E��Fd���t��5���+�(M6�t����Ü�UU|zW�=a�Ts�Tg������dqP�Q����b'�m���1{|Y����X�N��b �P~��F^F:����k6�"�j!�� �I�r�`��1&�-$�Bevk:y���#yw��I0��x��=D�4��tU���P�ZH��ڠ底taP��6����b>�xa����Q�#� WeF��ŮNj�p�J* mQ�N����*I�-*�ȩ�F�g�3 �5��V�ʊ�ɮ�a��5F���O@{���NX��?����H�]3��1�Ri_u��������ѕ�� ����0��� F��~��:60�p�͈�S��qX#a�5>���`�o&+�<2�D����: �������ڝ�$�nP���*)�N�|y�Ej�F�5ټ�e���ihy�Z �>���k�bH�a�v��h�-#���!�Po=@k̆IEN��@��}Ll?j�O������߭�ʞ���Q|A07x���wt!xf���I2?Z��<ץ�T���cU�j��]��陎Ltl �}5�ϓ��$�,��O�mˊ�;�@O��jE��j(�ا,��LX���LO���Ц�90�O �.����a��nA���7������j4 ��W��_ٓ���zW�jcB������y՗+EM�)d���N�g6�y1_x��p�$Lv:��9�"z��p���ʙ$��^��JԼ*�ϭ����o���=x�Lj�6�J��u82�A�H�3$�ٕ@�=Vv�]�'�qEz�;I˼��)��=��ɯ���x �/�W(V���p�����$ �m�������u�����񶤑Oqˎ�T����r��㠚x�sr�GC��byp�G��1ߠ�w e�8�$⿄����/�M{*}��W�]˷.�CK\�ުx���/$�WPw���r� |i���&�}�{�X� �>��$-��l���?-z���g����lΆ���(F���h�vS*���b���߲ڡn,|)mrH[���a�3�ר�[1��3o_�U�3�TC�$��(�=�)0�kgP���� ��u�^=��4 �WYCҸ:��vQ�ר�X�à��tk�m,�t*��^�,�}D*� �"(�I��9R����>`�`��[~Q]�#af��i6l��8���6�:,s�s�N6�j"�A4���IuQ��6E,�GnH��zS�HO�uk�5$�I�4��ؤ�Q9�@��C����wp�BGv[]�u�Ov���0I4���\��y�����Q�Ѹ��~>Z��8�T��a��q�ޣ;z��a���/��S��I:�ܫ_�|������>=Z����8:�S��U�I�J��"IY���8%b8���H��:�QO�6�;7�I�S��J��ҌAά3��>c���E+&jf$eC+�z�;��V����� �r���ʺ������my�e���aQ�f&��6�ND��.:��NT�vm�<- u���ǝ\MvZY�N�NT��-A�>jr!S��n�O 1�3�Ns�%�3D@���`������ܟ 1�^c<���� �a�ɽ�̲�Xë#�w�|y�cW�=�9I*H8�p�^(4���՗�k��arOcW�tO�\�ƍR��8����'�K���I�Q�����?5�>[�}��yU�ײ -h��=��% q�ThG�2�)���"ו3]�!kB��*p�FDl�A���,�eEi�H�f�Ps�����5�H:�Փ~�H�0Dت�D�I����h�F3�������c��2���E��9�H��5�zԑ�ʚ�i�X�=:m�xg�hd(�v����׊�9iS��O��d@0ڽ���:�p�5�h-��t�&���X�q�ӕ,��ie�|���7A�2���O%P��E��htj��Y1��w�Ѓ!����  ���� ࢽ��My�7�\�a�@�ţ�J �4�Ȼ�F�@o�̒?4�wx��)��]�P��~�����u�����5�����7X ��9��^ܩ�U;Iꭆ 5 �������eK2�7(�{|��Y׎ �V��\"���Z�1� Z�����}��(�Ǝ"�1S���_�vE30>���p;� ΝD��%x�W�?W?v����o�^V�i�d��r[��/&>�~`�9Wh��y�;���R��� ;;ɮT��?����r$�g1�K����A��C��c��K��l:�'��3 c�ﳯ*"t8�~l��)���m��+U,z��`(�>yJ�?����h>��]��v��ЍG*�{`��;y]��I�T� ;c��NU�fo¾h���/$���|NS���1�S�"�H��V���T���4��uhǜ�]�v;���5�͠x��'C\�SBpl���h}�N����� A�Bx���%��ޭ�l��/����T��w�ʽ]D�=����K���ž�r㻠l4�S�O?=�k �M:� ��c�C�a�#ha���)�ѐxc�s���gP�iG��{+���x���Q���I= �� z��ԫ+ �8"�k�ñ�j=|����c ��y��CF��/��*9ж�h{ �?4�o� ��k�m�Q�N�x��;�Y��4膚�a�w?�6�>e]�����Q�r�:����g�,i"�����ԩA�*M�<�G��b�if��l^M��5� �Ҩ�{����6J��ZJ�����P�*�����Y���ݛu�_4�9�I8�7���������,^ToR���m4�H��?�N�S�ѕw��/S��甍�@�9H�S�T��t�ƻ���ʒU��*{Xs�@����f�����֒Li�K{H�w^���������Ϥm�tq���s� ���ք��f:��o~s��g�r��ט� �S�ѱC�e]�x���a��) ���(b-$(�j>�7q�B?ӕ�F��hV25r[7 Y� }L�R��}����*sg+��x�r�2�U=�*'WS��ZDW]�WǞ�<��叓���{�$�9Ou4��y�90-�1�'*D`�c�^o?(�9��u���ݐ��'PI&� f�Jݮ�������:wS����jfP1F:X �H�9dԯ���˝[�_54 �}*;@�ܨ�� ð�yn�T���?�ןd�#���4rG�ͨ��H�1�|-#���Mr�S3��G�3�����)�.᧏3v�z֑��r����$G"�`j �1t��x0<Ɔ�Wh6�y�6��,œ�Ga��gA����y��b��)��h�D��ß�_�m��ü �gG;��e�v��ݝ�nQ� ��C����-�*��o���y�a��M��I�>�<���]obD��"�:���G�A��-\%LT�8���c�)��+y76���o�Q�#*{�(F�⽕�y����=���rW�\p���۩�c���A���^e6��K������ʐ�cVf5$�'->���ՉN"���F�"�UQ@�f��Gb~��#�&�M=��8�ט�JNu9��D��[̤�s�o�~������ G��9T�tW^g5y$b��Y'��س�Ǵ�=��U-2 #�MC�t(�i� �lj�@Q 5�̣i�*�O����s�x�K�f��}\��M{E�V�{�υ��Ƈ�����);�H����I��fe�Lȣr�2��>��W�I�Ȃ6������i��k�� �5�YOxȺ����>��Y�f5'��|��H+��98pj�n�.O�y�������jY��~��i�w'������l�;�s�2��Y��:'lg�ꥴ)o#'Sa�a�K��Z� �m��}�`169�n���"���x��I ��*+� }F<��cГ���F�P�������ֹ*�PqX�x۩��,� ��N�� �4<-����%����:��7����W���u�`����� $�?�I��&����o��o��`v�>��P��"��l���4��5'�Z�gE���8���?��[�X�7(��.Q�-��*���ތL@̲����v��.5���[��=�t\+�CNܛ��,g�SQnH����}*F�G16���&:�t��4ُ"A��̣��$�b �|����#rs��a�����T�� ]�<�j��BS�('$�ɻ� �wP;�/�n��?�ݜ��x�F��yUn�~mL*-�������Xf�wd^�a�}��f�,=t�׵i�.2/wpN�Ep8�OР���•��R�FJ� 55TZ��T �ɭ�<��]��/�0�r�@�f��V��V����Nz�G��^���7hZi����k��3�,kN�e|�vg�1{9]_i��X5y7� 8e]�U����'�-2,���e"����]ot�I��Y_��n�(JҼ��1�O ]bXc���Nu�No��pS���Q_���_�?i�~�x h5d'�(qw52] ��'ޤ�q��o1�R!���`ywy�A4u���h<קy���\[~�4�\ X�Wt/� 6�����n�F�a8��f���z �3$�t(���q��q�x��^�XWeN'p<-v�!�{�(>ӽDP7��ո0�y)�e$ٕv�Ih'Q�EA�m*�H��RI��=:��� ���4牢) �%_iN�ݧ�l]� �Nt���G��H�L��� ɱ�g<���1V�,�J~�ٹ�"K��Q�� 9�HS�9�?@��k����r�;we݁�]I�!{ �@�G�[�"��`���J:�n]�{�cA�E����V��ʆ���#��U9�6����j�#Y�m\��q�e4h�B�7��C�������d<�?J����1g:ٳ���=Y���D�p�ц� ׈ǔ��1�]26؜oS�'��9�V�FVu�P�h�9�xc�oq�X��p�o�5��Ա5$�9W�V(�[Ak�aY錎qf;�'�[�|���b�6�Ck��)��#a#a˙��8���=äh�4��2��C��4tm^ �n'c���]GQ$[Wҿ��i���vN�{Fu ��1�gx��1┷���N�m��{j-,��x�� Ūm�ЧS�[�s���Gna���䑴�� x�p 8<������97�Q���ϴ�v�aϚG��Rt�Һ׈�f^\r��WH�JU�7Z���y)�vg=����n��4�_)y��D'y�6�]�c�5̪�\� �PF�k����&�c;��cq�$~T�7j ���nç]�<�g ":�to�t}�159�<�/�8������m�b�K#g'I'.W�����6��I/��>v��\�MN��g���m�A�yQL�4u�Lj�j9��#44�t��l^�}L����n��R��!��t��±]��r��h6ٍ>�yҏ�N��fU�� ���� Fm@�8}�/u��jb9������he:A�y�ծw��GpΧh�5����l}�3p468��)U��d��c����;Us/�֔�YX�1�O2��uq�s��`hwg�r~�{ R��mhN��؎*q 42�*th��>�#���E����#��Hv�O����q�}�����6�e��\�,Wk�#���X��b>��p}�դ��3���T5��†��6��[��@�P�y*n��|'f�֧>�lư΂�̺����SU�'*�q�p�_S�����M�� '��c�6�����m�� ySʨ;M��r���Ƌ�m�Kxo,���Gm�P��A�G�:��i��w�9�}M(�^�V��$ǒ�ѽ�9���|���� �a����J�SQ�a���r�B;����}���ٻ֢�2�%U���c�#�g���N�a�ݕ�'�v�[�OY'��3L�3�;,p�]@�S��{ls��X�'���c�jw�k'a�.��}�}&�� �dP�*�bK=ɍ!����;3n�gΊU�ߴmt�'*{,=SzfD� A��ko~�G�aoq�_mi}#�m�������P�Xhύ����mxǍ�΂���巿zf��Q���c���|kc�����?���W��Y�$���_Lv����l߶��c���`?����l�j�ݲˏ!V��6����U�Ђ(A���4y)H���p�Z_�x��>���e��R��$�/�`^'3qˏ�-&Q�=?��CFVR �D�fV�9��{�8g�������n�h�(P"��6�[�D���< E�����~0<@�`�G�6����Hг�cc�� �c�K.5��D��d�B���`?�XQ��2��ٿyqo&+�1^� DW�0�ꊩ���G�#��Q�nL3��c���������/��x ��1�1[y�x�პCW��C�c�UĨ80�m�e�4.{�m��u���I=��f�����0QRls9���f���������9���~f�����Ǩ��a�"@�8���ȁ�Q����#c�ic������G��$���G���r/$W�(��W���V�"��m�7�[m�A�m����bo��D� j����۳� l���^�k�h׽����� ��#� iXn�v��eT�k�a�^Y�4�BN��ĕ��0 !01@Q"2AaPq3BR������?���@4�Q�����T3,���㺠�W�[=JK�Ϟ���2�r^7��vc�:�9 �E�ߴ�w�S#d���Ix��u��:��Hp��9E!�� V 2;73|F��9Y���*ʬ�F��D����u&���y؟��^EA��A��(ɩ���^��GV:ݜDy�`��Jr29ܾ�㝉��[���E;Fzx��YG��U�e�Y�C���� ����v-tx����I�sם�Ę�q��Eb�+P\ :>�i�C'�;�����k|z�رn�y]�#ǿb��Q��������w�����(�r|ӹs��[�D��2v-%��@;�8<a���[\o[ϧw��I!��*0�krs)�[�J9^��ʜ��p1)� "��/_>��o��<1����A�E�y^�C��`�x1'ܣn�p��s`l���fQ��):�l����b>�Me�jH^?�kl3(�z:���1ŠK&?Q�~�{�ٺ�h�y���/�[��V�|6��}�KbX����mn[-��7�5q�94�������dm���c^���h� X��5��<�eޘ>G���-�}�دB�ޟ� ��|�rt�M��V+�]�c?�-#ڛ��^ǂ}���Lkr���O��u�>�-D�ry� D?:ޞ�U��ǜ�7�V��?瓮�"�#���r��չģVR;�n���/_� ؉v�ݶe5d�b9��/O��009�G���5n�W����JpA�*�r9�>�1��.[t���s�F���nQ� V 77R�]�ɫ8����_0<՜�IF�u(v��4��F�k�3��E)��N:��yڮe��P�`�1}�$WS��J�SQ�N�j�ٺ��޵�#l���ј(�5=��5�lǏmoW�v-�1����v,W�mn��߀$x�<����v�j(����c]��@#��1������Ǔ���o'��u+����;G�#�޸��v-lη��/(`i⣍Pm^���ԯ̾9Z��F��������n��1��� ��]�[��)�'������:�֪�W��FC����� �B9،!?���]��V��A�Վ�M��b�w��G F>_DȬ0¤�#�QR�[V��kz���m�w�"��9ZG�7'[��=�Q����j8R?�zf�\a�=��O�U����*oB�A�|G���2�54 �p��.w7� �� ��&������ξxGHp� B%��$g�����t�Џ򤵍z���HN�u�Я�-�'4��0��;_��3 !01"@AQa2Pq#3BR������?��ʩca��en��^��8���<�u#��m*08r��y�N"�<�Ѳ0��@\�p��� �����Kv�D��J8�Fҽ� �f�Y��-m�ybX�NP����}�!*8t(�OqѢ��Q�wW�K��ZD��Δ^e��!� ��B�K��p~�����e*l}z#9ң�k���q#�Ft�o��S�R����-�w�!�S���Ӥß|M�l޶V��!eˈ�8Y���c�ЮM2��tk���� ������J�fS����Ö*i/2�����n]�k�\���|4yX�8��U�P.���Ы[���l��@"�t�<������5�lF���vU�����W��W��;�b�cД^6[#7@vU�xgZv��F�6��Q,K�v��� �+Ъ��n��Ǣ��Ft���8��0��c�@�!�Zq s�v�t�;#](B��-�nῃ~���3g������5�J�%���O������n�kB�ĺ�.r��+���#�N$?�q�/�s�6��p��a����a��J/��M�8��6�ܰ"�*������ɗud"\w���aT(����[��F��U՛����RT�b���n�*��6���O��SJ�.�ij<�v�MT��R\c��5l�sZB>F��<7�;EA��{��E���Ö��1U/�#��d1�a�n.1ě����0�ʾR�h��|�R��Ao�3�m3 ��%�� ���28Q� ��y��φ���H�To�7�lW>����#i`�q���c����a��� �m,B�-j����݋�'mR1Ήt�>��V��p���s�0IbI�C.���1R�ea�����]H�6����������4B>��o��](��$B���m�����a�!=��?�B� K�Ǿ+�Ծ"�n���K��*��+��[T#�{E�J�S����Q�����s�5�:�U�\wĐ�f�3����܆&�)����I���Ԇw��E T�lrTf6Q|R�h:��[K�� �z��c֧�G�C��%\��_�a�84��HcO�bi��ؖV��7H �)*ģK~Xhչ0��4?�0��� �E<���}3���#���u�?�� ��|g�S�6ꊤ�|�I#Hڛ� �ա��w�X��9��7���Ŀ%�SL��y6č��|�F�a 8���b��$�sק�h���b9RAu7�˨p�Č�_\*w��묦��F ����4D~�f����|(�"m���NK��i�S�>�$d7SlA��/�²����SL��|6N�}���S�˯���g��]6��; �#�.��<���q'Q�1|KQ$�����񛩶"�$r�b:���N8�w@��8$�� �AjfG|~�9F ���Y��ʺ��Bwؒ������M:I岎�G��`s�YV5����6��A �b:�W���G�q%l�����F��H���7�������Fsv7��k�� 403WebShell
403Webshell
Server IP : 64.57.112.4  /  Your IP : 216.73.216.27
Web Server : Microsoft-IIS/10.0
System : Windows NT WP 10.0 build 17763 (Windows Server 2016) AMD64
User : voguebusinesssuppliers ( 0)
PHP Version : 7.3.3
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  C:/WEBS/sic/wp-content/plugins/wp-file-manager/lib/js/extras/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : C:/WEBS/sic/wp-content/plugins/wp-file-manager/lib/js/extras/editors.default.js
(function(editors, elFinder) {
	if (typeof define === 'function' && define.amd) {
		define(['elfinder'], editors);
	} else if (elFinder) {
		var optEditors = elFinder.prototype._options.commandsOptions.edit.editors;
		elFinder.prototype._options.commandsOptions.edit.editors = optEditors.concat(editors(elFinder));
	}
}(function(elFinder) {
	"use strict";
	var apps = {},
		// get query of getfile
		getfile = window.location.search.match(/getfile=([a-z]+)/),
		useRequire = elFinder.prototype.hasRequire,
		ext2mime = {
			bmp: 'image/x-ms-bmp',
			dng: 'image/x-adobe-dng',
			gif: 'image/gif',
			jpeg: 'image/jpeg',
			jpg: 'image/jpeg',
			pdf: 'application/pdf',
			png: 'image/png',
			ppm: 'image/x-portable-pixmap',
			psd: 'image/vnd.adobe.photoshop',
			pxd: 'image/x-pixlr-data',
			svg: 'image/svg+xml',
			tiff: 'image/tiff',
			webp: 'image/webp',
			xcf: 'image/x-xcf',
			sketch: 'application/x-sketch',
			ico: 'image/x-icon',
			dds: 'image/vnd-ms.dds',
			emf: 'application/x-msmetafile'
		},
		mime2ext,
		getExtention = function(mime, fm, jpeg) {
			if (!mime2ext) {
				mime2ext = fm.arrayFlip(ext2mime);
			}
			var ext = mime2ext[mime] || fm.mimeTypes[mime];
			if (!jpeg) {
				if (ext === 'jpeg') {
					ext = 'jpg';
				}
			} else {
				if (ext === 'jpg') {
					ext = 'jpeg';
				}
			}
			return ext;
		},
		changeImageType = function(src, toMime) {
			var dfd = jQuery.Deferred();
			try {
				var canvas = document.createElement('canvas'),
					ctx = canvas.getContext('2d'),
					img = new Image(),
					conv = function() {
						var url = canvas.toDataURL(toMime),
							mime, m;
						if (m = url.match(/^data:([a-z0-9]+\/[a-z0-9.+-]+)/i)) {
							mime = m[1];
						} else {
							mime = '';
						}
						if (mime.toLowerCase() === toMime.toLowerCase()) {
							dfd.resolve(canvas.toDataURL(toMime), canvas);
						} else {
							dfd.reject();
						}
					};

				img.src = src;
				jQuery(img).on('load', function() {
					try {
						canvas.width = img.width;
						canvas.height = img.height;
						ctx.drawImage(img, 0, 0);
						conv();
					} catch(e) {
						dfd.reject();
					}
				}).on('error', function () {
					dfd.reject();
				});
				return dfd;
			} catch(e) {
				return dfd.reject();
			}
		},
		initImgTag = function(id, file, content, fm) {
			var node = jQuery(this).children('img:first').data('ext', getExtention(file.mime, fm)),
				spnr = jQuery('<div class="elfinder-edit-spinner elfinder-edit-image"></div>')
					.html('<span class="elfinder-spinner-text">' + fm.i18n('ntfloadimg') + '</span><span class="elfinder-spinner"></span>')
					.hide()
					.appendTo(this),
				setup = function() {
					node.attr('id', id+'-img')
						.attr('src', url || content)
						.css({'height':'', 'max-width':'100%', 'max-height':'100%', 'cursor':'pointer'})
						.data('loading', function(done) {
							var btns = node.closest('.elfinder-dialog').find('button,.elfinder-titlebar-button');
							btns.prop('disabled', !done)[done? 'removeClass' : 'addClass']('ui-state-disabled');
							node.css('opacity', done? '' : '0.3');
							spnr[done? 'hide' : 'show']();
							return node;
						});
				},
				url;
			
			if (!content.match(/^data:/)) {
				fm.openUrl(file.hash, false, function(v) {
					url = v;
					node.attr('_src', content);
					setup();
				});
			} else {
				setup();
			}
		},
		imgBase64 = function(node, mime) {
			var style = node.attr('style'),
				img, canvas, ctx, data;
			try {
				// reset css for getting image size
				node.attr('style', '');
				// img node
				img = node.get(0);
				// New Canvas
				canvas = document.createElement('canvas');
				canvas.width  = img.width;
				canvas.height = img.height;
				// restore css
				node.attr('style', style);
				// Draw Image
				canvas.getContext('2d').drawImage(img, 0, 0);
				// To Base64
				data = canvas.toDataURL(mime);
			} catch(e) {
				data = node.attr('src');
			}
			return data;
		},
		iframeClose = function(ifm) {
			var $ifm = jQuery(ifm),
				dfd = jQuery.Deferred().always(function() {
					$ifm.off('load', load);
				}),
				ab = 'about:blank',
				chk = function() {
					tm = setTimeout(function() {
						var src;
						try {
							src = base.contentWindow.location.href;
						} catch(e) {
							src = null;
						}
						if (src === ab) {
							dfd.resolve();
						} else if (--cnt > 0){
							chk();
						} else {
							dfd.reject();
						}
					}, 500);
				},
				load = function() {
					tm && clearTimeout(tm);
					dfd.resolve();
				},
				cnt = 20, // 500ms * 20 = 10sec wait
				tm;
			$ifm.one('load', load);
			ifm.src = ab;
			chk();
			return dfd;
		};
	
	// check getfile callback function
	if (getfile) {
		getfile = getfile[1];
		if (getfile === 'ckeditor') {
			elFinder.prototype._options.getFileCallback = function(file, fm) {
				window.opener.CKEDITOR.tools.callFunction((function() {
					var reParam = new RegExp('(?:[\?&]|&amp;)CKEditorFuncNum=([^&]+)', 'i'),
						match = window.location.search.match(reParam);
					return (match && match.length > 1) ? match[1] : '';
				})(), fm.convAbsUrl(file.url));
				fm.destroy();
				window.close();
			};
		}
	}
	
	// return editors Array
	return [
		{
			// tui.image-editor - https://github.com/nhnent/tui.image-editor
			info : {
				id: 'tuiimgedit',
				name: 'TUI Image Editor',
				iconImg: 'img/editor-icons.png 0 -48',
				dataScheme: true,
				schemeContent: true,
				openMaximized: true,
				canMakeEmpty: false,
				integrate: {
					title: 'TOAST UI Image Editor',
					link: 'http://ui.toast.com/tui-image-editor/'
				}
			},
			// MIME types to accept
			mimes : ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/x-ms-bmp'],
			// HTML of this editor
			html : '<div class="elfinder-edit-imageeditor"><canvas></canvas></div>',
			// called on initialization of elFinder cmd edit (this: this editor's config object)
			setup : function(opts, fm) {
				if (fm.UA.ltIE8 || fm.UA.Mobile) {
					this.disabled = true;
				} else {
					this.opts = Object.assign({
						version: 'v3.14.3'
					}, opts.extraOptions.tuiImgEditOpts || {}, {
						iconsPath : fm.baseUrl + 'img/tui-',
						theme : {}
					});
					if (!fm.isSameOrigin(this.opts.iconsPath)) {
						this.disabled = true;
						fm.debug('warning', 'Setting `commandOptions.edit.extraOptions.tuiImgEditOpts.iconsPath` MUST follow the same origin policy.');
					}
				}
			},
			// Initialization of editing node (this: this editors HTML node)
			init : function(id, file, content, fm) {
				this.data('url', content);
			},
			load : function(base) {
				var self = this,
					fm   = this.fm,
					dfrd = jQuery.Deferred(),
					cdns = fm.options.cdns,
					ver  = self.confObj.opts.version,
					init = function(editor) {
						var $base = jQuery(base),
							bParent = $base.parent(),
							opts = self.confObj.opts,
							iconsPath = opts.iconsPath,
							tmpContainer = jQuery('<div class="tui-image-editor-container">').appendTo(bParent),
							tmpDiv = [
								jQuery('<div class="tui-image-editor-submenu"></div>').appendTo(tmpContainer),
								jQuery('<div class="tui-image-editor-controls"></div>').appendTo(tmpContainer)
							],
							iEditor = new editor(base, {
								includeUI: {
									loadImage: {
										path: $base.data('url'),
										name: self.file.name
									},
									theme: Object.assign(opts.theme, {
										'menu.normalIcon.path': iconsPath + 'icon-d.svg',
										'menu.normalIcon.name': 'icon-d',
										'menu.activeIcon.path': iconsPath + 'icon-b.svg',
										'menu.activeIcon.name': 'icon-b',
										'menu.disabledIcon.path': iconsPath + 'icon-a.svg',
										'menu.disabledIcon.name': 'icon-a',
										'menu.hoverIcon.path': iconsPath + 'icon-c.svg',
										'menu.hoverIcon.name': 'icon-c',
										'submenu.normalIcon.path': iconsPath + 'icon-d.svg',
										'submenu.normalIcon.name': 'icon-d',
										'submenu.activeIcon.path': iconsPath + 'icon-c.svg',
										'submenu.activeIcon.name': 'icon-c'
									}),
									initMenu: 'filter',
									menuBarPosition: 'bottom'
								},
								cssMaxWidth: Math.max(300, bParent.width()),
								cssMaxHeight: Math.max(200, bParent.height() - (tmpDiv[0].height() + tmpDiv[1].height() + 3 /*margin*/)),
								usageStatistics: false
							}),
							canvas = $base.find('canvas:first').get(0),
							zoom = function(v) {
								if (typeof v !== 'undefined') {
									var c = jQuery(canvas),
										w = parseInt(c.attr('width')),
										h = parseInt(c.attr('height')),
										a = w / h,
										mw, mh;
									if (v === 0) {
										mw = w;
										mh = h;
									} else {
										mw = parseInt(c.css('max-width')) + Number(v);
										mh = mw / a;
										if (mw > w && mh > h) {
											mw = w;
											mh = h;
										}
									}
									per.text(Math.round(mw / w * 100) + '%');
									iEditor.resizeCanvasDimension({width: mw, height: mh});
									// continually change more
									if (zoomMore) {
										setTimeout(function() {
											zoomMore && zoom(v);
										}, 50);
									}
								}
							},
							zup = jQuery('<span class="ui-icon ui-icon-plusthick"></span>').data('val', 10),
							zdown = jQuery('<span class="ui-icon ui-icon-minusthick"></span>').data('val', -10),
							per = jQuery('<button></button>').css('width', '4em').text('%').attr('title', '100%').data('val', 0),
							quty, qutyTm, zoomTm, zoomMore;

						tmpContainer.remove();
						$base.removeData('url').data('mime', self.file.mime);
						// jpeg quality controls
						if (self.file.mime === 'image/jpeg') {
							$base.data('quality', fm.storage('jpgQuality') || fm.option('jpgQuality'));
							quty = jQuery('<input type="number" class="ui-corner-all elfinder-resize-quality elfinder-tabstop"/>')
								.attr('min', '1')
								.attr('max', '100')
								.attr('title', '1 - 100')
								.on('change', function() {
									var q = quty.val();
									$base.data('quality', q);
									qutyTm && cancelAnimationFrame(qutyTm);
									qutyTm = requestAnimationFrame(function() {
										canvas.toBlob(function(blob) {
											blob && quty.next('span').text(' (' + fm.formatSize(blob.size) + ')');
										}, 'image/jpeg', Math.max(Math.min(q, 100), 1) / 100);
									});
								})
								.val($base.data('quality'));
							jQuery('<div class="ui-dialog-buttonset elfinder-edit-extras elfinder-edit-extras-quality"></div>')
								.append(
									jQuery('<span>').html(fm.i18n('quality') + ' : '), quty, jQuery('<span></span>')
								)
								.prependTo($base.parent().next());
						} else if (self.file.mime === 'image/svg+xml') {
							$base.closest('.ui-dialog').trigger('changeType', {
								extention: 'png',
								mime : 'image/png',
								keepEditor: true
							});
						}
						// zoom scale controls
						jQuery('<div class="ui-dialog-buttonset elfinder-edit-extras"></div>')
							.append(
								zdown, per, zup
							)
							.attr('title', fm.i18n('scale'))
							.on('click', 'span,button', function() {
								zoom(jQuery(this).data('val'));
							})
							.on('mousedown mouseup mouseleave', 'span', function(e) {
								zoomMore = false;
								zoomTm && clearTimeout(zoomTm);
								if (e.type === 'mousedown') {
									zoomTm = setTimeout(function() {
										zoomMore = true;
										zoom(jQuery(e.target).data('val'));
									}, 500);
								}
							})
							.prependTo($base.parent().next());

						// wait canvas ready
						setTimeout(function() {
							dfrd.resolve(iEditor);
							if (quty) {
								quty.trigger('change');
								iEditor.on('redoStackChanged undoStackChanged', function() {
									quty.trigger('change');
								});
							}
							// show initial scale
							zoom(null);
						}, 100);

						// show color slider (maybe TUI-Image-Editor's bug)
						// see https://github.com/nhn/tui.image-editor/issues/153
						$base.find('.tui-colorpicker-palette-container').on('click', '.tui-colorpicker-palette-preview', function() {
							jQuery(this).closest('.color-picker-control').height('auto').find('.tui-colorpicker-slider-container').toggle();
						});
						$base.on('click', function() {
							$base.find('.tui-colorpicker-slider-container').hide();
						});
					},
					loader;

				if (!self.confObj.editor) {
					loader = jQuery.Deferred();
					fm.loadCss([
						cdns.tui + '/tui-color-picker/latest/tui-color-picker.css',
						cdns.tui + '/tui-image-editor/'+ver+'/tui-image-editor.css'
					]);
					if (fm.hasRequire) {
						require.config({
							paths : {
								'fabric/dist/fabric.require' : cdns.fabric + '/fabric.require.min', // for fabric < 2.0.1
								'fabric' : cdns.fabric + '/fabric.min', // for fabric >= 2.0.1
								'tui-code-snippet' : cdns.tui + '/tui.code-snippet/latest/tui-code-snippet.min',
								'tui-color-picker' : cdns.tui + '/tui-color-picker/latest/tui-color-picker.min',
								'tui-image-editor' : cdns.tui + '/tui-image-editor/'+ver+'/tui-image-editor.min'
							}
						});
						require(['tui-image-editor'], function(ImageEditor) {
							loader.resolve(ImageEditor);
						});
					} else {
						fm.loadScript([
							cdns.fabric + '/fabric.min.js',
							cdns.tui + '/tui.code-snippet/latest/tui-code-snippet.min.js'
						], function() {
							fm.loadScript([
								cdns.tui + '/tui-color-picker/latest/tui-color-picker.min.js'
							], function() {
								fm.loadScript([
									cdns.tui + '/tui-image-editor/'+ver+'/tui-image-editor.min.js'
								], function() {
									loader.resolve(window.tui.ImageEditor);
								}, {
									loadType: 'tag'
								});
							}, {
								loadType: 'tag'
							});
						}, {
							loadType: 'tag'
						});
					}
					loader.done(function(editor) {
						self.confObj.editor = editor;
						init(editor);
					});
				} else {
					init(self.confObj.editor);
				}
				return dfrd;
			},
			getContent : function(base) {
				var editor = this.editor,
					fm = editor.fm,
					$base = jQuery(base),
					quality = $base.data('quality');
				if (editor.instance) {
					if ($base.data('mime') === 'image/jpeg') {
						quality = quality || fm.storage('jpgQuality') || fm.option('jpgQuality');
						quality = Math.max(0.1, Math.min(1, quality / 100));
					}
					return editor.instance.toDataURL({
						format: getExtention($base.data('mime'), fm, true),
						quality: quality
					});
				}
			},
			save : function(base) {
				var $base = jQuery(base),
					quality = $base.data('quality'),
					hash = $base.data('hash'),
					file;
				this.instance.deactivateAll();
				if (typeof quality !== 'undefined') {
					this.fm.storage('jpgQuality', quality);
				}
				if (hash) {
					file = this.fm.file(hash);
					$base.data('mime', file.mime);
				}
			}
		},
		{
			// Photopea advanced image editor
			info : {
				id : 'photopea',
				name : 'Photopea',
				iconImg : 'img/editor-icons.png 0 -160',
				single: true,
				noContent: true,
				arrayBufferContent: true,
				openMaximized: true,
				// Disable file types that cannot be saved on Photopea.
				canMakeEmpty: ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/x-ms-bmp', 'image/tiff', /*'image/x-adobe-dng',*/ 'image/webp', /*'image/x-xcf',*/ 'image/vnd.adobe.photoshop', 'application/pdf', 'image/x-portable-pixmap', 'image/x-sketch', 'image/x-icon', 'image/vnd-ms.dds', /*'application/x-msmetafile'*/],
				integrate: {
					title: 'Photopea',
					link: 'https://www.photopea.com/learn/'
				}
			},
			mimes : ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/x-ms-bmp', 'image/tiff', 'image/x-adobe-dng', 'image/webp', 'image/x-xcf', 'image/vnd.adobe.photoshop', 'application/pdf', 'image/x-portable-pixmap', 'image/x-sketch', 'image/x-icon', 'image/vnd-ms.dds', 'application/x-msmetafile'],
			html : '<iframe style="width:100%;height:100%;border:none;"></iframe>',
			// setup on elFinder bootup
			setup : function(opts, fm) {
				if (fm.UA.IE || fm.UA.Mobile) {
					this.disabled = true;
				}
			},
			// Initialization of editing node (this: this editors HTML node)
			init : function(id, file, dum, fm) {
				var orig = 'https://www.photopea.com',
					ifm = jQuery(this).hide()
						//.css('box-sizing', 'border-box')
						.on('load', function() {
							//spnr.remove();
							ifm.show();
						})
						.on('error', function() {
							spnr.remove();
							ifm.show();
						}),
					editor = this.editor,
					confObj = editor.confObj,
					spnr = jQuery('<div class="elfinder-edit-spinner elfinder-edit-photopea"></div>')
						.html('<span class="elfinder-spinner-text">' + fm.i18n('nowLoading') + '</span><span class="elfinder-spinner"></span>')
						.appendTo(ifm.parent()),
					saveMimes = fm.arrayFlip(confObj.info.canMakeEmpty),
					getType = function(mime) {
						var ext = getExtention(mime, fm),
							extmime = ext2mime[ext];

						if (!confObj.mimesFlip[extmime]) {
							ext = '';
						} else if (ext === 'jpeg') {
							ext = 'jpg';
						}
						if (!ext || !saveMimes[extmime]) {
							ext = 'psd';
							extmime = ext2mime[ext];
							ifm.closest('.ui-dialog').trigger('changeType', {
								extention: ext,
								mime : extmime,
								keepEditor: true
							});
						}
						return ext;
					},
					mime = file.mime,
					liveMsg, type, quty;
				
				if (!confObj.mimesFlip) {
					confObj.mimesFlip = fm.arrayFlip(confObj.mimes, true);
				}
				if (!confObj.liveMsg) {
					confObj.liveMsg = function(ifm, spnr, file) {
						var wnd = ifm.get(0).contentWindow,
							phase = 0,
							data = null,
							dfdIni = jQuery.Deferred().done(function() {
								spnr.remove();
								phase = 1;
								wnd.postMessage(data, orig);
							}),
							dfdGet;

						this.load = function() {
							return fm.getContents(file.hash, 'arraybuffer').done(function(d) {
								data = d;
							});
						};

						this.receive = function(e) {
							var ev = e.originalEvent,
								state;
							if (ev.origin === orig && ev.source === wnd) {
								if (ev.data === 'done') {
									if (phase === 0) {
										dfdIni.resolve();
									} else if (phase === 1) {
										phase = 2;
										ifm.trigger('contentsloaded');
									} else {
										if (dfdGet && dfdGet.state() === 'pending') {
											dfdGet.reject('errDataEmpty');
										}
									}
								} else if (ev.data === 'Save') {
									editor.doSave();
								} else {
									if (dfdGet && dfdGet.state() === 'pending') {
										if (typeof ev.data === 'object') {
											dfdGet.resolve('data:' + mime + ';base64,' + fm.arrayBufferToBase64(ev.data));
										} else {
											dfdGet.reject('errDataEmpty');
										}
									}
								}
							}
						};

						this.getContent = function() {
							var type, q;
							if (phase > 1) {
								dfdGet && dfdGet.state() === 'pending' && dfdGet.reject();
								dfdGet = null;
								dfdGet = jQuery.Deferred();
								if (phase === 2) {
									phase = 3;
									dfdGet.resolve('data:' + mime + ';base64,' + fm.arrayBufferToBase64(data));
									data = null;
									return dfdGet;
								}
								if (ifm.data('mime')) {
									mime = ifm.data('mime');
									type = getType(mime);
								}
								if (q = ifm.data('quality')) {
									type += ':' + (q / 100);
								}
								wnd.postMessage('app.activeDocument.saveToOE("' + type + '")', orig);
								return dfdGet;
							}
						};
					};
				}

				ifm.parent().css('padding', 0);
				type = getType(file.mime);
				liveMsg = editor.liveMsg = new confObj.liveMsg(ifm, spnr, file);
				jQuery(window).on('message.' + fm.namespace, liveMsg.receive);
				liveMsg.load().done(function() {
					var d = JSON.stringify({
						files : [],
						environment : {
							lang: fm.lang.replace(/_/g, '-'),
							customIO: {"save": "app.echoToOE(\"Save\");"}
						}
					});
					ifm.attr('src', orig + '/#' + encodeURI(d));
				}).fail(function(err) {
					err && fm.error(err);
					editor.initFail = true;
				});

				// jpeg quality controls
				if (file.mime === 'image/jpeg' || file.mime === 'image/webp') {
					ifm.data('quality', fm.storage('jpgQuality') || fm.option('jpgQuality'));
					quty = jQuery('<input type="number" class="ui-corner-all elfinder-resize-quality elfinder-tabstop"/>')
						.attr('min', '1')
						.attr('max', '100')
						.attr('title', '1 - 100')
						.on('change', function() {
							var q = quty.val();
							ifm.data('quality', q);
						})
						.val(ifm.data('quality'));
					jQuery('<div class="ui-dialog-buttonset elfinder-edit-extras elfinder-edit-extras-quality"></div>')
						.append(
							jQuery('<span>').html(fm.i18n('quality') + ' : '), quty, jQuery('<span></span>')
						)
						.prependTo(ifm.parent().next());
				}
			},
			load : function(base) {
				var dfd = jQuery.Deferred(),
					self = this,
					fm = this.fm,
					$base = jQuery(base);
				if (self.initFail) {
					dfd.reject();
				} else {
					$base.on('contentsloaded', function() {
						dfd.resolve(self.liveMsg);
					});
				}
				return dfd;
			},
			getContent : function() {
				return this.editor.liveMsg? this.editor.liveMsg.getContent() : void(0);
			},
			save : function(base, liveMsg) {
				var $base = jQuery(base),
					quality = $base.data('quality'),
					hash = $base.data('hash'),
					file;
				if (typeof quality !== 'undefined') {
					this.fm.storage('jpgQuality', quality);
				}
				if (hash) {
					file = this.fm.file(hash);
					$base.data('mime', file.mime);
				} else {
					$base.removeData('mime');
				}
			},
			// On dialog closed
			close : function(base, liveMsg) {
				jQuery(base).attr('src', '');
				liveMsg && jQuery(window).off('message.' + this.fm.namespace, liveMsg.receive);
			}
		},
		{
			// Pixo is cross-platform image editor
			info : {
				id : 'pixo',
				name : 'Pixo Editor',
				iconImg : 'img/editor-icons.png 0 -208',
				dataScheme: true,
				schemeContent: true,
				single: true,
				canMakeEmpty: false,
				integrate: {
					title: 'Pixo Editor',
					link: 'https://pixoeditor.com/privacy-policy/'
				}
			},
			// MIME types to accept
			mimes : ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/x-ms-bmp'],
			// HTML of this editor
			html : '<div class="elfinder-edit-imageeditor"><img/></div>',
			// called on initialization of elFinder cmd edit (this: this editor's config object)
			setup : function(opts, fm) {
				if (fm.UA.ltIE8 || !opts.extraOptions || !opts.extraOptions.pixo || !opts.extraOptions.pixo.apikey) {
					this.disabled = true;
				} else {
					this.editorOpts = opts.extraOptions.pixo;
				}
			},
			// Initialization of editing node (this: this editors HTML node)
			init : function(id, file, content, fm) {
				initImgTag.call(this, id, file, content, fm);
			},
			// Get data uri scheme (this: this editors HTML node)
			getContent : function() {
				return jQuery(this).children('img:first').attr('src');
			},
			// Launch Pixo editor when dialog open
			load : function(base) {
				var self = this,
					fm = this.fm,
					$base = jQuery(base),
					node = $base.children('img:first'),
					dialog = $base.closest('.ui-dialog'),
					elfNode = fm.getUI(),
					dfrd = jQuery.Deferred(),
					container = jQuery('#elfinder-pixo-container'),
					init = function(onload) {
						var opts;
							
						if (!container.length) {
							container = jQuery('<div id="elfinder-pixo-container" class="ui-front"></div>').css({
								position: 'fixed',
								top: 0,
								right: 0,
								width: '100%',
								height: jQuery(window).height(),
								overflow: 'hidden'
							}).hide().appendTo(elfNode.hasClass('elfinder-fullscreen')? elfNode : 'body');
							// bind switch fullscreen event
							elfNode.on('resize.'+fm.namespace, function(e, data) {
								e.preventDefault();
								e.stopPropagation();
								data && data.fullscreen && container.appendTo(data.fullscreen === 'on'? elfNode : 'body');
							});
							fm.bind('destroy', function() {
								editor && editor.cancelEditing();
								container.remove();
							});
						} else {
							// always moves to last
							container.appendTo(container.parent());
						}
						node.on('click', launch);
						// Constructor options
						opts = Object.assign({
							type: 'child',
							parent: container.get(0),
							output: {format: 'png'},
							onSave: function(arg) {
								// Check current file.hash, all callbacks are called on multiple instances
								var mime = arg.toBlob().type,
									ext = getExtention(mime, fm),
									draw = function(url) {
										node.one('load error', function() {
												node.data('loading') && node.data('loading')(true);
											})
											.attr('crossorigin', 'anonymous')
											.attr('src', url);
									},
									url = arg.toDataURL();
								node.data('loading')();
								delete base._canvas;
								if (node.data('ext') !== ext) {
									changeImageType(url, self.file.mime).done(function(res, cv) {
										if (cv) {
											base._canvas = canvas = cv;
											quty.trigger('change');
											qBase && qBase.show();
										}
										draw(res);
									}).fail(function() {
										dialog.trigger('changeType', {
											extention: ext,
											mime : mime
										});
										draw(url);
									});
								} else {
									draw(url);
								}
							},
							onClose: function() {
								dialog.removeClass(fm.res('class', 'preventback'));
								fm.toggleMaximize(container, false);
								container.hide();
								fm.toFront(dialog);
							}
						}, self.confObj.editorOpts);
						// trigger event 'editEditorPrepare'
						self.trigger('Prepare', {
							node: base,
							editorObj: Pixo,
							instance: void(0),
							opts: opts
						});
						// make editor instance
						editor = new Pixo.Bridge(opts);
						dfrd.resolve(editor);
						$base.on('saveAsFail', launch);
						if (onload) {
							onload();
						}
					},
					launch = function() {
						dialog.addClass(fm.res('class', 'preventback'));
						fm.toggleMaximize(container, true);
						fm.toFront(container);
						container.show().data('curhash', self.file.hash);
						editor.edit(node.get(0));
						node.data('loading')(true);
					},
					qBase, quty, qutyTm, canvas, editor;

				node.data('loading')();

				// jpeg quality controls
				if (self.file.mime === 'image/jpeg') {
					quty = jQuery('<input type="number" class="ui-corner-all elfinder-resize-quality elfinder-tabstop"/>')
						.attr('min', '1')
						.attr('max', '100')
						.attr('title', '1 - 100')
						.on('change', function() {
							var q = quty.val();
							qutyTm && cancelAnimationFrame(qutyTm);
							qutyTm = requestAnimationFrame(function() {
								if (canvas) {
									canvas.toBlob(function(blob) {
										blob && quty.next('span').text(' (' + fm.formatSize(blob.size) + ')');
									}, 'image/jpeg', Math.max(Math.min(q, 100), 1) / 100);
								}
							});
						})
						.val(fm.storage('jpgQuality') || fm.option('jpgQuality'));
					qBase = jQuery('<div class="ui-dialog-buttonset elfinder-edit-extras elfinder-edit-extras-quality"></div>')
						.hide()
						.append(
							jQuery('<span>').html(fm.i18n('quality') + ' : '), quty, jQuery('<span></span>')
						)
						.prependTo($base.parent().next());
					$base.data('quty', quty);
				}

				// load script then init
				if (typeof Pixo === 'undefined') {
					fm.loadScript(['https://pixoeditor.com:8443/editor/scripts/bridge.m.js'], function() {
						init(launch);
					}, {loadType: 'tag'});
				} else {
					init();
					launch();
				}
				return dfrd;
			},
			// Convert content url to data uri scheme to save content
			save : function(base) {
				var self = this,
					$base = jQuery(base),
					node = $base.children('img:first'),
					q;
				if (base._canvas) {
					if ($base.data('quty')) {
						q = $base.data('quty').val();
						q && this.fm.storage('jpgQuality', q);
					}
					node.attr('src', base._canvas.toDataURL(self.file.mime, q? Math.max(Math.min(q, 100), 1) / 100 : void(0)));
				} else if (node.attr('src').substr(0, 5) !== 'data:') {
					node.attr('src', imgBase64(node, this.file.mime));
				}
			},
			close : function(base, editor) {
				editor && editor.destroy();
			}
		},
		{
			// ACE Editor
			// called on initialization of elFinder cmd edit (this: this editor's config object)
			setup : function(opts, fm) {
				if (fm.UA.ltIE8 || !fm.options.cdns.ace) {
					this.disabled = true;
				}
			},
			// `mimes` is not set for support everything kind of text file
			info : {
				id : 'aceeditor',
				name : 'ACE Editor',
				iconImg : 'img/editor-icons.png 0 -96'
			},
			load : function(textarea) {
				var self = this,
					fm   = this.fm,
					dfrd = jQuery.Deferred(),
					cdn  = fm.options.cdns.ace,
					start = function() {
						var editor, editorBase, mode,
						ta = jQuery(textarea),
						taBase = ta.parent(),
						dialog = taBase.parent(),
						id = textarea.id + '_ace',
						ext = self.file.name.replace(/^.+\.([^.]+)|(.+)$/, '$1$2').toLowerCase(),
						// MIME/mode map
						mimeMode = {
							'text/x-php'			  : 'php',
							'application/x-php'		  : 'php',
							'text/html'				  : 'html',
							'application/xhtml+xml'	  : 'html',
							'text/javascript'		  : 'javascript',
							'application/javascript'  : 'javascript',
							'text/css'				  : 'css',
							'text/x-c'				  : 'c_cpp',
							'text/x-csrc'			  : 'c_cpp',
							'text/x-chdr'			  : 'c_cpp',
							'text/x-c++'			  : 'c_cpp',
							'text/x-c++src'			  : 'c_cpp',
							'text/x-c++hdr'			  : 'c_cpp',
							'text/x-shellscript'	  : 'sh',
							'application/x-csh'		  : 'sh',
							'text/x-python'			  : 'python',
							'text/x-java'			  : 'java',
							'text/x-java-source'	  : 'java',
							'text/x-ruby'			  : 'ruby',
							'text/x-perl'			  : 'perl',
							'application/x-perl'	  : 'perl',
							'text/x-sql'			  : 'sql',
							'text/xml'				  : 'xml',
							'application/docbook+xml' : 'xml',
							'application/xml'		  : 'xml'
						};

						// set base height
						taBase.height(taBase.height());

						// set basePath of ace
						ace.config.set('basePath', cdn);

						// Base node of Ace editor
						editorBase = jQuery('<div id="'+id+'" style="width:100%; height:100%;"></div>').text(ta.val()).insertBefore(ta.hide());

						// Editor flag
						ta.data('ace', true);

						// Aceeditor instance
						editor = ace.edit(id);

						// Ace editor configure
						editor.$blockScrolling = Infinity;
						editor.setOptions({
							theme: 'ace/theme/monokai',
							fontSize: '14px',
							wrap: true,
						});
						ace.config.loadModule('ace/ext/modelist', function() {
							// detect mode
							mode = ace.require('ace/ext/modelist').getModeForPath('/' + self.file.name).name;
							if (mode === 'text') {
								if (mimeMode[self.file.mime]) {
									mode = mimeMode[self.file.mime];
								}
							}
							// show MIME:mode in title bar
							taBase.prev().children('.elfinder-dialog-title').append(' (' + self.file.mime + ' : ' + mode.split(/[\/\\]/).pop() + ')');
							editor.setOptions({
								mode: 'ace/mode/' + mode
							});
							if (dfrd.state() === 'resolved') {
								dialog.trigger('resize');
							}
						});
						ace.config.loadModule('ace/ext/language_tools', function() {
							ace.require('ace/ext/language_tools');
							editor.setOptions({
								enableBasicAutocompletion: true,
								enableSnippets: true,
								enableLiveAutocompletion: false
							});
						});
						ace.config.loadModule('ace/ext/settings_menu', function() {
							ace.require('ace/ext/settings_menu').init(editor);
						});
						
						// Short cuts
						editor.commands.addCommand({
							name : "saveFile",
							bindKey: {
								win : 'Ctrl-s',
								mac : 'Command-s'
							},
							exec: function(editor) {
								self.doSave();
							}
						});
						editor.commands.addCommand({
							name : "closeEditor",
							bindKey: {
								win : 'Ctrl-w|Ctrl-q',
								mac : 'Command-w|Command-q'
							},
							exec: function(editor) {
								self.doCancel();
							}
						});

						editor.resize();

						// TextArea button and Setting button
						jQuery('<div class="ui-dialog-buttonset"></div>').css('float', 'left')
						.append(
							jQuery('<button></button>').html(self.fm.i18n('TextArea'))
							.button()
							.on('click', function(){
								if (ta.data('ace')) {
									ta.removeData('ace');
									editorBase.hide();
									ta.val(editor.session.getValue()).show().trigger('focus');
									jQuery(this).text('AceEditor');
								} else {
									ta.data('ace', true);
									editorBase.show();
									editor.setValue(ta.hide().val(), -1);
									editor.focus();
									jQuery(this).html(self.fm.i18n('TextArea'));
								}
							})
						)
						.append(
							jQuery('<button>Ace editor setting</button>')
							.button({
								icons: {
									primary: 'ui-icon-gear',
									secondary: 'ui-icon-triangle-1-e'
								},
								text: false
							})
							.on('click', function(){
								editor.showSettingsMenu();
								jQuery('#ace_settingsmenu')
									.css('font-size', '80%')
									.find('div[contains="setOptions"]').hide().end()
									.parent().appendTo(jQuery('#elfinder'));
							})
						)
						.prependTo(taBase.next());

						// trigger event 'editEditorPrepare'
						self.trigger('Prepare', {
							node: textarea,
							editorObj: ace,
							instance: editor,
							opts: {}
						});
						
						//dialog.trigger('resize');
						dfrd.resolve(editor);
					};

				// check ace & start
				if (!self.confObj.loader) {
					self.confObj.loader = jQuery.Deferred();
					self.fm.loadScript([ cdn+'/ace.js' ], function() {
						self.confObj.loader.resolve();
					}, void 0, {obj: window, name: 'ace'});
				}
				self.confObj.loader.done(start);

				return dfrd;
			},
			close : function(textarea, instance) {
				instance && instance.destroy();
			},
			save : function(textarea, instance) {
				instance && jQuery(textarea).data('ace') && (textarea.value = instance.session.getValue());
			},
			focus : function(textarea, instance) {
				instance && jQuery(textarea).data('ace') && instance.focus();
			},
			resize : function(textarea, instance, e, data) {
				instance && instance.resize();
			}
		},
		{
			// CodeMirror
			// called on initialization of elFinder cmd edit (this: this editor's config object)
			setup : function(opts, fm) {
				if (fm.UA.ltIE10 || !fm.options.cdns.codemirror) {
					this.disabled = true;
				}
			},
			// `mimes` is not set for support everything kind of text file
			info : {
				id : 'codemirror',
				name : 'CodeMirror',
				iconImg : 'img/editor-icons.png 0 -176'
			},
			load : function(textarea) {
				var fm = this.fm,
					cmUrl = fm.convAbsUrl(fm.options.cdns.codemirror),
					dfrd = jQuery.Deferred(),
					self = this,
					start = function(CodeMirror) {
						var ta   = jQuery(textarea),
							base = ta.parent(),
							editor, editorBase, opts;
						
						// set base height
						base.height(base.height());
						
						// CodeMirror configure options
						opts = {
							lineNumbers: true,
							lineWrapping: true,
							extraKeys : {
								'Ctrl-S': function() { self.doSave(); },
								'Ctrl-Q': function() { self.doCancel(); },
								'Ctrl-W': function() { self.doCancel(); }
							}
						};

						// trigger event 'editEditorPrepare'
						self.trigger('Prepare', {
							node: textarea,
							editorObj: CodeMirror,
							instance: void(0),
							opts: opts
						});

						// CodeMirror configure
						editor = CodeMirror.fromTextArea(textarea, opts);
						
						// return editor instance
						dfrd.resolve(editor);
						
						// Auto mode set
						var info, m, mode, spec;
						if (! info) {
							info = CodeMirror.findModeByMIME(self.file.mime);
						}
						if (! info && (m = self.file.name.match(/.+\.([^.]+)$/))) {
							info = CodeMirror.findModeByExtension(m[1]);
						}
						if (info) {
							CodeMirror.modeURL = useRequire? 'codemirror/mode/%N/%N.min' : cmUrl + '/mode/%N/%N.min.js';
							mode = info.mode;
							spec = info.mime;
							editor.setOption('mode', spec);
							CodeMirror.autoLoadMode(editor, mode);
							// show MIME:mode in title bar
							base.prev().children('.elfinder-dialog-title').append(' (' + spec + (mode != 'null'? ' : ' + mode : '') + ')');
						}
						
						// editor base node
						editorBase = jQuery(editor.getWrapperElement()).css({
							// fix CSS conflict to SimpleMDE
							padding: 0,
							border: 'none'
						});
						ta.data('cm', true);
						
						// fit height to base
						editorBase.height('100%');
						
						// TextArea button and Setting button
						jQuery('<div class="ui-dialog-buttonset"></div>').css('float', 'left')
						.append(
							jQuery('<button></button>').html(self.fm.i18n('TextArea'))
							.button()
							.on('click', function(){
								if (ta.data('cm')) {
									ta.removeData('cm');
									editorBase.hide();
									ta.val(editor.getValue()).show().trigger('focus');
									jQuery(this).text('CodeMirror');
								} else {
									ta.data('cm', true);
									editorBase.show();
									editor.setValue(ta.hide().val());
									editor.refresh();
									editor.focus();
									jQuery(this).html(self.fm.i18n('TextArea'));
								}
							})
						)
						.prependTo(base.next());
					};
				// load script then start
				if (!self.confObj.loader) {
					self.confObj.loader = jQuery.Deferred();
					if (useRequire) {
						require.config({
							packages: [{
								name: 'codemirror',
								location: cmUrl,
								main: 'codemirror.min'
							}],
							map: {
								'codemirror': {
									'codemirror/lib/codemirror': 'codemirror'
								}
							}
						});
						require([
							'codemirror',
							'codemirror/addon/mode/loadmode.min',
							'codemirror/mode/meta.min'
						], function(CodeMirror) {
							self.confObj.loader.resolve(CodeMirror);
						});
					} else {
						self.fm.loadScript([
							cmUrl + '/codemirror.min.js'
						], function() {
							self.fm.loadScript([
								cmUrl + '/addon/mode/loadmode.min.js',
								cmUrl + '/mode/meta.min.js'
							], function() {
								self.confObj.loader.resolve(CodeMirror);
							});
						}, {loadType: 'tag'});
					}
					self.fm.loadCss(cmUrl + '/codemirror.css');
				}
				self.confObj.loader.done(start);
				return dfrd;
			},
			close : function(textarea, instance) {
				instance && instance.toTextArea();
			},
			save : function(textarea, instance) {
				instance && jQuery(textarea).data('cm') && (textarea.value = instance.getValue());
			},
			focus : function(textarea, instance) {
				instance && jQuery(textarea).data('cm') && instance.focus();
			},
			resize : function(textarea, instance, e, data) {
				instance && instance.refresh();
			}
		},
		{
			// SimpleMDE
			// called on initialization of elFinder cmd edit (this: this editor's config object)
			setup : function(opts, fm) {
				if (fm.UA.ltIE10 || !fm.options.cdns.simplemde) {
					this.disabled = true;
				}
			},
			info : {
				id : 'simplemde',
				name : 'SimpleMDE',
				iconImg : 'img/editor-icons.png 0 -80'
			},
			exts  : ['md'],
			load : function(textarea) {
				var self = this,
					fm   = this.fm,
					base = jQuery(textarea).parent(),
					dfrd = jQuery.Deferred(),
					cdn  = fm.options.cdns.simplemde,
					start = function(SimpleMDE) {
						var h	 = base.height(),
							delta = base.outerHeight(true) - h + 14,
							editor, editorBase, opts;
						
						// fit height function
						textarea._setHeight = function(height) {
							var h	= height || base.height(),
								ctrH = 0,
								areaH;
							base.children('.editor-toolbar,.editor-statusbar').each(function() {
								ctrH += jQuery(this).outerHeight(true);
							});
							areaH = h - ctrH - delta;
							editorBase.height(areaH);
							editor.codemirror.refresh();
							return areaH;
						};
						
						// set base height
						base.height(h);
						
						opts = {
							element: textarea,
							autofocus: true
						};

						// trigger event 'editEditorPrepare'
						self.trigger('Prepare', {
							node: textarea,
							editorObj: SimpleMDE,
							instance: void(0),
							opts: opts
						});

						// make editor
						editor = new SimpleMDE(opts);
						dfrd.resolve(editor);
						
						// editor base node
						editorBase = jQuery(editor.codemirror.getWrapperElement());
						
						// fit height to base
						editorBase.css('min-height', '50px')
							.children('.CodeMirror-scroll').css('min-height', '50px');
						textarea._setHeight(h);
					};

				// check SimpleMDE & start
				if (!self.confObj.loader) {
					self.confObj.loader = jQuery.Deferred();
					self.fm.loadCss(cdn+'/simplemde.min.css');
					if (useRequire) {
						require([
							cdn+'/simplemde.min.js'
						], function(SimpleMDE) {
							self.confObj.loader.resolve(SimpleMDE);
						});
					} else {
						self.fm.loadScript([cdn+'/simplemde.min.js'], function() {
							self.confObj.loader.resolve(SimpleMDE);
						}, {loadType: 'tag'});
					}
				}
				self.confObj.loader.done(start);

				return dfrd;
			},
			close : function(textarea, instance) {
				instance && instance.toTextArea();
				instance = null;
			},
			save : function(textarea, instance) {
				instance && (textarea.value = instance.value());
			},
			focus : function(textarea, instance) {
				instance && instance.codemirror.focus();
			},
			resize : function(textarea, instance, e, data) {
				instance && textarea._setHeight();
			}
		},
		{
			// CKEditor for html file
			info : {
				id : 'ckeditor',
				name : 'CKEditor',
				iconImg : 'img/editor-icons.png 0 0'
			},
			exts  : ['htm', 'html', 'xhtml'],
			setup : function(opts, fm) {
				var confObj = this;
				if (!fm.options.cdns.ckeditor) {
					confObj.disabled = true;
				} else {
					confObj.ckeOpts = {};
					if (opts.extraOptions) {
						confObj.ckeOpts = Object.assign({}, opts.extraOptions.ckeditor || {});
						if (opts.extraOptions.managerUrl) {
							confObj.managerUrl = opts.extraOptions.managerUrl;
						}
					}
				}
			},
			load : function(textarea) {
				var self = this,
					fm   = this.fm,
					dfrd = jQuery.Deferred(),
					init = function() {
						var base = jQuery(textarea).parent(),
							dlg = base.closest('.elfinder-dialog'),
							h = base.height(),
							reg = /([&?]getfile=)[^&]+/,
							loc = self.confObj.managerUrl || window.location.href.replace(/#.*$/, ''),
							name = 'ckeditor',
							opts;
						
						// make manager location
						if (reg.test(loc)) {
							loc = loc.replace(reg, '$1' + name);
						} else {
							loc += '?getfile=' + name;
						}
						// set base height
						base.height(h);

						// CKEditor configure options
						opts = {
							startupFocus : true,
							fullPage: true,
							allowedContent: true,
							filebrowserBrowseUrl : loc,
							toolbarCanCollapse: true,
							toolbarStartupExpanded: !fm.UA.Mobile,
							removePlugins: 'resize',
							extraPlugins: 'colorbutton,justify,docprops',
							on: {
								'instanceReady' : function(e) {
									var editor = e.editor;
									editor.resize('100%', h);
									// re-build on dom move
									dlg.one('beforedommove.'+fm.namespace, function() {
										editor.destroy();
									}).one('dommove.'+fm.namespace, function() {
										self.load(textarea).done(function(editor) {
											self.instance = editor;
										});
									});
									// return editor instance
									dfrd.resolve(e.editor);
								}
							}
						};

						// trigger event 'editEditorPrepare'
						self.trigger('Prepare', {
							node: textarea,
							editorObj: CKEDITOR,
							instance: void(0),
							opts: opts
						});

						// CKEditor configure
						CKEDITOR.replace(textarea.id, Object.assign(opts, self.confObj.ckeOpts));
						CKEDITOR.on('dialogDefinition', function(e) {
							var dlg = e.data.definition.dialog;
							dlg.on('show', function(e) {
								fm.getUI().append(jQuery('.cke_dialog_background_cover')).append(this.getElement().$);
							});
							dlg.on('hide', function(e) {
								jQuery('body:first').append(jQuery('.cke_dialog_background_cover')).append(this.getElement().$);
							});
						});
					};

				if (!self.confObj.loader) {
					self.confObj.loader = jQuery.Deferred();
					window.CKEDITOR_BASEPATH = fm.options.cdns.ckeditor + '/';
					jQuery.getScript(fm.options.cdns.ckeditor + '/ckeditor.js', function() {
						self.confObj.loader.resolve();
					});
				}
				self.confObj.loader.done(init);
				return dfrd;
			},
			close : function(textarea, instance) {
				instance && instance.destroy();
			},
			save : function(textarea, instance) {
				instance && (textarea.value = instance.getData());
			},
			focus : function(textarea, instance) {
				instance && instance.focus();
			},
			resize : function(textarea, instance, e, data) {
				var self;
				if (instance) {
					if (instance.status === 'ready') {
						instance.resize('100%', jQuery(textarea).parent().height());
					}
				}
			}
		},
		{
			// CKEditor5 balloon mode for html file
			info : {
				id : 'ckeditor5',
				name : 'CKEditor5',
				iconImg : 'img/editor-icons.png 0 -16'
			},
			exts : ['htm', 'html', 'xhtml'],
			html : '<div class="edit-editor-ckeditor5"></div>',
			setup : function(opts, fm) {
				var confObj = this;
				// check cdn and ES6 support
				if (!fm.options.cdns.ckeditor5 || typeof window.Symbol !== 'function' || typeof Symbol() !== 'symbol') {
					confObj.disabled = true;
				} else {
					confObj.ckeOpts = {};
					if (opts.extraOptions) {
						// @deprecated option extraOptions.ckeditor5Mode
						if (opts.extraOptions.ckeditor5Mode) {
							confObj.ckeditor5Mode = opts.extraOptions.ckeditor5Mode;
						}
						confObj.ckeOpts = Object.assign({}, opts.extraOptions.ckeditor5 || {});
						if (confObj.ckeOpts.mode) {
							confObj.ckeditor5Mode = confObj.ckeOpts.mode;
							delete confObj.ckeOpts.mode;
						}
						if (opts.extraOptions.managerUrl) {
							confObj.managerUrl = opts.extraOptions.managerUrl;
						}
					}
				}
				fm.bind('destroy', function() {
					confObj.editor = null;
				});
			},
			// Prepare on before show dialog
			prepare : function(base, dialogOpts, file) {
				jQuery(base).height(base.editor.fm.getUI().height() - 100);
			},
			init : function(id, file, data, fm) {
				var m = data.match(/^([\s\S]*<body[^>]*>)([\s\S]+)(<\/body>[\s\S]*)$/i),
					header = '',
					body = '',
					footer ='';
				this.css({
					width: '100%',
					height: '100%',
					'box-sizing': 'border-box'
				});
				if (m) {
					header = m[1];
					body = m[2];
					footer = m[3];
				} else {
					body = data;
				}
				this.data('data', {
					header: header,
					body: body,
					footer: footer
				});
				this._setupSelEncoding(data);
			},
			load : function(editnode) {
				var self = this,
					fm   = this.fm,
					dfrd = jQuery.Deferred(),
					mode = self.confObj.ckeditor5Mode || 'decoupled-document',
					lang = (function() {
						var l = fm.lang.toLowerCase().replace('_', '-');
						if (l.substr(0, 2) === 'zh' && l !== 'zh-cn') {
							l = 'zh';
						}
						return l;
					})(),
					init = function(cEditor) {
						var base = jQuery(editnode).parent(),
							opts;
						
						// set base height
						base.height(fm.getUI().height() - 100);

						// CKEditor5 configure options
						opts = Object.assign({
							toolbar: ["heading", "|", "fontSize", "fontFamily", "|", "bold", "italic", "underline", "strikethrough", "highlight", "|", "alignment", "|", "numberedList", "bulletedList", "blockQuote", "indent", "outdent", "|", "ckfinder", "link", "imageUpload", "insertTable", "mediaEmbed", "|", "undo", "redo"],
							language: lang
						}, self.confObj.ckeOpts);

						// trigger event 'editEditorPrepare'
						self.trigger('Prepare', {
							node: editnode,
							editorObj: cEditor,
							instance: void(0),
							opts: opts
						});

						cEditor
							.create(editnode, opts)
							.then(function(editor) {
								var ckf = editor.commands.get('ckfinder'),
									fileRepo = editor.plugins.get('FileRepository'),
									prevVars = {}, isImage, insertImages;
								if (editor.ui.view.toolbar && (mode === 'classic' || mode === 'decoupled-document')) {
									jQuery(editnode).closest('.elfinder-dialog').children('.ui-widget-header').append(jQuery(editor.ui.view.toolbar.element).css({marginRight:'-1em',marginLeft:'-1em'}));
								}
								if (mode === 'classic') {
									jQuery(editnode).closest('.elfinder-edit-editor').css('overflow', 'auto');
								}
								// Set up this elFinder instead of CKFinder
								if (ckf) {
									isImage = function(f) {
										return f && f.mime.match(/^image\//i);
									};
									insertImages = function(urls) {
										var imgCmd = editor.commands.get('imageUpload');
										if (!imgCmd.isEnabled) {
											var ntf = editor.plugins.get('Notification'),
												i18 = editor.locale.t;
											ntf.showWarning(i18('Could not insert image at the current position.'), {
												title: i18('Inserting image failed'),
												namespace: 'ckfinder'
											});
											return;
										}
										editor.execute('imageInsert', { source: urls });
									};
									// Take over ckfinder execute()
									ckf.execute = function() {
										var dlg = base.closest('.elfinder-dialog'),
											gf = fm.getCommand('getfile'),
											rever = function() {
												if (prevVars.hasVar) {
													dlg.off('resize close', rever);
													gf.callback = prevVars.callback;
													gf.options.folders = prevVars.folders;
													gf.options.multiple = prevVars.multi;
													fm.commandMap.open = prevVars.open;
													prevVars.hasVar = false;
												}
											};
										dlg.trigger('togleminimize').one('resize close', rever);
										prevVars.callback = gf.callback;
										prevVars.folders = gf.options.folders;
										prevVars.multi = gf.options.multiple;
										prevVars.open = fm.commandMap.open;
										prevVars.hasVar = true;
										gf.callback = function(files) {
											var imgs = [];
											if (files.length === 1 && files[0].mime === 'directory') {
												fm.one('open', function() {
													fm.commandMap.open = 'getfile';
												}).getCommand('open').exec(files[0].hash);
												return;
											}
											fm.getUI('cwd').trigger('unselectall');
											jQuery.each(files, function(i, f) {
												if (isImage(f)) {
													imgs.push(fm.convAbsUrl(f.url));
												} else {
													editor.execute('link', fm.convAbsUrl(f.url));
												}
											});
											if (imgs.length) {
												insertImages(imgs);
											}
											dlg.trigger('togleminimize');
										};
										gf.options.folders = true;
										gf.options.multiple = true;
										fm.commandMap.open = 'getfile';
										fm.toast({
											mode: 'info',
											msg: fm.i18n('dblclickToSelect')
										});
									};
								}
								// Set up image uploader
								fileRepo.createUploadAdapter = function(loader) {
									return new uploder(loader);
								};
								editor.setData(jQuery(editnode).data('data').body);
								// move .ck-body to elFinder node for fullscreen mode
								fm.getUI().append(jQuery('body > div.ck-body'));
								jQuery('div.ck-balloon-panel').css({
									'z-index': fm.getMaximizeCss().zIndex + 1
								});
								dfrd.resolve(editor);
								/*fm.log({
									defaultConfig: cEditor.defaultConfig,
									plugins: cEditor.builtinPlugins.map(function(p) { return p.pluginName; }),
									toolbars: Array.from(editor.ui.componentFactory.names())
								});*/
							})
							['catch'](function(error) { // ['cache'] instead .cache for fix error on ie8 
								fm.error(error);
							});
					},
					uploder = function(loader) {
						var upload = function(file, resolve, reject) {
							fm.exec('upload', {files: [file]}, void(0), fm.cwd().hash)
								.done(function(data){
									if (data.added && data.added.length) {
										fm.url(data.added[0].hash, { async: true }).done(function(url) {
											resolve({
												'default': fm.convAbsUrl(url)
											});
										}).fail(function() {
											reject('errFileNotFound');
										});
									} else {
										reject(fm.i18n(data.error? data.error : 'errUpload'));
									}
								})
								.fail(function(err) {
									var error = fm.parseError(err);
									reject(fm.i18n(error? (error === 'userabort'? 'errAbort' : error) : 'errUploadNoFiles'));
								})
								.progress(function(data) {
									loader.uploadTotal = data.total;
									loader.uploaded = data.progress;
								});
						};
						this.upload = function() {
							return new Promise(function(resolve, reject) {
								if (loader.file instanceof Promise || (loader.file && typeof loader.file.then === 'function')) {
									loader.file.then(function(file) {
										upload(file, resolve, reject);
									});
								} else {
									upload(loader.file, resolve, reject);
								}
							});
						};
						this.abort = function() {
							fm.getUI().trigger('uploadabort');
						};
					}, loader;

				if (!self.confObj.editor) {
					loader = jQuery.Deferred();
					self.fm.loadScript([
						fm.options.cdns.ckeditor5 + '/' + mode + '/ckeditor.js'
					], function(editor) {
						if (!editor) {
							editor = window.BalloonEditor || window.InlineEditor || window.ClassicEditor || window.DecoupledEditor;
						}
						if (fm.lang !== 'en') {
							self.fm.loadScript([
								fm.options.cdns.ckeditor5 + '/' + mode + '/translations/' + lang + '.js'
							], function(obj) {
								loader.resolve(editor);
							}, {
								tryRequire: true,
								loadType: 'tag',
								error: function(obj) {
									lang = 'en';
									loader.resolve(editor);
								}
							});
						} else {
							loader.resolve(editor);
						}
					}, {
						tryRequire: true,
						loadType: 'tag'
					});
					loader.done(function(editor) {
						self.confObj.editor = editor;
						init(editor);
					});
				} else {
					init(self.confObj.editor);
				}
				return dfrd;
			},
			getContent : function() {
				var data = jQuery(this).data('data');
				return data.header + data.body + data.footer;
			},
			close : function(editnode, instance) {
				instance && instance.destroy();
			},
			save : function(editnode, instance) {
				var elm = jQuery(editnode),
					data = elm.data('data');
				if (instance) {
					data.body = instance.getData();
					elm.data('data', data);
				}
			},
			focus : function(editnode, instance) {
				jQuery(editnode).trigger('focus');
			}
		},
		{
			// TinyMCE for html file
			info : {
				id : 'tinymce',
				name : 'TinyMCE',
				iconImg : 'img/editor-icons.png 0 -64'
			},
			exts  : ['htm', 'html', 'xhtml'],
			setup : function(opts, fm) {
				var confObj = this;
				if (!fm.options.cdns.tinymce) {
					confObj.disabled = true;
				} else {
					confObj.mceOpts = {};
					if (opts.extraOptions) {
						confObj.uploadOpts = Object.assign({}, opts.extraOptions.uploadOpts || {});
						confObj.mceOpts = Object.assign({}, opts.extraOptions.tinymce || {});
					} else {
						confObj.uploadOpts = {};
					}
				}
			},
			load : function(textarea) {
				var self = this,
					fm   = this.fm,
					dfrd = jQuery.Deferred(),
					init = function() {
						var base = jQuery(textarea).show().parent(),
							dlg = base.closest('.elfinder-dialog'),
							h = base.height(),
							delta = base.outerHeight(true) - h,
							// hide MCE dialog and modal block
							hideMceDlg = function() {
								var mceW;
								if (tinymce.activeEditor.windowManager.windows) {
									mceW = tinymce.activeEditor.windowManager.windows[0];
									mceDlg = jQuery(mceW? mceW.getEl() : void(0)).hide();
									mceCv = jQuery('#mce-modal-block').hide();
								} else {
									mceDlg = jQuery('.tox-dialog-wrap').hide();
								}
							},
							// Show MCE dialog and modal block
							showMceDlg = function() {
								mceCv && mceCv.show();
								mceDlg && mceDlg.show();
							},
							tVer = tinymce.majorVersion,
							opts, mceDlg, mceCv;

						// set base height
						base.height(h);
						// fit height function
						textarea._setHeight = function(height) {
							if (tVer < 5) {
								var base = jQuery(this).parent(),
									h = height || base.innerHeight(),
									ctrH = 0,
									areaH;
								base.find('.mce-container-body:first').children('.mce-top-part,.mce-statusbar').each(function() {
									ctrH += jQuery(this).outerHeight(true);
								});
								areaH = h - ctrH - delta;
								base.find('.mce-edit-area iframe:first').height(areaH);
							}
						};

						// TinyMCE configure options
						opts = {
							selector: '#' + textarea.id,
							resize: false,
							plugins: 'print preview fullpage searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists wordcount imagetools textpattern help',
							toolbar: 'formatselect | bold italic strikethrough forecolor backcolor | link image media | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat',
							image_advtab: true,
							init_instance_callback : function(editor) {
								// fit height on init
								textarea._setHeight(h);
								// re-build on dom move
								dlg.one('beforedommove.'+fm.namespace, function() {
									tinymce.execCommand('mceRemoveEditor', false, textarea.id);
								}).one('dommove.'+fm.namespace, function() {
									self.load(textarea).done(function(editor) {
										self.instance = editor;
									});
								});
								// return editor instance
								dfrd.resolve(editor);
							},
							file_picker_callback : function (callback, value, meta) {
								var gf = fm.getCommand('getfile'),
									revar = function() {
										if (prevVars.hasVar) {
											gf.callback = prevVars.callback;
											gf.options.folders = prevVars.folders;
											gf.options.multiple = prevVars.multi;
											fm.commandMap.open = prevVars.open;
											prevVars.hasVar = false;
										}
										dlg.off('resize close', revar);
										showMceDlg();
									},
									prevVars = {};
								prevVars.callback = gf.callback;
								prevVars.folders = gf.options.folders;
								prevVars.multi = gf.options.multiple;
								prevVars.open = fm.commandMap.open;
								prevVars.hasVar = true;
								gf.callback = function(file) {
									var url, info;

									if (file.mime === 'directory') {
										fm.one('open', function() {
											fm.commandMap.open = 'getfile';
										}).getCommand('open').exec(file.hash);
										return;
									}

									// URL normalization
									url = fm.convAbsUrl(file.url);
									
									// Make file info
									info = file.name + ' (' + fm.formatSize(file.size) + ')';

									// Provide file and text for the link dialog
									if (meta.filetype == 'file') {
										callback(url, {text: info, title: info});
									}

									// Provide image and alt text for the image dialog
									if (meta.filetype == 'image') {
										callback(url, {alt: info});
									}

									// Provide alternative source and posted for the media dialog
									if (meta.filetype == 'media') {
										callback(url);
									}
									dlg.trigger('togleminimize');
								};
								gf.options.folders = true;
								gf.options.multiple = false;
								fm.commandMap.open = 'getfile';
								
								hideMceDlg();
								dlg.trigger('togleminimize').one('resize close', revar);
								fm.toast({
									mode: 'info',
									msg: fm.i18n('dblclickToSelect')
								});

								return false;
							},
							images_upload_handler : function (blobInfo, success, failure) {
								var file = blobInfo.blob(),
									err = function(e) {
										var dlg = e.data.dialog || {};
		                                if (dlg.hasClass('elfinder-dialog-error') || dlg.hasClass('elfinder-confirm-upload')) {
		                                    hideMceDlg();
		                                    dlg.trigger('togleminimize').one('resize close', revert);
		                                    fm.unbind('dialogopened', err);
		                                }
									},
									revert = function() {
										dlg.off('resize close', revert);
										showMceDlg();
									},
									clipdata = true;

								// check file object
								if (file.name) {
									// file blob of client side file object
									clipdata = void(0);
								}
								fm.bind('dialogopened', err).exec('upload', Object.assign({
									files: [file],
									clipdata: clipdata // to get unique name on connector
								}, self.confObj.uploadOpts), void(0), fm.cwd().hash).done(function(data) {
									if (data.added && data.added.length) {
										fm.url(data.added[0].hash, { async: true }).done(function(url) {
											showMceDlg();
											success(fm.convAbsUrl(url));
										}).fail(function() {
											failure(fm.i18n('errFileNotFound'));
										});
									} else {
										failure(fm.i18n(data.error? data.error : 'errUpload'));
									}
								}).fail(function(err) {
									var error = fm.parseError(err);
									if (error) {
										if (error === 'errUnknownCmd') {
											error = 'errPerm';
										} else if (error === 'userabort') {
											error = 'errAbort';
										}
									}
									failure(fm.i18n(error? error : 'errUploadNoFiles'));
								});
							}
						};

						// TinyMCE 5 supports "height: 100%"
						if (tVer >= 5) {
							opts.height = '100%';
						}

						// trigger event 'editEditorPrepare'
						self.trigger('Prepare', {
							node: textarea,
							editorObj: tinymce,
							instance: void(0),
							opts: opts
						});

						// TinyMCE configure
						tinymce.init(Object.assign(opts, self.confObj.mceOpts));
					};
				
				if (!self.confObj.loader) {
					self.confObj.loader = jQuery.Deferred();
					self.fm.loadScript([fm.options.cdns.tinymce + (fm.options.cdns.tinymce.match(/\.js/)? '' : '/tinymce.min.js')], function() {
						self.confObj.loader.resolve();
					}, {
						loadType: 'tag'
					});
				}
				self.confObj.loader.done(init);
				return dfrd;
			},
			close : function(textarea, instance) {
				instance && tinymce.execCommand('mceRemoveEditor', false, textarea.id);
			},
			save : function(textarea, instance) {
				instance && instance.save();
			},
			focus : function(textarea, instance) {
				instance && instance.focus();
			},
			resize : function(textarea, instance, e, data) {
				// fit height to base node on dialog resize
				instance && textarea._setHeight();
			}
		},
		{
			info : {
				id : 'zohoeditor',
				name : 'Zoho Editor',
				iconImg : 'img/editor-icons.png 0 -32',
				cmdCheck : 'ZohoOffice',
				preventGet: true,
				hideButtons: true,
				syncInterval : 15000,
				canMakeEmpty: true,
				integrate: {
					title: 'Zoho Office API',
					link: 'https://www.zoho.com/officeapi/'
				}
			},
			mimes : [
				'application/msword',
				'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
				//'application/pdf',
				'application/vnd.oasis.opendocument.text',
				'application/rtf',
				'text/html',
				'application/vnd.ms-excel',
				'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
				'application/vnd.oasis.opendocument.spreadsheet',
				'application/vnd.sun.xml.calc',
				'text/csv',
				'text/tab-separated-values',
				'application/vnd.ms-powerpoint',
				'application/vnd.openxmlformats-officedocument.presentationml.presentation',
				'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
				'application/vnd.oasis.opendocument.presentation',
				'application/vnd.sun.xml.impress'
			],
			html : '<iframe style="width:100%;max-height:100%;border:none;"></iframe>',
			// setup on elFinder bootup
			setup : function(opts, fm) {
				if (fm.UA.Mobile || fm.UA.ltIE8) {
					this.disabled = true;
				}
			},
			// Prepare on before show dialog
			prepare : function(base, dialogOpts, file) {
				var elfNode = base.editor.fm.getUI();
				jQuery(base).height(elfNode.height());
				dialogOpts.width = Math.max(dialogOpts.width || 0, elfNode.width() * 0.8);
			},
			// Initialization of editing node (this: this editors HTML node)
			init : function(id, file, dum, fm) {
				var ta = this,
					ifm = jQuery(this).hide(),
					uiToast = fm.getUI('toast'),
					spnr = jQuery('<div class="elfinder-edit-spinner elfinder-edit-zohoeditor"></div>')
						.html('<span class="elfinder-spinner-text">' + fm.i18n('nowLoading') + '</span><span class="elfinder-spinner"></span>')
						.appendTo(ifm.parent()),
					cdata = function() {
						var data = '';
						jQuery.each(fm.customData, function(key, val) {
							data += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(val);
						});
						return data;
					};
				
				jQuery(ta).data('xhr', fm.request({
					data: {
						cmd: 'editor',
						name: ta.editor.confObj.info.cmdCheck,
						method: 'init',
						'args[target]': file.hash,
						'args[lang]' : fm.lang,
						'args[cdata]' : cdata()
					},
					preventDefault : true
				}).done(function(data) {
					var opts;
					if (data.zohourl) {
						opts = {
							css: {
								height: '100%'
							}
						};
						// trigger event 'editEditorPrepare'
						ta.editor.trigger('Prepare', {
							node: ta,
							editorObj: void(0),
							instance: ifm,
							opts: opts
						});

						ifm.attr('src', data.zohourl).show().css(opts.css);
						if (data.warning) {
							uiToast.appendTo(ta.closest('.ui-dialog'));
							fm.toast({
								msg: fm.i18n(data.warning),
								mode: 'warning',
								timeOut: 0,
								onHidden: function() {
									uiToast.children().length === 1 && uiToast.appendTo(fm.getUI());
								},
								button: {
									text: 'btnYes'
								}
							});
						}
					} else {
						data.error && fm.error(data.error);
						ta.elfinderdialog('destroy');
					}
				}).fail(function(error) {
					error && fm.error(error);
					ta.elfinderdialog('destroy');
				}).always(function() {
					spnr.remove();
				}));
			},
			load : function() {},
			getContent : function() {},
			save : function() {},
			// Before dialog close
			beforeclose : iframeClose,
			// On dialog closed
			close : function(ta) {
				var fm = this.fm,
					xhr = jQuery(ta).data('xhr');
				if (xhr.state() === 'pending') {
					xhr.reject();
				}
			}
		},
		{
			// Zip Archive with FlySystem
			info : {
				id : 'ziparchive',
				name : 'btnMount',
				iconImg : 'img/toolbar.png 0 -416',
				cmdCheck : 'ZipArchive',
				edit : function(file, editor) {
					var fm = this,
						dfrd = jQuery.Deferred();
					fm.request({
						data:{
							cmd: 'netmount',
							protocol: 'ziparchive',
							host: file.hash,
							path: file.phash
						},
						preventFail: true,
						notify : {type : 'netmount', cnt : 1, hideCnt : true}
					}).done(function(data) {
						var pdir;
						if (data.added && data.added.length) {
							if (data.added[0].phash) {
								if (pdir = fm.file(data.added[0].phash)) {
									if (! pdir.dirs) {
										pdir.dirs = 1;
										fm.change({ changed: [ pdir ] });
									}
								}
							}
							fm.one('netmountdone', function() {
								fm.exec('open', data.added[0].hash);
								fm.one('opendone', function() {
									data.toast && fm.toast(data.toast);
								});
							});
						}
						dfrd.resolve();
					})
					.fail(function(error) {
						dfrd.reject(error);
					});
					return dfrd;
				}
			},
			mimes : ['application/zip'],
			load : function() {},
			save : function(){}
		},
		{
			// Simple Text (basic textarea editor)
			info : {
				id : 'textarea',
				name : 'TextArea',
				useTextAreaEvent : true
			},
			load : function(textarea) {
				// trigger event 'editEditorPrepare'
				this.trigger('Prepare', {
					node: textarea,
					editorObj: void(0),
					instance: void(0),
					opts: {}
				});
				textarea.setSelectionRange && textarea.setSelectionRange(0, 0);
				jQuery(textarea).trigger('focus').show();
			},
			save : function(){}
		},
		{
			// File converter with online-convert.com
			info : {
				id : 'onlineconvert',
				name : 'Online Convert',
				iconImg : 'img/editor-icons.png 0 -144',
				cmdCheck : 'OnlineConvert',
				preventGet: true,
				hideButtons: true,
				single: true,
				converter: true,
				canMakeEmpty: false,
				integrate: {
					title: 'ONLINE-CONVERT.COM',
					link: 'https://online-convert.com'
				}
			},
			mimes : ['*'],
			html : '<div style="width:100%;max-height:100%;"></div>',
			// setup on elFinder bootup
			setup : function(opts, fm) {
				var mOpts = opts.extraOptions.onlineConvert || {maxSize:100,showLink:true};
				if (mOpts.maxSize) {
					this.info.maxSize = mOpts.maxSize * 1048576;
				}
				this.set = Object.assign({
					url : 'https://%s.online-convert.com%s?external_url=',
					conv : {
						Archive: {'7Z':{}, 'BZ2':{ext:'bz'}, 'GZ':{}, 'ZIP':{}},
						Audio: {'MP3':{}, 'OGG':{ext:'oga'}, 'WAV':{}, 'WMA':{}, 'AAC':{}, 'AIFF':{ext:'aif'}, 'FLAC':{}, 'M4A':{}, 'MMF':{}, 'OPUS':{ext:'oga'}},
						Document: {'DOC':{}, 'DOCX':{}, 'HTML':{}, 'ODT':{}, 'PDF':{}, 'PPT':{}, 'PPTX':{}, 'RTF':{}, 'SWF':{}, 'TXT':{}},
						eBook: {'AZW3':{ext:'azw'}, 'ePub':{}, 'FB2':{ext:'xml'}, 'LIT':{}, 'LRF':{}, 'MOBI':{}, 'PDB':{}, 'PDF':{},'PDF-eBook':{ext:'pdf'}, 'TCR':{}},
						Hash: {'Adler32':{},  'Apache-htpasswd':{}, 'Blowfish':{}, 'CRC32':{}, 'CRC32B':{}, 'Gost':{}, 'Haval128':{},'MD4':{}, 'MD5':{}, 'RIPEMD128':{}, 'RIPEMD160':{}, 'SHA1':{}, 'SHA256':{}, 'SHA384':{}, 'SHA512':{}, 'Snefru':{}, 'Std-DES':{}, 'Tiger128':{}, 'Tiger128-calculator':{}, 'Tiger128-converter':{}, 'Tiger160':{}, 'Tiger192':{}, 'Whirlpool':{}},
						Image: {'BMP':{}, 'EPS':{ext:'ai'}, 'GIF':{}, 'EXR':{}, 'ICO':{}, 'JPG':{}, 'PNG':{}, 'SVG':{}, 'TGA':{}, 'TIFF':{ext:'tif'}, 'WBMP':{}, 'WebP':{}},
						Video: {'3G2':{}, '3GP':{}, 'AVI':{}, 'FLV':{}, 'HLS':{ext:'m3u8'}, 'MKV':{}, 'MOV':{}, 'MP4':{}, 'MPEG-1':{ext:'mpeg'}, 'MPEG-2':{ext:'mpeg'}, 'OGG':{ext:'ogv'}, 'OGV':{}, 'WebM':{}, 'WMV':{}, 'Android':{link:'/convert-video-for-%s',ext:'mp4'}, 'Blackberry':{link:'/convert-video-for-%s',ext:'mp4'}, 'DPG':{link:'/convert-video-for-%s',ext:'avi'}, 'iPad':{link:'/convert-video-for-%s',ext:'mp4'}, 'iPhone':{link:'/convert-video-for-%s',ext:'mp4'}, 'iPod':{link:'/convert-video-for-%s',ext:'mp4'}, 'Nintendo-3DS':{link:'/convert-video-for-%s',ext:'avi'}, 'Nintendo-DS':{link:'/convert-video-for-%s',ext:'avi'}, 'PS3':{link:'/convert-video-for-%s',ext:'mp4'}, 'Wii':{link:'/convert-video-for-%s',ext:'avi'}, 'Xbox':{link:'/convert-video-for-%s',ext:'wmv'}}
					},
					catExts : {
						Hash: 'txt'
					},
					link : '<div class="elfinder-edit-onlineconvert-link"><a href="https://www.online-convert.com" target="_blank"><span class="elfinder-button-icon"></span>ONLINE-CONVERT.COM</a></div>',
					useTabs : (jQuery.fn.tabs && !fm.UA.iOS)? true : false // Can't work on iOS, I don't know why.
				}, mOpts);
			},
			// Prepare on before show dialog
			prepare : function(base, dialogOpts, file) {
				var elfNode = base.editor.fm.getUI();
				jQuery(base).height(elfNode.height());
				dialogOpts.width = Math.max(dialogOpts.width || 0, elfNode.width() * 0.8);
			},
			// Initialization of editing node (this: this editors HTML node)
			init : function(id, file, dum, fm) {
				var ta = this,
					confObj = ta.editor.confObj,
					set = confObj.set,
					uiToast = fm.getUI('toast'),
					idxs = {},
					allowZip = fm.uploadMimeCheck('application/zip', file.phash),
					selfUrl = jQuery('base').length? document.location.href.replace(/#.*$/, '') : '',
					getExt = function(cat, con) {
						var c;
						if (set.catExts[cat]) {
							return set.catExts[cat];
						}
						if (set.conv[cat] && (c = set.conv[cat][con])) {
							return (c.ext || con).toLowerCase();
						}
						return con.toLowerCase();
					},
					setOptions = function(cat, done) {
						var type, dfdInit, dfd;
						if (typeof confObj.api === 'undefined') {
							dfdInit = fm.request({
								data: {
									cmd: 'editor',
									name: 'OnlineConvert',
									method: 'init'
								},
								preventDefault : true
							});
						} else {
							dfdInit = jQuery.Deferred().resolve({api: confObj.api});
						}
						cat = cat.toLowerCase();
						dfdInit.done(function(data) {
							confObj.api = data.api;
							if (confObj.api) {
								if (cat) {
									type = '?category=' + cat;
								} else {
									type = '';
									cat = 'all';
								}
								if (!confObj.conversions) {
									confObj.conversions = {};
								}
								if (!confObj.conversions[cat]) {
									dfd = jQuery.getJSON('https://api2.online-convert.com/conversions' + type);
								} else {
									dfd = jQuery.Deferred().resolve(confObj.conversions[cat]);
								}
								dfd.done(function(d) {
									confObj.conversions[cat] = d;
									jQuery.each(d, function(i, o) {
										btns[set.useTabs? 'children' : 'find']('.onlineconvert-category-' + o.category).children('.onlineconvert-' + o.target).trigger('makeoption', o);
									});
									done && done();
								});
							}
						});
					},
					btns = (function() {
						var btns = jQuery('<div></div>').on('click', 'button', function() {
								var b = jQuery(this),
									opts = b.data('opts') || null,
									cat = b.closest('.onlineconvert-category').data('cname'),
									con = b.data('conv');
								if (confObj.api === true) {
									api({
										category: cat,
										convert: con,
										options: opts
									});
								}
							}).on('change', function(e) {
								var t = jQuery(e.target),
									p = t.parent(), 
									b = t.closest('.elfinder-edit-onlineconvert-button').children('button:first'),
									o = b.data('opts') || {},
									v = p.data('type') === 'boolean'? t.is(':checked') : t.val();
								e.stopPropagation();
								if (v) {
									if (p.data('type') === 'integer') {
										v = parseInt(v);
									}
									if (p.data('pattern')) {
										var reg = new RegExp(p.data('pattern'));
										if (!reg.test(v)) {
											requestAnimationFrame(function() {
												fm.error('"' + fm.escape(v) + '" is not match to "/' + fm.escape(p.data('pattern')) + '/"');
											});
											v = null;
										}
									}
								}
								if (v) {
									o[t.parent().data('optkey')] = v;
								} else {
									delete o[p.data('optkey')];
								}
								b.data('opts', o);
							}),
							ul = jQuery('<ul></ul>'),
							oform = function(n, o) {
								var f = jQuery('<p></p>').data('optkey', n).data('type', o.type),
									checked = '',
									disabled = '',
									nozip = false,
									opts, btn, elm;
								if (o.description) {
									f.attr('title', fm.i18n(o.description));
								}
								if (o.pattern) {
									f.data('pattern', o.pattern);
								}
								f.append(jQuery('<span></span>').text(fm.i18n(n) + ' : '));
								if (o.type === 'boolean') {
									if (o['default'] || (nozip = (n === 'allow_multiple_outputs' && !allowZip))) {
										checked = ' checked';
										if (nozip) {
											disabled = ' disabled';
										}
										btn = this.children('button:first');
										opts = btn.data('opts') || {};
										opts[n] = true;
										btn.data('opts', opts);
									}
									f.append(jQuery('<input type="checkbox" value="true"'+checked+disabled+'/>'));
								} else if (o['enum']){
									elm = jQuery('<select></select>').append(jQuery('<option value=""></option>').text('Select...'));
									jQuery.each(o['enum'], function(i, v) {
										elm.append(jQuery('<option value="'+v+'"></option>').text(v));
									});
									f.append(elm);
								} else {
									f.append(jQuery('<input type="text" value=""/>'));
								}
								return f;
							},
							makeOption = function(o) {
								var elm = this,
									b = jQuery('<span class="elfinder-button-icon elfinder-button-icon-preference"></span>').on('click', function() {
										f.toggle();
									}),
									f = jQuery('<div class="elfinder-edit-onlinconvert-options"></div>').hide();
								if (o.options) {
									jQuery.each(o.options, function(k, v) {
										k !== 'download_password' && f.append(oform.call(elm, k, v));
									});
								}
								elm.append(b, f);
							},
							ts = (+new Date()),
							i = 0;
						
						if (!confObj.ext2mime) {
							confObj.ext2mime = Object.assign(fm.arrayFlip(fm.mimeTypes), ext2mime);
						}
						jQuery.each(set.conv, function(t, c) {
							var cname = t.toLowerCase(),
								id = 'elfinder-edit-onlineconvert-' + cname + ts,
								type = jQuery('<div id="' + id + '" class="onlineconvert-category onlineconvert-category-'+cname+'"></div>').data('cname', t),
								cext;
							jQuery.each(c, function(n, o) {
								var nl = n.toLowerCase(),
									ext = getExt(t, n);
								if (!confObj.ext2mime[ext]) {
									if (cname === 'audio' || cname === 'image' || cname === 'video') {
										confObj.ext2mime[ext] = cname + '/x-' + nl;
									} else {
										confObj.ext2mime[ext] = 'application/octet-stream';
									}
								}
								if (fm.uploadMimeCheck(confObj.ext2mime[ext], file.phash)) {
									type.append(jQuery('<div class="elfinder-edit-onlineconvert-button onlineconvert-'+nl+'"></div>').on('makeoption', function(e, data) {
										var elm = jQuery(this);
										if (!elm.children('.elfinder-button-icon-preference').length) {
											makeOption.call(elm, data);
										}
									}).append(jQuery('<button></button>').text(n).data('conv', n)));
								}
							});
							if (type.children().length) {
								ul.append(jQuery('<li></li>').append(jQuery('<a></a>').attr('href', selfUrl + '#' + id).text(t)));
								btns.append(type);
								idxs[cname] = i++;
							}
						});
						if (set.useTabs) {
							btns.prepend(ul).tabs({
								beforeActivate: function(e, ui) {
									setOptions(ui.newPanel.data('cname'));
								}
							});
						} else {
							jQuery.each(set.conv, function(t) {
								var tl = t.toLowerCase();
								btns.append(jQuery('<fieldset class="onlineconvert-fieldset-' + tl + '"></fieldset>').append(jQuery('<legend></legend>').text(t)).append(btns.children('.onlineconvert-category-' + tl)));
							});
						}
						return btns;
					})(),
					select = jQuery(this)
						.append(
							btns,
							(set.showLink? jQuery(set.link) : null)
						),
					spnr = jQuery('<div class="elfinder-edit-spinner elfinder-edit-onlineconvert"></div>')
						.hide()
						.html('<span class="elfinder-spinner-text">' + fm.i18n('nowLoading') + '</span><span class="elfinder-spinner"></span>')
						.appendTo(select.parent()),
					prog = jQuery('<div class="elfinder-quicklook-info-progress"></div>').appendTo(spnr),
					_url = null,
					url = function() {
						var onetime;
						if (_url) {
							return jQuery.Deferred().resolve(_url);
						} else {
							spnr.show();
							return fm.forExternalUrl(file.hash, { progressBar: prog }).done(function(url) {
								_url = url;
							}).fail(function(error) {
								error && fm.error(error);
								ta.elfinderdialog('destroy');
							}).always(function() {
								spnr.hide();
							});
						}
					},
					api = function(opts) {
						jQuery(ta).data('dfrd', url().done(function(url) {
							select.fadeOut();
							setStatus({info: 'Start conversion request.'});
							fm.request({
								data: {
									cmd: 'editor',
									name: 'OnlineConvert',
									method: 'api',
									'args[category]' : opts.category.toLowerCase(),
									'args[convert]'  : opts.convert.toLowerCase(),
									'args[options]'  : JSON.stringify(opts.options),
									'args[source]'   : fm.convAbsUrl(url),
									'args[filename]' : fm.splitFileExtention(file.name)[0] + '.' + getExt(opts.category, opts.convert),
									'args[mime]'     : file.mime
								},
								preventDefault : true
							}).done(function(data) {
								checkRes(data.apires, opts.category, opts.convert);
							}).fail(function(error) {
								error && fm.error(error);
								ta.elfinderdialog('destroy');
							});
						}));
					},
					checkRes = function(res, cat, con) {
						var status, err = [];
						if (res && res.id) {
							status = res.status;
							if (status.code === 'failed') {
								spnr.hide();
								if (res.errors && res.errors.length) {
									jQuery.each(res.errors, function(i, o) {
										o.message && err.push(o.message);
									});
								}
								fm.error(err.length? err : status.info);
								select.fadeIn();
							} else if (status.code === 'completed') {
								upload(res);
							} else {
								setStatus(status);
								setTimeout(function() {
									polling(res.id);
								}, 1000);
							}
						} else {
							uiToast.appendTo(ta.closest('.ui-dialog'));
							if (res.message) {
								fm.toast({
									msg: fm.i18n(res.message),
									mode: 'error',
									timeOut: 5000,
									onHidden: function() {
										uiToast.children().length === 1 && uiToast.appendTo(fm.getUI());
									}
								});
							}
							fm.toast({
								msg: fm.i18n('editorConvNoApi'),
								mode: 'error',
								timeOut: 3000,
								onHidden: function() {
									uiToast.children().length === 1 && uiToast.appendTo(fm.getUI());
								}
							});
							spnr.hide();
							select.show();
						}
					},
					setStatus = function(status) {
						spnr.show().children('.elfinder-spinner-text').text(status.info);
					},
					polling = function(jobid) {
						fm.request({
							data: {
								cmd: 'editor',
								name: 'OnlineConvert',
								method: 'api',
								'args[jobid]': jobid
							},
							preventDefault : true
						}).done(function(data) {
							checkRes(data.apires);
						}).fail(function(error) {
							error && fm.error(error);
							ta.elfinderdialog('destroy');
						});
					},
					upload = function(res) {
						var output = res.output,
							id = res.id,
							url = '';
						spnr.hide();
						if (output && output.length) {
							ta.elfinderdialog('destroy');
							jQuery.each(output, function(i, o) {
								if (o.uri) {
									url += o.uri + '\n';
								}
							});
							fm.upload({
								target: file.phash,
								files: [url],
								type: 'text',
								extraData: {
									contentSaveId: 'OnlineConvert-' + res.id
								}
							});
						}
					},
					mode = 'document',
					cl, m;
				select.parent().css({overflow: 'auto'}).addClass('overflow-scrolling-touch');
				if (m = file.mime.match(/^(audio|image|video)/)) {
					mode = m[1];
				}
				if (set.useTabs) {
					if (idxs[mode]) {
						btns.tabs('option', 'active', idxs[mode]);
					}
				} else {
					cl = Object.keys(set.conv).length;
					jQuery.each(set.conv, function(t) {
						if (t.toLowerCase() === mode) {
							setOptions(t, function() {
								jQuery.each(set.conv, function(t0) {
									t0.toLowerCase() !== mode && setOptions(t0);
								});
							});
							return false;
						}
						cl--;
					});
					if (!cl) {
						jQuery.each(set.conv, function(t) {
							setOptions(t);
						});
					}
					select.parent().scrollTop(btns.children('.onlineconvert-fieldset-' + mode).offset().top);
				}
			},
			load : function() {},
			getContent : function() {},
			save : function() {},
			// On dialog closed
			close : function(ta) {
				var fm = this.fm,
					dfrd = jQuery(ta).data('dfrd');
				if (dfrd && dfrd.state() === 'pending') {
					dfrd.reject();
				}
			}
		}
	];
}, window.elFinder));

Youez - 2016 - github.com/yon3zu
LinuXploit