miércoles, 28 de diciembre de 2016

setTimeout y setInterval con argumentos en la función de llamada y posibilidad de aplicar a objetos

(1) setTimeout:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//------------------------------------------------------------------------------------------------
// Engines      JavaScript 1.5+
//              JScript    5.5+
// Environments NN6+ IE5.5+ MOZILLA1+ SAFARI1+
//------------------------------------------------------------------------------------------------
 
function setTimeoutEx
(
      f // src
    , m // milliseconds
    , o /* target
    , arg1 [, ... [, argN]] */
){
    var i = typeof f;
 
    if (i == 'string' || i == 'function')
    {
        if (!setTimeoutEx.__cnt)
            setTimeoutEx.__cnt = 1;
 
        if (i == 'string')
            f = new Function(f);
 
        if (m == null)
            m = 0;
 
        setTimeoutEx[i = setTimeoutEx.__cnt++] =
        {
              a: Array.prototype.slice.call(arguments, 3)
            , o: o
            , f: f
            , i: setTimeout
                 (
                      'setTimeoutEx[' + i + '].f.apply(setTimeoutEx[' +
                      i + '].o, setTimeoutEx[' + i + '].a)'
                     , m
                 )
        };
 
        return setTimeoutEx[i].i;
    }
 
    return -1;
}
 
//------------------------------------------------------------------------------------------------
 
function clearTimeoutEx (i /* id */)
{
    if (typeof i == 'number' && i > 0)
    {
        clearTimeout(i);
 
        for (var j = 0; j < setTimeoutEx.__cnt; ++j)
            if (setTimeoutEx[j] && setTimeoutEx[j].i == i)
                delete setTimeoutEx[j];
    }
}
(1) Test:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
setTimeoutEx
(
      function (s)
      {
          alert(s);
      }
    , 1000
    , null
    , '¡Test!'
);
 
var myobj = {test: 'Ok!'};
 
setTimeoutEx
(
      function (s)
      {
          alert(this.test);
          this.arg1 = s;
      }
    , 1000
    , myobj
    , 'my arg test ok!'
);
(2) setInterval:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//------------------------------------------------------------------------------------------------
// Engines      JavaScript 1.5+
//              JScript    5.5+
// Environments NN6+ IE5.5+ MOZILLA1+ SAFARI1+
//------------------------------------------------------------------------------------------------
 
function setIntervalEx
(
      f // src
    , m // milliseconds
    , o /* target
    , arg1 [, ... [, argN]] */
){
    var i = typeof f;
      
    if (i == 'string' || i == 'function')
    {
        if (!setIntervalEx.__cnt)
            setIntervalEx.__cnt = 1;
 
        if (i == 'string')
            f = new Function(f);
 
        if (m == null)
            m = 0;
 
        setIntervalEx[i = setIntervalEx.__cnt++] =
        {
              a: Array.prototype.slice.call(arguments, 3)
            , o: o
            , f: f
            , i: setInterval
                 (
                      'if (setIntervalEx[' + i + '].f.apply(setIntervalEx['   +
                      i + '].o, setIntervalEx[' + i + '].a))clearIntervalEx(' +
                      'setIntervalEx[' + i + '].i)'
                     , m
                 )
        };
 
        return setIntervalEx[i].i;
    }
 
    return -1;
}
 
//------------------------------------------------------------------------------------------------
 
function clearIntervalEx (i /* id */)
{
    if (typeof i == 'number' && i > 0)
    {
        clearInterval(i);
 
        for (var j = 0; j < clearIntervalEx.__cnt; ++j)
            if (clearIntervalEx[j] && clearIntervalEx[j].i == i)
                delete clearIntervalEx[j];
    }
}
(2) Test:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
setIntervalEx
(
      function (s, b)
      {
          alert(s);
          return b;
      }
    , 1000
    , null
    , '¡Test!'
    , true
);
 
var myobj = {test: 'Ok!'};
 
