docs: function(ql) {
  				var fm      = ql.fm,
  			mimes   = Object.assign(fm.arrayFlip(ql.options.googleDocsMimes || [], 'g'), fm.arrayFlip(ql.options.officeOnlineMimes || [], 'm')),
  			preview = ql.preview,
  			win     = ql.window,
  			navi    = ql.navbar,
  			urls    = {
  				g: 'docs.google.com/gview?embedded=true&url=',
  				m: 'view.officeapps.live.com/op/embed.aspx?wdStartOn=0&src='
  			},
  			navBottom = {
  				g: '56px',
  				m: '24px'
  			},
  			mLimits = {
  				xls  : 5242880, // 5MB
  				xlsb : 5242880,
  				xlsx : 5242880,
  				xlsm : 5242880,
  				other: 10485760 // 10MB
  			},
  			node;
  		
  		if (ql.options.googleDocsMimes.length) {
  			ql.addIntegration({
  				title: 'Google Docs Viewer',
  				link: 'https://docs.google.com/'
  			});
  		}
  		if (ql.options.officeOnlineMimes.length) {
  			ql.addIntegration({
  				title: 'MS Online Doc Viewer',
  				link: 'https://products.office.com/office-online/view-office-documents-online'
  			});
  		}
  
  
  		preview.on(ql.evUpdate, function(e) {
  			var file = e.file,
  				type;
  			// 25MB is maximum filesize of Google Docs prevew
  			if (file.size <= 26214400 && (type = mimes[file.mime])) {
  				var win     = ql.window,
  					setNavi = function() {
  						navi.css('bottom', win.hasClass('elfinder-quicklook-fullscreen')? navBottom[type] : '');
  					},
  					ext     = fm.mimeTypes[file.mime],
  					loading, url;
  				
  				if (type === 'm') {
  					if ((mLimits[ext] && file.size > mLimits[ext]) || file.size > mLimits.other) {
  						type = 'g';
  					}
  				}
  				if (file.url == '1') {
  					preview.hide();
  					$('<div class="elfinder-quicklook-info-data"><button class="elfinder-info-button">'+fm.i18n('getLink')+'</button></div>').appendTo(ql.info.find('.elfinder-quicklook-info'))
  					.on('click', function() {
  						var self = $(this);
  						self.html('<span class="elfinder-info-spinner">');
  						fm.request({
  							data : {cmd : 'url', target : file.hash},
  							preventDefault : true
  						})
  						.always(function() {
  							self.html('');
  						})
  						.done(function(data) {
  							var rfile = fm.file(file.hash);
  							file.url = rfile.url = data.url || '';
  							if (file.url) {
  								preview.trigger({
  									type: ql.evUpdate,
  									file: file,
  									forceUpdate: true
  								});
  							}
  						});
  					});
  				}
  				if (file.url !== '' && file.url != '1') {
  					e.stopImmediatePropagation();
  					preview.one('change', function() {
  						win.off('viewchange.googledocs');
  						loading.remove();
  						node.off('load').remove();
  						node = null;
  					}).addClass('elfinder-overflow-auto');
  					
  					loading = $('<div class="elfinder-quicklook-info-data"> '+fm.i18n('nowLoading')+'<span class="elfinder-info-spinner"></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
  					
  					url = fm.convAbsUrl(fm.url(file.hash));
  					if (file.ts) {
  						url += (url.match(/\?/)? '&' : '?') + '_t=' + file.ts;
  					}
  					node = $('<iframe class="elfinder-quicklook-preview-iframe"/>')
  						.css('background-color', 'transparent')
  						.appendTo(preview)
  						.on('load', function() {
  							ql.hideinfo();
  							loading.remove();
  							ql.preview.after(ql.info);
  							$(this).css('background-color', '#fff').show();
  						})
  						.on('error', function() {
  							loading.remove();
  							ql.preview.after(ql.info);
  						})
  						.attr('src', 'https://' + urls[type] + encodeURIComponent(url));
  					
  					win.on('viewchange.googledocs', setNavi);
  					setNavi();
  					ql.info.after(ql.preview);
  				}
  			}
  			
  		});
  	}