<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Thomas Stiegler</title>
<subtitle></subtitle>
<link href="http://thomasstiegler.com/feed" rel="self" />
<id>http://thomasstiegler.com/feed</id>
<updated>2017-01-15T16:56:53-05:00</updated>
<entry>
<title type="html">Declarative Web Crawling and Data Extraction</title>
<content type="html">&lt;p&gt;
    A few little projects I&#039;ve been working on had involved ripping information from sites with multiple pages into a database or JSON file. I&#039;ve done this kind of stuff before and it usually ended up in the same kind of code, something that iterates over a queue of URLs, pulls the data down and parses it into a data structure and sends it off to where it needs to go.
&lt;/p&gt;
&lt;p&gt;
    I made a little script for managing all of the logic common to scraping information from websites, intended to be reused over different projects whenever I needed it. In the process of doing that I got to learn some new stuff like publishing an npm package to &lt;a href=&quot;http://npmjs.com&quot;&gt;npmjs&lt;/a&gt; and doing automated testing on git commit with &lt;a href=&quot;http://travis-ci.org&quot;&gt;TravisCI&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
    So the package I&#039;ve made for this is &lt;a href=&quot;https://github.com/tstiegler/httprip&quot;&gt;httprip&lt;/a&gt;. The module exposes a factory method for creating a ripper instance. The instance allows you to attach implementations for &quot;processing&quot; and &quot;yielding&quot;. Processor implementations allow you to define the parsing and extraction of html into the elements of data you want. These elements are to be &quot;yielded&quot; to the data collectors of the ripper instance. Multiple processors and data collectors can be specified. Check out the most basic example of usage below.
&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var httprip = require(&quot;httprip&quot;);

var ripper = httprip()
    .processor(function(error, res, body, resolve) {
        // Perform parsing on body here.

        // Yield each item parse from body.
        ripper.yield(&quot;item&quot; + Math.floor(Math.random() * 999));
        ripper.yield(&quot;item&quot; + Math.floor(Math.random() * 999));

        // Resolve after we&#039;ve finished processing.
        resolve();
    })
    .data(function(output) {
        console.log(&quot;Retrieved item:&quot;, output);
    });


