Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Sunday, February 10, 2019

HTML a tag target="_blank" vulnerability tabnabbing

HTML a tag target="_blank" vulnerability tabnabbing

window.opener.location = 'https://fakewebsite/facebook.com/PHISHING-PAGE.html';

Solution 1:

<a target="_blank" rel="noopener noreferrer">demo</a>

Solution 2:

var newWnd = window.open();
newWnd.opener = null;

Reference:

https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/

https://medium.com/@ali.dev/how-to-fix-target-blank-a-security-and-performance-issue-in-web-pages-2118eba1ce2f

Saturday, January 12, 2019

Install Vue

Install NVM (Node Version Manager):

$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash

Note: You need to logout and log back in.

List the available node versions:

$ nvm ls-remote

Install a node version:

$ nvm install 10.15.0

Use a certain version of node:

$ nvm use 10.15.0

Check node version:

$ node -v

List installed node versions:

$ nvm ls

Install Vue:

$ npm install -g @vue/cli

Create a Vue project:

$ vue create my_project

Switch to the project and add more tools:

$ cd my_project
$ npm install vue-axios axios iview --save
$ npm install js-beautify --save-dev

Add the following lines under "scripts" key:

$ vim package.json

"scripts": {
    "build": "vue-cli-service build --mode production",
    "watch": "vue-cli-service build --mode development --watch",
},

Set up some Vue configuration:

$ vim vue.config.js

module.exports = {
    baseUrl: '/dist/',
    outputDir: 'dist',
    runtimeCompiler: true,
};

Install a hot reload tool to run Go application:

$ go get -u github.com/oxequa/realize
$ realize init

Start realize:

$ realize start

Sunday, July 15, 2018

Create SVG dynamically with JavaScript and save export download SVG file

Create SVG dynamically with JavaScript and save export download SVG file

function saveSvg(svgEl, name) {
    svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
    var svgData = svgEl.outerHTML;
    var preface = '<?xml version="1.0" standalone="no"?>\r\n';
    var svgBlob = new Blob([preface, svgData], {type:"image/svg+xml;charset=utf-8"});
    var svgUrl = URL.createObjectURL(svgBlob);
    var downloadLink = document.createElement("a");
    downloadLink.href = svgUrl;
    downloadLink.download = name;
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
}

saveSvg(svg, 'test.svg');

Reference:

https://stackoverflow.com/questions/23218174/how-do-i-save-export-an-svg-file-after-creating-an-svg-with-d3-js-ie-safari-an

Sunday, May 13, 2018

String length in bytes in JavaScript

String length in bytes in JavaScript

(new TextEncoder('utf-8').encode('foo')).length

Reference:

https://stackoverflow.com/questions/5515869/string-length-in-bytes-in-javascript

Thursday, February 22, 2018

Ace Text Editor Bookmarklet

Ace is a standalone code editor written in JavaScript. Our goal is to create a browser based editor that matches and extends the features, usability and performance of existing native editors such as TextMate, Vim or Eclipse.

Ace Bookmarklet http://ajaxorg.github.io/ace/build/demo/bookmarklet/index.html

