home *** CD-ROM | disk | FTP | other *** search
/ ftp.swcp.com / ftp.swcp.com.zip / ftp.swcp.com / mac / mozilla-mac-0.9.sea.hqx / mozilla-mac-0.9 / Chrome / chatzilla.jar / content / chatzilla / lib / js / utils.js < prev   
Text File  |  2001-05-05  |  14KB  |  657 lines

  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  *
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  *
  13.  * The Original Code is JSIRC Library
  14.  *
  15.  * The Initial Developer of the Original Code is New Dimensions Consulting,
  16.  * Inc. Portions created by New Dimensions Consulting, Inc. are
  17.  * Copyright (C) 1999 New Dimenstions Consulting, Inc. All
  18.  * Rights Reserved.
  19.  *
  20.  * Contributor(s): 
  21.  *
  22.  *
  23.  * Contributor(s):
  24.  *  Robert Ginda, rginda@ndcico.com, original author
  25.  *
  26.  *
  27.  * JavaScript utility functions.
  28.  *
  29.  * 1999-08-15 rginda@ndcico.com           v1.0
  30.  */
  31.  
  32. var DEBUG = true;
  33.  
  34. var dumpln;
  35. var dd;
  36.  
  37. if (typeof document == "undefined") /* in xpcshell */
  38.     dumpln = print;
  39. else
  40.     if (typeof dump == "function")
  41.         dumpln = function (str) {dump (str + "\n");}
  42.     else if (jsenv.HAS_RHINO)
  43.         dumpln = function (str) {var out = java.lang.System.out;
  44.                                  out.println(str); out.flush(); }
  45.     else
  46.         dumpln = function () {} /* no suitable function */
  47.  
  48. if (DEBUG)
  49.     dd = dumpln;
  50. else
  51.     dd = function (){};
  52.  
  53. var jsenv = new Object();
  54. jsenv.HAS_SECURITYMANAGER = ((typeof netscape == "object") &&
  55.                              (typeof netscape.security == "object"));
  56. jsenv.HAS_XPCOM = ((typeof Components == "function") &&
  57.                    (typeof Components.classes == "function"));
  58. jsenv.HAS_JAVA = (typeof java == "object");
  59. jsenv.HAS_RHINO = (typeof defineClass == "function");
  60. jsenv.HAS_DOCUMENT = (typeof document == "object");
  61.  
  62. function dumpObject (o, pfx, sep)
  63. {
  64.     var p;
  65.     var s = "";
  66.  
  67.     sep = (typeof sep == "undefined") ? " = " : sep;
  68.     pfx = (typeof pfx == "undefined") ? "" : pfx;    
  69.  
  70.     for (p in o)
  71.     {
  72.         if (typeof (o[p]) != "function")
  73.             s += pfx + p + sep + o[p] + "\n";
  74.         else
  75.             s += pfx + p + sep + "function\n";
  76.     }
  77.  
  78.     return s;
  79.  
  80. }
  81.  
  82. /* Dumps an object in tree format, recurse specifiec the the number of objects
  83.  * to recurse, compress is a boolean that can uncompress (true) the output
  84.  * format, and level is the number of levels to intitialy indent (only useful
  85.  * internally.)  A sample dumpObjectTree (o, 1) is shown below.
  86.  *
  87.  * + parent (object)
  88.  * + users (object)
  89.  * | + jsbot (object)
  90.  * | + mrjs (object)
  91.  * | + nakkezzzz (object)
  92.  * | *
  93.  * + bans (object)
  94.  * | *
  95.  * + topic (string) 'ircclient.js:59: nothing is not defined'
  96.  * + getUsersLength (function) 9 lines
  97.  * *
  98.  */
  99. function dumpObjectTree (o, recurse, compress, level)
  100. {
  101.     var s = "";
  102.     var pfx = "";
  103.  
  104.     if (typeof recurse == "undefined")
  105.         recurse = 0;
  106.     if (typeof level == "undefined")
  107.         level = 0;
  108.     if (typeof compress == "undefined")
  109.         compress = true;
  110.     
  111.     for (var i = 0; i < level; i++)
  112.         pfx += (compress) ? "| " : "|  ";
  113.  
  114.     var tee = (compress) ? "+ " : "+- ";
  115.  
  116.     for (i in o)
  117.     {
  118.         
  119.         var t = typeof o[i];
  120.         switch (t)
  121.         {
  122.             case "function":
  123.                 var sfunc = String(o[i]).split("\n");
  124.                 if (sfunc[2] == "    [native code]")
  125.                     sfunc = "[native code]";
  126.                 else
  127.                     if (sfunc.length == 1)
  128.                         sfunc = String(sfunc);
  129.                     else
  130.                         sfunc = sfunc.length + " lines";
  131.                 s += pfx + tee + i + " (function) " + sfunc + "\n";
  132.                 break;
  133.  
  134.             case "object":
  135.                 s += pfx + tee + i + " (object)\n";
  136.                 if (!compress)
  137.                     s += pfx + "|\n";
  138.                 if ((i != "parent") && (recurse))
  139.                     s += dumpObjectTree (o[i], recurse - 1,
  140.                                          compress, level + 1);
  141.                 break;
  142.  
  143.             case "string":
  144.                 if (o[i].length > 200)
  145.                     s += pfx + tee + i + " (" + t + ") " + 
  146.                         o[i].length + " chars\n";
  147.                 else
  148.                     s += pfx + tee + i + " (" + t + ") '" + o[i] + "'\n";
  149.                 break;
  150.  
  151.             default:
  152.                 s += pfx + tee + i + " (" + t + ") " + o[i] + "\n";
  153.                 
  154.         }
  155.  
  156.         if (!compress)
  157.             s += pfx + "|\n";
  158.  
  159.     }
  160.  
  161.     s += pfx + "*\n";
  162.     
  163.     return s;
  164.     
  165. }
  166.  
  167. /*
  168.  * Clones an existing object (Only the enumerable properties
  169.  * of course.) use as a function..
  170.  * var c = Clone (obj);
  171.  * or a constructor...
  172.  * var c = new Clone (obj);
  173.  */
  174. function Clone (obj)
  175. {
  176.     robj = new Object();
  177.  
  178.     for (var p in obj)
  179.         robj[p] = obj[p];
  180.  
  181.     return robj;
  182.     
  183. }
  184.  
  185. /*
  186.  * matches a real object against one or more pattern objects.
  187.  * if you pass an array of pattern objects, |negate| controls wether to check
  188.  * if the object matches ANY of the patterns, or NONE of the patterns.
  189.  */
  190. function matchObject (o, pattern, negate)
  191. {
  192.     negate = Boolean(negate);
  193.     
  194.     function _match (o, pattern)
  195.     {
  196.         if (pattern instanceof Function)
  197.             return pattern(o);
  198.         
  199.         for (p in pattern)
  200.         {
  201.             var val;
  202.                 /* nice to have, but slow as molases, allows you to match
  203.                  * properties of objects with obj$prop: "foo" syntax      */
  204.                 /*
  205.                   if (p[0] == "$")
  206.                   val = eval ("o." + 
  207.                   p.substr(1,p.length).replace (/\$/g, "."));
  208.                   else
  209.                 */
  210.             val = o[p];
  211.             
  212.             if (pattern[p] instanceof Function)
  213.             {
  214.                 if (!pattern[p](val))
  215.                     return false;
  216.             }
  217.             else
  218.             {
  219.                 var ary = (new String(val)).match(pattern[p]);
  220.                 if (ary == null)
  221.                     return false;
  222.                 else
  223.                     o.matchresult = ary;
  224.             }
  225.         }
  226.  
  227.         return true;
  228.  
  229.     }
  230.  
  231.     if (!(pattern instanceof Array))
  232.         return Boolean (negate ^ _match(o, pattern));
  233.             
  234.     for (var i in pattern)
  235.         if (_match (o, pattern[i]))
  236.             return !negate;
  237.  
  238.     return negate;
  239.     
  240. }
  241.  
  242. function matchEntry (partialName, list)
  243. {
  244.     
  245.     if ((typeof partialName == "undefined") ||
  246.         (String(partialName) == ""))
  247.         return list;
  248.  
  249.     var ary = new Array();
  250.  
  251.     for (var i in list)
  252.     {
  253.         if (list[i].indexOf(partialName) == 0)
  254.             ary.push (list[i]);
  255.     }
  256.  
  257.     return ary;
  258.     
  259. }
  260.  
  261. function getCommonPfx (list)
  262. {
  263.     var pfx = list[0];
  264.     var l = list.length;
  265.     
  266.     for (var i = 1; i < l; i++)
  267.     {
  268.         for (var c = 0; c < pfx.length; c++)
  269.             if (pfx[c] != list[i][c])
  270.                 pfx = pfx.substr (0, c);
  271.     }
  272.  
  273.     return pfx;
  274.  
  275. }
  276.  
  277. function renameProperty (obj, oldname, newname)
  278. {
  279.  
  280.     if (oldname == newname)
  281.         return;
  282.     
  283.     obj[newname] = obj[oldname];
  284.     delete obj[oldname];
  285.     
  286. }
  287.  
  288. function newObject(contractID, iface)
  289. {
  290.     if (!jsenv.HAS_XPCOM)
  291.         return null;
  292.  
  293.     var obj = Components.classes[contractID].createInstance();
  294.     var rv;
  295.  
  296.     switch (typeof iface)
  297.     {
  298.         case "string":
  299.             rv = obj.QueryInterface(Components.interfaces[iface]);
  300.             break;
  301.  
  302.         case "object":
  303.             rv = obj.QueryInterface[iface];
  304.             break;
  305.  
  306.         default:
  307.             rv = null;
  308.             break;
  309.     }
  310.  
  311.     return rv;
  312.     
  313. }
  314.  
  315. function getPriv (priv)
  316. {
  317.     if (!jsenv.HAS_SECURITYMANAGER)
  318.         return true;
  319.  
  320.     var rv = true;
  321.  
  322.     try
  323.     {
  324.         netscape.security.PrivilegeManager.enablePrivilege(priv);
  325.     }
  326.     catch (e)
  327.     {
  328.         dd ("getPriv: unable to get privlege '" + priv + "': " + e);
  329.         rv = false;
  330.     }
  331.     
  332.     return rv;
  333.     
  334. }
  335.  
  336. function keys (o)
  337. {
  338.     var rv = new Array();
  339.     
  340.     for (var p in o)
  341.         rv.push(p);
  342.  
  343.     return rv;
  344.     
  345. }
  346.  
  347. function stringTrim (s)
  348. {
  349.     if (!s)
  350.         return "";
  351.     s = s.replace (/^\s+/, "");
  352.     return s.replace (/\s+$/, "");
  353.     
  354. }
  355.  
  356. function formatDateOffset (seconds, format)
  357. {
  358.     seconds = parseInt(seconds);
  359.     var minutes = parseInt(seconds / 60);
  360.     seconds = seconds % 60;
  361.     var hours   = parseInt(minutes / 60);
  362.     minutes = minutes % 60;
  363.     var days    = parseInt(hours / 24);
  364.     hours = hours % 24;
  365.  
  366.     if (!format)
  367.     {
  368.         var ary = new Array();
  369.         if (days > 0)
  370.             ary.push (days + " days");
  371.         if (hours > 0)
  372.             ary.push (hours + " hours");
  373.         if (minutes > 0)
  374.             ary.push (minutes + " minutes");
  375.         if (seconds > 0)
  376.             ary.push (seconds + " seconds");
  377.  
  378.         format = ary.join(", ");
  379.     }
  380.     else
  381.     {
  382.         format = format.replace ("%d", days);
  383.         format = format.replace ("%h", hours);
  384.         format = format.replace ("%m", minutes);
  385.         format = format.replace ("%s", seconds);
  386.     }
  387.     
  388.     return format;
  389. }
  390.  
  391. function arraySpeak (ary, single, plural)
  392. {
  393.     var rv = "";
  394.     
  395.     switch (ary.length)
  396.     {
  397.         case 0:
  398.             break;
  399.             
  400.         case 1:
  401.             rv = ary[0];
  402.             if (single)
  403.                 rv += " " + single;            
  404.             break;
  405.  
  406.         case 2:
  407.             rv = ary[0] + " and " + ary[1];
  408.             if (plural)
  409.                 rv += " " + plural;
  410.             break;
  411.  
  412.         default:
  413.             for (var i = 0; i < ary.length - 1; ++i)
  414.                 rv += ary[i] + ", ";
  415.             rv += "and " + ary[ary.length - 1];
  416.             if (plural)
  417.                 rv += " " + plural;
  418.             break;
  419.     }
  420.  
  421.     return rv;
  422.     
  423. }
  424.  
  425.  
  426. function arrayContains (ary, elem)
  427. {
  428.     return (arrayIndexOf (ary, elem) != -1);
  429. }
  430.  
  431. function arrayIndexOf (ary, elem)
  432. {
  433.     for (var i in ary)
  434.         if (ary[i] == elem)
  435.             return i;
  436.  
  437.     return -1;
  438. }
  439.     
  440. function arrayInsertAt (ary, i, o)
  441. {
  442.  
  443.     ary.splice (i, 0, o);
  444.  
  445.     /* doh, forgot about that 'splice' thing
  446.     if (ary.length < i)
  447.     {
  448.         this[i] = o;
  449.         return;
  450.     }
  451.  
  452.     for (var j = ary.length; j > i; j--)
  453.         ary[j] = ary[j - 1];
  454.  
  455.     ary[i] = o;
  456.     */
  457. }
  458.  
  459. function arrayRemoveAt (ary, i)
  460. {
  461.  
  462.     ary.splice (i, 1);
  463.  
  464.     /* doh, forgot about that 'splice' thing
  465.     if (ary.length < i)
  466.         return false;
  467.  
  468.     for (var j = i; j < ary.length; j++)
  469.         ary[j] = ary[j + 1];
  470.  
  471.     ary.length--;
  472.     */
  473.  
  474. }
  475.  
  476. /* length should be an even number >= 6 */
  477. function abbreviateWord (str, length)
  478. {
  479.     if (str.length <= length || length < 6)
  480.         return str;
  481.  
  482.     var left = str.substr (0, (length / 2) - 1);
  483.     var right = str.substr (str.length - (length / 2) + 1);
  484.  
  485.     return left + "..." + right;
  486. }
  487.  
  488. /*
  489.  * Inserts the string |hyphen| into string |str| every |pos| characters.
  490.  * If there are any wordbreaking characters in |str| within -/+5 characters of
  491.  * of a |pos| then the hyphen is inserted there instead, in order to produce a
  492.  * "cleaner" break.
  493.  */
  494. function hyphenateWord (str, pos, hyphen)
  495. {
  496.     if (str.length <= pos)
  497.         return str;
  498.     if (typeof hyphen == "undefined")
  499.         hyphen = " ";
  500.  
  501.     /* search for a nice place to break the word, fuzzfactor of +/-5, centered
  502.      * around |pos| */
  503.     var splitPos =
  504.         str.substring(pos - 5, pos + 5).search(/[^A-Za-z0-9]/);
  505.  
  506.     splitPos = (splitPos != -1) ? pos - 4 + splitPos : pos;
  507.     var left = str.substr (0, splitPos);
  508.     var right = hyphenateWord(str.substr (splitPos), pos, hyphen);
  509.  
  510.     return left + hyphen + right;
  511. }
  512.  
  513. /*
  514.  * Like hyphenateWord, except individual chunks of the word are returned as
  515.  * elements of an array.
  516.  */
  517. function splitLongWord (str, pos)
  518. {
  519.     if (str.length <= pos)
  520.         return [str];
  521.  
  522.     var ary = new Array();
  523.     var right = str;
  524.     
  525.     while (right.length > pos)
  526.     {
  527.         /* search for a nice place to break the word, fuzzfactor of +/-5, 
  528.          * centered around |pos| */
  529.         var splitPos =
  530.             right.substring(pos - 5, pos + 5).search(/[^A-Za-z0-9]/);
  531.  
  532.         splitPos = (splitPos != -1) ? pos - 4 + splitPos : pos;
  533.         ary.push(right.substr (0, splitPos));
  534.         right = right.substr (splitPos);
  535.     }
  536.  
  537.     ary.push (right);
  538.  
  539.     return ary;
  540. }
  541.  
  542. function getRandomElement (ary)
  543. {
  544.     var i = parseInt (Math.random() * ary.length)
  545.     if (i == ary.length) i = 0;
  546.  
  547.     return ary[i];
  548.  
  549. }
  550.  
  551. function roundTo (num, prec)
  552. {
  553.  
  554.     return parseInt ( Math.round(num * Math.pow (10, prec))) /
  555.         Math.pow (10, prec);   
  556.  
  557. }
  558.  
  559. function randomRange (min, max)
  560. {
  561.  
  562.     if (typeof min == "undefined")
  563.         min = 0;
  564.  
  565.     if (typeof max == "undefined")
  566.         max = 1;
  567.  
  568.     var rv = (parseInt(Math.round((Math.random() * (max - min)) + min )));
  569.     
  570.     return rv;
  571.  
  572. }
  573.  
  574. function getStackTrace ()
  575. {
  576.  
  577.     if (!jsenv.HAS_XPCOM)
  578.         return "No stack trace available.";
  579.  
  580.     var frame = Components.stack.caller;
  581.     var str = "<top>";
  582.  
  583.     while (frame)
  584.     {
  585.         var name = frame.functionName ? frame.functionName : "[anonymous]";
  586.         str += "\n" + name + "@" + frame.lineNumber;
  587.         frame = frame.caller;
  588.     }
  589.  
  590.     return str;
  591.     
  592. }
  593.  
  594. function getInterfaces (cls)
  595. {
  596.     if (!jsenv.HAS_XPCOM)
  597.         return null;
  598.  
  599.     var rv = new Object();
  600.     var e;
  601.  
  602.     for (var i in Components.interfaces)
  603.     {
  604.         try
  605.         {
  606.             var ifc = Components.interfaces[i];
  607.             cls.QueryInterface(ifc);
  608.             rv[i] = ifc;
  609.         }
  610.         catch (e)
  611.         {
  612.             /* nada */
  613.         }
  614.     }
  615.  
  616.     return rv;
  617.     
  618. }
  619.  
  620. /**
  621.  * Calls a named function for each element in an array, sending
  622.  * the same parameter each call.
  623.  *
  624.  * @param ary           an array of objects
  625.  * @param func_name     string name of function to call.
  626.  * @param data          data object to pass to each object.
  627.  */      
  628. function mapObjFunc(ary, func_name, data)
  629. {
  630.     /* 
  631.      * WARNING: Caller assumes resonsibility to verify ary
  632.      * and func_name
  633.      */
  634.  
  635.     for (var i in ary)
  636.         ary[i][func_name](data);
  637. }
  638.  
  639. /**
  640.  * Passes each element of an array to a given function object.
  641.  *
  642.  * @param func  a function object.
  643.  * @param ary   an array of values.
  644.  */
  645. function map(func, ary) {
  646.  
  647.     /*
  648.      * WARNING: Caller assumnes responsibility to verify
  649.      * func and ary.
  650.      */
  651.  
  652.     for (var i in ary)
  653.         func(ary[i]);
  654.  
  655. }
  656.  
  657.