constructor () {
        this.version = '2.0.x'
        this.tmp = {}
        this.settings = this.extend({}, {
            'dataType'       : 'HTTPJSON', // can be HTTP, HTTPJSON, RESTFULL, JSON (case sensitive)
            'dateStartYear'  : 1950,  // start year for date-picker
            'dateEndYear'    : 2030,  // end year for date picker
            'macButtonOrder' : false, // if true, Yes on the right side
            'warnNoPhrase'   : false,  // call console.warn if lang() encounters a missing phrase
        }, w2locale, { phrases: null }), // if there are no phrases, then it is original language
        this.i18nCompare = Intl.Collator().compare
        this.hasLocalStorage = testLocalStorage()
        // some internal variables
        this.isMac = /Mac/i.test(navigator.platform)
        this.isMobile = /(iphone|ipod|mobile|android)/i.test(navigator.userAgent)
        this.isIOS = /(iphone|ipod|ipad)/i.test(navigator.platform)
        this.isAndroid = /(android)/i.test(navigator.userAgent)
        this.isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
        this.isFirefox = /(Firefox)/i.test(navigator.userAgent)
        // Formatters: Primarily used in grid
        this.formatters = {
            'number'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (parseInt(params) > 20) params = 20
                if (parseInt(params) < 0) params = 0
                if (value == null || value === '') return ''
                return w2utils.formatNumber(parseFloat(value), params, true)
            },
            'float'(record, extra) {
                return w2utils.formatters.number(record, extra)
            },
            'int'(record, extra) {
                return w2utils.formatters.number(record, extra)
            },
            'money'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (value == null || value === '') return ''
                let data = w2utils.formatNumber(Number(value), w2utils.settings.currencyPrecision, true)
                return (w2utils.settings.currencyPrefix || '') + data + (w2utils.settings.currencySuffix || '')
            },
            'currency'(record, extra) {
                return w2utils.formatters.money(record, extra)
            },
            'percent'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (value == null || value === '') return ''
                return w2utils.formatNumber(value, params || 1) + '%'
            },
            'size'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (value == null || value === '') return ''
                return w2utils.formatSize(parseInt(value))
            },
            'date'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (params === '') params = w2utils.settings.dateFormat
                if (value == null || value === 0 || value === '') return ''
                let dt = w2utils.isDateTime(value, params, true)
                if (dt === false) dt = w2utils.isDate(value, params, true)
                return '<span title="'+ dt +'">' + w2utils.formatDate(dt, params) + '</span>'
            },
            'datetime'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (params === '') params = w2utils.settings.datetimeFormat
                if (value == null || value === 0 || value === '') return ''
                let dt = w2utils.isDateTime(value, params, true)
                if (dt === false) dt = w2utils.isDate(value, params, true)
                return '<span title="'+ dt +'">' + w2utils.formatDateTime(dt, params) + '</span>'
            },
            'time'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (params === '') params = w2utils.settings.timeFormat
                if (params === 'h12') params = 'hh:mi pm'
                if (params === 'h24') params = 'h24:mi'
                if (value == null || value === 0 || value === '') return ''
                let dt = w2utils.isDateTime(value, params, true)
                if (dt === false) dt = w2utils.isDate(value, params, true)
                return '<span title="'+ dt +'">' + w2utils.formatTime(value, params) + '</span>'
            },
            'timestamp'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (params === '') params = w2utils.settings.datetimeFormat
                if (value == null || value === 0 || value === '') return ''
                let dt = w2utils.isDateTime(value, params, true)
                if (dt === false) dt = w2utils.isDate(value, params, true)
                return dt.toString ? dt.toString() : ''
            },
            'gmt'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (params === '') params = w2utils.settings.datetimeFormat
                if (value == null || value === 0 || value === '') return ''
                let dt = w2utils.isDateTime(value, params, true)
                if (dt === false) dt = w2utils.isDate(value, params, true)
                return dt.toUTCString ? dt.toUTCString() : ''
            },
            'age'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (value == null || value === 0 || value === '') return ''
                let dt = w2utils.isDateTime(value, null, true)
                if (dt === false) dt = w2utils.isDate(value, null, true)
                return '<span title="'+ dt +'">' + w2utils.age(value) + (params ? (' ' + params) : '') + '</span>'
            },
            'interval'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                if (value == null || value === 0 || value === '') return ''
                return w2utils.interval(value) + (params ? (' ' + params) : '')
            },
            'toggle'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                return (value ? w2utils.lang('Yes') : '')
            },
            'password'(record, extra) {
                if (extra == undefined) extra = record
                let { value, params } = extra
                let ret = ''
                if (!value) return ret
                for (let i = 0; i < value.length; i++) {
                    ret += '*'
                }
                return ret
            }
        }
        return
        function testLocalStorage() {
            // test if localStorage is available, see issue #1282
            let str = 'w2ui_test'
            try {
                localStorage.setItem(str, str)
                localStorage.removeItem(str)
                return true
            } catch (e) {
                return false
            }
        }
    }
Part of w2ui 2.0 library
 - Dependencies: mQuery, w2utils, w2base, w2locale

== TODO ==
 - add w2utils.lang wrap for all captions in all buttons.
 - check transition (also with layout)
 - deprecate w2utils.tooltip

== 2.0 changes
 - CSP - fixed inline events (w2utils.tooltip still has it)
 - transition returns a promise
 - removed jQuery
 - refactores w2utils.message()
 - added w2utils.confirm()
 - added isPlainObject
 - added stripSpaces
 - implemented marker - can now take an element or just html
 - cssPrefix - deprecated
 - w2utils.debounce
 - w2utils.prepareParams
 - w2utils.getStrHeight
 - w2utils.alrert() - same as w2utils.message()
 - w2utils.prompt() - similar to w2prompt
 - w2utils.normMenu(..., options) got options parameter that can have itemMap
 - w2utils.getNested()
 - w2utils.wait() - async timer