Node.js Simple Command Line Confirm Messages

user confirmation, terminal actions, yes, no

Sometime, special terminal commands can be dangerous for your users. To ensure that they are really want to run the command the proven “best practise” is to wait for an explicit user confirmation by typing yes/no into the terminal.

Install “prompt” using NPM#

First of all, you have to install prompt – a powerfull package for command line prompts & user interactions. The “–save” option will add this package to your package.json file.

npm install prompt --save

Confirm Dialog#

After installing the prompt package you can use the following code to show a confirm dialog to your users.

var _prompt = require('prompt');

// user confirmation required!
_prompt.start();

// disable prefix message & colors
_prompt.message = '';
_prompt.delimiter = '';
_prompt.colors = false;

// wait for user confirmation
_prompt.get({
    properties: {
        
        // setup the dialog
        confirm: {
            // allow yes, no, y, n, YES, NO, Y, N as answer
            pattern: /^(yes|no|y|n)$/gi,
            description: 'Do you really want to format the filesystem and delete all file ?',
            message: 'Type yes/no',
            required: true,
            default: 'no'
        }
    }
}, function (err, result){
    // transform to lower case
    var c = result.confirm.toLowerCase();

    // yes or y typed ? otherwise abort
    if (c!='y' && c!='yes'){
        console.log('ABORT');
        return;
    }
    
    // your code
    console.log('Action confirmed');
    
});

 

Maybe your wondering about some HTTP Headers sent to your browser which are not set in your script by the header() function ? Especially these Cache-Control headers:

Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache

First of all: everything is ok! These headers are automatically set by the PHP Session module to prevent browser/proxy based caching of your pages. Depending on your environment setup, it’s possible to control these headers by using the session_cache_limiter() function or use the php.ini

To disable these behaviour just pass an empty string to the session_cache_limiter() function as mentioned in the documentation:

Solution#

// add this line to the beginning of your php script to disable the cache limiter funktion:
session_cache_limiter('');

Create Static Social-Media “Share” Buttons without Javascript

no external resources required, corporate privacy compliance

Social-Media Share Buttons are everywhere, but most of them are working with external hosted javascript resources which are loaded on each page request. Depending on the servers cache settings this can cause multiple additional http request for your visitors. Additionally it can raise some privacy issues becaue of the possibility that your users can be […]

MooTools: A modern Element.highlight() implementation

using CSS3 Transisitons instead of Fx.Tween

Use the following code as Element.highlight() replacement:

Element.implement({
    /**
     * Custom Element Highlighting Function
     * @param color
     */
    highlight: function(color){
        // get current background color
        var originalColor = this.getStyle('background-color');

        // set new background color
        this.setStyle('background-color', color);

        // restore background color after 300ms
        (function(){
            this.setStyle('background-color', originalColor);
        }).delay(300, this);
    }
});

It will only change the background color to the given value and reverse this after a time of 300ms. To get a fading-effect you need to add the following css, matching the elements you wish to apply the highlight() method:

.autocomplete-input{
    transition: background-color 200ms;
}

That’s it ;)

Are you using a Yubikey and want to create your custom Keyserver written in Node.js ? In this case this piece of code might be useful :)

/**
 * Convert the Yubico MODHEX encoded Strings to hex
 * @param modhex String
 * @returns hex String
 */
var modhex2hex = function(modhex){
    // strip whitespaces and string cleanup - all non matching characters are 0x00 (c in modhex)
    modhex = modhex.replace(/\s*/g, '').replace(/[^cbdefghijklnrtuv]/g, 'c');

    // even length ?
    if (modhex.length%2 !== 0){
        return null;
    }

    // modhex mapping base; c.....v => 0x0 ... 0xF
    var modhexBase = 'cbdefghijklnrtuv'.split('');

    // tmp
    var output = '';

    // convert
    for (var i=0;i<modhex.length;i++){
        // convert index to hex
        output += modhexBase.indexOf(modhex.charAt(i)).toString(16);
    }

    return output;
};

console.log(modhex2hex('te vt hh fg ue dk gv rt lv hb lu gf nk ge ng cv'));

Bootstrap Dismissible alerts with MooTools

use .alert-dismissible without jQuery

Bootstrap & MooTool#

Using Dismissible alerts with pure MooTools code. Just insert the following code within your domready startup:

Alert.js Replacement#

// get all elements with the .alert-dismissible class
document.getElements('.alert-dismissible').each(function(el){
  // add a onclick event to each element
  el.getElement('button.close').addEvent('click', function(){
    // hide the element on click
    el.setStyle('display', 'none');
  });
});

Dismissible alerts Example#

<div class="alert alert-danger alert-dismissible" id="alert">
    <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    <strong>Invalid Regex Rule: </strong> <code class="txt"></code>
</div>

HowTo: Upgrade Notification for WordPress Plugins

add version based notices to the wordpress plugin page; wp 4.2

Notify your users!# Sometimes, your WordPress plugin will have a major release which may causes groundbreaking API changes. In the past, WordPress displays the “Upgrade Notice” section from readme.txt directly to the users but it seems currently broken – i’ve got no notification for any plugin in the last few month. Therefore i’ve carried out […]

Install Sophos UTM Essential Firewall 9.3 with an USB Stick

plug ‘n play ? not really… (version 9.308-16.1)

First of all, you need to download the iso image (it’s required to create an account – your license key will be sent to this email address).

Install the ISO Image to an USB Drive#

