Anders Tornblad

All about the code

Label archive for stackoverflow

Using Source Maps with CSS

StackOverflow user Rob had a problem inspecting his SASS stylesheets after having them preprocessed by Codekit.

Having set the Output Style to "Compressed", the resulting CSS stylesheets were optimized and minified, making it almost impossible to trace the CSS back to the original SASS files.

Checking the Create a Source Map setting allowed him to help Google Chrome DevTools map the compiled CSS to the original SASS files, using a .map file, that the browser automatically uses. The principle of Source Maps is well known for JavaScript developers, but most people don't know that it is possible for CSS preprocessors too.

More information is available in the Codekit documentation for SASS.

Converting from Type to SqlDbType

StackOverflow user Simone Salvo asked how to do a smart conversion between .Net System.Type and System.Data.SqlDbType, which is not really a trivial task.

For my answer, I wrote the following somewhat naïve code:

public class SqlHelper { private static Dictionary<Type, SqlDbType> typeMap; // Create and populate the dictionary in the static constructor static SqlHelper() { typeMap = new Dictionary<Type, SqlDbType>(); typeMap[typeof(string)] = SqlDbType.NVarChar; typeMap[typeof(char[])] = SqlDbType.NVarChar; typeMap[typeof(byte)] = SqlDbType.TinyInt; typeMap[typeof(short)] = SqlDbType.SmallInt; typeMap[typeof(int)] = SqlDbType.Int; typeMap[typeof(long)] = SqlDbType.BigInt; typeMap[typeof(byte[])] = SqlDbType.Image; typeMap[typeof(bool)] = SqlDbType.Bit; typeMap[typeof(DateTime)] = SqlDbType.DateTime2; typeMap[typeof(DateTimeOffset)] = SqlDbType.DateTimeOffset; typeMap[typeof(decimal)] = SqlDbType.Money; typeMap[typeof(float)] = SqlDbType.Real; typeMap[typeof(double)] = SqlDbType.Float; typeMap[typeof(TimeSpan)] = SqlDbType.Time; /* ... and so on ... */ } // Non-generic argument-based method public static SqlDbType GetDbType(Type giveType) { if (typeMap.ContainsKey(giveType)) { return typeMap[giveType]; } throw new ArgumentException($"{giveType.FullName} is not a supported .NET class"); } // Generic version public static SqlDbType GetDbType<T>() { return GetDbType(typeof(T)); } }

Caveat

The above code works fine in most cases, but comes with some problems:

  • How do you pick the correct SqlDbType value for strings? It depends on how you are using/storing that string in the database and in your application's business logic. The alternatives are:
    • Char: Fixed-length non-Unicode string of no more than 8 000 characters
    • NChar: Fixed-length Unicode string of no more than 8 000 characters
    • VarChar: Variable-length non-Unicode string of no more than 8 000 characters
    • NVarChar: Variable-length Unicode string of no more than 8 000 characters
    • Text: Non-Unicode stream of no more than 2 147 483 647 characters
    • NText: Unicode stream of no more than 1 073 741 823 characters
    • Xml: SQL Server native XML data type
  • How do you pick the correct value for blobs? There are a few alternatives there too:
    • Binary: Fixed-length stream of no more than 8 000 bytes
    • VarBinary: Variable-length stream of no more than 8 000 bytes
    • Image: Variable-length stream of no more than 2 147 483 647 bytes
  • Also for dates or timestamps there are a few different ways to go:
    • Binary: Fixed-length stream of no more than 8 000 bytes

The best thing would almost always be to let some ORM tool do the heavy lifting.

Finding the right namespace

StackOverflow user graham added a reference to a third-party DLL called ServiceProvider.dll, but couldn't figure out which using directive to use to access the types made available in that DLL.

Most times, the DLL is named after the default namespace, which would suggest that a simple using ServiceProvider; should help, but that didn't work. When using closed-source SDKs that you purchase licenses for from some company, it is pretty common to find that their namespaces are named after the company itself. In this case, the root of the namespace hierarchy was Avaya, after the company.

Object Browser screenshotObject Browser When you double-click the reference in the Solution Explorer, the Object Browser opens up with the double-clicked referenced assembly pre-selected. All you have to do then is to expand the selected row to see all namespaces included in the dll file.

JavaScript countdown using localStorage

New StackOverflow user Pankaj Badera asked how to create a simple JavaScript timer that would survive reboots of the user's computer.

For the specific question, this is not a good idea, because it seems as if the problem needs to deal with some sort of timing rules (school assignment deadlines, maybe?), in which case a server-side solution is a must. However, the technical aspects is pretty intriguing. As it turns out, I have already faced this problem before, when building Tajmkiper, which handles all of its timing client-side.

In principal, you can start any type of countdown, or "countup", allowing the counter to continue between browser and computer restarts, by simply recording the current time for when an event starts, and then continuously checking the difference between that saved value and the current time of a later event.

In Tajmkiper, this is done for many projects at the same time, but the principle is the same. In the case of this StackOverflow question, there is only one timer. Also, Tajmkiper is meant to be a tool for the user, and not for keeping track of (from the browser's perspective) externally checked rules like deadlines, so a solution involving local storage is fine.

My answer looks like this:

(function() { var started = localStorage['started']; if (started) { // This is not the first time the user opens this file // How long has it been? var diff = Date.now() - started; if (diff >= 1000 * 60 * 60 * 24 * 7) { // At least one week has passed. Do something here. } else { // Less than a week has passed. Do something else here. } } else { // This is the first time the user opens this file localStorage['started'] = Date.now(); // Do something else here to welcome the user... } })();

For my project time clock, this happens every time you select a different project. I combine this with keeping track of how much time has been clocked total.

Formatting a truncated float in JavaScript

StackOverflow user nips asked how to format a floating point number in JavaScript, truncating the value instead of rounding it.

According to the question, this was the desired result:

  • The value 12.999 must be displayed as 12.99
  • The value 14 must be displayed as 14.00

The developer.mozilla.org page gives a thorough example of how to perform decimal rounding correctly, avoiding any rounding errors in the process. For this question, however, a simple multiplication-division pair is surely good enough:

// Step by step var multiplied = value * 100; var truncated = Math.floor(multiplied); var divided = truncated * 0.01; var output = divided.toFixed(2); // One-liner version var output = (Math.floor(value * 100) * 0.01).toFixed(2);

The above code performs the following steps, in order:

  • Value is multiplied by 100
    12.999 => 1299.9
    14 => 1400
  • Value is truncated using the Math.floor function
    1299.9 => 1299
    1400 => 1400
  • Value is multiplied by 0.01
    1299 => 12.99
    1400 => 14
  • Value is formatted for printing using two decimal places using the Number.prototype.toFixed function
    12.99 => "12.99"
    14 => "14.00"

Most languages do have functions called round, ceil, floor or similar ones, but almost all of them round to the nearest integer, so the multiply-round-divide chain (or divide-round-multiply for rounding to tens, hundreds, thousands...) is a good pattern to know.

In JavaScript there is no float datatype like in a lot of other languages, but the Number object is used for both integers and floating point numbers. Internally, numbers are just 64 bit floating point numbers (source: ecma262-6.com), conforming to the IEEE 754 standard. So when dealing with numbers in JavaScript, you always need to take floating point precision into consideration!