~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to www/media/common/util.js

  • Committer: mattgiuca
  • Date: 2008-01-13 10:24:53 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:208
dispatch.html, ivle.css: "apptabs" is now an ID, not a class.
    This is so JavaScript code can easily identify it.
editor: Replaced dummy stub with a simple call to browser.handle.
    Editor and File Browser are now integrated with each other.
util.js: New functions, endswith and path_basename.
browser.js: Major changes to accomodate merging editor with file browser.
    Now detects "edit" URLs and handles files slightly-differently.
    In "edit mode", all files are edited even if they are binary.
    There is a warning for editing files that are binary files.
    Changes the styling of the tabs so that the "selected" tab is
    either the file browser or editor depending on whether the editor
    panel is open or not. (So the actual contents of the page determine
    which tab is selected, not the URL or the server).
    Sets the window title to the name of the directory or file being browsed.`

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
/* Expects the following variables to have been declared by JavaScript in
26
26
 * the HTML generated by the server:
27
27
 * - root_dir
28
 
 * - public_host
29
28
 * - username
30
29
 */
31
30
 
70
69
 *  it will automatically be URL-encoded.
71
70
 * \param onclick Optional string. Will be set as the "onclick" attribute
72
71
 *  of the "a" element.
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.
76
72
 * \return DOM Element object.
77
73
 */
78
 
function dom_make_link_elem(tagname, text, title, href, onclick, dontencode)
 
74
function dom_make_link_elem(tagname, text, title, href, onclick)
79
75
{
80
76
    if (text == null) text = "";
81
77
    if (href == null) href = "";
82
78
    var elem = document.createElement(tagname);
83
79
    var link = document.createElement("a");
84
 
    if (dontencode != true)
85
 
        href = urlencode_path(href);
86
 
    link.setAttribute("href", href);
 
80
    link.setAttribute("href", encodeURI(href));
87
81
    if (title != null)
88
82
        link.setAttribute("title", title);
89
83
    if (onclick != null)
99
93
function dom_make_img(src, width, height, title, alt)
100
94
{
101
95
    var img = document.createElement("img");
102
 
    img.setAttribute("src", urlencode_path(src));
 
96
    img.setAttribute("src", src);
103
97
    if (width != null)
104
98
        img.setAttribute("width", width);
105
99
    if (height != null)
155
149
 * args is never null, though it may be empty.
156
150
 *
157
151
 * All strings are decoded/unescaped. Reserved characters
158
 
 * (; , / ? : @ & = + * $) are not decoded except in args and path.
 
152
 * (; , / ? : @ & = + * $) are not decoded except in args.
159
153
 *
160
154
 * \param url String. A URL. To read from the current browser window, use
161
155
 *  window.location.href.
168
162
    var serverpart;
169
163
    var args;
170
164
 
 
165
    url = decodeURI(url);
 
166
 
171
167
    /* Split scheme from rest */
172
168
    index = url.indexOf("://");
173
169
    if (index < 0)
224
220
            obj.query_string = url.substr(index+1);
225
221
        }
226
222
    }
227
 
    obj.path = decodeURIComponent(obj.path);
228
223
 
229
224
    /* Split query string into arguments */
230
225
    args = {};
279
274
            query_string += "&" + encodeURIComponent(arg_key) + "=" +
280
275
                encodeURIComponent(arg_val);
281
276
    }
282
 
    if (query_string != "")
 
277
    if (query_string == "")
 
278
        query_string = null;
 
279
    else
283
280
        /* Drop the first "&" */
284
281
        query_string = query_string.substr(1);
285
282
 
310
307
        url += ":" + obj.server_port.toString();
311
308
    if (("path" in obj) && obj.path != null)
312
309
    {
313
 
        var path = urlencode_path(obj.path.toString());
314
 
        if (url.length > 0 && path.length > 0 && path.charAt(0) != "/")
 
310
        var path = obj.path.toString();
 
311
        if (url.length > 0 && path.length > 0 && path[0] != "/")
315
312
            path = "/" + path;
316
313
        url += path;
317
314
    }
318
315
    if (("query_string" in obj) && obj.query_string != null)
319
 
        query_string = encodeURI(obj.query_string.toString());
 
316
        query_string = obj.query_string.toString();
320
317
    else if (("args" in obj) && obj.args != null)
321
318
        query_string = make_query_string(obj.args);
322
319
 
323
 
    if (query_string != "" && query_string != null)
 
320
    if (query_string != null)
324
321
        url += "?" + query_string;
325
322
 
326
 
    return url;
327
 
}
328
 
 
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);
341
 
    if (split[0] == "" && split.length > 1) path = "/" + path;
342
 
    return path;
343
 
}
344
 
 
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) + "="
351
 
        + encodeURIComponent(JSON.stringify(value))
352
 
        + "; path=" + urlencode_path(root_dir);
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
 
    }
 
323
    return encodeURI(url);
377
324
}
378
325
 
379
326
/** Given an argument map, as output in the args parameter of the return of
426
373
    {
427
374
        arg = arguments[i];
428
375
        if (arg.length == 0) continue;
429
 
        if (arg.charAt(0) == '/')
 
376
        if (arg[0] == '/')
430
377
            path = arg;
431
378
        else
432
379
        {
433
 
            if (path.length > 0 && path.charAt(path.length-1) != '/')
 
380
            if (path.length > 0 && path[path.length-1] != '/')
434
381
                path += '/';
435
382
            path += arg;
436
383
        }
461
408
    {
462
409
        /* FIXME: Encoding not supported here (should not matter if we
463
410
         * only use ASCII names */
464
 
        data += "--" + boundary + "\r\n"
 
411
        data += "--" + boundary + "\n"
465
412
            + "Content-Disposition: form-data; name=\"" + arg_key
466
 
            + "\"\r\n\r\n"
467
 
            + arg_val + "\r\n";
 
413
            + "\"\n\n"
 
414
            + arg_val + "\n";
468
415
    }
469
416
 
470
417
    for (var arg_key in args)
479
426
            extend_data(arg_key, arg_val);
480
427
    }
481
428
    /* End boundary */
482
 
    data += "--" + boundary + "--\r\n";
 
429
    data += "--" + boundary + "--\n";
483
430
 
484
431
    return data;
485
432
}
491
438
function pathlist_to_path(pathlist)
492
439
{
493
440
    ret = path_join.apply(null, pathlist);
494
 
    if (ret.charAt(ret.length-1) != '/')
 
441
    if (ret[ret.length-1] != '/')
495
442
        ret += '/';
496
443
    return ret;
497
444
}
504
451
    return path_join(root_dir, path);
505
452
}
506
453
 
507
 
/** Shorthand for make_path(path_join(app, ...))
508
 
 * Creates an absolute path for a given path within a given app.
509
 
 */
510
 
function app_path(app /*,...*/)
511
 
{
512
 
    return make_path(path_join.apply(null, arguments));
513
 
}
514
 
 
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
 
 
522
 
/** Generates an absolute URL to a public application
523
 
 */
524
 
function public_app_url(app /*,...*/)
525
 
{
526
 
    return "http://" + public_host + app_url.apply(null, arguments);
527
 
}
528
 
 
529
454
/** Given a path, gets the "basename" (the last path segment).
530
455
 */
531
456
function path_basename(path)
544
469
    return str.substr(str.length - substring.length) == substring;
545
470
}
546
471
 
547
 
/** Removes all occurences of a value from an array.
548
 
 */
549
 
Array.prototype.removeall = function(val)
550
 
{
551
 
    var i, j;
552
 
    var arr = this;
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
 
 
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
 
 
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
 
 
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
 
 
620
 
/** Makes an XMLHttpRequest call to the server.
621
 
 * Sends the XMLHttpRequest object containing the completed response to a
622
 
 * specified callback function.
 
472
/** Makes an XMLHttpRequest call to the server. Waits (synchronously) for a
 
473
 * response, and returns an XMLHttpRequest object containing the completed
 
474
 * response.
623
475
 *
624
 
 * \param callback A callback function. Will be called when the response is
625
 
 *      complete. Passed 1 parameter, an XMLHttpRequest object containing the
626
 
 *      completed response. If callback is null this is a syncronous request 
627
 
 *      otherwise this is an asynchronous request.
628
476
 * \param app IVLE app to call (such as "fileservice").
629
477
 * \param path URL path to make the request to, within the application.
630
478
 * \param args Argument object, as described in parse_url and friends.
631
 
 * \param method String; "GET", "POST", "PUT", or "PATCH"
632
 
 * \param content_type String, optional.
 
479
 * \param method String; "GET" or "POST"
 
480
 * \param content_type String, optional. Only applies if method is "POST".
 
481
 *      May be "application/x-www-form-urlencoded" or "multipart/form-data".
633
482
 *      Defaults to "application/x-www-form-urlencoded".
 
483
 * \return An XMLHttpRequest object containing the completed response.
634
484
 */
635
 
function ajax_call(callback, app, path, args, method, content_type)
 
485
function ajax_call(app, path, args, method, content_type)
636
486
{
637
 
    if (!content_type)
 
487
    if (content_type != "multipart/form-data")
638
488
        content_type = "application/x-www-form-urlencoded";
639
 
    path = app_path(app, path);
 
489
    path = make_path(path_join(app, path));
640
490
    var url;
641
491
    /* A random string, for multipart/form-data
642
492
     * (This is not checked against anywhere else, it is solely defined and
643
493
     * used within this function) */
644
 
    var boundary = random_string(20);
645
 
    var xhr = new_xmlhttprequest();
646
 
    var asyncronous = callback != null;
647
 
    if (asyncronous)
648
 
    {
649
 
        xhr.onreadystatechange = function()
650
 
            {
651
 
                if (xhr.readyState == 4)
652
 
                {
653
 
                    callback(xhr);
654
 
                }
655
 
            }
656
 
    }
 
494
    var boundary = "48234n334nu7n4n2ynonjn234t683jyh80j";
 
495
    var xhr = new XMLHttpRequest();
657
496
    if (method == "GET")
658
497
    {
659
498
        /* GET sends the args in the URL */
660
499
        url = build_url({"path": path, "args": args});
661
 
        /* open's 3rd argument = true -> asynchronous */
662
 
        xhr.open(method, url, asyncronous);
 
500
        /* open's 3rd argument = false -> SYNCHRONOUS (wait for response)
 
501
         * (No need for a callback function) */
 
502
        xhr.open(method, url, false);
663
503
        xhr.send(null);
664
504
    }
665
505
    else
666
506
    {
667
 
        /* POST & PUT & PATCH sends the args in the request body */
 
507
        /* POST sends the args in application/x-www-form-urlencoded */
668
508
        url = encodeURI(path);
669
 
        xhr.open(method, url, asyncronous);
 
509
        xhr.open(method, url, false);
670
510
        var message;
671
511
        if (content_type == "multipart/form-data")
672
512
        {
673
513
            xhr.setRequestHeader("Content-Type",
674
 
                "multipart/form-data; boundary=" + boundary);
 
514
                "multipart/form-data, boundary=" + boundary);
675
515
            message = make_multipart_formdata(args, boundary);
676
516
        }
677
 
        else if (content_type == "application/x-www-form-urlencoded")
 
517
        else
678
518
        {
679
519
            xhr.setRequestHeader("Content-Type", content_type);
680
520
            message = make_query_string(args);
681
521
        }
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
 
        }
692
522
        xhr.send(message);
693
523
    }
694
 
    /* Only return the XHR for syncronous requests */
695
 
    if (!asyncronous)
696
 
    { 
697
 
        return xhr;
698
 
    }
 
524
    return xhr;
699
525
}
700
526
 
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
 
}