docs: function(id, file, dum, fm) {
  				var ta = this,
  					confObj = ta.editor.confObj,
  					set = confObj.set,
  					idxs = {},
  					allowZip = fm.uploadMimeCheck('application/zip', file.phash),
  					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();
  					},
  					btns = (function() {
  						var btns = $('<div/>').on('click', 'button', function() {
  								var b = $(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
  									});
  								} else {
  									open(cat, con);
  								}
  							}).on('change', function(e) {
  								var t = $(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 = $('<ul/>'),
  							oform = function(n, o) {
  								var f = $('<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($('<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($('<input type="checkbox" value="true"'+checked+disabled+'/>'));
  								} else if (o.enum){
  									elm = $('<select/>').append($('<option value=""/>').text('Select...'));
  									$.each(o.enum, function(i, v) {
  										elm.append($('<option value="'+v+'"/>').text(v));
  									});
  									f.append(elm);
  								} else {
  									f.append($('<input type="text" value=""/>'));
  								}
  								return f;
  							},
  							makeOption = function(o) {
  								var elm = this,
  									b = $('<span class="elfinder-button-icon elfinder-button-icon-preference"/>').on('click', function() {
  										f.toggle();
  									}),
  									f = $('<div class="elfinder-edit-onlinconvert-options"/>').hide();
  								if (o.options) {
  									$.each(o.options, function(k, v) {
  										k !== 'download_password' && f.append(oform.call(elm, k, v));
  									});
  								}
  								elm.append(b, f);
  							},
  							setOptions = function(cat) {
  								var type, dfdInit, dfd;
  								if (typeof confObj.api === 'undefined') {
  									dfdInit = fm.request({
  										data: {
  											cmd: 'editor',
  											name: 'OnlineConvert',
  											method: 'init'
  										},
  										preventDefault : true
  									});
  								} else {
  									dfdInit = $.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 = $.getJSON('https://api2.online-convert.com/conversions' + type);
  										} else {
  											dfd = $.Deferred().resolve(confObj.conversions[cat]);
  										}
  										dfd.done(function(d) {
  											confObj.conversions[cat] = d;
  											$.each(d, function(i, o) {
  												btns[set.useTabs? 'children' : 'find']('.onlineconvert-category-' + o.category).children('.onlineconvert-' + o.target).trigger('makeoption', o);
  											});
  										});
  									}
  								});
  							},
  							ts = (+new Date()),
  							i = 0;
  						
  						if (!confObj.ext2mime) {
  							confObj.ext2mime = fm.arrayFlip(fm.mimeTypes);
  						}
  						$.each(set.conv, function(t, c) {
  							var cname = t.toLowerCase(),
  								id = 'elfinder-edit-onlineconvert-' + cname + ts,
  								type = $('<div id="' + id + '" class="onlineconvert-category onlineconvert-category-'+cname+'"/>').data('cname', t),
  								cext;
  							$.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($('<div class="elfinder-edit-onlineconvert-button onlineconvert-'+nl+'"/>').on('makeoption', function(e, data) {
  										var elm = $(this);
  										if (!elm.children('.elfinder-button-icon-preference').length) {
  											makeOption.call(elm, data);
  										}
  									}).append($('<button/>').text(n).data('conv', n)));
  								}
  							});
  							if (type.children().length) {
  								ul.append($('<li/>').append($('<a/>').attr('href', '#' + 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 {
  							$.each(set.conv, function(t) {
  								btns.append($('<fieldset/>').append($('<legend/>').text(t)).append(btns.children('.onlineconvert-category-' + t.toLowerCase())));
  								setOptions(t);
  							});
  						}
  						return btns;
  					})(),
  					ifm = $(this).hide(),
  					select = $('<div/>')
  						.append(
  							btns,
  							$('<div class="elfinder-edit-onlineconvert-bottom-btn"/>').append($('<button/>').html(fm.i18n('convertOn', 'Online-Convert.com')).on('click', function() {
  								open();
  							})),
  							(set.showLink? $(set.link) : null)
  						)
  						.appendTo(ifm.parent().css({overflow: 'auto'})),
  					spnr = $('<div class="elfinder-edit-spiner elfinder-edit-online-convert"/>')
  						.hide()
  						.css({
  							position: 'absolute',
  							top: '50%',
  							textAlign: 'center',
  							width: '100%',
  							fontSize: '16pt'
  						})
  						.html('<span class="elfinder-edit-loadingmsg">' + fm.i18n('nowLoading') + '</span><span class="elfinder-spinner"/>')
  						.appendTo(ifm.parent()),
  					_url = null,
  					url = function() {
  						if (_url) {
  							return $.Deferred().resolve(_url);
  						} else {
  							spnr.show();
  							return fm.url(file.hash, {
  								async: true,
  								temporary: true
  							}).done(function(url) {
  								_url = url;
  							}).fail(function(error) {
  								error && fm.error(error);
  								ta.elfinderdialog('destroy');
  							}).always(function() {
  								spnr.hide();
  							});
  						}
  					},
  					api = function(opts) {
  						$(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)
  								},
  								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) {
  									$.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.output);
  							} else {
  								setStatus(status);
  								setTimeout(function() {
  									polling(res.id);
  								}, 1000);
  							}
  						} else {
  							if (res.message) {
  								fm.toast({
  									msg: fm.i18n(res.message),
  									mode: 'error',
  									timeOut: 5000,
  									width: set.toastWidth
  								});
  							}
  							fm.toast({
  								msg: fm.i18n('editorConvNoApi'),
  								mode: 'warning',
  								timeOut: 3000,
  								width: set.toastWidth,
  								onHidden: function() {
  									open(cat, con);
  								}
  							});
  						}
  					},
  					setStatus = function(status) {
  						spnr.show().children('.elfinder-edit-loadingmsg').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(output) {
  						var url = '';
  						spnr.hide();
  						if (output && output.length) {
  							ta.elfinderdialog('destroy');
  							$.each(output, function(i, o) {
  								if (o.uri) {
  									url += o.uri + '\n';
  								}
  							});
  							fm.upload({
  								target: file.phash,
  								files: [url],
  								type: 'text'
  							});
  						}
  					},
  					open = function(cat, con) {
  						var link;
  						if (cat && con) {
  							if (set.conv[cat] && set.conv[cat][con] && set.conv[cat][con].link) {
  								link = set.conv[cat][con].link.replace('%s', con);
  							} else {
  								link = cat === 'hash'? ('/' + con + '-generator') : ('/convert-to-' + con);
  							}
  							link = set.url.replace('%s', cat).replace('%s', link);
  						} else {
  							link = set.url.replace('%s', mode + '-conversion').replace('%s', '');
  						}
  						spnr.hide();
  						select.hide();
  						ifm.parent().css({overflow: 'hidden'});
  						$(ta).data('dfrd', url().done(function(url) {
  							var opts;
  							if (url) {
  								fm.toast({
  									msg: fm.i18n('editorConvNeedUpload'),
  									mode: 'info',
  									timeOut: 5000,
  									width: set.toastWidth
  								});
  								opts = {
  									css: {
  										height: '100%'
  									}
  								};
  								// trigger event 'editEditorPrepare'
  								ta.editor.trigger('Prepare', {
  									node: ta,
  									editorObj: void(0),
  									instance: ifm,
  									opts: opts
  								});
  
  								url = encodeURIComponent(fm.convAbsUrl(url));
  								// need `.replace(/%2520/g, '%252520')` for a bug of online-convert.com
  								if (set['fix%20']) {
  									url = url.replace(/%2520/g, '%252520');
  								}
  								url = link + url;
  								ifm.attr('src', url).show().css(opts.css);
  							} else {
  								data.error && fm.error(data.error);
  								ta.elfinderdialog('destroy');
  							}
  						}));
  					},
  					mode = 'document',
  					m;
  				if (m = file.mime.match(/^(audio|image|video)/)) {
  					mode = m[1];
  				}
  				if (set.useTabs && idxs[mode]) {
  					btns.tabs('option', 'active', idxs[mode]);
  				}
  			}