Johan Broddfelt
/* Comments on code */

Obstetric pain timer

What do you spend time on when your lady has obstetric pain?

When my wife was pregnant and about to conceive, we looked for a good Obstetric pain timer. We checked out some apps and some web pages, but none of them really showed us what we wanted and in a way that was usable in a mobile phone. So, I did what every parent to be does in this situation. I started to write some code. =)

Obstetric pain timer (English)
Värktimer (Svenska)

jQuery to pure javascript and an issue with the Edge browser

When I wrote the timer I used jQuery but on my blog I want all my code to be pure javascript, so I rewrote the code. And here you can see the difference between jQuery code and pure javascript.

There is one other thing I noticed though. Foolishly enough I tested the code in the Edge browser, where it failed completely, even though it worked fine in chrome. All the numbers from the timer return as NaN. I ran a lot of tests and searched the Internet for an answer and finally i found this old post that gave me some insights to what might cause the problem. The toLocaleTimeString() returns a string with some non-ascii characters in it, thanks for those Microsoft. When I later tried to use parseInt on the string it failed. I just had to create a RegEx that removed the invisible characters and then it worked in the Edge browser as well. If you encounter this problem, look for the removeNonAscii function in my code.


           background: #ff9999;
         }
       </style>
 -     <script src="js/jquery-1.3.2.min.js"></script>
       <script>
 -       $(document).ready(function() {
 +     // Manage classes in html elements
 +     function hasClass(ele,cls) {
 +       return !!ele.className.match(new RegExp('(s|^)'+cls+'(s|$)'));
 +     }
 + 
 +     function addClass(ele,cls) {
 +       if (!hasClass(ele,cls)) { ele.className += " " + cls; }
 +     }
 + 
 +     function removeClass(ele,cls) {
 +       if (hasClass(ele,cls)) {
 +         var reg = new RegExp('(s|^)'+cls+'(s|$)');
 +         ele.className=ele.className.replace(reg,' ');
 +       }
 +     }
 +     function insertAfter(newNode, referenceNode) {
 +         referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
 +     }
 +     // In IE 11 and Edge the toLocaleTimeString() function adds some non-ascii characters that makes it imposible to do parseInt on the string later
 +     function removeNonAscii(str) {
 +         var regx = new RegExp("[^u0000-u007F]", "g");
 +         return str.replace(regx, '');
 +     }
 +     document.addEventListener("DOMContentLoaded", function() {
           // Init time
           var starttime, endtime, duration, frequency, s, e, laststart, l, d, f, ad, af;
           var highlightEndOfLabour, highlightStartOfLabour, numberOfdataForAvg;
 +         var clock = document.getElementById('clock');
 +         var button = document.getElementById('button');
           highlightEndOfLabour = 10; // Hur många sekunder innan värken är beräknad att sluta skall klockan byta till grön färg
           highlightStartOfLabour = 30; // Hur många sekunder innan värken är beräknad att börja skall klockan byta till röd färg
           numberOfdataForAvg = 3; // Hur många av de senaste verkarna skall användas vid beräkning av medeltid på värkar
...

           }
   
           function setTime() {
 +             var left = document.getElementById('left');
             var dt = new Date();
 -           $('#clock').html(dt.toLocaleTimeString());
 -           curr = $('#clock').html();
 +           // removeNoneAscii is neede in IE11 and Edge browser, otherwise we can not do parseInt on the string later
 +           clock.innerHTML = removeNonAscii(dt.toLocaleTimeString());
 +           curr = clock.innerHTML;
             c = curr.split(':');
             c = parseInt(c[0], 10)*60*60 + parseInt(c[1], 10)*60 + parseInt(c[2], 10);
 -           if ($('#button').attr('class') === 'active') {
 +           if (hasClass(button, 'active')) {
               tmp = (ad-(c-s));
               if (tmp < 0) {
 -               $('#left').css({color:'#cc0000'});
 +               left.style.color = '#cc0000';
                 tmp = '-' + secToTime(-tmp);
               } else {
 -               $('#left').css({color:'#000000'});
 -               tmp = secToTime(tmp);
 +                 if (left !== null) {
 +                     left.style.color = '#000000';
 +                 }
 +                 tmp = secToTime(tmp);
               }
 -             $('#left').html(tmp);
 +             if (left !== null) {
 +                 left.innerHTML = tmp;
 +             }
               if ((c-s) > (ad-(highlightEndOfLabour+1))) {
 -               $('#clock').css({color:'#00cc00'});
 +               clock.style.color = '#00cc00';
               }
             } else {
               af = parseInt(af, 10);

...

               tmp = (af-(c-s))
               if (!isNaN(tmp)) {
                 if (tmp < 0) {
 -                 $('#left').css({color:'#cc0000'});
 +                 left.style.color = '#cc0000';
                   tmp = '-' + secToTime(-tmp);
                 } else {
 -                 $('#left').css({color:'#000000'});
 +                 left.style.color = '#000000';
                   tmp = secToTime(tmp);
                 }
 -               $('#left').html(tmp);
 +               left.innerHTML = tmp;
               } else {
 -               $('#left').html('-');
 +                 if (left !== null) {
 +                     left.innerHTML = '-';
 +                 }
               }
               if ((c-s) > (af-(highlightStartOfLabour+1))) {
 -               $('#clock').css({color:'#cc0000'});
 +               clock.style.color = '#cc0000';
               }
             }
             
...

           }
           updateTime();
           laststart = '';
 -         $('#button').click(function() {
 -           if ($('#button').attr('class') === 'active') {
 -             $('#clock').css({color:'#000000'});
 -             $('#button').attr('class', 'inactive');
 -             $('#button').html('Klicka när värken börjar');
 -             endtime = $('#clock').html();
 +         button.addEventListener("click",function() {
 +           if (hasClass(button, 'active')) {
 +             clock.style.color = '#000000';
 +             removeClass(button, 'active');
 +             addClass(button, 'inactive');
 +             button.innerHTML = 'Klicka när värken börjar';
 +             endtime = clock.innerHTML;
               // Beräkna tiden i sekunder
               e = endtime.split(':');
               e = parseInt(e[0], 10)*60*60 + parseInt(e[1], 10)*60 + parseInt(e[2], 10);

...

                 frequency = '-';
               }
               // Updatera tabellen
 -             $('<tr class="rows" d="'+d+'" f="'+f+'"><td>' + starttime + '</td><td>' + endtime + '</td><td>' + duration + '</td><td>' + frequency + '</td></tr>').insertAfter('#titles');
 +             var titles = document.getElementById('titles');
 +             var newNode = document.createElement('tr');
 +             addClass(newNode, 'rows');
 +             newNode.setAttribute('d', d);
 +             newNode.setAttribute('f', f);
 +             //newNode = '<tr class="rows" d="'+d+'" f="'+f+'"><td>' + starttime + '</td><td>' + endtime + '</td><td>' + duration + '</td><td>' + frequency + '</td></tr>';
 +             newNode.innerHTML = '<td>' + starttime + '</td><td>' + endtime + '</td><td>' + duration + '</td><td>' + frequency + '</td>';
 +             insertAfter(newNode, titles);
               laststart = starttime;
               
               // Recalculate avarage

...
               dTot = 0;
               fCnt = 0;
               dCnt = 0;
 -             $('.rows').each(function() {
 +             var rows = document.getElementsByClassName('rows');
 +             //rows.each(function() {
 +             var i = 0;
 +             while (i < rows.length) {
                 if (cnt > numberOfdataForAvg) {
                   return false;
                 }
 -               if (parseInt($(this).attr('f'), 10) > 0) {
 -                 fTot = fTot + parseInt($(this).attr('f'), 10);
 +               if (parseInt(rows[i].getAttribute('f'), 10) > 0) {
 +                 fTot = fTot + parseInt(rows[i].getAttribute('f'), 10);
                   fCnt++;
                 }
 -               dTot = dTot + parseInt($(this).attr('d'), 10);
 +               dTot = dTot + parseInt(rows[i].getAttribute('d'), 10);
                 dCnt++;
                 cnt++;
 -             });
 +               i++;
 +             }
 +             //});
               //console.log('Res: f ' + Math.round(fTot/fCnt) + ', d ' + Math.round(dTot/dCnt));
               af = parseInt(Math.round(fTot/fCnt), 10);
               avgF = secToTime(af);
               if (fTot > 0) {} else { avgF = '-'; }
               ad = Math.round(dTot/dCnt);
               avgD = secToTime(ad);
 -             $('#avg').html('Genomsnitt längd: ' + avgD + '<br> Genomsnitt frekvens: ' + avgF + '<br><b>Tid kvar: <span id="left"></span></b>');
 +             var avg = document.getElementById('avg');
 +             avg.innerHTML = 'Genomsnitt längd: ' + avgD + '<br> Genomsnitt frekvens: ' + avgF + '<br><b>Tid kvar: <span id="left"></span></b>';
             } else {
 -             $('#clock').css({color:'#000000'});
 -             $('#button').attr('class', 'active');
 -             $('#button').html('Klicka när värken slutar');
 -             starttime = $('#clock').html();
 +             clock.style.color = '#000000';
 +             removeClass(button, 'inactive');
 +             addClass(button, 'active');
 +             button.innerHTML = 'Klicka när värken slutar';
 +             starttime = clock.innerHTML;
               s = starttime.split(':');
               //console.log(starttime + ' ' + s[0]+s[1]+s[2]);
               s = parseInt(s[0], 10)*60*60 + parseInt(s[1], 10)*60 + parseInt(s[2], 10);
             }
           });
 -       });
 +     },false);
       </script>
     </head>
     <body>

- javascript, jQuery, Edge, toLocaleTimeString

Follow using RSS

<< Offline Web Application Learn lowercase letters >>

Comment

Name
Mail (Not public)
Send mail uppdates on new comments
0 comment