Animate the navigation between pages with CSS3 and Angular 1.x

Just created a code pen to demonstrate the navigation between pages in Angular 1.x by using css3.
The animation should mimic scrolling the pages from top to bottom, now I could have just  used TypeScript,
to calculate the correct scroll position, but in this case I wanted to use pure CSS3.
I had some difficulties to create this animation, because my first reaction was, to try and use ng-if or 
ng-show / ng-hide, to hide the pages that are not visible. After hours of trying, I did not succeed, 
so I tried a different approach, by stacking the pages on top of each other and moving “previous pages” 
outside of the list at the top and moving next pages outside of the list at the bottom, without using 
ng-if or ng-hide.
Note:
- by using a translateX you could make the pages scroll from left to right instead of from bottom to top.
- by switching the values for translateY, you could make the pages scroll from top to bottom.
http://codepen.io/roelvanlisdonk/pen/YGZqgO/"
image

How to pass a function to an attribute directive, without using isolated scope or eval in Angular 1.x

I have created a little POC to demonstrate, how you can pass a function that resides on the scope, to be passed to a attribute directive without using isolated scope or eval in Angular 1.x.

The first button will be focused when the page is loaded.

When you tab on the first button, the default tab action is applied, so the second button is focused.

When you tab on the second button the function, that was passed to the “tab directive” is called. It will set a message on the scope. 

image

 

namespace poc {
'use strict';
const app = angular.module('poc', []);
class PocDirective implements ng.IDirective {
public link: ($scope: IPocScope, $element: ng.IAugmentedJQuery, attrs: ng.IAttributes) => void;
public restrict = 'E';
public template = `

<action-button>

            <button id="button-1" type="button">Tab on this button</button>

        </action-button>

        <action-button>

            <button poc-tab="{ fn: onTab }" type="button">Tab on this button</button>

        </action-button>

        <div ng-bind="message"></div>

`;
constructor(public $timeout:ng.ITimeoutService) {
const self: PocDirective = this;
self.link = self.unboundLink.bind(self);
}
unboundLink($scope: IPocScope, $element: ng.IAugmentedJQuery, attrs: ng.IAttributes) {
const self: PocDirective = this;
function onTab(){
$scope.message = "Tabbed on button";
}
self.$timeout(function() {
const button1 = document.getElementById('button-1');
button1.focus();
});
$scope.onTab = onTab;
}
}
interface IPocScope extends ng.IScope {
message: string;
onTab: () => void;
}
app.directive('poc', ['$timeout', ($timeout) => new PocDirective($timeout)]);
function safeApply($scope: ng.IScope): boolean {
var result = false;
var phase = $scope.$root.$$phase;
if (phase !== '$apply' && phase !== '$digest') {
$scope.$apply();
result = true;
}
return result;
}
/**
* We want to able to use this directive in association with other directives on the same element.
* So we don't use isolated scope, to prevent the error:
*      "Multiple directives [..., ...] asking for new/isolated scope on: ...".
* But we want to be able to pass a function to this directive from outside, 
* that's why we parse the value of the "poc-tab" attribute.
*/
class TabDirective implements ng.IDirective {
public link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ITabAttributes) => void;
public restrict = 'A';
constructor(public $parse: ng.IParseService) {
const self: TabDirective = this;
self.link = self.unboundLink.bind(self);
}
unboundLink(scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ITabAttributes) {
const self: TabDirective = this;
element.bind('keydown keypress', function (event) {
const tabKey = 9;
const tabIsPressed = (event.which === tabKey); 
if (tabIsPressed) {
const optionsAsString: string = attrs.pocTab;
const optionsAsExpression: ng.ICompiledExpression = self.$parse(optionsAsString);
const options: ITabOptions = optionsAsExpression(scope);
options.fn();
safeApply(scope);
event.preventDefault();
}
});
}
}
interface ITabAttributes extends ng.IAttributes {
pocTab: string;
}
export interface ITabOptions {
fn: () => void;
ignore?: boolean; // When true, given fn is NOT executed.
}
app.directive('pocTab', ['$parse', ($parse) => new TabDirective($parse)]);
angular.bootstrap(document, ['poc']);
}

Fixing: NPM / Node error on Windows: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.

