├── .babelrc ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .prettierignore ├── .travis.yml ├── LICENSE ├── README.md ├── README_ZH.md ├── config ├── banner.js ├── const.js ├── rollup │ ├── dist │ │ ├── umd-min.js │ │ └── umd.js │ └── module │ │ ├── cjs-all.js │ │ ├── es-all.js │ │ ├── es.js │ │ └── umd.js └── webpack.config.js ├── dist ├── bbo.js ├── bbo.min.js └── bbo.min.js.map ├── jest.config.js ├── package.json ├── prettier.config.js ├── src ├── args │ ├── args.js │ ├── call.js │ ├── has_own_property.js │ ├── merge.js │ ├── noop.js │ └── over.js ├── array │ ├── all.js │ ├── all_equal.js │ ├── any.js │ ├── chunk.js │ ├── column.js │ ├── compact.js │ ├── contains.js │ ├── copy_array.js │ ├── count_by.js │ ├── count_occurrences.js │ ├── difference.js │ ├── difference_by.js │ ├── drop.js │ ├── drop_right.js │ ├── drop_right_while.js │ ├── drop_while.js │ ├── equal.js │ ├── includes_all.js │ ├── includes_any.js │ ├── index_by.js │ ├── intersect.js │ ├── intersect_by.js │ ├── max.js │ ├── min.js │ ├── pluck.js │ ├── random.js │ ├── random_size.js │ ├── remove.js │ ├── remove_at.js │ ├── shuffle.js │ ├── split.js │ ├── unary.js │ ├── union.js │ ├── union_by.js │ ├── union_with.js │ ├── unique.js │ ├── unique_by.js │ └── unique_from.js ├── behavior │ ├── copy_to_clipboard.js │ ├── lock_touch.js │ └── trigger.js ├── bom │ ├── attr.js │ ├── c.js │ ├── element_contains.js │ ├── g.js │ ├── gc.js │ ├── get_style.js │ ├── hide.js │ ├── open.js │ ├── query.js │ ├── set_style.js │ ├── show.js │ └── stop_propagation.js ├── chain │ ├── chain.js │ └── wrapper.js ├── collection │ ├── clone.js │ ├── entries.js │ ├── extend.js │ ├── flush.js │ ├── search.js │ ├── size.js │ └── values.js ├── cookie │ ├── cookie.js │ ├── delete_cookie.js │ ├── get_cookie.js │ ├── parse_cookie.js │ └── set_cookie.js ├── device │ ├── ie_version.js │ ├── is_android.js │ ├── is_ie.js │ ├── is_ios.js │ ├── is_ipad.js │ ├── is_iphone.js │ ├── is_iphonex_model.js │ ├── is_mobile.js │ ├── is_news_app.js │ ├── is_pc.js │ ├── is_qq.js │ ├── is_qq_browser.js │ ├── is_tenvideo.js │ ├── is_weishi.js │ ├── is_weixin.js │ └── ua.js ├── fill │ ├── chain_async.js │ ├── fill0.js │ ├── floor.js │ ├── modulo.js │ └── number_format.js ├── functions.js ├── http │ ├── delete_url_param.js │ ├── get_url_param.js │ ├── http_get.js │ ├── http_post.js │ ├── is_absolute_url.js │ ├── object_param.js │ └── set_url_param.js ├── index.js ├── json │ ├── jsonp.js │ └── to_json.js ├── lodash │ ├── debounce.js │ ├── find.js │ ├── find_index.js │ ├── for_each.js │ ├── get.js │ ├── get_tag.js │ ├── has.js │ ├── is.js │ ├── is_array.js │ ├── is_boolean.js │ ├── is_date.js │ ├── is_empty.js │ ├── is_function.js │ ├── is_map.js │ ├── is_nil.js │ ├── is_number.js │ ├── is_object.js │ ├── is_set.js │ ├── is_shallow_equal.js │ ├── is_string.js │ ├── is_symbol.js │ ├── map.js │ ├── map_values.js │ ├── omit.js │ ├── pick.js │ ├── reduce.js │ ├── set.js │ ├── string_to_path.js │ ├── throttle.js │ └── to_path.js ├── object │ ├── added_diff.js │ ├── deleted_diff.js │ ├── detailed_diff.js │ ├── object_diff.js │ ├── proper_object.js │ └── updated_diff.js ├── other │ ├── construct.js │ ├── get_type.js │ ├── hash.js │ ├── is_typeof.js │ ├── judge.js │ ├── log.js │ ├── params_name.js │ └── uuid.js ├── random │ ├── random_a2b.js │ ├── random_color.js │ └── random_key.js ├── string │ ├── byte_len.js │ ├── byte_size.js │ ├── camelize.js │ ├── capitalize.js │ ├── capwords.js │ ├── contains_with.js │ ├── dasherize.js │ ├── de_capitalize.js │ ├── effort_Index.js │ ├── ends_with.js │ ├── fill_zero.js │ ├── long_unique.js │ ├── map_string.js │ ├── mask.js │ ├── repeat.js │ ├── split_lines.js │ ├── starts_with.js │ ├── strip_tags.js │ ├── trim.js │ ├── truncate.js │ ├── underscored.js │ └── xss_filter.js ├── times │ ├── clear_timesout.js │ ├── format_duration.js │ ├── format_pass_time.js │ ├── format_remain_time.js │ ├── get_date.js │ ├── retry.js │ ├── set_timesout.js │ └── sleep.js └── util │ ├── get_global.js │ ├── no_conflict.js │ └── version.js └── test ├── args ├── args.js ├── call.js ├── has_own_property.js ├── merge.js ├── noop.js └── over.js ├── array ├── all.js ├── all_equal.js ├── any.js ├── chunk.js ├── column.js ├── compact.js ├── contains.js ├── copy_array.js ├── count_by.js ├── count_occurrences.js ├── difference.js ├── difference_by.js ├── drop.js ├── dropWhile.js ├── drop_right.js ├── drop_right_while.js ├── equal.js ├── includes_all.js ├── includes_any.js ├── index_by.js ├── intersect.js ├── intersect_by.js ├── max.js ├── min.js ├── pluck.js ├── random.js ├── random_size.js ├── remove.js ├── remove_at.js ├── shuffle.js ├── split.js ├── unary.js ├── union.js ├── union_by.js ├── union_with.js ├── unique.js ├── unique_by.js └── unique_from.js ├── bbo.js ├── behavior ├── copy_to_clipboard.js ├── lock_touch.js └── trigger.js ├── bom ├── attr.js ├── c.js ├── element_contains.js ├── g.js ├── gc.js ├── get_style.js ├── hide.js ├── open.js ├── query.js ├── set_style.js ├── show.js └── stop_propagation.js ├── chain └── chain.js ├── collection ├── clone.js ├── entries.js ├── extend.js ├── flush.js ├── search.js ├── size.js └── values.js ├── const.js ├── cookie ├── cookie.js ├── delete_cookie.js ├── get_cookie.js ├── parse_cookie.js └── set_cookie.js ├── device ├── ie_version.js ├── is_android.js ├── is_ie.js ├── is_ios.js ├── is_ipad.js ├── is_iphone.js ├── is_iphonex_model.js ├── is_mobile.js ├── is_news_app.js ├── is_pc.js ├── is_qq.js ├── is_qq_browser.js ├── is_tenvideo.js ├── is_weishi.js └── is_weixin.js ├── fill ├── chain_async.js ├── fill0.js ├── floor.js ├── modulo.js └── number_format.js ├── http ├── delete_url_param.js ├── get_url_param.js ├── http_get.js ├── http_post.js ├── is_absolute_url.js ├── object_param.js └── set_url_param.js ├── index.js ├── json ├── jsonp.js └── to_json.js ├── lodash ├── debounce.js ├── find.js ├── find_index.js ├── for_each.js ├── get.js ├── get_tag.js ├── has.js ├── is.js ├── is_array.js ├── is_boolean.js ├── is_date.js ├── is_empty.js ├── is_function.js ├── is_map.js ├── is_nil.js ├── is_number.js ├── is_object.js ├── is_set.js ├── is_shallow_equal.js ├── is_string.js ├── is_symbol.js ├── map.js ├── map_values.js ├── omit.js ├── pick.js ├── reduce.js ├── set.js ├── throttle.js └── to_path.js ├── object ├── added_diff.js ├── deleted_diff.js ├── detailed_diff.js ├── object_diff.js ├── proper_object.js └── updated_diff.js ├── other ├── construct.js ├── get_type.js ├── hash.js ├── is_typeof.js ├── judge.js ├── log.js └── uuid.js ├── random ├── random_a2b.js ├── random_color.js └── random_key.js ├── string ├── byte_len.js ├── byte_size.js ├── camelize.js ├── capitalize.js ├── capwords.js ├── contains_with.js ├── dasherize.js ├── de_capitalize.js ├── effort_Index.js ├── ends_with.js ├── fill_zero.js ├── long_unique.js ├── map_string.js ├── mask.js ├── repeat.js ├── split_lines.js ├── starts_with.js ├── strip_tags.js ├── trim.js ├── truncate.js ├── underscored.js └── xss_filter.js ├── times ├── clear_timesout.js ├── format_duration.js ├── format_pass_time.js ├── format_remain_time.js ├── get_date.js ├── retry.js ├── set_timesout.js └── sleep.js └── util ├── no_conflict.js └── version.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@babel/plugin-transform-object-assign", 4 | "@babel/plugin-transform-block-scoping", 5 | "@babel/plugin-transform-parameters", 6 | "@babel/plugin-transform-shorthand-properties", 7 | "@babel/plugin-transform-spread", 8 | "@babel/plugin-transform-destructuring", 9 | [ 10 | "module-resolver", 11 | { 12 | "root": ["./src"] 13 | } 14 | ] 15 | ], 16 | "env": { 17 | "test": { 18 | "plugins": [["@babel/plugin-transform-modules-commonjs"]] 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/*.js 3 | dist_mod/ 4 | docs/ -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | // https://github.com/AlloyTeam/eslint-config-alloy 4 | 'alloy' 5 | ], 6 | globals: { 7 | window: false, 8 | define: true, 9 | bbo: false, 10 | jest: false 11 | }, 12 | rules: { 13 | indent: [ 14 | 'error', 15 | 2, 16 | { 17 | SwitchCase: 1, 18 | flatTernaryExpressions: true 19 | } 20 | ], 21 | semi: 0, 22 | complexity: [ 23 | 'error', 24 | { 25 | max: 30 26 | } 27 | ] 28 | }, 29 | overrides: [ 30 | { 31 | files: ['test/**/*.js'], 32 | env: { jest: true } 33 | } 34 | ] 35 | }; 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea/ 3 | .ipr 4 | .iws 5 | *~ 6 | ~* 7 | *.diff 8 | *.patch 9 | *.bak 10 | .DS_Store 11 | Thumbs.db 12 | .svn/ 13 | *.swp 14 | .nojekyll 15 | .project 16 | .settings/ 17 | node_modules/ 18 | site/ 19 | .vscode/ 20 | node_modules/ 21 | npm-debug.log 22 | .npmrc 23 | package-lock.json 24 | .idea 25 | node_modules 26 | coverage 27 | npm-debug.log 28 | docs 29 | .tern-project 30 | .codecov.yml 31 | dist_mod/ 32 | test_runner/test_bundle.js 33 | development/ 34 | /development -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /dist_mod 3 | /node_modules 4 | /docs 5 | /.vscode 6 | /coverage 7 | node_modules 8 | .eslintrc.js 9 | package.json 10 | package-lock.json -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | branches: 3 | only: 4 | - master 5 | notifications: 6 | email: false 7 | matrix: 8 | include: 9 | - node_js: '10' 10 | before_script: 11 | - npm prune 12 | script: 13 | - npm run coverage 14 | - npm run eslint 15 | - npm run build 16 | after_success: 17 | - bash <(curl -s https://codecov.io/bash) 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c)2013 - 2021 halldwang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /config/banner.js: -------------------------------------------------------------------------------- 1 | import pack from '../package.json'; 2 | 3 | export default `/* 4 | * bbo 5 | * bbo is a utility library of zero dependencies for javascript. 6 | * (c) 2011 - 2021 7 | * https://github.com/tnfe/bbo.git 8 | * version ${pack.version} 9 | */ 10 | `; 11 | -------------------------------------------------------------------------------- /config/const.js: -------------------------------------------------------------------------------- 1 | export const SRC = 'src'; 2 | export const DIST_MODULE_CJS = 'dist_mod'; 3 | export const DIST_MODULE_ES = 'dist_mod/es'; 4 | export const DIST_UNIVERSAL = 'dist'; 5 | -------------------------------------------------------------------------------- /config/rollup/dist/umd-min.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | 3 | import banner from '../../banner'; 4 | import { terser } from 'rollup-plugin-terser'; 5 | import { DIST_UNIVERSAL, SRC } from '../../const'; 6 | 7 | export default { 8 | input: `${SRC}/index.js`, 9 | plugins: [babel(), terser()], 10 | output: { 11 | file: `${DIST_UNIVERSAL}/bbo.min.js`, 12 | format: 'umd', 13 | name: 'bbo', 14 | sourcemap: true, 15 | banner: banner 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /config/rollup/dist/umd.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import banner from '../../banner'; 3 | 4 | import { DIST_UNIVERSAL, SRC } from '../../const'; 5 | 6 | export default { 7 | input: `${SRC}/index.js`, 8 | plugins: [babel()], 9 | output: { 10 | file: `${DIST_UNIVERSAL}/bbo.js`, 11 | format: 'umd', 12 | name: 'bbo', 13 | sourcemap: false, 14 | banner: banner 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /config/rollup/module/cjs-all.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import glob from 'glob'; 3 | 4 | import { DIST_MODULE_CJS, SRC } from '../../const'; 5 | 6 | function modulesPaths() { 7 | const paths = glob.sync(SRC + '/*/*.js', { 8 | ignore: [SRC + '/chain/*.js', SRC + '/util/**/*.js', SRC + '/functions.js', SRC + '/index.js'] 9 | }); 10 | return paths; 11 | } 12 | 13 | export default { 14 | input: modulesPaths(), 15 | plugins: [babel()], 16 | output: { 17 | dir: DIST_MODULE_CJS, 18 | format: 'cjs', 19 | chunkFileNames: 'internal/[name].js' 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /config/rollup/module/es-all.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import glob from 'glob'; 3 | 4 | import { DIST_MODULE_ES, SRC } from '../../const'; 5 | 6 | function modulesPaths() { 7 | const paths = glob.sync(SRC + '/*/*.js', { 8 | ignore: [SRC + '/chain/*.js', SRC + '/util/**/*.js', SRC + '/functions.js', SRC + '/index.js'] 9 | }); 10 | return paths; 11 | } 12 | 13 | export default { 14 | input: modulesPaths(), 15 | plugins: [babel()], 16 | 17 | output: { 18 | dir: DIST_MODULE_ES, 19 | format: 'es', 20 | chunkFileNames: 'internal/[name].js' 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /config/rollup/module/es.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import banner from '../../banner'; 3 | 4 | import { DIST_MODULE_ES, SRC } from '../../const'; 5 | 6 | export default { 7 | input: `${SRC}/index.js`, 8 | plugins: [babel()], 9 | output: { 10 | file: `${DIST_MODULE_ES}/index.js`, 11 | format: 'es', 12 | name: 'bbo', 13 | sourcemap: false, 14 | banner: banner 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /config/rollup/module/umd.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import banner from '../../banner'; 3 | 4 | import { DIST_MODULE_CJS, SRC } from '../../const'; 5 | 6 | export default { 7 | input: `${SRC}/index.js`, 8 | plugins: [babel()], 9 | output: { 10 | file: `${DIST_MODULE_CJS}/index.js`, 11 | format: 'umd', 12 | name: 'bbo', 13 | sourcemap: false, 14 | banner: banner 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /config/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 2 | module.exports = { 3 | mode: 'development', 4 | entry: { 5 | index: './development/index' 6 | }, 7 | module: { 8 | rules: [ 9 | { 10 | test: /\.css$/, 11 | use: [ 12 | { 13 | loader: 'css-loader' 14 | } 15 | ] 16 | } 17 | ] 18 | }, 19 | plugins: [ 20 | new HtmlWebpackPlugin({ 21 | template: './development/index.html' 22 | }) 23 | ], 24 | devtool: 'source-map', 25 | devServer: { 26 | disableHostCheck: true 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | verbose: true, 3 | modulePaths: ['/src/'], 4 | collectCoverageFrom: ['src/**/*.js'], 5 | testMatch: ['/test/*/*.js'], 6 | testURL: 'http://localhost', 7 | testPathIgnorePatterns: ['node_modules', '.cache'], 8 | transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|ts|tsx)$'], 9 | moduleFileExtensions: ['js', 'json'], 10 | coverageThreshold: { 11 | global: { 12 | statements: 80, 13 | branches: 80, 14 | functions: 80, 15 | lines: 80 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 2, 4 | useTabs: false, 5 | semi: true, 6 | singleQuote: true, 7 | quoteProps: 'as-needed', 8 | jsxSingleQuote: false, 9 | trailingComma: 'none', 10 | bracketSpacing: true, 11 | jsxBracketSameLine: false, 12 | arrowParens: 'always', 13 | rangeStart: 0, 14 | rangeEnd: Infinity, 15 | requirePragma: false, 16 | insertPragma: false, 17 | proseWrap: 'preserve', 18 | htmlWhitespaceSensitivity: 'css', 19 | endOfLine: 'lf' 20 | }; 21 | -------------------------------------------------------------------------------- /src/args/args.js: -------------------------------------------------------------------------------- 1 | /** 2 | * arguments to array 3 | */ 4 | 5 | /** 6 | * Converts the arguments object to an array object and slice it. 7 | * first defalult is 0. 8 | * @export 9 | * @param {*} $arguments 10 | * @param {*} first 11 | * @returns 12 | */ 13 | export default function args($arguments, first) { 14 | return Array.prototype.slice.call($arguments, first || 0); 15 | } 16 | -------------------------------------------------------------------------------- /src/args/call.js: -------------------------------------------------------------------------------- 1 | const call = (key, ...args) => (context) => context[key](...args); 2 | 3 | export default call; 4 | -------------------------------------------------------------------------------- /src/args/has_own_property.js: -------------------------------------------------------------------------------- 1 | export default function hasOwnProperty(obj, keyName) { 2 | return Object.prototype.hasOwnProperty.call(obj, keyName); 3 | } 4 | -------------------------------------------------------------------------------- /src/args/merge.js: -------------------------------------------------------------------------------- 1 | const merge = (...objs) => 2 | [...objs].reduce( 3 | (acc, obj) => 4 | Object.keys(obj).reduce((a, k) => { 5 | acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k]; 6 | return acc; 7 | }, {}), 8 | {} 9 | ); 10 | 11 | export default merge; 12 | -------------------------------------------------------------------------------- /src/args/noop.js: -------------------------------------------------------------------------------- 1 | const noop = () => {}; 2 | 3 | export default noop; 4 | -------------------------------------------------------------------------------- /src/args/over.js: -------------------------------------------------------------------------------- 1 | const over = (...fns) => (...args) => fns.map((fn) => fn.apply(null, args)); 2 | 3 | export default over; 4 | -------------------------------------------------------------------------------- /src/array/all.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns true if the provided predicate function returns true for all elements in a collection, false otherwise. 3 | */ 4 | const all = (arr, fn = Boolean) => arr.every(fn); 5 | 6 | export default all; 7 | -------------------------------------------------------------------------------- /src/array/all_equal.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check if all elements in an array are equal. 3 | */ 4 | const allEqual = (arr) => arr.every((val) => val === arr[0]); 5 | 6 | export default allEqual; 7 | -------------------------------------------------------------------------------- /src/array/any.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns true if the provided predicate function returns true for at least one element in a collection,false otherwise. 3 | */ 4 | const any = (arr, fn = Boolean) => arr.some(fn); 5 | 6 | export default any; 7 | -------------------------------------------------------------------------------- /src/array/chunk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Chunks an array into smaller arrays of a specified size. 3 | */ 4 | const chunk = (arr, size) => { 5 | return Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => 6 | arr.slice(i * size, i * size + size) 7 | ); 8 | }; 9 | 10 | export default chunk; 11 | -------------------------------------------------------------------------------- /src/array/column.js: -------------------------------------------------------------------------------- 1 | /** 2 | * discuss at: https://locutus.io/php/array_column/ 3 | */ 4 | import isObject from '../lodash/is_object'; 5 | import isArray from '../lodash/is_array'; 6 | 7 | export default function column(input, ColumnKey, IndexKey = null) { 8 | if (input !== null && (isObject(input) || isArray(input))) { 9 | let newarray = []; 10 | if (isObject(input)) { 11 | let temparray = []; 12 | for (let key of Object.keys(input)) { 13 | temparray.push(input[key]); 14 | } 15 | // eslint-disable-next-line no-param-reassign 16 | input = temparray; 17 | } 18 | if (isArray(input)) { 19 | for (let key of input.keys()) { 20 | if (IndexKey && input[key][IndexKey]) { 21 | if (ColumnKey) { 22 | newarray[input[key][IndexKey]] = input[key][ColumnKey]; 23 | } else { 24 | newarray[input[key][IndexKey]] = input[key]; 25 | } 26 | } else { 27 | if (ColumnKey) { 28 | newarray.push(input[key][ColumnKey]); 29 | } else { 30 | newarray.push(input[key]); 31 | } 32 | } 33 | } 34 | } 35 | // eslint-disable-next-line prefer-object-spread 36 | return Object.assign({}, newarray); 37 | } else { 38 | throw new Error('throw an error'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/array/compact.js: -------------------------------------------------------------------------------- 1 | /** 2 | * returns a copy of an array with falsey values removed 3 | */ 4 | 5 | import isArray from '../lodash/is_array'; 6 | 7 | export default function compact(arr) { 8 | if (!isArray(arr)) { 9 | throw new Error('expected an array'); 10 | } 11 | let result = []; 12 | let len = arr.length; 13 | for (let i = 0; i < len; i++) { 14 | let elem = arr[i]; 15 | if (elem) { 16 | result.push(elem); 17 | } 18 | } 19 | return result; 20 | } 21 | -------------------------------------------------------------------------------- /src/array/contains.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns true if the element has the specified Array, false otherwise. 3 | */ 4 | export default function contains(target, item) { 5 | return target.indexOf(item) > -1; 6 | } 7 | -------------------------------------------------------------------------------- /src/array/copy_array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copies the values of `source` to `array`. 3 | * 4 | * @private 5 | * @param {Array} source The array to copy values from. 6 | * @param {Array} [array=[]] The array to copy values to. 7 | * @returns {Array} Returns `array`. 8 | */ 9 | function copyArray(source, array) { 10 | let index = -1; 11 | const length = source.length; 12 | 13 | // eslint-disable-next-line no-param-reassign 14 | array || (array = new Array(length)); 15 | while (++index < length) { 16 | array[index] = source[index]; 17 | } 18 | return array; 19 | } 20 | 21 | export default copyArray; 22 | -------------------------------------------------------------------------------- /src/array/count_by.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Groups the elements of an array based on the given function and returns the count of elements in each group. 3 | */ 4 | 5 | import isFunction from '../lodash/is_function'; 6 | 7 | const countBy = (arr, fn) => { 8 | return arr.map(isFunction(fn) ? fn : (val) => val[fn]).reduce((acc, val) => { 9 | acc[val] = (acc[val] || 0) + 1; 10 | return acc; 11 | }, {}); 12 | }; 13 | 14 | export default countBy; 15 | -------------------------------------------------------------------------------- /src/array/count_occurrences.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Counts the occurrences of a value in an array. 3 | */ 4 | const countOccurrences = (arr, val) => { 5 | return arr.reduce((a, v) => (v === val ? a + 1 : a), 0); 6 | }; 7 | 8 | export default countOccurrences; 9 | -------------------------------------------------------------------------------- /src/array/difference.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the difference between two arrays. 3 | * Create a Set from b, then use Array.prototype. 4 | * Filter() on a to only keep values not contained in b. 5 | */ 6 | export default function difference(a, b) { 7 | const s = new Set(b); 8 | return a.filter((x) => !s.has(x)); 9 | } 10 | -------------------------------------------------------------------------------- /src/array/difference_by.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the difference between two arrays, 3 | * after applying the provided function to each array element of both. 4 | */ 5 | export default function differenceBy(a, b, fn) { 6 | const s = new Set(b.map(fn)); 7 | return a.map(fn).filter((el) => !s.has(el)); 8 | } 9 | -------------------------------------------------------------------------------- /src/array/drop.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a new array with n elements removed from the left. 3 | */ 4 | const drop = (arr, n = 1) => arr.slice(n); 5 | 6 | export default drop; 7 | -------------------------------------------------------------------------------- /src/array/drop_right.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a new array with n elements removed from the right. 3 | */ 4 | const dropRight = (arr, n = 1) => arr.slice(0, -n); 5 | 6 | export default dropRight; 7 | -------------------------------------------------------------------------------- /src/array/drop_right_while.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Removes elements from the end of an array until the passed function returns true, 3 | * Returns the remaining elements in the array. 4 | */ 5 | 6 | import size from '../collection/size'; 7 | 8 | export default function dropRightWhile(arr, func) { 9 | let rightIndex = size(arr); 10 | while (rightIndex-- && !func(arr[rightIndex])); 11 | return arr.slice(0, rightIndex + 1); 12 | } 13 | -------------------------------------------------------------------------------- /src/array/drop_while.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Removes elements in an array until the passed function returns true. 3 | * Returns the remaining elements in the array. 4 | */ 5 | export default function dropWhile(arr, func) { 6 | let _arr = arr; 7 | while (_arr.length > 0 && !func(_arr[0])) _arr = _arr.slice(1); 8 | return _arr; 9 | } 10 | -------------------------------------------------------------------------------- /src/array/equal.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check two arrays are equal 3 | */ 4 | import size from '../collection/size'; 5 | export default function equal(arr1, arr2) { 6 | let length = size(arr1); 7 | if (length !== size(arr2)) return false; 8 | for (let i = 0; i < length; i++) if (arr1[i] !== arr2[i]) return false; 9 | return true; 10 | } 11 | -------------------------------------------------------------------------------- /src/array/includes_all.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns true if all the elements values are included in arr, false otherwise. 3 | */ 4 | const includesAll = (arr, values) => values.every((v) => arr.includes(v)); 5 | 6 | export default includesAll; 7 | -------------------------------------------------------------------------------- /src/array/includes_any.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns true if at least one element of values is included in arr , false otherwise. 3 | */ 4 | const includesAny = (arr, values) => values.some((v) => arr.includes(v)); 5 | 6 | export default includesAny; 7 | -------------------------------------------------------------------------------- /src/array/index_by.js: -------------------------------------------------------------------------------- 1 | /** 2 | * return an object from an array, keyed by the value at the given id 3 | */ 4 | 5 | import isArray from '../lodash/is_array'; 6 | import isString from '../lodash/is_string'; 7 | 8 | export default function indexBy(arr, key) { 9 | if (!isArray(arr)) { 10 | throw new Error('expected an array for first argument'); 11 | } 12 | if (!isString(key)) { 13 | throw new Error('expected a string for second argument'); 14 | } 15 | let result = {}; 16 | let len = arr.length; 17 | for (let i = 0; i < len; i++) { 18 | let index = arr[i] && arr[i][key]; 19 | 20 | if (index) { 21 | result[index] = arr[i]; 22 | } 23 | } 24 | return result; 25 | } 26 | -------------------------------------------------------------------------------- /src/array/intersect.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a list of elements that exist in both arrays. 3 | */ 4 | export default function intersect(a, b) { 5 | const s = new Set(b); 6 | return a.filter((x) => s.has(x)); 7 | } 8 | -------------------------------------------------------------------------------- /src/array/intersect_by.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a list of elements that exist in both arrays, 3 | * after applying the provided function to each array element of both. 4 | */ 5 | export default function intersectBy(a, b, fn) { 6 | const s = new Set(b.map(fn)); 7 | return a.filter((x) => s.has(fn(x))); 8 | } 9 | -------------------------------------------------------------------------------- /src/array/max.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the largest element in an array 3 | */ 4 | export default function max(target) { 5 | return Math.max.apply(0, target); 6 | } 7 | -------------------------------------------------------------------------------- /src/array/min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the smallest element in an array 3 | */ 4 | export default function min(target) { 5 | return Math.min.apply(0, target); 6 | } 7 | -------------------------------------------------------------------------------- /src/array/pluck.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the attribute values in an array object and combine them into a new array 3 | */ 4 | export default function pluck(target, name) { 5 | let result = []; 6 | let temp; 7 | target.forEach(function(item) { 8 | if (item[name]) { 9 | temp = item[name]; 10 | result.push(temp); 11 | } 12 | }); 13 | return result; 14 | } 15 | -------------------------------------------------------------------------------- /src/array/random.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a random element from an array. 3 | */ 4 | const random = (arr) => arr[Math.floor(Math.random() * arr.length)]; 5 | 6 | export default random; 7 | -------------------------------------------------------------------------------- /src/array/random_size.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gets n random elements at unique keys from array up to the size of array. 3 | */ 4 | export default function randomSize([...arr], n = 1) { 5 | let m = arr.length; 6 | while (m) { 7 | const i = Math.floor(Math.random() * m--); 8 | [arr[m], arr[i]] = [arr[i], arr[m]]; 9 | } 10 | return arr.slice(0, n); 11 | } 12 | -------------------------------------------------------------------------------- /src/array/remove.js: -------------------------------------------------------------------------------- 1 | import isArray from '../lodash/is_array'; 2 | 3 | export default function remove(arr1, arr2) { 4 | if (!isArray(arr1) || !isArray(arr2)) { 5 | throw new Error('expected both arguments to be arrays'); 6 | } 7 | let result = []; 8 | let len = arr1.length; 9 | for (let i = 0; i < len; i++) { 10 | let elem = arr1[i]; 11 | if (arr2.indexOf(elem) === -1) { 12 | result.push(elem); 13 | } 14 | } 15 | return result; 16 | } 17 | -------------------------------------------------------------------------------- /src/array/remove_at.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Remove the element specified by parameter 2 in parameter 1 and return Boolean 3 | */ 4 | export default function removeAt(target, index) { 5 | return !!target.splice(index, 1).length; 6 | } 7 | -------------------------------------------------------------------------------- /src/array/shuffle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Randomizes the order of the values of an array, returning a new array. 3 | */ 4 | export default function shuffle([...arr]) { 5 | let m = arr.length; 6 | while (m) { 7 | const i = Math.floor(Math.random() * m--); 8 | [arr[m], arr[i]] = [arr[i], arr[m]]; 9 | } 10 | return arr; 11 | } 12 | -------------------------------------------------------------------------------- /src/array/split.js: -------------------------------------------------------------------------------- 1 | import isNumber from '../lodash/is_number'; 2 | import isArray from '../lodash/is_array'; 3 | 4 | export default function split(arr, n) { 5 | if (!isArray(arr)) { 6 | throw new Error('expected an array for the first argument'); 7 | } 8 | if (n !== null && !isNumber(n)) { 9 | throw new Error('expected a number or null for the second argument'); 10 | } 11 | // eslint-disable-next-line no-param-reassign 12 | n = n !== null ? n : arr.length; 13 | let len = arr.length; 14 | let groups = []; 15 | for (let i = 0; i < len; i += n) { 16 | groups.push(arr.slice(i, i + n)); 17 | } 18 | return groups; 19 | } 20 | -------------------------------------------------------------------------------- /src/array/unary.js: -------------------------------------------------------------------------------- 1 | const unary = (fn) => (val) => fn(val); 2 | 3 | export default unary; 4 | -------------------------------------------------------------------------------- /src/array/union.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns every element that exists in any of the two arrays once 3 | * Create a Set with all values of a and b and convert to an array. 4 | */ 5 | const union = (a, b) => Array.from(new Set([...a, ...b])); 6 | 7 | export default union; 8 | -------------------------------------------------------------------------------- /src/array/union_by.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns every element that exists in any of the two arrays once, 3 | * after applying the provided function to each array element of both. 4 | */ 5 | const unionBy = (a, b, fn) => { 6 | const s = new Set(a.map(fn)); 7 | return Array.from(new Set([...a, ...b.filter((x) => !s.has(fn(x)))])); 8 | }; 9 | 10 | export default unionBy; 11 | -------------------------------------------------------------------------------- /src/array/union_with.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns every element that exists in any of the two arrays once, 3 | * using a provided comparator function. 4 | */ 5 | const unionWith = (a, b, comp) => { 6 | return Array.from(new Set([...a, ...b.filter((x) => a.findIndex((y) => comp(x, y)) === -1)])); 7 | }; 8 | 9 | export default unionWith; 10 | -------------------------------------------------------------------------------- /src/array/unique.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns all unique values of an array. 3 | */ 4 | 5 | const unique = (arr) => [...new Set(arr)]; 6 | 7 | export default unique; 8 | -------------------------------------------------------------------------------- /src/array/unique_by.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns all unique values of an array, based on a provided comparator function. 3 | */ 4 | const uniqueBy = (arr, fn) => 5 | arr.reduce((acc, v) => { 6 | if (!acc.some((x) => fn(v, x))) acc.push(v); 7 | return acc; 8 | }, []); 9 | 10 | export default uniqueBy; 11 | -------------------------------------------------------------------------------- /src/array/unique_from.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Remove duplicates from an array of objects 3 | * https://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript 4 | */ 5 | export default function uniqueFrom(arr, target) { 6 | return Object.values(arr.reduce((acc, cur) => Object.assign(acc, { [cur[target]]: cur }), {})); 7 | } 8 | -------------------------------------------------------------------------------- /src/behavior/copy_to_clipboard.js: -------------------------------------------------------------------------------- 1 | import attr from '../bom/attr'; 2 | import setStyle from '../bom/set_style'; 3 | 4 | export default function copyToClipboard(str) { 5 | const el = document.createElement('textarea'); 6 | el.value = str; 7 | attr(el, 'readonly', ''); 8 | setStyle(el, 'position', 'absolute'); 9 | setStyle(el, 'left', '-9999px'); 10 | document.body.appendChild(el); 11 | const selected = 12 | document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; 13 | el.select(); 14 | document.execCommand('copy'); 15 | document.body.removeChild(el); 16 | if (selected) { 17 | document.getSelection().removeAllRanges(); 18 | document.getSelection().addRange(selected); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/behavior/lock_touch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * lock touch in mobile phone 3 | */ 4 | const lockTouch = () => { 5 | document.addEventListener( 6 | 'touchmove', 7 | function(e) { 8 | e.preventDefault(); 9 | }, 10 | !1 11 | ); 12 | document.addEventListener('touchstart', preventDefault, !1); 13 | document.addEventListener('touchend', preventDefault, !1); 14 | 15 | function not(e, tag) { 16 | return e.target.tagName !== tag.toUpperCase() && e.target.tagName !== tag.toLowerCase(); 17 | } 18 | 19 | function preventDefault(e) { 20 | if (not(e, 'input') && not(e, 'textarea') && not(e, 'select') && not(e, 'menus')) 21 | e.preventDefault(); 22 | } 23 | }; 24 | 25 | export default lockTouch; 26 | -------------------------------------------------------------------------------- /src/behavior/trigger.js: -------------------------------------------------------------------------------- 1 | /** 2 | * trigger event 3 | * https://stackoverflow.com/questions/2490825/how-to-trigger-event-in-javascript 4 | */ 5 | const trigger = (element, event, eventType) => { 6 | // delete document.createEventObject of ie 7 | let e = document.createEvent(eventType || 'HTMLEvents'); 8 | e.initEvent(event, true, true); 9 | element.dispatchEvent(e); 10 | }; 11 | 12 | export default trigger; 13 | -------------------------------------------------------------------------------- /src/bom/attr.js: -------------------------------------------------------------------------------- 1 | export default function attr(el, ruleName, val) { 2 | el.setAttribute(ruleName, val); 3 | } 4 | -------------------------------------------------------------------------------- /src/bom/c.js: -------------------------------------------------------------------------------- 1 | import attr from './attr'; 2 | 3 | // eslint-disable-next-line max-params 4 | export default function c(t, cn, i, id) { 5 | let el = document.createElement(t); 6 | if (cn) { 7 | attr(el, 'class', cn); 8 | } 9 | if (i) { 10 | el.innerHTML = i; 11 | } 12 | if (id) { 13 | attr(el, 'id', id); 14 | } 15 | return el; 16 | } 17 | -------------------------------------------------------------------------------- /src/bom/element_contains.js: -------------------------------------------------------------------------------- 1 | const elementContains = (parent, child) => parent !== child && parent.contains(child); 2 | 3 | export default elementContains; 4 | -------------------------------------------------------------------------------- /src/bom/g.js: -------------------------------------------------------------------------------- 1 | export default function g(i) { 2 | return document.getElementById(i); 3 | } 4 | -------------------------------------------------------------------------------- /src/bom/gc.js: -------------------------------------------------------------------------------- 1 | export default function gc(cn) { 2 | return document.getElementsByClassName(cn); 3 | } 4 | -------------------------------------------------------------------------------- /src/bom/get_style.js: -------------------------------------------------------------------------------- 1 | const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; 2 | 3 | export default getStyle; 4 | -------------------------------------------------------------------------------- /src/bom/hide.js: -------------------------------------------------------------------------------- 1 | const hide = (...el) => 2 | [...el].forEach((e) => { 3 | e.style.display = 'none'; 4 | }); 5 | 6 | export default hide; 7 | -------------------------------------------------------------------------------- /src/bom/open.js: -------------------------------------------------------------------------------- 1 | import setStyle from './set_style'; 2 | import attr from './attr'; 3 | import trigger from '../behavior/trigger'; 4 | import g from './g'; 5 | import c from './c'; 6 | 7 | /** 8 | * open new url dont not blocked by browser 9 | */ 10 | const open = (href) => { 11 | let id = '_bbo_open_proxy'; 12 | let a = g(id) || c('a', id, '', id); 13 | setStyle(a, 'display', 'none'); 14 | attr(a, 'href', href); 15 | attr(a, 'target', '_blank'); 16 | if (!a.parentNode) document.body.appendChild(a); 17 | trigger(a, 'click', 'MouseEvents'); 18 | }; 19 | 20 | export default open; 21 | -------------------------------------------------------------------------------- /src/bom/query.js: -------------------------------------------------------------------------------- 1 | export default function query(i) { 2 | return document.querySelector(i); 3 | } 4 | -------------------------------------------------------------------------------- /src/bom/set_style.js: -------------------------------------------------------------------------------- 1 | export default function setStyle(el, ruleName, val) { 2 | el.style[ruleName] = val; 3 | } 4 | -------------------------------------------------------------------------------- /src/bom/show.js: -------------------------------------------------------------------------------- 1 | const show = (...el) => 2 | [...el].forEach((e) => { 3 | e.style.display = ''; 4 | }); 5 | 6 | export default show; 7 | -------------------------------------------------------------------------------- /src/bom/stop_propagation.js: -------------------------------------------------------------------------------- 1 | const stopPropagation = (event) => { 2 | const e = event || window.event; 3 | const stop = e.stopPropagation ? e.stopPropagation() : (e.cancelBubble = true); 4 | return stop; 5 | }; 6 | 7 | export default stopPropagation; 8 | -------------------------------------------------------------------------------- /src/chain/chain.js: -------------------------------------------------------------------------------- 1 | import ChainWrapper from 'chain/wrapper'; 2 | 3 | export default function chain(subject) { 4 | return new ChainWrapper(subject, true); 5 | } 6 | -------------------------------------------------------------------------------- /src/collection/entries.js: -------------------------------------------------------------------------------- 1 | import isFunction from '../lodash/is_function'; 2 | import isObject from '../lodash/is_object'; 3 | 4 | export default function entries(obj) { 5 | if ((!isObject(obj) && !isFunction(obj)) || obj === null) { 6 | throw new Error('argument to `entries` must be an object'); 7 | } 8 | 9 | let result = []; 10 | for (let key in obj) { 11 | if (obj.hasOwnProperty(key)) { 12 | result.push([key, obj[key]]); 13 | } 14 | } 15 | return result; 16 | } 17 | -------------------------------------------------------------------------------- /src/collection/extend.js: -------------------------------------------------------------------------------- 1 | import isObject from '../lodash/is_object'; 2 | import isBoolean from '../lodash/is_boolean'; 3 | import isArray from '../lodash/is_array'; 4 | import isFunction from '../lodash/is_function'; 5 | 6 | export default function extend(/* [deep], obj1, obj2, [objn] */) { 7 | let args = [].slice.call(arguments); 8 | let deep = false; 9 | if (isBoolean(args[0])) { 10 | deep = args.shift(); 11 | } 12 | let result = args[0]; 13 | if (isUnextendable(result)) { 14 | throw new Error('extendee must be an object'); 15 | } 16 | let extenders = args.slice(1); 17 | let len = extenders.length; 18 | for (let i = 0; i < len; i++) { 19 | let extender = extenders[i]; 20 | for (let key in extender) { 21 | if (extender.hasOwnProperty(key)) { 22 | let value = extender[key]; 23 | if (deep && isCloneable(value)) { 24 | let base = isArray(value) ? [] : {}; 25 | result[key] = extend( 26 | true, 27 | result.hasOwnProperty(key) && !isUnextendable(result[key]) ? result[key] : base, 28 | value 29 | ); 30 | } else { 31 | result[key] = value; 32 | } 33 | } 34 | } 35 | } 36 | return result; 37 | } 38 | 39 | function isCloneable(obj) { 40 | return isArray(obj) || isObject(obj); 41 | } 42 | 43 | function isUnextendable(val) { 44 | return !val || (!isObject(val) && !isFunction(val)); 45 | } 46 | -------------------------------------------------------------------------------- /src/collection/flush.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable eqeqeq */ 2 | /* eslint-disable no-eq-null */ 3 | import isObject from '../lodash/is_object'; 4 | import isArray from '../lodash/is_array'; 5 | 6 | export default function flush(collection) { 7 | let result; 8 | let len; 9 | let i; 10 | if (!collection) { 11 | return undefined; 12 | } 13 | if (isArray(collection)) { 14 | result = []; 15 | len = collection.length; 16 | for (i = 0; i < len; i++) { 17 | let elem = collection[i]; 18 | if (elem != null) { 19 | result.push(elem); 20 | } 21 | } 22 | return result; 23 | } 24 | if (isObject(collection)) { 25 | result = {}; 26 | let keys = Object.keys(collection); 27 | len = keys.length; 28 | for (i = 0; i < len; i++) { 29 | let key = keys[i]; 30 | let value = collection[key]; 31 | if (value != null) { 32 | result[key] = value; 33 | } 34 | } 35 | return result; 36 | } 37 | return undefined; 38 | } 39 | -------------------------------------------------------------------------------- /src/collection/search.js: -------------------------------------------------------------------------------- 1 | import hasOwnProperty from '../args/has_own_property'; 2 | 3 | export default function search(needle, haystack, argStrict) { 4 | let strict = !!argStrict; 5 | let key = ''; 6 | for (key in haystack) { 7 | if (hasOwnProperty(haystack, key)) { 8 | // eslint-disable-next-line eqeqeq 9 | if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) { 10 | return key; 11 | } 12 | } 13 | } 14 | 15 | return false; 16 | } 17 | -------------------------------------------------------------------------------- /src/collection/size.js: -------------------------------------------------------------------------------- 1 | import isArray from '../lodash/is_array'; 2 | import isString from '../lodash/is_string'; 3 | import isMap from '../lodash/is_map'; 4 | import isSet from '../lodash/is_set'; 5 | 6 | /** 7 | * Gets the size of `collection` by returning its length for array-like 8 | * values or the number of own enumerable string keyed properties for objects. 9 | * 10 | * @category Collection 11 | * @param {Array|Object|string} collection The collection to inspect. 12 | * @returns {number} Returns the collection size. 13 | */ 14 | export default function size(collection) { 15 | if (collection === null || collection === undefined) { 16 | return 0; 17 | } 18 | if (isArray(collection) || isString(collection)) { 19 | return collection.length; 20 | } 21 | 22 | if (isMap(collection) || isSet(collection)) { 23 | return collection.size; 24 | } 25 | 26 | return Object.keys(collection).length; 27 | } 28 | -------------------------------------------------------------------------------- /src/collection/values.js: -------------------------------------------------------------------------------- 1 | import isFunction from '../lodash/is_function'; 2 | import isObject from '../lodash/is_object'; 3 | import isArray from '../lodash/is_array'; 4 | 5 | export default function values(obj) { 6 | let result = []; 7 | if (isArray(obj)) { 8 | return obj.slice(0); 9 | } 10 | if (isObject(obj) || isFunction(obj)) { 11 | let keys = Object.keys(obj); 12 | let len = keys.length; 13 | for (let i = 0; i < len; i++) { 14 | result.push(obj[keys[i]]); 15 | } 16 | return result; 17 | } 18 | throw new Error('argument to `values` must be an object'); 19 | } 20 | -------------------------------------------------------------------------------- /src/cookie/delete_cookie.js: -------------------------------------------------------------------------------- 1 | import setCookie from './set_cookie'; 2 | 3 | const deleteCookie = (name) => { 4 | setCookie(name, '', { 5 | hour: -1 6 | }); 7 | }; 8 | 9 | export default deleteCookie; 10 | -------------------------------------------------------------------------------- /src/cookie/get_cookie.js: -------------------------------------------------------------------------------- 1 | const getCookie = (name) => { 2 | let nameEQ = encodeURIComponent(name) + '='; 3 | let ca = document.cookie.split(';'); 4 | for (let i = 0; i < ca.length; i++) { 5 | let c = ca[i]; 6 | while (c.charAt(0) === ' ') c = c.substring(1, c.length); 7 | if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length)); 8 | } 9 | 10 | return null; 11 | }; 12 | 13 | export default getCookie; 14 | -------------------------------------------------------------------------------- /src/cookie/parse_cookie.js: -------------------------------------------------------------------------------- 1 | const parseCookie = (str) => 2 | str 3 | .split(';') 4 | .map((v) => v.split('=')) 5 | .reduce((acc, v) => { 6 | acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); 7 | return acc; 8 | }, {}); 9 | 10 | export default parseCookie; 11 | -------------------------------------------------------------------------------- /src/cookie/set_cookie.js: -------------------------------------------------------------------------------- 1 | /** 2 | * setCookie / getCookie / deleteCookie 3 | * From https://stackoverflow.com/questions/1458724/how-do-i-set-unset-cookie-with-jquery/1458728#1458728 4 | */ 5 | const setCookie = (name, value, option) => { 6 | let longTime = 10; 7 | // let path = '; path=/'; 8 | let val = option && option.raw ? value : encodeURIComponent(value); 9 | let cookie = encodeURIComponent(name) + '=' + val; 10 | 11 | if (option) { 12 | if (option.days) { 13 | let date = new Date(); 14 | let ms = option.days * 24 * 3600 * 1000; 15 | date.setTime(date.getTime() + ms); 16 | cookie += '; expires=' + date.toGMTString(); 17 | } else if (option.hour) { 18 | let date = new Date(); 19 | let ms = option.hour * 3600 * 1000; 20 | date.setTime(date.getTime() + ms); 21 | cookie += '; expires=' + date.toGMTString(); 22 | } else { 23 | let date = new Date(); 24 | let ms = longTime * 365 * 24 * 3600 * 1000; 25 | date.setTime(date.getTime() + ms); 26 | cookie += '; expires=' + date.toGMTString(); 27 | } 28 | if (option.path) cookie += '; path=' + option.path; 29 | if (option.domain) cookie += '; domain=' + option.domain; 30 | if (option.secure) cookie += '; true'; 31 | } 32 | 33 | document.cookie = cookie; 34 | }; 35 | 36 | export default setCookie; 37 | -------------------------------------------------------------------------------- /src/device/ie_version.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | 3 | /** 4 | * ie version 5 | * From https://codepen.io/gapcode/pen/vEJNZN 6 | * IE 10 ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'; 7 | * IE 11 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko'; 8 | * Edge 12 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0'; 9 | * Edge 13 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586'; 10 | */ 11 | export default function ieVersion() { 12 | let uakit = ua(); 13 | let msie = uakit.indexOf('MSIE '); 14 | if (msie > 0) { 15 | return parseInt(uakit.substring(msie + 5, uakit.indexOf('.', msie)), 10); 16 | } 17 | 18 | let trident = uakit.indexOf('Trident/'); 19 | if (trident > 0) { 20 | let rv = uakit.indexOf('rv:'); 21 | return parseInt(uakit.substring(rv + 3, uakit.indexOf('.', rv)), 10); 22 | } 23 | 24 | let edge = uakit.indexOf('Edge/'); 25 | if (edge > 0) { 26 | return parseInt(ua.substring(edge + 5, uakit.indexOf('.', edge)), 10); 27 | } 28 | 29 | return ''; 30 | } 31 | -------------------------------------------------------------------------------- /src/device/is_android.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | /** 3 | * detect Android 4 | * From https://stackoverflow.com/questions/6031412/detect-android-phone-via-javascript-jquery 5 | */ 6 | export default function isAndroid() { 7 | return ua('l').indexOf('android') > -1; 8 | } 9 | -------------------------------------------------------------------------------- /src/device/is_ie.js: -------------------------------------------------------------------------------- 1 | import ieVersion from './ie_version'; 2 | 3 | export default function isIE() { 4 | return ieVersion() > 0; 5 | } 6 | -------------------------------------------------------------------------------- /src/device/is_ios.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | /** 3 | * detect IOS 4 | * From https://stackoverflow.com/questions/9038625/detect-if-device-is-ios 5 | * more see: 6 | * https://github.com/madrobby/zepto/blob/master/src/detect.js#files 7 | */ 8 | 9 | export default function isIOS() { 10 | return /iPad|iPhone|iPod/.test(ua()); 11 | } 12 | -------------------------------------------------------------------------------- /src/device/is_ipad.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | 3 | export default function isIPad() { 4 | return /iPad/.test(ua()); 5 | } 6 | -------------------------------------------------------------------------------- /src/device/is_iphone.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | 3 | export default function iPhone() { 4 | return /iPhone/.test(ua()); 5 | } 6 | -------------------------------------------------------------------------------- /src/device/is_iphonex_model.js: -------------------------------------------------------------------------------- 1 | export default function isIphoneXmodel() { 2 | // X XS, XS Max, XR 3 | const xSeriesConfig = [ 4 | { 5 | devicePixelRatio: 3, 6 | width: 375, 7 | height: 812 8 | }, 9 | { 10 | devicePixelRatio: 3, 11 | width: 414, 12 | height: 896 13 | }, 14 | { 15 | devicePixelRatio: 2, 16 | width: 414, 17 | height: 896 18 | } 19 | ]; 20 | if (typeof window !== 'undefined' && window) { 21 | const { devicePixelRatio, screen } = window; 22 | const { width, height } = screen; 23 | return xSeriesConfig.some( 24 | (item) => 25 | item.devicePixelRatio === devicePixelRatio && item.width === width && item.height === height 26 | ); 27 | } 28 | return false; 29 | } 30 | -------------------------------------------------------------------------------- /src/device/is_mobile.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | 3 | /** 4 | * detect PC / Mobile 5 | * From https://stackoverflow.com/questions/3514784/what-is-the-best-way-to-detect-a-mobile-device-in-jquery 6 | */ 7 | export default function isMobile() { 8 | return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(ua('l')); 9 | } 10 | -------------------------------------------------------------------------------- /src/device/is_news_app.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | 3 | export default function isNewsApp() { 4 | return /qqnews/.test(ua()); // 腾讯新闻app 5 | } 6 | -------------------------------------------------------------------------------- /src/device/is_pc.js: -------------------------------------------------------------------------------- 1 | import isMobile from './is_mobile'; 2 | 3 | /** 4 | * detect PC / Mobile 5 | * From https://stackoverflow.com/questions/3514784/what-is-the-best-way-to-detect-a-mobile-device-in-jquery 6 | */ 7 | export default function isPC() { 8 | return !isMobile(); 9 | } 10 | -------------------------------------------------------------------------------- /src/device/is_qq.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | 3 | export default function isQQ() { 4 | return /qq\//.test(ua('l')); // 手机QQ 5 | } 6 | -------------------------------------------------------------------------------- /src/device/is_qq_browser.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | 3 | export default function isQQbrowser() { 4 | return /mqqbrowser\//.test(ua('l')); // QQ浏览器 5 | } 6 | -------------------------------------------------------------------------------- /src/device/is_tenvideo.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | 3 | export default function isTenvideo() { 4 | return /qqlivebrowser/.test(ua('l')); // 腾讯视频 5 | } 6 | -------------------------------------------------------------------------------- /src/device/is_weishi.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | 3 | export default function isWeiShi() { 4 | return /weishi/.test(ua('l')); // 腾讯微视 5 | } 6 | -------------------------------------------------------------------------------- /src/device/is_weixin.js: -------------------------------------------------------------------------------- 1 | import ua from './ua'; 2 | 3 | export default function isWeixin() { 4 | return /MicroMessenger/i.test(ua('l')); // 微信 5 | } 6 | -------------------------------------------------------------------------------- /src/device/ua.js: -------------------------------------------------------------------------------- 1 | export default function ua(lower) { 2 | return lower ? window.navigator.userAgent.toLowerCase() : window.navigator.userAgent; 3 | } 4 | -------------------------------------------------------------------------------- /src/fill/chain_async.js: -------------------------------------------------------------------------------- 1 | const chainAsync = (fns) => { 2 | let curr = 0; 3 | const last = fns[fns.length - 1]; 4 | const next = () => { 5 | const fn = fns[curr++]; 6 | fn === last ? fn() : fn(next); 7 | }; 8 | next(); 9 | }; 10 | 11 | export default chainAsync; 12 | -------------------------------------------------------------------------------- /src/fill/fill0.js: -------------------------------------------------------------------------------- 1 | export default function fill0(num) { 2 | let _num = parseFloat(num); 3 | return _num < 10 ? '0' + _num : String(_num); 4 | } 5 | -------------------------------------------------------------------------------- /src/fill/floor.js: -------------------------------------------------------------------------------- 1 | const floor = (n, m = 0) => { 2 | return Math.floor(n * Math.pow(10, m)) / Math.pow(10, m); 3 | }; 4 | 5 | export default floor; 6 | -------------------------------------------------------------------------------- /src/fill/modulo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * modulo of a number and a divisor 3 | */ 4 | 5 | export default function modulo(n, d) { 6 | // bbo.modulo(7, 5); // 2 7 | // bbo.modulo(17, 23); // 17 8 | // bbo.modulo(16.2, 3.8); // 1 9 | // bbo.modulo(5.8, 3.4); //2.4 10 | // bbo.modulo(4, 0); // 4 11 | // bbo.modulo(-7, 5); // 3 12 | // bbo.modulo(-2, 15); // 13 13 | // bbo.modulo(-5.8, 3.4); // 1 14 | // bbo.modulo(12, -1); // NaN 15 | // bbo.modulo(-3, -8); // NaN 16 | // bbo.modulo(12, 'apple'); // NaN 17 | // bbo.modulo('bee', 9); // NaN 18 | // bbo.modulo(null, undefined); // NaN 19 | 20 | if (d === 0) { 21 | return n; 22 | } 23 | if (d < 0) { 24 | return NaN; 25 | } 26 | return ((n % d) + d) % d; 27 | } 28 | -------------------------------------------------------------------------------- /src/fill/number_format.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://locutus.io/php/ 3 | */ 4 | // eslint-disable-next-line max-params 5 | const numberFormat = (number, decimals, decPoint, thousandsSep) => { 6 | let _number = String(number).replace(/[^0-9+\-Ee.]/g, ''); 7 | let _decimals = decimals; 8 | let n = !isFinite(Number(_number)) ? 0 : Number(_number); 9 | let prec = !isFinite(Number(_decimals)) ? 0 : Math.abs(_decimals); 10 | let sep = typeof thousandsSep === 'undefined' ? ',' : thousandsSep; 11 | let dec = typeof decPoint === 'undefined' ? '.' : decPoint; 12 | let s = ''; 13 | 14 | let toFixedFix = function(n, prec) { 15 | if (String(n).indexOf('e') === -1) { 16 | return Number(Math.round(n + 'e+' + prec) + 'e-' + prec); 17 | } else { 18 | let arr = String(n).split('e'); 19 | let sig = ''; 20 | if (Number(arr[1]) + prec > 0) { 21 | sig = '+'; 22 | } 23 | return Number( 24 | Math.round(Number(arr[0]) + 'e' + sig + (Number(arr[1]) + prec)) + 'e-' + prec 25 | ).toFixed(prec); 26 | } 27 | }; 28 | 29 | // @todo: for IE parseFloat(0.55).toFixed(0) = 0; 30 | s = (prec ? toFixedFix(n, prec).toString() : String(Math.round(n))).split('.'); 31 | if (s[0].length > 3) { 32 | s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep); 33 | } 34 | if ((s[1] || '').length < prec) { 35 | s[1] = s[1] || ''; 36 | s[1] += new Array(prec - s[1].length + 1).join('0'); 37 | } 38 | 39 | return s.join(dec); 40 | }; 41 | 42 | export default numberFormat; 43 | -------------------------------------------------------------------------------- /src/http/delete_url_param.js: -------------------------------------------------------------------------------- 1 | /** 2 | * getUrlParam / deleteUrlParam 3 | * From https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript 4 | */ 5 | 6 | const deleteUrlParam = (param, url = window.location.href) => { 7 | // prefer to use l.search if you have a location/link object 8 | let urlparts = url.split('?'); 9 | if (urlparts.length >= 2) { 10 | let prefix = encodeURIComponent(param) + '='; 11 | let pars = urlparts[1].split(/[&;]/g); 12 | 13 | // reverse iteration as may be destructive 14 | for (let i = pars.length; i-- > 0; ) { 15 | // idiom for string.startsWith 16 | if (pars[i].lastIndexOf(prefix, 0) !== -1) { 17 | pars.splice(i, 1); 18 | } 19 | } 20 | return urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : ''); 21 | } else { 22 | return url; 23 | } 24 | }; 25 | 26 | export default deleteUrlParam; 27 | -------------------------------------------------------------------------------- /src/http/get_url_param.js: -------------------------------------------------------------------------------- 1 | /** 2 | * getUrlParam / deleteUrlParam 3 | * From https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript 4 | */ 5 | const getUrlParam = (name, url = window.location.href) => { 6 | name.replace(/[\[\]]/g, '\\$&'); 7 | let regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'); 8 | let results = regex.exec(url); 9 | if (!results) return null; 10 | if (!results[2]) return ''; 11 | 12 | return decodeURIComponent(results[2].replace(/\+/g, ' ')); 13 | }; 14 | 15 | export default getUrlParam; 16 | -------------------------------------------------------------------------------- /src/http/http_get.js: -------------------------------------------------------------------------------- 1 | const httpGet = (url, callback, err = console.error) => { 2 | const request = new XMLHttpRequest(); 3 | request.open('GET', url, true); 4 | request.onload = () => callback(request.responseText); 5 | request.onerror = () => err(request); 6 | request.send(); 7 | }; 8 | 9 | export default httpGet; 10 | -------------------------------------------------------------------------------- /src/http/http_post.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line max-params 2 | const httpPost = (url, data, callback, err = console.error) => { 3 | const request = new XMLHttpRequest(); 4 | request.open('POST', url, true); 5 | request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); 6 | request.onload = () => callback(request.responseText); 7 | request.onerror = () => err(request); 8 | request.send(data); 9 | }; 10 | 11 | export default httpPost; 12 | -------------------------------------------------------------------------------- /src/http/is_absolute_url.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns true if the given string is an absolute URL, false otherwise. 3 | */ 4 | const isAbsoluteURL = (str) => /^[a-z][a-z0-9+.-]*:/.test(str); 5 | 6 | export default isAbsoluteURL; 7 | -------------------------------------------------------------------------------- /src/http/object_param.js: -------------------------------------------------------------------------------- 1 | import isArray from '../lodash/is_array'; 2 | const objectParam = (arr) => { 3 | let str = ''; 4 | if (isArray(arr)) { 5 | str = arr 6 | .map((item) => { 7 | return item.name + '=' + item.value; 8 | }) 9 | .join('&'); 10 | } else { 11 | str = objectParam(objectBigParam(arr)); 12 | } 13 | return str; 14 | }; 15 | 16 | const objectBigParam = (obj) => { 17 | let arr = []; 18 | Object.keys(obj).forEach((k) => { 19 | if (isArray(obj[k])) { 20 | arr = arr.concat( 21 | obj[k].map((v) => { 22 | return { 23 | name: k, 24 | value: v 25 | }; 26 | }) 27 | ); 28 | } else { 29 | arr.push({ 30 | name: k, 31 | value: obj[k] 32 | }); 33 | } 34 | }); 35 | return arr; 36 | }; 37 | 38 | export default objectParam; 39 | -------------------------------------------------------------------------------- /src/http/set_url_param.js: -------------------------------------------------------------------------------- 1 | /** 2 | * setUrlParam 3 | * From https://stackoverflow.com/questions/5999118/add-or-update-query-string-parameter 4 | */ 5 | const setUrlParam = (key, value, uri = window.location.href) => { 6 | let re = new RegExp('([?&])' + key + '=.*?(&|$)', 'i'); 7 | let separator = uri.indexOf('?') !== -1 ? '&' : '?'; 8 | if (uri.match(re)) { 9 | return uri.replace(re, '$1' + key + '=' + value + '$2'); 10 | } else { 11 | return uri + separator + key + '=' + value; 12 | } 13 | }; 14 | 15 | export default setUrlParam; 16 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import chain from './chain/chain'; 2 | import ChainWrapper from './chain/wrapper'; 3 | import functions from './functions'; 4 | 5 | function bbo(subject) { 6 | return new ChainWrapper(subject, false); 7 | } 8 | 9 | Object.assign(bbo, functions, { 10 | chain: chain 11 | }); 12 | 13 | export default bbo; 14 | -------------------------------------------------------------------------------- /src/json/to_json.js: -------------------------------------------------------------------------------- 1 | /** 2 | * to json 3 | */ 4 | 5 | // eval hack 6 | const evil = (fn) => { 7 | // A variable points to Function, preventing reporting errors 8 | let Fn = Function; 9 | return new Fn('return ' + fn)(); 10 | }; 11 | 12 | // bbo.toJSON = bbo.tojson = bbo.toJson 13 | const toJson = (res) => { 14 | if (!res) return null; 15 | 16 | if (typeof res === 'string') { 17 | try { 18 | return JSON.parse(res); 19 | } catch (e) { 20 | return evil('(' + res + ')'); 21 | } 22 | } else { 23 | return res; 24 | } 25 | }; 26 | 27 | export default toJson; 28 | -------------------------------------------------------------------------------- /src/lodash/debounce.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-invalid-this */ 2 | export default function debounce(fn, wait, callFirst) { 3 | let timeout; 4 | return function() { 5 | if (!wait) { 6 | return fn.apply(this, arguments); 7 | } 8 | let context = this; 9 | let args = arguments; 10 | let callNow = callFirst && !timeout; 11 | clearTimeout(timeout); 12 | timeout = setTimeout(function() { 13 | timeout = null; 14 | if (!callNow) { 15 | return fn.apply(context, args); 16 | } 17 | }, wait); 18 | 19 | if (callNow) { 20 | return fn.apply(this, arguments); 21 | } 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /src/lodash/find.js: -------------------------------------------------------------------------------- 1 | import forEach from './for_each'; 2 | import isFunction from './is_function'; 3 | import isObject from './is_object'; 4 | import is from './is'; 5 | import isShallowEqual from './is_shallow_equal'; 6 | 7 | export default function find(src, func) { 8 | // eslint-disable-next-line no-undef-init 9 | let rst = undefined; 10 | forEach(src, (item, key, obj) => { 11 | if (isFunction(func)) { 12 | if (func(item, key, obj) === true) { 13 | rst = item; 14 | return false; 15 | } 16 | } else if (is(item, func)) { 17 | rst = item; 18 | return false; 19 | } else if (isObject(item) && isObject(func)) { 20 | let subEqual = true; 21 | forEach(func, (v, k) => { 22 | subEqual = isShallowEqual(item[k], v); 23 | return subEqual; 24 | }); 25 | if (subEqual) { 26 | rst = item; 27 | return false; 28 | } 29 | } 30 | }); 31 | return rst; 32 | } 33 | -------------------------------------------------------------------------------- /src/lodash/find_index.js: -------------------------------------------------------------------------------- 1 | import forEach from './for_each'; 2 | import isFunction from './is_function'; 3 | import isObject from './is_object'; 4 | import is from './is'; 5 | import isShallowEqual from './is_shallow_equal'; 6 | 7 | export default function findIndex(src, func) { 8 | let rst = -1; 9 | forEach(src, (item, index, obj) => { 10 | if (isFunction(func)) { 11 | if (func(item, index, obj) === true) { 12 | rst = index; 13 | return false; 14 | } 15 | } else if (is(item, func)) { 16 | rst = index; 17 | return false; 18 | } else if (isObject(item) && isObject(func)) { 19 | let subEqual = true; 20 | forEach(func, (v, k) => { 21 | subEqual = isShallowEqual(item[k], v); 22 | return subEqual; 23 | }); 24 | if (subEqual) { 25 | rst = index; 26 | return false; 27 | } 28 | } 29 | }); 30 | return rst; 31 | } 32 | -------------------------------------------------------------------------------- /src/lodash/for_each.js: -------------------------------------------------------------------------------- 1 | import isArray from './is_array'; 2 | import isObject from './is_object'; 3 | 4 | export default function forEach(src, func) { 5 | let i = 0; 6 | if (isArray(src)) { 7 | while (i < src.length) { 8 | const rst = func(src[i], i, src); 9 | if (rst === false) { 10 | break; 11 | } 12 | i += 1; 13 | } 14 | } else if (isObject(src)) { 15 | const keys = Object.keys(src); 16 | while (i < keys.length) { 17 | const key = keys[i]; 18 | const rst = func(src[key], key, src); 19 | if (rst === false) { 20 | break; 21 | } 22 | i += 1; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/lodash/get.js: -------------------------------------------------------------------------------- 1 | import isString from './is_string'; 2 | import isSymbol from './is_symbol'; 3 | import isArray from './is_array'; 4 | 5 | export default function get(obj, propsArg, defaultValue) { 6 | if (!obj) { 7 | return defaultValue; 8 | } 9 | let props; 10 | let prop; 11 | if (Array.isArray(propsArg)) { 12 | props = propsArg.slice(0); 13 | } 14 | if (isString(propsArg)) { 15 | props = propsArg.split('.'); 16 | } 17 | if (isSymbol(propsArg)) { 18 | props = [propsArg]; 19 | } 20 | if (!isArray(props)) { 21 | throw new Error('props arg must be an array, a string or a symbol'); 22 | } 23 | while (props.length) { 24 | prop = props.shift(); 25 | if (!obj) { 26 | return defaultValue; 27 | } 28 | // eslint-disable-next-line no-param-reassign 29 | obj = obj[prop]; 30 | if (obj === undefined) { 31 | return defaultValue; 32 | } 33 | } 34 | return obj; 35 | } 36 | -------------------------------------------------------------------------------- /src/lodash/get_tag.js: -------------------------------------------------------------------------------- 1 | export default function getTag(src) { 2 | return Object.prototype.toString.call(src); 3 | } 4 | -------------------------------------------------------------------------------- /src/lodash/has.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable eqeqeq */ 2 | /* eslint-disable no-eq-null */ 3 | import hasOwnProperty from '../args/has_own_property'; 4 | export default function has(object, key) { 5 | return object != null && hasOwnProperty(object, key); 6 | } 7 | -------------------------------------------------------------------------------- /src/lodash/is.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-self-compare */ 2 | export default function is(x, y) { 3 | // inlined Object.is polyfill to avoid requiring consumers ship their own 4 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 5 | if (x === y) { 6 | // Steps 1-5, 7-10 7 | // Steps 6.b-6.e: +0 != -0 8 | // Added the nonzero y check to make Flow happy, but it is redundant 9 | return x !== 0 || y !== 0 || 1 / x === 1 / y; 10 | } else { 11 | // Step 6.a: NaN == NaN 12 | return x !== x && y !== y; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/lodash/is_array.js: -------------------------------------------------------------------------------- 1 | import getTag from './get_tag'; 2 | 3 | export default function isArray(arr) { 4 | return getTag(arr) === '[object Array]'; 5 | } 6 | -------------------------------------------------------------------------------- /src/lodash/is_boolean.js: -------------------------------------------------------------------------------- 1 | import getTag from './get_tag'; 2 | 3 | export default function isBoolean(bool) { 4 | return getTag(bool) === '[object Boolean]'; 5 | } 6 | -------------------------------------------------------------------------------- /src/lodash/is_date.js: -------------------------------------------------------------------------------- 1 | const isDate = (d) => d instanceof Date; 2 | 3 | export default isDate; 4 | -------------------------------------------------------------------------------- /src/lodash/is_empty.js: -------------------------------------------------------------------------------- 1 | import isArray from '../lodash/is_array'; 2 | import isString from '../lodash/is_string'; 3 | import isObject from '../lodash/is_object'; 4 | import isMap from '../lodash/is_map'; 5 | import isSet from '../lodash/is_set'; 6 | 7 | export default function isEmpty(obj) { 8 | if (obj === null) { 9 | return true; 10 | } 11 | 12 | if (isArray(obj)) { 13 | return !obj.length; 14 | } 15 | 16 | if (isString(obj)) { 17 | return !obj.length; 18 | } 19 | 20 | if (isObject(obj)) { 21 | return !Object.keys(obj).length; 22 | } 23 | 24 | if (isMap(obj) || isSet(obj)) { 25 | return !obj.size; 26 | } 27 | 28 | // other primitive || unidentifed object type 29 | return Object(obj) !== obj || !Object.keys(obj).length; 30 | } 31 | -------------------------------------------------------------------------------- /src/lodash/is_function.js: -------------------------------------------------------------------------------- 1 | import getTag from './get_tag'; 2 | 3 | export default function isFunction(func) { 4 | return getTag(func) === '[object Function]'; 5 | } 6 | -------------------------------------------------------------------------------- /src/lodash/is_map.js: -------------------------------------------------------------------------------- 1 | import getTag from './get_tag'; 2 | 3 | export default function isMap(map) { 4 | return getTag(map) === '[object Map]'; 5 | } 6 | -------------------------------------------------------------------------------- /src/lodash/is_nil.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-eq-null */ 2 | /* eslint-disable eqeqeq */ 3 | export default function isNil(value) { 4 | return value == undefined || value == null; 5 | } 6 | -------------------------------------------------------------------------------- /src/lodash/is_number.js: -------------------------------------------------------------------------------- 1 | import getTag from './get_tag'; 2 | 3 | export default function isNumber(number) { 4 | return getTag(number) === '[object Number]'; 5 | } 6 | -------------------------------------------------------------------------------- /src/lodash/is_object.js: -------------------------------------------------------------------------------- 1 | export default function isObject(value) { 2 | const type = typeof value; 3 | return value !== null && (type === 'object' || type === 'function'); 4 | } 5 | -------------------------------------------------------------------------------- /src/lodash/is_set.js: -------------------------------------------------------------------------------- 1 | import getTag from './get_tag'; 2 | 3 | export default function isSet(set) { 4 | return getTag(set) === '[object Set]'; 5 | } 6 | -------------------------------------------------------------------------------- /src/lodash/is_string.js: -------------------------------------------------------------------------------- 1 | import getTag from './get_tag'; 2 | 3 | export default function isString(str) { 4 | return getTag(str) === '[object String]'; 5 | } 6 | -------------------------------------------------------------------------------- /src/lodash/is_symbol.js: -------------------------------------------------------------------------------- 1 | import getTag from './get_tag'; 2 | 3 | export default function isSymbol(symbol) { 4 | return getTag(symbol) === '[object Symbol]'; 5 | } 6 | -------------------------------------------------------------------------------- /src/lodash/map.js: -------------------------------------------------------------------------------- 1 | import isArray from './is_array'; 2 | import isObject from './is_object'; 3 | 4 | export default function map(src, func) { 5 | const rst = []; 6 | let i = 0; 7 | if (isArray(src)) { 8 | while (i < src.length) { 9 | rst.push(func(src[i], i, src)); 10 | i += 1; 11 | } 12 | } else if (isObject(src)) { 13 | const keys = Object.keys(src); 14 | while (i < keys.length) { 15 | const key = keys[i]; 16 | rst.push(func(src[key], key, src)); 17 | i += 1; 18 | } 19 | } 20 | return rst; 21 | } 22 | -------------------------------------------------------------------------------- /src/lodash/map_values.js: -------------------------------------------------------------------------------- 1 | /* 2 | returns a new object with the predicate applied to each value 3 | like map-object, but (value, key, object) are passed to the predicate 4 | */ 5 | 6 | export default function mapValues(obj, predicate) { 7 | let result = {}; 8 | let keys = Object.keys(obj); 9 | let len = keys.length; 10 | for (let i = 0; i < len; i++) { 11 | let key = keys[i]; 12 | result[key] = predicate(obj[key], key, obj); 13 | } 14 | return result; 15 | } 16 | -------------------------------------------------------------------------------- /src/lodash/omit.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-param-reassign */ 2 | import isString from './is_string'; 3 | export default function omit(obj, remove) { 4 | let result = {}; 5 | if (isString(remove)) { 6 | remove = [].slice.call(arguments, 1); 7 | } 8 | for (let prop in obj) { 9 | if (!obj.hasOwnProperty || obj.hasOwnProperty(prop)) { 10 | if (remove.indexOf(prop) === -1) { 11 | result[prop] = obj[prop]; 12 | } 13 | } 14 | } 15 | return result; 16 | } 17 | -------------------------------------------------------------------------------- /src/lodash/pick.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-param-reassign */ 2 | import isString from './is_string'; 3 | export default function pick(obj, select) { 4 | let result = {}; 5 | if (isString(select)) { 6 | select = [].slice.call(arguments, 1); 7 | } 8 | let len = select.length; 9 | for (let i = 0; i < len; i++) { 10 | let key = select[i]; 11 | if (key in obj) { 12 | result[key] = obj[key]; 13 | } 14 | } 15 | return result; 16 | } 17 | -------------------------------------------------------------------------------- /src/lodash/reduce.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-param-reassign */ 2 | /* eslint-disable max-params */ 3 | export default function reduce(obj, predicate /* , initialValue */) { 4 | let args = [callback]; 5 | 6 | let hasInitialValue = 2 in arguments; 7 | hasInitialValue && args.push(arguments[2]); 8 | 9 | function callback(previousValue, currentKey, currentIndex, array) { 10 | if (!hasInitialValue) { 11 | previousValue = obj[array[0]]; 12 | hasInitialValue = true; 13 | } 14 | return predicate(previousValue, currentKey, obj[currentKey], currentIndex, array); 15 | } 16 | 17 | return Array.prototype.reduce.apply(Object.keys(obj), args); 18 | } 19 | -------------------------------------------------------------------------------- /src/lodash/set.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable eqeqeq */ 2 | /* eslint-disable no-param-reassign */ 3 | 4 | /** 5 | * set value at property, create intermediate properties if necessary 6 | */ 7 | import isString from './is_string'; 8 | import isSymbol from './is_symbol'; 9 | import isObject from './is_object'; 10 | 11 | export default function set(obj, props, value) { 12 | if (isString(props)) { 13 | props = props.split('.'); 14 | } 15 | if (isSymbol(props)) { 16 | props = [props]; 17 | } 18 | let lastProp = props.pop(); 19 | if (!lastProp) { 20 | return false; 21 | } 22 | let thisProp; 23 | while ((thisProp = props.shift())) { 24 | if (typeof obj[thisProp] == 'undefined') { 25 | obj[thisProp] = {}; 26 | } 27 | obj = obj[thisProp]; 28 | if (!obj || !isObject(obj)) { 29 | return false; 30 | } 31 | } 32 | obj[lastProp] = value; 33 | return true; 34 | } 35 | -------------------------------------------------------------------------------- /src/lodash/string_to_path.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-params */ 2 | const charCodeOfDot = '.'.charCodeAt(0); 3 | const reEscapeChar = /\\(\\)?/g; 4 | const rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g; 5 | 6 | export default function stringToPath(string) { 7 | const result = []; 8 | if (string.charCodeAt(0) === charCodeOfDot) { 9 | result.push(''); 10 | } 11 | string.replace(rePropName, (match, expression, quote, subString) => { 12 | let key = match; 13 | if (quote) { 14 | key = subString.replace(reEscapeChar, '$1'); 15 | } else if (expression) { 16 | key = expression.trim(); 17 | } 18 | result.push(key); 19 | }); 20 | return result; 21 | } 22 | -------------------------------------------------------------------------------- /src/lodash/throttle.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-invalid-this */ 2 | export default function throttle(fn, interval, callFirst) { 3 | let wait = false; 4 | let callNow = false; 5 | return function() { 6 | callNow = callFirst && !wait; 7 | let context = this; 8 | let args = arguments; 9 | if (!wait) { 10 | wait = true; 11 | setTimeout(function() { 12 | wait = false; 13 | if (!callFirst) { 14 | return fn.apply(context, args); 15 | } 16 | }, interval); 17 | } 18 | if (callNow) { 19 | callNow = false; 20 | return fn.apply(this, arguments); 21 | } 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /src/lodash/to_path.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable eqeqeq */ 2 | import isString from './is_string'; 3 | import isArray from './is_array'; 4 | import isSymbol from './is_symbol'; 5 | import map from './map'; 6 | import clone from '../collection/clone'; 7 | import stringToPath from './string_to_path'; 8 | // import copyArray from '../array/copyArray'; 9 | 10 | const INFINITY = 1 / 0; 11 | 12 | function toKey(value) { 13 | if (isString(value) || isSymbol(value)) { 14 | return value; 15 | } 16 | const result = `${value}`; 17 | return result == '0' && 1 / value == -INFINITY ? '-0' : result; 18 | } 19 | 20 | export default function toPath(value) { 21 | if (isArray(value)) { 22 | return map(value, toKey); 23 | } 24 | return isSymbol(value) ? [value] : clone(stringToPath(String(value))); 25 | } 26 | -------------------------------------------------------------------------------- /src/object/added_diff.js: -------------------------------------------------------------------------------- 1 | import isEmpty from '../lodash/is_empty'; 2 | import isObject from '../lodash/is_object'; 3 | import properObject from './proper_object'; 4 | 5 | const addedDiff = (lhs, rhs) => { 6 | if (lhs === rhs || !isObject(lhs) || !isObject(rhs)) return {}; 7 | 8 | const l = properObject(lhs); 9 | const r = properObject(rhs); 10 | 11 | return Object.keys(r).reduce((acc, key) => { 12 | if (l.hasOwnProperty(key)) { 13 | const difference = addedDiff(l[key], r[key]); 14 | 15 | if (isObject(difference) && isEmpty(difference)) return acc; 16 | 17 | return { ...acc, [key]: difference }; 18 | } 19 | 20 | return { ...acc, [key]: r[key] }; 21 | }, {}); 22 | }; 23 | 24 | export default addedDiff; 25 | -------------------------------------------------------------------------------- /src/object/deleted_diff.js: -------------------------------------------------------------------------------- 1 | import isEmpty from '../lodash/is_empty'; 2 | import isObject from '../lodash/is_object'; 3 | import properObject from './proper_object'; 4 | 5 | const deletedDiff = (lhs, rhs) => { 6 | if (lhs === rhs || !isObject(lhs) || !isObject(rhs)) return {}; 7 | 8 | const l = properObject(lhs); 9 | const r = properObject(rhs); 10 | 11 | return Object.keys(l).reduce((acc, key) => { 12 | if (r.hasOwnProperty(key)) { 13 | const difference = deletedDiff(l[key], r[key]); 14 | 15 | if (isObject(difference) && isEmpty(difference)) return acc; 16 | 17 | return { ...acc, [key]: difference }; 18 | } 19 | 20 | return { ...acc, [key]: undefined }; 21 | }, {}); 22 | }; 23 | 24 | export default deletedDiff; 25 | -------------------------------------------------------------------------------- /src/object/detailed_diff.js: -------------------------------------------------------------------------------- 1 | import addedDiff from './added_diff'; 2 | import deletedDiff from './deleted_diff'; 3 | import updatedDiff from './updated_diff'; 4 | 5 | const detailedDiff = (lhs, rhs) => ({ 6 | added: addedDiff(lhs, rhs), 7 | deleted: deletedDiff(lhs, rhs), 8 | updated: updatedDiff(lhs, rhs) 9 | }); 10 | 11 | export default detailedDiff; 12 | -------------------------------------------------------------------------------- /src/object/object_diff.js: -------------------------------------------------------------------------------- 1 | import isDate from '../lodash/is_date'; 2 | import isEmpty from '../lodash/is_empty'; 3 | import isObject from '../lodash/is_object'; 4 | import properObject from './proper_object'; 5 | 6 | const objectDiff = (lhs, rhs) => { 7 | if (lhs === rhs) return {}; // equal return no diff 8 | 9 | if (!isObject(lhs) || !isObject(rhs)) return rhs; // return updated rhs 10 | 11 | const l = properObject(lhs); 12 | const r = properObject(rhs); 13 | 14 | const deletedValues = Object.keys(l).reduce((acc, key) => { 15 | return r.hasOwnProperty(key) ? acc : { ...acc, [key]: undefined }; 16 | }, {}); 17 | 18 | if (isDate(l) || isDate(r)) { 19 | // eslint-disable-next-line eqeqeq 20 | if (l.valueOf() == r.valueOf()) return {}; 21 | return r; 22 | } 23 | 24 | return Object.keys(r).reduce((acc, key) => { 25 | if (!l.hasOwnProperty(key)) return { ...acc, [key]: r[key] }; // return added r key 26 | 27 | const difference = objectDiff(l[key], r[key]); 28 | 29 | if (isObject(difference) && isEmpty(difference) && !isDate(difference)) return acc; // return no diff 30 | 31 | return { ...acc, [key]: difference }; // return updated key 32 | }, deletedValues); 33 | }; 34 | 35 | export default objectDiff; 36 | -------------------------------------------------------------------------------- /src/object/proper_object.js: -------------------------------------------------------------------------------- 1 | import isObject from '../lodash/is_object'; 2 | 3 | const properObject = (o) => (isObject(o) && !o.hasOwnProperty ? { ...o } : o); 4 | 5 | export default properObject; 6 | -------------------------------------------------------------------------------- /src/object/updated_diff.js: -------------------------------------------------------------------------------- 1 | import isDate from '../lodash/is_date'; 2 | import isEmpty from '../lodash/is_empty'; 3 | import isObject from '../lodash/is_object'; 4 | import properObject from './proper_object'; 5 | 6 | const updatedDiff = (lhs, rhs) => { 7 | if (lhs === rhs) return {}; 8 | 9 | if (!isObject(lhs) || !isObject(rhs)) return rhs; 10 | 11 | const l = properObject(lhs); 12 | const r = properObject(rhs); 13 | 14 | if (isDate(l) || isDate(r)) { 15 | // eslint-disable-next-line eqeqeq 16 | if (l.valueOf() == r.valueOf()) return {}; 17 | return r; 18 | } 19 | 20 | return Object.keys(r).reduce((acc, key) => { 21 | if (l.hasOwnProperty(key)) { 22 | const difference = updatedDiff(l[key], r[key]); 23 | 24 | if (isObject(difference) && isEmpty(difference) && !isDate(difference)) return acc; 25 | 26 | return { ...acc, [key]: difference }; 27 | } 28 | 29 | return acc; 30 | }, {}); 31 | }; 32 | 33 | export default updatedDiff; 34 | -------------------------------------------------------------------------------- /src/other/construct.js: -------------------------------------------------------------------------------- 1 | export default function construct() { 2 | let classs = arguments[0]; 3 | return new (Function.prototype.bind.apply(classs, arguments))(); 4 | } 5 | -------------------------------------------------------------------------------- /src/other/get_type.js: -------------------------------------------------------------------------------- 1 | const getType = (v) => 2 | v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); 3 | 4 | export default getType; 5 | -------------------------------------------------------------------------------- /src/other/hash.js: -------------------------------------------------------------------------------- 1 | /** 2 | * string hash map 3 | * From https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery 4 | */ 5 | import size from '../collection/size'; 6 | 7 | export default function hash(str) { 8 | let _str = String(str); 9 | let hash = 0; 10 | let i; 11 | let chr; 12 | if (size(_str) === 0) return hash; 13 | for (i = 0; i < _str.length; i++) { 14 | chr = _str.charCodeAt(i); 15 | hash = (hash << 5) - hash + chr; 16 | hash |= 0; // Convert to 32bit integer 17 | } 18 | 19 | return hash; 20 | } 21 | -------------------------------------------------------------------------------- /src/other/is_typeof.js: -------------------------------------------------------------------------------- 1 | /** 2 | * is typeof type 3 | */ 4 | const isTypeof = (val, type) => { 5 | return ( 6 | Object.prototype.toString 7 | .call(val) 8 | .slice(8, -1) 9 | .toLowerCase() === type 10 | ); 11 | }; 12 | 13 | export default isTypeof; 14 | -------------------------------------------------------------------------------- /src/other/judge.js: -------------------------------------------------------------------------------- 1 | import isTypeof from './is_typeof'; 2 | /** 3 | * map condition judge 4 | * bbo.judge = bbo.judgment 5 | */ 6 | export default function judge(v, vals, strict) { 7 | if (!isTypeof(vals, 'array')) return false; 8 | 9 | for (let key in vals) { 10 | if (strict) { 11 | if (v === vals[key]) return true; 12 | } else { 13 | // eslint-disable-next-line eqeqeq 14 | if (v == vals[key]) return true; 15 | } 16 | } 17 | 18 | return false; 19 | } 20 | -------------------------------------------------------------------------------- /src/other/log.js: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * LOGS 3 | *************************************************************************/ 4 | /** 5 | * log on mobile html body 6 | */ 7 | import c from '../bom/c'; 8 | import g from '../bom/g'; 9 | import attr from '../bom/attr'; 10 | 11 | export default function log(msg, styles) { 12 | let ele = g('_bbo_log'); 13 | if (ele === null) { 14 | ele = c('div'); 15 | attr(ele, 'id', '_bbo_log'); 16 | attr(ele, 'style', 'position:fixed;left:0;top:0;z-index:9999;padding:4px;'); 17 | document.body.appendChild(ele); 18 | } 19 | 20 | if (styles) { 21 | for (let style in styles) { 22 | if (Object.prototype.hasOwnProperty.call(styles, style)) { 23 | ele.style[style] = styles[style]; 24 | } 25 | } 26 | } 27 | ele.innerHTML = msg; 28 | } 29 | -------------------------------------------------------------------------------- /src/other/params_name.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gets all the formal parameter names of a function 3 | * https://www.zhihu.com/question/28912825 4 | */ 5 | export default function paramsName(fn) { 6 | return /\(\s*([\s\S]*?)\s*\)/.exec(fn.toString())[1].split(/\s*,\s*/); 7 | } 8 | -------------------------------------------------------------------------------- /src/other/uuid.js: -------------------------------------------------------------------------------- 1 | /** 2 | * generate uuid 3 | * From https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript 4 | */ 5 | export default function uuid() { 6 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 7 | let r = (Math.random() * 16) | 0; 8 | let v = c === 'x' ? r : (r & 0x3) | 0x8; 9 | return v.toString(16); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /src/random/random_a2b.js: -------------------------------------------------------------------------------- 1 | // bbo.randomFromA2B = bbo.randomA2B 2 | const randomA2B = (a, b, int) => { 3 | let result = Math.random() * (b - a) + a; 4 | return int ? Math.floor(result) : result; 5 | }; 6 | 7 | export default randomA2B; 8 | -------------------------------------------------------------------------------- /src/random/random_color.js: -------------------------------------------------------------------------------- 1 | export default function randomColor() { 2 | return '#' + ('00000' + ((Math.random() * 0x1000000) << 0).toString(16)).slice(-6); 3 | } 4 | -------------------------------------------------------------------------------- /src/random/random_key.js: -------------------------------------------------------------------------------- 1 | const randomKey = (len = 32) => { 2 | /** Removed confusing characters 'oOLl,9gq,Vv,Uu,I1' **/ 3 | let possible = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; 4 | let key = ''; 5 | for (let i = 0; i < len; i++) { 6 | key += possible.charAt(Math.floor(Math.random() * possible.length)); 7 | } 8 | return key; 9 | }; 10 | 11 | export default randomKey; 12 | -------------------------------------------------------------------------------- /src/string/byte_len.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /** 3 | * Returns the length of a string in bytes by Unicode (utf-8 utf8 utf-16 utf16) 4 | */ 5 | export default function byteLen(str, charset) { 6 | let total = 0; 7 | let charCode; 8 | if (charset === 'utf-8' || charset === 'utf8') { 9 | for (let i = 0, len = str.length; i < len; i++) { 10 | charCode = str.codePointAt(i); 11 | 12 | if (charCode <= 0x007f) { 13 | total += 1; 14 | } else if (charCode <= 0x07ff) { 15 | total += 2; 16 | } else if (charCode <= 0xffff) { 17 | total += 3; 18 | } else { 19 | total += 4; 20 | i++; 21 | } 22 | } 23 | } else if (charset === 'utf-16' || charset === 'utf16') { 24 | for (let i = 0, len = str.length; i < len; i++) { 25 | charCode = str.codePointAt(i); 26 | 27 | if (charCode <= 0xffff) { 28 | total += 2; 29 | } else { 30 | total += 4; 31 | i++; 32 | } 33 | } 34 | } else { 35 | total = str.replace(/[^\x00-\xff]/g, 'aa').length; 36 | } 37 | return total; 38 | } 39 | -------------------------------------------------------------------------------- /src/string/byte_size.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the length of a string in bytes. 3 | */ 4 | export default function byteSize(str) { 5 | return new Blob([str]).size; 6 | } 7 | -------------------------------------------------------------------------------- /src/string/camelize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * _ or - to CamelCase 3 | */ 4 | export default function camelize(target) { 5 | if (target.indexOf('-') < 0 && target.indexOf('_') < 0) { 6 | return target; 7 | } 8 | return target.replace(/[-_][^-_]/g, function(match) { 9 | return match.charAt(1).toUpperCase(); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /src/string/capitalize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Capitalizes the first letter of a string. 3 | */ 4 | export default function capitalize(target) { 5 | return ( 6 | String(target) 7 | .charAt(0) 8 | .toUpperCase() + 9 | String(target) 10 | .slice(1) 11 | .toLowerCase() 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/string/capwords.js: -------------------------------------------------------------------------------- 1 | export default function capwords(str) { 2 | // example 1: capwords('kevin van zonneveld') 3 | // returns 1: 'Kevin Van Zonneveld' 4 | // example 2: capwords('HELLO WORLD') 5 | // returns 2: 'HELLO WORLD' 6 | 7 | let pattern = /^([a-z\u00E0-\u00FC])|\s+([a-z\u00E0-\u00FC])/g; 8 | return String(str).replace(pattern, function($1) { 9 | return $1.toUpperCase(); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /src/string/contains_with.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Whether a string contains another string 3 | */ 4 | export default function containsWith(target, item) { 5 | // discuss at: https://locutus.io/golang/strings/Contains 6 | // original by: Kevin van Zonneveld (https://kvz.io) 7 | // example 1: bbo.contains('Kevin', 'K') 8 | // returns 1: true 9 | return String(target).indexOf(item) !== -1; 10 | } 11 | -------------------------------------------------------------------------------- /src/string/dasherize.js: -------------------------------------------------------------------------------- 1 | import underscored from './underscored'; 2 | /** 3 | * Turn '_' in a string into '-' 4 | */ 5 | export default function dasherize(target) { 6 | return underscored(String(target)).replace(/_/g, '-'); 7 | } 8 | -------------------------------------------------------------------------------- /src/string/de_capitalize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * DeCapitalizes the first letter of a string. 3 | */ 4 | 5 | import isString from '../lodash/is_string'; 6 | import isNil from '../lodash/is_nil'; 7 | 8 | function coerceToString(value, defaultValue = '') { 9 | if (isNil(value)) { 10 | return defaultValue; 11 | } 12 | if (isString(value)) { 13 | return value; 14 | } 15 | return String(value); 16 | } 17 | 18 | export default function deCapitalize(subject) { 19 | const subjectString = coerceToString(subject); 20 | if (subjectString === '') { 21 | return ''; 22 | } 23 | return subjectString.substr(0, 1).toLowerCase() + subjectString.substr(1); 24 | } 25 | -------------------------------------------------------------------------------- /src/string/effort_Index.js: -------------------------------------------------------------------------------- 1 | export default function sindex(s, sep) { 2 | // discuss at: https://locutus.io/golang/strings/Index 3 | // original by: Kevin van Zonneveld (https://kvz.io) 4 | // example 1: Index('Kevin', 'K') 5 | // returns 1: 0 6 | // example 2: Index('Kevin', 'Z') 7 | // returns 2: -1 8 | return String(s).indexOf(sep); 9 | } 10 | -------------------------------------------------------------------------------- /src/string/ends_with.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Item is the end of the target 3 | */ 4 | export default function endsWith(target, item, ignore) { 5 | let str = target.slice(-item.length); 6 | return ignore ? str.toLowerCase() === item.toLowerCase() : str === item; 7 | } 8 | -------------------------------------------------------------------------------- /src/string/fill_zero.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Increase by 0 based on string length before string 3 | */ 4 | export default function fillZero(target, n) { 5 | let z = new Array(n).join('0'); 6 | let str = z + target; 7 | let result = str.slice(-n); 8 | return result; 9 | } 10 | -------------------------------------------------------------------------------- /src/string/long_unique.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Long string unique 3 | */ 4 | export default function longUnique(target) { 5 | let json = {}; 6 | for (let index = 0; index < target.length; index++) { 7 | if (!json[target[index]]) { 8 | json[target[index]] = -1; 9 | } 10 | } 11 | let longString = ''; 12 | for (let index = 0; index < target.length; index++) { 13 | if (json[target[index]]) { 14 | json[target[index]] = 0; 15 | longString = longString + target[index]; 16 | } 17 | } 18 | return longString; 19 | } 20 | -------------------------------------------------------------------------------- /src/string/map_string.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates a new string with the results of calling a provided function 3 | * on every character in the calling string. 4 | */ 5 | const mapString = (str, fn) => 6 | str 7 | .split('') 8 | .map((c, i) => fn(c, i, str)) 9 | .join(''); 10 | 11 | export default mapString; 12 | -------------------------------------------------------------------------------- /src/string/mask.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Replaces all but the last num of characters with the specified mask character. 3 | */ 4 | const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask); 5 | export default mask; 6 | -------------------------------------------------------------------------------- /src/string/repeat.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Repeat item, times times 3 | */ 4 | export default function repeat(item, times) { 5 | let s = String(item); 6 | let target = ''; 7 | while (times > 0) { 8 | if (times % 2 === 1) { 9 | target += s; 10 | } 11 | if (times === 1) { 12 | break; 13 | } 14 | s += s; 15 | // eslint-disable-next-line no-param-reassign 16 | times = times >> 1; 17 | } 18 | return target; 19 | } 20 | -------------------------------------------------------------------------------- /src/string/split_lines.js: -------------------------------------------------------------------------------- 1 | /** 2 | * splitLines('This\nis a\nmultiline\nstring.\n') => 3 | * ['This', 'is a', 'multiline', 'string.' , ''] 4 | */ 5 | export default function splitLines(str) { 6 | return str.split(/\r?\n/); 7 | } 8 | -------------------------------------------------------------------------------- /src/string/starts_with.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Item is the beginning of the target 3 | */ 4 | export default function startsWith(target, item, ignore) { 5 | let str = String(target).slice(0, item.length); 6 | return ignore ? str.toLowerCase() === item.toLowerCase() : str === item; 7 | } 8 | -------------------------------------------------------------------------------- /src/string/strip_tags.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Remove the html tags inside the script 3 | */ 4 | export default function stripTags(target) { 5 | return target.replace(/]*>(\S\s*?)<\/script>/gim, '').replace(/<[^>]+>/g, ''); 6 | } 7 | -------------------------------------------------------------------------------- /src/string/trim.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Remove spaces after removing previous string 3 | */ 4 | import isEmpty from '../lodash/is_empty'; 5 | 6 | export default function trim(str) { 7 | if (isEmpty(str)) { 8 | return str; 9 | } 10 | return str.replace(/(^\s*)|(\s*$)/g, ''); 11 | } 12 | -------------------------------------------------------------------------------- /src/string/truncate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Truncates a string up to a specified length. 3 | * The default length is 3, and the truncated symbol defaults '...' 4 | */ 5 | import size from '../collection/size'; 6 | const truncate = (str, num = 3) => { 7 | const len = size(str); 8 | return len > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; 9 | }; 10 | 11 | export default truncate; 12 | -------------------------------------------------------------------------------- /src/string/underscored.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Turn CamelCase to '_' 3 | */ 4 | export default function underscored(target) { 5 | return target.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase(); 6 | } 7 | -------------------------------------------------------------------------------- /src/string/xss_filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * XSS string filtering 3 | */ 4 | export default function xssFilter(str) { 5 | return str 6 | .replace(/&/g, '&') 7 | .replace(//g, '>') 9 | .replace(/"/g, '"') 10 | .replace(/'/g, '''); 11 | } 12 | -------------------------------------------------------------------------------- /src/times/clear_timesout.js: -------------------------------------------------------------------------------- 1 | export default function clearTimesout(id) { 2 | return clearInterval(id); 3 | } 4 | -------------------------------------------------------------------------------- /src/times/format_duration.js: -------------------------------------------------------------------------------- 1 | const formatDuration = (ms) => { 2 | // eslint-disable-next-line no-param-reassign 3 | if (ms < 0) ms = -ms; 4 | const time = { 5 | day: Math.floor(ms / 86400000), 6 | hour: Math.floor(ms / 3600000) % 24, 7 | minute: Math.floor(ms / 60000) % 60, 8 | second: Math.floor(ms / 1000) % 60, 9 | millisecond: Math.floor(ms) % 1000 10 | }; 11 | return Object.entries(time) 12 | .filter((val) => val[1] !== 0) 13 | .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) 14 | .join(', '); 15 | }; 16 | 17 | export default formatDuration; 18 | -------------------------------------------------------------------------------- /src/times/format_pass_time.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Date} startTime timestamp 3 | * @return {String} 4 | */ 5 | const formatPassTime = (startTime) => { 6 | let seconds = Math.floor((new Date() - startTime) / 1000); 7 | let interval = seconds / 31536000; 8 | if (interval > 1) { 9 | return Math.floor(interval) + ' years'; 10 | } 11 | interval = seconds / 2592000; 12 | if (interval > 1) { 13 | return Math.floor(interval) + ' months'; 14 | } 15 | interval = seconds / 86400; 16 | if (interval > 1) { 17 | return Math.floor(interval) + ' days'; 18 | } 19 | interval = seconds / 3600; 20 | if (interval > 1) { 21 | return Math.floor(interval) + ' hours'; 22 | } 23 | interval = seconds / 60; 24 | if (interval > 1) { 25 | return Math.floor(interval) + ' minutes'; 26 | } 27 | return Math.floor(seconds) + ' seconds'; 28 | }; 29 | 30 | export default formatPassTime; 31 | -------------------------------------------------------------------------------- /src/times/format_remain_time.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @desc format the remaining time from ${endTime} 3 | * @param {Date} endTime 4 | * @return {String} 5 | */ 6 | const formatRemainTime = (endTime) => { 7 | let startDate = new Date(); // startDate 8 | let endDate = new Date(endTime); // endDate 9 | let t = endDate.getTime() - startDate.getTime(); 10 | let d = 0; 11 | let h = 0; 12 | let m = 0; 13 | let s = 0; 14 | if (t >= 0) { 15 | d = Math.floor(t / 1000 / 3600 / 24); 16 | h = Math.floor((t / 1000 / 60 / 60) % 24); 17 | m = Math.floor((t / 1000 / 60) % 60); 18 | s = Math.floor((t / 1000) % 60); 19 | } 20 | return d + 'day ' + h + 'hour ' + m + 'minute ' + s + 'second'; 21 | }; 22 | 23 | export default formatRemainTime; 24 | -------------------------------------------------------------------------------- /src/times/get_date.js: -------------------------------------------------------------------------------- 1 | import fill0 from '../fill/fill0'; 2 | 3 | /** 4 | * getDate 5 | * https://stackoverflow.com/questions/1531093/how-do-i-get-the-current-date-in-javascript 6 | */ 7 | const getDate = (d1, d2) => { 8 | let today = new Date(); 9 | 10 | let dd = today.getDate(); 11 | let mm = today.getMonth() + 1; 12 | let yyyy = today.getFullYear(); 13 | let hh = today.getHours(); 14 | let ms = today.getMinutes(); 15 | let ss = today.getSeconds(); 16 | 17 | dd = fill0(dd); 18 | mm = fill0(mm); 19 | hh = fill0(hh); 20 | ms = fill0(ms); 21 | ss = fill0(ss); 22 | 23 | let _d1 = d1 || '/'; 24 | let _d2 = d2 || ':'; 25 | 26 | return yyyy + _d1 + mm + _d1 + dd + ' ' + hh + _d2 + ms + _d2 + ss; 27 | }; 28 | 29 | export default getDate; 30 | -------------------------------------------------------------------------------- /src/times/retry.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-promise-reject-errors */ 2 | /** 3 | * @param {any} attempt 4 | * @param {any} options 5 | * interval: 200, //ms 6 | * retries: 2 7 | * timeout: 8000 //ms 8 | */ 9 | export default function(attempt, options) { 10 | const option = options || {}; 11 | let interval = option.interval || 400; 12 | let retries = option.retries || 2; 13 | let timeout = option.timeout || 8000; 14 | 15 | function rejectDelay(reason) { 16 | return new Promise(function(resolve, reject) { 17 | setTimeout(reject.bind(null, reason), interval); 18 | }); 19 | } 20 | 21 | let p = Promise.reject(); 22 | for (let i = 0; i < retries; i++) { 23 | p = p.catch(timeoutReject(attempt, timeout)).catch(rejectDelay); 24 | } 25 | 26 | return p; 27 | } 28 | 29 | function timeoutReject(task, timeout) { 30 | let timer; 31 | 32 | return function() { 33 | return Promise.race([ 34 | Promise.reject().catch(task), 35 | new Promise(function(rs, rj) { 36 | timer = setTimeout(function() { 37 | rj('timeout.'); 38 | }, timeout || 8000); 39 | }) 40 | ]).then( 41 | function(r) { 42 | clearTimeout(timer); 43 | return r; 44 | }, 45 | function(err) { 46 | return Promise.reject(err); 47 | } 48 | ); 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /src/times/set_timesout.js: -------------------------------------------------------------------------------- 1 | import args from '../args/args'; 2 | import clearTimesout from '../times/clear_timesout'; 3 | /** 4 | * setInterval func fix times 5 | * https://stackoverflow.com/questions/2956966/javascript-telling-setinterval-to-only-fire-x-amount-of-times 6 | */ 7 | export default function setTimesout() { 8 | let func = arguments[0]; 9 | let delay = arguments[1] === undefined ? 0 : parseFloat(arguments[1]); 10 | let times = arguments[2] === undefined ? 1 : parseInt(arguments[2], 10); 11 | let _args = arguments.length > 3 ? args(arguments, 3) : null; 12 | let target = { 13 | index: 0, 14 | times: times, 15 | over: false 16 | }; 17 | 18 | let id = setInterval(function() { 19 | target.index++; 20 | if (target.index > times) { 21 | clearTimesout(id); 22 | } else { 23 | if (target.index === times) target.over = true; 24 | func.apply(target, _args); 25 | } 26 | }, delay); 27 | 28 | return id; 29 | } 30 | -------------------------------------------------------------------------------- /src/times/sleep.js: -------------------------------------------------------------------------------- 1 | const cachedSetTimeout = setTimeout; 2 | 3 | function createSleepPromise(timeout, { useCachedSetTimeout }) { 4 | const timeoutFunction = useCachedSetTimeout ? cachedSetTimeout : setTimeout; 5 | 6 | return new Promise((resolve) => { 7 | timeoutFunction(resolve, timeout); 8 | }); 9 | } 10 | 11 | export default function sleep(timeout, { useCachedSetTimeout } = {}) { 12 | const sleepPromise = createSleepPromise(timeout, { useCachedSetTimeout }); 13 | 14 | function promiseFunction(value) { 15 | return sleepPromise.then(() => value); 16 | } 17 | 18 | promiseFunction.then = (...args) => sleepPromise.then(...args); 19 | promiseFunction.catch = Promise.resolve().catch; 20 | 21 | return promiseFunction; 22 | } 23 | -------------------------------------------------------------------------------- /src/util/get_global.js: -------------------------------------------------------------------------------- 1 | let globalObject = null; 2 | 3 | function getGlobalObject() { 4 | if (globalObject !== null) { 5 | return globalObject; 6 | } 7 | /* istanbul ignore next */ 8 | // It's hard to mock the global variables. This code surely works fine. I hope :) 9 | if (typeof global === 'object' && global.Object === Object) { 10 | // NodeJS global object 11 | globalObject = global; 12 | } else if (typeof self === 'object' && self.Object === Object) { 13 | // self property from Window object 14 | globalObject = self; 15 | } else { 16 | // Other cases. Function constructor always has the context as global object 17 | // eslint-disable-next-line no-new-func 18 | globalObject = new Function('return this')(); 19 | } 20 | return globalObject; 21 | } 22 | 23 | export default getGlobalObject; 24 | -------------------------------------------------------------------------------- /src/util/no_conflict.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-invalid-this */ 2 | import getGlobalObject from './get_global'; 3 | 4 | const globalObject = getGlobalObject(); 5 | const previous = globalObject.bbo; 6 | 7 | export default function noConflict() { 8 | if (this === globalObject.bbo) { 9 | globalObject.bbo = previous; 10 | } 11 | return this; 12 | } 13 | -------------------------------------------------------------------------------- /src/util/version.js: -------------------------------------------------------------------------------- 1 | const version = '1.1.26'; 2 | 3 | export default version; 4 | -------------------------------------------------------------------------------- /test/args/args.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('args', () => { 4 | test('bbo.args is a Function', () => { 5 | expect(bbo.args).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('bbo.args works for slice', () => { 9 | function foo(a, b, c, d) { 10 | return bbo.args(arguments); 11 | } 12 | 13 | expect(foo(1, 2, 3)).toEqual([1, 2, 3]); 14 | expect(foo(1, 2, 3, 4, 5)).toEqual([1, 2, 3, 4, 5]); 15 | }); 16 | 17 | test('bbo.args(arguments, first?) first defalult is 0', () => { 18 | function boo(a, b, c, d) { 19 | return bbo.args(arguments, 1); 20 | } 21 | expect(boo(1, 2, 3, 4)).toEqual([2, 3, 4]); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/args/call.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('call', () => { 4 | test('bbo.call is a Function', () => { 5 | expect(bbo.call).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('calls function on given object', () => { 9 | expect(bbo.call('map', (x) => x * 2)([1, 2, 3])).toEqual([2, 4, 6]); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/args/has_own_property.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('hasOwnProperty', () => { 4 | test('bbo.hasOwnProperty is a Function', () => { 5 | expect(bbo.hasOwnProperty).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('should pass example 1', () => { 9 | const object = {}; 10 | object.property1 = 42; 11 | 12 | expect(bbo.hasOwnProperty(object, 'property1')).toBe(true); 13 | expect(bbo.hasOwnProperty(object, 'toString')).toBe(false); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/args/merge.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('merge', () => { 4 | test('bbo.merge is a Function', () => { 5 | expect(bbo.merge).toBeInstanceOf(Function); 6 | }); 7 | 8 | const object = { 9 | a: [{ x: 2 }, { y: 4 }], 10 | b: 1 11 | }; 12 | const other = { 13 | a: { z: 3 }, 14 | b: [2, 3], 15 | c: 'foo' 16 | }; 17 | test('merge two objects', () => { 18 | expect(bbo.merge(object, other)).toEqual({ 19 | a: [{ x: 2 }, { y: 4 }, { z: 3 }], 20 | b: [1, 2, 3], 21 | c: 'foo' 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/args/noop.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('noop', () => { 4 | test('bbo.noop is a Function', () => { 5 | expect(bbo.noop).toBeInstanceOf(Function); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/args/over.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('over', () => { 4 | test('bbo.over is a Function', () => { 5 | expect(bbo.over).toBeInstanceOf(Function); 6 | }); 7 | const minMax = bbo.over(Math.min, Math.max); 8 | test('Applies given functions over multiple arguments', () => { 9 | expect(minMax(1, 2, 3, 4, 5)).toEqual([1, 5]); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/array/all.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('all', () => { 4 | it('base case', () => { 5 | expect(bbo.all([4, 2, 3], (x) => x > 1)).toBe(true); 6 | expect(bbo.all([4, 2, 3], (x) => x < 1)).toBe(false); 7 | expect(bbo.all([1, 2, 3])).toBe(true); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/array/all_equal.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('allEqual', () => { 4 | it('base case', () => { 5 | expect(bbo.allEqual(['a', 'a', 'a', 'a'])).toBe(true); 6 | expect(bbo.allEqual(['a', 'a', 'b', 'a'])).toBe(false); 7 | }); 8 | 9 | it('base case2', () => { 10 | expect(bbo.allEqual(['false', ''])).toBe(false); 11 | expect(bbo.allEqual(['false', 'false'])).toBe(true); 12 | expect(bbo.allEqual(['false', false])).toBe(false); 13 | expect(bbo.allEqual([NaN, NaN])).toBe(false); 14 | }); 15 | 16 | // it('special case', () => { 17 | // expect(bbo.allEqual(null)).toBe(false); 18 | // expect(bbo.allEqual([])).toBe(true); 19 | // expect(bbo.allEqual({})).toBe(false); 20 | // expect(bbo.allEqual([1])).toBe(false); 21 | // expect(bbo.allEqual([1, 2])).toBe(false); 22 | // expect(bbo.allEqual(NaN)).toBe(false); 23 | // }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/array/any.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('any', () => { 4 | it('base case', () => { 5 | expect(bbo.any([4, 2, 3], (x) => x > 1)).toBe(true); 6 | expect(bbo.any([4, 2, 3], (x) => x < 1)).toBe(false); 7 | expect(bbo.any([1, 2, 3])).toBe(true); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/array/chunk.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('chunk', () => { 4 | it('base case', () => { 5 | expect(bbo.chunk([1, 2, 3, 4, 5], 2)).toEqual([[1, 2], [3, 4], [5]]); 6 | expect(bbo.chunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 4)).toEqual([ 7 | [1, 2, 3, 4], 8 | [5, 6, 7, 8], 9 | [9, 10, 11, 12], 10 | [13, 14, 15] 11 | ]); 12 | expect(bbo.chunk([], 3)).toEqual([]); 13 | expect(bbo.chunk([1, 2, 3], 4)).toEqual([[1, 2, 3]]); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/array/column.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('column', () => { 4 | const array = [ 5 | { name: 'a', value: 1 }, 6 | { name: 'b', value: 2 }, 7 | { name: 'c', value: 3 } 8 | ]; 9 | 10 | const object = { 11 | 0: { name: 'a', value: 1 }, 12 | 1: { name: 'b', value: 2 }, 13 | 2: { name: 'c', value: 3 } 14 | }; 15 | 16 | it('base case', () => { 17 | expect(bbo.column(array, 'name')).toEqual({ 0: 'a', 1: 'b', 2: 'c' }); 18 | expect(bbo.column(array, 'name', null)).toEqual({ 0: 'a', 1: 'b', 2: 'c' }); 19 | expect(bbo.column(array, 'name', 1)).toEqual({ 0: 'a', 1: 'b', 2: 'c' }); 20 | expect(bbo.column(array, null, 5)).toEqual(object); 21 | expect(bbo.column(array, 'name', 5)).toEqual({ 0: 'a', 1: 'b', 2: 'c' }); 22 | expect(bbo.column(array, 'name', 'value')).toEqual({ 1: 'a', 2: 'b', 3: 'c' }); 23 | expect(bbo.column(object, 'name')).toEqual({ 0: 'a', 1: 'b', 2: 'c' }); 24 | expect(bbo.column(object, 'name', 'value')).toEqual({ 1: 'a', 2: 'b', 3: 'c' }); 25 | expect(bbo.column(object, 'name', 1)).toEqual({ 0: 'a', 1: 'b', 2: 'c' }); 26 | expect(bbo.column(object, null, 'value')).toEqual({ 27 | 1: { name: 'a', value: 1 }, 28 | 2: { name: 'b', value: 2 }, 29 | 3: { name: 'c', value: 3 } 30 | }); 31 | }); 32 | 33 | test('bbo.column throws', () => { 34 | expect(() => { 35 | bbo.column(null); 36 | }).toThrow(); 37 | 38 | expect(() => { 39 | bbo.column({}, [], 1); 40 | }); 41 | 42 | expect(() => { 43 | bbo.column(null); 44 | }).toThrow(); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /test/array/compact.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('compact', () => { 4 | it('base case', () => { 5 | expect(bbo.compact([0, 1, false, 2, '', 3], 3)).toEqual([1, 2, 3]); 6 | 7 | const array = [1, 2, 3, 4, 5]; 8 | expect(bbo.compact([1, null, 2, undefined, null, NaN, 3, 4, false, 5], 3)).toEqual(array); 9 | 10 | expect(bbo.compact([1, 7, undefined, null, '', 0, false])).toEqual([1, 7]); 11 | expect(bbo.compact([1, 2, [], 4, {}])).toEqual([1, 2, [], 4, {}]); 12 | expect(bbo.compact([])).toEqual([]); 13 | }); 14 | 15 | test('bbo.compact !isArray throws an error', () => { 16 | expect(() => { 17 | bbo.compact(null); 18 | }).toThrow(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/array/contains.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('contains', () => { 4 | it('base case', () => { 5 | expect(bbo.contains([1, 2, 3], 1)).toBe(true); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/array/copy_array.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('copyArray', () => { 4 | it('base case', () => { 5 | expect(bbo.copyArray([])).toEqual([]); 6 | expect(bbo.copyArray([1, 2, 3])).toEqual([1, 2, 3]); 7 | 8 | // eslint-disable-next-line no-array-constructor 9 | const array = new Array(); 10 | expect(bbo.copyArray(array)).toEqual(array); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/array/count_by.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('countBy', () => { 4 | it('base case', () => { 5 | expect(bbo.countBy([6, 10, 100, 10], Math.sqrt)).toEqual({ 6 | '10': 1, 7 | '2.449489742783178': 1, 8 | '3.1622776601683795': 2 9 | }); 10 | expect(bbo.countBy([6.1, 4.2, 6.3], Math.floor)).toEqual({ 4: 1, 6: 2 }); 11 | expect(bbo.countBy(['one', 'two', 'three'], 'length')).toEqual({ 3: 2, 5: 1 }); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/array/count_occurrences.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('countOccurrences', () => { 4 | it('base case', () => { 5 | expect(bbo.countOccurrences([1, 1, 2, 1, 2, 3], 1)).toBe(3); 6 | expect(bbo.countOccurrences([1, 1, 2, 1, 2, 3], 2)).toBe(2); 7 | expect(bbo.countOccurrences([1, 1, 2, 1, 2, 3], 3)).toBe(1); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/array/difference.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('difference', () => { 4 | it('base case', () => { 5 | expect(bbo.difference([], [])).toEqual([]); 6 | expect(bbo.difference([1, 2, 3], [4, 2, 6])).toEqual([1, 3]); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/array/difference_by.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('differenceBy', () => { 4 | it('base case', () => { 5 | expect(bbo.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor)).toEqual([1]); 6 | expect(bbo.differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], (v) => v.x)).toEqual([2]); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/array/drop.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('drop', () => { 4 | it('base case', () => { 5 | expect(bbo.drop([1, 2, 3])).toEqual([2, 3]); 6 | expect(bbo.drop([1, 2, 3], 2)).toEqual([3]); 7 | expect(bbo.drop([1, 2, 3], 42)).toEqual([]); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/array/dropWhile.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('dropWhile', () => { 4 | it('base case', () => { 5 | expect(bbo.dropWhile([1, 2, 3, 4], (n) => n >= 3)).toEqual([3, 4]); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/array/drop_right.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('dropRight', () => { 4 | it('base case', () => { 5 | expect(bbo.dropRight([1, 2, 3])).toEqual([1, 2]); 6 | expect(bbo.dropRight([1, 2, 3], 2)).toEqual([1]); 7 | expect(bbo.dropRight([1, 2, 3], 42)).toEqual([]); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/array/drop_right_while.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('dropRightWhile', () => { 4 | it('base case', () => { 5 | expect(bbo.dropRightWhile([1, 2, 3, 4], (n) => n < 3)).toEqual([1, 2]); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/array/equal.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('equal', () => { 4 | it('base case', () => { 5 | expect(bbo.equal([1], [1, 2])).toBe(false); 6 | expect(bbo.equal([1, 2, 3], [1, 2, 3])).toBe(true); 7 | expect(bbo.equal([1, 2, 3], [1, 2, 4])).toBe(false); 8 | expect(bbo.equal([], [])).toBe(true); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/array/includes_all.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('includesAll', () => { 4 | it('base case', () => { 5 | expect(bbo.includesAll([1, 2, 3], [1, 2, 3])).toBe(true); 6 | expect(bbo.includesAll([1, 7, 2, 5, 4], [5])).toBe(true); 7 | expect(bbo.includesAll([1, 7, 2, 5, 4], [5, 4])).toBe(true); 8 | expect(bbo.includesAll([], [])).toBe(true); 9 | expect(bbo.includesAll([1, 7, 2, 5, 4], [5, 4, 3])).toBe(false); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/array/includes_any.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('includesAny', () => { 4 | it('base case', () => { 5 | expect(bbo.includesAny([1, 2, 3], [1, 2, 3])).toBe(true); 6 | expect(bbo.includesAny([1, 7, 2, 5, 4], [5])).toBe(true); 7 | expect(bbo.includesAny([1, 7, 2, 5, 4], [5, 4])).toBe(true); 8 | expect(bbo.includesAny([], [])).toBe(false); 9 | expect(bbo.includesAny([1, 7, 2, 5, 4], [5, 4, 3])).toBe(true); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/array/index_by.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('indexBy', () => { 4 | const array = [ 5 | { id: 'first', val: 1 }, 6 | { id: 'second', val: 2 } 7 | ]; 8 | 9 | it('base case', () => { 10 | expect(bbo.indexBy(array, 'id')).toEqual({ 11 | first: { id: 'first', val: 1 }, 12 | second: { id: 'second', val: 2 } 13 | }); 14 | 15 | expect(bbo.indexBy([{ id: 'first', val: 1 }, null], 'id')).toEqual({ 16 | first: { id: 'first', val: 1 } 17 | }); 18 | 19 | expect(bbo.indexBy([], 'id')).toEqual({}); 20 | }); 21 | 22 | test('bbo.indexBy !isArray throws an error', () => { 23 | expect(() => { 24 | bbo.indexBy('', 1); 25 | }).toThrow(); 26 | 27 | expect(() => { 28 | bbo.indexBy([], []); 29 | }).toThrow(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/array/intersect.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('intersect', () => { 4 | it('base case', () => { 5 | expect(bbo.intersect([1, 2, 3], [4, 3, 2])).toEqual([2, 3]); 6 | expect(bbo.intersect([1, 2, 3], [])).toEqual([]); 7 | expect(bbo.intersect([], [4, 3, 2])).toEqual([]); 8 | expect(bbo.intersect([], [])).toEqual([]); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/array/intersect_by.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('intersectBy', () => { 4 | it('base case', () => { 5 | expect(bbo.intersectBy([2.1, 1.2], [2.3, 3.4], Math.floor)).toEqual([2.1]); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/array/max.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | // import lodashStable from 'lodash'; 3 | // import { falsey, noop } from '../const'; 4 | import assert from 'assert'; 5 | 6 | describe('max', function() { 7 | it('should return the largest value from a collection', function() { 8 | assert.strictEqual(bbo.max([1, 2, 3]), 3); 9 | }); 10 | 11 | // it('should return `undefined` for empty collections', function() { 12 | // let values = falsey.concat([[]]); 13 | // let expected = lodashStable.map(values, noop); 14 | 15 | // let actual = lodashStable.map(values, function(value, index) { 16 | // try { 17 | // return index ? bbo.max(value) : bbo.max(); 18 | // } catch (e) {} 19 | // }); 20 | 21 | // assert.deepStrictEqual(actual, expected); 22 | // }); 23 | 24 | // it('should work with non-numeric collection values', function() { 25 | // assert.strictEqual(bbo.max(['a', 'b']), 'b'); 26 | // }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/array/min.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import assert from 'assert'; 3 | 4 | describe('min', function() { 5 | it('should return the largest value from a collection', function() { 6 | assert.strictEqual(bbo.min([1, 2, 3]), 1); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/array/pluck.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('pluck', () => { 4 | const array = [{ a: 1 }, { a: 2 }]; 5 | 6 | it('base case', () => { 7 | expect(bbo.pluck(array, 'a')).toEqual([1, 2]); 8 | }); 9 | 10 | it('base case2', () => { 11 | expect(bbo.pluck(array)).toEqual([]); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/array/random.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { deburredLetters } from '../const'; 3 | 4 | describe('random', () => { 5 | const random = bbo.random(deburredLetters); 6 | it('base case', () => { 7 | expect(bbo.contains(deburredLetters, random)).toBe(true); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/array/random_size.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { deburredLetters } from '../const'; 3 | 4 | describe('random', () => { 5 | const random = bbo.randomSize(deburredLetters, Math.floor(Math.random() * 50) + 1); 6 | it('base case', () => { 7 | expect(bbo.includesAll(deburredLetters, random)).toBe(true); 8 | expect(bbo.randomSize([1])).toEqual([1]); 9 | expect(bbo.randomSize([])).toEqual([]); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/array/remove.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('remove', () => { 4 | it('base case', () => { 5 | const array = [1, 2, 3, 4, 5]; 6 | expect(bbo.remove(array, [2, 4])).toEqual([1, 3, 5]); 7 | expect(bbo.remove(array, [])).toEqual(array); 8 | }); 9 | 10 | test('bbo.remove !isArray throws an error', () => { 11 | expect(() => { 12 | bbo.remove(true, 'str'); 13 | }).toThrow(); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/array/remove_at.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('removeAt', () => { 4 | it('base case', () => { 5 | const array = [1, 2, 3, 4, 5, 6]; 6 | const removeType1 = bbo.removeAt(array, 7); 7 | const removeType2 = bbo.removeAt(array, 0); 8 | 9 | expect(removeType1).toBe(false); 10 | expect(removeType2).toBe(true); 11 | }); 12 | 13 | it('base to equal', () => { 14 | const array1 = [1, 2, 3, 4, 5, 6]; 15 | bbo.removeAt(array1, 0); 16 | expect(array1).toEqual([2, 3, 4, 5, 6]); 17 | 18 | const array2 = [1, 2, 3, 4, 5, 6]; 19 | bbo.removeAt(array2, 7); 20 | expect(array2).toBe(array2); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/array/shuffle.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('shuffle', () => { 4 | const arr = [2.3, 100, 75, 120]; 5 | it('base case 1', () => { 6 | const result = bbo.shuffle(arr); 7 | const len = result.length; 8 | expect(len).toEqual(4); 9 | }); 10 | 11 | it('base case 2', () => { 12 | const result = bbo.shuffle(arr); 13 | expect(bbo.includesAll(arr, result)).toBe(true); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/array/split.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('split', () => { 4 | const array = [1, 2, 3, 4, 5]; 5 | 6 | it('base case 1', () => { 7 | expect(bbo.split(array, 2)).toEqual([[1, 2], [3, 4], [5]]); 8 | expect(bbo.split([], 3)).toEqual([]); 9 | 10 | expect(bbo.split([], null)).toEqual([]); 11 | }); 12 | 13 | test('bbo.split !isArray throws an error', () => { 14 | expect(() => { 15 | bbo.split('', 1); 16 | }).toThrow(); 17 | 18 | expect(() => { 19 | bbo.split([], 'a'); 20 | }).toThrow(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/array/unary.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('unary', () => { 4 | test('unary is a Function', () => { 5 | expect(bbo.unary).toBeInstanceOf(Function); 6 | }); 7 | test('Discards arguments after the first one', () => { 8 | expect(['6', '8', '10'].map(bbo.unary(parseInt))).toEqual([6, 8, 10]); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/array/union_by.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('unionBy', () => { 4 | test('unionBy is a Function', () => { 5 | expect(bbo.unionBy).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('Produces the appropriate results', () => { 9 | expect(bbo.unionBy([2.1], [1.2, 2.3], Math.floor)).toEqual([2.1, 1.2]); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/array/union_with.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('unionWith', () => { 4 | test('unionWith is a Function', () => { 5 | expect(bbo.unionWith).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('Produces the appropriate results', () => { 9 | expect( 10 | bbo.unionWith( 11 | [1, 1.2, 1.5, 3, 0], 12 | [1.9, 3, 0, 3.9], 13 | (a, b) => Math.round(a) === Math.round(b) 14 | ) 15 | ).toEqual([1, 1.2, 1.5, 3, 0, 3.9]); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/array/unique_by.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('uniqueBy', () => { 4 | test('bbo.uniqueBy is a Function', () => { 5 | expect(bbo.uniqueBy).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('bbo.uniqueBy works for properties', () => { 9 | expect( 10 | bbo.uniqueBy( 11 | [ 12 | { id: 0, value: 'a' }, 13 | { id: 1, value: 'b' }, 14 | { id: 2, value: 'c' }, 15 | { id: 1, value: 'd' }, 16 | { id: 0, value: 'e' } 17 | ], 18 | (a, b) => a.id === b.id 19 | ) 20 | ).toEqual([ 21 | { id: 0, value: 'a' }, 22 | { id: 1, value: 'b' }, 23 | { id: 2, value: 'c' } 24 | ]); 25 | }); 26 | 27 | test('bbo.uniqueBy works for nested properties', () => { 28 | expect( 29 | bbo.uniqueBy( 30 | [ 31 | { id: 0, value: 'a', n: { p: 0 } }, 32 | { id: 1, value: 'b', n: { p: 1 } }, 33 | { id: 2, value: 'c', n: { p: 2 } }, 34 | { id: 1, value: 'd', n: { p: 0 } }, 35 | { id: 0, value: 'e', n: { p: 1 } } 36 | ], 37 | (a, b) => a.id === b.id 38 | ) 39 | ).toEqual([ 40 | { id: 0, value: 'a', n: { p: 0 } }, 41 | { id: 1, value: 'b', n: { p: 1 } }, 42 | { id: 2, value: 'c', n: { p: 2 } } 43 | ]); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /test/array/unique_from.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('uniqueFrom', () => { 4 | test('bbo.uniqueFrom is a Function', () => { 5 | expect(bbo.uniqueFrom).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('bbo.uniqueFrom works for properties', () => { 9 | let array = [ 10 | { name: 'n1', id: '1' }, 11 | { name: 'n2', id: '11' }, 12 | { name: 'n3', id: '12' }, 13 | { name: 'n2', id: '11' } 14 | ]; 15 | 16 | expect(bbo.uniqueFrom(array, 'name')).toEqual([ 17 | { name: 'n1', id: '1' }, 18 | { name: 'n2', id: '11' }, 19 | { name: 'n3', id: '12' } 20 | ]); 21 | 22 | expect(bbo.uniqueFrom(array, 'id')).toEqual([ 23 | { name: 'n1', id: '1' }, 24 | { name: 'n2', id: '11' }, 25 | { name: 'n3', id: '12' } 26 | ]); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/bbo.js: -------------------------------------------------------------------------------- 1 | import bbo from '../src/index'; 2 | export default bbo; 3 | -------------------------------------------------------------------------------- /test/behavior/copy_to_clipboard.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('copyToClipboard', () => { 4 | test('copyToClipboard is a Function', () => { 5 | expect(bbo.copyToClipboard).toBeInstanceOf(Function); 6 | }); 7 | test('copyToClipboard does not throw errors', () => { 8 | document.getSelection = function() { 9 | return { 10 | rangeCount: 0, 11 | removeAllRanges() { 12 | return; 13 | }, 14 | addRange(x) { 15 | return x; 16 | } 17 | }; 18 | }; 19 | document.execCommand = function(x) { 20 | return x; 21 | }; 22 | 23 | expect(bbo.copyToClipboard('hi')).toBe(undefined); 24 | }); 25 | test('copyToClipboard does not throw errors', () => { 26 | document.getSelection = function() { 27 | return { 28 | rangeCount: 1, 29 | getRangeAt(x) { 30 | return x + 1; 31 | }, 32 | removeAllRanges() { 33 | return; 34 | }, 35 | addRange(x) { 36 | return x; 37 | } 38 | }; 39 | }; 40 | document.execCommand = function(x) { 41 | return x; 42 | }; 43 | 44 | expect(bbo.copyToClipboard('hi')).toBe(undefined); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /test/behavior/lock_touch.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('lockTouch', () => { 4 | it('should pass example 1', () => { 5 | const button = document.createElement('button'); 6 | button.innerText = 'click me'; 7 | document.body.appendChild(button); 8 | const buttons = document.querySelectorAll('button'); 9 | 10 | expect(buttons).toHaveLength(1); // true 11 | expect(buttons[0].innerText).toBe('click me'); // true 12 | 13 | buttons[0].addEventListener('touchmove', (e) => { 14 | e.target.innerText = 'touchmoved'; 15 | }); 16 | 17 | buttons[0].addEventListener('touchstart', (e) => { 18 | e.target.innerText = 'touchstartd'; 19 | }); 20 | expect(buttons[0].innerText).not.toBe('touchmoved'); // true 21 | 22 | const touchmove = new Event('touchmove'); 23 | buttons[0].dispatchEvent(touchmove); 24 | expect(buttons[0].innerText).toBe('touchmoved'); // true 25 | 26 | bbo.lockTouch(); 27 | 28 | const touchstart = new Event('touchstart'); 29 | buttons[0].dispatchEvent(touchstart); 30 | 31 | expect(buttons[0].innerText).toBe('touchstartd'); // true 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/behavior/trigger.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-return-assign */ 2 | import bbo from '../bbo'; 3 | 4 | describe('trigger', () => { 5 | test('triggers an event', () => { 6 | let el = document.createElement('div'); 7 | let val = false; 8 | const fn = () => (val = true); 9 | el.addEventListener('click', fn); 10 | bbo.trigger(el, 'click', 'MouseEvents'); 11 | expect(val).toBeTruthy(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/bom/attr.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('attr', () => { 4 | test('set attributes', function() { 5 | const button = document.createElement('button'); 6 | button.innerText = 'click me'; 7 | bbo.attr(button, 'sid', 'btn'); 8 | document.body.appendChild(button); 9 | const buttons = document.querySelectorAll('button'); 10 | expect(buttons[0].innerText).toBe('click me'); // true 11 | 12 | let output = {}; 13 | const attrs = buttons[0].attributes; 14 | if (buttons[0].hasAttributes()) { 15 | for (let i = attrs.length - 1; i >= 0; i--) { 16 | const name = attrs[i].name; 17 | output[name] = attrs[i].value; 18 | } 19 | expect(output['sid']).toBe('btn'); // true 20 | } 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/bom/c.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('c', () => { 4 | test('createElement & set attributes', function() { 5 | const button = bbo.c('button', 'className', 'click me', 'idName'); 6 | document.body.appendChild(button); 7 | const buttons = document.querySelectorAll('button'); 8 | 9 | expect(buttons[0].nodeName.toLowerCase()).toBe('button'); 10 | expect(buttons[0].className).toBe('className'); 11 | expect(buttons[0].textContent).toBe('click me'); 12 | expect(buttons[0].id).toBe('idName'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/bom/element_contains.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('elementContains', () => { 4 | test('elementContains is a Function', () => { 5 | expect(bbo.elementContains).toBeInstanceOf(Function); 6 | }); 7 | test('elementContains returns true', () => { 8 | let p = document.createElement('div'); 9 | let c = p.appendChild(document.createElement('div')); 10 | expect(bbo.elementContains(p, c)).toBeTruthy(); 11 | }); 12 | test('elementContains returns false', () => { 13 | let p = document.createElement('div'); 14 | let c = document.createElement('div'); 15 | expect(bbo.elementContains(p, c)).toBeFalsy(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/bom/g.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('g', () => { 4 | test('return document.getElementById', function() { 5 | const button = document.createElement('button'); 6 | button.innerText = 'click me'; 7 | button.setAttribute('id', 'idName'); 8 | document.body.appendChild(button); 9 | const buttons = document.querySelectorAll('button'); 10 | expect(buttons[0].innerText).toBe('click me'); 11 | 12 | expect(buttons[0].id).toBe('idName'); 13 | expect(bbo.g('idName')).toEqual(buttons[0]); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/bom/gc.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('gc', () => { 4 | test('return getElementsByClassName', function() { 5 | const button = document.createElement('button'); 6 | button.innerText = 'click me'; 7 | button.setAttribute('class', 'className'); 8 | document.body.appendChild(button); 9 | const buttons = document.querySelectorAll('button'); 10 | expect(buttons[0].innerText).toBe('click me'); 11 | 12 | expect(buttons[0].className).toBe('className'); 13 | expect(bbo.gc('className')[0]).toEqual(buttons[0]); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/bom/get_style.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('getStyle', () => { 4 | test('return getComputedStyle', function() { 5 | const button = document.createElement('button'); 6 | button.innerText = 'click me'; 7 | button.setAttribute('class', 'className'); 8 | button.style['display'] = 'none'; 9 | document.body.appendChild(button); 10 | 11 | expect(getComputedStyle(button)['display']).toEqual('none'); 12 | expect(bbo.getStyle(button, 'display')).toEqual('none'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/bom/hide.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('hide', () => { 4 | test('hide hides an element', () => { 5 | let el = document.createElement('div'); 6 | el.setAttribute('style', 'display: block;'); 7 | bbo.hide(el); 8 | expect(el.style.display).toBe('none'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/bom/open.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('hide', () => { 4 | test('open url', () => { 5 | const url = 'https://www.google.com/'; 6 | bbo.open(url); 7 | const href = document.querySelectorAll('a'); 8 | expect(url).toBe(href[0].href); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/bom/query.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('query', () => { 4 | test('query return document.querySelector', function() { 5 | const button = document.createElement('button'); 6 | button.innerText = 'click me'; 7 | button.setAttribute('class', 'className'); 8 | document.body.appendChild(button); 9 | const buttons = document.querySelectorAll('button'); 10 | expect(buttons[0].innerText).toBe('click me'); 11 | 12 | expect(buttons[0].className).toBe('className'); 13 | expect(buttons[0]).toEqual(bbo.query('button')); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/bom/set_style.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('setStyle', () => { 4 | test('return getComputedStyle', function() { 5 | const button = document.createElement('button'); 6 | button.innerText = 'click me'; 7 | button.setAttribute('class', 'className'); 8 | button.style['display'] = 'none'; 9 | document.body.appendChild(button); 10 | 11 | expect(getComputedStyle(button)['display']).toEqual('none'); 12 | expect(bbo.getStyle(button, 'display')).toEqual('none'); 13 | 14 | bbo.setStyle(button, 'display', 'block'); 15 | expect(getComputedStyle(button)['display']).toEqual('block'); 16 | expect(bbo.getStyle(button, 'display')).toEqual('block'); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/bom/show.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('show', () => { 4 | test('show shows an element', () => { 5 | let el = document.createElement('div'); 6 | el.setAttribute('style', 'display: none;'); 7 | bbo.show(el); 8 | expect(el.style.display).not.toBe('none'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/bom/stop_propagation.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('stopPropagation', () => { 4 | it('should pass example', () => { 5 | const button = document.createElement('button'); 6 | button.innerText = 'click me'; 7 | document.body.appendChild(button); 8 | const buttons = document.querySelectorAll('button'); 9 | 10 | expect(buttons[0].innerText).toBe('click me'); // true 11 | 12 | buttons[0].addEventListener('touchmove', (e) => { 13 | e.target.innerText = 'touchmoved'; 14 | }); 15 | 16 | bbo.stopPropagation(buttons); 17 | 18 | const touchmove = new Event('touchmove'); 19 | buttons[0].dispatchEvent(touchmove); 20 | 21 | expect(buttons[0].innerText).toBe('touchmoved'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/chain/chain.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('chain', function() { 4 | it('should calculate the result using explicit chaining', function() { 5 | expect(bbo.chain('Hello world').value()).toBe('Hello world'); 6 | expect( 7 | bbo 8 | .chain(' Hello world ') 9 | .trim() 10 | .value() 11 | ).toBe('Hello world'); 12 | 13 | expect( 14 | bbo 15 | .chain(' to-upper-case ') 16 | .trim() 17 | .camelize() 18 | .value() 19 | ).toBe('toUpperCase'); 20 | 21 | expect( 22 | bbo 23 | .chain([1, 1, 2, 3, 4, 2]) 24 | .unique() 25 | .split(2) 26 | .value() 27 | ).toEqual([ 28 | [1, 2], 29 | [3, 4] 30 | ]); 31 | }); 32 | 33 | it('wrapper object', function() { 34 | const obj = { a: { aa: { aaa: 2 } }, b: 4 }; 35 | expect( 36 | JSON.stringify( 37 | bbo 38 | .chain(obj) 39 | .get('a') 40 | .get('aa') 41 | .value() 42 | ) 43 | ).toBe('{"aaa":2}'); 44 | }); 45 | 46 | it('should allow to pass thru the wrapped value', function() { 47 | expect( 48 | bbo('Hello world') 49 | .chain() 50 | .deCapitalize() 51 | .thru(function(words) { 52 | return words[0] + 1; 53 | }) 54 | .value() 55 | ).toBe('h1'); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/collection/entries.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('entries', () => { 4 | test('regular objects return pairs of property/value', function() { 5 | expect(bbo.entries({ c: 8, a: 4 })).toEqual([ 6 | ['c', 8], 7 | ['a', 4] 8 | ]); 9 | 10 | expect(bbo.entries({ b: { bb: 4 }, a: { aa: 2 } })).toEqual([ 11 | ['b', { bb: 4 }], 12 | ['a', { aa: 2 }] 13 | ]); 14 | 15 | expect(bbo.entries({})).toEqual([]); 16 | }); 17 | 18 | test('arrays return pairs of index/value', function() { 19 | expect(bbo.entries([{ c: 8 }, { a: 4 }])).toEqual([ 20 | ['0', { c: 8 }], 21 | ['1', { a: 4 }] 22 | ]); 23 | 24 | expect(bbo.entries([])).toEqual([]); 25 | }); 26 | 27 | test('irregular objects return pairs of property/value', function() { 28 | expect(bbo.entries(new String('hello'))).toEqual([ 29 | ['0', 'h'], 30 | ['1', 'e'], 31 | ['2', 'l'], 32 | ['3', 'l'], 33 | ['4', 'o'] 34 | ]); 35 | 36 | expect( 37 | bbo.entries(function(a, b) { 38 | return a + b; 39 | }) 40 | ).toEqual([]); 41 | 42 | const fn = function() {}; 43 | fn.a = 4; 44 | expect(bbo.entries(fn)).toEqual([['a', 4]]); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /test/collection/flush.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('flush', () => { 4 | test('removes null/undefined from array', function() { 5 | expect(bbo.flush([1, undefined, 2, null, 3, 0])).toEqual([1, 2, 3, 0]); 6 | expect(bbo.flush([true, null, false, true, [null], undefined])).toEqual([ 7 | true, 8 | false, 9 | true, 10 | [null] 11 | ]); 12 | }); 13 | 14 | test('removes null/undefined from object', function() { 15 | expect(bbo.flush({ a: 2, b: null, c: 4, d: undefined })).toEqual({ a: 2, c: 4 }); 16 | }); 17 | 18 | test('returns empty array as-is', function() { 19 | expect(bbo.flush([])).toEqual([]); 20 | }); 21 | 22 | test('returns empty object array as-is', function() { 23 | expect(bbo.flush({})).toEqual({}); 24 | }); 25 | 26 | test('returns undefined if argument is not an array or object', function() { 27 | expect(bbo.flush('hello')).toEqual(undefined); 28 | expect(bbo.flush(null)).toEqual(undefined); 29 | expect(bbo.flush(undefined)).toEqual(undefined); 30 | expect(bbo.flush()).toEqual(undefined); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/collection/search.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('search', () => { 4 | it('should pass example 1', () => { 5 | let expected = 'surname'; 6 | let result = bbo.search('zonneveld', { 7 | firstname: 'kevin', 8 | middle: 'van', 9 | surname: 'zonneveld' 10 | }); 11 | expect(result).toEqual(expected); 12 | }); 13 | 14 | it('should pass example 2', () => { 15 | let expected = 'a'; 16 | let result = bbo.search('3', { a: 3, b: 5, c: 7 }); 17 | expect(result).toEqual(expected); 18 | }); 19 | 20 | it('should pass example 3', () => { 21 | let expected = 'a'; 22 | let result = bbo.search('3', { a: 3, b: 5, c: 7 }); 23 | expect(result).toEqual(expected); 24 | expect(bbo.search('3', { a: 3, b: 5, c: 7 }, 0)).toEqual(expected); 25 | }); 26 | 27 | it('should pass example 3', () => { 28 | expect(bbo.search({})).toEqual(false); 29 | expect(bbo.search([])).toEqual(false); 30 | expect(bbo.search(null)).toEqual(false); 31 | expect(bbo.search('1')).toEqual(false); 32 | expect(bbo.search(() => {})).toEqual(false); 33 | expect(bbo.search({}, {}, {})).toEqual(false); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/collection/values.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-new-wrappers */ 2 | import bbo from '../bbo'; 3 | 4 | describe('values', () => { 5 | test('regular objects return array of property values', function() { 6 | expect(bbo.values({ a: 4, c: 8 })).toEqual([4, 8]); 7 | expect(bbo.values({ a: { aa: 2 }, b: { bb: 4 } })).toEqual([{ aa: 2 }, { bb: 4 }]); 8 | expect(bbo.values({})).toEqual([]); 9 | }); 10 | 11 | test('array returns a copy of itself', function() { 12 | let arr1 = [1, 2, 3]; 13 | let arr2 = []; 14 | 15 | expect(bbo.values(arr1)).toEqual(arr1); 16 | expect(bbo.values(arr2)).toEqual(arr2); 17 | }); 18 | 19 | test('irregular objects return array of property values', function() { 20 | expect( 21 | bbo.values(function(a, b) { 22 | return a + b; 23 | }) 24 | ).toEqual([]); 25 | 26 | expect(bbo.values(new String('hello'))).toEqual(['h', 'e', 'l', 'l', 'o']); 27 | 28 | let fn = function() {}; 29 | fn.a = 4; 30 | expect(bbo.values(fn)).toEqual([4]); 31 | }); 32 | 33 | test('primitives throw exceptions', function() { 34 | expect(() => { 35 | bbo.values(1); 36 | }).toThrow(); 37 | 38 | expect(() => { 39 | bbo.values(true); 40 | }).toThrow(); 41 | 42 | expect(() => { 43 | bbo.values(undefined); 44 | }).toThrow(); 45 | 46 | expect(() => { 47 | bbo.values(null); 48 | }).toThrow(); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /test/cookie/delete_cookie.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('deleteCookie', () => { 4 | const cookie = 'c=v'; 5 | 6 | test('bbo.deleteCookie or delCookie is a Function', () => { 7 | expect(bbo.deleteCookie).toBeInstanceOf(Function); 8 | expect(bbo.delCookie).toBeInstanceOf(Function); 9 | }); 10 | 11 | test('delete simple value', function() { 12 | bbo.setCookie('c', 'v'); 13 | expect(document.cookie).toBe(cookie); 14 | 15 | bbo.deleteCookie('c'); 16 | expect(document.cookie).toBe(''); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/cookie/get_cookie.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('getCookie', () => { 4 | test('simple value', function() { 5 | document.cookie = 'c=v'; 6 | expect(bbo.getCookie('c')).toBe('v'); 7 | }); 8 | test('must encode ";"', function() { 9 | document.cookie = 'c%3B=foo'; 10 | expect(bbo.getCookie('c;')).toBe('foo'); 11 | }); 12 | 13 | test('reading name with encoded equals sign', function() { 14 | document.cookie = 'c%3D=foo'; 15 | expect(bbo.getCookie('c=')).toBe('foo'); 16 | }); 17 | 18 | test('setCookie', function() { 19 | bbo.setCookie('cv', 'cv'); 20 | expect(bbo.getCookie('cv')).toBe('cv'); 21 | }); 22 | 23 | test('null', function() { 24 | expect(bbo.getCookie('cv2')).toBe(null); 25 | expect(bbo.getCookie()).toBe(null); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/cookie/parse_cookie.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('parseCookie', () => { 4 | test('bbo.parseCookie is a Function', () => { 5 | expect(bbo.parseCookie).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('parses the cookie', () => { 9 | expect(bbo.parseCookie('foo=bar; equation=E%3Dmc%5E2')).toEqual({ 10 | foo: 'bar', 11 | equation: 'E=mc^2' 12 | }); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/device/ie_version.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { chrome, edge, Edge12, Edge13, IE10, IE11 } from '../const'; 3 | 4 | describe('ieVersion', () => { 5 | // ua = navigator.userAgent , isMobile = bbo.isMobile 6 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 7 | const ieVersion = (ua) => { 8 | let uakit = ua; 9 | let msie = uakit.indexOf('MSIE '); 10 | if (msie > 0) { 11 | return parseInt(uakit.substring(msie + 5, uakit.indexOf('.', msie)), 10); 12 | } 13 | 14 | let trident = uakit.indexOf('Trident/'); 15 | if (trident > 0) { 16 | let rv = uakit.indexOf('rv:'); 17 | return parseInt(uakit.substring(rv + 3, uakit.indexOf('.', rv)), 10); 18 | } 19 | 20 | let edge = uakit.indexOf('Edge/'); 21 | if (edge > 0) { 22 | return parseInt(ua.substring(edge + 5, uakit.indexOf('.', edge)), 10); 23 | } 24 | 25 | return ''; 26 | }; 27 | 28 | test('bbo.ieVersion is a Function', () => { 29 | expect(bbo.ieVersion).toBeInstanceOf(Function); 30 | }); 31 | 32 | test('bbo.ieVersion() for ua', () => { 33 | expect(bbo.ieVersion()).toBe(''); 34 | expect(ieVersion(chrome)).toBe(''); 35 | expect(ieVersion(edge)).toBe(12); 36 | expect(ieVersion(Edge12)).toBe(12); 37 | expect(ieVersion(Edge13)).toBe(13); 38 | expect(ieVersion(IE10)).toBe(10); 39 | expect(ieVersion(IE11)).toBe(11); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/device/is_android.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { android, chrome, edge } from '../const'; 3 | 4 | describe('isAndroid', () => { 5 | // ua = navigator.userAgent 6 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 7 | 8 | const isAndroid = (ua) => { 9 | return ua.toLowerCase().indexOf('android') > -1; 10 | }; 11 | 12 | test('bbo.isAndroid is a Function', () => { 13 | expect(bbo.isAndroid).toBeInstanceOf(Function); 14 | }); 15 | 16 | test('bbo.isAndroid() for ua', () => { 17 | expect(bbo.isAndroid()).toBe(false); 18 | expect(isAndroid(android)).toBe(true); 19 | expect(isAndroid(chrome)).toBe(false); 20 | expect(isAndroid(edge)).toBe(false); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/device/is_ie.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | describe('isIE', () => { 3 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 4 | 5 | test('bbo.isIE is a Function', () => { 6 | expect(bbo.isIE).toBeInstanceOf(Function); 7 | }); 8 | 9 | test('bbo.isIE() for ua', () => { 10 | expect(bbo.isIE()).toBe(false); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/device/is_ios.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { ios, ipad, android, iphone } from '../const'; 3 | describe('isIOS', () => { 4 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 5 | 6 | const isIOS = (ua) => { 7 | return /iPad|iPhone|iPod/.test(ua); 8 | }; 9 | 10 | test('bbo.isIOS is a Function', () => { 11 | expect(bbo.isIOS).toBeInstanceOf(Function); 12 | }); 13 | 14 | test('bbo.isIOS() for ua', () => { 15 | expect(bbo.isIOS()).toBe(false); 16 | expect(isIOS(ios)).toBe(true); 17 | expect(isIOS(iphone)).toBe(true); 18 | expect(isIOS(ipad)).toBe(true); 19 | expect(isIOS(android)).toBe(false); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/device/is_ipad.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { ios, ipad, android } from '../const'; 3 | describe('isIPad', () => { 4 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 5 | 6 | const isIPad = (ua) => { 7 | return /iPad/.test(ua); 8 | }; 9 | 10 | test('bbo.isIPad is a Function', () => { 11 | expect(bbo.isIPad).toBeInstanceOf(Function); 12 | }); 13 | 14 | test('bbo.isIPad() for ua', () => { 15 | expect(bbo.isIPad()).toBe(false); 16 | expect(isIPad(ios)).toBe(false); 17 | expect(isIPad(android)).toBe(false); 18 | expect(isIPad(ipad)).toBe(true); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/device/is_iphone.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { ios, ipad, android, iphone } from '../const'; 3 | describe('isiPhone', () => { 4 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 5 | 6 | const isiPhone = (ua) => { 7 | return /iPhone/.test(ua); 8 | }; 9 | 10 | test('bbo.isiPhone is a Function', () => { 11 | expect(bbo.isiPhone).toBeInstanceOf(Function); 12 | }); 13 | 14 | test('bbo.isiPhone() for ua', () => { 15 | expect(bbo.isiPhone()).toBe(false); 16 | expect(isiPhone(ipad)).toBe(false); 17 | expect(isiPhone(android)).toBe(false); 18 | expect(isiPhone(iphone)).toBe(true); 19 | expect(isiPhone(ios)).toBe(true); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/device/is_iphonex_model.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | describe('isIphoneXmodel', () => { 3 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 4 | 5 | test('bbo.isIphoneXmodel is a Function', () => { 6 | expect(bbo.isIphoneXmodel).toBeInstanceOf(Function); 7 | }); 8 | 9 | test('bbo.isIphoneXmodel() for devicePixelRatio ,screen', () => { 10 | expect(bbo.isIphoneXmodel()).toBe(false); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/device/is_mobile.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { chrome, edge, Edge12, Edge13, IE10, IE11, firefox, safari, ios, android } from '../const'; 3 | 4 | describe('isMobile', () => { 5 | // ua = navigator.userAgent , isMobile = bbo.isMobile 6 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 7 | const isMobile = (ua) => { 8 | return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(ua.toLowerCase()); 9 | }; 10 | 11 | test('bbo.isMobile is a Function', () => { 12 | expect(bbo.isMobile).toBeInstanceOf(Function); 13 | }); 14 | 15 | test('bbo.isMobile() for ua', () => { 16 | expect(bbo.isMobile(chrome)).toBe(false); 17 | expect(isMobile(chrome)).toBe(false); 18 | expect(isMobile(edge)).toBe(false); 19 | expect(isMobile(Edge12)).toBe(false); 20 | expect(isMobile(Edge13)).toBe(false); 21 | expect(isMobile(IE10)).toBe(false); 22 | expect(isMobile(IE11)).toBe(false); 23 | expect(isMobile(firefox)).toBe(false); 24 | expect(isMobile(safari)).toBe(false); 25 | 26 | expect(isMobile(ios)).toBe(true); 27 | expect(isMobile(android)).toBe(true); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/device/is_news_app.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { qqNews, ipad, android, iphone } from '../const'; 3 | describe('isNewsApp', () => { 4 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 5 | 6 | const isNewsApp = (ua) => { 7 | return /qqnews/.test(ua); // 腾讯新闻app 8 | }; 9 | 10 | test('bbo.isiPhone is a Function', () => { 11 | expect(bbo.isNewsApp).toBeInstanceOf(Function); 12 | }); 13 | 14 | test('bbo.isNewsApp() for ua', () => { 15 | expect(bbo.isNewsApp()).toBe(false); 16 | expect(isNewsApp(ipad)).toBe(false); 17 | expect(isNewsApp(android)).toBe(false); 18 | expect(isNewsApp(iphone)).toBe(false); 19 | expect(isNewsApp(qqNews)).toBe(true); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/device/is_pc.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { chrome, edge, Edge12, Edge13, IE10, IE11, firefox, safari, ios, android } from '../const'; 3 | 4 | describe('isPC', () => { 5 | // ua = navigator.userAgent ,isPC = !isMobile = !bbo.isMobile 6 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 7 | const isPC = (ua) => { 8 | return !/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(ua.toLowerCase()); 9 | }; 10 | 11 | test('bbo.isPC is a Function', () => { 12 | expect(bbo.isPC).toBeInstanceOf(Function); 13 | }); 14 | 15 | test('bbo.isPC() for ua', () => { 16 | expect(bbo.isPC(chrome)).toBe(true); 17 | expect(isPC(chrome)).toBe(true); 18 | expect(isPC(edge)).toBe(true); 19 | expect(isPC(Edge12)).toBe(true); 20 | expect(isPC(Edge13)).toBe(true); 21 | expect(isPC(IE10)).toBe(true); 22 | expect(isPC(IE11)).toBe(true); 23 | expect(isPC(firefox)).toBe(true); 24 | expect(isPC(safari)).toBe(true); 25 | 26 | expect(isPC(ios)).toBe(false); 27 | expect(isPC(android)).toBe(false); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/device/is_qq.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { qq, qqNews, ipad, android, iphone } from '../const'; 3 | describe('isQQ', () => { 4 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 5 | 6 | const isQQ = (ua) => { 7 | return /qq\//.test(ua.toLowerCase()); 8 | }; 9 | 10 | test('bbo.isQQ is a Function', () => { 11 | expect(bbo.isQQ).toBeInstanceOf(Function); 12 | }); 13 | 14 | test('bbo.isQQ() for ua', () => { 15 | expect(bbo.isQQ()).toBe(false); 16 | expect(isQQ(ipad)).toBe(false); 17 | expect(isQQ(android)).toBe(false); 18 | expect(isQQ(iphone)).toBe(false); 19 | expect(isQQ(qqNews)).toBe(false); 20 | expect(isQQ(qq)).toBe(true); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/device/is_qq_browser.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { qqBrowser, weixin, qq, qqNews, ipad, android, iphone } from '../const'; 3 | 4 | describe('isQQbrowser', () => { 5 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 6 | 7 | const isQQbrowser = (ua) => { 8 | return /mqqbrowser/i.test(ua.toLowerCase()); 9 | }; 10 | 11 | test('bbo.isQQbrowser() is a Function', () => { 12 | expect(bbo.isQQbrowser).toBeInstanceOf(Function); 13 | }); 14 | 15 | test('bbo.isQQbrowser() for ua', () => { 16 | expect(bbo.isQQbrowser()).toBe(false); 17 | expect(isQQbrowser(ipad)).toBe(false); 18 | expect(isQQbrowser(android)).toBe(false); 19 | expect(isQQbrowser(iphone)).toBe(false); 20 | expect(isQQbrowser(qqNews)).toBe(false); 21 | expect(isQQbrowser(qq)).toBe(false); 22 | expect(isQQbrowser(weixin)).toBe(false); 23 | expect(isQQbrowser(qqBrowser)).toBe(true); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/device/is_tenvideo.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { qqLiveBrowser, qq, qqNews, ipad, android, iphone } from '../const'; 3 | describe('isTenvideo', () => { 4 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 5 | 6 | const isTenvideo = (ua) => { 7 | return /qqlivebrowser/.test(ua.toLowerCase()); 8 | }; 9 | 10 | test('bbo.isTenvideo is a Function', () => { 11 | expect(bbo.isTenvideo).toBeInstanceOf(Function); 12 | }); 13 | 14 | test('bbo.isTenvideo() for ua', () => { 15 | expect(bbo.isTenvideo()).toBe(false); 16 | expect(isTenvideo(ipad)).toBe(false); 17 | expect(isTenvideo(android)).toBe(false); 18 | expect(isTenvideo(iphone)).toBe(false); 19 | expect(isTenvideo(qqNews)).toBe(false); 20 | expect(isTenvideo(qq)).toBe(false); 21 | expect(isTenvideo(qqLiveBrowser)).toBe(true); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/device/is_weishi.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { weishi, qqLiveBrowser, qq, qqNews, ipad, android, iphone } from '../const'; 3 | describe('isTenvideo', () => { 4 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 5 | 6 | const isWeiShi = (ua) => { 7 | return /weishi/.test(ua.toLowerCase()); 8 | }; 9 | 10 | test('bbo.isWeiShi() is a Function', () => { 11 | expect(bbo.isWeiShi).toBeInstanceOf(Function); 12 | }); 13 | 14 | test('bbo.isWeiShi() for ua', () => { 15 | expect(bbo.isWeiShi()).toBe(false); 16 | expect(isWeiShi(ipad)).toBe(false); 17 | expect(isWeiShi(android)).toBe(false); 18 | expect(isWeiShi(iphone)).toBe(false); 19 | expect(isWeiShi(qqNews)).toBe(false); 20 | expect(isWeiShi(qq)).toBe(false); 21 | expect(isWeiShi(qqLiveBrowser)).toBe(false); 22 | expect(isWeiShi(weishi)).toBe(true); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/device/is_weixin.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import { weixin, weishi, qqLiveBrowser, qq, qqNews, ipad, android, iphone } from '../const'; 3 | describe('isWeixin', () => { 4 | // jest jsdom ua = "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0" 5 | 6 | const isWeixin = (ua) => { 7 | return /MicroMessenger/i.test(ua.toLowerCase()); 8 | }; 9 | 10 | test('bbo.isWeixin() is a Function', () => { 11 | expect(bbo.isWeixin).toBeInstanceOf(Function); 12 | }); 13 | 14 | test('bbo.isWeixin() for ua', () => { 15 | expect(bbo.isWeixin()).toBe(false); 16 | expect(isWeixin(ipad)).toBe(false); 17 | expect(isWeixin(android)).toBe(false); 18 | expect(isWeixin(iphone)).toBe(false); 19 | expect(isWeixin(qqNews)).toBe(false); 20 | expect(isWeixin(qq)).toBe(false); 21 | expect(isWeixin(qqLiveBrowser)).toBe(false); 22 | expect(isWeixin(weishi)).toBe(false); 23 | expect(isWeixin(weixin)).toBe(true); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/fill/chain_async.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('chainAsync', () => { 4 | test('bbo.chainAsync() is a Function', () => { 5 | expect(bbo.chainAsync).toBeInstanceOf(Function); 6 | }); 7 | 8 | let incrementer = 0; 9 | test('Calls all functions in an array', () => { 10 | bbo.chainAsync([ 11 | (next) => { 12 | incrementer += 1; 13 | next(); 14 | }, 15 | (next) => { 16 | incrementer += 1; 17 | next(); 18 | }, 19 | (next) => { 20 | expect(incrementer).toEqual(2); 21 | } 22 | ]); 23 | }); 24 | 25 | test('Last function does not receive "next" argument', () => { 26 | bbo.chainAsync([ 27 | (next) => { 28 | next(); 29 | }, 30 | (next) => { 31 | expect(next).toBe(undefined); 32 | } 33 | ]); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/fill/fill0.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('fill0', () => { 4 | test('bbo.fill0() is a Function', () => { 5 | expect(bbo.fill0).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('should pass example', () => { 9 | const n = 3.1415926535897; 10 | 11 | expect(bbo.fill0(n)).toBe('03.1415926535897'); 12 | expect(bbo.fill0(9)).toBe('09'); 13 | expect(bbo.fill0(1)).toBe('01'); 14 | expect(bbo.fill0(1)).toBe('01'); 15 | expect(bbo.fill0(0.314)).toBe('00.314'); 16 | expect(bbo.fill0(10)).toBe('10'); 17 | expect(bbo.fill0(99)).toBe('99'); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/fill/floor.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('floor', () => { 4 | test('bbo.floor() is a Function', () => { 5 | expect(bbo.floor).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('should pass example', () => { 9 | const n = 3.1415926535897; 10 | 11 | expect(bbo.floor(n)).toBe(3); 12 | expect(bbo.floor(n, 0)).toBe(3); 13 | expect(bbo.floor(n, 2)).toBe(3.14); 14 | expect(bbo.floor(n, 4)).toBe(3.1415); 15 | expect(bbo.floor(n, 5)).toBe(3.14159); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/fill/modulo.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('modulo', () => { 4 | test('bbo.modulo() is a Function', () => { 5 | expect(bbo.modulo).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('should pass example', () => { 9 | // bbo.modulo(7, 5); // 2 10 | // bbo.modulo(17, 23); // 17 11 | // bbo.modulo(16.2, 3.8); // 1 12 | // bbo.modulo(5.8, 3.4); //2.4 13 | // bbo.modulo(4, 0); // 4 14 | // bbo.modulo(-7, 5); // 3 15 | // bbo.modulo(-2, 15); // 13 16 | // bbo.modulo(-5.8, 3.4); // 1 17 | // bbo.modulo(12, -1); // NaN 18 | // bbo.modulo(-3, -8); // NaN 19 | // bbo.modulo(12, 'apple'); // NaN 20 | // bbo.modulo('bee', 9); // NaN 21 | // bbo.modulo(null, undefined); // NaN 22 | 23 | expect(bbo.modulo(7, 5)).toBe(2); 24 | expect(bbo.modulo(17, 23)).toBe(17); 25 | expect(bbo.modulo(16.2, 3.8)).toBe(1); 26 | expect(bbo.modulo(5.8, 3.4)).toBe(2.4); 27 | expect(bbo.modulo(4, 0)).toBe(4); 28 | expect(bbo.modulo(-7, 5)).toBe(3); 29 | expect(bbo.modulo(-2, 15)).toBe(13); 30 | expect(bbo.modulo(-5.8, 3.4)).toBe(1); 31 | expect(bbo.modulo(12, -1)).toBe(NaN); 32 | expect(bbo.modulo(-3, -8)).toBe(NaN); 33 | expect(bbo.modulo(12, 'apple')).toBe(NaN); 34 | expect(bbo.modulo('bee', 9)).toBe(NaN); 35 | expect(bbo.modulo(null, undefined)).toBe(NaN); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/http/delete_url_param.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('deleteUrlParam', () => { 4 | test('bbo.deleteUrlParam() is a Function', () => { 5 | expect(bbo.deleteUrlParam).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('set a simple key value', () => { 9 | const url = bbo.deleteUrlParam('a'); 10 | // use URLSearchParams URL 11 | // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams#Browser_compatibility 12 | // https://developer.mozilla.org/zh-CN/docs/Web/API/URL 13 | // const searchParams = new URLSearchParams(url); 14 | const parsedUrl = new URL(url); 15 | expect(parsedUrl.searchParams.has('a')).toBe(false); 16 | 17 | const urlset = 'https://ww.abc.com/c/a.htm?id=2f&y=1.21&a=b'; 18 | const urlSetDelete = bbo.deleteUrlParam('a', urlset); 19 | const parsedUrlSet = new URL(urlSetDelete); 20 | expect(parsedUrlSet.searchParams.has('b')).toBe(false); 21 | expect(parsedUrlSet.searchParams.has('a')).toBe(false); 22 | expect(parsedUrlSet.searchParams.has('id')).toBe(true); 23 | expect(parsedUrlSet.searchParams.get('a')).toBe(null); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/http/get_url_param.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('getUrlParam', () => { 4 | test('bbo.getUrlParam() is a Function', () => { 5 | expect(bbo.getUrlParam).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('set a simple key value', () => { 9 | const url = bbo.getUrlParam('a'); 10 | // use URLSearchParams URL 11 | // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams#Browser_compatibility 12 | // https://developer.mozilla.org/zh-CN/docs/Web/API/URL 13 | // const searchParams = new URLSearchParams(url); 14 | const parsedUrl = new URL(window.location.href); // defalut url = window.location.href 15 | expect(parsedUrl.searchParams.has('a')).toBe(false); 16 | expect(url).toBe(null); 17 | 18 | const urlset = 'https://ww.abc.com/c/a.htm?id=2f&y=1.21&a=b&foo=lorem&bar=&baz'; 19 | expect(bbo.getUrlParam('a', urlset)).toBe('b'); 20 | expect(bbo.getUrlParam('', urlset)).toBe(null); 21 | expect(bbo.getUrlParam('foo', urlset)).toBe('lorem'); 22 | expect(bbo.getUrlParam('bar', urlset)).toBe(''); // "" (present with empty value) 23 | expect(bbo.getUrlParam('qux', urlset)).toBe(null); // "" null (absent) 24 | expect(bbo.getUrlParam('baz', urlset)).toBe(''); // "" (present with no value) 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/http/http_get.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('httpGet', () => { 4 | test('bbo.httpGet() is a Function', () => { 5 | expect(bbo.httpGet).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('httpGet', () => { 9 | bbo.httpGet( 10 | 'https://api.github.com/', 11 | (res) => { 12 | const cb = JSON.parse(res); // {message: "API...", documentation_url: "https://developer.github.com/v3/#rate-limiting"} 13 | expect(bbo.isObject(cb)).toBe(true); 14 | }, 15 | (error) => { 16 | console.log(error); 17 | } 18 | ); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/http/http_post.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('httpPost', () => { 4 | test('bbo.httpPost() is a Function', () => { 5 | expect(bbo.httpPost).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('httpPost', () => { 9 | bbo.httpPost( 10 | 'https://api.github.com/users', 11 | 'hrout', 12 | (res) => { 13 | const cb = JSON.parse(res); 14 | expect(bbo.isObject(cb)).toBe(true); 15 | }, 16 | (error) => { 17 | console.log(error); 18 | } 19 | ); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/http/is_absolute_url.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('isAbsoluteURL', () => { 4 | test('bbo.isAbsoluteURL() is a Function', () => { 5 | expect(bbo.isAbsoluteURL).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('an absolute URL', () => { 9 | expect(bbo.isAbsoluteURL('https://ww.com')).toBeTruthy(); 10 | }); 11 | test('an absolute URL', () => { 12 | expect(bbo.isAbsoluteURL('ftp://www.www.net')).toBeTruthy(); 13 | }); 14 | test('not a absolute URL', () => { 15 | expect(bbo.isAbsoluteURL('/foo/bar')).toBeFalsy(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/http/object_param.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('objectParam', () => { 4 | const param = 'a=1&b=2&c=3&d=4'; 5 | const array = [ 6 | { name: 'a', value: '1' }, 7 | { name: 'b', value: '2' }, 8 | { name: 'c', value: '3' }, 9 | { name: 'd', value: '4' } 10 | ]; 11 | const object = { 12 | a: 1, 13 | b: 2, 14 | c: 3, 15 | d: [4] 16 | }; 17 | 18 | test('bbo.objectParam() is a Function', () => { 19 | expect(bbo.objectParam).toBeInstanceOf(Function); 20 | }); 21 | 22 | test('param is array', () => { 23 | expect(bbo.objectParam(array)).toBe(param); 24 | }); 25 | test('param is object', () => { 26 | expect(bbo.objectParam(object)).toBe(param); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | // util 2 | import './util/no_conflict'; 3 | import './util/version'; 4 | -------------------------------------------------------------------------------- /test/json/jsonp.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | describe('jsonp', () => { 3 | const url = './'; 4 | // const url = 'https://view.inews.qq.com/g2/getOnsInfo?name=wuwei_ww_ww_share_action'; 5 | // window.URL.createObjectURL = jest.fn(); 6 | // afterEach(() => { 7 | // window.URL.createObjectURL.mockReset(); 8 | // }); 9 | // const url = URL.createObjectURL('callback({a: 1});'); 10 | 11 | test('bbo.jsonp() is a Function', () => { 12 | expect(bbo.jsonp).toBeInstanceOf(Function); 13 | }); 14 | 15 | it('should pass only url', () => { 16 | bbo.jsonp(url); 17 | }, 9999); 18 | 19 | it('should pass example', () => { 20 | bbo.jsonp( 21 | url, 22 | { 23 | name: 'callback' 24 | }, 25 | (err, data) => { 26 | expect(bbo.has(data, 'data')).toBe(true); 27 | } 28 | ); 29 | }, 9999); 30 | 31 | it('should pass example 2', () => { 32 | bbo.jsonp( 33 | url, 34 | (err, data) => { 35 | expect(bbo.has(data, 'data')).toBe(true); 36 | }, 37 | { 38 | name: 'callback' 39 | } 40 | ); 41 | }, 9999); 42 | 43 | it('should pass example 3', () => { 44 | bbo.jsonp( 45 | url, 46 | (err, data) => { 47 | expect(bbo.has(data, 'data')).toBe(true); 48 | }, 49 | { 50 | name: 'callback', 51 | timeout: 100, 52 | prefix: 'bbo', 53 | param: { 54 | a: 1, 55 | b: 2 56 | } 57 | } 58 | ); 59 | }, 9999); 60 | }); 61 | -------------------------------------------------------------------------------- /test/json/to_json.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('toJson', () => { 4 | test('bbo.toJson() is a Function', () => { 5 | expect(bbo.toJson).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('should pass example', () => { 9 | const a = '{"a":"[Function function () {}]"}'; 10 | const b = '{"a":1,"b":"[Circular ~]"}'; 11 | const res = "{ code: 0 , msg: 'msg' , data: {} }"; 12 | 13 | expect(bbo.toJson(a)).toEqual({ 14 | a: '[Function function () {}]' 15 | }); 16 | 17 | expect(bbo.toJson(b)).toEqual({ 18 | a: 1, 19 | b: '[Circular ~]' 20 | }); 21 | 22 | expect(bbo.toJson(res)).toEqual({ code: 0, msg: 'msg', data: {} }); 23 | 24 | expect(bbo.toJson()).toEqual(null); 25 | 26 | expect( 27 | bbo.toJson({ 28 | a: 1, 29 | b: 2 30 | }) 31 | ).toEqual({ 32 | a: 1, 33 | b: 2 34 | }); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /test/lodash/for_each.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | import bbo from '../bbo'; 3 | 4 | describe('forEach', function() { 5 | it('object', function() { 6 | const ctx = { keys: [] }; 7 | 8 | bbo.forEach( 9 | { a: 1, b: 2 }, 10 | (val, key) => { 11 | ctx.keys.push(key); 12 | }, 13 | ctx 14 | ); 15 | expect(ctx.keys).toContain('a'); 16 | expect(ctx.keys).toContain('b'); 17 | }); 18 | 19 | it('array', function() { 20 | const arr = [0, 1]; 21 | bbo.forEach(arr, function(val, i) { 22 | arr[i] = val * 2; 23 | }); 24 | 25 | expect(arr).toEqual([0, 2]); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lodash/get_tag.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { funcTag, numberTag, objectTag, arrayTag } from '../const'; 3 | import lodashStable from 'lodash'; 4 | import bbo from '../bbo'; 5 | 6 | describe('getTag', function() { 7 | let tags = [() => {}, 0, {}, []]; 8 | let tagsName = [funcTag, numberTag, objectTag, arrayTag]; 9 | lodashStable.each(tags, (methodName, index) => { 10 | it('bbo.getTag' + tagsName[index] + '` should support shortcut fusion', () => { 11 | assert.strictEqual(bbo.getTag(methodName), tagsName[index]); 12 | }); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/lodash/is.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import bbo from '../bbo'; 3 | 4 | describe('is', function() { 5 | it('using is normal', function() { 6 | assert.strictEqual(bbo.is('foo', 'foo'), true); 7 | assert.strictEqual(bbo.is(window, window), true); 8 | 9 | assert.strictEqual(bbo.is('foo', 'bar'), false); 10 | assert.strictEqual(bbo.is([], []), false); 11 | }); 12 | 13 | it('using is null', function() { 14 | assert.strictEqual(bbo.is(null, null), true); 15 | }); 16 | 17 | it('using is object', function() { 18 | let foo = { a: 1 }; 19 | let bar = { a: 1 }; 20 | assert.strictEqual(bbo.is(foo, foo), true); 21 | assert.strictEqual(bbo.is(foo, bar), false); 22 | }); 23 | 24 | it('using special cases', function() { 25 | assert.strictEqual(bbo.is(0, -0), false); 26 | assert.strictEqual(bbo.is(-0, -0), true); 27 | assert.strictEqual(bbo.is(NaN, 0 / 0), true); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/lodash/is_array.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | import assert from 'assert'; 3 | import { args, slice, symbol, realm } from '../const'; 4 | 5 | describe('isArray', function() { 6 | it('should return `true` for arrays', function() { 7 | assert.strictEqual(bbo.isArray([1, 2, 3]), true); 8 | }); 9 | 10 | it('should return `false` for non-arrays', function() { 11 | assert.strictEqual(bbo.isArray(args), false); 12 | assert.strictEqual(bbo.isArray(true), false); 13 | assert.strictEqual(bbo.isArray(new Date()), false); 14 | assert.strictEqual(bbo.isArray(new Error()), false); 15 | assert.strictEqual(bbo.isArray(slice), false); 16 | assert.strictEqual(bbo.isArray({ '0': 1, length: 1 }), false); 17 | assert.strictEqual(bbo.isArray(1), false); 18 | assert.strictEqual(bbo.isArray(/x/), false); 19 | assert.strictEqual(bbo.isArray('a'), false); 20 | assert.strictEqual(bbo.isArray(symbol), false); 21 | }); 22 | 23 | it('should work with an array from another realm', function() { 24 | if (realm.array) { 25 | assert.strictEqual(bbo.isArray(realm.array), true); 26 | } 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/lodash/is_boolean.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import bbo from '../bbo'; 3 | import { args, slice, symbol, realm } from '../const'; 4 | 5 | describe('isBoolean', function() { 6 | it('should return `true` for booleans', function() { 7 | assert.strictEqual(bbo.isBoolean(true), true); 8 | assert.strictEqual(bbo.isBoolean(false), true); 9 | assert.strictEqual(bbo.isBoolean(Object(true)), true); 10 | assert.strictEqual(bbo.isBoolean(Object(false)), true); 11 | }); 12 | 13 | it('should return `false` for non-booleans', function() { 14 | assert.strictEqual(bbo.isBoolean(args), false); 15 | assert.strictEqual(bbo.isBoolean([1, 2, 3]), false); 16 | assert.strictEqual(bbo.isBoolean(new Date()), false); 17 | assert.strictEqual(bbo.isBoolean(new Error()), false); 18 | assert.strictEqual(bbo.isBoolean(slice), false); 19 | assert.strictEqual(bbo.isBoolean({ a: 1 }), false); 20 | assert.strictEqual(bbo.isBoolean(1), false); 21 | assert.strictEqual(bbo.isBoolean(/x/), false); 22 | assert.strictEqual(bbo.isBoolean('a'), false); 23 | assert.strictEqual(bbo.isBoolean(symbol), false); 24 | }); 25 | 26 | it('should work with a boolean from another realm', function() { 27 | if (realm.boolean) { 28 | assert.strictEqual(bbo.isBoolean(realm.boolean), true); 29 | } 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/lodash/is_date.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import lodashStable from 'lodash'; 3 | import { falsey, stubFalse, args, slice, symbol, realm } from '../const'; 4 | import bbo from '../bbo'; 5 | 6 | describe('isDate', function() { 7 | it('should return `true` for dates', function() { 8 | assert.strictEqual(bbo.isDate(new Date()), true); 9 | }); 10 | 11 | it('should return `false` for non-dates', function() { 12 | let expected = lodashStable.map(falsey, stubFalse); 13 | 14 | let actual = lodashStable.map(falsey, function(value, index) { 15 | return index ? bbo.isDate(value) : bbo.isDate(); 16 | }); 17 | 18 | assert.deepStrictEqual(actual, expected); 19 | 20 | assert.strictEqual(bbo.isDate(args), false); 21 | assert.strictEqual(bbo.isDate([1, 2, 3]), false); 22 | assert.strictEqual(bbo.isDate(true), false); 23 | assert.strictEqual(bbo.isDate(new Error()), false); 24 | assert.strictEqual(bbo.isDate(slice), false); 25 | assert.strictEqual(bbo.isDate({ a: 1 }), false); 26 | assert.strictEqual(bbo.isDate(1), false); 27 | assert.strictEqual(bbo.isDate(/x/), false); 28 | assert.strictEqual(bbo.isDate('a'), false); 29 | assert.strictEqual(bbo.isDate(symbol), false); 30 | }); 31 | 32 | it('should work with a date object from another realm', function() { 33 | if (realm.date) { 34 | assert.strictEqual(bbo.isDate(realm.date), false); 35 | } 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/lodash/is_nil.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { args, slice, symbol, realm } from '../const'; 3 | import bbo from '../bbo'; 4 | 5 | describe('isNil', function() { 6 | it('should return `true` for nullish values', function() { 7 | assert.strictEqual(bbo.isNil(null), true); 8 | assert.strictEqual(bbo.isNil(), true); 9 | assert.strictEqual(bbo.isNil(undefined), true); 10 | }); 11 | 12 | it('should return `false` for non-nullish values', function() { 13 | assert.strictEqual(bbo.isNil(args), false); 14 | assert.strictEqual(bbo.isNil([1, 2, 3]), false); 15 | assert.strictEqual(bbo.isNil(true), false); 16 | assert.strictEqual(bbo.isNil(new Date()), false); 17 | assert.strictEqual(bbo.isNil(new Error()), false); 18 | assert.strictEqual(bbo.isNil(slice), false); 19 | assert.strictEqual(bbo.isNil({ a: 1 }), false); 20 | assert.strictEqual(bbo.isNil(1), false); 21 | assert.strictEqual(bbo.isNil(/x/), false); 22 | assert.strictEqual(bbo.isNil('a'), false); 23 | 24 | if (Symbol) { 25 | assert.strictEqual(bbo.isNil(symbol), false); 26 | } 27 | }); 28 | 29 | it('should work with nils from another realm', function() { 30 | if (realm.object) { 31 | assert.strictEqual(bbo.isNil(realm.null), true); 32 | assert.strictEqual(bbo.isNil(realm.undefined), true); 33 | } 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/lodash/is_string.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { args, slice, symbol, realm } from '../const'; 3 | import bbo from '../bbo'; 4 | 5 | describe('isString', function() { 6 | it('should return `true` for strings', function() { 7 | assert.strictEqual(bbo.isString('a'), true); 8 | assert.strictEqual(bbo.isString(Object('a')), true); 9 | }); 10 | 11 | it('should return `false` for non-strings', function() { 12 | assert.strictEqual(bbo.isString(args), false); 13 | assert.strictEqual(bbo.isString([1, 2, 3]), false); 14 | assert.strictEqual(bbo.isString(true), false); 15 | assert.strictEqual(bbo.isString(new Date()), false); 16 | assert.strictEqual(bbo.isString(new Error()), false); 17 | assert.strictEqual(bbo.isString(slice), false); 18 | assert.strictEqual(bbo.isString({ '0': 1, length: 1 }), false); 19 | assert.strictEqual(bbo.isString(1), false); 20 | assert.strictEqual(bbo.isString(/x/), false); 21 | assert.strictEqual(bbo.isString(symbol), false); 22 | }); 23 | 24 | it('should work with strings from another realm', function() { 25 | if (realm.string) { 26 | assert.strictEqual(bbo.isString(realm.string), true); 27 | } 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/lodash/is_symbol.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import lodashStable from 'lodash'; 3 | import { symbol, falsey, stubFalse, args, slice, realm } from '../const'; 4 | import bbo from '../bbo'; 5 | 6 | describe('isSymbol', function() { 7 | it('should return `true` for symbols', function() { 8 | if (Symbol) { 9 | assert.strictEqual(bbo.isSymbol(symbol), true); 10 | assert.strictEqual(bbo.isSymbol(Object(symbol)), true); 11 | } 12 | }); 13 | 14 | it('should return `false` for non-symbols', function() { 15 | let expected = lodashStable.map(falsey, stubFalse); 16 | 17 | let actual = lodashStable.map(falsey, function(value, index) { 18 | return index ? bbo.isSymbol(value) : bbo.isSymbol(); 19 | }); 20 | 21 | assert.deepStrictEqual(actual, expected); 22 | 23 | assert.strictEqual(bbo.isSymbol(args), false); 24 | assert.strictEqual(bbo.isSymbol([1, 2, 3]), false); 25 | assert.strictEqual(bbo.isSymbol(true), false); 26 | assert.strictEqual(bbo.isSymbol(new Date()), false); 27 | assert.strictEqual(bbo.isSymbol(new Error()), false); 28 | assert.strictEqual(bbo.isSymbol(slice), false); 29 | assert.strictEqual(bbo.isSymbol({ '0': 1, length: 1 }), false); 30 | assert.strictEqual(bbo.isSymbol(1), false); 31 | assert.strictEqual(bbo.isSymbol(/x/), false); 32 | assert.strictEqual(bbo.isSymbol('a'), false); 33 | }); 34 | 35 | it('should work with symbols from another realm', function() { 36 | if (Symbol && realm.symbol) { 37 | assert.strictEqual(bbo.isSymbol(realm.symbol), true); 38 | } 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/lodash/omit.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('omit', function() { 4 | it('omit returns new object', function() { 5 | let obj = { a: 3, b: 5, c: 9 }; 6 | expect(bbo.omit(obj, []) !== obj).toBe(true); 7 | }); 8 | 9 | test('omit using array', function() { 10 | let obj = { a: 3, b: 5, c: 9 }; 11 | expect(bbo.omit(obj, ['a', 'c'])).toStrictEqual({ b: 5 }); 12 | }); 13 | 14 | test('omit using arguments', function() { 15 | let obj = { a: 3, b: 5, c: 9 }; 16 | expect(bbo.omit(obj, 'a', 'c')).toStrictEqual({ b: 5 }); 17 | }); 18 | 19 | test('omit using a non-existent key', function() { 20 | let obj = { a: 3, b: 5, c: 9 }; 21 | expect(bbo.omit(obj, ['a', 'b', 'd'])).toStrictEqual({ c: 9 }); 22 | }); 23 | 24 | test('omit using a duplicate key', function() { 25 | let obj = { a: 3, b: 5, c: 9 }; 26 | expect(bbo.omit(obj, ['a', 'a'])).toStrictEqual({ b: 5, c: 9 }); 27 | }); 28 | 29 | test('omit where obj has a function value', function() { 30 | let fn = function() { 31 | return true; 32 | }; 33 | let obj = { 34 | a: 3, 35 | b: fn 36 | }; 37 | expect(bbo.omit(obj, 'a', { b: fn })); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/lodash/pick.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('pick', function() { 4 | test('pick returns new object', function() { 5 | let obj = { a: 3, b: 5, c: 9 }; 6 | expect(bbo.pick(obj, []) !== obj).toBe(true); 7 | }); 8 | 9 | test('pick using array', function() { 10 | let obj = { a: 3, b: 5, c: 9 }; 11 | expect(bbo.pick(obj, ['a', 'c'])).toStrictEqual({ a: 3, c: 9 }); 12 | }); 13 | 14 | test('pick using arguments', function() { 15 | let obj = { a: 3, b: 5, c: 9 }; 16 | expect(bbo.pick(obj, 'a', 'c')).toStrictEqual({ a: 3, c: 9 }); 17 | }); 18 | 19 | test('pick using a non-existent key', function() { 20 | let obj = { a: 3, b: 5, c: 9 }; 21 | expect(bbo.pick(obj, ['a', 'b', 'd'])).toStrictEqual({ a: 3, b: 5 }); 22 | }); 23 | 24 | test('pick using a duplicate key', function() { 25 | let obj = { a: 3, b: 5, c: 9 }; 26 | expect(bbo.pick(obj, ['a', 'a'])).toStrictEqual({ a: 3 }); 27 | }); 28 | 29 | test('pick where obj has a function value', function() { 30 | let fn = function() { 31 | return true; 32 | }; 33 | let obj = { 34 | a: 3, 35 | b: fn 36 | }; 37 | expect(bbo.pick(obj, 'b', { b: fn })); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/object/detailed_diff.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('detailedDiff', function() { 4 | test('base case', function() { 5 | const lhs = { 6 | foo: { 7 | bar: { 8 | a: ['a', 'b'], 9 | b: 2, 10 | c: ['x', 'y'], 11 | e: 100 // deleted 12 | } 13 | }, 14 | buzz: 'world' 15 | }; 16 | 17 | const rhs = { 18 | foo: { 19 | bar: { 20 | a: ['a'], // index 1 ('b') deleted 21 | b: 2, // unchanged 22 | c: ['x', 'y', 'z'], // 'z' added 23 | d: 'Hello, world!' // added 24 | } 25 | }, 26 | buzz: 'fizz' // updated 27 | }; 28 | 29 | const detailedDiffValue = bbo.detailedDiff(lhs, rhs); 30 | 31 | expect(bbo.detailedDiff(lhs, rhs)).toStrictEqual(detailedDiffValue); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/object/proper_object.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('properObject', () => { 4 | it('returns given object when object has keys and hasOwnProperty function', () => { 5 | const o = { a: 1 }; 6 | const a = [1]; 7 | expect(bbo.properObject(o)).toBe(o); 8 | expect(bbo.properObject(a)).toBe(a); 9 | }); 10 | 11 | it('returns given value when value is not an object', () => { 12 | const o = 'hello'; 13 | expect(bbo.properObject(o)).toBe(o); 14 | }); 15 | 16 | it('returns object that has given keys and hasOwnProperty function when given object is created from a null', () => { 17 | const o = Object.create(null); 18 | o.a = 1; 19 | const actual = bbo.properObject(o); 20 | expect(actual).toEqual({ a: 1 }); 21 | expect(typeof actual.hasOwnProperty === 'function').toBe(true); 22 | expect(actual).not.toBe(o); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/other/construct.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('construct', () => { 4 | class Dog { 5 | constructor(name) { 6 | this.name = name; 7 | } 8 | } 9 | class Cat { 10 | constructor(name) { 11 | this.name = name; 12 | } 13 | } 14 | 15 | class Goose { 16 | constructor(name) { 17 | this.name = name; 18 | } 19 | } 20 | 21 | class Elephant { 22 | constructor(name) { 23 | this.name = name; 24 | } 25 | } 26 | test('base example', () => { 27 | let classs = [Dog, Cat, Goose, Elephant]; 28 | let randomClass = bbo.random(classs); 29 | let animal = bbo.construct(randomClass, 'animal', 300); 30 | expect(animal.name).toBe('animal'); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/other/get_type.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('getType', () => { 4 | test('bbo.getType() is a Function', () => { 5 | expect(bbo.getType).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('bbo.getType()', () => { 9 | expect(bbo.getType(5)).toBe('number'); 10 | expect(bbo.getType({})).toBe('object'); // -> 'object' 11 | expect(bbo.getType([])).toBe('array'); // -> 'array' 12 | expect(bbo.getType(new Set([1, 2, 3]))).toBe('set'); // -> 'set' 13 | expect(bbo.getType(null)).toBe('null'); // -> null 14 | expect(bbo.getType(undefined)).toBe('undefined'); // -> undefined 15 | expect(bbo.getType(function() {})).toBe('function'); // -> 'function' 16 | expect(bbo.getType(async function() {})).toBe('asyncfunction'); // -> 'AsyncFunction' 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/other/hash.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('hash', () => { 4 | test('bbo.hash() is a Function', () => { 5 | expect(bbo.hash).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('bbo.hash()', () => { 9 | expect(bbo.hash('')).toBe(0); 10 | expect(bbo.hash(1)).toBe(49); 11 | expect(bbo.hash(1000)).toBe(1507423); 12 | expect(bbo.hash('sdf%$sdfMnjjskds23')).toBe(-844608950); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/other/is_typeof.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('isTypeof', () => { 4 | test('bbo.isTypeof() is a Function', () => { 5 | expect(bbo.isTypeof).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('bbo.isTypeof()', () => { 9 | expect(bbo.isTypeof(5, 'number')).toBe(true); 10 | expect(bbo.isTypeof({}, 'object')).toBe(true); // -> 'object' 11 | expect(bbo.isTypeof([], 'array')).toBe(true); // -> 'array' 12 | expect(bbo.isTypeof(new Set([1, 2, 3]), 'set')).toBe(true); // -> 'set' 13 | expect(bbo.isTypeof(null, 'null')).toBe(true); // -> null 14 | expect(bbo.isTypeof(undefined, 'undefined')).toBe(true); // -> undefined 15 | expect(bbo.isTypeof(function() {}, 'function')).toBe(true); // -> 'function' 16 | expect(bbo.isTypeof(async function() {}, 'asyncfunction')).toBe(true); // -> 'AsyncFunction' 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/other/judge.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('judge', () => { 4 | test('bbo.judge() is a Function', () => { 5 | expect(bbo.judge).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('bbo.judge()', () => { 9 | const array = ['2', 'js', 'jsx', '.js', '.jsx', '.css', '.less']; 10 | const object = {}; 11 | const loose = bbo.judge(2, array); 12 | const strict = bbo.judge(2, array, true); 13 | const error = bbo.judge(2, object); 14 | 15 | expect(loose).toBe(true); 16 | expect(strict).toBe(false); 17 | expect(error).toBe(false); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/other/log.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('log', () => { 4 | test('bbo.log is a Function', () => { 5 | expect(bbo.log).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('base example', () => { 9 | const cookie = 'cookie'; 10 | bbo.log(cookie, { color: '#fff', background: '#ff0000' }); 11 | const el = document.getElementById('_bbo_log'); 12 | expect(el.innerHTML).toEqual(cookie); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/other/uuid.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('uuid', () => { 4 | test('bbo.uuid() is a Function', () => { 5 | expect(bbo.uuid).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('bbo.uuid()', () => { 9 | const regUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/; 10 | for (let i = 0; i < 1000; i++) { 11 | expect(regUuid.test(bbo.uuid())).toBe(true); 12 | } 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/random/random_a2b.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('randomA2B', () => { 4 | test('bbo.randomA2B() is a Function', () => { 5 | expect(bbo.randomA2B).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('should pass example', () => { 9 | const max = 999; 10 | const min = 1; 11 | const number = bbo.randomA2B(min, max, true); 12 | expect(number < max).toBe(true); 13 | expect(number > max).toBe(false); 14 | expect(bbo.isNumber(number)).toBe(true); 15 | expect(bbo.isString(number)).toBe(false); 16 | 17 | const numberNoFloor = bbo.randomA2B(min, max); 18 | expect(bbo.isNumber(numberNoFloor)).toBe(true); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/random/random_color.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('randomColor', () => { 4 | test('bbo.randomColor() is a Function', () => { 5 | expect(bbo.randomColor).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('should pass example', () => { 9 | const isColor = (strColor) => { 10 | let s = new Option().style; 11 | s.color = strColor; 12 | let test1 = s.color === strColor; 13 | let test2 = /^#[0-9A-F]{6}$/i.test(strColor); 14 | if (test1 === true || test2 === true) { 15 | return true; 16 | } else { 17 | return false; 18 | } 19 | }; 20 | 21 | const num = 20; 22 | for (let i = 0; i < num.length; i++) { 23 | expect(isColor(bbo.randomColor())).toBe(true); 24 | } 25 | const testColor = bbo.randomColor(); 26 | expect(isColor(testColor)).toBe(true); 27 | expect(isColor('red')).toBe(true); 28 | expect(isColor('reds')).toBe(false); 29 | expect(isColor('#ff0000')).toBe(true); 30 | expect(isColor('#ff000011')).toBe(false); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/random/random_key.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('randomKey', () => { 4 | test('bbo.randomKey() is a Function', () => { 5 | expect(bbo.randomKey).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('should pass example', () => { 9 | const size = bbo.randomA2B(1, 32, true); 10 | expect(bbo.randomKey(size).length).toBe(size); 11 | expect(bbo.isString(bbo.randomKey(size))).toBe(true); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/string/byte_size.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('byteSize', function() { 4 | it('bytesize using special cases', function() { 5 | expect(bbo.byteSize('a')).toBe(1); 6 | expect(bbo.byteSize('')).toBe(0); 7 | expect(bbo.byteSize(1)).toBe(1); 8 | expect(bbo.byteSize(null)).toBe(4); 9 | expect(bbo.byteSize([])).toBe(0); 10 | expect(bbo.byteSize(undefined)).toBe(9); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/string/camelize.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('camelize', function() { 4 | test('_ or - to camelCase', function() { 5 | expect(bbo.camelize('to-upper-case')).toStrictEqual('toUpperCase'); 6 | }); 7 | test('base case', function() { 8 | expect(bbo.camelize('toUpperCase')).toStrictEqual('toUpperCase'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/string/capwords.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('capwords', function() { 4 | test('should pass base example 1', function() { 5 | expect(bbo.capwords('kevin van zonneveld')).toStrictEqual('Kevin Van Zonneveld'); 6 | expect(bbo.capwords('HELLO WORLD')).toStrictEqual('HELLO WORLD'); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/string/contains_with.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | describe('containsWith', function() { 3 | it('should pass example 1', function(done) { 4 | let expected = true; 5 | let result = bbo.containsWith('Kevin', 'K'); 6 | expect(result).toEqual(expected); 7 | done(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/string/dasherize.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | describe('dasherize', function() { 3 | it('should pass example 1', function(done) { 4 | let expected = 'hello-world'; 5 | let result = bbo.dasherize('hello_world'); 6 | expect(result).toEqual(expected); 7 | done(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/string/de_capitalize.js: -------------------------------------------------------------------------------- 1 | import { PRINTABLE_ASCII } from '../const'; 2 | import bbo from '../bbo'; 3 | 4 | describe('deCapitalize', function() { 5 | it('should decapitalize the first character in a string', function() { 6 | expect(bbo.deCapitalize('Light')).toBe('light'); 7 | expect(bbo.deCapitalize('light')).toBe('light'); 8 | expect(bbo.deCapitalize('Sun')).toBe('sun'); 9 | expect(bbo.deCapitalize('f')).toBe('f'); 10 | expect(bbo.deCapitalize('')).toBe(''); 11 | expect(bbo.deCapitalize('*light')).toBe('*light'); 12 | expect(bbo.deCapitalize(PRINTABLE_ASCII)).toBe(PRINTABLE_ASCII); 13 | }); 14 | 15 | it('should decapitalize the first character in a string representation of an object', function() { 16 | expect(bbo.deCapitalize(['Fruit'])).toBe('fruit'); 17 | expect( 18 | bbo.deCapitalize( 19 | { 20 | toString: function() { 21 | return 'CaRrOt'; 22 | } 23 | }, 24 | false 25 | ) 26 | ).toBe('caRrOt'); 27 | }); 28 | 29 | it('should not modify numbers', function() { 30 | expect(bbo.deCapitalize(100)).toBe('100'); 31 | expect(bbo.deCapitalize(812, false)).toBe('812'); 32 | }); 33 | 34 | it('should return an empty string for null or undefined', function() { 35 | expect(bbo.deCapitalize()).toBe(''); 36 | expect(bbo.deCapitalize(undefined)).toBe(''); 37 | expect(bbo.deCapitalize(null)).toBe(''); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/string/effort_Index.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('effortIndex', function() { 4 | it('should pass example 1', function(done) { 5 | let expected = 0; 6 | let result = bbo.effortIndex('Kevin', 'K'); 7 | expect(result).toEqual(expected); 8 | done(); 9 | }); 10 | it('should pass example 2', function(done) { 11 | let expected = -1; 12 | let result = bbo.effortIndex('Kevin', 'Z'); 13 | expect(result).toEqual(expected); 14 | done(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/string/ends_with.js: -------------------------------------------------------------------------------- 1 | import { PRINTABLE_ASCII } from '../const'; 2 | import bbo from '../bbo'; 3 | 4 | describe('endsWith', function() { 5 | it('should return true for valid ending string', function() { 6 | expect(bbo.endsWith('Hello World!', '!')).toBe(true); 7 | expect(bbo.endsWith('Hello World!', 'd!')).toBe(true); 8 | expect(bbo.endsWith('Hello World!', 'rld!')).toBe(true); 9 | expect(bbo.endsWith('Hello World!', 'orld!')).toBe(true); 10 | expect(bbo.endsWith('Hello World!', 'World!')).toBe(true); 11 | expect(bbo.endsWith('Hello World!', ' World!')).toBe(true); 12 | expect(bbo.endsWith('Hello World!', 'o World!')).toBe(true); 13 | expect(bbo.endsWith('Hello World!', 'lo World!')).toBe(true); 14 | expect(bbo.endsWith('Hello World!', 'llo World!')).toBe(true); 15 | expect(bbo.endsWith('Hello World!', 'ello World!')).toBe(true); 16 | expect(bbo.endsWith('Hello World!', 'Hello World!')).toBe(true); 17 | expect(bbo.endsWith('Привет Мир!', 'Мир!')).toBe(true); 18 | expect(bbo.endsWith('', '')).toBe(true); 19 | expect(bbo.endsWith(PRINTABLE_ASCII, '~')).toBe(true); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/string/fill_zero.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('fillZero', function() { 4 | it('should pass no number input', function(done) { 5 | expect(bbo.fillZero('abc')).toEqual('abc'); 6 | expect(bbo.fillZero('12345')).toEqual('12345'); 7 | expect(bbo.fillZero('1')).toEqual('1'); 8 | expect(bbo.fillZero('')).toEqual(''); 9 | done(); 10 | }); 11 | 12 | it('should pass base example 1', function(done) { 13 | expect(bbo.fillZero('12345', 10)).toEqual('0000012345'); 14 | expect(bbo.fillZero('abcdefg', 10)).toEqual('000abcdefg'); 15 | done(); 16 | }); 17 | 18 | it('should pass slice', function(done) { 19 | expect(bbo.fillZero('12345', 2)).toEqual('45'); 20 | expect(bbo.fillZero('abc', 3)).toEqual('abc'); 21 | expect(bbo.fillZero('abc', 1)).toEqual('c'); 22 | done(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/string/long_unique.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('longUnique', function() { 4 | it('should pass no number input', function(done) { 5 | expect(bbo.longUnique('abc')).toEqual('abc'); 6 | expect(bbo.longUnique('12345')).toEqual('12345'); 7 | expect(bbo.longUnique('1')).toEqual('1'); 8 | expect(bbo.longUnique('')).toEqual(''); 9 | done(); 10 | }); 11 | 12 | it('should pass base example 1', function(done) { 13 | expect(bbo.longUnique('strtring')).toEqual('string'); 14 | expect(bbo.longUnique('sTrString')).toEqual('sTrSting'); 15 | expect(bbo.longUnique('abcdefg abcdefgi hijk')).toEqual('abcdefg ihjk'); 16 | expect(bbo.longUnique('123456 123 7')).toEqual('123456 7'); 17 | done(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/string/map_string.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('mapString', function() { 4 | it('should pass base example 1', function(done) { 5 | expect( 6 | bbo.mapString('a b c d', (c, i, str) => { 7 | return c + i; 8 | }) 9 | ).toEqual('a0 1b2 3c4 5d6'); 10 | 11 | expect(bbo.mapString('Using our timing function', (c) => c.toUpperCase())).toEqual( 12 | 'USING OUR TIMING FUNCTION' 13 | ); 14 | done(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/string/mask.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('mask', function() { 4 | it('should pass base number example 1', function(done) { 5 | expect(bbo.mask(1234567890)).toEqual('******7890'); 6 | expect(bbo.mask(1234567890, 3)).toEqual('*******890'); 7 | expect(bbo.mask(1234567890, -4, '$')).toEqual('$$$$567890'); 8 | done(); 9 | }); 10 | 11 | it('should pass base string example 1', function(done) { 12 | expect(bbo.mask('adcdefghijk')).toEqual('*******hijk'); 13 | expect(bbo.mask('adcdefghijk', 3)).toEqual('********ijk'); 14 | expect(bbo.mask('adcdefghijk', -4, '$')).toEqual('$$$$efghijk'); 15 | done(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/string/repeat.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('repeat', function() { 4 | it('should pass base number example 1', function(done) { 5 | expect(bbo.repeat(123, 3)).toEqual('123123123'); 6 | done(); 7 | }); 8 | it('should pass base string example 1', function(done) { 9 | expect(bbo.repeat('TechOnTheNet', 3)).toEqual('TechOnTheNetTechOnTheNetTechOnTheNet'); 10 | done(); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/string/split_lines.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('splitLines', function() { 4 | it('should pass base example 1', function(done) { 5 | const before = 'This\nis a\nmultiline\nstring.\n'; 6 | const after = ['This', 'is a', 'multiline', 'string.', '']; 7 | expect(bbo.splitLines(before)).toEqual(after); 8 | done(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/string/strip_tags.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('stripTags', function() { 4 | it('should pass base stripTags', function(done) { 5 | expect(bbo.longUnique('abc')).toEqual('abc'); 6 | 7 | expect(bbo.stripTags('abc')).toEqual('abc'); 8 | expect(bbo.stripTags('abc')).toEqual('abc'); 9 | expect(bbo.stripTags('abc')).toEqual('abc'); 10 | expect(bbo.stripTags('abc')).toEqual('abc'); 11 | expect(bbo.stripTags('abc')).toEqual('abc'); 12 | expect(bbo.stripTags('abc')).toEqual('abc'); 13 | expect(bbo.stripTags('abc<>123')).toEqual('abc<>123'); 14 | 15 | expect(bbo.stripTags('')).toEqual(''); 16 | expect(bbo.stripTags('')).toEqual(''); 17 | expect(bbo.stripTags('') 20 | ).toEqual(''); 21 | 22 | expect(bbo.stripTags('')).toEqual(''); 23 | expect(bbo.stripTags(' ')).toEqual(' '); 24 | done(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/string/trim.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('trim', function() { 4 | it('should pass base example 1', function(done) { 5 | expect(bbo.trim(' abc ')).toEqual('abc'); 6 | expect(bbo.trim(' abc')).toEqual('abc'); 7 | expect(bbo.trim('abc')).toEqual('abc'); 8 | expect(bbo.trim('a bc')).toEqual('a bc'); 9 | expect(bbo.trim(' ')).toEqual(''); 10 | expect(bbo.trim(null)).toEqual(null); 11 | done(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/string/truncate.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('truncate', function() { 4 | it('should pass base example 1', function(done) { 5 | expect(bbo.truncate('abcdefg')).toEqual('abc...'); 6 | expect(bbo.truncate('abcdefg', 1)).toEqual('a...'); 7 | expect(bbo.truncate('abcdefg', 3)).toEqual('abc...'); 8 | expect(bbo.truncate('abcdefg', 4)).toEqual('a...'); 9 | expect(bbo.truncate('boomerang', 7)).toEqual('boom...'); 10 | expect(bbo.truncate('abcdefgabcdefg', 7)).toEqual('abcd...'); 11 | expect(bbo.truncate('abcdefgabcdefg', 10)).toEqual('abcdefg...'); 12 | done(); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/string/underscored.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('underscored', function() { 4 | test('Turn CamelCase to _ ', function() { 5 | expect(bbo.underscored('toUpperCase')).toStrictEqual('to_upper_case'); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/string/xss_filter.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('xssFilter', function() { 4 | test('should pass base example 1', function() { 5 | const uncode = '
x-html
'; 6 | const filterCode = 7 | '<div>x-html<img src="/bbo/image.png" onerror="onError()"></div>'; 8 | expect(bbo.xssFilter(uncode)).toStrictEqual(filterCode); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/times/clear_timesout.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('clearTimesout', function() { 4 | test('clearTimesout is a Function', () => { 5 | expect(bbo.clearTimesout).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('base example', () => { 9 | let i = 0; 10 | const less = 6; 11 | let interval = setInterval(function() { 12 | console.log(i++); 13 | if (i > less) { 14 | bbo.clearTimesout(interval); 15 | expect(i).toBeLessThan(less); 16 | } 17 | }, 1); 18 | 19 | expect(bbo.clearTimesout(interval)).toEqual(window.clearInterval(interval)); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/times/format_duration.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('formatDuration', function() { 4 | test('formatDuration is a Function', () => { 5 | expect(bbo.formatDuration).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('number of milliseconds', () => { 9 | expect(bbo.formatDuration(1001)).toBe('1 second, 1 millisecond'); 10 | }); 11 | test('number of milliseconds (negative)', () => { 12 | expect(bbo.formatDuration(-1001)).toBe('1 second, 1 millisecond'); 13 | }); 14 | test('number of milliseconds', () => { 15 | expect(bbo.formatDuration(34325055574)).toBe( 16 | '397 days, 6 hours, 44 minutes, 15 seconds, 574 milliseconds' 17 | ); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/times/format_pass_time.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('formatPassTime', function() { 4 | test('formatPassTime is a Function', () => { 5 | expect(bbo.formatPassTime).toBeInstanceOf(Function); 6 | }); 7 | test('date aogo', () => { 8 | const aDay = 24 * 60 * 60 * 1000; 9 | expect(bbo.formatPassTime(new Date(Date.now() - 60 * 30))).toBe('1 seconds'); 10 | expect(bbo.formatPassTime(new Date(Date.now() - 0.5 * 60 * 60 * 1000))).toBe('30 minutes'); 11 | expect(bbo.formatPassTime(new Date(Date.now() - 2 * 60 * 60 * 1000))).toBe('2 hours'); 12 | expect(bbo.formatPassTime(new Date(Date.now() - aDay))).toBe('24 hours'); 13 | expect(bbo.formatPassTime(new Date(Date.now() - aDay * 2))).toBe('2 days'); 14 | expect(bbo.formatPassTime(new Date(Date.now() - aDay * 33))).toBe('1 months'); 15 | expect(bbo.formatPassTime(new Date(Date.now() - aDay * 365 * 50))).toBe('50 years'); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/times/format_remain_time.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('formatRemainTime', function() { 4 | test('formatRemainTime is a Function', () => { 5 | expect(bbo.formatRemainTime).toBeInstanceOf(Function); 6 | }); 7 | test('eemain time', () => { 8 | const aDay = 24 * 60 * 60 * 1000; 9 | const aHour = 60 * 60 * 1000; 10 | const aMinute = 60 * 1000; 11 | const aSecond = 1 * 1000; 12 | const endTime = Date.now() + aDay + aHour + aMinute + aSecond; 13 | 14 | expect(bbo.formatRemainTime(endTime)).toBe('1day 1hour 1minute 1second'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/times/get_date.js: -------------------------------------------------------------------------------- 1 | import bbo from '../bbo'; 2 | 3 | describe('getDate', function() { 4 | test('getDate is a Function', () => { 5 | expect(bbo.getDate).toBeInstanceOf(Function); 6 | }); 7 | 8 | test('number of milliseconds', () => { 9 | let today = new Date(); 10 | let dd = String(today.getDate()).padStart(2, '0'); 11 | let mm = String(today.getMonth() + 1).padStart(2, '0'); // January is 0! 12 | let yyyy = today.getFullYear(); 13 | 14 | let hh = String(today.getHours()).padStart(2, '0'); 15 | let ms = String(today.getMinutes()).padStart(2, '0'); 16 | let ss = String(today.getSeconds()).padStart(2, '0'); 17 | let expectDefalut = `${yyyy}/${mm}/${dd} ${hh}:${ms}:${ss}`; 18 | expect(bbo.getDate()).toBe(expectDefalut); 19 | 20 | let expectNew = `${yyyy}-${mm}-${dd} ${hh}-${ms}-${ss}`; 21 | expect(bbo.getDate('-', '-')).toBe(expectNew); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/times/set_timesout.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-invalid-this */ 2 | import bbo from '../bbo'; 3 | 4 | describe('setTimesout', function() { 5 | test('setTimesout is a Function', () => { 6 | expect(bbo.setTimesout).toBeInstanceOf(Function); 7 | }); 8 | 9 | test('base example', () => { 10 | const repeat = 8; 11 | const skip = 50; 12 | const cb = () => { 13 | return 'abc'; 14 | }; 15 | let id = bbo.setTimesout( 16 | function(word) { 17 | // console.log(this); // log {index: 3 ,times: 8, over: false} 18 | if (this.over) { 19 | expect(this.times).toEqual(repeat); 20 | expect(this.over).toBe(true); 21 | expect(word()).toEqual('abc'); 22 | } else { 23 | expect(this.times > this.index).toBe(true); 24 | } 25 | }, 26 | skip, 27 | repeat, 28 | cb 29 | ); 30 | expect(typeof id === 'number').toEqual(bbo.isNumber(id)); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/util/no_conflict.js: -------------------------------------------------------------------------------- 1 | import getGlobalObject from '../../src/util/get_global'; 2 | import bboLibrary from '../bbo'; 3 | 4 | describe('noConflict', function() { 5 | it('should return bbo library instance and restore bbo global variable', function() { 6 | const globalObject = getGlobalObject(); 7 | globalObject.bbo = bboLibrary; 8 | const bbo = bboLibrary.noConflict(); 9 | expect(bbo).toBe(bboLibrary); 10 | expect(globalObject.bbo).toBe(undefined); 11 | }); 12 | 13 | it('should return bbo library instance and not modify bbo global variable', function() { 14 | const globalObject = getGlobalObject(); 15 | const bbo = bboLibrary.noConflict(); 16 | expect(bbo).toBe(bboLibrary); 17 | expect(globalObject.bbo).toBe(undefined); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/util/version.js: -------------------------------------------------------------------------------- 1 | import { REGEXP_SEMVER } from '../const'; 2 | import bbo from '../bbo'; 3 | 4 | describe('version', function() { 5 | it('should match semantic version number pattern', function() { 6 | expect(REGEXP_SEMVER.test(bbo.version)).toBe(true); 7 | }); 8 | }); 9 | --------------------------------------------------------------------------------