2016-10-13 11:43:39 +02:00
( function ( module ) {
2013-10-28 23:33:37 +02:00
'use strict' ;
2013-08-28 02:32:38 +08:00
2017-02-17 20:20:42 -07:00
var utils ;
var fs ;
var XRegExp ;
2013-05-23 13:21:38 -04:00
2013-10-28 23:55:45 +02:00
if ( 'undefined' === typeof window ) {
2013-05-23 13:21:38 -04:00
fs = require ( 'fs' ) ;
2016-02-24 18:11:42 +02:00
XRegExp = require ( 'xregexp' ) ;
2014-01-14 19:23:27 -05:00
2016-10-13 11:43:39 +02:00
process . profile = function ( operation , start ) {
2014-03-18 18:51:03 -04:00
console . log ( '%s took %d milliseconds' , operation , process . elapsedTimeSince ( start ) ) ;
2014-03-12 00:13:42 -04:00
} ;
2016-10-13 11:43:39 +02:00
process . elapsedTimeSince = function ( start ) {
2014-01-14 19:23:27 -05:00
var diff = process . hrtime ( start ) ;
2014-03-12 00:13:42 -04:00
return diff [ 0 ] * 1e3 + diff [ 1 ] / 1e6 ;
} ;
2014-01-14 19:23:27 -05:00
2014-01-04 14:24:50 -05:00
} else {
XRegExp = window . XRegExp ;
2013-10-28 23:55:45 +02:00
}
2013-05-23 13:21:38 -04:00
module . exports = utils = {
2016-10-13 11:43:39 +02:00
generateUUID : function ( ) {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' . replace ( /[xy]/g , function ( c ) {
2017-02-17 20:20:42 -07:00
var r = Math . random ( ) * 16 | 0 ;
var v = c === 'x' ? r : ( r & 0x3 | 0x8 ) ;
2013-05-23 13:21:38 -04:00
return v . toString ( 16 ) ;
} ) ;
} ,
//Adapted from http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search
2016-10-13 11:43:39 +02:00
walk : function ( dir , done ) {
2014-03-04 17:08:15 -05:00
var results = [ ] ;
2013-09-07 11:51:37 -04:00
2016-10-13 11:43:39 +02:00
fs . readdir ( dir , function ( err , list ) {
2013-10-28 23:33:37 +02:00
if ( err ) {
return done ( err ) ;
}
2013-06-20 16:48:17 -04:00
var pending = list . length ;
2013-10-28 23:33:37 +02:00
if ( ! pending ) {
return done ( null , results ) ;
}
2016-10-13 11:43:39 +02:00
list . forEach ( function ( file ) {
2013-05-23 13:21:38 -04:00
file = dir + '/' + file ;
2016-10-13 11:43:39 +02:00
fs . stat ( file , function ( err , stat ) {
2016-08-16 19:46:59 +02:00
if ( err ) {
return done ( err ) ;
}
2013-05-23 13:21:38 -04:00
if ( stat && stat . isDirectory ( ) ) {
2016-10-13 11:43:39 +02:00
utils . walk ( file , function ( err , res ) {
2016-08-16 19:46:59 +02:00
if ( err ) {
return done ( err ) ;
}
2013-05-23 13:21:38 -04:00
results = results . concat ( res ) ;
2013-10-28 23:33:37 +02:00
if ( ! -- pending ) {
done ( null , results ) ;
}
2013-05-23 13:21:38 -04:00
} ) ;
} else {
2014-03-04 17:08:15 -05:00
results . push ( file ) ;
2013-10-28 23:33:37 +02:00
if ( ! -- pending ) {
done ( null , results ) ;
}
2013-06-20 16:48:17 -04:00
}
2013-05-23 13:21:38 -04:00
} ) ;
} ) ;
} ) ;
} ,
2013-08-28 02:32:38 +08:00
2014-02-26 21:55:29 -05:00
invalidUnicodeChars : XRegExp ( '[^\\p{L}\\s\\d\\-_]' , 'g' ) ,
invalidLatinChars : /[^\w\s\d\-_]/g ,
trimRegex : /^\s+|\s+$/g ,
collapseWhitespace : /\s+/g ,
collapseDash : /-+/g ,
trimTrailingDash : /-$/g ,
trimLeadingDash : /^-/g ,
2015-03-12 13:39:04 -04:00
isLatin : /^[\w\d\s.,\-@]+$/ ,
2015-02-18 15:33:21 -05:00
languageKeyRegex : /\[\[[\w]+:.+\]\]/ ,
2014-01-21 12:01:09 -05:00
2013-05-23 13:21:38 -04:00
//http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/
2016-10-13 11:43:39 +02:00
slugify : function ( str , preserveCase ) {
2015-03-12 13:26:29 -04:00
if ( ! str ) {
return '' ;
}
2014-01-21 12:01:09 -05:00
str = str . replace ( utils . trimRegex , '' ) ;
2014-01-21 12:02:46 -05:00
if ( utils . isLatin . test ( str ) ) {
2014-01-21 11:48:56 -05:00
str = str . replace ( utils . invalidLatinChars , '-' ) ;
} else {
str = XRegExp . replace ( str , utils . invalidUnicodeChars , '-' ) ;
}
2015-03-03 12:34:41 -05:00
str = ! preserveCase ? str . toLocaleLowerCase ( ) : str ;
2015-01-19 10:39:44 -05:00
str = str . replace ( utils . collapseWhitespace , '-' ) ;
2014-01-21 12:02:46 -05:00
str = str . replace ( utils . collapseDash , '-' ) ;
2014-01-21 12:01:09 -05:00
str = str . replace ( utils . trimTrailingDash , '' ) ;
2014-01-26 22:36:06 -05:00
str = str . replace ( utils . trimLeadingDash , '' ) ;
2013-05-23 13:21:38 -04:00
return str ;
} ,
2016-03-22 18:22:42 +02:00
2016-10-13 11:43:39 +02:00
cleanUpTag : function ( tag , maxLength ) {
2016-12-09 18:53:08 +03:00
if ( typeof tag !== 'string' || ! tag . length ) {
2016-03-22 18:22:42 +02:00
return '' ;
}
tag = tag . trim ( ) . toLowerCase ( ) ;
// see https://github.com/NodeBB/NodeBB/issues/4378
tag = tag . replace ( /\u202E/gi , '' ) ;
tag = tag . replace ( /[,\/#!$%\^\*;:{}=_`<>'"~()?\|]/g , '' ) ;
tag = tag . substr ( 0 , maxLength || 15 ) . trim ( ) ;
var matches = tag . match ( /^[.-]*(.+?)[.-]*$/ ) ;
if ( matches && matches . length > 1 ) {
tag = matches [ 1 ] ;
}
return tag ;
} ,
2013-05-23 13:21:38 -04:00
2016-10-13 11:43:39 +02:00
removePunctuation : function ( str ) {
2014-05-21 21:15:11 -04:00
return str . replace ( /[\.,-\/#!$%\^&\*;:{}=\-_`<>'"~()?]/g , '' ) ;
2014-05-21 20:20:44 -04:00
} ,
2014-03-17 21:47:37 -04:00
2016-10-13 11:43:39 +02:00
isEmailValid : function ( email ) {
2014-03-17 21:47:37 -04:00
return typeof email === 'string' && email . length && email . indexOf ( '@' ) !== - 1 ;
2013-06-25 15:50:14 -04:00
} ,
2016-10-13 11:43:39 +02:00
isUserNameValid : function ( name ) {
2016-10-21 15:31:27 -04:00
return ( name && name !== '' && ( /^['"\s\-\+.*0-9\u00BF-\u1FFF\u2C00-\uD7FF\w]+$/ . test ( name ) ) ) ;
2013-06-25 15:50:14 -04:00
} ,
2013-08-28 02:32:38 +08:00
2016-10-13 11:43:39 +02:00
isPasswordValid : function ( password ) {
2014-08-26 15:05:42 -04:00
return typeof password === 'string' && password . length ;
2013-06-25 15:50:14 -04:00
} ,
2014-02-26 21:55:29 -05:00
2016-10-13 11:43:39 +02:00
isNumber : function ( n ) {
2014-01-20 12:41:35 -05:00
return ! isNaN ( parseFloat ( n ) ) && isFinite ( n ) ;
} ,
2014-02-26 21:55:29 -05:00
2016-10-13 11:43:39 +02:00
hasLanguageKey : function ( input ) {
2015-02-18 15:33:21 -05:00
return utils . languageKeyRegex . test ( input ) ;
} ,
2014-01-20 12:41:35 -05:00
// shallow objects merge
2016-10-13 11:43:39 +02:00
merge : function ( ) {
2017-02-17 20:20:42 -07:00
var result = { } ;
var obj ;
var keys ;
2014-01-20 12:41:35 -05:00
for ( var i = 0 ; i < arguments . length ; i ++ ) {
obj = arguments [ i ] || { } ;
keys = Object . keys ( obj ) ;
for ( var j = 0 ; j < keys . length ; j ++ ) {
result [ keys [ j ] ] = obj [ keys [ j ] ] ;
}
}
return result ;
} ,
2013-08-11 16:41:49 -04:00
2014-02-26 21:55:29 -05:00
fileExtension : function ( path ) {
return ( '' + path ) . split ( '.' ) . pop ( ) ;
} ,
2015-02-18 21:09:33 -05:00
extensionMimeTypeMap : {
"bmp" : "image/bmp" ,
"cmx" : "image/x-cmx" ,
"cod" : "image/cis-cod" ,
"gif" : "image/gif" ,
"ico" : "image/x-icon" ,
"ief" : "image/ief" ,
"jfif" : "image/pipeg" ,
"jpe" : "image/jpeg" ,
"jpeg" : "image/jpeg" ,
"jpg" : "image/jpeg" ,
"png" : "image/png" ,
"pbm" : "image/x-portable-bitmap" ,
"pgm" : "image/x-portable-graymap" ,
"pnm" : "image/x-portable-anymap" ,
"ppm" : "image/x-portable-pixmap" ,
"ras" : "image/x-cmu-raster" ,
"rgb" : "image/x-rgb" ,
"svg" : "image/svg+xml" ,
"tif" : "image/tiff" ,
"tiff" : "image/tiff" ,
"xbm" : "image/x-xbitmap" ,
"xpm" : "image/x-xpixmap" ,
2017-02-17 19:31:21 -07:00
"xwd" : "image/x-xwindowdump" ,
2015-02-18 21:09:33 -05:00
} ,
fileMimeType : function ( path ) {
2016-06-12 07:30:49 +05:00
return utils . extensionToMimeType ( utils . fileExtension ( path ) ) ;
2015-02-18 21:09:33 -05:00
} ,
2016-10-13 11:43:39 +02:00
extensionToMimeType : function ( extension ) {
2015-02-18 21:09:33 -05:00
return utils . extensionMimeTypeMap [ extension ] || '*' ;
} ,
2014-02-26 21:55:29 -05:00
2016-10-13 11:43:39 +02:00
isRelativeUrl : function ( url ) {
2013-09-17 13:04:40 -04:00
var firstChar = url . slice ( 0 , 1 ) ;
2013-08-22 09:50:29 -04:00
return ( firstChar === '.' || firstChar === '/' ) ;
2013-10-16 13:25:17 -04:00
} ,
2016-10-13 11:43:39 +02:00
makeNumbersHumanReadable : function ( elements ) {
elements . each ( function ( ) {
2014-03-31 14:43:44 -04:00
$ ( this ) . html ( utils . makeNumberHumanReadable ( $ ( this ) . attr ( 'title' ) ) ) ;
} ) ;
} ,
2016-10-13 11:43:39 +02:00
makeNumberHumanReadable : function ( num ) {
2013-11-29 14:12:19 -05:00
var n = parseInt ( num , 10 ) ;
if ( ! n ) {
return num ;
2013-10-28 23:33:37 +02:00
}
2013-11-29 14:12:19 -05:00
if ( n > 999999 ) {
return ( n / 1000000 ) . toFixed ( 1 ) + 'm' ;
2017-02-17 22:11:35 -07:00
} else if ( n > 999 ) {
2013-11-29 14:12:19 -05:00
return ( n / 1000 ) . toFixed ( 1 ) + 'k' ;
}
return n ;
2014-01-18 23:18:58 -05:00
} ,
2014-03-31 14:43:44 -04:00
addCommasToNumbers : function ( elements ) {
elements . each ( function ( index , element ) {
$ ( element ) . html ( utils . addCommas ( $ ( element ) . html ( ) ) ) ;
} ) ;
} ,
// takes a string like 1000 and returns 1,000
addCommas : function ( text ) {
return text . replace ( /(\d)(?=(\d\d\d)+(?!\d))/g , "$1," ) ;
} ,
2016-10-13 11:43:39 +02:00
toISOString : function ( timestamp ) {
2014-11-11 11:44:49 -05:00
if ( ! timestamp || ! Date . prototype . toISOString ) {
2014-01-18 23:28:13 -05:00
return '' ;
}
2014-11-11 11:44:49 -05:00
return Date . prototype . toISOString ? new Date ( parseInt ( timestamp , 10 ) ) . toISOString ( ) : timestamp ;
2014-02-07 15:00:53 -05:00
} ,
tags : [ 'a' , 'abbr' , 'acronym' , 'address' , 'applet' , 'area' , 'article' , 'aside' , 'audio' , 'b' , 'base' , 'basefont' , 'bdi' , 'bdo' , 'big' , 'blockquote' , 'body' , 'br' , 'button' , 'canvas' , 'caption' , 'center' , 'cite' , 'code' , 'col' , 'colgroup' , 'command' , 'datalist' , 'dd' , 'del' , 'details' , 'dfn' , 'dialog' , 'dir' , 'div' , 'dl' , 'dt' , 'em' , 'embed' , 'fieldset' , 'figcaption' , 'figure' , 'font' , 'footer' , 'form' , 'frame' , 'frameset' , 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' , 'head' , 'header' , 'hr' , 'html' , 'i' , 'iframe' , 'img' , 'input' , 'ins' , 'kbd' , 'keygen' , 'label' , 'legend' , 'li' , 'link' , 'map' , 'mark' , 'menu' , 'meta' , 'meter' , 'nav' , 'noframes' , 'noscript' , 'object' , 'ol' , 'optgroup' , 'option' , 'output' , 'p' , 'param' , 'pre' , 'progress' , 'q' , 'rp' , 'rt' , 'ruby' , 's' , 'samp' , 'script' , 'section' , 'select' , 'small' , 'source' , 'span' , 'strike' , 'strong' , 'style' , 'sub' , 'summary' , 'sup' , 'table' , 'tbody' , 'td' , 'textarea' , 'tfoot' , 'th' , 'thead' , 'time' , 'title' , 'tr' , 'track' , 'tt' , 'u' , 'ul' , 'var' , 'video' , 'wbr' ] ,
2014-01-18 23:18:58 -05:00
2015-02-07 20:30:03 -05:00
stripTags : [ 'abbr' , 'acronym' , 'address' , 'applet' , 'area' , 'article' , 'aside' , 'audio' , 'base' , 'basefont' ,
'bdi' , 'bdo' , 'big' , 'blink' , 'body' , 'button' , 'canvas' , 'caption' , 'center' , 'cite' , 'code' , 'col' , 'colgroup' ,
'command' , 'datalist' , 'dd' , 'del' , 'details' , 'dfn' , 'dialog' , 'dir' , 'div' , 'dl' , 'dt' , 'em' , 'embed' ,
'fieldset' , 'figcaption' , 'figure' , 'font' , 'footer' , 'form' , 'frame' , 'frameset' , 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' ,
'head' , 'header' , 'hr' , 'html' , 'iframe' , 'input' , 'ins' , 'kbd' , 'keygen' , 'label' , 'legend' , 'li' , 'link' ,
'map' , 'mark' , 'marquee' , 'menu' , 'meta' , 'meter' , 'nav' , 'noframes' , 'noscript' , 'object' , 'ol' , 'optgroup' , 'option' ,
'output' , 'param' , 'pre' , 'progress' , 'q' , 'rp' , 'rt' , 'ruby' , 's' , 'samp' , 'script' , 'section' , 'select' ,
'source' , 'span' , 'strike' , 'style' , 'sub' , 'summary' , 'sup' , 'table' , 'tbody' , 'td' , 'textarea' , 'tfoot' ,
'th' , 'thead' , 'time' , 'title' , 'tr' , 'track' , 'tt' , 'u' , 'ul' , 'var' , 'video' , 'wbr' ] ,
2014-04-05 13:01:10 -04:00
2016-10-13 11:43:39 +02:00
escapeRegexChars : function ( text ) {
2014-04-05 13:01:10 -04:00
return text . replace ( /[-[\]{}()*+?.,\\^$|#\s]/g , "\\$&" ) ;
2014-04-08 17:35:12 -04:00
} ,
2016-10-13 11:43:39 +02:00
escapeHTML : function ( raw ) {
2015-01-18 17:03:08 -05:00
return raw . replace ( /&/gm , "&" ) . replace ( /</gm , "<" ) . replace ( />/gm , ">" ) ;
} ,
2016-10-13 11:43:39 +02:00
isAndroidBrowser : function ( ) {
2014-04-08 17:35:12 -04:00
// http://stackoverflow.com/questions/9286355/how-to-detect-only-the-native-android-browser
var nua = navigator . userAgent ;
return ( ( nua . indexOf ( 'Mozilla/5.0' ) > - 1 && nua . indexOf ( 'Android ' ) > - 1 && nua . indexOf ( 'AppleWebKit' ) > - 1 ) && ! ( nua . indexOf ( 'Chrome' ) > - 1 ) ) ;
2014-05-01 13:43:07 -04:00
} ,
2016-10-13 11:43:39 +02:00
isTouchDevice : function ( ) {
2015-11-02 11:16:31 -05:00
return 'ontouchstart' in document . documentElement ;
} ,
2016-10-13 11:43:39 +02:00
findBootstrapEnvironment : function ( ) {
2014-05-01 13:43:07 -04:00
//http://stackoverflow.com/questions/14441456/how-to-detect-which-device-view-youre-on-using-twitter-bootstrap-api
2017-02-17 20:20:42 -07:00
var envs = [ 'xs' , 'sm' , 'md' , 'lg' ] ;
var $el = $ ( '<div>' ) ;
2014-05-01 13:43:07 -04:00
2015-01-06 16:05:06 -05:00
$el . appendTo ( $ ( 'body' ) ) ;
2014-05-01 13:43:07 -04:00
2015-01-06 16:05:06 -05:00
for ( var i = envs . length - 1 ; i >= 0 ; i -- ) {
var env = envs [ i ] ;
2014-05-01 13:43:07 -04:00
2016-10-13 11:42:29 +02:00
$el . addClass ( 'hidden-' + env ) ;
2015-01-06 16:05:06 -05:00
if ( $el . is ( ':hidden' ) ) {
$el . remove ( ) ;
return env ;
2014-05-01 13:43:07 -04:00
}
2015-01-06 16:05:06 -05:00
}
2014-05-16 01:38:47 -04:00
} ,
2016-10-13 11:43:39 +02:00
isMobile : function ( ) {
2016-02-25 16:12:50 -05:00
var env = utils . findBootstrapEnvironment ( ) ;
2016-10-13 11:43:39 +02:00
return [ 'xs' , 'sm' ] . some ( function ( targetEnv ) {
2016-02-25 16:12:50 -05:00
return targetEnv === env ;
} ) ;
} ,
2016-10-13 11:43:39 +02:00
getHoursArray : function ( ) {
2017-02-17 20:20:42 -07:00
var currentHour = new Date ( ) . getHours ( ) ;
var labels = [ ] ;
2016-02-25 16:12:50 -05:00
for ( var i = currentHour , ii = currentHour - 24 ; i > ii ; i -- ) {
var hour = i < 0 ? 24 + i : i ;
labels . push ( hour + ':00' ) ;
}
return labels . reverse ( ) ;
} ,
2016-10-13 11:43:39 +02:00
getDaysArray : function ( from ) {
2017-02-17 20:20:42 -07:00
var currentDay = new Date ( from || Date . now ( ) ) . getTime ( ) ;
var months = [ 'Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' , 'Oct' , 'Nov' , 'Dec' ] ;
var labels = [ ] ;
var tmpDate ;
2016-02-25 16:12:50 -05:00
2016-10-25 21:34:47 +02:00
for ( var x = 29 ; x >= 0 ; x -- ) {
2016-10-13 11:42:29 +02:00
tmpDate = new Date ( currentDay - ( 1000 * 60 * 60 * 24 * x ) ) ;
2016-02-25 16:12:50 -05:00
labels . push ( months [ tmpDate . getMonth ( ) ] + ' ' + tmpDate . getDate ( ) ) ;
}
return labels ;
} ,
2016-03-27 15:52:26 -04:00
/* Retrieved from http://stackoverflow.com/a/7557433 @ 27 Mar 2016 */
2016-10-13 11:43:39 +02:00
isElementInViewport : function ( el ) {
2016-03-27 15:52:26 -04:00
//special bonus for those using jQuery
if ( typeof jQuery === "function" && el instanceof jQuery ) {
el = el [ 0 ] ;
}
var rect = el . getBoundingClientRect ( ) ;
return (
rect . top >= 0 &&
rect . left >= 0 &&
rect . bottom <= ( window . innerHeight || document . documentElement . clientHeight ) && /*or $(window).height() */
rect . right <= ( window . innerWidth || document . documentElement . clientWidth ) /*or $(window).width() */
) ;
} ,
2014-05-16 01:38:47 -04:00
// get all the url params in a single key/value hash
2016-10-13 11:43:39 +02:00
params : function ( options ) {
2017-02-17 20:20:42 -07:00
var a ;
var hash = { } ;
var params ;
2014-05-16 01:38:47 -04:00
options = options || { } ;
options . skipToType = options . skipToType || { } ;
if ( options . url ) {
a = utils . urlToLocation ( options . url ) ;
}
params = ( a ? a . search : window . location . search ) . substring ( 1 ) . split ( "&" ) ;
2016-10-13 11:43:39 +02:00
params . forEach ( function ( param ) {
2017-02-17 20:20:42 -07:00
var val = param . split ( '=' ) ;
var key = decodeURI ( val [ 0 ] ) ;
var value = options . skipToType [ key ] ? decodeURI ( val [ 1 ] ) : utils . toType ( decodeURI ( val [ 1 ] ) ) ;
2014-05-16 01:38:47 -04:00
2015-01-19 10:39:44 -05:00
if ( key ) {
2015-02-19 16:11:23 -05:00
if ( key . substr ( - 2 , 2 ) === '[]' ) {
key = key . slice ( 0 , - 2 ) ;
}
2015-02-05 14:55:36 -05:00
if ( ! hash [ key ] ) {
hash [ key ] = value ;
2015-03-12 13:26:29 -04:00
} else {
2015-02-05 14:55:36 -05:00
if ( ! $ . isArray ( hash [ key ] ) ) {
hash [ key ] = [ hash [ key ] ] ;
}
hash [ key ] . push ( value ) ;
}
2015-01-19 10:39:44 -05:00
}
2014-05-16 01:38:47 -04:00
} ) ;
return hash ;
} ,
2016-10-13 11:43:39 +02:00
param : function ( key ) {
2014-05-16 01:38:47 -04:00
return this . params ( ) [ key ] ;
} ,
2016-10-13 11:43:39 +02:00
urlToLocation : function ( url ) {
2014-05-16 01:38:47 -04:00
var a = document . createElement ( 'a' ) ;
a . href = url ;
return a ;
} ,
// return boolean if string 'true' or string 'false', or if a parsable string which is a number
// also supports JSON object and/or arrays parsing
2016-10-13 11:43:39 +02:00
toType : function ( str ) {
2014-05-16 01:38:47 -04:00
var type = typeof str ;
if ( type !== 'string' ) {
return str ;
} else {
var nb = parseFloat ( str ) ;
2015-01-19 10:39:44 -05:00
if ( ! isNaN ( nb ) && isFinite ( str ) ) {
2014-05-16 01:38:47 -04:00
return nb ;
2015-01-19 10:39:44 -05:00
}
if ( str === 'false' ) {
2014-05-16 01:38:47 -04:00
return false ;
2015-01-19 10:39:44 -05:00
}
if ( str === 'true' ) {
2014-05-16 01:38:47 -04:00
return true ;
2015-01-19 10:39:44 -05:00
}
2014-05-16 01:38:47 -04:00
try {
str = JSON . parse ( str ) ;
} catch ( e ) { }
return str ;
}
} ,
// Safely get/set chained properties on an object
// set example: utils.props(A, 'a.b.c.d', 10) // sets A to {a: {b: {c: {d: 10}}}}, and returns 10
// get example: utils.props(A, 'a.b.c') // returns {d: 10}
// get example: utils.props(A, 'a.b.c.foo.bar') // returns undefined without throwing a TypeError
// credits to github.com/gkindel
2016-10-13 11:43:39 +02:00
props : function ( obj , props , value ) {
2015-01-19 10:39:44 -05:00
if ( obj === undefined ) {
2014-05-16 01:38:47 -04:00
obj = window ;
2015-01-19 10:39:44 -05:00
}
if ( props == null ) {
2014-05-16 01:38:47 -04:00
return undefined ;
2015-01-19 10:39:44 -05:00
}
2014-05-16 01:38:47 -04:00
var i = props . indexOf ( '.' ) ;
if ( i == - 1 ) {
2015-01-19 10:39:44 -05:00
if ( value !== undefined ) {
2014-05-16 01:38:47 -04:00
obj [ props ] = value ;
2015-01-19 10:39:44 -05:00
}
2014-05-16 01:38:47 -04:00
return obj [ props ] ;
}
2017-02-17 20:20:42 -07:00
var prop = props . slice ( 0 , i ) ;
var newProps = props . slice ( i + 1 ) ;
2014-05-16 01:38:47 -04:00
2015-01-19 10:39:44 -05:00
if ( props !== undefined && ! ( obj [ prop ] instanceof Object ) ) {
2014-05-16 01:38:47 -04:00
obj [ prop ] = { } ;
2015-01-19 10:39:44 -05:00
}
2014-05-16 01:38:47 -04:00
2014-05-24 10:21:20 -04:00
return utils . props ( obj [ prop ] , newProps , value ) ;
2016-08-22 16:24:28 -04:00
} ,
2016-10-13 11:43:39 +02:00
isInternalURI : function ( targetLocation , referenceLocation , relative _path ) {
2016-08-22 16:24:28 -04:00
return targetLocation . host === '' || // Relative paths are always internal links
(
targetLocation . host === referenceLocation . host && targetLocation . protocol === referenceLocation . protocol && // Otherwise need to check if protocol and host match
( relative _path . length > 0 ? targetLocation . pathname . indexOf ( relative _path ) === 0 : true ) // Subfolder installs need this additional check
) ;
2017-02-17 19:31:21 -07:00
} ,
2013-10-28 23:33:37 +02:00
} ;
2013-05-23 13:21:38 -04:00
2017-02-17 22:31:05 -07:00
if ( typeof String . prototype . startsWith !== 'function' ) {
2016-10-25 21:34:47 +02:00
String . prototype . startsWith = function ( prefix ) {
2015-01-19 10:39:44 -05:00
if ( this . length < prefix . length ) {
2014-09-06 23:57:51 -04:00
return false ;
2015-01-19 10:39:44 -05:00
}
2017-02-17 22:31:05 -07:00
return this . slice ( 0 , prefix . length ) === prefix ;
2014-09-06 23:57:51 -04:00
} ;
2015-03-20 19:42:59 -04:00
}
2015-03-20 19:36:18 -04:00
2017-02-17 22:31:05 -07:00
if ( typeof String . prototype . endsWith !== 'function' ) {
2016-10-13 11:43:39 +02:00
String . prototype . endsWith = function ( suffix ) {
2015-03-20 19:36:18 -04:00
if ( this . length < suffix . length ) {
return false ;
}
2017-02-17 22:31:05 -07:00
if ( suffix . length === 0 ) {
return true ;
2015-03-20 19:36:18 -04:00
}
2017-02-17 22:31:05 -07:00
return this . slice ( - suffix . length ) === suffix ;
2015-03-20 19:36:18 -04:00
} ;
2014-09-06 23:57:51 -04:00
}
2017-02-17 22:31:05 -07:00
if ( typeof String . prototype . rtrim !== 'function' ) {
2016-10-13 11:43:39 +02:00
String . prototype . rtrim = function ( ) {
2015-10-14 16:00:45 -04:00
return this . replace ( /\s+$/g , '' ) ;
} ;
}
2013-05-23 13:21:38 -04:00
if ( 'undefined' !== typeof window ) {
window . utils = module . exports ;
}
2016-10-13 11:40:10 +02:00
} ( 'undefined' === typeof module ? {
2013-09-17 13:04:40 -04:00
module : {
2017-02-17 19:31:21 -07:00
exports : { } ,
} ,
2016-10-13 11:40:10 +02:00
} : module ) ) ;