Source: gs_mobile_jslib.js

/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

var argscheck = require('cordova/argscheck');
var channel = require('cordova/channel');
var exec = require('cordova/exec');
var cordova = require('cordova');

channel.createSticky('onCordovaInfoReady');
// Tell cordova channel to wait on the CordovaInfoReady event
channel.waitForInitialization('onCordovaInfoReady');

/**
 * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
 * phone, etc.
 * @constructor
 */
function Utility () {
    this.available = false;
    this.platform = null;
    this.version = null;
    this.uuid = null;
    this.cordova = null;
    this.model = null;
    this.manufacturer = null;
    this.isVirtual = null;
    this.serial = null;

    var me = this;

    channel.onCordovaReady.subscribe(function () {
        me.getInfo(function (info) {
            // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
            // TODO: CB-5105 native implementations should not return info.cordova
            var buildLabel = cordova.version;
            me.available = true;
            me.platform = info.platform;
            me.version = info.version;
            me.uuid = info.uuid;
            me.cordova = buildLabel;
            me.model = info.model;
            me.isVirtual = info.isVirtual;
            me.manufacturer = info.manufacturer || 'unknown';
            me.serial = info.serial || 'unknown';
                   
            channel.onCordovaInfoReady.fire();
        }, function (e) {
            me.available = false;
            console.error('[ERROR] Error initializing cordova-plugin-device: ' + e);
        });
    });
}

/**
 * 取得行動裝置資訊
 *
 * @param {Function} successCallback The function to call when the heading data is available
 * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
 */
Utility.prototype.getInfo = function (successCallback, errorCallback) {
    argscheck.checkArgs('fF', 'Utility.getInfo', arguments);
    exec(successCallback, errorCallback, 'GS_Mobile_JSLib', 'getDeviceInfo', []);
};

/**
 * @summary 固定n位數, 不足補0
 * @description leftPad(1,3)
 * @param {int} value 傳入值
 * @param {int} length n位數
 * @returns {String} str 001
 */        
Utility.prototype.leftPad = function(value, length) {
  var str = '' + value;
  while (str.length < length) {
      str = '0' + str;
  }
  return str;
}

/**
 * @summary 格式化數字補千分位,固定小數n位
 * @description formatNumber(1234.123, 2)
 * @param {String} number 傳入值
 * @param {String} point 固定小數n位
 * @returns {String} num 1,234.12
 */
Utility.prototype.formatNumber = function (number, point) {
    var num;
    try
    {
       number = number.toFixed(point) + '';
       x = number.split('.');
       x1 = x[0];
       x2 = x.length > 1 ? '.' + x[1] : '';
       var rgx = /(\d+)(\d{3})/;
       while (rgx.test(x1)) {
           x1 = x1.replace(rgx, '$1' + ',' + '$2');
       }
       num =  x1 + x2;
    }
    catch(err)
    {
       num=0;
    }
    return num;
};
          
/**
 * @summary 西元年轉民國年
 * @description yyyy2yyy('2020年01月02日')
 * @returns {String} 109年01月02日
 */
Utility.prototype.yyyy2yyy = function (date) {
    if (date != null) {
        var odate = (date.substring(0, 4) - 1911) + date.substring(4, 5) + date.substring(5, 7) + date.substring(7, 8) + date.substring(8, 10) + date.substring(10, 11);
        if (date.length > 11)
            odate = odate + " " + date.substring(11, date.length);

        odate = odate.trim();
        return odate;
    }
    else
        return "--";
}

/**
 * @summary 民國年轉西元年
 * @description yyyy2yyy('107年01月02日')
 * @returns {String} 2020年01月02日
 */
Utility.prototype.yyy2yyyy = function (date) {
    if (date != null) {
        var odate = (parseInt(date.substring(0, 3)) + 1911) + date.substring(3, 4) + date.substring(4, 6) + date.substring(6, 7) + date.substring(7, 9) + date.substring(9, 10);

        if (date.length > 10)
            odate = odate + " " + date.substring(10, date.length);

        odate = odate.trim();
        return odate
    }
    else
        return "--";
}

/**
 * @summary 取得當下民國日期
 * @returns {String} 109年01月02日
 */
Utility.prototype.getCurrentDate = function () {
   var date = new Date();
   var currentYear = date.getFullYear() - 1911;
   var currentMonth = date.getMonth() + 1;
   var currentDate = date.getDate();
   return utility.leftPad(String(currentYear), 3) + "年" +
       utility.leftPad(String(currentMonth), 2) + "月" +
       utility.leftPad(currentDate, 2) + "日";
}
            


/**
 * @summary 取得當下日期減天數
 * @description getCurrentDateDiff(2) 假設當下是2020/01/03
 * @param {String} diff 欲減掉的天數
 * @returns {String} 傳回就是2020/01/01
 */
Utility.prototype.getCurrentDateDiff = function (diff) {
   var date = new Date();
   date.setDate(date.getDate() - diff);
   var currentYear = date.getFullYear();
   var currentMonth = date.getMonth() + 1;
   var currentDate = date.getDate();
   return utility.leftPad(String(currentYear), 3) + "/" +
       utility.leftPad(String(currentMonth), 2) + "/" +
       utility.leftPad(currentDate, 2);
}

/**
 * @summary 取得當下時間(時跟分)
 * @returns {String} 18時10分
 */