// Queue requests.
ripper.enqueueRip({url: &quot;http://google.com&quot;});
ripper.enqueueRip({url: &quot;http://yahoo.com&quot;});
ripper.enqueueRip({url: &quot;http://bing.com&quot;});

// Wait for finish.
ripper.lastQueued().then(function() {
    console.log(&quot;done&quot;);
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    So as you can see, this queues up three URLs to be ripped. The processor function disregards the output however and yields 2 random items for each request. The data collector method simply console logs the items. Also, a method is attached to the Promise of the last queued element so that some logic can be performed after all queued entries have been completed. There is a more detailed documentation over at the readme for the &lt;a href=&quot;https://github.com/tstiegler/httprip&quot;&gt;httprip&lt;/a&gt; project.
&lt;/p&gt;
&lt;h2&gt;Creating NPM packages is easy&lt;/h2&gt;
&lt;p&gt;
    I was kind of expecting this whole process to be a lot more involved and complicated than it actually was. but it was seriously as easy as this:
&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;Create an account at &lt;a href=&quot;http://npmjs.com&quot;&gt;npmjs.copm&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;Open up a command prompt and navigate to your code&#039;s folder&lt;/li&gt;
        &lt;li&gt;Run &lt;code&gt;npm init&lt;/code&gt; and follow the prompts&lt;/li&gt;
        &lt;li&gt;Run &lt;code&gt;npm login&lt;/code&gt; and enter your username and password&lt;/li&gt;
        &lt;li&gt;Run &lt;code&gt;npm publish&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;p&gt;
    I mean really, that was it. Every time you want to update your package, just increment your version number in &lt;code&gt;package.json&lt;/code&gt; and run &lt;code&gt;npm publish&lt;/code&gt; again. NPM publish will automatically ignore anything in &lt;code&gt;.gitignore&lt;/code&gt; so don&#039;t worry about all the bloat you might have in your package, it wont get pushed to npm.
&lt;/p&gt;
&lt;h2&gt;Automated testing with TravisCI is easy too&lt;/h2&gt;
&lt;p&gt;
    I mean I only really did this to get that little &quot;passing&quot; badge on the github page, but it was pretty interesting to see how easy Travis is to set up. By connecting travis to a github account, it will already see all available projects. Setting it up for NodeJS is as simple as committing in a &lt;code&gt;.tavis.yml&lt;/code&gt; file and activating the repository in Travis.
&lt;/p&gt;
&lt;p&gt;
    The &lt;code&gt;.travis.yml&lt;/code&gt; file is just a config YAML file, which is how you let Travis know that you are testing a NodeJS project as well as other things like what Node version to use for testing.
&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;language: node_js
node_js:
  - &quot;6&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    Not a hell of a lot. By default, Travis will run &lt;code&gt;npm test&lt;/code&gt;, meaning your &lt;code&gt;package.json&lt;/code&gt; file needs to have a test script. &lt;code&gt;httprip&lt;/code&gt; just uses mocha, nothing special. Once Travis detects a push to github, it will grab the latest code and run the tests. Travis gives you a cool image link to get that &quot;build passing&quot; badge, provided your builds are passing.
&lt;/p&gt;</content>
<link href="http://thomasstiegler.com/post/declarative-web-crawling-and-data-extraction/" />
<id>http://thomasstiegler.com/post/declarative-web-crawling-and-data-extraction/</id>
<updated>2017-01-15T16:56:53-05:00</updated>
<category term="Uncategorised"/>
</entry>
<entry>
<title type="html">Integer Indexable Spiral Algorithm</title>
<content type="html">&lt;p&gt;This is a little algorithm I wrote for generating multiple coordinates in a pseudo-spiral fashion using a single incrementing integer index. This function, given a single integer index, will generate an X and Y coordinate that represents a position on a two-dimensional graph, moving around in a spiral as the given index increments. This might sound a little confusing at first, but consider the diagram below. The cell values represent the index given to the function and shows the resulting X and Y coordinates.&lt;/p&gt;
&lt;p&gt;
    &lt;div class=&quot;row&quot;&gt;
        &lt;div class=&quot;col sm12 m8 push-m2 l4 push-l4&quot;&gt;
            &lt;table class=&quot;bordered striped&quot;&gt;
                &lt;tr&gt;
                    &lt;th width=&quot;20&quot;&gt;&lt;/th&gt;
                    &lt;th width=&quot;20&quot;&gt;-3&lt;/th&gt;
                    &lt;th width=&quot;20&quot;&gt;-2&lt;/th&gt;
                    &lt;th width=&quot;20&quot;&gt;-1&lt;/th&gt;
                    &lt;th width=&quot;20&quot;&gt;0&lt;/th&gt;
                    &lt;th width=&quot;20&quot;&gt;1&lt;/th&gt;
                    &lt;th width=&quot;20&quot;&gt;2&lt;/th&gt;
                    &lt;th width=&quot;20&quot;&gt;3&lt;/th&gt;
                &lt;/tr&gt;
                
                &lt;tr&gt;
                    &lt;th&gt;3&lt;/th&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                &lt;/tr&gt;
        
                &lt;tr&gt;
                    &lt;th&gt;2&lt;/th&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;24&lt;/td&gt;
                    &lt;td&gt;9&lt;/td&gt;
                    &lt;td&gt;10&lt;/td&gt;
                    &lt;td&gt;11&lt;/td&gt;
                    &lt;td&gt;12&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                &lt;/tr&gt;    
                
                &lt;tr&gt;
                    &lt;th&gt;1&lt;/th&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;23&lt;/td&gt;
                    &lt;td&gt;8&lt;/td&gt;
                    &lt;td&gt;1&lt;/td&gt;
                    &lt;td&gt;2&lt;/td&gt;
                    &lt;td&gt;13&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                &lt;/tr&gt; 
        		
        		&lt;tr&gt;
                    &lt;th&gt;0&lt;/th&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;22&lt;/td&gt;
                    &lt;td&gt;7&lt;/td&gt;
                    &lt;td&gt;0&lt;/td&gt;
                    &lt;td&gt;3&lt;/td&gt;
                    &lt;td&gt;14&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                &lt;/tr&gt;  
        
        		&lt;tr&gt;
                    &lt;th&gt;-1&lt;/th&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;21&lt;/td&gt;
                    &lt;td&gt;6&lt;/td&gt;
                    &lt;td&gt;5&lt;/td&gt;
                    &lt;td&gt;4&lt;/td&gt;
                    &lt;td&gt;15&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                &lt;/tr&gt;   
        		
        		&lt;tr&gt;
                    &lt;th&gt;-2&lt;/th&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;20&lt;/td&gt;
                    &lt;td&gt;19&lt;/td&gt;
                    &lt;td&gt;18&lt;/td&gt;
                    &lt;td&gt;17&lt;/td&gt;
                    &lt;td&gt;16&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                &lt;/tr&gt;   
        		
        		&lt;tr&gt;
                    &lt;th&gt;-3&lt;/th&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;/td&gt;
                &lt;/tr&gt;   
            &lt;/table&gt;  
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;
    As you can see the following indexes match with the given coordinates.
&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;0 -&gt; {x: 0, y: 0}&lt;/li&gt;
    &lt;li&gt;1 -&gt; {x: 0, y: 1}&lt;/li&gt;
    &lt;li&gt;2 -&gt; {x: 1, y: 1}&lt;/li&gt;
    &lt;li&gt;3 -&gt; {x: 1, y: 0}&lt;/li&gt;
    &lt;li&gt;4 -&gt; {x: 1, y: -1}&lt;/li&gt;
    &lt;li&gt;5 -&gt; {x: 0, y: -1}&lt;/li&gt;
    &lt;li&gt;6 -&gt; {x: -1, y: -1}&lt;/li&gt;
    &lt;li&gt;7 -&gt; {x: -1, y: 0}&lt;/li&gt;
    &lt;li&gt;8 -&gt; {x: -1, y: 1}&lt;/li&gt;
    &lt;li&gt;9 -&gt; {x: -1, y: 2}&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;/**
 * Convert spiral location idex to x/y coordinates.
 * 
 * @param {number} idx  Spiral location index.
 * @param {coordinates} origin X/Y origin to start spiral at.
 * 
 * @returns {coordinates} Spiral location coordinates.
 */
function spiralIndexToCoord(idx, origin) {
    origin = origin || {x: 0, y: 0};

    var swSteps = 1;
    var offset = {
        x: 0,
        y: 0
    };

    while(idx &gt; 0) {
        // Calculate number of steps to navigate southwest 1 block.
        var stepsEndpoint = swSteps + 1;
        var movements = ((stepsEndpoint - 1) * 2) + stepsEndpoint * 2;        

        // If we have more indexes left to cover the southwest movement,
        // move the offset.
        if(movements &amp;lt;= idx) {
            idx -= movements;
            
            offset.x--;
            offset.y--;
        } else {        
            // If not, then we need to move it manually to hit the destination.
            // For the given directions N to W, 0 to 3, list out the amount of steps needed.
            var direction = 0;
            var stepArr = [
                swSteps,
                swSteps,
                swSteps + 1,
                swSteps + 1
            ];
            
            // Loop for the remainder of idx.
            while(idx &gt; 0) {
                // Decrement the direction step.
                stepArr[direction]--;

                // Move in the given direction.
                if(direction == 0) { offset.y++; }
                if(direction == 1) { offset.x++; } 
                if(direction == 2) { offset.y--; }
                if(direction == 3) { offset.x--; }

                // Move to next direction if this directions steps have run out.
                if(stepArr[direction] == 0)
                    direction++;

                idx--;
            }
        }

        // Move to next sw count for next iteration.
        swSteps += 2;
    }

    return {
        x: origin.x + offset.x,
        y: origin.y + offset.y
    };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Origin parameter&lt;/h2&gt;
&lt;p&gt;
    By default, the 0th index of the spiral will start at (0, 0). However you manually set the origin of the spiral through the origin parameter.
&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;spiralIndexToCoord(0, {x: 5, y: 12});&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Performance Issues&lt;/h2&gt;
&lt;p&gt;
    Due to the nature of the algorithm, higher indexes take longer time to calculate than lower indexes. I have tested the performance hit for generating the first million indexes as well as &lt;code&gt;Number.MAX_SAFE_INTEGER&lt;/code&gt; (Which in NodeJS is 9,007,199,254,740,991).
&lt;/p&gt;
&lt;p&gt;
    The testing script implementation and result is as follows:
&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Show the first ten indexes.
for(var i = 0; i &lt; 10; i++) {
    console.log(&quot;Index &quot; + i + &quot;:&quot;, spiralIndexToCoord(i, {x: 0, y: 0}))
}

// Measure time taken for 1 million iterations of spiral index to coordinate conversions.
console.time(&quot;First million indexes&quot;);
for(var i = 0; i &lt; 1000000; i++) {
    var coords = spiralIndexToCoord(i, {x: 0, y: 0});
}
console.timeEnd(&quot;First million indexes&quot;);

// Measure time taken for a large index.
console.time(&quot;MAX_SAFE_INTEGER&quot;);
console.log(&quot;Index &quot; + Number.MAX_SAFE_INTEGER + &quot;:&quot;, spiralIndexToCoord(Number.MAX_SAFE_INTEGER, {x: 0, y: 0}));
console.timeEnd(&quot;MAX_SAFE_INTEGER&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;Index 0: { x: 0, y: 0 }
Index 1: { x: 0, y: 1 }
Index 2: { x: 1, y: 1 }
Index 3: { x: 1, y: 0 }
Index 4: { x: 1, y: -1 }
Index 5: { x: 0, y: -1 }
Index 6: { x: -1, y: -1 }
Index 7: { x: -1, y: 0 }
Index 8: { x: -1, y: 1 }
Index 9: { x: -1, y: 2 }
First million indexes: 6925ms
Index 9007199254740991: { x: 47453133, y: 23868632 }
MAX_SAFE_INTEGER: 1886ms
&lt;/code&gt;&lt;/pre&gt;</content>
<link href="http://thomasstiegler.com/post/integer-indexable-spiral-algorithm/" />
<id>http://thomasstiegler.com/post/integer-indexable-spiral-algorithm/</id>
<updated>2017-01-10T15:01:11-05:00</updated>
<category term="Uncategorised"/>
</entry>
<entry>
<title type="html">FastPokeMap API scraping - Spawn notifications by Email</title>
<content type="html">&lt;p&gt;&lt;strong&gt;(Edit: FPM has long since been dead, was awesome while it worked!)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Skip to the next section if you want to get straight to the good stuff. This is just backstory.&lt;/p&gt;
&lt;p&gt;Anyone who knows me, knows that I am massively into Pokemon GO. I was into Pokemon as a kid during the late 90s when the gameboy games and trading cards were huge. If you&#039;re reading this and don&#039;t understand the new mobile game, you might want to read up on it otherwise the below might not make too much sense.&lt;/p&gt;
&lt;p&gt;Back when Pokemon GO came out, there was a cool feature that let you &quot;track&quot; pokemon. A portion of the UI would show you how far away you were from the nearby pokemon, letting you track the rare pokemon that you don&#039;t have yet. This was later removed before I could get the chance to really use it. There is a lot of speculation as to why Niantic removed it. Some say it was to lessen server load, some say they wanted to implement something different. I don&#039;t know.&lt;/p&gt;
&lt;p&gt;The removal of this feature sparked a bit of innovation in the community, and some people have made really cool web apps that made use of the Pokemon go backend API to discover pokemon spawns at any given location, essentially letting people see what pokemon were nearby and exactly where they were. This was (and still is) frowned upon and is actively being fought against by Niantic.&lt;/p&gt;
&lt;p&gt;I don&#039;t doubt the ethical grey area that using these apps is in. But given how much of an advantage anyone near the Santa Monica Pier has over anyone else, I almost feel like using these maps is just getting me up to speed with anyone who has the luck to be able to play over there.&lt;/p&gt;
&lt;p&gt;Anyway, I digress. The biggest and best map/scraper for Pokemon spawns out there (in my opinion) is FastPokeMap. I&#039;ve used it a few times and had the idea of writing an automated service that would make use of their API to fetch Pokemon spawns at your current location and send you emails when something rare is nearby.&lt;/p&gt;
&lt;h1&gt;Using the FastPokeMap API&lt;/h1&gt;
&lt;p&gt;Just using Chrome Developer Tools, I checked out what kind of ajax requests were being made to fetch data from the FPM servers. Straight away I could see a ton of requests to https://api.fastpokemap.se/, all with the same query parameters showing the latitude and longitude for the request as well as what I can only assume is a string for filtering responses to only contain specific pokemon.&lt;/p&gt;
&lt;p&gt;This struck me as weird at first as it was a lot of calls for the same data. However I could see the result of the call was a small bit of JSON representing an &quot;overload&quot; error. It seems that the FPM servers cant quite handle the traffic they&#039;re receiving. The web client just tries over and over with the server throwing back this JSON message until it finally works.&lt;/p&gt;
&lt;p&gt;I tried for a while to recreate this API call in Postman, but for some reason couldn&#039;t get it just right so I opted to use the Chrome Developer Tools to copy the ajax request as a CURL command. This is what I had used in my scraper script. A bit of a hacky workaround, but it works.&lt;/p&gt;
&lt;p&gt;
&lt;script src=&quot;https://gist.github.com/tstiegler/d0184c8809f1cbf4ec0a92c8f8a26337.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;As of late i&#039;ve been writing code for small little projects in NodeJS since it&#039;s so simple to get small little proof of concepts up and running really quickly. In a short while I had the API call up and running, letting you supply your own GPS coordinates to it and getting back spawn locations in the area.&lt;/p&gt;
&lt;h1&gt;Getting current GPS coordinates&lt;/h1&gt;
&lt;p&gt;So i wanted this thing to grab my phones current GPS coordinates and send them over to FPM&#039;s API to get the nearby spawns. Rather than rolling my own android app, I looked around for something that could do what I wanted already. I found an app called Self-Hosted GPS Tracker (&lt;a href=&quot;https://play.google.com/store/apps/details?id=fr.herverenault.selfhostedgpstracker&amp;hl=en&quot;&gt;Google Play Link&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;This was pretty cool, because it would let me use my own script, hosted wherever I wanted and it would just hit the URL with the latitude and longitude appended onto the end as query string parameters. So I wrote a quick PHP script that would dump the incoming GPS coordinates out as a JSON file that I could grab with the scraper script.&lt;/p&gt;
&lt;p&gt;
&lt;script src=&quot;https://gist.github.com/tstiegler/0f7f3b11325f2f604ea504852f78ca84.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The only thing left was emails, which was pretty easy with the nodemailer package.&lt;/p&gt;
&lt;h1&gt;Wrapping things up&lt;/h1&gt;
&lt;p&gt;This was only really the beginning of what I wanted to do, the final version of the script sends all spawns that it finds to an external script, which saves the data into an SQL database so I could do some research on it later (which I plan to write about very soon).&lt;/p&gt;
&lt;p&gt;At the moment, the script does the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Specify a range of Pokemon IDs to send email notifications for (excluding the rest).&lt;/li&gt;
&lt;li&gt;Specify a URL to get GPS data from for spawn scraping.&lt;/li&gt;
&lt;li&gt;Specify stationary GPS coordinates to scrape spawns from.&lt;/li&gt;
&lt;li&gt;Specify a URL to post all scraped spawns to.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Github Project&lt;/h1&gt;
&lt;p&gt;Below is a link to the Github repository for the project. All that&#039;s required to run it, is some changes in config.js, making sure CURL is accessible (via a path variable on windows, or just dropping the library in the folder) and an &quot;npm install&quot;. Then all you need to do is run:&lt;br /&gt;&lt;br /&gt;node main.js&lt;/p&gt;
&lt;div style=&#039;text-align: center&#039;&gt;&lt;div class=&quot;github-card&quot; data-user=&quot;tstiegler&quot; data-repo=&quot;fpm-scraper&quot;&gt;&lt;/div&gt;&lt;/div&gt;</content>
<link href="http://thomasstiegler.com/post/fastpokemap-api-scraping-spawn-notifications-by-email/" />
<id>http://thomasstiegler.com/post/fastpokemap-api-scraping-spawn-notifications-by-email/</id>
<updated>2016-09-18T22:37:35-04:00</updated>
<category term="Uncategorised"/>
</entry>
<entry>
<title type="html">Setting up AngularJS in Visual Studio 2013 with TypeScript</title>
<content type="html">&lt;p&gt;&lt;strong&gt;EDIT (18th September 2016):&lt;/strong&gt; The code samples for this post have ceased to exist. This post probably won&#039;t be helpful to anyone.&lt;strong&gt; &lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In this post I&#039;m going to show you the way that I&#039;ve come to develop AngularJS applications in Visual Studio in conjunction with TypeScript and ASP.NET MVC. When I searched around for how to do this, I wanted a way to have VS automatically stitch together all of the javascript without having to use something like RequireJS. Which as it turns out, is not hard to do. This meant having my TypeScript files all split out logically into different folders for controllers, directives, services and filters. As well as having one file per controller and etc (While not necessary, eases the part of me that likes to have a place for everything and have everything in its place).&lt;/p&gt;
&lt;p&gt;So first off, what you&#039;re going to need to do is create a new ASP.NET MVC project using the &quot;Basic&quot; template. Create a &lt;span style=&quot;font-family: monospace;&quot;&gt;HomeController &lt;/span&gt;and view for the Index method and make sure that all works nicely.&lt;/p&gt;
&lt;p&gt;Using NuGet, go ahead and grab the &lt;span style=&quot;font-family: monospace;&quot;&gt;AngularJS &lt;/span&gt; and &lt;span style=&quot;font-family: monospace;&quot;&gt;angularjs.TypeScript.DefinitelyTyped&lt;/span&gt; packages. This will dump a bunch of scripts into the Scripts folder, not all of which are necessary... I just tend to add them in whenever I need them. Add in the &lt;span style=&quot;font-family: monospace;&quot;&gt;AngularJS &lt;/span&gt;reference to &lt;span style=&quot;font-family: monospace;&quot;&gt;BundleConfig.cs&lt;/span&gt; as needed and get it included in &lt;span style=&quot;font-family: monospace;&quot;&gt;_Layout.html&lt;/span&gt;. Add the ng-app directive anywhere you want the AngularJS application to be scoped to. For me, I just use the root HTML tag.&lt;/p&gt;
&lt;p&gt;In your Scripts folder, create a new TypeScript file. Name it whatever you want, this will be where AngularJS gets initiated from. For this tutorial i&#039;ll be using the name &lt;span style=&quot;font-family: monospace;&quot;&gt;AngularDemo&lt;/span&gt;, so I&#039;ll be creating&lt;span style=&quot;font-family: monospace;&quot;&gt; AngularDemo.ts&lt;/span&gt;. You&#039;ll need to add in the reference comment to load in the AngularJS typings and then go about creating the Angular application instance.&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/tstiegler/aad46570f75ab8457c36.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;So at this point you really don&#039;t have much. Basic MVC, AngularJS being included and ... Well that&#039;s about it. This next step will get VS ready to stitch together all your TypeScript files so our entire application runs under a single JavaScript file despite having our TypeScript logically split up into different files.&lt;/p&gt;
&lt;p&gt;Go to your project properties page (Project &gt; &quot;ProjectName&quot; Properties...) and load up the &quot;TypeScript Build&quot; section. Under &quot;Output&quot;, check &quot;Combine JavaScript output into file&quot;, set the textbox to &quot;Scripts/AngularDemo.js&quot; (Or whatever you want... I&#039;m not picky) and hit Ctrl+S to save it.&lt;/p&gt;
&lt;p&gt;Obviously you wont see the effects of this so far since we only have the one TypeScript file, so lets add in a new TypeScript file for a basic controller. Like everything else, you can add these wherever you want, but I&#039;ll be using &quot;Scripts/ng/controllers/TestController.ts&quot;. Using the code below, I&#039;ve created a basic controller. The &lt;span style=&quot;font-family: monospace;&quot;&gt;$scope&lt;/span&gt; gets passed in as a &lt;span style=&quot;font-family: monospace;&quot;&gt;ITestControllerScope &lt;/span&gt;which extends &lt;span style=&quot;font-family: monospace;&quot;&gt;ng.IScope&lt;/span&gt;, this allows our scopes to be type safe and fully defined.&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/tstiegler/a0e1a7f561adea91dc2f.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;Now due to the TypeScript build settings we added previously, the &lt;span style=&quot;font-family: monospace;&quot;&gt;AngularDemo.js&lt;/span&gt; file now contains the JavaScript output for both the main TypeScript file as well as the controller we&#039;ve created. All of our TypeScript is being automatically concatenated into a single output file. Just add in some HTML to make use of the controller and now you can see everything coming to life in the browser.&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/tstiegler/0b211183b89c14cee836.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;That&#039;s really all there is to the actual setup of AngularJS in Visual Studio using TypeScript. This is really just scratching the surface of what is required to build full applications with these technologies. In the next post I&#039;ll be writing about AngularJS routing and serving templates for AngularJS to use via ASP.NET MVC.&lt;/p&gt;</content>
<link href="http://thomasstiegler.com/post/setting-up-angularjs-in-visual-studio-2013-with-typescript/" />
<id>http://thomasstiegler.com/post/setting-up-angularjs-in-visual-studio-2013-with-typescript/</id>
<updated>2016-01-29T18:30:54-05:00</updated>
<category term="Uncategorised"/>
</entry>
</feed>