javascript:(function inject(options, callback) { var load = function(path, callback) { var head = document.getElementsByTagName('head')[0]; var s = document.createElement('script'); s.src = options.baseUrl + "/" + path; head.appendChild(s); s.onload = s.onreadystatechange = function(_, isAbort) { if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") { s = s.onload = s.onreadystatechange = null; if (!isAbort) callback(); } }; }; var pending = []; var transform = function(el) { pending.push(el) }; load("ace.js", function() { ace.config.loadModule("ace/ext/textarea", function(m) { transform = function(el) { if (!el.ace) el.ace = m.transformTextarea(el, options.ace); }; pending = pending.forEach(transform); callback && setTimeout(callback); }); }); if (options.target) return transform(options.target); window.addEventListener("click", function(e) { if (e.detail == 3 && e.target.localName == "textarea") transform(e.target); });})({"selectionStyle":"line","highlightActiveLine":true,"highlightSelectedWord":true,"readOnly":false,"copyWithEmptySelection":false,"cursorStyle":"ace","mergeUndoDeltas":true,"behavioursEnabled":true,"wrapBehavioursEnabled":true,"keyboardHandler":"ace/keyboard/vim","hScrollBarAlwaysVisible":false,"vScrollBarAlwaysVisible":false,"highlightGutterLine":true,"animatedScroll":false,"showInvisibles":false,"showPrintMargin":false,"printMarginColumn":80,"printMargin":false,"fadeFoldWidgets":false,"showFoldWidgets":true,"showLineNumbers":true,"showGutter":true,"displayIndentGuides":true,"fontSize":"12px","scrollPastEnd":0,"theme":"textmate","scrollSpeed":2,"dragDelay":0,"dragEnabled":true,"focusTimeout":0,"tooltipFollowsMouse":true,"firstLineNumber":1,"overwrite":false,"newLineMode":"auto","useWorker":true,"useSoftTabs":true,"navigateWithinSoftTabs":false,"tabSize":4,"wrap":"off","indentedSoftWrap":true,"foldStyle":"markbegin","mode":"javascript","enableMultiselect":true,"enableBlockSelect":true,"baseUrl":"https://ajaxorg.github.io/ace-builds/src-noconflict"})

Reference:

https://github.com/ajaxorg/ace/

Saturday, February 10, 2018

ajax global default setting

(function($) {
    $(document).ready(function(){
        // ajax global default setting
        $.ajaxSetup({
            contentType: 'Content-Type: application/json',
            method: 'POST',
            dateType: 'json',
        });

        //
        let obj = {Asdf: 'asdf'};

        $.ajax({
            url: '/admin/region/request',
            data: JSON.stringify(obj),
        }).done(function(data) {
            console.log(data);
        }).fail(function(jqXHR, textStatus) {
            console.log(jqXHR.responseJSON);
        }).always(function(data) {
        });
    });
})(jQuery);

How can I get form data with JavaScript/jQuery?

How can I get form data with JavaScript/jQuery?

JQuery:

let formData = new FormData($('#RegionForm')[0]);

for (let [key, val] of formData.entries()) {
  console.log(key + ': ' + val);
}

JavaScript:

document.querySelector('form').addEventListener('submit', (e) => {
  const formData = new FormData(e.target);

  // Now you can use formData.get('foo'), for example.

  for (let pair of formData.entries()) {
    console.log(pair[0] + ', ' + pair[1]); 
  }

  // Don't forget e.preventDefault() if you want to stop normal form .submission
});

Reference:

https://stackoverflow.com/questions/2276463/how-can-i-get-form-data-with-javascript-jquery

Saturday, January 27, 2018

Fastest way to flatten / un-flatten nested JSON objects

Fastest way to flatten / un-flatten nested JSON objects

Solution 1:

// Reference:
// https://github.com/henrytseng/dataobject-parser

/**
 * Dependencies
 */

// True if Object
function _isObject(value) {
  return typeof(value) === 'object' && value !== null;
}

// True if Array
function _isArray(value) {
  return Array.isArray(value);
}

/// True if type is string
function _isString(value) {
  return typeof(value) === 'string';
}

// True if undefined
function _isUndefined(value) {
  return typeof(value) === 'undefined';
}

// True if Number
function _isNumber(value) {
  return typeof(value) === 'number';
}

// True if Boolean
function _isBoolean(value) {
  return typeof(value) === 'boolean';
}

// True if Date object
function _isDate(value) {
  return value instanceof Date;
}

function DataObjectParser($data){
  this._data = $data || {};
}

/**
 * Given a dot deliminated string set will create an object
 * based on the structure of the string with the desired value
 *
 * @param {[String} $path  path indicating where value should be placed
 * @param {Mixed} $value   the value desired to be set at the location determined by path
 */
DataObjectParser.prototype.set = function($path, $value) {
  if(!$path || $path==='') return void 0;

  var _self = this;
  var re = /[\$\w-|]+|\[\]|([^\[[\w]\]]|["'](.*?)['"])/g;
  // parse $path on dots, and brackets
  var pathList = $path.match(re);
  var parent = this._data;
  var parentKey;
  var grandParent = null;
  var grandParentKey = null;

  var addObj = function($obj, $key, $data) {
    if($key === '[]') {
      $obj.push($data);
    } else {
      $obj[$key] = $data;
    }
  };

  while(pathList.length > 0) {
    parentKey = pathList.shift().replace(/["']/g, '');

    // Number, treat it as an array
    if (!isNaN(+parentKey) || parentKey === "[]") {
      if(!_isArray(parent)  /* prevent overwritting */ ) {
        parent = [];
        addObj(grandParent, grandParentKey, parent);
      }

    // String, treat it as a key
    } else if (_isString(parentKey)) {
      if(!_isObject(parent)) {
        parent = {};
        addObj(grandParent, grandParentKey, parent);
      }
    }
    // Next
    grandParent = parent;
    grandParentKey = parentKey;
    parent = parent[parentKey];
  }

  addObj(grandParent, grandParentKey, $value);
  return this;
};

/**
 * Returns the value defined by the path passed in
 *
 * @param  {String} $path string leading to a desired value
 * @return {Mixed}        a value in an object
 */
DataObjectParser.prototype.get = function($path) {
  var data = this._data;
  var regex = /[\$\w-|]+|\[\]|([^\[[\w]\]]|["'](.*?)['"])/g;
  //check if $path is truthy
  if (!$path) return void 0;
  //parse $path on dots and brackets
  var paths = $path.match(regex);
  //step through data object until all keys in path have been processed
  while (data !== null && paths.length > 0) {
    if(data.propertyIsEnumerable(paths[0].replace(/"/g, ''))){
      data = data[paths.shift().replace(/"/g, '')];
    }
    else{
      return undefined;
    }
  }
  return data;
};

DataObjectParser.prototype.data = function($data) {
  if(!_isUndefined($data)) {
    this._data = $data;
    return this;
  }
  return this._data;
};

/**
 * "Transposes" data; receives flat data and returns structured
 *
 * @param  {Object}           $data Structured object
 * @return {DataObjectParser} An instance of a DataObjectParser
 */
DataObjectParser.transpose = function($flat) {
  var parser = (new DataObjectParser());
  for(var n in $flat) {
    if($flat[n]!==undefined) {
      parser.set(n, $flat[n]);
    }
  }
  return parser;
};

/**
 * "Untransposes" data object; opposite of transpose
 *
 * @param  {Mixed}  $structured A Object or a DataObjectParser
 * @return {Object}             Flat object
 */
DataObjectParser.untranspose = function($structured) {
  //check to see if $structured is passed
  $structured = $structured || {};
  //handles if an object or a dataObjectParser is passed in
  var structuredData = $structured._data || $structured;

  var traverse = function($data, $isIndex) {
    var result = [];

    var createMapHandler = function($name, $data) {
      return function($item, $i) {
        var name = $name;
        //check if $name is a key of form "hello.world"
        if((/\./).test($name)) name = '["'+name+'"]';
        //add name to $item.key
        $item.key.unshift(name+".");
        //return $item.key with updated key
        return {
          key: $item.key,
          data: $item.data
        };
      };
    };

    for(var name in $data) {
      var modifiedName;
      // check if current name is an arrays index
      if($isIndex) modifiedName = "["+name+"]";
      else modifiedName = name;

      // check if current name is linked to a value
      if(_isString($data[name]) || _isNumber($data[name]) || $data[name]===null || _isBoolean($data[name]) || _isDate($data[name])) {
        if((/\./).test(name)) modifiedName = '["'+name+'"]';
        result.push({
          key: [modifiedName],
          data: $data[name]
        });
      }

      // check if current name is an array
      else if(_isArray($data[name])) {
        // tell traverse next name is an array's index
        var subArray = traverse($data[name],true);
        result = result.concat(subArray.map(createMapHandler(modifiedName, $data)));
      }

      //check if current name is an object
      else if(_isObject($data[name])) {
        var subObject = traverse($data[name],false);
        result = result.concat(subObject.map(createMapHandler(modifiedName, $data)));
      }
    }
    return result;
  };

  var flatArray = traverse(structuredData,false);
  var flatObj = {};

  flatArray.every(function($item) {
    //check for any dots followed by brackets and remove the dots
    for(var i = 0;i<$item.key.length-1;i++){
      var name = $item.key[i];
      var nextName = $item.key[i+1];
      if((/^\[/).test(nextName)){
        $item.key[i] = name.replace(/\.$/,"");
      }
    }
    //join all the keys in flatArray to form one key
    flatObj[$item.key.join("")] = $item.data;
    return true;
  });
  return flatObj;
};

var d = new DataObjectParser();

d.set("User.caravan.personel.leader","Travis");
d.set("User.caravan.personel.cook","Brent");
d.set("User.location.rooms[0]", "kitchen");
d.set("User.location.rooms[1]", "bathroom");
d.set("User.location.rowArr[0][0].Name", "Jun 00");
d.set("User.location.rowArr[0][0].Age", 19);
d.set("User.location.rowArr[0][1].Name", "Jun 01");
d.set("User.location.rowArr[0][1].Age", 20);
d.set("User.location.rowArr[1][0].Name", "Jun 10");
d.set("User.location.rowArr[1][0].Age", 21);
d.set("User.location.rowArr[1][1].Name", "Jun 11");
d.set("User.location.rowArr[1][1].Age", 22);
var obj1 = d.data();
console.log(obj1);

var flat = DataObjectParser.untranspose(obj1);
var obj2 = DataObjectParser.transpose(flat).data();

console.log(flat);
console.log(obj2);

Solution 2:

// Reference:
// https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objects
// https://stackoverflow.com/questions/24833379/why-and-when-do-we-need-to-flatten-json-objects
// https://stackoverflow.com/questions/7793811/convert-javascript-dot-notation-object-to-nested-object
// https://github.com/henrytseng/dataobject-parser

function unflatten(table) {
    var result = {};

    for (var path in table) {
        var cursor = result, length = path.length, property = "", index = 0;

        while (index < length) {
            var char = path.charAt(index);

            if (char === "[") {
                var start = index + 1,
                    end = path.indexOf("]", start),
                    cursor = cursor[property] = cursor[property] || [],
                    property = path.slice(start, end),
                    index = end + 1;
            } else {
                var cursor = cursor[property] = cursor[property] || {},
                    start = char === "." ? index + 1 : index,
                    bracket = path.indexOf("[", start),
                    dot = path.indexOf(".", start);

                if (bracket < 0 && dot < 0) var end = index = length;
                else if (bracket < 0) var end = index = dot;
                else if (dot < 0) var end = index = bracket;
                else var end = index = bracket < dot ? bracket : dot;

                var property = path.slice(start, end);
            }
        }

        cursor[property] = table[path];
    }

    return result[""];
}

var flatten = (function (isArray, wrapped) {
    return function (table) {
        return reduce("", {}, table);
    };

    function reduce(path, accumulator, table) {
        if (isArray(table)) {
            var length = table.length;

            if (length) {
                var index = 0;

                while (index < length) {
                    var property = path + "[" + index + "]", item = table[index++];
                    if (wrapped(item) !== item) accumulator[property] = item;
                    else reduce(property, accumulator, item);
                }
            } else accumulator[path] = table;
        } else {
            var empty = true;

            if (path) {
                for (var property in table) {
                    var item = table[property], property = path + "." + property, empty = false;
                    if (wrapped(item) !== item) accumulator[property] = item;
                    else reduce(property, accumulator, item);
                }
            } else {
                for (var property in table) {
                    var item = table[property], empty = false;
                    if (wrapped(item) !== item) accumulator[property] = item;
                    else reduce(property, accumulator, item);
                }
            }

            if (empty) accumulator[path] = table;
        }

        return accumulator;
    }
}(Array.isArray, Object));

let obj1 = {
  "User": {
   "UserID": 999,
    "Username": "Jun",
    "IsEnabled": true,
    "PermissionArr": {
     "52": ["VIEW", "UPDATE"],
      "53": ["VIEW", "UPDATE"],
      "54": [{"Name": "View", "Status": true}, {"Name": "Create", "Status": false}],
    },
    "CreditCardArr": [
      {"Num": "12345"},
      {"Num": "6789"},
    ],
    "RowArr": [
     [{"Name": "Jun 00"}, {"Name": "Jun 01"}],
      [{"Name": "Jun 10"}, {"Name": "Jun 11"}],
    ],
  }
};

let data1 = flatten(obj1);
let obj2 = unflatten(data1);
//console.log(data1);
console.log(obj2);

Reference:

https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objects

https://stackoverflow.com/questions/7793811/convert-javascript-dot-notation-object-to-nested-object

how to exclude css files from eslint parser

how to exclude css files from eslint parser

# vim .eslintignore

*.css

Reference:

https://stackoverflow.com/questions/43626296/how-to-exclude-css-files-from-eslint-parser-in-react

Saturday, December 9, 2017

XMLHttpRequest cannot load. No 'Access-Control-Allow-Origin' header is present on the requested resource

XMLHttpRequest cannot load. No 'Access-Control-Allow-Origin' header is present on the requested resource

APIs are the threads that let you stitch together a rich web experience. But this experience has a hard time translating to the browser, where the options for cross-domain requests are limited to techniques like JSON-P (which has limited use due to security concerns) or setting up a custom proxy (which can be a pain to set up and maintain).

Cross-Origin Resource Sharing (CORS) is a W3C spec that allows cross-domain communication from the browser. By building on top of the XMLHttpRequest object, CORS allows developers to work with the same idioms as same-domain requests.

The use-case for CORS is simple. Imagine the site alice.com has some data that the site bob.com wants to access. This type of request traditionally wouldn’t be allowed under the browser’s same origin policy. However, by supporting CORS requests, alice.com can add a few special response headers that allows bob.com to access the data.

As you can see from this example, CORS support requires coordination between both the server and client. Luckily, if you are a client-side developer you are shielded from most of these details. The rest of this article shows how clients can make cross-origin requests, and how servers can configure themselves to support CORS.

Method 1:

On the remote server, add:

<?php
header('Access-Control-Allow-Origin: http://symfony.cent-dev.local');
#header('Access-Control-Allow-Headers: X-Requested-With');
#header('Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS');
?>

Then, go observe the response in the browser at client side. You will see the three lines above.

Method 2:

On the remote server, edit your Apache configuration file:

<ifModule mod_headers.c>
    Header set Access-Control-Allow-Origin: http://symfony.cent-dev.local
</ifModule>

Note: you can replace http://symfony.cent-dev.local to a wildcard *.

Note: and don't forget to load module: a2enmod headers

Method 3:

Add a proxy script on your server, ex: proxy.php then having your client side script to access the proxy.php script.

The proxy.php script then send the request to the remote server.

Method 4:

On your server, set up proxy on Apache:

<LocationMatch "/api">
   ProxyPass http://remote-server.com:8000/api/
   #Header add "Access-Control-Allow-Origin" "*"
   Header add "Access-Control-Allow-Origin" "http://symfony.cent-dev.local"
</LocationMatch>

Note: You need to enable mod_proxy and mod_headers.

Reference:

http://www.html5rocks.com/en/tutorials/cors/
http://www.html5rocks.com/en/tutorials/file/xhr2/#toc-cors
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
http://www.andlabs.org/html5.html
https://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity

Thursday, February 2, 2017

Google MAP API group marker together cluster zoom out

This example shows six different ways of adding mouseover event listener to the marker.

Download js-marker-clusterer: https://github.com/googlemaps/js-marker-clusterer

or from

https://github.com/googlemaps/v3-utility-library

test.json:

var data = {
  'points': [
    {lat: 37.4119, lng: -122.1419, idDealer: 1, dealerName: 'test 1', salesDiff: 100},
    {lat: 37.4219, lng: -122.1419, idDealer: 2, dealerName: 'test 2', salesDiff: -100},
    {lat: 37.4319, lng: -122.1419, idDealer: 3, dealerName: 'test 3', salesDiff: 100},
    {lat: 37.4419, lng: -122.1419, idDealer: 4, dealerName: 'test 4', salesDiff: -100},
    {lat: 37.4519, lng: -122.1419, idDealer: 5, dealerName: 'test 5', salesDiff: 100},
    {lat: 37.4619, lng: -122.1419, idDealer: 6, dealerName: 'test 6', salesDiff: -100},
    {lat: 37.4719, lng: -122.1419, idDealer: 7, dealerName: 'test 7', salesDiff: 100},
    {lat: 37.4819, lng: -122.1419, idDealer: 8, dealerName: 'test 8', salesDiff: 100},
  ],
};

test.html:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>MarkerClusterer v3 Simple Example</title>
    <style >
      #map {
        width: 800px;
        height: 600px;
      }
    </style>

    <script src="https://maps.googleapis.com/maps/api/js"></script>
    <script src="test.json"></script>
    <script src="jquery-2.1.3.min.js"></script>
    <script type="text/javascript" src="../src/markerclusterer_compiled.js"></script>
    <script>
      function initialize() {
        var center = new google.maps.LatLng(37.4419, -122.1419);

        var map = new google.maps.Map(document.getElementById('map'), {
          zoom: 13,
          center: center,
          mapTypeId: google.maps.MapTypeId.ROADMAP,
        });
        var infowindow = new google.maps.InfoWindow();

        var iconURL = 'http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=';
        var iconRed = iconURL + 'D|FF0000|000000';
        var iconOrange = iconURL + 'D|ff9933|000000';
        var iconGreen = iconURL + 'U|33cc00|000000';
        var myIcon = iconGreen;

        var markers = [];

        for (var i = 0; i < data.points.length; i++) {
          var latLng = new google.maps.LatLng(data.points[i].lat, data.points[i].lng);
          var marker = new google.maps.Marker({
            //id: 'test' + i, // this is optional.
            icon: myIcon,
            //icon: genIcon(),
            position: latLng,
            mystr: 'str ' + i,
          });

          // infowindow mouseover - version 1
          google.maps.event.addListener(marker, 'mouseover', setInfoWindowContent_v1(map, marker, infowindow));

          // (preferred) infowindow mouseover - version 2
          // without passing map, marker to the closure function.
          google.maps.event.addListener(marker, 'mouseover', setInfoWindowContent_v2(infowindow));

          // infowindow mouseover - version 3
          google.maps.event.addListener(marker, 'mouseover', (function(marker, i) {
            return function() {
              infowindow.setContent(data.points[i].dealerName);
              infowindow.open(map, marker); // or change marker to this.
            }
          })(marker, i));

          // infowindow mouseover - version 4
          google.maps.event.addListener(marker, 'mouseover', (function(marker, dataPoint) {
            return function() {
              infowindow.setContent(dataPoint.dealerName);
              infowindow.open(map, marker); // or change marker to this
            }
          })(marker, data.points[i]));

          // infowindow mouseover - version 5
          // without passing marker to the closure function. Use this instead of marker.
          google.maps.event.addListener(marker, 'mouseover', (function(dataPoint) {
            return function() {
              infowindow.setContent(dataPoint.dealerName);
              infowindow.open(this.map, this);
            }
          })(data.points[i]));

          // infowindow mouseover - version 6
          google.maps.event.addListener(marker, 'mouseover', function() {
            infowindow.setContent(this.mystr);
            infowindow.open(map, this);
          });

          // click
          google.maps.event.addListener(marker, 'click', function() {
            console.log($(this).attr('mystr'));
          });

          markers.push(marker);
        }

        var markerCluster = new MarkerClusterer(map, markers);
      }

      google.maps.event.addDomListener(window, 'load', initialize);

      $(document).ready(function(){
        $(document).on('click', '#test0', function(e){
          e.preventDefault();
          console.log('clicked!');
        });

        $(document).on('click', '.gan', function(e){
          e.preventDefault();
          console.log('clicked!!!!');
        });
      });

      function setInfoWindowContent_v1(map, marker, infowindow) {
        return function() {
          infowindow.setContent(marker.mystr);
          infowindow.open(map, marker);
        }
      }

      function setInfoWindowContent_v2(infowindow) {
        return function() {
          infowindow.setContent(this.mystr);
          infowindow.open(this.map, this);
        }
      }

      function genIcon() {
        var icon = {
          path: google.maps.SymbolPath.CIRCLE,
          fillOpacity: 1,
          fillColor: '#002664',
          strokeWeight: 1, 
          strokeColor: '#FFFFFF',
          scale: 5 //pixels
        };
        return icon;
      }
    </script>
  </head>
  <body>
    <div id="map"></div>
    <a class="gan">test</a>
  </body>
</html>

Reference:

http://stackoverflow.com/questions/7044587/adding-multiple-markers-with-infowindows-google-maps-api
http://stackoverflow.com/questions/3059044/google-maps-js-api-v3-simple-multiple-marker-example/16325107#16325107
http://codereview.stackexchange.com/questions/25882/adding-events-to-multiple-markers-in-a-google-map?newreg=8f84e1facf3c42ac9e3adb089a3c6559

Thursday, June 2, 2016

How to create an HTML button that acts like a link?

    // PrintBtn
    $('#PrintBtn').on('click', function(event){
      event.preventDefault();

      window.location.href = 'customprotocol:Hello World';
    });

Sunday, April 24, 2016

Useful Go Library (some PHP, JavaScript)

Useful Go Library (some PHP, JavaScript)

Gorilla is a web toolkit for the Go programming language

https://github.com/gorilla/websocket
https://github.com/gorilla/csrf
https://github.com/gorilla/mux

Golang implementation of JSON Web Tokens (JWT)

https://github.com/dgrijalva/jwt-go

Redis client for Golang

https://github.com/go-redis/redis

Golang module for google re-captcha

https://github.com/haisum/recaptcha

Time-based One Time Passwords (TOTP) two factor authentication library

https://github.com/pquerna/otp

Golang two factor authentication library

https://github.com/sec51/twofactor

Google Authenticator for Go

https://github.com/dgryski/dgoogauth

Go implementation of RFC 4226 OATH-HOTP authentication

https://github.com/gokyle/hotp

A small decorator for the JavaScript WebSocket API that automatically reconnects (JavaScript)

https://github.com/joewalnes/reconnecting-websocket

A PHP extension for Redis (PHP)

https://github.com/phpredis/phpredis

Go development plugin for Vim

https://github.com/fatih/vim-go

Fast PostgreSQL client and ORM for Golang

https://github.com/go-pg/pg

Tuesday, March 29, 2016

Monday, March 28, 2016

HTTP Cookies: What's the difference between Max-age and Expires?

HTTP Cookies: What's the difference between Max-age and Expires?

Quick Answer:

Expires sets an expiry date for when a cookie gets deleted
Max-age sets the time in seconds for when a cookie will be deleted
Internet Explorer (ie6, ie7, and ie8) does not support “max-age”, while (mostly) all browsers support expires

Reference:

http://mrcoles.com/blog/cookies-max-age-vs-expires/

Monday, March 21, 2016

use EDGE.JS to integrate .NET framework into Node.js

We use EDGE.JS to integrate .NET framework into Node.js.

To install edge.js on client side:

# npm install edge

Server side index.php - http://my.cent-dev.local:

<html>
  <head>
    <script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
    <script>
    $( document ).ready(function() {
      $('#uploadBtn').on('click', function(event){
        $.get( 'http://127.0.0.1:1337/', function( data ) {
          console.log(data);
        });
      });
    });
    </script>
  </head>
  <body>

    <p id="uploadBtn">Hit me to Upload</p>
  </bodY>
</html>

Server side - upload.php:

<?php
file_put_contents('/tmp/debug1', print_r($_FILES, TRUE) . PHP_EOL, FILE_APPEND);

if (!empty($_FILES)) {
  $dir = '/www/my/javascript/tmp/upload_dir/';

  ### Warning: remember to sanitize the filename because it could be forged.
  move_uploaded_file($_FILES['file1']['tmp_name'], $dir . $_FILES['file1']['name']);
}
?>

Client side - running a Node.js web server that will upload the local files to the remote server:

const http = require('http');

const hostname = '127.0.0.1';
const port = 1337;

var url = require('url');
var edge = require('edge');

var uploadFile = edge.func(
    {
        source: function() {/*
            using System;
            using System.IO;
            using System.Threading.Tasks;
            using System.Drawing;
            using System.Drawing.Printing;
            using System.Net.Http;

            public class Startup
            {
                public async Task<object> Invoke(dynamic input)
                {
                    int a = (int)input.a;
                    int b = (int)input.b;

                    //MathHelper.printToPrinter(input.myMsg);
                    MathHelper.Upload(input.uploadURL, input.filePath);

                    return MathHelper.Add(a, b);
                }

            }

            static class MathHelper
            {
                public static int Add(int a, int b)
                {
                    return a + b;
                }

                public static System.IO.Stream Upload(string url, string filename)
                {

                    Stream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
                    HttpContent fileStreamContent = new StreamContent(fileStream);

                    // Submit the form using HttpClient and 
                    // create form data as Multipart (enctype="multipart/form-data")

                    using (var client = new HttpClient())
                    using (var formData = new MultipartFormDataContent())
                    {
                        formData.Add(fileStreamContent, "file1", filename);

                        // equivalent to (action="{url}" method="post")
                        var response = client.PostAsync(url, formData).Result;

                        // equivalent of pressing the submit button on the form
                        if (!response.IsSuccessStatusCode)
                        {
                            return null;
                        }
                        return response.Content.ReadAsStreamAsync().Result;
                    }
                }

                public static void printToPrinter(string s) {
                  //string s = "string to print2";

                  PrintDocument p = new PrintDocument();
                  p.PrintPage += delegate (object sender1, PrintPageEventArgs e1)
                  {
                      e1.Graphics.DrawString(s, new Font("Times New Roman", 12), new SolidBrush(Color.Black), new RectangleF(0, 0, p.DefaultPageSettings.PrintableArea.Width, p.DefaultPageSettings.PrintableArea.Height));
                  };
                  try
                  {
                      p.Print();
                  }
                  catch (Exception ex)
                  {
                      throw new Exception("Exception Occured While Printing", ex);
                  }
                }
            }
        */},
        references: ["System.dll", "System.Drawing.dll", "System.Net.Http.dll"]
    });

var myTxt = "Hello World";
var remoteURL = 'http://my.cent-dev.local';
var uploadURL = remoteURL + "/javascript/tmp/upload.php";

var filePath = "C:/Users/bot/Downloads/tmp/node.js/asdf2.pdf";

http.createServer((req, res) => {
  var queryData = url.parse(req.url, true).query;

  console.log(queryData);

  uploadFile({ a: 5, b: 10, myMsg: myTxt, uploadURL: uploadURL, filePath: filePath}, function (error, result) {
      console.log(result);
  });

  res.writeHead(200, {
    'Content-Type': 'text/plain',
    'Access-Control-Allow-Origin': remoteURL,
  });

  res.end('Hello World123\n');

}).listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});


Reference:

http://tjanczuk.github.io/edge/#/

http://stackoverflow.com/questions/566462/upload-files-with-httpwebrequest-multipart-form-data

Sunday, March 20, 2016

How to create an empty object

Object.create(null) is similar to { }, but without the delegation to Object.prototype, so it's "more empty" than just { }

var emptyObj = Object.create( null );

Reference:

https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/ch2.md

Wednesday, March 9, 2016

Display a video from a Blob Javascript

<video autoplay controls poster="../images/poster.jpg" preload="metadata">Your browser does not support the video element</video>
<script src="js/main.js"></script>

js/main.js:

'use strict';

/* globals FileError */

// get video file via XHR
// store with File API
// read Blob from File API and set as video src using createObjectUrl()
// play video

var video = document.querySelector('video');

function getVideo(fileEntry) {
  get('../video/chrome.webm', function(uInt8Array) {
    var blob = new Blob([uInt8Array], {
      type: 'video/webm'
    });
    writeToFile(fileEntry, blob);
  });
}

function get(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'arraybuffer';
  xhr.send();

  xhr.onload = function() {
    if (xhr.status !== 200) {
      alert('Unexpected status code ' + xhr.status + ' for ' + url);
      return false;
    }
    callback(new Uint8Array(xhr.response));
  };
}

// code adapted from HTML5 Rocks article by Eric Bidelman
// http://www.html5rocks.com/en/tutorials/file/filesystem/

// init a FileSystem
// create a file
// write to the file
// read from the file

window.requestFileSystem =
window.requestFileSystem || window.webkitRequestFileSystem;

window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, // 5MB
  handleInitSuccess, handleError);

function handleInitSuccess(fileSystem) {
  window.fileSystem = fileSystem;
  log('Initiated FileSystem: ' + fileSystem.name);
  createFile('video.webm');
}

function createFile(fullPath) {
  window.fileSystem.root.getFile(fullPath, {
    create: true
    /* exclusive: true */
  },
  function(fileEntry) {
    log('Created file: ' + fileEntry.fullPath);
    getVideo(fileEntry);
  }, handleError);
}

function writeToFile(fileEntry, blob) {
  // Create a FileWriter object for fileEntry
  fileEntry.createWriter(function(fileWriter) {
    fileWriter.onwriteend = function() {
      // read from file
      log('Wrote to file ' + fileEntry.fullPath);
      readFromFile(fileEntry.fullPath);
    };
    fileWriter.onerror = function(e) {
      log('Write failed: ' + e.toString());
    };
    // Create a new Blob and write it to file
    fileWriter.write(blob);
  }, handleError);
}

function readFromFile(fullPath) {
  window.fileSystem.root.getFile(fullPath, {}, function(fileEntry) {
    // Get a File object representing the file
    // then use FileReader to read its contents
    fileEntry.file(function(file) {
      var reader = new FileReader();
      reader.onloadend = function() {
        // video.src = this.result;
        video.src = URL.createObjectURL(new Blob([this.result]));
      };
      // reader.readAsDataURL(file);
      reader.readAsArrayBuffer(file);
    }, handleError);
  }, handleError);
}

function handleError(e) {
  switch (e.code) {
  case FileError.QUOTA_EXCEEDED_ERR:
    log('QUOTA_EXCEEDED_ERR');
    break;
  case FileError.NOT_FOUND_ERR:
    log('NOT_FOUND_ERR');
    break;
  case FileError.SECURITY_ERR:
    log('SECURITY_ERR');
    break;
  case FileError.INVALID_MODIFICATION_ERR:
    log('INVALID_MODIFICATION_ERR');
    break;
  case FileError.INVALID_STATE_ERR:
    log('INVALID_STATE_ERR');
    break;
  default:
    log('Unknown error');
    break;
  }
}

var data = document.getElementById('data');

function log(text) {
  data.innerHTML += text + '<br />';
}

document.querySelector('video').addEventListener('loadedmetadata', function() {
  var fileName = this.currentSrc.replace(/^.*[\\\/]/, '');
  document.querySelector('#videoSrc').innerHTML = 'currentSrc: ' + fileName +
  '<br /> videoWidth: ' + this.videoWidth + 'px<br /> videoHeight: ' + this
  .videoHeight + 'px';
});

Reference:

http://stackoverflow.com/questions/14317179/display-a-video-from-a-blob-javascript

http://simpl.info/video/offline/

https://github.com/samdutton/simpl/blob/gh-pages/video/offline/index.html