Utility.prototype.getCurrentTime = function () {
   var d = new Date();
   var curr_hour = d.getHours();
   var curr_min = d.getMinutes();

   var curr_sec = d.getSeconds();

   return curr_hour + "時" + curr_min+"分";//+ ":" + curr_sec;
}

/**
 * @summary 取得N個月前的當天
 * @description 假設當天是109/01/02
 * @param {String} num 往前n個月
 * @returns {String} 回傳108/12/02
 */
Utility.prototype.getLastMonthCurrentDate = function (n) {
   var x = new Date();
   x.setMonth(x.getMonth() - n);
   return x;
}

/**
 * @summary 取得N個月後的當天
 * @description 假設當天是109/01/02
 * @param {String} num 往後n個月
 * @returns {String} 回傳109/02/02
 */
Utility.prototype.getNextMonthCurrentDate = function (n) {
   var x = new Date();
   x.setMonth(x.getMonth() + n);
   return x;
}

/**
 * @summary 取得網址參數的值
 * @description 假設網址(url)是https://a.b.c/xxx.aspx?x=val1&y=val2, getParameterByName(y,url)
 * @param {String} name 欲取得的參數名稱
 * @param {String} num 完整的網址
 * @returns {String} 回傳y的值是val2
 */
Utility.prototype.getParameterByName = function(name, url) {
   if (!url) {
     url = window.location.href;
   }
   name = name.replace(/[\[\]]/g, "\\$&");
   var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
       results = regex.exec(url);
   if (!results) return null;
   if (!results[2]) return '';
   return decodeURIComponent(results[2].replace(/\+/g, " "));
}

/**
 * @summary TWD97轉WGS84
 * @param {float} $x TWD97 x坐標
 * @param {float} $y TWD97 y坐標
 * @returns {array} 回傳WGS84坐標陣列
 */
Utility.prototype.twd97_to_latlng = function($x, $y) {
    var pow = Math.pow, M_PI = Math.PI;
    var sin = Math.sin, cos = Math.cos, tan = Math.tan;
    var $a = 6378137.0, $b = 6356752.314245;
    var $lng0 = 121 * M_PI / 180, $k0 = 0.9999, $dx = 250000, $dy = 0;
    var $e = pow((1 - pow($b, 2) / pow($a, 2)), 0.5);
    $x -= $dx;
    $y -= $dy;
    var $M = $y / $k0;
    var $mu = $M / ($a * (1.0 - pow($e, 2) / 4.0 - 3 * pow($e, 4) / 64.0 - 5 * pow($e, 6) / 256.0));
    var $e1 = (1.0 - pow((1.0 - pow($e, 2)), 0.5)) / (1.0 + pow((1.0 - pow($e, 2)), 0.5));
    var $J1 = (3 * $e1 / 2 - 27 * pow($e1, 3) / 32.0);
    var $J2 = (21 * pow($e1, 2) / 16 - 55 * pow($e1, 4) / 32.0);
    var $J3 = (151 * pow($e1, 3) / 96.0);
    var $J4 = (1097 * pow($e1, 4) / 512.0);
    var $fp = $mu + $J1 * sin(2 * $mu) + $J2 * sin(4 * $mu) + $J3 * sin(6 * $mu) + $J4 * sin(8 * $mu);
    var $e2 = pow(($e * $a / $b), 2);
    var $C1 = pow($e2 * cos($fp), 2);
    var $T1 = pow(tan($fp), 2);
    var $R1 = $a * (1 - pow($e, 2)) / pow((1 - pow($e, 2) * pow(sin($fp), 2)), (3.0 / 2.0));
    var $N1 = $a / pow((1 - pow($e, 2) * pow(sin($fp), 2)), 0.5);
    var $D = $x / ($N1 * $k0);
    var $Q1 = $N1 * tan($fp) / $R1;
    var $Q2 = (pow($D, 2) / 2.0);
    var $Q3 = (5 + 3 * $T1 + 10 * $C1 - 4 * pow($C1, 2) - 9 * $e2) * pow($D, 4) / 24.0;
    var $Q4 = (61 + 90 * $T1 + 298 * $C1 + 45 * pow($T1, 2) - 3 * pow($C1, 2) - 252 * $e2) * pow($D, 6) / 720.0;
    var $lat = $fp - $Q1 * ($Q2 - $Q3 + $Q4);
    var $Q5 = $D;
    var $Q6 = (1 + 2 * $T1 + $C1) * pow($D, 3) / 6;
    var $Q7 = (5 - 2 * $C1 + 28 * $T1 - 3 * pow($C1, 2) + 8 * $e2 + 24 * pow($T1, 2)) * pow($D, 5) / 120.0;
    var $lng = $lng0 + ($Q5 - $Q6 + $Q7) / cos($fp);
    $lat = ($lat * 180) / M_PI;
    $lng = ($lng * 180) / M_PI;
    return {
    lat: $lat,
    lng: $lng
    };
}
               
/**
 * @summary 去除字串頭尾空白
 * @returns {String} 
 */
String.prototype.trim = function () {
   ///<summary></summary>
   return this.replace(/(^\s*)|(\s*$)/g, "");
}
              
/**
 * @summary 小數四捨五入2
 * @returns {float} 
 */
Math.Round = function (P, K) {
   try {
       if (typeof (K) == "undefined") { var K = 0; }
       return Math.round(P * Math.pow(10, K)) / Math.pow(10, K)
   } catch (z) { return NaN }
}

module.exports = new Utility();