Solved

Convert numeric entry into formatted time string

Posted on 2016-08-15
13
65 Views
Last Modified: 2016-08-17
I want the user to be able to type numbers - such as 3468 - and for that to be transformed / formatted into a time string. So, 3468 would translate to 34.68 (which is 34 seconds and .68 seconds or 680 milliseconds), 10200 would translate to 1 minute, 2 seconds and 0 milliseconds. So, the user would always have to enter the time down to the milliseconds.

This is for a swimming results website, so users would expect to enter 34.68, not 34.680

I have seen the HTML 5 "time" input type, but I can't get it to only show 2 digits for the milliseconds.

Is there a ready-built control to handle this type of input, that is also cross-browser friendly (and as wide support as possible, including mobile)?

Don't mind if it is a jQuery control, JavaScript, etc but it is for a C# / MVC website.
0
Comment
Question by:ascendinternet
  • 6
  • 3
  • 2
  • +2
13 Comments
 
LVL 12

Expert Comment

by:Dustin Saunders
Comment Utility
I don't quite understand what you need.  Why not just store the information as milliseconds and use code to display the format?

When they enter in the time how do you know that 10200 is 1 minute 2 seconds 0 milliseconds and not 10 seconds 200 milliseconds?
0
 

Author Comment

by:ascendinternet
Comment Utility
Because of convention ... swimming events are recorded to .01 of a second, so 10200 is 1:02.00 - or 1 minute, 2 seconds, 0 milliseconds.

So, I want an input box where a user can type in ... 10200 (1 min, 2 sec, 0 ms), or 3459 (34 sec, 59 ms). Either when the user enters it, it should be formatted correct (a mask like the HTML 5 "Time" input), or after leaving the input box (jQuery?).
0
 
LVL 12

Expert Comment

by:Dustin Saunders
Comment Utility
I see- in that case you can use the Masked Text Box control to format the input.  You can either have it static set to show the mask (something like 00:00.00) or have it start at 00 then use something like this to update the mask as you extend it (giving it a more dynamic feeling):

        private void maskedTextBox1_TextChanged(object sender, EventArgs e)
        {
            label1.Text = maskedTextBox1.Text.Length.ToString();
            if (maskedTextBox1.Text.Length == 2)
            {
                maskedTextBox1.Mask = "00.00";
                maskedTextBox1.SelectionStart = maskedTextBox1.Text.Length - 1;
                maskedTextBox1.SelectionLength = 0;
            }
            else if (maskedTextBox1.Text.Length == 5)
            {
                maskedTextBox1.Mask = "00:00.00";
                maskedTextBox1.SelectionStart = maskedTextBox1.Text.Length - 1;
                maskedTextBox1.SelectionLength = 0;
            }
        }

Open in new window


(in my box I have the property RightToLeft set, as well as HidePromptOnLeave)
0
 

Author Comment

by:ascendinternet
Comment Utility
Ah, sorry - I should have made it clearer that this is for a web page, so I can't use the Masked Text Box - at least I assume I can't!?

(Can I edit my question to add more relevant tags?!)
0
 
LVL 78

Expert Comment

by:David Johnson, CD, MVP
Comment Utility
i HAD a vb webform open so I used this
webform2.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="webForm2.aspx.vb" Inherits="webForm2" %>
<%@ Register assembly="Telerik.Web.UI" namespace="Telerik.Web.UI" tagprefix="telerik" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>EE28963458</title>
</head>
    <body>
    <form id="form1" runat="server">
        <telerik:RadScriptManager ID="RadScriptManager1" runat="server" EnableTheming="True">
            <Scripts>
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js">
                </asp:ScriptReference>
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js">
                </asp:ScriptReference>
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQueryInclude.js">
                </asp:ScriptReference>
            </Scripts>
        </telerik:RadScriptManager>
        <telerik:RadStyleSheetManager ID="RadStyleSheetManager1" runat="server">
        </telerik:RadStyleSheetManager>
        <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
        </telerik:RadAjaxManager>
    <div>
    
        <telerik:RadMaskedTextBox ID="RadMaskedTextBox1" Runat="server" AutoPostBack="True" DisplayMask="#:##.##" HideOnBlur="True" LabelWidth="64px" Mask="#:##.##" PromptChar="#" ToolTip="Minutes:Seconds.Milliseconds" Width="160px">
        </telerik:RadMaskedTextBox>
        <br />
        The Entered Time is <asp:Label ID="Label1" runat="server" Text="0"></asp:Label>
&nbsp;Minutes
        <asp:Label ID="Label2" runat="server" Text="0"></asp:Label>
&nbsp;Seconds
        <asp:Label ID="Label3" runat="server" Text="0"></asp:Label>
&nbsp;Milliseconds</div>
    </form>
</body>
</html>

Open in new window

Webform2.asps.vb
Partial Class WebForm2
    Inherits System.Web.UI.Page

    Protected Sub RadMaskedTextBox1_TextChanged(sender As Object, e As EventArgs) Handles RadMaskedTextBox1.TextChanged
        Label1.Text = Left(RadMaskedTextBox1.Text, 1)
        Label2.Text = Mid(RadMaskedTextBox1.Text, 2, 2)
        Label3.Text = Mid(RadMaskedTextBox1.Text, 4, 2)
    End Sub