setIntervalEx
(
      function (s)
      {
          alert(this.test);
          this.arg1 = s;
 
          return true;
      }
    , 1000
    , myobj
    , 'my arg test ok!'
);

miércoles, 10 de julio de 2013

Codificación de base 2 a base 63 en JavaScript

El método toString sólo admite hasta la base 36, así que hay que partir de una nueva codificación. Base32 no tiene la especificación rfc4648, pero con el presente objeto se pueden codificar todos los caracteres desde la base 2 a la 63 (aunque podrían ser más):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//------------------------------------------------------------------------------------------------
// Engines      JavaScript 1.3+
//              JScript    5.5+
// Environments NN4.06+ IE5.5+ MOZILLA1+ SAFARI1+
//------------------------------------------------------------------------------------------------
var Coding =
{
      Num:
      {
            codec : '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_'
          , getBlockSize : function (b /* radix [2..63] */)
            {
                if      (b == 2)          b = 8;
                else if (b == 3)          b = 6;
                else if (b > 3 && b < 7)  b = 4;
                else if (b > 6 && b < 16) b = 3;
                else                      b = 2;
  
                return b; 
            }
 
            //------------------------------------------------------------------------------------
 
          , encode: function (n /* number */, b /* radix [2..63] */)
            {
                var s = '';
                if (!isNaN(n) && !isNaN(b))
                {
                    if (typeof n == 'string')
                        n = parseInt(n);
  
                    b = Math.min(Math.max(2, b), 63);
        
                    do
                    {
                        s = this.codec.charAt(n % b) + s;
                        n = Math.floor(n / b)
                    }
  
                    while (n > 0);
      
                    n = Coding.Num.getBlockSize(b);
                    b = s.length;
      
                    while (b++ < n)
                        s = '0' + s;
                }
 
                return s;
            }
 
            //------------------------------------------------------------------------------------
 
          , decode: function (s /* src */, b /* radix [2..63] */)
            {
                var n = 0;
                if (s != null && !isNaN(b))
                {
                    b = Math.min(Math.max(2, b), 63);
         
                    for (var i = 0, l = (s += '').length; i < l; ++i)
                        n = n * b + this.codec.indexOf(s.charAt(i));
                }
 
                return n;
            }
      }
 
      //-----------------------------------------------------------------------------------------
 
    , Base2x63:
      {
            encode: function (s /* src */, b /* base [2..63] */)
            {
                var r = '';
                if (s != null && !isNaN(b))
                {
                    b = Math.min(Math.max(b, 2), 63);
 
                    for (var i = 0, l = (s += '').length; i < l; ++i)
                        r += Coding.Num.encode(s.charCodeAt(i), b);
                }
 
                return r;
            }
 
            //------------------------------------------------------------------------------------
 
         , decode: function (s /* src */, b /* base [2..63] */)
           {
                var n, r = '';
                if (s != null && !isNaN(b))
                {
                    b = Math.min(Math.max(b, 2), 63);
                    n = Coding.Num.getBlockSize(b);
      
                    for (var i = 0, l = (s += '').length; i < l; i += n)
                        r += String.fromCharCode(Coding.Num.decode(s.substr(i, n), b));
                }
 
                return r;
           }
      }
};
Test:
1
2
3
4
5
6
7
8
9
10
var e, s = 'Tomaré una decisión con la cigüeña.';
for (var i = 2; i < 64; ++i)
{
    e = Coding.Base2x63.encode(s, i);
    alert
    (
        'base: ' + i + ', length: ' + e.length + ', encoded: ' + e + ', decoded: ' +
        Coding.Base2x63.decode(e, i)
    );
}

jueves, 4 de julio de 2013

Test Criptográfico: PHP mcrypt y CryptoJS (AES)

1
2
<script type="text/javascript" src="cryptojs/3.1.2/rollups/aes.js"></script>
<script type="text/javascript" src="cryptojs/3.1.2/components/pad-zeropadding.js"></script>
1
2
3
4
5
<form method="post" enctype="application/x-www-form-urlencoded" action="crypto.php">
    <input type="text" id="md5" name="md5" size="100" maxlength="100" />
    <input type="text" id="code" name="code" size="100" maxlength="100" />
    <input type="submit" value="Test" />
