• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/APP-IPK/AiCloud-ipk/opt/etc/aicloud_UI/js/davclient.js/jsbase/
1/*****************************************************************************
2 *
3 * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
4 *
5 * This software is distributed under the terms of the JSBase
6 * License. See LICENSE.txt for license text.
7 *
8 *****************************************************************************/
9
10var global = this;
11global.misclib = new function() {
12    /* This lib mostly contains fixes for common problems in JS, additions to
13        the core global functions and wrappers for fixing browser issues.
14
15        See the comments in the code for further explanations.
16    */
17
18    // reference to the lib to reach it from the functions/classes
19    var misclib = this;
20
21    var Timer = function() {
22        /* Wrapper around window.setTimeout, to solve number of problems:
23
24            * setTimeout gets a string rather than a function reference as an
25                argument
26
27            * setTimeout can not handle arguments to the callable properly,
28                since it's evaluated in the window namespace, not in the current
29                scope
30
31            Usage:
32
33                // call the global 'schedule' function to register a function
34                // called 'foo' on the current (imaginary) object, passing in
35                // a variable called 'bar' as an argument, so it gets called
36                // after 1000 msecs
37                window.misclib.schedule(this, this.foo,  1000, bar);
38
39            Note that if you don't care about 'this' inside the function
40            you register, you can just pass in a ref to the 'window' object
41            as the first argument. No lookup is done in the namespace, the
42            first argument is only used as the 'this' variable inside the
43            function.
44        */
45        this.lastid = 0;
46        this.functions = {};
47
48        this.registerCallable = function(object, func, timeout) {
49            /* register a function to be called with a timeout
50
51                args:
52                    object - the context in which to call the function ('this')
53                    func - the function
54                    timeout - timeout in millisecs
55
56                all other args will be passed 1:1 to the function when called
57            */
58            var args = new Array();
59            for (var i=3; i < arguments.length; i++) {
60                args.push(arguments[i]);
61            }
62            var id = this._createUniqueId();
63            this.functions[id] = new Array(object, func, args);
64            // setTimeout will be called in the module namespace, where the
65            // timer_instance variable also resides (see below)
66            setTimeout("window.misclib.timer_instance." +
67                        "_handleFunction(" + id + ")", timeout);
68        };
69
70        this._handleFunction = function(id) {
71            /* private method that does the actual function call */
72            var obj = this.functions[id][0];
73            var func = this.functions[id][1];
74            var args = this.functions[id][2];
75            this.functions[id] = null;
76            func.apply(obj, args);
77        };
78
79        this._createUniqueId = function() {
80            /* create a unique id to store the function by */
81            while (this.lastid in this.functions &&
82                        this.functions[this.lastid]) {
83                this.lastid++;
84                if (this.lastid > 100000) {
85                    this.lastid = 0;
86                }
87            }
88            return this.lastid;
89        };
90    };
91
92    // create a timer instance in the module namespace
93    var timer_instance = this.timer_instance = new Timer();
94
95    // this is the function that should be called to register callables
96    this.schedule = function() {
97            timer_instance.registerCallable.apply(timer_instance, arguments)};
98
99    // cross-browser event registration
100    var events_supported = true;
101    try {
102        window;
103    } catch(e) {
104        events_supported = false;
105    };
106
107    if (events_supported) {
108        // first some privates
109
110        // a registry for events so they can be unregistered on unload of the
111        // body
112        var event_registry = {};
113
114        // an iterator for unique ids
115        var currid = 0;
116
117        // just to make some guy on irc happy, store references to
118        // browser-specific wrappers so we don't have to find out the type of
119        // browser on every registration (yeah, yeah, i admit it was quite a
120        // good tip... ;)
121        var reg_handler = null;
122        var unreg_handler = null;
123        if (window.addEventListener) {
124            reg_handler = function(element, eventname, handler) {
125                // XXX not sure if anyone ever uses the last argument...
126                element.addEventListener(eventname, handler, false);
127            };
128            unreg_handler = function(element, eventname, handler) {
129                element.removeEventListener(eventname, handler, false);
130            };
131        } else if (window.attachEvent) {
132            reg_handler = function(element, eventname, handler) {
133                element.attachEvent('on' + eventname, handler);
134            };
135            dereg_handler = function(element, eventname, handler) {
136                element.detachEvent('on' + eventname, handler);
137            };
138        } else {
139            reg_handler = function(element, eventname, handler) {
140                var message = 'Event registration not supported or not ' +
141                                'understood on this platform';
142                if (global.exception) {
143                    throw(new exception.NotSupported(message));
144                } else {
145                    throw(message);
146                };
147            };
148        };
149
150        this.addEventHandler = function(element, eventname, handler, context) {
151            /* Method to register an event handler
152
153                Works in standards compliant browsers and IE, and solves a
154                number of different problems. Most obviously it makes that
155                there's only a single function to use and memorize, but also
156                it makes that 'this' inside the function points to the context
157                (usually you'll want to pass in the object the method is
158                defined on), and it fixes memory leaks (IE is infamous for
159                leaking memory, which can lead to problems if you register a
160                lot of event handlers, especially since the memory leakage
161                doesn't disappear on page reloads, see e.g.
162                http://www.bazon.net/mishoo/articles.epl?art_id=824).
163
164                Arguments:
165
166                    * element - the object to register the event on
167
168                    * eventname - a string describing the event (Mozilla style,
169                        so without the 'on')
170
171                    * handler - a reference to the function to be called when
172                        the event occurs
173
174                    * context - the 'this' variable inside the function
175
176                The arguments passed to the handler:
177
178                    * event - a reference to the event fired
179
180                    * all arguments passed in to this function besides the ones
181                        described
182
183            */
184            var args = new Array();
185            for (var i=4; i < arguments.length; i++) {
186                args.push(arguments[i]);
187            };
188            var wrapper = function(event) {
189                args = [event].concat(args);
190                handler.apply(context, args)
191                args.shift();
192            };
193            currid++;
194            event_registry[currid] = [element, eventname, wrapper];
195            reg_handler(element, eventname, wrapper);
196            // return the wrapper so the event can be unregistered later on
197            return currid;
198        };
199
200        this.removeEventHandler = function(regid) {
201            /* method to remove an event handler for both IE and Mozilla
202
203                pass in the id returned by addEventHandler
204            */
205            // remove the entry from the event_registry
206            var args = event_registry[regid];
207            if (!args) {
208                var message = 'removeEventListener called with ' +
209                                'unregistered id';
210                if (global.exception) {
211                    throw((new exception.NotFound(message)));
212                } else {
213                    throw(message);
214                };
215            };
216            delete event_registry[regid];
217            unreg_handler(args[0], args[1], args[2]);
218        };
219
220        this.removeAllEventHandlers = function() {
221            for (var id in event_registry) {
222                try {
223                    misclib.removeEventHandler(id);
224                } catch(e) {
225                    // element must have been discarded or something...
226                };
227            };
228        };
229    };
230
231    // string representation of objects
232    this.safe_repr = function(o) {
233        var visited = {};
234        var ret = misclib._repr_helper(o, visited);
235        delete visited;
236        return ret;
237    };
238
239    this.repr = function(o, dontfallback) {
240        try {
241            return misclib._repr_helper(o);
242        } catch(e) {
243            // when something fails here, we assume it's because of recursion
244            // and fall back to safe_repr()
245            if (dontfallback) {
246                throw(e);
247            };
248            return misclib.safe_repr(o);
249        };
250    };
251
252    this._repr_helper = function(o, visited) {
253        var newid = 0;
254        if (visited) {
255            // XXX oomph... :|
256            for (var attr in visited) {
257                if (visited[attr] === o) {
258                    return '#' + attr + '#';
259                };
260                newid++;
261            };
262        };
263        var ret = 'unknown?';
264        var type = typeof o;
265        switch (type) {
266            case 'undefined':
267                ret = 'undefined'
268                break;
269            case 'string':
270                ret = '"' + string.escape(o) + '"';
271                break;
272            case 'object':
273                if (o instanceof Array) {
274                    if (visited) {
275                        visited[newid] = o;
276                    };
277                    var r = [];
278                    for (var i=0; i < o.length; i++) {
279                        var newo = o[i];
280                        r.push(misclib._repr_helper(newo, visited));
281                    };
282                    ret = ''
283                    if (visited) {
284                        ret += '#' + newid + '=';
285                    };
286                    ret += '[' + r.join(', ') + ']';
287                } else if (o instanceof Date) {
288                    ret = '(new Date(' + o.valueOf() + '))';
289                } else {
290                    if (visited) {
291                        visited[newid] = o;
292                    };
293                    var r = [];
294                    for (var attr in o) {
295                        var newo = o[attr];
296                        r.push(attr + ': ' + misclib._repr_helper(newo,
297                                                                visited));
298                    };
299                    ret = '';
300                    if (visited) {
301                        ret += '#' + newid + '=';
302                    };
303                    ret += '{' + r.join(', ') + '}';
304                };
305                break;
306            default:
307                ret = o.toString();
308                break;
309        };
310        return ret;
311    };
312
313    this.dir = function(obj) {
314        /* list all the attributes of an object */
315        var ret = [];
316        for (var attr in obj) {
317            ret.push(attr);
318        };
319        return ret;
320    };
321
322    this.print = function(message, win) {
323        /* write output in a way that the user can see it
324
325            creates a div in browsers, prints to stdout in spidermonkey
326
327            this is here not only as a convenient way to print output, but also
328            so that it's possible to override, that way customizing prints
329            from code
330        */
331        if (win === undefined) {
332            win = window;
333        };
334        message = '' + message;
335        var p = null;
336        try {
337          win.foo;
338        } catch(e) {
339          // no window, so we guess we're inside some JS console, assuming it
340          // has a print() function... if there are situations in which this
341          // doesn't suffice, please mail me (johnny@johnnydebris.net)
342          print(message);
343          return;
344        };
345        var div = document.createElement('div');
346        div.className = 'printed';
347        div.appendChild(document.createTextNode(message));
348        document.getElementsByTagName('body')[0].appendChild(div);
349    };
350}();
351