JavaScript Snippet – Convert HTML Table To 2D Array

A few days ago I was working on manipulating data that I found in Wikipedia. The data was in a table where the colspans and rowspans were making it difficult to simply programmatically pull data. Then I started looking into code to turn HTML table to JSON but for some reason the rowspans were still causing issues. Finally, I decided to just write a quick and dirty function to get the job done:

The cool thing about this function is that in the case of cells that span multiple columns and/or rows the value in that cell will be written to each corresponding sub-array value.

JavaScript Snippet – isValidVarName()

Now Available in YourJS

Recently I was working on a function which needed to determine whether or not a string could be used as a variable name. Variable name validation can get tricky so instead of using a crazy regular expression which includes all keywords (which may change over time) and instead of testing for strange unicode characters which are rarely used for variable names, I decided to leverage the JavaScript Function constructor:

The above function takes the string in question and returns true if the string can be used a variable name. If the string can not be used as a variable name false is returned.

Some may wonder why I’m doing the following:

varName.replace(/[\s\xA0,\/]|^$/g, '.')

The reason I included the above replacement is to avoid false-positives in the case of an empty string, extra spacing, commas, and forward slashes.

Security

Others have attempted to make the same function using the evil eval() function which allows for JS injection. Even though the Function constructor can also be used for evil, when supplying arguments it does prevent you from doing JS injection by making sure the arguments don’t have parentheses.

Examples

The following is an example of what will happen when running for the function for a number of strings:

console.log(isValidVarName(''));           // -> false
console.log(isValidVarName('3'));           // -> false
console.log(isValidVarName('3d'));          // -> false
console.log(isValidVarName('D3'));          // -> true
console.log(isValidVarName('D3 '));         // -> false
console.log(isValidVarName('D3,Q'));        // -> false
console.log(isValidVarName('D3/*Qs*/'));   // -> false
console.log(isValidVarName('D3Q'));         // -> true
console.log(isValidVarName('var'));         // -> false
console.log(isValidVarName('true'));        // -> false
console.log(isValidVarName('undefined'));   // -> true
console.log(isValidVarName('null'));        // -> false
console.log(isValidVarName('coolio.pop'));  // -> false
console.log(isValidVarName('coolio'));      // -> true
console.log(isValidVarName('coolio_pop'));  // -> true
console.log(isValidVarName('$'));           // -> true
console.log(isValidVarName('$á'));          // -> true
console.log(isValidVarName('áÑ'));          // -> true
console.log(isValidVarName('_'));           // -> true

Here is a similar example hosted on JSBin:
JS Bin on jsbin.com

Installing Watchtower Library on Mac with Wine

Instead of always switching to your PC or using a VM just to use the Watchtower Library you can use Wine. Here is how you can do it:

  1. Go to the WineBottler home page and download WineBottler (which comes with Wine).
  2. Open the image file (the DMG file that you downloaded) and drag-and-drop both Wine and WineBottler into the Applications directory.
  3. Insert the Watchtower Library DVD.
  4. Open the Wine application from the Applications menu.
  5. In the menu bar at the top of the screen, select the Wine icon (Wine.app Icon) to pull down the menu and then select the File Manager. This will setup your prefix which is a fancy way of saying the file structure for your mini virtual machine. Once done, click OK to see the File Manager.

  6. In the Wine File Manager you will need to click on the / (Root Directory Button) button to open a panel for accessing your local file system.
  7. Go into the Volumes directory and then into the directory with the name of your Watchtower Library DVD (eg. WTLIB15S).
    Wine File Manager
  8. Double-click the Setup.exe file.
  9. Click through the steps to install the Watchtower Library in the default location (normally C:\Program Files\Watchtower).
    Installation
  10. Once the install is complete, download this ZIP file.
  11. Double-click the downloaded ZIP file to extract the contained Watchtower Library app starter.
  12. Drag-and-drop the extracted Watchtower Library app into the Applications directory.
  13. Open this Watchtower Library app which is designed to work with the Watchtower Library program that you installed using Wine.
    Start Screen

Hopefully you will now be able to use the Watchtower Library with ease on your Mac. If you have an issue while trying to execute one or more of these steps please let me know. Have fun! :cool:

JavaScript – Detecting Infinite Loops

When allowing a user to input code that could potentially cause an infinite loop, it is nice to test the code first, right? Even, if the code doesn’t run infinitely, it would be nice to know if it takes longer than you would want. One way to nicely test for infinite loops or long running code is by using web workers. The following is a function which uses eval() in a web worker to execute the code and adds a timeout so that if the code takes too long to run, the web worker will be terminated:

Now let’s say that the user inputs the following loop in your textbox which has an ID of txtCode:

for (var i = 0; i != 10; i++) {
  if (i % 2 == 0) {
    i *= 2;
  }
}

Unfortunately, the above loop will run infinitely because i will progress as shown below:

