PageSourceSearch

https://demo.pennyauctionsoftware.net/assets/js/socket.io-file-client.js

js pennyauctionsoftware.net collected 2026-10-09 03:02:25 UTC 23,330 bytes, 771 lines download raw bytes

1/*
2 *                 Copyright (C) 2015 Shane Carr and others
3 *                               X11 License
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Except as contained in this notice, the names of the authors or copyright
24 * holders shall not be used in advertising or otherwise to promote the sale,
25 * use or other dealings in this Software without prior written authorization
26 * from the authors or copyright holders.
27 */
28
29// Do not check function indentation because this is intentionally ignored in order to preserve history in git.
30/* eslint-disable indent */
31
32/*
33 * A client-side JavaScript object to handle file uploads to a Node.JS server
34 * via Socket.IO.
35 * @implements EventTarget
36 * @param {SocketIO} socket The current Socket.IO connection.
37 */
38(function (scope, name, factory) {
39	/* eslint-disable no-undef */
40	if (typeof define === "function" && define.amd) {
41		define([], factory);
42	}
43	else if (typeof module === "object" && module.exports) {
44		module.exports = factory();
45	}
46	else {
47		scope[name] = factory();
48	}
49	/* eslint-enable no-undef */
50}(this, "SocketIOFileUpload", function () {
51 return function (socket, options) {
52	"use strict";
53
54	var self = this; // avoids context issues
55
56	// Check for compatibility
57	if (!window.File || !window.FileReader) {
58		throw new Error("Socket.IO File Upload: Browser Not Supported");
59	}
60
61	if ( !window.siofu_global ) {
62		window.siofu_global = {
63			instances: 0,
64			downloads: 0
65		};
66	}
67
68	// Private and Public Variables
69	var callbacks = {},
70		uploadedFiles = {},
71		chunkCallbacks = {},
72		readyCallbacks = {},
73		communicators = {};
74
75	var _getOption = function (key, defaultValue) {
76		if(!options) {
77			return defaultValue;
78		}
79		return options[key] || defaultValue;
80	};
81
82	self.fileInputElementId = "siofu_input_"+window.siofu_global.instances++;
83	self.resetFileInputs = true;
84	self.useText = _getOption("useText", false);
85	self.serializedOctets = _getOption("serializedOctets", false);
86	self.useBuffer = _getOption("useBuffer", true);
87	self.chunkSize = _getOption("chunkSize", 1024 * 100); // 100kb default chunk size
88	self.topicName = _getOption("topicName", "siofu");
89
90	/**
91	* WrapData allow you to wrap the Siofu messages into a predefined format.
92	* You can then easily use Siofu packages even in strongly typed topic.
93	* wrapData can be a boolean or an object. It is false by default.
94	* If wrapData is true it will allow you to send all the messages to only one topic by wrapping the siofu actions and messages.
95	*
96	* ex:
97	{
98		action: 'complete',
99		message: {
100		 id: id,
101		 success: success,
102		 detail: fileInfo.clientDetail
103		}
104	}
105	*
106	* If wrapData is an object constituted of two mandatory key and one optional:
107	* wrapKey and unwrapKey (mandatory): Corresponding to the key used to wrap the siofu data and message
108	* additionalData (optional): Corresponding to the data to send along with file data
109	*
110	* ex:
111	* if wrapData = {
112		wrapKey: {
113			action: 'actionType',
114			message: 'data'
115		},
116		unwrapKey: {
117			action: 'actionType',
118			message: 'message'
119		},
120		additionalData: {
121			acknowledgement: true
122		}
123	}
124	* When Siofu will send for example a complete message this will send:
125	*
126	{
127		acknowledgement: true,
128		actionType: 'complete',
129		data: {
130		 id: id,
131		 success: success,
132		 detail: fileInfo.clientDetail
133		}
134	}
135	* and it's waiting from client data formatted like this:
136	*
137	{
138		actionType: '...',
139		message: {...}
140	}
141	* /!\ If wrapData is wrong configured is interpreted as false /!\
142	*/
143	self.wrapData = _getOption("wrapData", false);
144
145	var _isWrapDataWellConfigured = function () {
146		if (typeof self.wrapData === "boolean") {
147			return true;
148		}
149		if (typeof self.wrapData !== "object" || Array.isArray(self.wrapData)) {
150			return false;
151		}
152
153		if(!self.wrapData.wrapKey || typeof self.wrapData.wrapKey.action !== "string" || typeof self.wrapData.wrapKey.message !== "string" ||
154			!self.wrapData.unwrapKey || typeof self.wrapData.unwrapKey.action !== "string" || typeof self.wrapData.unwrapKey.message !== "string") {
155			return false;
156		}
157
158		return true;
159	};
160
161
162	/**
163	 * Allow user to access to some private function to customize message reception.
164	 * This is used if you specified wrapOptions on the client side and have to manually bind message to callback.
165	 */
166	self.exposePrivateFunction = _getOption("exposePrivateFunction", false);
167
168	var _getTopicName = function (topicExtension) {
169		if (self.wrapData) {
170			return self.topicName;
171		}
172
173		return self.topicName + topicExtension;
174	};
175
176	var _wrapData = function (data, action) {
177		if(!_isWrapDataWellConfigured() || !self.wrapData) {
178			return data;
179		}
180		var dataWrapped = {};
181		if(self.wrapData.additionalData) {
182			Object.assign(dataWrapped, self.wrapData.additionalData);
183		}
184
185		var actionKey = self.wrapData.wrapKey && typeof self.wrapData.wrapKey.action === "string" ? self.wrapData.wrapKey.action : "action";
186		var messageKey = self.wrapData.wrapKey && typeof self.wrapData.wrapKey.message === "string" ? self.wrapData.wrapKey.message : "message";
187
188		dataWrapped[actionKey] = action;
189		dataWrapped[messageKey] = data;
190		return dataWrapped;
191	};
192
193	/**
194	 * Private method to dispatch a custom event on the instance.
195	 * @param  {string} eventName  Name for which listeners can listen.
196	 * @param  {object} properties An object literal with additional properties
197	 *                             to be attached to the event object.
198	 * @return {boolean} false if any callback returned false; true otherwise
199	 */
200	var _dispatch = function (eventName, properties) {
201		var evnt = document.createEvent("Event");
202		evnt.initEvent(eventName, false, false);
203		for (var prop in properties) {
204			if (properties.hasOwnProperty(prop)) {
205				evnt[prop] = properties[prop];
206			}
207		}
208		return self.dispatchEvent(evnt);
209	};
210
211	/**
212	 * Private method to bind an event listener.  Useful to ensure that all
213	 * events have been unbound.  Inspired by Backbone.js.
214	 */
215	var _listenedReferences = [];
216	var _listenTo = function (object, eventName, callback, bubble) {
217		object.addEventListener(eventName, callback, bubble);
218		_listenedReferences.push(arguments);
219	};
220	var _stopListeningTo = function (object, eventName, callback, bubble) {
221		if (object.removeEventListener) {
222			object.removeEventListener(eventName, callback, bubble);
223		}
224	};
225	var _stopListening = function () {
226		for (var i = _listenedReferences.length - 1; i >= 0; i--) {
227			_stopListeningTo.apply(this, _listenedReferences[i]);
228		}
229		_listenedReferences = [];
230	};
231
232	/**
233	 * Private closure for the _load function.
234	 * @param  {File} file A W3C File object
235	 * @return {void}
236	 */
237	var _loadOne = function (file) {
238		// First check for file size
239		if (self.maxFileSize !== null && file.size > self.maxFileSize) {
240			_dispatch("error", {
241				file: file,
242				message: "Attempt by client to upload file exceeding the maximum file size",
243				code: 1
244			});
245			return;
246		}
247
248		// Dispatch an event to listeners and stop now if they don't want
249		// this file to be uploaded.
250		var evntResult = _dispatch("start", {
251			file: file
252		});
253		if (!evntResult) return;
254
255		// Scope variables
256		var reader = new FileReader(),
257			id = window.siofu_global.downloads++,
258			uploadComplete = false,
259			useText = self.useText,
260			offset = 0,
261			newName;
262		if (reader._realReader) reader = reader._realReader; // Support Android Crosswalk
263		uploadedFiles[id] = file;
264
265		// An object for the outside to use to communicate with us
266		var communicator = { id: id };
267
268		// Calculate chunk size
269		var chunkSize = self.chunkSize;
270		if (chunkSize >= file.size || chunkSize <= 0) chunkSize = file.size;
271
272		// Private function to handle transmission of file data
273		var transmitPart = function (start, end, content) {
274			var isBase64 = false;
275			if (!useText) {
276				try {
277					var uintArr = new Uint8Array(content);
278
279					// Support the transmission of serialized ArrayBuffers
280					// for experimental purposes, but default to encoding the
281					// transmission in Base 64.
282					if (self.serializedOctets) {
283						content = uintArr;
284					}
285					else if (self.useBuffer) {
286						content = uintArr.buffer;
287					}
288					else {
289						isBase64 = true;
290						content = _uint8ArrayToBase64(uintArr);
291					}
292				}
293				catch (error) {
294					socket.emit(_getTopicName("_done"), _wrapData({
295						id: id,
296						interrupt: true
297					}, "done"));
298					return;
299				}
300			}
301
302			// TODO override the send data
303			socket.emit(_getTopicName("_progress"), _wrapData({
304				id: id,
305				size: file.size,
306				start: start,
307				end: end,
308				content: content,
309				base64: isBase64
310			}, "progress"));
311		};
312
313		// Callback when tranmission is complete.
314		var transmitDone = function () {
315			socket.emit(_getTopicName("_done"), _wrapData({
316				id: id
317			}, "done"));
318		};
319
320		// Load a "chunk" of the file from offset to offset+chunkSize.
321		//
322		// Note that FileReader has its own "progress" event.  However,
323		// it has not proven to be reliable enough for production. See
324		// Stack Overflow question #16713386.
325		//
326		// To compensate, we will manually load the file in chunks of a
327		// size specified by the user in the uploader.chunkSize property.
328		var processChunk = function () {
329			// Abort if we are told to do so.
330			if (communicator.abort) return;
331
332			var chunk = file.slice(offset, Math.min(offset+chunkSize, file.size));
333			if (useText) {
334				reader.readAsText(chunk);
335			}
336			else {
337				reader.readAsArrayBuffer(chunk);
338			}
339		};
340
341		// Callback for when the reader has completed a load event.
342		var loadCb = function (event) {
343			// Abort if we are told to do so.
344			if (communicator.abort) return;
345
346			// Transmit the newly loaded data to the server and emit a client event
347			var bytesLoaded = Math.min(offset+chunkSize, file.size);
348			transmitPart(offset, bytesLoaded, event.target.result);
349			_dispatch("progress", {
350				file: file,
351				bytesLoaded: bytesLoaded,
352				name: newName
353			});
354
355			// Get ready to send the next chunk
356			offset += chunkSize;
357			if (offset >= file.size) {
358				// All done!
359				transmitDone();
360				_dispatch("load", {
361					file: file,
362					reader: reader,
363					name: newName
364				});
365				uploadComplete = true;
366			}
367		};
368		_listenTo(reader, "load", loadCb);
369
370		// Listen for an "error" event.  Stop the transmission if one is received.
371		_listenTo(reader, "error", function () {
372			socket.emit(_getTopicName("_done"), _wrapData({
373				id: id,
374				interrupt: true
375			}, "done"));
376			_stopListeningTo(reader, "load", loadCb);
377		});
378
379		// Do the same for the "abort" event.
380		_listenTo(reader, "abort", function () {
381			socket.emit(_getTopicName("_done"), _wrapData({
382				id: id,
383				interrupt: true
384			}, "done"));
385			_stopListeningTo(reader, "load", loadCb);
386		});
387
388		// Transmit the "start" message to the server.
389		socket.emit(_getTopicName("_start"), _wrapData({
390			name: file.name,
391			mtime: file.lastModified,
392			meta: file.meta,
393			size: file.size,
394			encoding: useText ? "text" : "octet",
395			id: id
396		}, "start"));
397
398		// To avoid a race condition, we don't want to start transmitting to the
399		// server until the server says it is ready.
400		var readyCallback = function (_newName) {
401			newName = _newName;
402			processChunk();
403		};
404		var chunkCallback = function(){
405			if ( !uploadComplete )
406				processChunk();
407		};
408		readyCallbacks[id] = readyCallback;
409		chunkCallbacks[id] = chunkCallback;
410
411		return communicator;
412	};
413
414	/**
415	 * Private function to load the file into memory using the HTML5 FileReader object
416	 * and then transmit that file through Socket.IO.
417	 *
418	 * @param  {FileList} files An array of files
419	 * @return {void}
420	 */
421	var _load = function (files) {
422		// Iterate through the array of files.
423		for (var i = 0; i < files.length; i++) {
424			// Evaluate each file in a closure, because we will need a new
425			// instance of FileReader for each file.
426			var communicator = _loadOne(files[i]);
427			communicators[communicator.id] = communicator;
428		}
429	};
430
431	/**
432	 * Private function to fetch an HTMLInputElement instance that can be used
433	 * during the file selection process.
434	 * @return {void}
435	 */
436	var _getInputElement = function () {
437		var inpt = document.getElementById(self.fileInputElementId);
438		if (!inpt) {
439			inpt = document.createElement("input");
440			inpt.setAttribute("type", "file");
441			inpt.setAttribute("id", self.fileInputElementId);
442			inpt.style.display = "none";
443			document.body.appendChild(inpt);
444		}
445		return inpt;
446	};
447
448	/**
449	 * Private function to remove an HTMLInputElement created by this instance
450	 * of SIOFU.
451	 *
452	 * @return {void}
453	 */
454	var _removeInputElement = function () {
455		var inpt = document.getElementById(self.fileInputElementId);
456		if (inpt) {
457			inpt.parentNode.removeChild(inpt);
458		}
459	};
460
461	var _baseFileSelectCallback = function (files) {
462		if (files.length === 0) return;
463
464		// Ensure existence of meta property on each file
465		for (var i = 0; i < files.length; i++) {
466			if(!files[i].meta) files[i].meta = {};
467		}
468
469		// Dispatch the "choose" event
470		var evntResult = _dispatch("choose", {
471			files: files
472		});
473
474		// If the callback didn't return false, continue with the upload
475		if (evntResult) {
476			_load(files);
477		}
478	};
479
480	/**
481	 * Private function that serves as a callback on file input.
482	 * @param  {Event} event The file input change event
483	 * @return {void}
484	 */
485	var _fileSelectCallback = function (event) {
486		var files = event.target.files || event.dataTransfer.files;
487		event.preventDefault();
488		_baseFileSelectCallback(files);
489
490		if (self.resetFileInputs) {
491			try {
492				event.target.value = ""; //for IE11, latest Chrome/Firefox/Opera...
493			} catch(err) {
494				// ignore
495			}
496			if (event.target.value) { //for IE5 ~ IE10
497				var form = document.createElement("form"),
498				parentNode = event.target.parentNode, ref = event.target.nextSibling;
499				form.appendChild(event.target);
500				form.reset();
501				parentNode.insertBefore(event.target, ref);
502			}
503		}
504	};
505
506
507	/**
508	 * Submit files at arbitrary time
509	 * @param {FileList} files Files received form the input element.
510	 * @return {void}
511	 */
512	this.submitFiles = function (files) {
513		if (files) {
514			_baseFileSelectCallback(files);
515		}
516	};
517
518	/**
519	 * Use a submitButton to upload files from the field given
520	 * @param {HTMLInputElement} submitButton the button that the user has to
521	 *                           click to start the upload
522	 * @param {HTMLInputElement} input the field with the data to upload
523	 *
524	 * @return {void}
525	 */
526	this.listenOnSubmit = function (submitButton, input) {
527		if (!input.files) return;
528		_listenTo(submitButton, "click", function () {
529			_baseFileSelectCallback(input.files);
530		}, false);
531	};
532
533	/**
534	 * Use a submitButton to upload files from the field given
535	 * @param {HTMLInputElement} submitButton the button that the user has to
536	 *                           click to start the upload
537	 * @param {Array} array an array of fields with the files to upload
538	 *
539	 * @return {void}
540	 */
541	this.listenOnArraySubmit = function (submitButton, array) {
542		for (var index in array) {
543			this.listenOnSubmit(submitButton, array[index]);
544		}
545	};
546
547	/**
548	 * Use a file input to activate this instance of the file uploader.
549	 * @param  {HTMLInputElement} inpt The input element (e.g., as returned by
550	 *                                 document.getElementById("yourId"))
551	 * @return {void}
552	 */
553	this.listenOnInput = function (inpt) {
554		if (!inpt.files) return;
555		_listenTo(inpt, "change", _fileSelectCallback, false);
556	};
557
558	/**
559	 * Accept files dropped on an element and upload them using this instance
560	 * of the file uploader.
561	 * @param  {HTMLELement} div Any HTML element.  When the user drags a file
562	 *                           or files onto this element, those files will
563	 *                           be processed by the instance.
564	 * @return {void}
565	 */
566	this.listenOnDrop = function (div) {
567		// We need to preventDefault on the dragover event in order for the
568		// drag-and-drop operation to work.
569		_listenTo(div, "dragover", function (event) {
570			event.preventDefault();
571		}, false);
572
573		_listenTo(div, "drop", _fileSelectCallback);
574	};
575
576	/**
577	 * Display a dialog box for the user to select a file.  The file will then
578	 * be uploaded using this instance of SocketIOFileUpload.
579	 *
580	 * This method works in all current browsers except Firefox, though Opera
581	 * requires that the input element be visible.
582	 *
583	 * @return {void}
584	 */
585	this.prompt = function () {
586		var inpt = _getInputElement();
587
588		// Listen for the "change" event on the file input element.
589		_listenTo(inpt, "change", _fileSelectCallback, false);
590
591		// Fire a click event on the input element.  Firefox does not allow
592		// programatic clicks on input elements, but the other browsers do.
593		// Note that Opera requires that the element be visible when "clicked".
594		var evnt = document.createEvent("MouseEvents");
595		evnt.initMouseEvent("click", true, true, window,
596			0, 0, 0, 0, 0, false, false, false, false, 0, null);
597		inpt.dispatchEvent(evnt);
598	};
599
600	/**
601	 * Destroy an instance of Socket.IO file upload (i.e., unbind events and
602	 * relieve memory).
603	 *
604	 * IMPORTANT: To finish the memory relief process, set all external
605	 * references to this instance of SIOFU (including the reference used to
606	 * call this destroy function) to null.
607	 *
608	 * @return {void}
609	 */
610	this.destroy = function () {
611		_stopListening();
612		_removeInputElement();
613		for (var id in communicators) {
614			if (communicators.hasOwnProperty(id)) {
615				communicators[id].abort = true;
616			}
617		}
618		callbacks = null, uploadedFiles = null, readyCallbacks = null, communicators = null;
619	};
620
621	/**
622	 * Registers an event listener.  If the callback function returns false,
623	 * the file uploader will stop uploading the current file.
624	 * @param  {string}   eventName Type of event for which to listen.
625	 * @param  {Function} callback  Listener function.  Will be passed the
626	 *                              event as an argument when the event occurs.
627	 * @return {void}
628	 */
629	this.addEventListener = function (eventName, callback) {
630		if (!callbacks[eventName]) callbacks[eventName] = [];
631		callbacks[eventName].push(callback);
632	};
633
634	/**
635	 * Removes an event listener.
636	 * @param  {string}   eventName Type of event.
637	 * @param  {Function} callback  Listener function to remove.
638	 * @return {boolean}            true if callback removed; false otherwise
639	 */
640	this.removeEventListener = function (eventName, callback) {
641		if (!callbacks[eventName]) return false;
642		for (var i = 0; i < callbacks[eventName].length; i++) {
643			if (callbacks[eventName][i] === callback) {
644				callbacks[eventName].splice(i, 1);
645				return true;
646			}
647		}
648		return false;
649	};
650
651	/**
652	 * Dispatches an event into this instance's event model.
653	 * @param  {Event} evnt The event to dispatch.
654	 * @return {boolean} false if any callback returned false; true otherwise
655	 */
656	this.dispatchEvent = function (evnt) {
657		var eventCallbacks = callbacks[evnt.type];
658		if (!eventCallbacks) return true;
659		var retVal = true;
660		for (var i = 0; i < eventCallbacks.length; i++) {
661			var callbackResult = eventCallbacks[i](evnt);
662			if (callbackResult === false) {
663				retVal = false;
664			}
665		}
666		return retVal;
667	};
668
669	// OTHER LIBRARIES
670	/*
671	 * base64-arraybuffer
672	 * https://github.com/niklasvh/base64-arraybuffer
673	 *
674	 * Copyright (c) 2012 Niklas von Hertzen
675	 * Licensed under the MIT license.
676	 *
677	 * Adapted for SocketIOFileUpload.
678	 */
679	var _uint8ArrayToBase64 = function (bytes) {
680		var i, len = bytes.buffer.byteLength, base64 = "",
681			chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
682
683		for (i = 0; i < len; i += 3) {
684			base64 += chars[bytes[i] >> 2];
685			base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
686			base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
687			base64 += chars[bytes[i + 2] & 63];
688		}
689
690		if ((len % 3) === 2) {
691			base64 = base64.substring(0, base64.length - 1) + "=";
692		}
693		else if (len % 3 === 1) {
694			base64 = base64.substring(0, base64.length - 2) + "==";
695		}
696
697		return base64;
698	};
699	// END OTHER LIBRARIES
700	var _chunckCallback = function(data) {
701		if ( chunkCallbacks[data.id] )
702			chunkCallbacks[data.id]();
703	};
704
705	var _readyCallback = function (data) {
706		if (readyCallbacks[data.id])
707			readyCallbacks[data.id](data.name);
708	};
709
710	var _completCallback = function (data) {
711		if (uploadedFiles[data.id]) {
712			_dispatch("complete", {
713				file: uploadedFiles[data.id],
714				detail: data.detail,
715				success: data.success
716			});
717		}
718	};
719
720	var _errorCallback = function (data) {
721		if ( uploadedFiles[data.id] ) {
722			_dispatch("error", {
723				file: uploadedFiles[data.id],
724				message: data.message,
725				code: 0
726			});
727			if (communicators) communicators[data.id].abort = true;
728		}
729	};
730
731	// CONSTRUCTOR: Listen to the "complete", "ready", and "error" messages
732	// on the socket.
733	if (_isWrapDataWellConfigured() && self.wrapData) {
734		var mapActionToCallback = {
735			chunk: _chunckCallback,
736			ready: _readyCallback,
737			complete: _completCallback,
738			error: _errorCallback
739		};
740
741		_listenTo(socket, _getTopicName(), function (message) {
742			if (typeof message !== "object") {
743				console.log("SocketIOFileUploadClient Error: You choose to wrap your data so the message from the server need to be an object"); // eslint-disable-line no-console
744				return;
745			}
746			var actionKey = self.wrapData.unwrapKey && typeof self.wrapData.unwrapKey.action === "string" ? self.wrapData.unwrapKey.action : "action";
747			var messageKey = self.wrapData.unwrapKey && typeof self.wrapData.unwrapKey.message === "string" ? self.wrapData.unwrapKey.message : "message";
748
749			var action = message[actionKey];
750			var data = message[messageKey];
751			if (!action || !data || !mapActionToCallback[action]) {
752				console.log("SocketIOFileUploadClient Error: You choose to wrap your data but the message from the server is wrong configured. Check the message and your wrapData option"); // eslint-disable-line no-console
753				return;
754			}
755			mapActionToCallback[action](data);
756		});
757	} else {
758		_listenTo(socket, _getTopicName("_chunk"), _chunckCallback);
759		_listenTo(socket, _getTopicName("_ready"), _readyCallback);
760		_listenTo(socket, _getTopicName("_complete"), _completCallback);
761		_listenTo(socket, _getTopicName("_error"), _errorCallback);
762	}
763
764	if (this.exposePrivateFunction) {
765		this.chunckCallback = _chunckCallback;
766		this.readyCallback = _readyCallback;
767		this.completCallback = _completCallback;
768		this.errorCallback = _errorCallback;
769	}
770 };
771}));

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.