</form>
1
2
3
4
5
6
7
8
9
10
11
var hash = CryptoJS.MD5('8765432187654321');
var key  = CryptoJS.enc.Utf8.parse(hash);
var iv   = CryptoJS.enc.Utf8.parse('1234567812345678');
 
document.getElementById('md5').value  = hash;
document.getElementById('code').value = CryptoJS.AES.encrypt
(
      'Test Ok!'
    , key
    , {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding }
);
1
2
3
4
5
6
7
8
9
10
11
12
<?php
 
$text      = "Test Ok!";
$key       = md5("8765432187654321");
$iv        = utf8_encode("1234567812345678");
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);
//$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($_POST["code"]), MCRYPT_MODE_CBC, $iv);
 
echo "md5: " . $_POST["md5"] . " -> " . $key . ", encrypted: " . $_POST["code"] . " -> " . base64_encode($encrypted) . ", decrypted: " . $decrypted;
 
?>

miércoles, 3 de julio de 2013

Subir archivos con Ajax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//------------------------------------------------------------------------------------------------
// Engines      JavaScript 1.8.5+
//              JScript    10+
// Environments IE10+ FIREFOX4+ CHROME6+ OPERA12+ SAFARI5+
//------------------------------------------------------------------------------------------------
function upload
(
      s // action-url
    , e // input file (id | element)
    , u // user
    , p // password
){
    if (typeof e != 'object')
        e = document.getElementById(e);
  
    var f, l = 0;
 
    if ((f = e.files) && (l = f.length) == 1) // HTML5! (FileList)
    {
        var h = new XMLHttpRequest();
   
        h.open('POST', s, false, u, p);
        h.setRequestHeader('Content-type', 'multipart/form-data');
        h.setRequestHeader('X-File-Name', (f = f[0]).name);
        h.setRequestHeader('X-File-Size', f.size);
        h.setRequestHeader('X-File-Type', f.type);
        h.send(f);
   
        return h.readyState == 4 && h.status == 200;
    }
  
    else if (l > 1)
    {
        f = [];
        for (var i = 0; i < l; ++i) f.push
        ({
               fileName : e.files[i].name
             , uploaded : upload(s, {files: [e.files[i]]}, u, p)
        });
   
        return f;
    }
  
    return false;
}

Uso con un sólo archivo:

1
<input id="file" type="file" />
1
2
3
4
if (upload('upload.php', 'file'))
{
    //TODO...
}

Uso con múltiples archivos:

1
<input id="files" type="file" multiple />
1
2
3
4
5
6
7
var r = upload('upload.php', 'files');
 
for (var i = 0, l = r.length; i < l; ++i) if (!r[i].uploaded)
{
    alert('"' + r[i].fileName + '" Not uploaded correctly!');
    // TODO...
}
upload.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
 
$hd   = getallheaders();
$name = $hd["X-File-Name"];
 
if (strlen($name) > 0)
{
    //$size = $hd["X-File-Size"];
    //$type = $hd["X-File-Type"];
    // TODO...
 
    $in  = fopen("php://input", "r");
    $out = fopen("upload/" . $name, "w");
    while($data = fread($in, 1024)) fwrite($out, $data);
    fclose($out);
    fclose($in);
}
 
?>
upload.jsp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<%@ page import="java.io.*" %>
<%
    String fileName = request.getHeader("X-File-Name");
    if (fileName != null && fileName.length() > 0)
    {
        //String fileSize = request.getHeader("X-File-Size");
        //String fileType = request.getHeader("X-File-Type");   
        //TODO..
     
        FileOutputStream fos    = new FileOutputStream("webapps/test/upload/" + fileName);
        InputStream      is     = request.getInputStream();
        byte[]           buffer = new byte[1024];
        int              length = 0;
     
        while ((length = is.read(buffer)) != -1)
            fos.write(buffer, 0, length);
   
        fos.flush();
        fos.close();
    }