0
1
4
5
12
13
14
29
30
61
62
125
126
253
254
509
510
1021
...

If you don’t believe me you can try the following code in the console :wink: :

// Let's stop the loop once we get to or above 1000
for (var i = 0; console.log(i + ' != 10'), i != 10 && i < 1000; i++) {
  if (i % 2 == 0) {
    i *= 2;
  }
}

The good thing about web workers is that any code that runs in them will not interfere with your JS in the main process but the downside is that you cant innately determine if a web worker is still running after a specified amount of time (well not as easily as you might hope). Fortunately, with the limitEval() function we find a way around this issue by sending and receiving messages. Feel free to check out how I accomplish this by analyzing the code.

Now let's setup a way to determine if the user's input, found in txtCode, takes more than 3 seconds to run:

var code = document.getElementById('txtCode').value;
limitEval(code, function(success, returnValue) {
  if (success) {
    // do whatever you want with the return value (returnValue)
  }
  else {
    alert('The code takes too long to run.  Is there is an infinite loop?');
  }
}, 3000);

So, if the code takes more than 3 seconds to run an alert will be shown after 3 seconds and the eval will be terminated.

As you can see limitEval takes two required parameters and one optional one:

  1. code {string}:
    The JS code to be eval'd.
  2. fnOnStop {Function}:
    The function which will be called either after the eval completes or after the timeout occurs. The following are the arguments that will be passed:

    1. success {boolean}:
      true will be passed if the eval executed successfully before the timeout. Otherwise false will be passed.
    2. opt_returnValue {*}:
      If the eval executes successfully this will be the return value. If the timeout occurs this will not be passed and arguments.length will be 1.
  3. opt_timeoutInMS {number}:
    Optional. Defaults to 1000. The number of milliseconds before timing out.

It is important to note that this solution, although very useful, only works on newer browsers. According to MDN, it will work in the following browsers and higher:

  • Chrome 23
  • Firefox (Gecko) 21
  • Internet Explorer 11
  • Safari (WebKit) 7

Hopefully you find the limitEval() function useful. Have fun! :cool:

JavaScript Snippet – Recurse A Directory Synchronously

Recently I took a look at making HTML5 programs that will work on Mac, Linux and Windows via Electron and needed a way to recurse a directory synchronously in Node.js. I ended up with the following code:

The above function allows us to recursively get the contents of a directory. It also provides the ability to filter out files and sub-directories. The following is an example of using it to simply get all files and directories within a specified directory:

var dir = recurseDirSync('/Users/jsmith/Movies');

/*****
// Example directory structure:
{
  isFile: false,
  path: '/Users/jsmith/Movies/',
  stat: ,
  files: [
    {
      isFile: true,
      path: '/Users/jsmith/Movies/Scrooge McDuck.mp4',
      stat: ,
    },
    {
      isFile: false,
      path: '/Users/jsmith/Movies/The Other Movies/',
      stat: ,
      files: [...]
    },
    ...
  ]
}
*****/

As you can see, get the files and sub-directories of a directory is very easy. You can also easily filter with this function. Let’s say we want to only include directories and MP4s:

recurseDirSync('/Users/jsmith/Movies', function(path, isFile, stat) {
  return !isFile || /\.mp4$/i.test(path);
});

Once again, using this helper function makes something that could’ve been complex a lot easier. Feel free to use and even modify this function. :cool:

PHP Snippet – array_splice_assoc(…)

Recently I was working on something that required inserting key-value pairs into an array after a specific key in PHP. As I was looking through stackoverflow answers I realized that there was no awesome answer that really jumped out at me. Therefore I decided to take a few minutes to just write my own array_splice_assoc() function to get the job done:

As you can see this function takes the same parameters that array_splice() does but the difference is that the offset can be a string in this key which refers to the key after which the new array elements should be inserted.

One important thing to note is that if you try to insert a key-value pair in which the key exists before or at the offset, your key-value pair will not be inserted. On the other hand if you try to insert a key-value pair in which the key exists after offset, your value will replace the previous one.

Have fun! :cool:

Game – Bible Book Master

Yesterday I really wanted to make a multi-lingual so I decided to make a game in which you have to go through all of the books of the Bible as fast as you can. I still need to do some work on the game to make it more user-friendly, but the following (which can also be accessed here) is what I came up with:

As of when I wrote this post the game supported 9 languages including English, Spanish, Vietnamese, Korean, and Haitian Creole. I chose the languages based on those in which I could find the names of all 66 Bible books. In fact, in all cases except for Vietnamese I used the Online Watchtower Library on jw.org in order to get the bible book names, using this JavaScript code in the web console:

$('.book .name').map(function() {
  return $(this).text();
});

As far as translating the rest of the words in the game, since I kept the amount of text to a minimum I simply used good ol’ Google Translate.

