]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/swfupload/plugins/swfupload.speed.js
Wordpress 2.8
[autoinstalls/wordpress.git] / wp-includes / js / swfupload / plugins / swfupload.speed.js
1 /*\r
2         Speed Plug-in\r
3         \r
4         Features:\r
5                 *Adds several properties to the 'file' object indicated upload speed, time left, upload time, etc.\r
6                         - currentSpeed -- String indicating the upload speed, bytes per second\r
7                         - averageSpeed -- Overall average upload speed, bytes per second\r
8                         - movingAverageSpeed -- Speed over averaged over the last several measurements, bytes per second\r
9                         - timeRemaining -- Estimated remaining upload time in seconds\r
10                         - timeElapsed -- Number of seconds passed for this upload\r
11                         - percentUploaded -- Percentage of the file uploaded (0 to 100)\r
12                         - sizeUploaded -- Formatted size uploaded so far, bytes\r
13                 \r
14                 *Adds setting 'moving_average_history_size' for defining the window size used to calculate the moving average speed.\r
15                 \r
16                 *Adds several Formatting functions for formatting that values provided on the file object.\r
17                         - SWFUpload.speed.formatBPS(bps) -- outputs string formatted in the best units (Gbps, Mbps, Kbps, bps)\r
18                         - SWFUpload.speed.formatTime(seconds) -- outputs string formatted in the best units (x Hr y M z S)\r
19                         - SWFUpload.speed.formatSize(bytes) -- outputs string formatted in the best units (w GB x MB y KB z B )\r
20                         - SWFUpload.speed.formatPercent(percent) -- outputs string formatted with a percent sign (x.xx %)\r
21                         - SWFUpload.speed.formatUnits(baseNumber, divisionArray, unitLabelArray, fractionalBoolean)\r
22                                 - Formats a number using the division array to determine how to apply the labels in the Label Array\r
23                                 - factionalBoolean indicates whether the number should be returned as a single fractional number with a unit (speed)\r
24                                     or as several numbers labeled with units (time)\r
25         */\r
26 \r
27 var SWFUpload;\r
28 if (typeof(SWFUpload) === "function") {\r
29         SWFUpload.speed = {};\r
30         \r
31         SWFUpload.prototype.initSettings = (function (oldInitSettings) {\r
32                 return function () {\r
33                         if (typeof(oldInitSettings) === "function") {\r
34                                 oldInitSettings.call(this);\r
35                         }\r
36                         \r
37                         this.ensureDefault = function (settingName, defaultValue) {\r
38                                 this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];\r
39                         };\r
40 \r
41                         // List used to keep the speed stats for the files we are tracking\r
42                         this.fileSpeedStats = {};\r
43                         this.speedSettings = {};\r
44 \r
45                         this.ensureDefault("moving_average_history_size", "10");\r
46                         \r
47                         this.speedSettings.user_file_queued_handler = this.settings.file_queued_handler;\r
48                         this.speedSettings.user_file_queue_error_handler = this.settings.file_queue_error_handler;\r
49                         this.speedSettings.user_upload_start_handler = this.settings.upload_start_handler;\r
50                         this.speedSettings.user_upload_error_handler = this.settings.upload_error_handler;\r
51                         this.speedSettings.user_upload_progress_handler = this.settings.upload_progress_handler;\r
52                         this.speedSettings.user_upload_success_handler = this.settings.upload_success_handler;\r
53                         this.speedSettings.user_upload_complete_handler = this.settings.upload_complete_handler;\r
54                         \r
55                         this.settings.file_queued_handler = SWFUpload.speed.fileQueuedHandler;\r
56                         this.settings.file_queue_error_handler = SWFUpload.speed.fileQueueErrorHandler;\r
57                         this.settings.upload_start_handler = SWFUpload.speed.uploadStartHandler;\r
58                         this.settings.upload_error_handler = SWFUpload.speed.uploadErrorHandler;\r
59                         this.settings.upload_progress_handler = SWFUpload.speed.uploadProgressHandler;\r
60                         this.settings.upload_success_handler = SWFUpload.speed.uploadSuccessHandler;\r
61                         this.settings.upload_complete_handler = SWFUpload.speed.uploadCompleteHandler;\r
62                         \r
63                         delete this.ensureDefault;\r
64                 };\r
65         })(SWFUpload.prototype.initSettings);\r
66 \r
67         \r
68         SWFUpload.speed.fileQueuedHandler = function (file) {\r
69                 if (typeof this.speedSettings.user_file_queued_handler === "function") {\r
70                         file = SWFUpload.speed.extendFile(file);\r
71                         \r
72                         return this.speedSettings.user_file_queued_handler.call(this, file);\r
73                 }\r
74         };\r
75         \r
76         SWFUpload.speed.fileQueueErrorHandler = function (file, errorCode, message) {\r
77                 if (typeof this.speedSettings.user_file_queue_error_handler === "function") {\r
78                         file = SWFUpload.speed.extendFile(file);\r
79                         \r
80                         return this.speedSettings.user_file_queue_error_handler.call(this, file, errorCode, message);\r
81                 }\r
82         };\r
83 \r
84         SWFUpload.speed.uploadStartHandler = function (file) {\r
85                 if (typeof this.speedSettings.user_upload_start_handler === "function") {\r
86                         file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);\r
87                         return this.speedSettings.user_upload_start_handler.call(this, file);\r
88                 }\r
89         };\r
90         \r
91         SWFUpload.speed.uploadErrorHandler = function (file, errorCode, message) {\r
92                 file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);\r
93                 SWFUpload.speed.removeTracking(file, this.fileSpeedStats);\r
94 \r
95                 if (typeof this.speedSettings.user_upload_error_handler === "function") {\r
96                         return this.speedSettings.user_upload_error_handler.call(this, file, errorCode, message);\r
97                 }\r
98         };\r
99         SWFUpload.speed.uploadProgressHandler = function (file, bytesComplete, bytesTotal) {\r
100                 this.updateTracking(file, bytesComplete);\r
101                 file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);\r
102 \r
103                 if (typeof this.speedSettings.user_upload_progress_handler === "function") {\r
104                         return this.speedSettings.user_upload_progress_handler.call(this, file, bytesComplete, bytesTotal);\r
105                 }\r
106         };\r
107         \r
108         SWFUpload.speed.uploadSuccessHandler = function (file, serverData) {\r
109                 if (typeof this.speedSettings.user_upload_success_handler === "function") {\r
110                         file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);\r
111                         return this.speedSettings.user_upload_success_handler.call(this, file, serverData);\r
112                 }\r
113         };\r
114         SWFUpload.speed.uploadCompleteHandler = function (file) {\r
115                 file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);\r
116                 SWFUpload.speed.removeTracking(file, this.fileSpeedStats);\r
117 \r
118                 if (typeof this.speedSettings.user_upload_complete_handler === "function") {\r
119                         return this.speedSettings.user_upload_complete_handler.call(this, file);\r
120                 }\r
121         };\r
122         \r
123         // Private: extends the file object with the speed plugin values\r
124         SWFUpload.speed.extendFile = function (file, trackingList) {\r
125                 var tracking;\r
126                 \r
127                 if (trackingList) {\r
128                         tracking = trackingList[file.id];\r
129                 }\r
130                 \r
131                 if (tracking) {\r
132                         file.currentSpeed = tracking.currentSpeed;\r
133                         file.averageSpeed = tracking.averageSpeed;\r
134                         file.movingAverageSpeed = tracking.movingAverageSpeed;\r
135                         file.timeRemaining = tracking.timeRemaining;\r
136                         file.timeElapsed = tracking.timeElapsed;\r
137                         file.percentUploaded = tracking.percentUploaded;\r
138                         file.sizeUploaded = tracking.bytesUploaded;\r
139 \r
140                 } else {\r
141                         file.currentSpeed = 0;\r
142                         file.averageSpeed = 0;\r
143                         file.movingAverageSpeed = 0;\r
144                         file.timeRemaining = 0;\r
145                         file.timeElapsed = 0;\r
146                         file.percentUploaded = 0;\r
147                         file.sizeUploaded = 0;\r
148                 }\r
149                 \r
150                 return file;\r
151         };\r
152         \r
153         // Private: Updates the speed tracking object, or creates it if necessary\r
154         SWFUpload.prototype.updateTracking = function (file, bytesUploaded) {\r
155                 var tracking = this.fileSpeedStats[file.id];\r
156                 if (!tracking) {\r
157                         this.fileSpeedStats[file.id] = tracking = {};\r
158                 }\r
159                 \r
160                 // Sanity check inputs\r
161                 bytesUploaded = bytesUploaded || tracking.bytesUploaded || 0;\r
162                 if (bytesUploaded < 0) {\r
163                         bytesUploaded = 0;\r
164                 }\r
165                 if (bytesUploaded > file.size) {\r
166                         bytesUploaded = file.size;\r
167                 }\r
168                 \r
169                 var tickTime = (new Date()).getTime();\r
170                 if (!tracking.startTime) {\r
171                         tracking.startTime = (new Date()).getTime();\r
172                         tracking.lastTime = tracking.startTime;\r
173                         tracking.currentSpeed = 0;\r
174                         tracking.averageSpeed = 0;\r
175                         tracking.movingAverageSpeed = 0;\r
176                         tracking.movingAverageHistory = [];\r
177                         tracking.timeRemaining = 0;\r
178                         tracking.timeElapsed = 0;\r
179                         tracking.percentUploaded = bytesUploaded / file.size;\r
180                         tracking.bytesUploaded = bytesUploaded;\r
181                 } else if (tracking.startTime > tickTime) {\r
182                         this.debug("When backwards in time");\r
183                 } else {\r
184                         // Get time and deltas\r
185                         var now = (new Date()).getTime();\r
186                         var lastTime = tracking.lastTime;\r
187                         var deltaTime = now - lastTime;\r
188                         var deltaBytes = bytesUploaded - tracking.bytesUploaded;\r
189                         \r
190                         if (deltaBytes === 0 || deltaTime === 0) {\r
191                                 return tracking;\r
192                         }\r
193                         \r
194                         // Update tracking object\r
195                         tracking.lastTime = now;\r
196                         tracking.bytesUploaded = bytesUploaded;\r
197                         \r
198                         // Calculate speeds\r
199                         tracking.currentSpeed = (deltaBytes * 8 ) / (deltaTime / 1000);\r
200                         tracking.averageSpeed = (tracking.bytesUploaded * 8) / ((now - tracking.startTime) / 1000);\r
201 \r
202                         // Calculate moving average\r
203                         tracking.movingAverageHistory.push(tracking.currentSpeed);\r
204                         if (tracking.movingAverageHistory.length > this.settings.moving_average_history_size) {\r
205                                 tracking.movingAverageHistory.shift();\r
206                         }\r
207                         \r
208                         tracking.movingAverageSpeed = SWFUpload.speed.calculateMovingAverage(tracking.movingAverageHistory);\r
209                         \r
210                         // Update times\r
211                         tracking.timeRemaining = (file.size - tracking.bytesUploaded) * 8 / tracking.movingAverageSpeed;\r
212                         tracking.timeElapsed = (now - tracking.startTime) / 1000;\r
213                         \r
214                         // Update percent\r
215                         tracking.percentUploaded = (tracking.bytesUploaded / file.size * 100);\r
216                 }\r
217                 \r
218                 return tracking;\r
219         };\r
220         SWFUpload.speed.removeTracking = function (file, trackingList) {\r
221                 try {\r
222                         trackingList[file.id] = null;\r
223                         delete trackingList[file.id];\r
224                 } catch (ex) {\r
225                 }\r
226         };\r
227         \r
228         SWFUpload.speed.formatUnits = function (baseNumber, unitDivisors, unitLabels, singleFractional) {\r
229                 var i, unit, unitDivisor, unitLabel;\r
230 \r
231                 if (baseNumber === 0) {\r
232                         return "0 " + unitLabels[unitLabels.length - 1];\r
233                 }\r
234                 \r
235                 if (singleFractional) {\r
236                         unit = baseNumber;\r
237                         unitLabel = unitLabels.length >= unitDivisors.length ? unitLabels[unitDivisors.length - 1] : "";\r
238                         for (i = 0; i < unitDivisors.length; i++) {\r
239                                 if (baseNumber >= unitDivisors[i]) {\r
240                                         unit = (baseNumber / unitDivisors[i]).toFixed(2);\r
241                                         unitLabel = unitLabels.length >= i ? " " + unitLabels[i] : "";\r
242                                         break;\r
243                                 }\r
244                         }\r
245                         \r
246                         return unit + unitLabel;\r
247                 } else {\r
248                         var formattedStrings = [];\r
249                         var remainder = baseNumber;\r
250                         \r
251                         for (i = 0; i < unitDivisors.length; i++) {\r
252                                 unitDivisor = unitDivisors[i];\r
253                                 unitLabel = unitLabels.length > i ? " " + unitLabels[i] : "";\r
254                                 \r
255                                 unit = remainder / unitDivisor;\r
256                                 if (i < unitDivisors.length -1) {\r
257                                         unit = Math.floor(unit);\r
258                                 } else {\r
259                                         unit = unit.toFixed(2);\r
260                                 }\r
261                                 if (unit > 0) {\r
262                                         remainder = remainder % unitDivisor;\r
263                                         \r
264                                         formattedStrings.push(unit + unitLabel);\r
265                                 }\r
266                         }\r
267                         \r
268                         return formattedStrings.join(" ");\r
269                 }\r
270         };\r
271         \r
272         SWFUpload.speed.formatBPS = function (baseNumber) {\r
273                 var bpsUnits = [1073741824, 1048576, 1024, 1], bpsUnitLabels = ["Gbps", "Mbps", "Kbps", "bps"];\r
274                 return SWFUpload.speed.formatUnits(baseNumber, bpsUnits, bpsUnitLabels, true);\r
275         \r
276         };\r
277         SWFUpload.speed.formatTime = function (baseNumber) {\r
278                 var timeUnits = [86400, 3600, 60, 1], timeUnitLabels = ["d", "h", "m", "s"];\r
279                 return SWFUpload.speed.formatUnits(baseNumber, timeUnits, timeUnitLabels, false);\r
280         \r
281         };\r
282         SWFUpload.speed.formatBytes = function (baseNumber) {\r
283                 var sizeUnits = [1073741824, 1048576, 1024, 1], sizeUnitLabels = ["GB", "MB", "KB", "bytes"];\r
284                 return SWFUpload.speed.formatUnits(baseNumber, sizeUnits, sizeUnitLabels, true);\r
285         \r
286         };\r
287         SWFUpload.speed.formatPercent = function (baseNumber) {\r
288                 return baseNumber.toFixed(2) + " %";\r
289         };\r
290         \r
291         SWFUpload.speed.calculateMovingAverage = function (history) {\r
292                 var vals = [], size, sum = 0.0, mean = 0.0, varianceTemp = 0.0, variance = 0.0, standardDev = 0.0;\r
293                 var i;\r
294                 var mSum = 0, mCount = 0;\r
295                 \r
296                 size = history.length;\r
297                 \r
298                 // Check for sufficient data\r
299                 if (size >= 8) {\r
300                         // Clone the array and Calculate sum of the values \r
301                         for (i = 0; i < size; i++) {\r
302                                 vals[i] = history[i];\r
303                                 sum += vals[i];\r
304                         }\r
305 \r
306                         mean = sum / size;\r
307 \r
308                         // Calculate variance for the set\r
309                         for (i = 0; i < size; i++) {\r
310                                 varianceTemp += Math.pow((vals[i] - mean), 2);\r
311                         }\r
312 \r
313                         variance = varianceTemp / size;\r
314                         standardDev = Math.sqrt(variance);\r
315                         \r
316                         //Standardize the Data\r
317                         for (i = 0; i < size; i++) {\r
318                                 vals[i] = (vals[i] - mean) / standardDev;\r
319                         }\r
320 \r
321                         // Calculate the average excluding outliers\r
322                         var deviationRange = 2.0;\r
323                         for (i = 0; i < size; i++) {\r
324                                 \r
325                                 if (vals[i] <= deviationRange && vals[i] >= -deviationRange) {\r
326                                         mCount++;\r
327                                         mSum += history[i];\r
328                                 }\r
329                         }\r
330                         \r
331                 } else {\r
332                         // Calculate the average (not enough data points to remove outliers)\r
333                         mCount = size;\r
334                         for (i = 0; i < size; i++) {\r
335                                 mSum += history[i];\r
336                         }\r
337                 }\r
338 \r
339                 return mSum / mCount;\r
340         };\r
341         \r
342 }