%>
upload.aspx:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<%@ Page Language="C#" %>
<%
if (Request.ContentLength > 0)
{
    string fileName = Request.Headers["X-File-Name"];
 
    if (fileName != null)
    {
        //string fileSize = Request.Headers["X-File-Size"];
        //string fileType = Request.Headers["X-File-Type"];
        //TODO...
          
        Request.SaveAs(Server.MapPath("/upload/") + fileName, false);
    }
}
%>
upload.asp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<%@ Language="VBScript" %>
<%
Function Save (fileName, byteArray)
    on error resume next
    Dim  BinaryStream
 
    Set BinaryStream = CreateObject("ADODB.Stream")
    
    BinaryStream.Type = 1
 
    BinaryStream.Open
    BinaryStream.Write byteArray
 
    BinaryStream.SaveToFile Server.MapPath("upload") & "\" & fileName, 2
End Function
 
Dim strFileName
strFileName = Request.ServerVariables("HTTP_X-File-Name")
 
If (Len(strfileName) > 0) Then
 
    '... Request.ServerVariables("HTTP_X-File-Size")
    '... Request.ServerVariables("HTTP_X-File-Type")
    'TODO...
 
    Save strFileName, Request.BinaryRead(Request.TotalBytes)
End If
%>

martes, 2 de julio de 2013

Soporte "call" y "apply" para navegadores antiguos

Call:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//------------------------------------------------------------------------------------------------
// Engines      JavaScript 1.1+
//              JScript    2+
// Environments NN3+ IE4+ MOZILLA1+ SAFARI1+
//------------------------------------------------------------------------------------------------
function __fn_call (o /* object, arg1 [, ... [, argN]] */)
{
    var a = arguments;
    var s = '';
    var u;
 
    for (var i = 1, l = a.length, n = l - 1; i < l; ++i)
    {
        s += 'a[' + i + ']';
   
        if (i < n)
            s+= ',';
    }
  
    if (o == null)
        s = eval('this(' + s + ')');
   
    else
    {
        o.__callback = this;
        s = eval('o.__callback(' + s + ')');
        o.__callback = u;
    }
  
    return s;
}
 
//------------------------------------------------------------------------------------------------
 
if (!Function.prototype.call) Function.prototype.call = __fn_call;

Apply:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//------------------------------------------------------------------------------------------------
// Engines      JavaScript 1.1+
//              JScript    2+
// Environments NN3+ IE4+ MOZILLA1+ SAFARI1+
//------------------------------------------------------------------------------------------------
function __fn_apply (o /* object */, a /* [args] */ )
{
    var u, s = '';
    if (a && a.constructor == Array) for (var i = 0, l = a.length, n = l - 1; i < l; ++i)
    {
        s += 'a[' + i + ']';
   
        if (i < n)
            s+= ',';
    }
  
    if (o == null)
        s = eval('this(' + s + ')');
   
    else
    {
        o.__callback = this;
        s = eval('o.__callback(' + s + ')');
        o.__callback = u;
    }
  
    return s;
}
 
//------------------------------------------------------------------------------------------------
 
if (!Function.prototype.apply) Function.prototype.apply = __fn_apply;

lunes, 1 de julio de 2013

Diálogos modales en JavaScript