It’s not possible to copy the image via dd directly to the usb drive because of a missing usb bootloader. Therefore you need external bootloader like Universal-USB-Installer from pendrivelinux.

Download and execute the tool.

  • Step 1 choose “Try unlisted Linux ISO” from the bottom of the page.
  • Step 2 select the iso image e.g. asg-9.308-16.1.iso
  • Step 3 select your usb drive (at least 2GB)

After the installation has finished, remove and reattach the usb stick from your system to process with the next step.

Fix the local package repository#

The current (9.308-16.1) iso image has some broken filenames within the local package repository. The files are located under “install/rpm/”. Check each file if it ends with “.rb1.i686.rpm” – if not, modify the filename and add the missing part!

Otherwise the installation will abort and message like “can’t stat file /install/install/rpm/….. rb1.i686.rpm” will appear. I hope this issue will be fixed soon…

Now you can attach the usb stick to your firewall-box and power it up!

Remount the USB Drive#

Ready ? not really… the hardware-detection of the installer will unmount the usb stick, which cause the error message “install.tar not found”. Therefore you have to remount the usb-stick after the hardware detection succeed.

  • After Hardware Detection succeed press “ok”
  • Select the Keyboard Layout and Timezone
  • Press “Alt+F2” to switch to the console
  • Re-Mount the USB drive: mount /dev/sdb /install
  • Press “Alt+F1” to return to the installer
  • Proceed the installation

 

Google Universal Analytics provides a great possibility to track custom events on your website. These feature can be used to analyze special user-interactions with e.g. advertised/highlighted content or social media links. The recorded data can be directly used to optimize your website!

The event tracking is very simple:

To simplify the integration you can implment a simple data-binding which will automatically add event listeners (click) to you DOM elements. Just add an additional attribute to your elements which includes (in this example) a prefix, the event-category and the event-label (scheme: "prefix:category:label").

Example: Social Links with data-binding#

<a href="https://www.facebook.com/groups/" title="Facebook" data-event="ga:social:facebook" class="FacebookButton"></a>
<a href="https://twitter.com/" title="Twitter Stream" data-event="ga:social:twitter" class="TwitterButton"></a>

Finally, we need some javascript to process the additional attributes. You should always check if Google Analytics is enabled (maybe an adblocker is used or an opt-out option is set!) to avoid javascript errors. The following code will send an event to analytics each time a user clicks on the bound elements.

MooTools based Data-Binding#

window.addEvent('domready', function(){
  // GA loaded ? Used to avoid js errors on blocked analytics
  if (typeof ga !== 'function'){
    return;
  }
  
  // event binding
  document.getElements('[data-event]').each(function(el){
    // get event string
    var d = el.get('data-event').split(':');
    
    // format:  "type:category:name"
    if (d.length != 3){
      return;
    }
    
    // extract vars
    var evtType = d[0];
    var evtCategory = d[1];
    var evtName = d[2];
    
    // outgoing link on click event
    el.addEvent('click', function(){
      // universal analytics event ?
      if (evtType == 'ga'){
        ga('send', 'event', evtCategory, 'click', evtName);
      }
    });		
  });
});

 

Simple “Zen” Reading Mode with MooTools

simplifying website headers on-demand

Gigantic, image-based headers are an up-to-date web-feature. It looks amazing but they are squandering space, especially on sites with large tutorials containing long text.

This site is using a simply method which transforms the header-size depending on the current page-scroll: the users scrolls down and the header is automatically transformed to a smart toolbar – i’m calling this mode (following WordPress’ fullscreen editor) “Zen” reader mode. Need a demo ? Just open an article on this site and scroll down.

To integrate this feature into you website, you need the followindd things:

  • “Standard” Header Design
  • “Smart/Compact” Header Design
  • Javascript Page-Scroll Observer
  • Optional: Amazing css3 transition

Different Header-Styles (using LESS):#

/* Basic (default) Styling */
.navbar-beyond{
  height: 70px;
  .transition(500ms);
}

/* Smart Styling */
.navbar-beyond-light{		
  height: 45px;
  border-bottom: solid 1px #e7e7e7;	
  background-color: @color_bluegrey1 !important;
}

/* Large Navbar */
.navbar-beyond-dark{
  background-color: rgba(0,0,0,0.85);
  border-bottom: none;
}

Scroll-Observer Script (MooTools) :#

Description: user scrolls 200px down and the header is transformed by changing the css classes

var head = document.getElement('header .navbar-beyond');
... 
window.addEvent('scroll', function(){
  // get current scroll
  var s = this.getScroll().y;
        
  // dark/light topnav
  if (s > 200){
    head.addClass('navbar-beyond-light');
    head.removeClass('navbar-beyond-dark');
  }else{
    head.addClass('navbar-beyond-dark');
    head.removeClass('navbar-beyond-light');
  }
});

Header Structure (Bootstrap based example from this website)#

<!-- Fixed navbar -->
<div class="navbar navbar-default navbar-fixed-top navbar-beyond navbar-beyond-dark" role="navigation">
  <div class="container container-lg">
    <!-- Website Title + Mobile Nav Button !-->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle">
        <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="http://andidittrich.com">Beyond Technology<br /><span>beyond the visible world</span></a>
    </div>
    
    <!-- Navi !-->
    <div class="navbar-collapse hidden-xs">
      <ul id="menu-topnavi" class="nav navbar-nav navbar-right">
      ....
      </ul>
    </div>
  </div>
</div>

<!-- Image -->
<div id="HeaderImage">
</div>