End Class

Open in new window


This requires the telerik web UI Controls.. I don't know how much coding you do if  buying the controls is worthwhile for you
0
 

Author Comment

by:ascendinternet
Comment Utility
Unfortunately, price-wise, the Telerik controls are a "massive sledgehammer" to crack a fairly small "nut"! :-(
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
Here is a simple implementation
HTML
<input class="millisecs" type="text" />

Open in new window

JQuery
<script src="http://code.jquery.com/jquery.js"></script>
<script>
$(function() {
  $('.millisecs').on('keypress',function(e) {

    // Check for valid input and return false if
    // not a number or a navigation key
    if ((e.charCode < 48 || e.charCode > 57) &&
      e.keyCode != 8 &&
      e.keyCode != 9 &&
      e.keyCode != 13 &&
      e.keyCode != 18 &&
      e.keyCode != 35 &&
      e.keyCode != 36 &&
      e.keyCode != 37 &&
      e.keyCode != 39 &&
      e.keyCode != 46) {
      
      return false;
    }
  });
  // Format the output  
  $('.millisecs').on('keyup',function() {
    var x = $(this).val();
    // Get rid of any previous decimal
    while (x - parseInt(x) > 0) {
      x *=10;
    }
    // Set the new output
    $(this).val((x/100).toFixed(2));
  });
});
</script>

Open in new window

Working sample here
1
 

Author Comment

by:ascendinternet
Comment Utility
Julian - thanks for your post.

I seem to have forgotten to mention a few things in my post (it's a shame I can't change it), but for seconds and milliseconds the format is 34.56. However, for minutes, seconds and milliseconds it needs to be 1:34.56.

I found a jQuery "mask" plugin http://igorescobar.github.io/jQuery-Mask-Plugin/ which has given me (hopefully) the functionality I need:

<input type="text" maxlength="8" class="form-control timeInput" name="timeInput" id="@RaceNumber">

Open in new window


and
        var opts = {
            reverse: true,
            onKeyPress: function(cep, e, field, options) {
                if (cep.length === 6) {
                    e.preventDefault();
                }
            }
        };
        $('.timeInput').mask('00:00.00', opts);

Open in new window


However, if I could write the jQuery code myself (and/or with help!!) then that would probably be preferable.
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
The mask plugin is probably the way to go - my code is just a quick and dirty.

Here is an update that should handle the new format

$('.millisecs').on('keyup',function() {
    var current = $(this).val();
    var clean = '' + parseInt(current.replace(/[^\d]/g,''));
    var masked = '';
    for (i = clean.length - 1;i >=0;i--) {
      // Add the .
      if (clean.length - i == 3) {
        masked = '.' + masked;
      }
      // Add the :
      if (clean.length - i == 5) {
        masked = ':' + masked;
      }
      masked = clean[i] + masked;
    }

  $(this).val(masked);

Open in new window

Updated sample here
0
 

Author Comment

by:ascendinternet
Comment Utility
That looks very interesting and almost works ;-) (delete all digits and you get "NaN").

The plugin works but if it can be done in as few lines as above, I might prefer to pursue that option.
0
 
LVL 49

Expert Comment

by:Gustav Brock
Comment Utility
As you have C# you could use this to build the string:
String entry;
TimeSpan result;
string format = "hh':'mm':'ss'.'ff";

entry = "23453241";

int formatSubLength = entry.Length;
formatSubLength -= 3 * (-(formatSubLength - 1) / 2);
format = format.Substring (format.Length - formatSubLength);
char pad = '0';
entry = entry.PadLeft(8, pad);
IFormatProvider formatProvider =  System.Globalization.CultureInfo.InvariantCulture;
result = TimeSpan.ParseExact(entry, "hhmmssff", formatProvider);

entry = result.ToString(format); 
// 23:45:32.41

Open in new window

Wrap it in a try-error to catch invalid entries from typing errors like the eight (8) here: 23458271

/gustav
0
 
LVL 51

Accepted Solution

by:
Julian Hansen earned 500 total points
Comment Utility
Fix for NaN
  $('.millisecs').on('keyup',function() {
    var current = $(this).val();
    if (current == '') {
      masked = '';
    }
    else {
      var clean = '' + parseInt(current.replace(/[^\d]/g,''));
      var masked = '';
      for (i = clean.length - 1;i >=0;i--) {
        // Add the .
        if (clean.length - i == 3) {
        masked = '.' + masked;
        }
        // Add the :
        if (clean.length - i == 5) {
          masked = ':' + masked;
        }
        masked = clean[i] + masked;
      }
    }
   
    $(this).val(masked);
  });

Open in new window

Updated sample here
0
 

Author Closing Comment

by:ascendinternet
Comment Utility
There is a little extra code in the linked to sample which was needed to make it a more complete answer.
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

How to build a simple, quick and effective accordion menu using just 15 lines of jQuery and 2 css classes
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now