I was using Visual Studio 2015 update 3 on Windows 10 x64 and was getting the error: “The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.”, when running some gulp tasks.

I fixed the problem by letting Visual Studio 2015 update 3 use the “current”(at the time of writing) node version (v6.5.0), that was  installed in “C:\Program Files\nodejs”.

Steps

  • Download the “current” (v6.5.0) Windows x64 version of node (NOT, I repeat, NOT the LTS version) at https://nodejs.org/en/
  • Install it
  • Open Visual Studio 2015 > Tools > Options… > Project and Solutions > External Web Tools > Add an entry “C:\Program Files\nodejs”
  • Move the entry to the top of the list and restart visual studio:

image

No the following steps might not be necessary, but in case the error persists:

  • Remove the node_modules folder
  • Open the solution and project (this will trigger an npm install)
  • Open the Package Manger Console
  • npm cache clean
  • npm dedupe
  • npm install

How to fix: ENOENT: no such file or directory, rename … \abbrev (angular cli)

When I was running “npm install -g angular-cli”, I was getting the following error:

npm ERR! npm  v3.10.3                                                 

npm ERR! path C:\Users\Roel\AppData\Roaming\npm\node_modules\.staging\a

bbrev-69492d5e                                                        

npm ERR! code ENOENT                                                  

npm ERR! errno -4058                                                  

npm ERR! syscall rename                                               

npm ERR! enoent ENOENT: no such file or directory, rename ‘C:\Users\Roe

l\AppData\Roaming\npm\node_modules\.staging\abbrev-69492d5e’ -> ‘C:\Use

rs\Roel\AppData\Roaming\npm\node_modules\angular-cli\node_modules\ember

-cli\node_modules\npm\node_modules\abbrev’                            

npm ERR! enoent ENOENT: no such file or directory, rename ‘C:\Users\Roe

l\AppData\Roaming\npm\node_modules\.staging\abbrev-69492d5e’ -> ‘C:\Use

rs\Roel\AppData\Roaming\npm\node_modules\angular-cli\node_modules\ember

-cli\node_modules\npm\node_modules\abbrev’                            

npm ERR! enoent This is most likely not a problem with npm itself     

npm ERR! enoent and is related to npm not being able to find a file.  

npm ERR! enoent

npm ERR! Please include the following file with any support request:  

npm ERR!     C:\dev\angular2\npm-debug.log                            

npm ERR! code 1

My environment consisted of:

  • windows 10 64 bit
  • node v6.4.0
  • npm v3.10.3

This problem was also solved by @davidrensh solution:

npm uninstall -g angular-cli

npm install -g angular-cli

From <https://github.com/angular/angular-cli/issues/1190>

How to create an IIS application pool and web site on Windows 10 with PowerShell and Visual Studio Code

