Script doesn't work in Safari

Discussion in 'Javascript' started by elektrophyte, May 20, 2005.

  1. elektrophyte

    elektrophyte Guest

    I've got a short script that works fine in I.E. and Firefox, but not in
    Safari. It is supposed to print a constantly-updating counter on the
    webpage. Any ideas how to get it to work in Safari? The script uses the
    Date object, especially Date.getTime(). Could that have something to do
    with the problem?

    Thanks,

    E


    // This <form> is put into the same HTML page as the script...
    <form name="counter" style="margin: 0; padding: 0;">
    <input type="text" name="amount" value="0" size="40" readonly="true"
    style="margin:0;padding:0;border:none;font-size:24px;color:#cc0000;">
    </form>

    // Here is the script...
    <script type="text/javascript">

    // The formatNumber function comes from Danny Goodman's JavaScript
    Cookbook.
    [ ... some code left out here for brevity ... ]

    var startingDate = new Date(2005, 0, 1);
    var startingDebt = 1000000000;
    function updateCounter(){
    var nowDate = new Date();
    var debtTimeInSeconds = (nowDate.getTime() -
    startingDate.getTime())/1000;
    var newValue = startingDebt + (debtTimeInSeconds * 3.47);
    document.counter.amount.value = "$" + formatNumber(newValue, 2);
    }
    updateCounter();
    intervalID = setInterval("updateCounter()", 1000);
    </script>
     
    elektrophyte, May 20, 2005
    #1
    1. Advertising

  2. elektrophyte

    RobG Guest

    elektrophyte wrote:
    > I've got a short script that works fine in I.E. and Firefox, but not in
    > Safari. It is supposed to print a constantly-updating counter on the
    > webpage. Any ideas how to get it to work in Safari? The script uses the
    > Date object, especially Date.getTime(). Could that have something to do
    > with the problem?
    >
    > Thanks,
    >
    > E
    >
    >
    > // This <form> is put into the same HTML page as the script...
    > <form name="counter" style="margin: 0; padding: 0;">
    > <input type="text" name="amount" value="0" size="40" readonly="true"
    > style="margin:0;padding:0;border:none;font-size:24px;color:#cc0000;">
    > </form>
    >
    > // Here is the script...
    > <script type="text/javascript">
    >
    > // The formatNumber function comes from Danny Goodman's JavaScript
    > Cookbook.
    > [ ... some code left out here for brevity ... ]
    >
    > var startingDate = new Date(2005, 0, 1);
    > var startingDebt = 1000000000;
    > function updateCounter(){
    > var nowDate = new Date();
    > var debtTimeInSeconds = (nowDate.getTime() -
    > startingDate.getTime())/1000;


    Manually wrap posted code at about 70 characters, allowing
    auto-wrapping can cause problems and with space indents not tabs.

    You also don't need the 'getTime()' method:

    var debtTimeInSeconds = (nowDate - startingDate)/1000;


    > var newValue = startingDebt + (debtTimeInSeconds * 3.47);
    > document.counter.amount.value = "$" + formatNumber(newValue, 2);
    > }
    > updateCounter();
    > intervalID = setInterval("updateCounter()", 1000);
    > </script>
    >


    It works fine in Safari 1.0.3 as far as I can tell if you remove the
    'formatNumber()' function. Post it for a fix.


    --
    RobG
     
    RobG, May 21, 2005
    #2
    1. Advertising

  3. elektrophyte

    RobG Guest

    RobG wrote:
    > elektrophyte wrote:
    >

    [...]
    >
    > It works fine in Safari 1.0.3 as far as I can tell if you remove the
    > 'formatNumber()' function. Post it for a fix.


    A little more playing shows that the debit in cents seems to exceed the
    size of integer that Safari can handle. I'll guess that the Danny
    Goodman's function converts the amount to cents and uses Math.floor (or
    round maybe) to truncate the decimal cents.

    Here's a version of the script that uses a modified version of Dr J R
    Stockton's 'TryCash()' function (which originally was based on cents
    but I've modified it to use decimal currency). Lightly tested (Firefox
    & Safari on OS X):


    <script type="text/javascript">

    var startingDate = new Date(2005,0,1);
    var startingDebt = 1000000000;

    function updateCounter(){
    var nowDate = new Date();
    var debtTimeInSeconds = (nowDate - startingDate)/1000;
    var newValue = startingDebt + (debtTimeInSeconds * 3.47);
    document.counter.amount.value = TryCash(newValue + ' $ , .');
    }
    updateCounter();
    intervalID = setInterval("updateCounter()",1000);

    function toCash(p, c, t, d) {
    var s = (0 > p)? "-" : "";
    p = p.split('.');
    var m = String(Math.abs(p[0]));
    var j, k = "", f;
    c = c || "";
    t = t || "";
    d = d || ".";
    while (m.length < 3) {
    m = "0"+m;
    }
    f = (p[1])? twoDigits(p[1]) : '00';
    j = m.length;
    while (j > 3) {
    k = t+m.substring(j-3, j)+k;
    j -= 3;
    }
    k = m.substring(0, j)+k;
    return s+c+k+d+f;
    }

    function TryCash(S) {
    var T = S.split(/\s+/);
    return toCash(T[0], T[1], T[2], T[3]);
    }

    function twoDigits(x){
    return (x.length < 2)? x+'0' : x.substring(0,2);
    }

    </script>





    --
    RobG
     
    RobG, May 21, 2005
    #3
  4. JRS: In article <428e9d89$0$956$5a62ac22@per-qv1-newsreader-
    01.iinet.net.au>, dated Sat, 21 May 2005 12:31:32, seen in
    news:comp.lang.javascript, RobG <> posted :
    >RobG wrote:
    >> elektrophyte wrote:
    >>

    >[...]
    >>
    >> It works fine in Safari 1.0.3 as far as I can tell if you remove the
    >> 'formatNumber()' function. Post it for a fix.

    >
    > A little more playing shows that the debit in cents seems to exceed the
    > size of integer that Safari can handle.
    > ...


    Which is?

    Does Safari actually have a distinct integer type?

    Is it just that Math.floor .ceil .round use Int32 internally (so that
    they may have the mechanism for returning larger numbers, but never
    generate them)?

    AFAIR, according to spec, the only things that should be limited to
    Int32 are the seven operators ~ & | ^ << >> >>> and their assignment
    forms.

    ~~X appears to truncate X towards zero and do a signed modulo
    2^32 on it. There must be a use for that.

    --
    © John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
    <URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
    <URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
    <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
     
    Dr John Stockton, May 22, 2005
    #4
  5. elektrophyte

    elektrophyte Guest

    Thank you very much for the replies. As suggested I removed the
    getTime() and formatNumber() calls and now it works in Safari. Now I
    just need to debug formatNumber(). I got it from Danny Goodman's
    JavaScript Cookbook (Oreilly). Maybe I'll just try to write my own
    function to format the number. In case anyone is curious, I'll add
    Goodman's code below.

    // The formatNumber function comes from Danny Goodman's
    // JavaScript Cookbook.
    function formatNumber (num, decplaces) {
    // convert in case it arrives as a string value
    num = parseFloat(num);
    // make sure it passes conversion
    if (!isNaN(num)) {
    // multiply value by 10 to the decplaces power;
    // round the result to the nearest integer;
    // convert the result to a string
    var str = "" + Math.round (eval(num) *
    Math.pow(10,decplaces));
    // exponent means value is too big or small
    // for this routine
    if (str.indexOf("e") != -1) {
    return "Out of Range";
    }
    // if needed for small values, pad zeros
    // to the left of the number
    while (str.length <= decplaces) {
    str = "0" + str;
    }
    // calculate decimal point position
    var decpoint = str.length - decplaces;
    // assemble final result from: (a) the string
    // up to the position of
    // the decimal point; (b) the decimal point;
    // and (c) the balance
    // of the string. Return finished product.
    return str.substring(0,decpoint) + "." +
    str.substring(decpoint,str.length);
    } else {
    return "NaN";
    }
    }
     
    elektrophyte, May 23, 2005
    #5
  6. elektrophyte

    RobG Guest

    elektrophyte wrote:
    > Thank you very much for the replies. As suggested I removed the
    > getTime() and formatNumber() calls and now it works in Safari. Now I
    > just need to debug formatNumber(). I got it from Danny Goodman's
    > JavaScript Cookbook (Oreilly). Maybe I'll just try to write my own
    > function to format the number. In case anyone is curious, I'll add
    > Goodman's code below.
    >


    Here's another that can handle any precision and adds commas. Remove
    validation and comments and it's only marginally longer that DG's.


    function formatDecimal(n, d) {
    // Is n digit(s) with optional point or optional point and digit(s)
    if ( !/^(\d+)[\.|(\.\d+)]*$/.test(n) ) {
    return "Number part should be format 0 or 0.0";
    }

    // Is d an int?
    if ( !/^(\d+)[\.|(\.0+)]*$/.test(d) ) {
    return "Number of decimal places must be an integer";
    }

    // nd is number of digits before zero
    var nd = (n + '').split('.')[0].length;

    // len is total number of digits required
    var len = +d + nd;

    // n is array of digits with decimal place removed
    n = n.replace(/\./,'').split('');

    // If there is a digit after required length, do rounding,
    var i=len, r='';

    // If last+1 digit is bigger than 4
    if ( n && n > 4 ){
    // While preceding number is 9 and not first
    while ( 9 == n[--i] && i > 0 ) {
    // Make it zero
    n = 0;
    }
    // Add one to wherever we got to
    n -= -1;
    }

    // Build up integer part
    i = 0;
    while ( i < nd ) {
    // No commas version;
    // r += '' + n[i++];

    // Commas version
    r += (( (nd-i)%3 )? '' : (0 == i)? '':',') + n[i++];
    }

    // Add decimal part
    if ( d > 0 ) {
    r += '.';
    while ( i < len ) {
    r += n[i++] || '0';
    }
    }
    return r;
    }


    --
    Rob
     
    RobG, May 24, 2005
    #6
  7. elektrophyte

    RobG Guest

    RobG wrote:
    [...]
    > Here's another that can handle any precision and adds commas. Remove
    > validation and comments and it's only marginally longer that DG's.


    I should post sooner, I'd find the bugs quicker...

    >
    >
    > function formatDecimal(n, d) {
    > // Is n digit(s) with optional point or optional point and digit(s)
    > if ( !/^(\d+)[\.|(\.\d+)]*$/.test(n) ) {
    > return "Number part should be format 0 or 0.0";
    > }
    >
    > // Is d an int?
    > if ( !/^(\d+)[\.|(\.0+)]*$/.test(d) ) {
    > return "Number of decimal places must be an integer";
    > }
    >
    > // nd is number of digits before zero
    > var nd = (n + '').split('.')[0].length;
    >
    > // len is total number of digits required
    > var len = +d + nd;
    >
    > // n is array of digits with decimal place removed
    > n = n.replace(/\./,'').split('');
    >
    > // If there is a digit after required length, do rounding,
    > var i=len, r='';
    >
    > // If last+1 digit is bigger than 4
    > if ( n && n > 4 ){
    > // While preceding number is 9 and not first
    > while ( 9 == n[--i] && i > 0 ) {
    > // Make it zero
    > n = 0;
    > }
    > // Add one to wherever we got to
    > n -= -1;
    > }


    If the number is 999.9, result is 1000.0 not 1,000.0. Here's the fix:

    // Add one to wherever we got to
    n -= -1;

    // Make sure it's not '10'
    if ( 10 == n )
    n = 0;
    n.splice(i,0,'1');
    }

    If the 'comma' output is not required, the fix isn't needed.

    [...]

    --
    Rob
     
    RobG, May 24, 2005
    #7
  8. elektrophyte

    RobG Guest

    RobG wrote:
    > RobG wrote:
    > [...]
    >

    [...]
    >
    > // Make sure it's not '10'
    > if ( 10 == n )
    > n = 0;
    > n.splice(i,0,'1');
    > }
    >


    Brain-dead day:

    // Make sure it's not '10'
    if ( 10 == n ) {
    n = 0;
    n.splice(i,0,'1');
    nd++;
    }




    --
    Rob
     
    RobG, May 24, 2005
    #8
  9. JRS: In article <>,
    dated Mon, 23 May 2005 11:03:26, seen in news:comp.lang.javascript,
    elektrophyte <> posted :
    >Thank you very much for the replies. As suggested I removed the
    >getTime() and formatNumber() calls and now it works in Safari. Now I
    >just need to debug formatNumber(). I got it from Danny Goodman's
    >JavaScript Cookbook (Oreilly). Maybe I'll just try to write my own
    >function to format the number.


    That would be unwise, unless you need the practice; many have done so
    and got it wrong. Instead, read the newsgroup FAQ.

    > In case anyone is curious, I'll add
    >Goodman's code below.
    >
    >// The formatNumber function comes from Danny Goodman's
    >// JavaScript Cookbook.
    >function formatNumber (num, decplaces) {
    > // convert in case it arrives as a string value
    > num = parseFloat(num);
    > // make sure it passes conversion
    > if (!isNaN(num)) {
    > // multiply value by 10 to the decplaces power;
    > // round the result to the nearest integer;
    > // convert the result to a string
    > var str = "" + Math.round (eval(num) *

    ^^^^

    Pointless. Function parseFloat always returns a Number, even though it
    may be NaN or an Infinity.

    When replying, please quote, attribute & ignore Lahn :

    Keith Thompson wrote in comp.lang.c, message ID
    <> :-
    If you want to post a followup via groups.google.com, don't use
    the "Reply" link at the bottom of the article. Click on "show
    options" at the top of the article, then click on the "Reply" at
    the bottom of the article headers.

    --
    © John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
    <URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
    <URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
    <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
     
    Dr John Stockton, May 24, 2005
    #9
  10. JRS: In article <08yke.1605$>, dated Tue, 24
    May 2005 04:33:00, seen in news:comp.lang.javascript, RobG
    <> posted :
    >
    > Here's another that can handle any precision and adds commas. Remove
    > validation and comments and it's only marginally longer that DG's.
    >
    >
    >function formatDecimal(n, d) {



    Float arithmetic has rounding errors; therefore, a Number that ideally
    would be zero may be slightly negative. Your routine fails with those,
    as with genuine negatives.

    Also, it fails with input '5e5', though it works with '550000'

    It looks rather slow, though I've not checked.

    I don't see why one should want a routine that treats its parameter as a
    string; but it does work with numbers that more-numeric methods would
    find too big.

    --
    © John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
    <URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
    <URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
    <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
     
    Dr John Stockton, May 24, 2005
    #10
  11. elektrophyte

    RobG Guest

    Dr John Stockton wrote:
    > JRS: In article <08yke.1605$>, dated Tue, 24
    > May 2005 04:33:00, seen in news:comp.lang.javascript, RobG
    > <> posted :
    >
    >> Here's another that can handle any precision and adds commas. Remove
    >> validation and comments and it's only marginally longer that DG's.
    >>
    >>
    >>function formatDecimal(n, d) {

    >
    >
    >
    > Float arithmetic has rounding errors; therefore, a Number that ideally
    > would be zero may be slightly negative. Your routine fails with those,
    > as with genuine negatives.


    Yes, but the negative part could be easily fixed.

    >
    > Also, it fails with input '5e5', though it works with '550000'
    >


    Yes.

    > It looks rather slow, though I've not checked.


    Takes about 6 times longer than toFixed(), 3 times longer than simple
    string truncation methods.

    >
    > I don't see why one should want a routine that treats its parameter as a
    > string; but it does work with numbers that more-numeric methods would
    > find too big.
    >


    'cos it's more fun than using toFixed() :)

    toFixed() is *the* fastest method and, in the OP's case, if it's not
    supported, then simply truncating the decimal cents is likely perfectly
    adequate (unless decimal cents are important in what looks like US
    military spending or national debt).



    --
    Rob
     
    RobG, May 25, 2005
    #11
  12. JRS: In article <RMSke.1644$>, dated Wed, 25
    May 2005 04:01:53, seen in news:comp.lang.javascript, RobG
    <> posted :
    >
    > toFixed() is *the* fastest method and, in the OP's case, if it's not
    > supported, then simply truncating the decimal cents is likely perfectly
    > adequate (unless decimal cents are important in what looks like US
    > military spending or national debt).


    AIUI, when actually doing accounts, the arithmetic must be exact, and in
    compliance with applicable rounding rules.

    Here, BT has recently announced that, from 2005-06-17, billed VAT will
    be rounded up, rather than down, to the nearest penny. In either case,
    small rounding errors such as can be expected when using non-integers
    can flip the result from one state to another, when the nominal
    calculation gives an exact result.

    Wasting a few billion is another matter, of course; only to be expected.

    --
    © John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
    <URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
    <URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
    <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
     
    Dr John Stockton, May 25, 2005
    #12
  13. elektrophyte wrote:

    > [...]
    > // The formatNumber function comes from Danny Goodman's
    > // JavaScript Cookbook.
    > function formatNumber (num, decplaces) {
    > // convert in case it arrives as a string value
    > num = parseFloat(num);
    > // make sure it passes conversion
    > if (!isNaN(num)) {

    ^^^^^^^^^^^
    > // multiply value by 10 to the decplaces power;
    > // round the result to the nearest integer;
    > // convert the result to a string
    > var str = "" + Math.round (eval(num) *

    ^^^^^^^^^
    > Math.pow(10,decplaces));


    OK, at least from now on Goodman can no longer be considered a viable
    source for JS information either. Sometimes I hate it when I'm right.


    PointedEars
     
    Thomas 'PointedEars' Lahn, May 27, 2005
    #13
  14. Thomas 'PointedEars' Lahn wrote:
    > elektrophyte wrote:
    >> // The formatNumber function comes from Danny Goodman's

    <snip>
    >> var str = "" + Math.round (eval(num) *

    > ^^^^^^^^^
    >> Math.pow(10,decplaces));

    >
    > OK, at least from now on Goodman can no longer be considered
    > a viable source for JS information either.


    No change then. Danny Goodman has promoted the most extraordinary -
    eval - abuses over the years, and much else that is positively
    discouraged by the competent.

    Richard.
     
    Richard Cornford, May 27, 2005
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dan
    Replies:
    3
    Views:
    1,027
  2. rigo
    Replies:
    0
    Views:
    191
  3. Kim Forbes
    Replies:
    5
    Views:
    137
    Kim Forbes
    Oct 18, 2004
  4. MPennig
    Replies:
    4
    Views:
    127
  5. jennyw

    onbeforeunload doesn't work in Safari

    jennyw, Nov 11, 2005, in forum: Javascript
    Replies:
    4
    Views:
    141
Loading...

Share This Page