PageSourceSearch

https://stadiumkedah.gov.my/psnkcloud/core/js/oc-dialogs.js?v=e81ad89ccd551814ed7c72139b5cf64d

js stadiumkedah.gov.my collected 2026-10-03 02:55:16 UTC 26,602 bytes, 862 lines download raw bytes

1/**
2 * ownCloud
3 *
4 * @author Bartek Przybylski, Christopher Schäpers, Thomas Tanghus
5 * @copyright 2012 Bartek Przybylski [email protected]
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public
18 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22/* global alert */
23
24/**
25 * this class to ease the usage of jquery dialogs
26 * @lends OC.dialogs
27 */
28var OCdialogs = {
29	// dialog button types
30	YES_NO_BUTTONS:		70,
31	OK_BUTTONS:		71,
32	// used to name each dialog
33	dialogsCounter: 0,
34	/**
35	* displays alert dialog
36	* @param text content of dialog
37	* @param title dialog title
38	* @param callback which will be triggered when user presses OK
39	* @param modal make the dialog modal
40	*/
41	alert:function(text, title, callback, modal) {
42		this.message(
43			text,
44			title,
45			'alert',
46			OCdialogs.OK_BUTTON,
47			callback,
48			modal
49		);
50	},
51	/**
52	* displays info dialog
53	* @param text content of dialog
54	* @param title dialog title
55	* @param callback which will be triggered when user presses OK
56	* @param modal make the dialog modal
57	*/
58	info:function(text, title, callback, modal) {
59		this.message(text, title, 'info', OCdialogs.OK_BUTTON, callback, modal);
60	},
61	/**
62	* displays confirmation dialog
63	* @param text content of dialog
64	* @param title dialog title
65	* @param callback which will be triggered when user presses YES or NO
66	*        (true or false would be passed to callback respectively)
67	* @param modal make the dialog modal
68	*/
69	confirm:function(text, title, callback, modal) {
70		return this.message(
71			text,
72			title,
73			'notice',
74			OCdialogs.YES_NO_BUTTONS,
75			callback,
76			modal
77		);
78	},
79	/**
80	 * displays prompt dialog
81	 * @param text content of dialog
82	 * @param title dialog title
83	 * @param callback which will be triggered when user presses YES or NO
84	 *        (true or false would be passed to callback respectively)
85	 * @param modal make the dialog modal
86	 * @param name name of the input field
87	 * @param password whether the input should be a password input
88	 */
89	prompt: function (text, title, callback, modal, name, password) {
90		return $.when(this._getMessageTemplate()).then(function ($tmpl) {
91			var dialogName = 'oc-dialog-' + OCdialogs.dialogsCounter + '-content';
92			var dialogId = '#' + dialogName;
93			var $dlg = $tmpl.octemplate({
94				dialog_name: dialogName,
95				title      : title,
96				message    : text,
97				type       : 'notice'
98			});
99			var input = $('<input/>');
100			input.attr('type', password ? 'password' : 'text').attr('id', dialogName + '-input');
101			var label = $('<label/>').attr('for', dialogName + '-input').text(name + ': ');
102			$dlg.append(label);
103			$dlg.append(input);
104			if (modal === undefined) {
105				modal = false;
106			}
107			$('body').append($dlg);
108			var buttonlist = [{
109					text : t('core', 'No'),
110					click: function () {
111						if (callback !== undefined) {
112							callback(false, input.val());
113						}
114						$(dialogId).ocdialog('close');
115					}
116				}, {
117					text         : t('core', 'Yes'),
118					click        : function () {
119						if (callback !== undefined) {
120							callback(true, input.val());
121						}
122						$(dialogId).ocdialog('close');
123					},
124					defaultButton: true
125				}
126			];
127
128			$(dialogId).ocdialog({
129				closeOnEscape: true,
130				modal        : modal,
131				buttons      : buttonlist
132			});
133			OCdialogs.dialogsCounter++;
134		});
135	},
136	/**
137	 * show a file picker to pick a file from
138	 * @param title dialog title
139	 * @param callback which will be triggered when user presses Choose
140	 * @param multiselect whether it should be possible to select multiple files
141	 * @param mimetypeFilter mimetype to filter by - directories will always be included
142	 * @param modal make the dialog modal
143	*/
144	filepicker:function(title, callback, multiselect, mimetypeFilter, modal) {
145		var self = this;
146		// avoid opening the picker twice
147		if (this.filepicker.loading) {
148			return;
149		}
150		this.filepicker.loading = true;
151		$.when(this._getFilePickerTemplate()).then(function($tmpl) {
152			self.filepicker.loading = false;
153			var dialogName = 'oc-dialog-filepicker-content';
154			if(self.$filePicker) {
155				self.$filePicker.ocdialog('close');
156			}
157			self.$filePicker = $tmpl.octemplate({
158				dialog_name: dialogName,
159				title: title
160			}).data('path', '').data('multiselect', multiselect).data('mimetype', mimetypeFilter);
161
162			if (modal === undefined) {
163				modal = false;
164			}
165			if (multiselect === undefined) {
166				multiselect = false;
167			}
168			if (mimetypeFilter === undefined) {
169				mimetypeFilter = '';
170			}
171
172			$('body').append(self.$filePicker);
173
174			self.$filePicker.ready(function() {
175				self.$filelist = self.$filePicker.find('.filelist');
176				self.$dirTree = self.$filePicker.find('.dirtree');
177				self.$dirTree.on('click', 'span:not(:last-child)', self, self._handleTreeListSelect);
178				self.$filelist.on('click', 'li', function(event) {
179					self._handlePickerClick(event, $(this));
180				});
181				self._fillFilePicker('');
182			});
183
184			// build buttons
185			var functionToCall = function() {
186				if (callback !== undefined) {
187					var datapath;
188					if (multiselect === true) {
189						datapath = [];
190						self.$filelist.find('.filepicker_element_selected .filename').each(function(index, element) {
191							datapath.push(self.$filePicker.data('path') + '/' + $(element).text());
192						});
193					} else {
194						datapath = self.$filePicker.data('path');
195						datapath += '/' + self.$filelist.find('.filepicker_element_selected .filename').text();
196					}
197					callback(datapath);
198					self.$filePicker.ocdialog('close');
199				}
200			};
201			var buttonlist = [{
202				text: t('core', 'Choose'),
203				click: functionToCall,
204				defaultButton: true
205			}];
206
207			self.$filePicker.ocdialog({
208				closeOnEscape: true,
209				// max-width of 600
210				width: Math.min((4/5)*$(document).width(), 600),
211				height: 420,
212				modal: modal,
213				buttons: buttonlist,
214				close: function() {
215					try {
216						$(this).ocdialog('destroy').remove();
217					} catch(e) {}
218					self.$filePicker = null;
219				}
220			});
221
222			// We can access primary class only from oc-dialog.
223			// Hence this is one of the approach to get the choose button.
224			var getOcDialog = self.$filePicker.closest('.oc-dialog');
225			var buttonEnableDisable = getOcDialog.find('.primary');
226			buttonEnableDisable.prop("disabled", "true");
227
228			if (!OC.Util.hasSVGSupport()) {
229				OC.Util.replaceSVG(self.$filePicker.parent());
230			}
231		})
232		.fail(function(status, error) {
233			// If the method is called while navigating away
234			// from the page, it is probably not needed ;)
235			self.filepicker.loading = false;
236			if(status !== 0) {
237				alert(t('core', 'Error loading file picker template: {error}', {error: error}));
238			}
239		});
240	},
241	/**
242	 * Displays raw dialog
243	 * You better use a wrapper instead ...
244	*/
245	message:function(content, title, dialogType, buttons, callback, modal, cssClass) {
246		return $.when(this._getMessageTemplate()).then(function($tmpl) {
247			var dialogName = 'oc-dialog-' + OCdialogs.dialogsCounter + '-content';
248			var dialogId = '#' + dialogName;
249			var $dlg = $tmpl.octemplate({
250				dialog_name: dialogName,
251				title: title,
252				message: content,
253				type: dialogType
254			});
255
256			if (modal === undefined) {
257				modal = false;
258			}
259
260			$('body').append($dlg);
261			var buttonlist = [];
262			if (_.isArray(buttons)) {
263				buttonlist = buttons;
264			} else {
265				switch (buttons) {
266				case OCdialogs.YES_NO_BUTTONS:
267					buttonlist = [{
268						text: t('core', 'No'),
269						click: function(){
270							if (callback !== undefined) {
271								callback(false);
272							}
273							$(dialogId).ocdialog('close');
274						}
275					},
276					{
277						text: t('core', 'Yes'),
278						click: function(){
279							if (callback !== undefined) {
280								callback(true);
281							}
282							$(dialogId).ocdialog('close');
283						},
284						defaultButton: true
285					}];
286					break;
287				case OCdialogs.OK_BUTTON:
288					var functionToCall = function() {
289						$(dialogId).ocdialog('close');
290						if(callback !== undefined) {
291							callback();
292						}
293					};
294					buttonlist[0] = {
295						text: t('core', 'Ok'),
296						click: functionToCall,
297						defaultButton: true
298					};
299					break;
300				}
301			}
302
303			$(dialogId).ocdialog({
304				closeOnEscape: true,
305				modal: modal,
306				buttons: buttonlist
307			});
308
309			if (cssClass != undefined) {
310				$(dialogId).addClass(cssClass);
311			}
312
313			OCdialogs.dialogsCounter++;
314		})
315		.fail(function(status, error) {
316			// If the method is called while navigating away from
317			// the page, we still want to deliver the message.
318			if(status === 0) {
319				alert(title + ': ' + content);
320			} else {
321				alert(t('core', 'Error loading message template: {error}', {error: error}));
322			}
323		});
324	},
325	_fileexistsshown: false,
326	/**
327	 * Displays file exists dialog
328	 * @param {object} data upload object
329	 * @param {object} original file with name, size and mtime
330	 * @param {object} replacement file with name, size and mtime
331	 * @param {object} controller with onCancel, onSkip, onReplace and onRename methods
332	 * @return {Promise} jquery promise that resolves after the dialog template was loaded
333	*/
334	fileexists:function(data, original, replacement, controller) {
335		var self = this;
336		var dialogDeferred = new $.Deferred();
337
338		var getCroppedPreview = function(file) {
339			var deferred = new $.Deferred();
340			// Only process image files.
341			var type = file.type && file.type.split('/').shift();
342			if (window.FileReader && type === 'image') {
343				var reader = new FileReader();
344				reader.onload = function (e) {
345					var blob = new Blob([e.target.result]);
346					window.URL = window.URL || window.webkitURL;
347					var originalUrl = window.URL.createObjectURL(blob);
348					var image = new Image();
349					image.src = originalUrl;
350					image.onload = function () {
351						var url = crop(image);
352						deferred.resolve(url);
353					};
354				};
355				reader.readAsArrayBuffer(file);
356			} else {
357				deferred.reject();
358			}
359			return deferred;
360		};
361
362		var crop = function(img) {
363			var canvas = document.createElement('canvas'),
364					targetSize = 96,
365					width = img.width,
366					height = img.height,
367					x, y, size;
368
369			// Calculate the width and height, constraining the proportions
370			if (width > height) {
371				y = 0;
372				x = (width - height) / 2;
373			} else {
374				y = (height - width) / 2;
375				x = 0;
376			}
377			size = Math.min(width, height);
378
379			// Set canvas size to the cropped area
380			canvas.width = size;
381			canvas.height = size;
382			var ctx = canvas.getContext("2d");
383			ctx.drawImage(img, x, y, size, size, 0, 0, size, size);
384
385			// Resize the canvas to match the destination (right size uses 96px)
386			resampleHermite(canvas, size, size, targetSize, targetSize);
387
388			return canvas.toDataURL("image/png", 0.7);
389		};
390
391		/**
392		 * Fast image resize/resample using Hermite filter with JavaScript.
393		 *
394		 * @author: ViliusL
395		 *
396		 * @param {*} canvas
397		 * @param {number} W
398		 * @param {number} H
399		 * @param {number} W2
400		 * @param {number} H2
401		 */
402		var resampleHermite = function (canvas, W, H, W2, H2) {
403			W2 = Math.round(W2);
404			H2 = Math.round(H2);
405			var img = canvas.getContext("2d").getImageData(0, 0, W, H);
406			var img2 = canvas.getContext("2d").getImageData(0, 0, W2, H2);
407			var data = img.data;
408			var data2 = img2.data;
409			var ratio_w = W / W2;
410			var ratio_h = H / H2;
411			var ratio_w_half = Math.ceil(ratio_w / 2);
412			var ratio_h_half = Math.ceil(ratio_h / 2);
413
414			for (var j = 0; j < H2; j++) {
415				for (var i = 0; i < W2; i++) {
416					var x2 = (i + j * W2) * 4;
417					var weight = 0;
418					var weights = 0;
419					var weights_alpha = 0;
420					var gx_r = 0;
421					var gx_g = 0;
422					var gx_b = 0;
423					var gx_a = 0;
424					var center_y = (j + 0.5) * ratio_h;
425					for (var yy = Math.floor(j * ratio_h); yy < (j + 1) * ratio_h; yy++) {
426						var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half;
427						var center_x = (i + 0.5) * ratio_w;
428						var w0 = dy * dy; //pre-calc part of w
429						for (var xx = Math.floor(i * ratio_w); xx < (i + 1) * ratio_w; xx++) {
430							var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half;
431							var w = Math.sqrt(w0 + dx * dx);
432							if (w >= -1 && w <= 1) {
433								//hermite filter
434								weight = 2 * w * w * w - 3 * w * w + 1;
435								if (weight > 0) {
436									dx = 4 * (xx + yy * W);
437									//alpha
438									gx_a += weight * data[dx + 3];
439									weights_alpha += weight;
440									//colors
441									if (data[dx + 3] < 255)
442										weight = weight * data[dx + 3] / 250;
443									gx_r += weight * data[dx];
444									gx_g += weight * data[dx + 1];
445									gx_b += weight * data[dx + 2];
446									weights += weight;
447								}
448							}
449						}
450					}
451					data2[x2] = gx_r / weights;
452					data2[x2 + 1] = gx_g / weights;
453					data2[x2 + 2] = gx_b / weights;
454					data2[x2 + 3] = gx_a / weights_alpha;
455				}
456			}
457			canvas.getContext("2d").clearRect(0, 0, Math.max(W, W2), Math.max(H, H2));
458			canvas.width = W2;
459			canvas.height = H2;
460			canvas.getContext("2d").putImageData(img2, 0, 0);
461		};
462
463		var addConflict = function($conflicts, original, replacement) {
464
465			var $conflict = $conflicts.find('.template').clone().removeClass('template').addClass('conflict');
466			var $originalDiv = $conflict.find('.original');
467			var $replacementDiv = $conflict.find('.replacement');
468
469			$conflict.data('data',data);
470
471			$conflict.find('.filename').text(original.name);
472			$originalDiv.find('.size').text(humanFileSize(original.size));
473			$originalDiv.find('.mtime').text(formatDate(original.mtime));
474			// ie sucks
475			if (replacement.size && replacement.lastModifiedDate) {
476				$replacementDiv.find('.size').text(humanFileSize(replacement.size));
477				$replacementDiv.find('.mtime').text(formatDate(replacement.lastModifiedDate));
478			}
479			var path = original.directory + '/' +original.name;
480			var urlSpec = {
481				file:		path,
482				x:		96,
483				y:		96,
484				c:		original.etag,
485				forceIcon:	0
486			};
487			var previewpath = Files.generatePreviewUrl(urlSpec);
488			// Escaping single quotes
489			previewpath = previewpath.replace(/'/g, "%27");
490			$originalDiv.find('.icon').css({"background-image":   "url('" + previewpath + "')"});
491			getCroppedPreview(replacement).then(
492				function(path){
493					$replacementDiv.find('.icon').css('background-image','url(' + path + ')');
494				}, function(){
495					path = OC.MimeType.getIconUrl(replacement.type);
496					$replacementDiv.find('.icon').css('background-image','url(' + path + ')');
497				}
498			);
499			// connect checkboxes with labels
500			var checkboxId = $conflicts.find('.conflict').length;
501			$originalDiv.find('input:checkbox').attr('id', 'checkbox_original_'+checkboxId);
502			$replacementDiv.find('input:checkbox').attr('id', 'checkbox_replacement_'+checkboxId);
503
504			$conflicts.append($conflict);
505
506			//set more recent mtime bold
507			// ie sucks
508			if (replacement.lastModifiedDate && replacement.lastModifiedDate.getTime() > original.mtime) {
509				$replacementDiv.find('.mtime').css('font-weight', 'bold');
510			} else if (replacement.lastModifiedDate && replacement.lastModifiedDate.getTime() < original.mtime) {
511				$originalDiv.find('.mtime').css('font-weight', 'bold');
512			} else {
513				//TODO add to same mtime collection?
514			}
515
516			// set bigger size bold
517			if (replacement.size && replacement.size > original.size) {
518				$replacementDiv.find('.size').css('font-weight', 'bold');
519			} else if (replacement.size && replacement.size < original.size) {
520				$originalDiv.find('.size').css('font-weight', 'bold');
521			} else {
522				//TODO add to same size collection?
523			}
524
525			//TODO show skip action for files with same size and mtime in bottom row
526
527			// always keep readonly files
528
529			if (original.status === 'readonly') {
530				$originalDiv
531					.addClass('readonly')
532					.find('input[type="checkbox"]')
533						.prop('checked', true)
534						.prop('disabled', true);
535				$originalDiv.find('.message')
536					.text(t('core','read-only'))
537			}
538		};
539		//var selection = controller.getSelection(data.originalFiles);
540		//if (selection.defaultAction) {
541		//	controller[selection.defaultAction](data);
542		//} else {
543		var dialogName = 'oc-dialog-fileexists-content';
544		var dialogId = '#' + dialogName;
545		if (this._fileexistsshown) {
546			// add conflict
547
548			var $conflicts = $(dialogId+ ' .conflicts');
549			addConflict($conflicts, original, replacement);
550
551			var count = $(dialogId+ ' .conflict').length;
552			var title = n('core',
553							'{count} file conflict',
554							'{count} file conflicts',
555							count,
556							{count:count}
557						);
558			$(dialogId).parent().children('.oc-dialog-title').text(title);
559
560			//recalculate dimensions
561			$(window).trigger('resize');
562			dialogDeferred.resolve();
563		} else {
564			//create dialog
565			this._fileexistsshown = true;
566			$.when(this._getFileExistsTemplate()).then(function($tmpl) {
567				var title = t('core','One file conflict');
568				var $dlg = $tmpl.octemplate({
569					dialog_name: dialogName,
570					title: title,
571					type: 'fileexists',
572
573					allnewfiles: t('core','New Files'),
574					allexistingfiles: t('core','Already existing files'),
575
576					why: t('core','Which files do you want to keep?'),
577					what: t('core','If you select both versions, the copied file will have a number added to its name.')
578				});
579				$('body').append($dlg);
580
581				if (original && replacement) {
582					var $conflicts = $dlg.find('.conflicts');
583					addConflict($conflicts, original, replacement);
584				}
585
586				var buttonlist = [{
587						text: t('core', 'Cancel'),
588						classes: 'cancel',
589						click: function(){
590							if ( typeof controller.onCancel !== 'undefined') {
591								controller.onCancel(data);
592							}
593							$(dialogId).ocdialog('close');
594						}
595					},
596					{
597						text: t('core', 'Continue'),
598						classes: 'continue',
599						click: function(){
600							if ( typeof controller.onContinue !== 'undefined') {
601								controller.onContinue($(dialogId + ' .conflict'));
602							}
603							$(dialogId).ocdialog('close');
604						}
605					}];
606
607				$(dialogId).ocdialog({
608					width: 500,
609					closeOnEscape: true,
610					modal: true,
611					buttons: buttonlist,
612					closeButton: null,
613					close: function() {
614							self._fileexistsshown = false;
615							$(this).ocdialog('destroy').remove();
616						}
617				});
618
619				$(dialogId).css('height','auto');
620
621				var $primaryButton = $dlg.closest('.oc-dialog').find('button.continue');
622				$primaryButton.prop('disabled', true);
623
624				function updatePrimaryButton() {
625					var checkedCount = $dlg.find('.conflicts .checkbox:checked').length;
626					$primaryButton.prop('disabled', checkedCount === 0);
627				}
628
629				//add checkbox toggling actions
630				$(dialogId).find('.allnewfiles').on('click', function() {
631					var $checkboxes = $(dialogId).find('.conflict .replacement input[type="checkbox"]');
632					$checkboxes.prop('checked', $(this).prop('checked'));
633				});
634				$(dialogId).find('.allexistingfiles').on('click', function() {
635					var $checkboxes = $(dialogId).find('.conflict .original:not(.readonly) input[type="checkbox"]');
636					$checkboxes.prop('checked', $(this).prop('checked'));
637				});
638				$(dialogId).find('.conflicts').on('click', '.replacement,.original:not(.readonly)', function() {
639					var $checkbox = $(this).find('input[type="checkbox"]');
640					$checkbox.prop('checked', !$checkbox.prop('checked'));
641				});
642				$(dialogId).find('.conflicts').on('click', '.replacement input[type="checkbox"],.original:not(.readonly) input[type="checkbox"]', function() {
643					var $checkbox = $(this);
644					$checkbox.prop('checked', !$checkbox.prop('checked'));
645				});
646
647				//update counters
648				$(dialogId).on('click', '.replacement,.allnewfiles', function() {
649					var count = $(dialogId).find('.conflict .replacement input[type="checkbox"]:checked').length;
650					if (count === $(dialogId+ ' .conflict').length) {
651						$(dialogId).find('.allnewfiles').prop('checked', true);
652						$(dialogId).find('.allnewfiles + .count').text(t('core','(all selected)'));
653					} else if (count > 0) {
654						$(dialogId).find('.allnewfiles').prop('checked', false);
655						$(dialogId).find('.allnewfiles + .count').text(t('core','({count}
655 selected)',{count:count}));
656					} else {
657						$(dialogId).find('.allnewfiles').prop('checked', false);
658						$(dialogId).find('.allnewfiles + .count').text('');
659					}
660					updatePrimaryButton();
661				});
662				$(dialogId).on('click', '.original,.allexistingfiles', function(){
663					var count = $(dialogId).find('.conflict .original input[type="checkbox"]:checked').length;
664					if (count === $(dialogId+ ' .conflict').length) {
665						$(dialogId).find('.allexistingfiles').prop('checked', true);
666						$(dialogId).find('.allexistingfiles + .count').text(t('core','(all selected)'));
667					} else if (count > 0) {
668						$(dialogId).find('.allexistingfiles').prop('checked', false);
669						$(dialogId).find('.allexistingfiles + .count')
670							.text(t('core','({count} selected)',{count:count}));
671					} else {
672						$(dialogId).find('.allexistingfiles').prop('checked', false);
673						$(dialogId).find('.allexistingfiles + .count').text('');
674					}
675					updatePrimaryButton();
676				});
677
678				dialogDeferred.resolve();
679			})
680			.fail(function() {
681				dialogDeferred.reject();
682				alert(t('core', 'Error loading file exists template'));
683			});
684		}
685		//}
686		return dialogDeferred.promise();
687	},
688	_getFilePickerTemplate: function() {
689		var defer = $.Deferred();
690		if(!this.$filePickerTemplate) {
691			var self = this;
692			$.get(OC.filePath('core', 'templates', 'filepicker.html'), function(tmpl) {
693				self.$filePickerTemplate = $(tmpl);
694				self.$listTmpl = self.$filePickerTemplate.find('.filelist li:first-child').detach();
695				defer.resolve(self.$filePickerTemplate);
696			})
697			.fail(function(jqXHR, textStatus, errorThrown) {
698				defer.reject(jqXHR.status, errorThrown);
699			});
700		} else {
701			defer.resolve(this.$filePickerTemplate);
702		}
703		return defer.promise();
704	},
705	_getMessageTemplate: function() {
706		var defer = $.Deferred();
707		if(!this.$messageTemplate) {
708			var self = this;
709			$.get(OC.filePath('core', 'templates', 'message.html'), function(tmpl) {
710				self.$messageTemplate = $(tmpl);
711				defer.resolve(self.$messageTemplate);
712			})
713			.fail(function(jqXHR, textStatus, errorThrown) {
714				defer.reject(jqXHR.status, errorThrown);
715			});
716		} else {
717			defer.resolve(this.$messageTemplate);
718		}
719		return defer.promise();
720	},
721	_getFileExistsTemplate: function () {
722		var defer = $.Deferred();
723		if (!this.$fileexistsTemplate) {
724			var self = this;
725			$.get(OC.filePath('files', 'templates', 'fileexists.html'), function (tmpl) {
726				self.$fileexistsTemplate = $(tmpl);
727				defer.resolve(self.$fileexistsTemplate);
728			})
729			.fail(function () {
730				defer.reject();
731			});
732		} else {
733			defer.resolve(this.$fileexistsTemplate);
734		}
735		return defer.promise();
736	},
737	_getFileList: function(dir, mimeType) {
738		if (typeof(mimeType) === "string") {
739			mimeType = [mimeType];
740		}
741
742		return $.getJSON(
743			OC.filePath('files', 'ajax', 'list.php'),
744			{
745				dir: dir,
746				mimetypes: JSON.stringify(mimeType)
747			}
748		);
749	},
750
751	/**
752	 * fills the filepicker with files
753	*/
754	_fillFilePicker:function(dir) {
755		var dirs = [];
756		var others = [];
757		var self = this;
758		this.$filelist.empty().addClass('icon-loading');
759		this.$filePicker.data('path', dir);
760		$.when(this._getFileList(dir, this.$filePicker.data('mimetype'))).then(function(response) {
761
762			$.each(response.data.files, function(index, file) {
763				if (file.type === 'dir') {
764					dirs.push(file);
765				} else {
766					others.push(file);
767				}
768			});
769
770			self._fillSlug();
771			var sorted = dirs.concat(others);
772
773			$.each(sorted, function(idx, entry) {
774				entry.icon = OC.MimeType.getIconUrl(entry.mimetype);
775				var $li = self.$listTmpl.octemplate({
776					type: entry.type,
777					dir: dir,
778					filename: entry.name,
779					date: OC.Util.relativeModifiedDate(entry.mtime)
780				});
781				if (entry.type === 'file') {
782					var urlSpec = {
783						file: dir + '/' + entry.name
784					};
785					var previewUrl = OC.generateUrl('/core/preview.png?') + $.param(urlSpec);
786					$li.find('img').attr('src', previewUrl);
787				}
788				else {
789					$li.find('img').attr('src', OC.Util.replaceSVGIcon(entry.icon));
790				}
791				self.$filelist.append($li);
792			});
793
794			self.$filelist.removeClass('icon-loading');
795			if (!OC.Util.hasSVGSupport()) {
796				OC.Util.replaceSVG(self.$filePicker.find('.dirtree'));
797			}
798		});
799	},
800	/**
801	 * fills the tree list with directories
802	*/
803	_fillSlug: function() {
804		this.$dirTree.empty();
805		var self = this;
806		var path = this.$filePicker.data('path');
807		var $template = $('<span data-dir="{dir}">{name}</span>');
808		if(path) {
809			var paths = path.split('/');
810			$.each(paths, function(index, dir) {
811				dir = paths.pop();
812				if(dir === '') {
813					return false;
814				}
815				self.$dirTree.prepend($template.octemplate({
816					dir: paths.join('/') + '/' + dir,
817					name: dir
818				}));
819			});
820		}
821		$template.octemplate({
822			dir: '',
823			name: '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' // Ugly but works ;)
824		}, {escapeFunction: null}).addClass('home svg').prependTo(this.$dirTree);
825	},
826	/**
827	 * handle selection made in the tree list
828	*/
829	_handleTreeListSelect:function(event) {
830		var self = event.data;
831		var dir = $(event.target).data('dir');
832		self._fillFilePicker(dir);
833		var getOcDialog = this.closest('.oc-dialog');
834		var buttonEnableDisable = $('.primary', getOcDialog);
835		if (this.$filePicker.data('mimetype') === "http/unix-directory") {
836			buttonEnableDisable.prop("disabled", false);
837		} else {
838			buttonEnableDisable.prop("disabled", true);
839		}
840	},
841	/**
842	 * handle clicks made in the filepicker
843	*/
844	_handlePickerClick:function(event, $element) {
845		var getOcDialog = this.$filePicker.closest('.oc-dialog');
846		var buttonEnableDisable = getOcDialog.find('.primary');
847		if ($element.data('type') === 'file') {
848			if (this.$filePicker.data('multiselect') !== true || !event.ctrlKey) {
849				this.$filelist.find('.filepicker_element_selected').removeClass('filepicker_element_selected');
850			}
851			$element.toggleClass('filepicker_element_selected');
852			buttonEnableDisable.prop("disabled", false);
853		} else if ( $element.data('type') === 'dir' ) {
854			this._fillFilePicker(this.$filePicker.data('path') + '/' + $element.data('entryname'));
855			if (this.$filePicker.data('mimetype') === "httpd/unix-directory") {
856				buttonEnableDisable.prop("disabled", false);
857			} else {
858				buttonEnableDisable.prop("disabled", true);
859			}
860		}
861	}
862};

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.