171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
1 |
/* IVLE - Informatics Virtual Learning Environment
|
2 |
* Copyright (C) 2007-2008 The University of Melbourne
|
|
3 |
*
|
|
4 |
* This program is free software; you can redistribute it and/or modify
|
|
5 |
* it under the terms of the GNU General Public License as published by
|
|
6 |
* the Free Software Foundation; either version 2 of the License, or
|
|
7 |
* (at your option) any later version.
|
|
8 |
*
|
|
9 |
* This program is distributed in the hope that it will be useful,
|
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12 |
* GNU General Public License for more details.
|
|
13 |
*
|
|
14 |
* You should have received a copy of the GNU General Public License
|
|
15 |
* along with this program; if not, write to the Free Software
|
|
16 |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17 |
*
|
|
18 |
* Module: JavaScript Utilities
|
|
19 |
* Author: Matt Giuca
|
|
20 |
* Date: 11/1/2008
|
|
21 |
*
|
|
22 |
* Defines some generic JavaScript utility functions.
|
|
23 |
*/
|
|
24 |
||
200
by mattgiuca
fileservice.listing: Now returns a nicer date format for mtime_nice. |
25 |
/* Expects the following variables to have been declared by JavaScript in
|
26 |
* the HTML generated by the server:
|
|
27 |
* - root_dir
|
|
728
by dcoles
Browser: Added support for the 'Share this file' button. At the moment it opens |
28 |
* - public_host
|
200
by mattgiuca
fileservice.listing: Now returns a nicer date format for mtime_nice. |
29 |
* - username
|
30 |
*/
|
|
31 |
||
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
32 |
/** Removes all children of a given DOM element
|
33 |
* \param elem A DOM Element. Will be modified.
|
|
34 |
*/
|
|
35 |
function dom_removechildren(elem) |
|
36 |
{
|
|
37 |
while (elem.lastChild != null) |
|
38 |
elem.removeChild(elem.lastChild); |
|
39 |
}
|
|
40 |
||
41 |
/** Creates a DOM element with simple text inside it.
|
|
42 |
* \param tagname String. Name of the element's tag (eg. "p").
|
|
43 |
* \param text String. Text to be placed inside the element.
|
|
200
by mattgiuca
fileservice.listing: Now returns a nicer date format for mtime_nice. |
44 |
* \param title String, optional. Tooltip for the text.
|
45 |
* (Note, title creates a span element around the text).
|
|
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
46 |
* \return DOM Element object.
|
47 |
*/
|
|
200
by mattgiuca
fileservice.listing: Now returns a nicer date format for mtime_nice. |
48 |
function dom_make_text_elem(tagname, text, title) |
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
49 |
{
|
188
by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!) |
50 |
if (text == null) text = ""; |
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
51 |
var elem = document.createElement(tagname); |
200
by mattgiuca
fileservice.listing: Now returns a nicer date format for mtime_nice. |
52 |
var textnode; |
53 |
if (title == null) |
|
54 |
textnode = document.createTextNode(text); |
|
55 |
else
|
|
56 |
{
|
|
57 |
textnode = document.createElement("span"); |
|
58 |
textnode.setAttribute("title", title); |
|
59 |
textnode.appendChild(document.createTextNode(text)); |
|
60 |
}
|
|
61 |
elem.appendChild(textnode); |
|
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
62 |
return elem; |
63 |
}
|
|
64 |
||
65 |
/** Creates a DOM element with hyperlinked text inside it.
|
|
66 |
* \param tagname String. Name of the element's tag (eg. "p").
|
|
67 |
* \param text String. Text to be placed inside the element.
|
|
200
by mattgiuca
fileservice.listing: Now returns a nicer date format for mtime_nice. |
68 |
* \param title String, optional. Sets a tooltip for the link.
|
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
69 |
* \param href String. URL the text will link to. This is a raw string,
|
70 |
* it will automatically be URL-encoded.
|
|
71 |
* \param onclick Optional string. Will be set as the "onclick" attribute
|
|
72 |
* of the "a" element.
|
|
241
by mattgiuca
util.js: dom_make_link_elem: Added argument dontencode, necessary to sometimes |
73 |
* \param dontencode Optional boolean. If true, will not encode the href.
|
74 |
* if including query strings, you must set this to true and use build_url
|
|
75 |
* to escape the URI correctly.
|
|
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
76 |
* \return DOM Element object.
|
77 |
*/
|
|
241
by mattgiuca
util.js: dom_make_link_elem: Added argument dontencode, necessary to sometimes |
78 |
function dom_make_link_elem(tagname, text, title, href, onclick, dontencode) |
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
79 |
{
|
188
by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!) |
80 |
if (text == null) text = ""; |
81 |
if (href == null) href = ""; |
|
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
82 |
var elem = document.createElement(tagname); |
83 |
var link = document.createElement("a"); |
|
241
by mattgiuca
util.js: dom_make_link_elem: Added argument dontencode, necessary to sometimes |
84 |
if (dontencode != true) |
85 |
href = urlencode_path(href); |
|
86 |
link.setAttribute("href", href); |
|
200
by mattgiuca
fileservice.listing: Now returns a nicer date format for mtime_nice. |
87 |
if (title != null) |
88 |
link.setAttribute("title", title); |
|
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
89 |
if (onclick != null) |
90 |
link.setAttribute("onclick", onclick); |
|
91 |
link.appendChild(document.createTextNode(text)); |
|
92 |
elem.appendChild(link); |
|
93 |
return elem; |
|
94 |
}
|
|
95 |
||
190
by mattgiuca
util: Added function dom_make_img, creates <img> elements. |
96 |
/** Creates a DOM img element. All parameters are optional except src.
|
97 |
* If alt (compulsory in HTML) is omitted, will be set to "".
|
|
98 |
*/
|
|
99 |
function dom_make_img(src, width, height, title, alt) |
|
100 |
{
|
|
101 |
var img = document.createElement("img"); |
|
234
by mattgiuca
browser/listing.js: |
102 |
img.setAttribute("src", urlencode_path(src)); |
190
by mattgiuca
util: Added function dom_make_img, creates <img> elements. |
103 |
if (width != null) |
104 |
img.setAttribute("width", width); |
|
105 |
if (height != null) |
|
106 |
img.setAttribute("height", height); |
|
107 |
if (title != null) |
|
108 |
img.setAttribute("title", title); |
|
109 |
if (alt == null) alt = ""; |
|
110 |
img.setAttribute("alt", alt); |
|
111 |
return img; |
|
112 |
}
|
|
113 |
||
180
by mattgiuca
util: Added function nice_filesize. |
114 |
/** Given a number of bytes, returns a string representing the file size in a
|
115 |
* human-readable format.
|
|
116 |
* eg. nice_filesize(6) -> "6 bytes"
|
|
117 |
* nice_filesize(81275) -> "79.4 kB"
|
|
118 |
* nice_filesize(13498346) -> "12.9 MB"
|
|
119 |
* \param bytes Number of bytes. Must be an integer.
|
|
120 |
* \return String.
|
|
121 |
*/
|
|
122 |
function nice_filesize(bytes) |
|
123 |
{
|
|
188
by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!) |
124 |
if (bytes == null) return ""; |
180
by mattgiuca
util: Added function nice_filesize. |
125 |
var size; |
126 |
if (bytes < 1024) |
|
188
by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!) |
127 |
return bytes.toString() + " B"; |
180
by mattgiuca
util: Added function nice_filesize. |
128 |
size = bytes / 1024; |
129 |
if (size < 1024) |
|
130 |
return size.toFixed(1) + " kB"; |
|
131 |
size = size / 1024; |
|
132 |
if (size < 1024) |
|
133 |
return size.toFixed(1) + " MB"; |
|
134 |
size = size / 1024; |
|
135 |
return size.toFixed(1) + " GB"; |
|
136 |
}
|
|
137 |
||
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
138 |
/** Given a URL, returns an object containing a number of attributes
|
139 |
* describing the components of the URL, similar to CGI request variables.
|
|
140 |
* The object has the following attributes:
|
|
141 |
* - scheme
|
|
142 |
* - server_name
|
|
143 |
* - server_port
|
|
144 |
* - path
|
|
145 |
* - query_string
|
|
146 |
* - args
|
|
147 |
* The first five of these are strings, which comprise the URL as follows:
|
|
148 |
* <scheme> "://" <server_name> ":" <server_port> <path> "?" <query_string>
|
|
149 |
* Any of these strings may be set to null if not found.
|
|
150 |
*
|
|
151 |
* "args" is an object whose attributes are the query_string arguments broken
|
|
152 |
* up.
|
|
153 |
* Args values are strings for single values, arrays of strings for values
|
|
154 |
* whose names appear multiple times.
|
|
155 |
* args is never null, though it may be empty.
|
|
156 |
*
|
|
174
by mattgiuca
util: Fixed up URL encoding; documented properly. |
157 |
* All strings are decoded/unescaped. Reserved characters
|
225
by mattgiuca
util.js: Yet more fixes for encoding/decoding URIs. build_url and parse_url |
158 |
* (; , / ? : @ & = + * $) are not decoded except in args and path.
|
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
159 |
*
|
160 |
* \param url String. A URL. To read from the current browser window, use
|
|
161 |
* window.location.href.
|
|
162 |
* \return The above described object.
|
|
163 |
*/
|
|
164 |
function parse_url(url) |
|
165 |
{
|
|
166 |
var obj = {}; |
|
167 |
var index; |
|
168 |
var serverpart; |
|
169 |
var args; |
|
170 |
||
171 |
/* Split scheme from rest */
|
|
172 |
index = url.indexOf("://"); |
|
173 |
if (index < 0) |
|
174 |
obj.scheme = null; |
|
175 |
else
|
|
176 |
{
|
|
177 |
obj.scheme = url.substr(0, index); |
|
178 |
url = url.substr(index+3); |
|
179 |
}
|
|
180 |
||
181 |
/* Split server name/port from rest */
|
|
182 |
index = url.indexOf("/"); |
|
183 |
if (index < 0) |
|
184 |
{
|
|
185 |
serverpart = url; |
|
186 |
url = null; |
|
187 |
}
|
|
188 |
else
|
|
189 |
{
|
|
190 |
serverpart = url.substr(0, index); |
|
187
by mattgiuca
util.js: Minor fix to parse_url: Path needs to begin with a '/' |
191 |
url = url.substr(index); |
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
192 |
}
|
193 |
||
194 |
/* Split server name from port */
|
|
195 |
index = serverpart.indexOf(":"); |
|
196 |
if (index < 0) |
|
197 |
{
|
|
198 |
obj.server_name = serverpart; |
|
199 |
obj.server_port = null; |
|
200 |
}
|
|
201 |
else
|
|
202 |
{
|
|
203 |
obj.server_name = serverpart.substr(0, index); |
|
204 |
obj.server_port = serverpart.substr(index+1); |
|
205 |
}
|
|
206 |
||
207 |
/* Split path from query string */
|
|
208 |
if (url == null) |
|
209 |
{
|
|
210 |
obj.path = null; |
|
211 |
obj.query_string = null; |
|
212 |
}
|
|
213 |
else
|
|
214 |
{
|
|
215 |
index = url.indexOf("?"); |
|
216 |
if (index < 0) |
|
217 |
{
|
|
218 |
obj.path = url; |
|
219 |
obj.query_string = null; |
|
220 |
}
|
|
221 |
else
|
|
222 |
{
|
|
223 |
obj.path = url.substr(0, index); |
|
224 |
obj.query_string = url.substr(index+1); |
|
225 |
}
|
|
226 |
}
|
|
225
by mattgiuca
util.js: Yet more fixes for encoding/decoding URIs. build_url and parse_url |
227 |
obj.path = decodeURIComponent(obj.path); |
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
228 |
|
229 |
/* Split query string into arguments */
|
|
230 |
args = {}; |
|
231 |
if (obj.query_string != null) |
|
232 |
{
|
|
233 |
var args_strs = obj.query_string.split("&"); |
|
234 |
var arg_str; |
|
235 |
var arg_key, arg_val; |
|
236 |
for (var i=0; i<args_strs.length; i++) |
|
237 |
{
|
|
238 |
arg_str = args_strs[i]; |
|
239 |
index = arg_str.indexOf("="); |
|
240 |
/* Ignore malformed args */
|
|
241 |
if (index >= 0) |
|
242 |
{
|
|
174
by mattgiuca
util: Fixed up URL encoding; documented properly. |
243 |
arg_key = decodeURIComponent(arg_str.substr(0, index)); |
244 |
arg_val = decodeURIComponent(arg_str.substr(index+1)); |
|
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
245 |
if (arg_key in args) |
246 |
{
|
|
247 |
/* Collision - make an array */
|
|
248 |
if (args[arg_key] instanceof Array) |
|
249 |
args[arg_key][args[arg_key].length] = arg_val; |
|
250 |
else
|
|
251 |
args[arg_key] = [args[arg_key], arg_val]; |
|
252 |
}
|
|
253 |
else
|
|
254 |
args[arg_key] = arg_val; |
|
255 |
}
|
|
256 |
}
|
|
257 |
}
|
|
258 |
obj.args = args; |
|
259 |
||
260 |
return obj; |
|
261 |
}
|
|
262 |
||
177
by mattgiuca
util: Split the creation of the query string in build_url into |
263 |
/** Builds a query_string from an args object. Encodes the arguments.
|
264 |
* \param args Args object as described in parse_url.
|
|
265 |
* \return Query string portion of a URL.
|
|
266 |
*/
|
|
267 |
function make_query_string(args) |
|
268 |
{
|
|
269 |
var query_string = ""; |
|
270 |
var arg_val; |
|
271 |
for (var arg_key in args) |
|
272 |
{
|
|
273 |
arg_val = args[arg_key]; |
|
274 |
if (arg_val instanceof Array) |
|
275 |
for (var i=0; i<arg_val.length; i++) |
|
276 |
query_string += "&" + encodeURIComponent(arg_key) + "=" + |
|
277 |
encodeURIComponent(arg_val[i]); |
|
278 |
else
|
|
279 |
query_string += "&" + encodeURIComponent(arg_key) + "=" + |
|
280 |
encodeURIComponent(arg_val); |
|
281 |
}
|
|
441
by drtomc
make_query_string - change the interface so that it no longer returns null. |
282 |
if (query_string != "") |
177
by mattgiuca
util: Split the creation of the query string in build_url into |
283 |
/* Drop the first "&" */
|
284 |
query_string = query_string.substr(1); |
|
285 |
||
286 |
return query_string; |
|
287 |
}
|
|
288 |
||
172
by mattgiuca
util: Added buildurl function. |
289 |
/** Given an object exactly of the form described for the output of parseurl,
|
174
by mattgiuca
util: Fixed up URL encoding; documented properly. |
290 |
* returns a URL string built from those parameters. The URL is properly
|
291 |
* encoded.
|
|
172
by mattgiuca
util: Added buildurl function. |
292 |
* parseurl and buildurl are strict inverses of each other.
|
293 |
* Note that either query_string or args may be supplied. If both are
|
|
294 |
* supplied, query_string is preferred (because it keeps the argument order).
|
|
295 |
* If you take a url from parseurl, modify args, and pass to buildurl,
|
|
296 |
* you need to set query_string to null to use the new args.
|
|
297 |
* \param obj Object as returned by parseurl.
|
|
298 |
* \return String, a URL.
|
|
299 |
*/
|
|
173
by mattgiuca
util.build_url: Added _ for consistency. Fixed logic concerning missing |
300 |
function build_url(obj) |
172
by mattgiuca
util: Added buildurl function. |
301 |
{
|
302 |
var url = ""; |
|
303 |
var query_string = null; |
|
304 |
||
173
by mattgiuca
util.build_url: Added _ for consistency. Fixed logic concerning missing |
305 |
if (("scheme" in obj) && obj.scheme != null) |
172
by mattgiuca
util: Added buildurl function. |
306 |
url = obj.scheme.toString() + "://"; |
173
by mattgiuca
util.build_url: Added _ for consistency. Fixed logic concerning missing |
307 |
if (("server_name" in obj) && obj.server_name != null) |
172
by mattgiuca
util: Added buildurl function. |
308 |
url += obj.server_name.toString(); |
173
by mattgiuca
util.build_url: Added _ for consistency. Fixed logic concerning missing |
309 |
if (("server_port" in obj) && obj.server_port != null) |
172
by mattgiuca
util: Added buildurl function. |
310 |
url += ":" + obj.server_port.toString(); |
173
by mattgiuca
util.build_url: Added _ for consistency. Fixed logic concerning missing |
311 |
if (("path" in obj) && obj.path != null) |
172
by mattgiuca
util: Added buildurl function. |
312 |
{
|
225
by mattgiuca
util.js: Yet more fixes for encoding/decoding URIs. build_url and parse_url |
313 |
var path = urlencode_path(obj.path.toString()); |
770
by mattgiuca
media/common/util.js: Internet Explorer compatibility. |
314 |
if (url.length > 0 && path.length > 0 && path.charAt(0) != "/") |
172
by mattgiuca
util: Added buildurl function. |
315 |
path = "/" + path; |
316 |
url += path; |
|
317 |
}
|
|
173
by mattgiuca
util.build_url: Added _ for consistency. Fixed logic concerning missing |
318 |
if (("query_string" in obj) && obj.query_string != null) |
225
by mattgiuca
util.js: Yet more fixes for encoding/decoding URIs. build_url and parse_url |
319 |
query_string = encodeURI(obj.query_string.toString()); |
173
by mattgiuca
util.build_url: Added _ for consistency. Fixed logic concerning missing |
320 |
else if (("args" in obj) && obj.args != null) |
177
by mattgiuca
util: Split the creation of the query string in build_url into |
321 |
query_string = make_query_string(obj.args); |
172
by mattgiuca
util: Added buildurl function. |
322 |
|
442
by drtomc
util.js: Small fix for make_query_string. |
323 |
if (query_string != "" && query_string != null) |
172
by mattgiuca
util: Added buildurl function. |
324 |
url += "?" + query_string; |
325 |
||
225
by mattgiuca
util.js: Yet more fixes for encoding/decoding URIs. build_url and parse_url |
326 |
return url; |
172
by mattgiuca
util: Added buildurl function. |
327 |
}
|
328 |
||
223
by mattgiuca
util.js: Added "urlencode_path" which is specially designed to encode paths. |
329 |
/** URL-encodes a path. This is a special case of URL encoding as all
|
330 |
* characters *except* the slash must be encoded.
|
|
331 |
*/
|
|
332 |
function urlencode_path(path) |
|
333 |
{
|
|
334 |
/* Split up the path, URLEncode each segment with encodeURIComponent,
|
|
335 |
* and rejoin.
|
|
336 |
*/
|
|
337 |
var split = path.split('/'); |
|
338 |
for (var i=0; i<split.length; i++) |
|
339 |
split[i] = encodeURIComponent(split[i]); |
|
340 |
path = path_join.apply(null, split); |
|
232
by mattgiuca
common/util.js: Fixed urlencode_path - empty paths no longer get a mysterious |
341 |
if (split[0] == "" && split.length > 1) path = "/" + path; |
223
by mattgiuca
util.js: Added "urlencode_path" which is specially designed to encode paths. |
342 |
return path; |
343 |
}
|
|
344 |
||
651
by mattgiuca
util.js: Added write_cookie and read_cookie functions for JavaScript, |
345 |
/** Writes a JSONable object to the cookie under a particular key
|
346 |
* (JSON encoded and URL encoded).
|
|
347 |
*/
|
|
348 |
function write_cookie(key, value) |
|
349 |
{
|
|
350 |
var sendstr = encodeURIComponent(key) + "=" |
|
652
by mattgiuca
util.js: write_cookie now sets the cookie's path to root_dir, so that |
351 |
+ encodeURIComponent(JSON.stringify(value)) |
352 |
+ "; path=" + urlencode_path(root_dir); |
|
651
by mattgiuca
util.js: Added write_cookie and read_cookie functions for JavaScript, |
353 |
/* This actually just assigns to the key, not replacing the whole cookie
|
354 |
* as it appears to. */
|
|
355 |
document.cookie = sendstr; |
|
356 |
}
|
|
357 |
/** Reads a cookie which has a JSONable object encoded as its value.
|
|
358 |
* Returns the object, parsed from JSON.
|
|
359 |
*/
|
|
360 |
function read_cookie(key) |
|
361 |
{
|
|
362 |
var cookies = document.cookie.split(";"); |
|
363 |
var checkstart = encodeURIComponent(key) + "="; |
|
364 |
var checklen = checkstart.length; |
|
365 |
for (var i=0; i<cookies.length; i++) |
|
366 |
{
|
|
367 |
var cookie = cookies[i]; |
|
368 |
while (cookie[0] == ' ') |
|
369 |
cookie = cookie.substr(1); |
|
370 |
if (cookie.substr(0, checklen) == checkstart) |
|
371 |
{
|
|
372 |
var valstr = cookie.substr(checklen); |
|
373 |
valstr = decodeURIComponent(valstr); |
|
374 |
return JSON.parse(valstr); |
|
375 |
}
|
|
376 |
}
|
|
377 |
}
|
|
378 |
||
171
by mattgiuca
Added "util.js" in common. Contains useful utility functions. |
379 |
/** Given an argument map, as output in the args parameter of the return of
|
380 |
* parseurl, gets the first occurence of an argument in the URL string.
|
|
381 |
* If the argument was not found, returns null.
|
|
382 |
* If there was a single argument, returns the argument.
|
|
383 |
* If there were multiple arguments, returns the first.
|
|
384 |
* \param args Object mapping arguments to strings or arrays of strings.
|
|
385 |
* \param arg String. Argument name.
|
|
386 |
* \return String.
|
|
387 |
*/
|
|
388 |
function arg_getfirst(args, arg) |
|
389 |
{
|
|
390 |
if (!(arg in args)) |
|
391 |
return null; |
|
392 |
var r = args[arg]; |
|
393 |
if (r instanceof Array) |
|
394 |
return r[0]; |
|
395 |
else
|
|
396 |
return r; |
|
397 |
}
|
|
398 |
||
399 |
/** Given an argument map, as output in the args parameter of the return of
|
|
400 |
* parseurl, gets all occurences of an argument in the URL string, as an
|
|
401 |
* array.
|
|
402 |
* If the argument was not found, returns [].
|
|
403 |
* Otherwise, returns all occurences as an array, even if there was only one.
|
|
404 |
* \param args Object mapping arguments to strings or arrays of strings.
|
|
405 |
* \param arg String. Argument name.
|
|
406 |
* \return Array of strings.
|
|
407 |
*/
|
|
408 |
function arg_getlist(args, arg) |
|
409 |
{
|
|
410 |
if (!(arg in args)) |
|
411 |
return []; |
|
412 |
var r = args[arg]; |
|
413 |
if (r instanceof Array) |
|
414 |
return r; |
|
415 |
else
|
|
416 |
return [r]; |
|
417 |
}
|
|
173
by mattgiuca
util.build_url: Added _ for consistency. Fixed logic concerning missing |
418 |
|
175
by mattgiuca
dispatch.html: HTML headers for all pages now include a JavaScript |
419 |
/** Joins one or more paths together. Accepts 1 or more arguments.
|
420 |
*/
|
|
421 |
function path_join(path1 /*, path2, ... */) |
|
422 |
{
|
|
423 |
var arg; |
|
200
by mattgiuca
fileservice.listing: Now returns a nicer date format for mtime_nice. |
424 |
var path = ""; |
425 |
for (var i=0; i<arguments.length; i++) |
|
175
by mattgiuca
dispatch.html: HTML headers for all pages now include a JavaScript |
426 |
{
|
427 |
arg = arguments[i]; |
|
428 |
if (arg.length == 0) continue; |
|
770
by mattgiuca
media/common/util.js: Internet Explorer compatibility. |
429 |
if (arg.charAt(0) == '/') |
175
by mattgiuca
dispatch.html: HTML headers for all pages now include a JavaScript |
430 |
path = arg; |
431 |
else
|
|
432 |
{
|
|
770
by mattgiuca
media/common/util.js: Internet Explorer compatibility. |
433 |
if (path.length > 0 && path.charAt(path.length-1) != '/') |
175
by mattgiuca
dispatch.html: HTML headers for all pages now include a JavaScript |
434 |
path += '/'; |
435 |
path += arg; |
|
436 |
}
|
|
437 |
}
|
|
438 |
return path; |
|
439 |
}
|
|
440 |
||
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
441 |
|
442 |
/** Builds a multipart_formdata string from an args object. Similar to
|
|
443 |
* make_query_string, but it returns data of type "multipart/form-data"
|
|
444 |
* instead of "application/x-www-form-urlencoded". This is good for
|
|
445 |
* encoding large strings such as text objects from the editor.
|
|
446 |
* Should be written with a Content-Type of
|
|
447 |
* "multipart/form-data, boundary=<boundary>".
|
|
448 |
* All fields are sent with a Content-Type of text/plain.
|
|
449 |
* \param args Args object as described in parse_url.
|
|
450 |
* \param boundary Random "magic" string which DOES NOT appear in any of
|
|
451 |
* the argument values. This should match the "boundary=" value written to
|
|
452 |
* the Content-Type header.
|
|
453 |
* \return String in multipart/form-data format.
|
|
454 |
*/
|
|
455 |
function make_multipart_formdata(args, boundary) |
|
456 |
{
|
|
457 |
var data = ""; |
|
458 |
var arg_val; |
|
459 |
/* Mutates data */
|
|
460 |
var extend_data = function(arg_key, arg_val) |
|
461 |
{
|
|
462 |
/* FIXME: Encoding not supported here (should not matter if we
|
|
463 |
* only use ASCII names */
|
|
308
by mattgiuca
util.js: Multipart/form-data output: Newlines are \r\n instead of \n. |
464 |
data += "--" + boundary + "\r\n" |
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
465 |
+ "Content-Disposition: form-data; name=\"" + arg_key |
308
by mattgiuca
util.js: Multipart/form-data output: Newlines are \r\n instead of \n. |
466 |
+ "\"\r\n\r\n" |
467 |
+ arg_val + "\r\n"; |
|
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
468 |
}
|
469 |
||
470 |
for (var arg_key in args) |
|
471 |
{
|
|
472 |
arg_val = args[arg_key]; |
|
473 |
if (arg_val instanceof Array) |
|
474 |
for (var i=0; i<arg_val.length; i++) |
|
475 |
{
|
|
476 |
extend_data(arg_key, arg_val[i]); |
|
477 |
}
|
|
478 |
else
|
|
479 |
extend_data(arg_key, arg_val); |
|
480 |
}
|
|
481 |
/* End boundary */
|
|
308
by mattgiuca
util.js: Multipart/form-data output: Newlines are \r\n instead of \n. |
482 |
data += "--" + boundary + "--\r\n"; |
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
483 |
|
484 |
return data; |
|
485 |
}
|
|
486 |
||
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
487 |
/** Converts a list of directories into a path name, with a slash at the end.
|
488 |
* \param pathlist List of strings.
|
|
489 |
* \return String.
|
|
490 |
*/
|
|
491 |
function pathlist_to_path(pathlist) |
|
492 |
{
|
|
493 |
ret = path_join.apply(null, pathlist); |
|
770
by mattgiuca
media/common/util.js: Internet Explorer compatibility. |
494 |
if (ret.charAt(ret.length-1) != '/') |
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
495 |
ret += '/'; |
496 |
return ret; |
|
497 |
}
|
|
498 |
||
175
by mattgiuca
dispatch.html: HTML headers for all pages now include a JavaScript |
499 |
/** Given a path relative to the IVLE root, gives a path relative to
|
500 |
* the site root.
|
|
501 |
*/
|
|
502 |
function make_path(path) |
|
503 |
{
|
|
504 |
return path_join(root_dir, path); |
|
505 |
}
|
|
506 |
||
224
by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called |
507 |
/** Shorthand for make_path(path_join(app, ...))
|
508 |
* Creates an absolute path for a given path within a given app.
|
|
223
by mattgiuca
util.js: Added "urlencode_path" which is specially designed to encode paths. |
509 |
*/
|
224
by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called |
510 |
function app_path(app /*,...*/) |
223
by mattgiuca
util.js: Added "urlencode_path" which is specially designed to encode paths. |
511 |
{
|
224
by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called |
512 |
return make_path(path_join.apply(null, arguments)); |
223
by mattgiuca
util.js: Added "urlencode_path" which is specially designed to encode paths. |
513 |
}
|
514 |
||
1661
by Matt Giuca
browser.js: Fixed generation of links in file browser to Serve, Download and Share-this-file links containing special URI characters. Now properly URL-encoded. Added util.js app_url and public_app_url, replacing calls to app_path and public_app_path. Fixes Launchpad bug #524176. |
515 |
/** Same as app_path but creates a properly-escaped site-relative URL.
|
516 |
*/
|
|
517 |
function app_url(app /*,...*/) |
|
518 |
{
|
|
519 |
return urlencode_path(app_path.apply(null, arguments)); |
|
520 |
}
|
|
521 |
||
728
by dcoles
Browser: Added support for the 'Share this file' button. At the moment it opens |
522 |
/** Generates an absolute URL to a public application
|
523 |
*/
|
|
1661
by Matt Giuca
browser.js: Fixed generation of links in file browser to Serve, Download and Share-this-file links containing special URI characters. Now properly URL-encoded. Added util.js app_url and public_app_url, replacing calls to app_path and public_app_path. Fixes Launchpad bug #524176. |
524 |
function public_app_url(app /*,...*/) |
728
by dcoles
Browser: Added support for the 'Share this file' button. At the moment it opens |
525 |
{
|
1661
by Matt Giuca
browser.js: Fixed generation of links in file browser to Serve, Download and Share-this-file links containing special URI characters. Now properly URL-encoded. Added util.js app_url and public_app_url, replacing calls to app_path and public_app_path. Fixes Launchpad bug #524176. |
526 |
return "http://" + public_host + app_url.apply(null, arguments); |
728
by dcoles
Browser: Added support for the 'Share this file' button. At the moment it opens |
527 |
}
|
528 |
||
208
by mattgiuca
dispatch.html, ivle.css: "apptabs" is now an ID, not a class. |
529 |
/** Given a path, gets the "basename" (the last path segment).
|
530 |
*/
|
|
531 |
function path_basename(path) |
|
532 |
{
|
|
533 |
segments = path.split("/"); |
|
534 |
if (segments[segments.length-1].length == 0) |
|
535 |
return segments[segments.length-2]; |
|
536 |
else
|
|
537 |
return segments[segments.length-1]; |
|
538 |
}
|
|
539 |
||
540 |
/** Given a string str, determines whether it ends with substr */
|
|
541 |
function endswith(str, substring) |
|
542 |
{
|
|
543 |
if (str.length < substring.length) return false; |
|
544 |
return str.substr(str.length - substring.length) == substring; |
|
545 |
}
|
|
546 |
||
238
by mattgiuca
util.js: Added Array method "removeall". |
547 |
/** Removes all occurences of a value from an array.
|
548 |
*/
|
|
549 |
Array.prototype.removeall = function(val) |
|
550 |
{
|
|
551 |
var i, j; |
|
239
by mattgiuca
browser.js: Fixed array loop, made normal for loop (for each loops break |
552 |
var arr = this; |
238
by mattgiuca
util.js: Added Array method "removeall". |
553 |
j = 0; |
554 |
for (i=0; i<arr.length; i++) |
|
555 |
{
|
|
556 |
arr[j] = arr[i]; |
|
557 |
if (arr[i] != val) j++; |
|
558 |
}
|
|
559 |
arr.splice(j, i-j); |
|
560 |
}
|
|
561 |
||
602
by mattgiuca
util.js: Added shallow_copy_object function. |
562 |
/** Shallow-clones an object */
|
563 |
function shallow_clone_object(obj) |
|
564 |
{
|
|
565 |
o = {}; |
|
566 |
for (k in obj) |
|
567 |
o[k] = obj[k]; |
|
568 |
return o; |
|
569 |
}
|
|
570 |
||
556
by mattgiuca
util.js: Made a function new_xmlhttprequest, for a more browser agnostic |
571 |
/** Returns a new XMLHttpRequest object, in a somewhat browser-agnostic
|
572 |
* fashion.
|
|
573 |
*/
|
|
574 |
function new_xmlhttprequest() |
|
575 |
{
|
|
576 |
try
|
|
577 |
{
|
|
578 |
/* Real Browsers */
|
|
579 |
return new XMLHttpRequest(); |
|
580 |
}
|
|
581 |
catch (e) |
|
582 |
{
|
|
583 |
/* Internet Explorer */
|
|
584 |
try
|
|
585 |
{
|
|
586 |
return new ActiveXObject("Msxml2.XMLHTTP"); |
|
587 |
}
|
|
588 |
catch (e) |
|
589 |
{
|
|
590 |
try
|
|
591 |
{
|
|
592 |
return new ActiveXObject("Microsoft.XMLHTTP"); |
|
593 |
}
|
|
594 |
catch (e) |
|
595 |
{
|
|
596 |
throw("Your browser does not support AJAX. " |
|
597 |
+ "IVLE requires a modern browser."); |
|
598 |
}
|
|
599 |
}
|
|
600 |
}
|
|
601 |
}
|
|
602 |
||
793
by mattgiuca
util.js: ajax_call multipart/form-data: Now randomly generates a boundary |
603 |
/** Creates a random string of length length,
|
604 |
* consisting of alphanumeric characters.
|
|
605 |
*/
|
|
606 |
var rand_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ" |
|
607 |
+ "abcdefghiklmnopqrstuvwxyz"; |
|
608 |
function random_string(length) |
|
609 |
{
|
|
610 |
var str = Array(length); |
|
611 |
var v; |
|
612 |
for (var i=0; i<length; i++) |
|
613 |
{
|
|
614 |
v = Math.floor(Math.random() * rand_chars.length); |
|
615 |
str[i] = rand_chars.charAt(v); |
|
616 |
}
|
|
617 |
return str.join(''); |
|
618 |
}
|
|
619 |
||
944
by dcoles
Special Home Directory: Work to create a special home directory that shows the |
620 |
/** Makes an XMLHttpRequest call to the server.
|
559
by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not |
621 |
* Sends the XMLHttpRequest object containing the completed response to a
|
622 |
* specified callback function.
|
|
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
623 |
*
|
559
by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not |
624 |
* \param callback A callback function. Will be called when the response is
|
625 |
* complete. Passed 1 parameter, an XMLHttpRequest object containing the
|
|
944
by dcoles
Special Home Directory: Work to create a special home directory that shows the |
626 |
* completed response. If callback is null this is a syncronous request
|
627 |
* otherwise this is an asynchronous request.
|
|
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
628 |
* \param app IVLE app to call (such as "fileservice").
|
629 |
* \param path URL path to make the request to, within the application.
|
|
630 |
* \param args Argument object, as described in parse_url and friends.
|
|
1099.1.58
by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the |
631 |
* \param method String; "GET", "POST", "PUT", or "PATCH"
|
632 |
* \param content_type String, optional.
|
|
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
633 |
* Defaults to "application/x-www-form-urlencoded".
|
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
634 |
*/
|
559
by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not |
635 |
function ajax_call(callback, app, path, args, method, content_type) |
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
636 |
{
|
1099.1.58
by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the |
637 |
if (!content_type) |
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
638 |
content_type = "application/x-www-form-urlencoded"; |
225
by mattgiuca
util.js: Yet more fixes for encoding/decoding URIs. build_url and parse_url |
639 |
path = app_path(app, path); |
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
640 |
var url; |
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
641 |
/* A random string, for multipart/form-data
|
642 |
* (This is not checked against anywhere else, it is solely defined and
|
|
643 |
* used within this function) */
|
|
793
by mattgiuca
util.js: ajax_call multipart/form-data: Now randomly generates a boundary |
644 |
var boundary = random_string(20); |
556
by mattgiuca
util.js: Made a function new_xmlhttprequest, for a more browser agnostic |
645 |
var xhr = new_xmlhttprequest(); |
944
by dcoles
Special Home Directory: Work to create a special home directory that shows the |
646 |
var asyncronous = callback != null; |
647 |
if (asyncronous) |
|
648 |
{
|
|
649 |
xhr.onreadystatechange = function() |
|
559
by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not |
650 |
{
|
944
by dcoles
Special Home Directory: Work to create a special home directory that shows the |
651 |
if (xhr.readyState == 4) |
652 |
{
|
|
653 |
callback(xhr); |
|
654 |
}
|
|
559
by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not |
655 |
}
|
944
by dcoles
Special Home Directory: Work to create a special home directory that shows the |
656 |
}
|
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
657 |
if (method == "GET") |
658 |
{
|
|
659 |
/* GET sends the args in the URL */
|
|
660 |
url = build_url({"path": path, "args": args}); |
|
559
by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not |
661 |
/* open's 3rd argument = true -> asynchronous */
|
944
by dcoles
Special Home Directory: Work to create a special home directory that shows the |
662 |
xhr.open(method, url, asyncronous); |
182
by mattgiuca
browser.js: Now correctly implements do_action and navigate. Able to perform |
663 |
xhr.send(null); |
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
664 |
}
|
665 |
else
|
|
666 |
{
|
|
1099.1.58
by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the |
667 |
/* POST & PUT & PATCH sends the args in the request body */
|
1665
by Matt Giuca
util.js: ajax_call - call urlencode_path, rather than encodeURI. You should never call encodeURI. This fixes certain characters in filenames such as # breaking all actions when in a file or directory with such a character. This fixes Launchpad bug #526240. |
668 |
url = urlencode_path(path); |
944
by dcoles
Special Home Directory: Work to create a special home directory that shows the |
669 |
xhr.open(method, url, asyncronous); |
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
670 |
var message; |
671 |
if (content_type == "multipart/form-data") |
|
672 |
{
|
|
673 |
xhr.setRequestHeader("Content-Type", |
|
792
by mattgiuca
util.js: ajax_call: Fixed multipart/form-data post request generation. (Syntax |
674 |
"multipart/form-data; boundary=" + boundary); |
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
675 |
message = make_multipart_formdata(args, boundary); |
676 |
}
|
|
1099.1.58
by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the |
677 |
else if (content_type == "application/x-www-form-urlencoded") |
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
678 |
{
|
679 |
xhr.setRequestHeader("Content-Type", content_type); |
|
680 |
message = make_query_string(args); |
|
681 |
}
|
|
1099.1.58
by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the |
682 |
else if (content_type == "application/json") |
683 |
{
|
|
684 |
xhr.setRequestHeader("Content-Type", content_type); |
|
685 |
message = JSON.stringify(args); |
|
686 |
}
|
|
687 |
else
|
|
688 |
{
|
|
689 |
xhr.setRequestHeader("Content-Type", content_type); |
|
690 |
message = args; |
|
691 |
}
|
|
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
692 |
xhr.send(message); |
693 |
}
|
|
944
by dcoles
Special Home Directory: Work to create a special home directory that shows the |
694 |
/* Only return the XHR for syncronous requests */
|
695 |
if (!asyncronous) |
|
696 |
{
|
|
697 |
return xhr; |
|
698 |
}
|
|
176
by mattgiuca
util: Rewrote pathlist_to_path in terms of path_join (more robust and |
699 |
}
|
178
by mattgiuca
util: Added multipart/form-data option for ajax calls. |
700 |
|
944
by dcoles
Special Home Directory: Work to create a special home directory that shows the |
701 |
/** Attempts to JSON decodes a response object
|
702 |
* If a non-200 response or the JSON decode fails then returns null
|
|
703 |
*/
|
|
704 |
function decode_response(response) |
|
705 |
{
|
|
706 |
if (response.status == 200) |
|
707 |
{
|
|
708 |
try
|
|
709 |
{
|
|
710 |
var responseText = response.responseText; |
|
711 |
return JSON.parse(responseText); |
|
712 |
}
|
|
713 |
catch (e) |
|
714 |
{
|
|
715 |
// Pass
|
|
716 |
}
|
|
717 |
}
|
|
718 |
||
719 |
return null; |
|
720 |
}
|