Tasks to create an IIS application pool and web site on Windows 10 with PowerShell and Visual Studio Code:

  • Install the Visual Studio Code plugin PowerShell 0.6.2
  • Create a file iis.configuration.ps1 in Visual Studio Code:

    # Note: When run with the Visual Studio Code PowerShell debugger, make sure you use the "x64" debugger,
    #       else you will get an error: New-WebAppPool : Cannot retrieve the dynamic parameters for the cmdlet.

    Import-Module WebAdministration

    # Create application pools
    New-WebAppPool -Name "myapp.localhost" -Force

    # Create websites
    New-Website -Name "myapp.localhost" -Port 80 -HostHeader "myapp.localhost" -ApplicationPool "myapp.localhost" -PhysicalPath "c:\projects\myapp\web" -Force

        • Create a launch.json in the same folder as the iis.configuration.ps1:

          {
              "version": "0.2.0",
               "configurations": [
                  {
                      "name": "PowerShell",
                      "type": "PowerShell",
                      "request": "launch",
                      "program": "${workspaceRoot}/iis.configuration.ps1",
                      "args": [],
                      "cwd": "${workspaceRoot}/iis.configuration.ps1"
                  },
                   {
                      "name": "PowerShell x86",
                      "type": "PowerShell x86",
                      "request": "launch",
                      "program": "${workspaceRoot}/iis.configuration.ps1",
                      "args": [],
                      "cwd": "${workspaceRoot}/iis.configuration.ps1"
                  }
              ]
          }

          Now you can debug / run the iis.configuration.ps1 file, by hitting F5, make sure you selected “PowerShell” and not “PowerShell x86” on the debug tab:

          image

          Caculate trendline datapoints in TypeScript

          If you want to calculate trendline datapoints in TypeScript, you can use the following code:

           

           

           

          Code

           

          module helpers.math {
          'use strict';
          /**
           * Based off: https://github.com/Tom-Alexander/regression-js/blob/master/src/regression.js
           * @param known_y - Array of numbers representing the y-axis values, [1, 2, ...].
           * @param known_x - Optional array of numbers representing the x-axis values, when not supplied this parameter will be [1,2,..."y-axis values total count"].
           */
          
          export function trend(known_y: Array<number>, known_x?: Array<number>): Array<number> {
          
          const ylength = known_y.length;
          
          // When "x-axis values" are not supplied, generate it as [1,2,..."y-axis values total count"].
          
          if (!known_x) {
               known_x = [];
          
          for (let xcounter = 0; xcounter < ylength; xcounter++) {
                  known_x.push(xcounter + 1);
               }
           }
          
          // The "data" should be in the format [[x[0], y[0]], [x[1], y[1]]], ...].
          
          const data = [];
          
          for (let ycounter = 0; ycounter < ylength; ycounter++) {
               data.push([known_x[ycounter], known_y[ycounter]]);
           }
          
          let n = 0;
          
          const results = [];
          const sum = [0, 0, 0, 0, 0];
          for (; n < data.length; n++) {
          if (data[n][1] != null) {
                   sum[0] += data[n][0];
                   sum[1] += data[n][1];
                   sum[2] += data[n][0] * data[n][0];
                   sum[3] += data[n][0] * data[n][1];
                   sum[4] += data[n][1] * data[n][1];
               }
           }
          
          const gradient = (n * sum[3] - sum[0] * sum[1]) / (n * sum[2] - sum[0] * sum[0]);
          const intercept = (sum[1] / n) - (gradient * sum[0]) / n;
          for (let i = 0, len = data.length; i < len; i++) {
          const trendY = data[i][0] * gradient + intercept;
               results.push(trendY);
           }
          
          return results;
           }
          }
          
          

           

           

           

          Unit Test

           

          const trend = helpers.math.trend;
          'use strict';
          describe('zvdz.helpers.calculate.trend', function () {
           it('given an array of points it should return an array of points representing the trendline of the given points.', function () {
              const known_y = [1,2,3,4,5,6];
               expect(trend(known_y)).toEqual([1, 2, 3, 4, 5, 6]);
           });
          });
          
          

          Shifting away from Windows PowerShell towards .NET Core

           

          Now that .NET Core 1.0 is released I find myself coding more and more in .NET Core instead of Windows PowerShell scripts for every day automation. When you are developing you spend a portion of your time setting up environments, renaming, copying, processing files and folders, for that I used to write Windows PowerShell scripts.

           

           

          With the release of .NET Core and its excellent command line and Visual Studio Code support, I’m writing plain old C#, but with dotnet run I can alter a C# file on the fly and run it immediately.

          Plus the C# code is portable between my Windows Desktop, Mac Book Pro laptop and Linux servers, very nice!

           

           

           

          Some examples

           

           

          Deleting *.css files (excluding the libraries folder)

          When you are writing your code in CSS Next you want to keep the CSS Next files in source control, but you don’t want to add the compiled css files in source control, to delete existing css files in a “App” folder, but not the css files in “App/Libraries” I wrote a little .NET Core code:

           

          public
          void DeleteCssFiles() {


          string projectFolder = @”C:\Projects\MyWebApp”;


          string appFolder = Path.Combine(projectFolder, “App”);


          string librariesFolder = Path.Combine(appFolder, “Libraries”);


          string csprojPath = Path.Combine(projectFolder, @” MyWebApp.csproj”);

           


          int fileCounter = 0;


          var files = FindFiles(new
          DirectoryInfo(appFolder), “*.css”); // This will get *.css and *.cssn files on Windows, don’t know why.


          foreach (FileInfo file in files)

          {


          if(

          !file.FullName.StartsWith(librariesFolder) &&

          !file.FullName.EndsWith(“.cssn”)

          ){

           

          fileCounter++;


          File.Delete(file.FullName);


          Console.WriteLine($”Delete {file.FullName});

          }

          }

           


          Console.WriteLine($”Total *.css files deleted = {fileCounter});

          }

           

           

          Rename all *.css files in the *.csproj file to *.cssn files (excluding the libraries folder) and make them build action “None”

           

          Public async
          Task RenameCssToCssnInCsProj() {


          string projectFolder = @”C:\Projects\MyWebApp “;


          string appFolder = Path.Combine(projectFolder, “App”);


          string librariesFolder = Path.Combine(appFolder, “Libraries”);


          string csprojPath = Path.Combine(projectFolder, @” MyWebApp.csproj”);


          string csprojContent = File.ReadAllText(csprojPath);


          int fileCounter = 0;

           


          var files = FindFiles(new
          DirectoryInfo(appFolder), “*.css”); // This will get *.css and *.cssn files on Windows, don’t know why.


          foreach (FileInfo file in files)

          {


          var cssnPath = Path.ChangeExtension(file.FullName, “.cssn”);


          if(

          !file.FullName.StartsWith(librariesFolder)

          ){

           

          fileCounter++;

           


          string relativePath = file.FullName.Replace(projectFolder + @”\”, string.Empty);


          string relativePathCssn = Path.ChangeExtension(relativePath, “.cssn”);


          string find = $”<Content Include=\”{relativePath}\” />”;


          if(csprojContent.Contains(find))

          {


          string replace = $”<None Include=\”{relativePathCssn}\” />”;


          Console.WriteLine($”find {find});


          Console.WriteLine($”replace {replace});

          csprojContent = csprojContent.Replace(find, replace);

          }

           


          await CreateOrUpdateFile(csprojPath, csprojContent);

          }

          }

           


          Console.WriteLine($”Total *.css files = {fileCounter});

          }

           

           

           

          Converting all css files in a Web Application to CSS Next files (where each CSS Next file depends on a shared “variables.cssn” file.

           

           

          public
          async
          Task RenameCssToCssnOnDisk() {


          string projectFolder = @”C:\Projects\ZvdZ\zvdzonline\Source\ZvdZOnline\ZvdZOnline.Web”;


          string appFolder = Path.Combine(projectFolder, “App”);


          string librariesFolder = Path.Combine(appFolder, “Libraries”);


          int fileCounter = 0;

           


          var files = FindFiles(new
          DirectoryInfo(projectFolder), “*.css”); // This will get *.css and *.cssn files, don’t know why.


          foreach (FileInfo file in files)

          {


          var cssnPath = Path.ChangeExtension(file.FullName, “.cssn”);


          if(

          !file.FullName.StartsWith(librariesFolder) &&

          !File.Exists(cssnPath)

          ){

           

          fileCounter++;

           


          string relativePath = file.FullName.Replace(projectFolder, string.Empty);


          Console.WriteLine($”relativePath {relativePath});


          int seperatorCounter = relativePath.Split(@”\”.ToCharArray()).Length – 1;


          Console.WriteLine($”seperatorCounter {seperatorCounter});

           


          // Determine the “import” variables line, that should be added to each CSS Next file.


          string relativePrefix = string.Empty;


          for(var i = 0; i< seperatorCounter; i++) {

          relativePrefix += “../”;

          }


          string importText = $”@import \”{relativePrefix}App/Styles/variables.cssn\”;”;


          Console.WriteLine($”importText {importText});

           


          string content = File.ReadAllText(file.FullName);


          await CreateOrUpdateFile(cssnPath, importText + Environment.NewLine + Environment.NewLine + content );

          }

          }

           


          Console.WriteLine($”Total *.css files renamed = {fileCounter});

          }

           

           

           

          Some Generic function used in the examples above

           

          public
          async
          Task CreateOrUpdateFile(string path, string content)

          {


          byte[] result = Encoding.UTF8.GetBytes(content);


          using (var stream = new
          FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write, bufferSize: 4096, useAsync: true))

          {


          await stream.WriteAsync(result, 0, result.Length);

          }

          }

           


          public
          IEnumerable<FileInfo> FindFiles(DirectoryInfo folder, string pattern)

          {


          // Note: using EnumerateFiles is faster then using “GetFiles”.


          return folder.EnumerateFiles(pattern, SearchOption.AllDirectories);

          }