Muestra un cuadro de diálogo modal con los parámetros especificados:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//------------------------------------------------------------------------------------------------
// Engines      JavaScript   1.4+
//              JScript      5.5+
// Environments NN6+ IE5.5+ MOZILLA1+ SAFARI1+
//------------------------------------------------------------------------------------------------
function getModalDlg
(
       s // url
     , c // callback
     , w // width
     , h // height
     , x // left
     , y // top
){
     if (s == null || (s += '').length < 1 || !/^((ht|f)tp(s)*\:\/\/)*\S+$/.test(s))
         throw new Error('getModalDlg: Invalid Url! "' + s + '"');
 
     if (typeof c != 'function')
         throw new Error('getModalDlg: Invalid callback function!');
 
     var a = Array.prototype.slice.call(arguments, 2);
     var b = a.length < 3;
     var f = ['width', 'height', 'left', 'top'];
  
     w = window;
 
     var p = w.showModalDialog;
     var d = p ? [':', 'px;'] : ['=', ','];
     var u = 'undefined';
     var m = typeof netscape != u;
     var n = navigator.userAgent;
 
     for (var i = 0; i < a.length; ++i)
         a[i] = (p ? 'dialog' : '') + f[i] + d[0] + a[i] + d[1];
 
     f = a.join('');
 
     if (p)
     {
         f += 'center:' + (b ? '1' : '0') + ';scroll:1;';
         f += n.indexOf('MSIE') + 1 ? 'status:0' : 'resizable:0';
         s  = p(s, null, f);
          
         c(typeof s.returnValue != u ? s.returnValue : s);
     }
 
     else
     {
         w.dlgcallback = c;
         f += 'dialog,scrollbars,chrome,modal=yes,location=0,status=0,toolbar=no';
 
         if (b)
             f += ',centerscreen';
 
         if (m && (m = netscape.security.PrivilegeManager))
         {
             try
             {
                 m.enablePrivilege(d = 'UniversalBrowserWrite');
                 w.open(s, '_blank', f);
                 m.disablePrivilege(d);
 
                 return;
             }
 
             catch (e) {}
         }
 
         if (typeof w.__dlg == u || w.__dlg.closed)
         {
             w.__dlg  = w.open(s, '_blank', f);
 
             try
             {
                 w.onfocus = function ()
                 {
                     if (typeof this.__dlg != u && !this.__dlg.closed)
                     {
                         this.blur();
                         this.__dlg.focus();
                     }
 
                     else delete this.onfocus;
                 }
  
                 w.__dlg.onblur = function ()
                 {
                     this.opener.blur();
                     this.focus();
                 }
             }
 
             catch (e)
             {
                 c    = { callback: c, dialog: w.__dlg};
                 c.id = setInterval
                 (
                       function (o)
                       {
                           var s = 'returnValue';
                           if (typeof o.dialog[s] != 'undefined')
                           {
                               o.callback(o.dialog[s]);
                               clearInterval(o.id);
                           }
                      }
                    , 0
                    , c
                );
             }
         }
 
         else if (typeof w.__dlg != u)
             w.__dlg.focus();
     }
}
Uso:
1
getModalDlg('my-url', function (returnValue) { /* TODO... */ }, 320, 240);
Código a insertar en la página del cuadro de diálogo:
1
2
3
4
5
6
7
8
9
10
function setDlgReturnValue (v /* value */)
{
     var s = 'returnValue';
     var w = window;
 
     if (w.showModalDialog || !w.opener || !w.opener.dlgcallback)
         w[s] = v;
 
     else w.opener.dlgcallback(v);
}
Uso:
1
2
setDlgReturnValue('my-value');
window.close();

viernes, 28 de junio de 2013

Inclusiones dinámicas de scripts en JavaScript

Verifica si ya se incluyó un script (en la sección de cabecera por defecto):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//------------------------------------------------------------------------------------------------
// Engines      JavaScript 1.2+
//              JScript    3+
// Environments NN6+ IE5+ MOZILLA1+ SAFARI1+
// DOM Level    1 Core
//------------------------------------------------------------------------------------------------
function included (s /* scr */, t /* tag-name (head by default) */)
{
    var d;
    if (!t) t = 'head';
 
    if (typeof s == 'string' && (d = s.indexOf('../')) != -1)
        s = s.substr(d + 3);
 
    d = document;
    t = d.getElementsByTagName(t);
 
    for (var i = 0, l = t.length, e; i < l; ++i)
    {
        e = t[i].getElementsByTagName('script');
 
        for (var j = 0, n = e.length; j < n; ++j)
            if (e[j].src && (s.test ? s.test(e[j].src) : e[j].src.lastIndexOf(s) != -1))
                return true;
    }
 
    return false;
}

