PageSourceSearch

https://kyurijeon.com/_jsapps/api/_cargo/_core/ImageUploader.js

js kyurijeon.com collected 2026-10-05 02:02:37 UTC 4,606 bytes, 213 lines download raw bytes

1Cargo.utils = Cargo.utils || {};
2
3/**
4 * @todo: process fields: totalBytes, uploadedBytes
5 * 		  global progress percentage calculated with the progress from all processes.
6 * 
7 */
8
9Cargo.utils.ImageUploader = function(options){
10
11	$.extend(this.options = {}, this.defaultOptions, options);
12
13	this.activeProcesses = [];
14
15}
16
17Cargo.utils.ImageUploader.prototype = {
18
19	upload: function(files, pid, customParameters){
20
21		if(files === undefined){
22			return undefined;
23		}
24
25		// TODO: handle either a single file or an array of files
26		if(files.length === 0) {
27			return undefined;
28		};
29
30		var _this = this;
31
32		// wrap all files in a process. This allows for 
33		// global progress tracking when uploading an array
34		// of files and easier management of multiple 
35		// concurrent processes. Also allows you to swap out processes
36		// between uploader instances or re-upload/re-use a certain process.
37		
38		var uploadProcess = {
39			uid: Cargo.Model.Site.GetId(),
40			url: Cargo.Helper.GetUrl(),
41			pid: (pid !== undefined ? pid : Cargo.Helper.GetCurrentProjectId()),
42			fileIndex: -1,
43			aborted: false,
44			totalBytes: 0,
45			uploadedBytes: 0,
46			customParameters: customParameters,
47			getUploadProgress: function(){
48				return (this.uploadedBytes / this.totalBytes) * 100;
49			},
50			files: [],
51			events: {
52				onFileComplete: function(file, event){},
53				onFileProgress: function(file, event){},
54				onFileFail: function(file, event){},
55				onFileError: function(file, event){},
56				onAbort: function(uploadProcess){},
57				onComplete: function(uploadProcess){}
58			},
59			getNextFile: function(){
60
61				if(this.fileIndex < this.files.length - 1 && this.aborted !== true){
62					return this.files[++this.fileIndex];
63				} 
64
65				return undefined;
66			},
67			getCurrentFile: function(){
68				return this.files[this.fileIndex];
69			},
70			abort: function(){
71
72				if(this.xhr !== undefined){
73
74					this.aborted = true;
75					this.xhr.abort();
76					this.events.onAbort(this);
77
78					var processIndex = _this.activeProcesses.indexOf(this);
79
80					if(processIndex !== -1){
81						_this.activeProcesses.splice(processIndex, 1);
82					}
83
84				}
85				
86			},
87			addFile: function(file){
88				
89				if(this.files.indexOf(file) === -1) {
90
91					if(_this.options.acceptFileTypes.test(file.type) && _this.options.acceptFileTypes.test(file.name)){
92				
93						uploadProcess.files.push(file);
94
95						this.totalBytes += file.size;
96
97					} else {
98
99						// TODO: Think this through again.
100						uploadProcess.events.onFileError(file, {
101							message: 'File type not allowed'
102						});
103
104					}
105
106				}
107
108			}
109		};
110
111		[].forEach.call(files, function(file){
112			uploadProcess.addFile(file);
113		});
114
115		if(uploadProcess.files.length === 0){
116			uploadProcess = null;
117			return undefined;
118		}
119
120		this.activeProcesses.push(uploadProcess);
121
122		this.handleUploadProcess(uploadProcess);
123
124		return uploadProcess;
125
126	},
127
128	handleUploadProcess: function(uploadProcess){
129
130		var file = uploadProcess.getNextFile(),
131			_this = this;
132
133		if(file === undefined) {
134
135			// no more files.
136			uploadProcess.xhr = undefined;
137			uploadProcess.events.onComplete(uploadProcess);
138
139			uploadProcess.fileIndex = -1;
140
141			var processIndex = _this.activeProcesses.indexOf(uploadProcess);
142
143			if(processIndex !== -1){
144				_this.activeProcesses.splice(processIndex, 1);
145			}
146
147			return;
148		}
149
150		file.lastProgress = 0;
151
152		var formData = new FormData();
153
154		formData.append('Filedata[]', file);
155
156		formData.append('pid', uploadProcess.pid);
157		formData.append('url', uploadProcess.url);
158		formData.append('uid', uploadProcess.uid);
159
160		if(typeof uploadProcess.customParameters === "object"){
161
162			Object.keys(uploadProcess.customParameters).forEach(function(key){
163				
164				formData.append(key, uploadProcess.customParameters[key]);
165
166			});
167
168		}
169		
170		uploadProcess.xhr = new Cargo.utils.CargoXHR({
171
172			url: this.options.posturl,
173			type: 'POST',
174			data: formData,
175			progress: function(e){
176				
177				if(e.lengthComputable){
178					
179					uploadProcess.uploadedBytes += e.loaded - file.lastProgress;
180					file.lastProgress = e.loaded;
181
182				}
183
184				uploadProcess.events.onFileProgress(file, e);
185
186			},
187			success: function(e){
188				
189				if (this.xhr.status == 200) {
190
191					var response = JSON.parse(this.xhr.responseText);
192					uploadProcess.events.onFileComplete.call(this, file, e);
193
194				} else {
195
196					uploadProcess.events.onFileFail.call(this, file, e);
197
198				}
199
200				// keep going until we run out of files to upload
201				_this.handleUploadProcess(uploadProcess);
202
203			}
204
205		});
206
207	},
208
209	defaultOptions: {
210		acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
211		posturl: '/dispatch/adminproject/handleMultiFileUpload'
212	}
213};

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.