PageSourceSearch

https://portal.jumbotech.co.za/assets/js/popup.min.js?v=31b13096902d41a4b739aa3373d5f7d8

js jumbotech.co.za collected 2026-10-08 17:31:47 UTC 28,776 bytes, 578 lines download raw bytes

1;
2(function($) {
3	var isWebkit = 'WebkitAppearance' in document.documentElement.style;
4	$.fn.showLoading = function(msg) {
5		var loadingText = msg || 'Loading please wait..';
6		return this.addClass('ajax-loading').append('<span class="ajax-loading-text">'+loadingText+'</span>');
7	};
8	$.fn.hideLoading = function() {
9		return this.removeClass('ajax-loading').find('.ajax-loading-text').remove();
10	};
11	var testDiv;
12	$.htmlSpecialChars = function(str) {
13		if (!testDiv) testDiv = $(document.createElement("div"));
14		return testDiv.text(str)[0].innerHTML;
15	};
16	$.fn.popup = function(data) {
17		return this.each(function() {
18			var self = $(this),
19				api = self.data('popup');
20			if (self.hasClass('popup') && api) {
21				if (data == 'show') self.show().trigger('shown');
22				if (data == 'hide') self.trigger('hide').hide().trigger('hidden');
23			}
24		});
25	};
26	var initPopupResize = false;
27	$.popup = function(data) {
28		var id = +new Date(),
29			scroll = $('<div class="popup-scrollable" data-popup-id="' + id + '" ></div>'),
30			backdrop = $('<div class="popup-backdrop" data-popup-id="' + id + '" ></div>'),
31			popup = $(['<div class="popup ' + (data.cls || '') + '" style="' + (data.width ? 'width:' + data.width : '') + ';" >', '<div class="popup-header" ></div>', '<div class="popup-body" ></div>', '<div class="popup-footer" ></div>'].join(''));
32		popup.data('popup-id', id);
33		$('.popup-hidden').trigger('popup.hidden').each(function() {
34			var api = $(this).data('popup');
35			if (api) {
36				api.popup.remove();
37				api.backdrop.remove();
38				api.scroll.remove();
39				popup.data('popup', null);
40			}
41		});
42		data = $.extend(data || {}, {
43			scroll: scroll,
44			backdrop: backdrop,
45			popup: popup
46		}, true);
47		popup.data('popup', data);
48		data.showParent = function(parent) {
49			var self = popup,
50				api, parentData;
51			while (self) {
52				if (self[0] && self[0] == parent[0]) break;
53				api = $(self).data('popup');
54				if (api) {
55					parentData = api.parent;
56					api.child = null;
57					api.parent = null;
58					self.popup('hide');
59					self = parentData;
60				} else {
61					api = null;
62					self = null;
63				}
64			}
65			if (!self) return;
66			parentData = $(parent).data('popup');
67			if (parentData) {
68				parentData.child = null;
69				parent.popup('show');
70			}
71		};
72		popup.on('shown', function(e) {
73			backdrop.show();
74			scroll.show();
75			var header = popup.find('.popup-header'),
76				close = header.find('.popup-close');
77		});
78		popup.on('hide', function(e) {
79			backdrop.hide();
80			scroll.hide();
81			if ($.isFunction(data.hide) && data.hide(popup) === false) {
82				e.preventDefault();
83				return;
84			}
85		});
86		popup.on('hidden', function(e) {
87			var parent = data.parent,
88				api;
89			if (data.child) return;
90			if (data.parent) {
91				if (data.destroy === true) while (parent) {
92					api = $(parent).addClass('popup-hidden').data('popup');
93					if (api) parent = api.parent;
94					else parent = null;
95				} else {
96					$(data.parent).data('popup').child = null;
97					var parentData = $(data.parent).data('popup');
98					$(data.parent).on('shown.load-popup-scroll', function() {
99						var self = $(this),
100							scroll = self.data('popup-scrolltop');
101						if (scroll) self.closest('.popup-scrollable').scrollTop(scroll);
102						self.off('shown.load-popup-scroll');
103					});
104					$(data.parent).popup('show');
105					popup.remove();
106					backdrop.remove();
107					scroll.remove();
108					popup.data('popup', null);
109				}
110			} else {
111				backdrop.hide();
112				scroll.hide();
113			}
114			if (!data.cache) popup.addClass('popup-hidden');
115		});
116		if (data.parent) {
117			$(data.parent).data('popup-scrolltop', $(data.parent).closest('.popup-scrollable').scrollTop());
118			$(data.parent).data('popup').child = popup;
119			$(data.parent).popup('hide');
120		}
121		backdrop.appendTo('body');
122		popup.appendTo(scroll);
123		scroll.appendTo('body');
124		if (data.href) {
125			popup.showLoading();
126			$.ajax({
127				method: data.method || 'get',
128				url: data.href,
129				success: function(html) {
130					if (!$.trim(html).length) return popup.popup('hide');
131					popup.hideLoading();
132					popup.empty().append(html);
133					if (!popup.find('.popup-body').length) {
134						debug.error('No Length');
135						return popup.popup('hide');
136					}
137					if ($.isFunction(data.load)) data.load(popup);
138					popup.popup('show');
139				},
140				dataType: 'html',
141				error: function() {
142					popup.popup('hide');
143				}
144			});
145		} else {
146			popup.find('.popup-header').append(data.header || '').prepend(data.closable == false ? '' : '<a class="popup-close" data-dismiss="popup" aria-hidden="true"><i class="fa fa-remove" ></i></a>');
147			popup.find('.popup-footer').append(data.footer || '');
148			popup.find('.popup-body').append(data.body || '');
149			if ($.isFunction(data.load)) data.load(popup);
150			popup.popup('show');
151		}
152		return popup;
153	};
154	$.fn.fileUploader = function(options) {
155		var ret = this;
156		this.each(function(index) {
157			if (!$(this).is(':file')) return;
158			var self, original, data, widget, opt = $.isPlainObject(options) ? $.extend({}, options, true) : {};
159			self = $(this);
160			if (self.data('fileuploader')) {
161				widget = self.closest('.fileuploader');
162				self.data('fileuploader', null).off('change.fileuploader').insertAfter(widget);
163				widget.remove();
164			}
165			widget = $(['<div class="fileuploader" >', '<div class="fileuploader-buttons" >', '<span class="btn btn-primary btn-file pull-left"><span class="fileupload-new">Select File</span></span>', '<span class="btn fileupload-remove pull-left hide">Undo</span>', '<div class="clearfix" ></div>', '</div>', '<div class="fileuploader-preview" ></div>', '</div>'].join(''));
166			data = {
167				hasFile: function() {
168					return widget.find('.fileuploader-preview').children().length > 0 && !widget.find('.fileuploader-original').length;
169				},
170				setFile: function(file) {
171					var preview = widget.find('.fileuploader-preview').html(['<div class="fileuploader-plain" >', '<span class="fileuploader-icon ext-icon ext-icon-' + (file.file_extension || '').toLowerCase() + '" ></span>', '<span class="fileuploader-text" >', '<strong>', $.htmlSpecialChars(file.file_name || ''), '</strong>', '(', $.htmlSpecialChars(file.file_mime_type || 'n/a'), ') ', ' - ', bytes(file.file_size, true), ', last modified: ', file.file_last_modified, '</sp
171an>', '</div>'].join('')),
172						width = preview.width();
173					if (file.file_mime_type.substr(0, 6) == 'image/') {
174						var wrap = $('<span class="fileuploader-image" ></span>').prependTo(preview).showLoading();
175						$('<img src="' + datatill.url('files/output_file/' + file.file_id) + '" style="visibility:visible;max-width:100%;" />').load(function() {
176							wrap.hideLoading();
177						}).prependTo(wrap);
178					}
179					original = preview.children();
180					return this;
181				},
182				showInput: function() {
183					self.show();
184					widget.find('.btn-file').append(self);
185				},
186				hideInput: function() {
187					self.detach();
188				},
189				setError: function(error) {
190					widget.append('<span class="error-text help-block text-danger" >' + $.htmlSpecialChars(error) + '</span>');
191				}
192			};
193			self.replaceWith(widget).data('fileuploader', data);
194			widget.find('.fileupload-remove').click(function() {
195				var preview = widget.find('.fileuploader-preview').empty();
196				if (original && original.length) preview.append(original);
197				$(this).hide();
198			});
199			if (opt.file) data.setFile(opt.file);
200			self.on('change.fileuploader', function(e) {
201				if (window.File && window.FileReader && window.FileList && window.Blob && !isWebkit) {
202					var file = e.target.files[0],
203						val, ext, reader, preview, img, width = 0,
204						dt;
205					if (file) {
206						dt = file.lastModifiedDate;
207						val = ['<strong>', $.htmlSpecialChars(file.name), '</strong>', '(', $.htmlSpecialChars(file.type || 'n/a'), ') ', ' - ', bytes(file.size, true), ', last modified: ', dt ? [dt.getFullYear(), '-', dt.getMonth(), '-', dt.getDate(), ' ', dt.getHours(), ':', dt.getMinutes(), ':', dt.getSeconds()].join('') : 'n/a'].join('');
208						ext = (file.name || '').split('.').pop().toLowerCase();
209						if ((file.type && file.type.substr(0, 6) == 'image/')) {
210							widget.find('.fileuploader-preview').html(['<span class="fileuploader-image" ></span>', '<div class="fileuploader-plain file-uploader-original" >', '<span class="fileuploader-icon ext-icon ext-icon-' + ext + '" ></span>', '<span class="fileuploader-text" >' + val + '</span>', '</div>'].join(''));
211							preview = widget.find('.fileuploader-image');
212							width = preview.width();
213							var reader = new FileReader();
214							reader.onload = function(e) {
215								img = $('<img src="' + e.target.result + '" style="visibility:hidden;" />').load(function() {
216									var w = $(this).width();
217									$(this).css('visibility', 'visible');
218									if (w > width) $(this).width(width);
219								}).appendTo(preview);
220							};
221							reader.readAsDataURL(file);
222						} else widget.find('.fileuploader-preview').html(['<div class="fileuploader-plain" >', '<span class="fileuploader-icon ext-icon ext-icon-' + ext + '" ></span>', '<span class="fileuploader-text" >' + val + '</span>', '</div>'].join(''));
223					}
224				} else {
225					val = self.val() + '', ext = val.split('.').pop().toLowerCase();
226					widget.find('.fileuploader-preview').html(['<div class="fileuploader-plain" >', '<span class="fileuploader-icon ext-icon ext-icon-' + ext + '" ></span>', '<span class="fileuploader-text" >' + val + '</span>', '</div>'].join(''));
227				}
228				widget.find('.fileupload-remove').show();
229			});
230			data.showInput();
231		});
232		return ret;
233	};
234	$.uploadModal = function(config) {
235		config = config || {};
236		if (!config.file_id) delete config.file_id;
237		var url = datatill.url('files/upload_file/' + (config.file_id || 0) + '/' + (config.thumb || 0)),
238			name = 'file_upload_frame_' + (+new Date()),
239			popup = $.popup({
240				header: '<h4><i class="icon-file" ></i> File</h4>',
241				body: [
242					'<form method="post" enctype="multipart/form-data" target="' + name + '" action="' + url + '" >',
243						'<div class="fileupload fileupload-new" data-provides="fileupload">', config.info ||
244							'<div class="well" >',
245								'<input type="file" name="file_upload" style="display:none;" />',
246								'<hr style="margin-top: 5px; margin-bottom: 5px;">',
247								'<div class="input-group center-block">',
248									'<label style="display:none;">Name</label>',
249									'<input style="display:none;" type="text" name="file_upload[file_name]" class="form-control input-lg" value="file">',
250								'</div>',
251								'<div class="input-group center-block">',
252									'<label style="display:none">Description</label>',
253									'<textarea name="file_upload[file_caption]" class="form-control input-lg" style="resize:none;" rows=2 ></textarea>',
254								'</div>',
255								'<div class="clearfix"></div>',
256							'</div>',
257						'</div>',
258					'</form>'
259					].join(''),
260				footer: ['<a class="btn btn-inverse pull-left" data-dismiss="popup" ><i class="icon icon-remove icon-white"></i> Close</a>', '<a class="btn btn-info pull-right btn-save-file" style="display:none;"  data-loading-text="Saving..." >Save <i class="icon icon-chevron-right icon-white"></i></a>'].join(''),
261				parent: config.parent,
262				load: function(popup) {
263					popup.showLoading();
264					var init = false,
265						btn = popup.find('.btn-save-file').click(function() {
266							form.submit();
267						}),
268						fileInput = popup.find(':file'),
269						fileUploader, form = popup.find('form').submit(function() {
270							fileUploader = fileInput.data('fileuploader');
271							if (!fileUploader.hasFile()) fileUploader.hideInput();
272							btn.button('loading');
273						});
274					var frame = $('<iframe name="' + name + '" src="' + url + '" style="display:none;" />').load(function() {
275						var win = this.contentWindow,
276							data = win.data,
277							abort = false,
278							resetFile = true;
279						if (!$.isPlainObject(data)) data = {};
280						if (!init) {
281							init = true;
282							popup.hideLoading();
283							if (data.file_upload) {
284								resetFile = false;
285								fileInput.fileUploader({
286									file: data.file_upload
287								});
288								form.append('<input type="hidden" value="' + $.htmlSpecialChars(data.file_upload.file_id) + '" name="file_upload[file_id]" />');
289							} else {
290								fileInput.fileUploader();
291								form.append('<input type="hidden" value="' + $.htmlSpecialChars(config.file_relation || '') + '" name="file_upload[file_relation]" />');
292								form.append('<input type="hidden" value="' + $.htmlSpecialChars(config.file_relation_id || 0) + '" name="file_upload[file_relation_id]" />');
293							}
294						} else if (fileUploader) fileUploader.showInput();
295						if ($.isFunction(config.load)) config.load(data, popup);
296						if ($.isFunction(config.save) && data.upload_id) abort = config.save(data, popup);
297						if (abort === true) return;
298						form.find('.error-text').remove();
299						if (data.errors && !$.isEmptyObject(data.errors)) {
300							$.each(data.errors, function(key, val) {
301								var input = form.find('[name="' + key + '"]'),
302									type = input.attr('type');
303								if (type && type.toUpperCase() == 'FILE') {
304									if (fileUploader) fileUploader.setError(val);
305								} else if (input.length) $('<span class="error-text help-block text-danger" >' + val + '</span>').insertAfter(input);
306							});
307							form.prepend('<div class="error-text alert alert-danger" >Errors have occured</div>');
308							popup.closest('.popup-scrollable').scrollTop(0);
309						}
310						if (data.file_upload) {
311							if (resetFile) fileInput.data('fileuploader').setFile(data.file_upload);
312							$.each(data.file_upload, function(key, val) {
313								var input = form.find('[name="file_upload[' + key + ']"]');
314								if (!input.length) form.append('<input type="hidden" name="file_upload[' + key + ']" value="' + $.htmlSpecialChars(val) + '" />');
315								else input.val($.htmlSpecialChars(val));
316							});
317							var prev = popup.find('textarea[name="file_upload[file_caption]"]');
318							popup.find('.btn-download-file').remove();
319							$('<hr/><a class="btn btn-charcoal pull-right btn-download-file" style="margin-top: 10px; margin-bottom: -10px;" ><i class="fa fa-download "></i>&nbsp;Download </a><div class="clearfix" ></div>').insertAfter(prev);
320							popup.find('.btn-download-file').click(function(e) {
321								e.preventDefault();
322								window.open(datatill.url('files/output_file/' + data.file_upload.id + '/download'), '_blank');
323							});
324							popup.find('.btn-delete-file').remove();
325							$('<a class="btn  btn-danger pull-right btn-delete-file"  ><i class="icon icon-trash icon-white "></i>&nbsp; Delete </a>').click(function(e) {
326								e.preventDefault();
327								$.popup({
328									parent: popup,
329									header: '<h4>Confirm</h4>',
330									body: '<div class="alert alert-danger"><strong>Are you sure you want to delete this file?</strong></div>',
331									footer: ['<a class="btn btn-inverse pull-left" data-dismiss="popup" ><i class="icon icon-remove icon-white"></i> Close</a>', '<a class="btn btn-danger pull-right btn-delete-file"  data-loading-text="Deleting..." ><i class="icon icon-trash icon-white"></i>&nbsp; Delete</a>'].join(''),
332									load: function(delete_popup) {
333										delete_popup.find('.btn-delete-file').click(function(e) {
334											var file_id = data.file_upload.id;
335											e.preventDefault();
336											$.post(datatill.url('files/delete_file'), {
337												file_id: file_id
338											}, function() {
339												var api = delete_popup.data('popup'),
340													parent = api.parent,
341													parentApi = $(parent).data('popup');
342												if (parentApi.parent) {
343													delete_popup.data('popup').showParent(popup.data('popup').parent);
344													if ($.isFunction(config.remove)) config.remove(file_id);
345												} else {
346													if (api) api.destroy = true;
347													delete_popup.popup('hide');
348													if ($.isFunction(config.remove)) config.remove(file_id);
349												}
350												if ($.isFunction(load_pics)) load_pics();
351											}, 'json');
352										});
353									}
354								});
355							}).appendTo(popup.find('.popup-footer'));
356						}
357						btn.show().button('reset');
358					}).prependTo('body');
359					popup.on('popup.hidden', function() {
360						frame.remove();
361					});
362				}
363			});
364	};
365    $.fn.fileUploaderDynamic = function(options) {
366        var ret = this;
367        this.each(function(index) {
368            if (!$(this).is(':file')) return;
369            var self, original, data, widget, opt = $.isPlainObject(options) ? $.extend({}, options, true) : {};
370            self = $(this);
371            if (self.data('fileUploader')) {
372                widget = self.closest('.fileuploader');
373                self.data('fileuploader', null).off('change.fileuploader').insertAfter(widget);
374                widget.remove();
375            }
376            widget = $(['<div class="fileuploader" >', '<div class="fileuploader-buttons" >','<span class="btn fileupload-remove pull-left hide">Undo</span>', '<div class="clearfix" ></div>', '</div>', '<div class="fileuploader-preview" ></div>', '</div>'].join(''));
377            data = {
378                hasFile: function() {
379                    return widget.find('.fileuploader-preview').children().length > 0 && !widget.find('.fileuploader-original').length;
380                },
381                setFile: function(file) {
382                    var preview = widget.find('.fileuploader-preview').html(['<div class="fileuploader-plain" >', '<span class="fileuploader-icon ext-icon ext-icon-' + (file.file_extension || '').toLowerCase() + '" ></span>', '<span class="fileuploader-text" >', '<strong>', $.htmlSpecialChars(file.file_name || ''), '</strong>', '(', $.htmlSpecialChars(file.file_mime_type || 'n/a'), ') ', ' - ', bytes(file.file_size, true), ', last modified: ', file.file_last_modified, '</sp
382an>', '</div>'].join('')),
383                        width = preview.width();
384                    if (file.file_mime_type.substr(0, 6) == 'image/') {
385                        var wrap = $('<span class="fileuploader-image" ></span>').prependTo(preview).showLoading();
386                        $('<img src="' + datatill.url('files/output/' + file.id+'/view') + '" style="visibility:visible;max-width:100%;" />').load(function() {
387                            wrap.hideLoading();
388                        }).prependTo(wrap);
389                    }
390                    original = preview.children();
391                    return this;
392                },
393                showInput: function() {
394                    self.show();
395                    widget.find('.btn-file').append(self);
396                },
397                hideInput: function() {
398                    self.detach();
399                },
400                setError: function(error) {
401                    widget.append('<span class="error-text help-block text-danger" >' + $.htmlSpecialChars(error) + '</span>');
402                }
403            };
404            self.replaceWith(widget).data('fileuploader', data);
405            widget.find('.fileupload-remove').click(function() {
406                var preview = widget.find('.fileuploader-preview').empty();
407                if (original && original.length) preview.append(original);
408                $(this).hide();
409            });
410            if (opt.file) data.setFile(opt.file);
411            self.on('change.fileuploader', function(e) {
412                if (window.File && window.FileReader && window.FileList && window.Blob && !isWebkit) {
413                    var file = e.target.files[0],
414                        val, ext, reader, preview, img, width = 0,
415                        dt;
416                    if (file) {
417                        dt = file.lastModifiedDate;
418                        val = ['<strong>', $.htmlSpecialChars(file.name), '</strong>', '(', $.htmlSpecialChars(file.type || 'n/a'), ') ', ' - ', bytes(file.size, true), ', last modified: ', dt ? [dt.getFullYear(), '-', dt.getMonth(), '-', dt.getDate(), ' ', dt.getHours(), ':', dt.getMinutes(), ':', dt.getSeconds()].join('') : 'n/a'].join('');
419                        ext = (file.name || '').split('.').pop().toLowerCase();
420                        if ((file.type && file.type.substr(0, 6) == 'image/')) {
421                            widget.find('.fileuploader-preview').html(['<span class="fileuploader-image" ></span>', '<div class="fileuploader-plain file-uploader-original" >', '<span class="fileuploader-icon ext-icon ext-icon-' + ext + '" ></span>', '<span class="fileuploader-text" >' + val + '</span>', '</div>'].join(''));
422                            preview = widget.find('.fileuploader-image');
423                            width = preview.width();
424                            var reader = new FileReader();
425                            reader.onload = function(e) {
426                                img = $('<img src="' + e.target.result + '" style="visibility:hidden;" />').load(function() {
427                                    var w = $(this).width();
428                                    $(this).css('visibility', 'visible');
429                                    if (w > width) $(this).width(width);
430                                }).appendTo(preview);
431                            };
432                            reader.readAsDataURL(file);
433                        } else widget.find('.fileuploader-preview').html(['<div class="fileuploader-plain" >', '<span class="fileuploader-icon ext-icon ext-icon-' + ext + '" ></span>', '<span class="fileuploader-text" >' + val + '</span>', '</div>'].join(''));
434                    }
435                } else {
436                    val = self.val() + '', ext = val.split('.').pop().toLowerCase();
437                    widget.find('.fileuploader-preview').html(['<div class="fileuploader-plain" >', '<span class="fileuploader-icon ext-icon ext-icon-' + ext + '" ></span>', '<span class="fileuploader-text" >' + val + '</span>', '</div>'].join(''));
438                }
439                widget.find('.fileupload-remove').show();
440            });
441            data.showInput();
442        });
443        return ret;
444    };
445    $.uploadModalDynamic = function(config) {
446        config = config || {};
447        //if (!config.file_id) delete config.file_id;
448        var url = datatill.url('files/upload_file_dynamic/' + (config.file_id || 0) + '/' + (config.thumb || 0)),
449		name = 'file_upload_frame_' + (+new Date()),
450		popup = $.popup({
451			header: '<h4><i class="icon-file" ></i> File</h4>',
452			body: [
453				'<form method="post" enctype="multipart/form-data" target="' + name + '" action="' + url + '" >',
454				'<div class="fileupload fileupload-new" data-provides="fileupload">', config.info ||
455				'<div class="well" >',
456				'<input type="file" name="file_upload" style="display:none;" />',
457				'<hr style="margin-top: 5px; margin-bottom: 5px;">',
458				'<div class="input-group center-block">',
459				'<label style="display:none;">Name</label>',
460				'<input style="display:none;" type="text" name="file_upload[file_name]" class="form-control input-lg" value="file">',
461				'</div>',
462				'<div class="input-group center-block">',
463				'<label style="display:none">Description</label>',
464				'<textarea name="file_upload[file_caption]" class="form-control input-lg" style="resize:none;" rows=2 ></textarea>',
465				'</div>',
466				'<div class="clearfix"></div>',
467				'</div>',
468				'</div>',
469				'</form>'
470			].join(''),
471			footer: ['<a class="btn btn-inverse pull-left" data-dismiss="popup" ><i class="icon icon-remove icon-white"></i> Close</a>', '<a class="btn btn-info pull-right btn-save-file" style="display:none;"  data-loading-text="Saving..." >Save <i class="icon icon-chevron-right icon-white"></i></a>'].join(''),
472			parent: config.parent,
473			load: function(popup) {
474				popup.showLoading();
475				var init = false,
476					btn = popup.find('.btn-save-file').click(function() {
477						form.submit();
478					}),
479					fileInput = popup.find(':file'),
480					fileUploaderDynamic, form = popup.find('form').submit(function() {
481						fileUploaderDynamic = fileInput.data('fileuploader');
482						if (!fileUploaderDynamic.hasFile()) fileUploaderDynamic.hideInput();
483						btn.button('loading');
484					});
485				var frame = $('<iframe name="' + name + '" src="' + url + '" style="display:none;" />').load(function() {
486					var win = this.contentWindow,
487						data = win.data,
488						abort = false,
489						resetFile = true;
490					if (!$.isPlainObject(data)) data = {};
491					if (!init) {
492						init = true;
493						popup.hideLoading();
494						if (data.file_upload) {
495							resetFile = false;
496							fileInput.fileUploaderDynamic({
497								file: data.file_upload
498							});
499							form.append('<input type="hidden" value="' + $.htmlSpecialChars(data.file_upload.id) + '" name="file_upload[file_id]" />');
500						} else {
501							fileInput.fileUploaderDynamic();
502							form.append('<input type="hidden" value="' + $.htmlSpecialChars(config.file_relation || '') + '" name="file_upload[file_relation]" />');
503							form.append('<input type="hidden" value="' + $.htmlSpecialChars(config.file_relation_id || 0) + '" name="file_upload[file_relation_id]" />');
504						}
505					} else if (fileUploaderDynamic) fileUploaderDynamic.showInput();
506					if ($.isFunction(config.load)) config.load(data, popup);
507					if ($.isFunction(config.save) && data.upload_id) abort = config.save(data, popup);
508					if (abort === true) return;
509					form.find('.error-text').remove();
510					if (data.errors && !$.isEmptyObject(data.errors)) {
511						$.each(data.errors, function(key, val) {
512							var input = form.find('[name="' + key + '"]'),
513								type = input.attr('type');
514							if (type && type.toUpperCase() == 'FILE') {
515								if (fileUploaderDynamic) fileUploaderDynamic.setError(val);
516							} else if (input.length) $('<span class="error-text help-block text-danger" >' + val + '</span>').insertAfter(input);
517						});
518						form.prepend('<div class="error-text alert alert-danger" >Errors have occured</div>');
519						popup.closest('.popup-scrollable').scrollTop(0);
520					}
521					if (data.file_upload) {
522						if (resetFile) fileInput.data('fileuploader').setFile(data.file_upload);
523						$.each(data.file_upload, function(key, val) {
524							var input = form.find('[name="file_upload[' + key + ']"]');
525							if (!input.length) form.append('<input type="hidden" name="file_upload[' + key + ']" value="' + $.htmlSpecialChars(val) + '" />');
526							else input.val($.htmlSpecialChars(val));
527						});
528						var prev = popup.find('textarea[name="file_upload[file_caption]"]');
529						popup.find('.btn-download-file').remove();
530						$('<hr/><a class="btn btn-charcoal pull-right btn-download-file" style="margin-top: 10px; margin-bottom: -10px;" ><i class="fa fa-download "></i>&nbsp;Download </a><div class="clearfix" ></div>').insertAfter(prev);
531						popup.find('.btn-download-file').click(function(e) {
532							e.preventDefault();
533							//console.log("data",data);
534							window.open(datatill.url('files/output/' + data.file_id + '/download'), '_blank');
535						});
536						popup.find('.btn-delete-file').remove();
537						$('<a class="btn  btn-danger pull-right btn-delete-file"  ><i class="icon icon-trash icon-white "></i>&nbsp; Delete </a>').click(function(e) {
538							e.preventDefault();
539							$.popup({
540								parent: popup,
541								header: '<h4>Confirm</h4>',
542								body: '<div class="alert alert-danger"><strong>Are you sure you want to delete this file?</strong></div>',
543								footer: ['<a class="btn btn-inverse pull-left" data-dismiss="popup" ><i class="icon icon-remove icon-white"></i> Close</a>', '<a class="btn btn-danger pull-right btn-delete-file"  data-loading-text="Deleting..." ><i class="icon icon-trash icon-white"></i>&nbsp; Delete</a>'].join(''),
544								load: function(delete_popup) {
545									delete_popup.find('.btn-delete-file').click(function(e) {
546										var file_id = data.file_upload.id;
547										e.preventDefault();
548										$.post(datatill.url('files/delete_file_dynamic'), {
549											file_id: file_id
550										}, function() {
551											var api = delete_popup.data('popup'),
552												parent = api.parent,
553												parentApi = $(parent).data('popup');
554											if (parentApi.parent) {
555												delete_popup.data('popup').showParent(popup.data('popup').parent);
556												if ($.isFunction(config.remove)) config.remove(file_id);
557											} else {
558												if (api) api.destroy = true;
559												delete_popup.popup('hide');
560												if ($.isFunction(config.remove)) config.remove(file_id);
561											}
562											//Added new delete function
563											if ($.isFunction(config.delete)) config.delete(data, popup);
564										}, 'json');
565									});
566								}
567							});
568						}).appendTo(popup.find('.popup-footer'));
569					}
570					btn.show().button('reset');
571				}).prependTo('body');
572				popup.on('popup.hidden', function() {
573					frame.remove();
574				});
575			}
576		});
577    };
578})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.