Since I wrote the server-side in PHP I ended up using $_SERVER['HTTP_ACCEPT_LANGUAGE'] to auto-detect the language if it wasn’t set:

$lang_code = valueOf($_REQUEST['lang'], preg_replace("/\W.*/", "", $_SERVER['HTTP_ACCEPT_LANGUAGE']));

Finally, I spent way more time than I wanted to on the rounded CSS3 buttons:

.round-button {
  font-size: 64px;
  line-height: 3em;
  height: 3em;
  width: 3em;
  border-radius: 3em;
  background: #000;
  color: #FFF;
  display: inline-block;
  text-align: center;
  font-family: fontello;
  transition: 0.5s cubic-bezier(0.5,0.5,0.5,0.5) all;
  cursor: pointer;
  box-shadow: 0 0 0.25em #000;
  z-index: 1;
  position: relative;
  border: 0.05em solid #000;
  padding: 0.45em;
  margin: 0.5em;
  box-shadow: 0 0 1em 0.5em rgba(0,0,0,0.5) inset, 0 0 0 #000;

  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -o-user-select: none;
  user-select: none;
}
.round-button .text {
  font-size: 0;
  position: absolute;
  line-height: 1em;
  margin-top: -2em;
  display: block;
  width: 6em;
  text-align: center;
  text-shadow: 0 0 3px #FFF, 0 0 3px #FFF, 0 0 3px #FFF, 0 0 3px #FFF, 0 0 3px #FFF;
  transition: 0.5s ease all;
}
.round-button:hover {
  box-shadow: 0 0 0 0 #000 inset, 0 0 0.125em 0.125em #FFF, 0 0 0.0625em 0.25em rgba(0,0,0,0.5);
  background: #FFF!important;
  z-index: 2;
  transform: rotate(360deg);
  -webkit-transform: rotate(360deg);
  color: #000;
  padding: 0;
  border-width: 0.5em;
}
.round-button:hover .text {
  font-size: 0.5em;
  text-shadow: 0 0 3px #FFF, 0 0 3px #FFF, 0 0 3px #FFF, 0 0 3px #FFF, 0 0 3px #FFF;
}
.round-button:active {
  box-shadow: 0 0 1em 0.1em #777 inset, 0 0 0.125em 0.125em #FFF, 0 0 0.0625em 0.25em rgba(0,0,0,0.5);
  transition: 0.1s ease box-shadow;
}

As you will see in the game, each rounded button is actually individually colored. For example, the following is for the facebook button:

.round-button.facebook {
  background: #3b5998;
  border-color: #3b5998;
}
.round-button.facebook:hover {
  color: #3b5998;
}

All-in-all I am happy with how this game turned out but I would like to add a few improvements. Try the Bible Book Master game out yourself and let me know what you think. :cool:

Game – Where’s the Nose that Knows?

I noticed that lately there has been interest in finding a panda in a large array of snowmen in this post. There was also this post where you have to find a cat amidst a great deal of owls. I started thinking about how I could make a similar game that is randomly generated. I ended up with the following HTML5 version in which you have to either find the one face with a nose or the one face without a nose:

Here is a link to the actual page. Let me know what you think! :cool:

PHP – Re-indexing 2D Array By A Specific Key

Today I was working on a personal project and wanted to be able to use a native PHP function to re-index a 2D array so that the key for each sub-array was pulled from a value in that sub-array. Unfortunately I wasn’t able to find a way to simply do it natively although it may exist. Therefore I wrote this array_by_column() function:

To use it you can simply supply the 2D array as the first argument and the key (or column name) as the second parameter.

365.2425 Days in a Year?

I was looking through some of the posts on Google+ and noticed that one of Douglas Crockford’s posts alluded to the fact that there are 365.2425 days on average in a year. At first I thought that the number should’ve actually been 365.25 due to us seeing a leap year every 4 years, but then I remembered that leap years don’t always happen every 4 years.

The rule is that a leap year will be a year evenly divisible by 4 and if it is evenly divisible 100 it must also be evenly divisible by 400. Therefore 1896 was a leap year, but the next leap year wasn’t observed until 1904.

Keeping all of this in mind, let’s see if we come to the same conclusion that there are 365.2425 days in a year on average. First, let’s determine how many days are in the typical 4 year period:
365 days × 4 + 1 leap day = 1,461 days

Now let’s determine how many days there actually are in a 400 year time span. Since we already have a rough calculation for 4 years, we can multiply that by 100 and then account for the 3 times the 3 leap days that wouldn’t occur because even though the year would be divisible by 4 and 100 it wouldn’t be divisible by 400:
1,461 days × 100 - 3 leap days = 146,097 days

Now let’s simply divide the number of days in a 400 year time span by 400 to get the average amount of days in a year:
146,097 ÷ 400 = 365.2425

So now you know why it is said that on average a year is 365.2425 days long. :cool:

JavaScript, Math, and much more.