Uso:

1
2
3
4
if (!included('my-file.js'))
{
    // TODO...
}

Incluye uno o varios scripts (en la sección de cabecera por defecto):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//------------------------------------------------------------------------------------------------
// Engines      JavaScript 1.2+
//              JScript    3+
// Environments NN6+ IE5+ MOZILLA1+ SAFARI1+
// DOM Level    1 Core
//------------------------------------------------------------------------------------------------
function include (/* arg1 [, ... [, argN]] */)
{
    var r = '', x = r;
    for (var d = document, i = 0, a = arguments, l = a.length, e, s; i < l; ++i)
    {
        if ((s = a[i]).root && (r = s.root + '').length > 0 && r.lastIndexOf('/') != r.length - 1)
            r += '/';
    
        if (s.extension && (x = s.extension + '').length > 0 && x.indexOf('.') != 0)
            x = '.' + x;
 
        if (s.src || typeof s == 'string')
        {
            e = d.createElement('script');
            e.setAttribute('src',  r + (s.src ? s.src : s) + x);
            e.setAttribute('type', s.type ? s.type : 'text/javascript');
 
            if (typeof s.onload == 'function')
            {
                if (e.readyState)
                {
                    e.onreadystatechange = function ()
                    {
                        if (this.readyState == 'loaded' || this.readyState == 'complete')
                        {
                            delete this.onreadystatechange;
                            this.loaded();
                        }
                    }
 
                    e.loaded = s.onload;
                }
     
                else e.onload = s.onload;
            }
 
            d.getElementsByTagName(s.tag ? s.tag : 'head')[0].appendChild(e);
        }
    }
}

Uso:

1
2
3
4
5
6
7
8
9
if (!included('my-file1.js') && !included('my-file2.js')) include
(
      {root: 'my-path', extension: 'js'}
    , {src: 'my-file1', onload: function () { /* TODO... */ }}
    , {src: 'my-file2', onload: function () { /* TODO... */ }}
);
 
if (!included('my-file4.js'))
    include({src: 'my-file4.js', onload: function () { /* TODO... */ }});

Existe otro modo de hacerlo, usando ajax:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//------------------------------------------------------------------------------------------------
// Engines      JavaScript 1.2+
//              JScript    3+
// Environments NN7.1+ IE5+ MOZILLA1+ SAFARI1.2+
//------------------------------------------------------------------------------------------------
function loadscript (s /* url */, b /* eval? (Boolean) */)
{
    var r, x, w = window;
  
    if (w && w.XMLHttpRequest)
        r = new w.XMLHttpRequest();
  
    else if (typeof Components != 'undefined' && Components.classes)                               // XPCOM!
    {
        try
        {
            r = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1'].createInstance
            (
                Components.interfaces.nsIXMLHttpRequest
            );
        }
    
        catch (e)
        {
            r = null;
        }
    }
  
    else if ((x = w.ActiveXObject) || (x = w.GeckoActiveXObject))
    {
        try
        {
            r = new x('Msxml2.XMLHTTP');
        }
   
        catch (e)
        {
            try
            {
                r = new x('Microsoft.XMLHTTP');
            }
 
            catch(e)
            {
                r = null;
            }
        }
    }
  
    if (r)
    {
        r.open('GET', s, false);
        r.send(null);
   
        if (r.readyState == 4 && r.status == 200)
        {
            if (b) eval(r.responseText);
            else
            {
                (w = (x = document).createElement('script')).setAttribute('type', 'text/javascript');
                w.text = r.responseText;
                x.getElementsByTagName('head')[0].appendChild(w);
            }
 
            return true;
        }
    }
     
    return false;
}

Uso:

1
2
3
4
5
6
if (loadscript('my-file1.js'))
{
    //TODO...
}
 
loadscript('my-file2.js', true);