function(method, isTest, paramsMethod, blob) {
      // Add data from the query options
      var query = evalOpts(this.flowObj.opts.query, this.fileObj, this, isTest);
      query = extend(query || {}, this.getParams());

      var target = evalOpts(this.flowObj.opts.target, this.fileObj, this, isTest);
      var data = null;
      if (method === 'GET' || paramsMethod === 'octet') {
        // Add data from the query options
        var params = [];
        each(query, function (v, k) {
          params.push([encodeURIComponent(k), encodeURIComponent(v)].join('='));
        });
        target = this.getTarget(target, params);
        data = blob || null;
      } else {
        // Add data from the query options
        data = new FormData();
        each(query, function (v, k) {
          data.append(k, v);
        });
        if (typeof blob !== "undefined") data.append(this.flowObj.opts.fileParameterName, blob, this.fileObj.file.name);
      }

      this.xhr.open(method, target, true);
      this.xhr.withCredentials = this.flowObj.opts.withCredentials;

      // Add data from header options
      each(evalOpts(this.flowObj.opts.headers, this.fileObj, this, isTest), function (v, k) {
        this.xhr.setRequestHeader(k, v);
      }, this);

      return data;
    }

function
(
method
,
isTest
,
paramsMethod
,
blob
)
{
// Add data from the query options
var
query
=
evalOpts
(
this
.
flowObj
.
opts
.
query
,
this
.
fileObj
,
this
,
isTest
)
;
query
=
extend
(
query
||
{
}
,
this
.
getParams
(
)
)
;
var
target
=
evalOpts
(
this
.
flowObj
.
opts
.
target
,
this
.
fileObj
,
this
,
isTest
)
;
var
data
=
;
if
(
method
===
'GET'
||
paramsMethod
===
'octet'
)
{
// Add data from the query options
var
params
=
[
]
;
each
(
query
,
function
(
v
,
k
)
{
params
.
push
(
[
encodeURIComponent
(
k
)
,
encodeURIComponent
(
v
)
]
.
join
(
'='
)
)
;
}
)
;
target
=
this
.
getTarget
(
target
,
params
)
;
data
=
blob
||
;
}
else
{
// Add data from the query options
data
=
new
FormData
(
)
;
each
(
query
,
function
(
v
,
k
)
{
data
.
append
(
k
,
v
)
;
}
)
;
if
(
typeof
blob
!==
"undefined"
)
data
.
append
(
this
.
flowObj
.
opts
.
fileParameterName
,
blob
,
this
.
fileObj
.
file
.
name
)
;
}
this
.
xhr
.
open
(
method
,
target
,
true
)
;
this
.
xhr
.
withCredentials
=
this
.
flowObj
.
opts
.
withCredentials
;
// Add data from header options
each
(
evalOpts
(
this
.
flowObj
.
opts
.
headers
,
this
.
fileObj
,
this
,
isTest
)
,
function
(
v
,
k
)
{
this
.
xhr
.
setRequestHeader
(
k
,
v
)
;
}
,
this
)
;
return
data
;
}

Prepare Xhr request. Set query, headers and data
@param {string} method GET or POST
@param {bool} isTest is this a test request
@param {string} [paramsMethod] octet or form
@param {Blob} [blob] to send
@returns {FormData|Blob|Null} data to send

Prepare Xhr request . Set query headers and data


function evalOpts(data, args) {
    if (typeof data === "function") {
      // `arguments` is an object, not array, in FF, so:
      args = Array.prototype.slice.call(arguments);
      data = data.apply(null, args.slice(1));
    }
    return data;
  }

If option is a function, evaluate it with given params
@param {*} data
@param {...} args arguments of a callback
@returns {*}

If option is a function evaluate it with given params


function each(obj, callback, context) {
    if (!obj) {
      return ;
    }
    var key;
    // Is Array?
    // Array.isArray won't work, not only arrays can be iterated by index https://github.com/flowjs/ng-flow/issues/236#
    if (typeof(obj.length) !== 'undefined') {
      for (key = 0; key < obj.length; key++) {
        if (callback.call(context, obj[key], key) === false) {
          return ;
        }
      }
    } else {
      for (key in obj) {
        if (obj.hasOwnProperty(key) && callback.call(context, obj[key], key) === false) {
          return ;
        }
      }
    }
  }

Iterate each element of an object
@function
@param {Array|Object} obj object or an array to iterate
@param {Function} callback first argument is a value and second is a key.
@param {Object=} context Object to become context (`this`) for the iterator function.


function createTable() {
    tableName = arguments[0];
    var fname = '';
    var callback;
    if (arguments.length === 2) {

        callback = arguments[1];
        fname = path.join(userData, tableName + '.json');
    } else if (arguments.length === 3) {
        fname = path.join(arguments[1], arguments[0] + '.json');
        callback = arguments[2];
    }

    // Check if the file with the tablename.json exists
    let exists = fs.existsSync(fname);

    if (exists) {
        // The file exists, do not recreate the table/json file
        callback(false, tableName + '.json already exists!');
        return;
    } else {
        // Create an empty object and pass an empty array as value
        let obj = new Object();
        obj[tableName] = [];

        // Write the object to json file
        try {
            fs.writeFileSync(fname, JSON.stringify(obj, null, 2), (err) => {

            })
            callback(true, "Success!")
            return;
        } catch (e) {
            callback(false, e.toString());
            return;
        }

    }
}

Create a table | a json file
The second argument is optional, if ommitted, the file
will be created at the default location.
@param  {[string]} arguments[0] [Table name]
@param {[string]} arguments[1] [Location of the database file] (Optional)
@param {[function]} arguments[2] [Callbak ]
 function createTable(tableName, callback) {

Create a table | a json file The second argument is optional if ommitted the file will be created at the default location .


function valid() {
    var fName = ''
    if (arguments.length == 2) {
        // Given the database name and location
        const dbName = arguments[0]
        const dbLocation = arguments[1]
        var fName = path.join(dbLocation, dbName + '.json')
    } else if (arguments.length == 1) {
        const dbName = arguments[0]
        fname = path.join(userData, dbName + '.json')
    }

    const content = fs.readFileSync(fName, 'utf-8')
    try {
        JSON.parse(content)
    } catch (e) {
        return false
    }
    return true
}

function
valid
(
)
{
var
fName
=
''
if
(
arguments
.
length
==
2
)
{
// Given the database name and location
const
dbName
=
arguments
[
0
]
const
dbLocation
=
arguments
[
1
]
var
fName
=
path
.
join
(
dbLocation
,
dbName
+
'.json'
)
}
else
if
(
arguments
.
length
==
1
)
{
const
dbName
=
arguments
[
0
]
fname
=
path
.
join
(
userData
,
dbName
+
'.json'
)
}
const
content
=
fs
.
readFileSync
(
fName
,
'utf-8'
)
try
{
JSON
.
parse
(
content
)
}
catch
(
e
)
{
return
false
}
return
true
}

Checks if a json file contains valid JSON string


function insertTableContent() {
    let tableName = arguments[0];
    var fname = '';
    var callback;
    var tableRow;
    if (arguments.length === 3) {
        callback = arguments[2];
        fname = path.join(userData, arguments[0] + '.json');
        tableRow = arguments[1];
    } else if (arguments.length === 4) {
        fname = path.join(arguments[1], arguments[0] + '.json');
        callback = arguments[3];
        tableRow = arguments[2];
    }

    let exists = fs.existsSync(fname);

    if (exists) {
        // Table | json parsed
        let table = JSON.parse(fs.readFileSync(fname));

        let date = new Date();
        let id = date.getTime();
        tableRow['id'] = id;

        table[tableName].push(tableRow);

        try {
            fs.writeFileSync(fname, JSON.stringify(table, null, 2), (err) => {

            })

            callback(true, "Object written successfully!");
            return;
        } catch (e) {
            callback(false, "Error writing object.");
            return;
        }
    }
    callback(false, "Table/json file doesn't exist!");
    return;
}

function
insertTableContent
(
)
{
let
tableName
=
arguments
[
0
]
;
var
fname
=
''
;
var
callback
;
var
tableRow
;
if
(
arguments
.
length
===
3
)
{
callback
=
arguments
[
2
]
;
fname
=
path
.
join
(
userData
,
arguments
[
0
]
+
'.json'
)
;
tableRow
=
arguments
[
1
]
;
}
else
if
(
arguments
.
length
===
4
)
{
fname
=
path
.
join
(
arguments
[
1
]
,
arguments
[
0
]
+
'.json'
)
;
callback
=
arguments
[
3
]
;
tableRow
=
arguments
[
2
]
;
}
let
exists
=
fs
.
existsSync
(
fname
)
;
if
(
exists
)
{
// Table | json parsed
let
table
=
JSON
.
parse
(
fs
.
readFileSync
(
fname
)
)
;
let
date
=
new
Date
(
)
;
let
id
=
date
.
getTime
(
)
;
tableRow
[
'id'
]
=
id
;
table
[
tableName
]
.
push
(
tableRow
)
;
try
{
fs
.
writeFileSync
(
fname
,
JSON
.
stringify
(
table
,
,
2
)
,
(
err
)
=>
{
}
)
callback
(
true
,
"Object written successfully!"
)
;
return
;
}
catch
(
e
)
{
callback
(
false
,
"Error writing object."
)
;
return
;
}
}
callback
(
false
,
"Table/json file doesn't exist!"
)
;
return
;
}

Insert object to table. The object will be appended with the property, id
which uses timestamp as value.
There are 3 required arguments.
@param  {string} arguments[0]  [Table name]
@param  {string} arguments[1] [Location of the database file] (Optional)
@param  {string} arguments[2] [Row object]
@param  {Function} arguments[3] [Callback function]
 function insertTableContent(tableName, tableRow, callback) {

Insert object to table . The object will be appended with the property id which uses timestamp as value . There are 3 required arguments .


function count() {
    let tableName = arguments[0]
    let callback
    if (arguments.length === 2) {
        callback = arguments[1]
        getAll(tableName, (succ, data) => {
            if (succ) {
                callback(true, data.length)
                return
            } else {
                callback(false, data)
                return
            }
        })
    } else if (arguments.length === 3) {
        callback = arguments[2]
        getAll(tableName, arguments[1], (succ, data) => {
            if (succ) {
                callback(true, data.length)
                return
            } else {
                callback(false, data)
                return
            }
        })
    } else {
        callback(false,'Wrong number of arguments. Must be either 2 or 3 arguments including callback function.')
        return
    }
}

Count the number of rows for a given table.
@param {string} FirstArgument Table name
@param {string} SecondArgument Location of the database file (Optional)
@param {callback} ThirdArgument Function callback

Count the number of rows for a given table .


function updateRow() {
    let tableName = arguments[0];
    var fname = '';
    var where;
    var set;
    var callback;

    if (arguments.length === 4) {
        fname = path.join(userData, tableName + '.json');
        where = arguments[1];
        set = arguments[2];
        callback = arguments[3];
    } else if (arguments.length === 5) {
        fname = path.join(arguments[1], arguments[0] + '.json');
        where = arguments[2];
        set = arguments[3];
        callback = arguments[4];
    }

    let exists = fs.existsSync(fname);

    let whereKeys = Object.keys(where);
    let setKeys = Object.keys(set);

    if (exists) {
        let table = JSON.parse(fs.readFileSync(fname));
        let rows = table[tableName];

        let matched = 0; // Number of matched complete where clause
        let matchedIndex = 0;

        for (var i = 0; i < rows.length; i++) {

            for (var j = 0; j < whereKeys.length; j++) {
                // Test if there is a matched key with where clause and single row of table
                if (rows[i].hasOwnProperty(whereKeys[j])) {
                    if (rows[i][whereKeys[j]] === where[whereKeys[j]]) {
                        matched++;
                        matchedIndex = i;
                    }
                }
            }
        }

        if (matched === whereKeys.length) {
            // All field from where clause are present in this particular
            // row of the database table
            try {
                for (var k = 0; k < setKeys.length; k++) {
                    // rows[i][setKeys[k]] = set[setKeys[k]];
                    rows[matchedIndex][setKeys[k]] = set[setKeys[k]];
                }

                // Create a new object and pass the rows
                let obj = new Object();
                obj[tableName] = rows;

                // Write the object to json file
                try {
                    fs.writeFileSync(fname, JSON.stringify(obj, null, 2), (err) => {

                    })

                    callback(true, "Success!")
                    return;
                } catch (e) {
                    callback(false, e.toString());
                    return;
                }

                callback(true, rows);
            } catch (e) {
                callback(false, e.toString());
                return;
            }
        } else {
            callback(false, "Cannot find the specified record.");
            return;
        }

    } else {
        callback(false, 'Table file does not exist!');
        return;
    }
}

Update a row or record which satisfies the where clause
@param  {[string]} arguments[0] [Table name]
@param {string} arguments[1] [Location of the database file] (Optional)
@param  {[object]} arguments[2]     [Objet for WHERE clause]
@param  {[object]} arguments[3]       [Object for SET clause]
@param  {Function} arguments[4]  [Callback function]
 function updateRow(tableName, where, set, callback) {


function createHeaderGetter (str) {
  var name = str.toLowerCase()

  return function (req, res) {
    // set appropriate Vary header
    vary(res, str)

    // get header
    var header = req.headers[name]

    if (!header) {
      return undefined
    }

    // multiple headers get joined with comma by node.js core
    var index = header.indexOf(',')

    // return first value
    return index !== -1
      ? header.substr(0, index).trim()
      : header.trim()
  }
}

Create a getter for the given header name.

Create a getter for the given header name .


function Param(name, shortName, process) {
      if (process == null) {
        process = cloudinary.Util.identity;
      }

      /**
       * The name of the parameter in snake_case
       * @member {string} Param#name
       */
      this.name = name;

      /**
       * The name of the serialized form of the parameter
       * @member {string} Param#shortName
       */
      this.shortName = shortName;

      /**
       * Manipulate origValue when value is called
       * @member {function} Param#process
       */
      this.process = process;
    }

Represents a single parameter
@class Param
@param {string} name - The name of the parameter in snake_case
@param {string} shortName - The name of the serialized form of the parameter.
If a value is not provided, the parameter will not be serialized.
@param {function} [process=cloudinary.Util.identity ] - Manipulate origValue when value is called
@ignore


function ArrayParam(name, shortName, sep, process) {
      if (sep == null) {
        sep = '.';
      }
      this.sep = sep;
      ArrayParam.__super__.constructor.call(this, name, shortName, process);
    }

function ArrayParam ( name , shortName , sep , process ) { if ( sep == null ) { sep = '.' ; } this . sep = sep ; ArrayParam . __super__ . constructor . call ( this , name , shortName , process ) ; }

A parameter that represents an array
@param {string} name - The name of the parameter in snake_case
@param {string} shortName - The name of the serialized form of the parameter
If a value is not provided, the parameter will not be serialized.
@param {string} [sep='.'] - The separator to use when joining the array elements together
@param {function} [process=cloudinary.Util.identity ] - Manipulate origValue when value is called
@class ArrayParam
@extends Param
@ignore


function TransformationParam(name, shortName, sep, process) {
      if (shortName == null) {
        shortName = "t";
      }
      if (sep == null) {
        sep = '.';
      }
      this.sep = sep;
      TransformationParam.__super__.constructor.call(this, name, shortName, process);
    }

function TransformationParam ( name , shortName , sep , process ) { if ( shortName == null ) { shortName = "t" ; } if ( sep == null ) { sep = '.' ; } this . sep = sep ; TransformationParam . __super__ . constructor . call ( this , name , shortName , process ) ; }

A parameter that represents a transformation
@param {string} name - The name of the parameter in snake_case
@param {string} [shortName='t'] - The name of the serialized form of the parameter
@param {string} [sep='.'] - The separator to use when joining the array elements together
@param {function} [process=cloudinary.Util.identity ] - Manipulate origValue when value is called
@class TransformationParam
@extends Param
@ignore


function RangeParam(name, shortName, process) {
      if (process == null) {
        process = this.norm_range_value;
      }
      RangeParam.__super__.constructor.call(this, name, shortName, process);
    }

function RangeParam ( name , shortName , process ) { if ( process == null ) { process = this . norm_range_value ; } RangeParam . __super__ . constructor . call ( this , name , shortName , process ) ; }

A parameter that represents a range
@param {string} name - The name of the parameter in snake_case
@param {string} shortName - The name of the serialized form of the parameter
If a value is not provided, the parameter will not be serialized.
@param {function} [process=norm_range_value ] - Manipulate origValue when value is called
@class RangeParam
@extends Param
@ignore


function Configuration(options) {
      if (options == null) {
        options = {};
      }
      this.configuration = Util.cloneDeep(options);
      Util.defaults(this.configuration, DEFAULT_CONFIGURATION_PARAMS);
    }

function Configuration ( options ) { if ( options == null ) { options = { } ; } this . configuration = Util . cloneDeep ( options ) ; Util . defaults ( this . configuration , DEFAULT_CONFIGURATION_PARAMS ) ; }

Cloudinary configuration class
@constructor Configuration
@param {Object} options - configuration parameters


function Cloudinary(options) {
      var configuration;
      this.devicePixelRatioCache = {};
      this.responsiveConfig = {};
      this.responsiveResizeInitialized = false;
      configuration = new Configuration(options);
      this.config = function(newConfig, newValue) {
        return configuration.config(newConfig, newValue);
      };

      /**
       * Use \<meta\> tags in the document to configure this Cloudinary instance.
       * @return {Cloudinary} this for chaining
       */
      this.fromDocument = function() {
        configuration.fromDocument();
        return this;
      };

      /**
       * Use environment variables to configure this Cloudinary instance.
       * @return {Cloudinary} this for chaining
       */
      this.fromEnvironment = function() {
        configuration.fromEnvironment();
        return this;
      };

      /**
       * Initialize configuration.
       * @function Cloudinary#init
       * @see Configuration#init
       * @return {Cloudinary} this for chaining
       */
      this.init = function() {
        configuration.init();
        return this;
      };
    }

Main Cloudinary class
@class Cloudinary
@param {Object} options - options to configure Cloudinary
@see Configuration for more details
@example
var cl = new cloudinary.Cloudinary( { cloud_name: "mycloud"});
var imgTag = cl.image("myPicID");


function getMode(env, argv) {
  // When running from parallel-webpack, grab the cli parameters
  argv = Object.keys(argv).length ? argv : require('minimist')(process.argv.slice(2));
  var isProd = (argv.mode || env.mode) === 'production' || env === 'prod' || env.prod;
  return isProd ? 'production' : 'development';
}

Determine the build mode.
@param {object} env - webpack environment
@param {boolean} [env.production] - when true, set mode to production
@param {boolean} [env.development] - when true, set mode to development
@param {object} argv - webpack options
@param {string} [argv.mode] - the build mode


function resolveLodash(context, request, callback) {
  if (/^lodash\//.test(request)) {
    callback(null, {
      commonjs: request,
      commonjs2: request,
      amd: request,
      root: ['_', request.split('/')[1]]
    });
  } else {
    callback();
  }
}

function resolveLodash ( context , request , callback ) { if ( / ^lodash\/ / . test ( request ) ) { callback ( null , { commonjs : request , commonjs2 : request , amd : request , root : [ '_' , request . split ( '/' ) [ 1 ] ] } ) ; } else { callback ( ) ; } }

This function is used by webpack to resolve individual lodash modules
@param context
@param request
@param callback


function baseConfig(name, mode) {
  const config = {
    name: `${name}-${mode}`,
    mode,
    output: {
      library: 'cloudinary',
      libraryTarget: 'umd',
      globalObject: "this",
      pathinfo: false
    },
    optimization: {
      concatenateModules: true,
      moduleIds: 'named',
      usedExports: true,
      minimizer: [new TerserPlugin({
        terserOptions: {
          mangle: {
            keep_classnames: true,
            reserved: reserved,
            ie8: true
          }
        },
      })]
    },
    resolve: {
      extensions: ['.js']
    },
    externals: [
      {
        jquery: 'jQuery'
      }
    ],
    node: {
      Buffer: false,
      process: false
    },
    devtool: "source-map",
    module: {
      rules: [
        {
          test: /\.m?js$/,
          exclude: /(node_modules|bower_components)/,
          use: {loader: 'babel-loader'}
        }
      ]
    },
    plugins: [
      new webpack.BannerPlugin({
        banner: `/**
   * cloudinary-[name].js
   * Cloudinary's JavaScript library - Version ${version}
   * Copyright Cloudinary
   * see https://github.com/cloudinary/cloudinary_js
   *
   */`, // the banner as string or function, it will be wrapped in a comment
        raw: true, // if true, banner will not be wrapped in a comment
        entryOnly: true, // if true, the banner will only be added to the entry chunks
      })
    ]
  };

  let filename = `cloudinary-${name}`;
  if(mode === 'production') { filename += '.min';}

  const util = name.startsWith('jquery') ? 'jquery' : 'lodash';
  const utilPath = path.resolve(__dirname, `src/util/${util}`);

  config.output.filename = `./${filename}.js`;
  config.entry = `./src/namespace/cloudinary-${name}.js`;
  config.resolve.alias = {
    "../util$": utilPath,
    "./util$": utilPath
  };
  // Add reference to each lodash function as a separate module.
  if (name === 'core') {
    config.externals.push(resolveLodash);
  }
  config.plugins.push(
    new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      reportFilename: `./${filename}-visualizer.html`,
      openAnalyzer: false
    })
  );
  return config;
}

Generate a webpack configuration
@param {string} name the name of the package
@param {string} mode either development or production
@return {object} webpack configuration


function finalizeResourceType(resourceType = "image", type = "upload", urlSuffix, useRootPath, shorten) {
  var options;
  resourceType = resourceType == null ? "image" : resourceType;
  type = type == null ? "upload" : type;
  if (isPlainObject(resourceType)) {
    options = resourceType;
    resourceType = options.resource_type;
    type = options.type;
    urlSuffix = options.url_suffix;
    useRootPath = options.use_root_path;
    shorten = options.shorten;
  }
  if (type == null) {
    type = 'upload';
  }
  if (urlSuffix != null) {
    resourceType = SEO_TYPES[`${resourceType}/${type}`];
    type = null;
    if (resourceType == null) {
      throw new Error(`URL Suffix only supported for ${Object.keys(SEO_TYPES).join(', ')}`);
    }
  }
  if (useRootPath) {
    if (resourceType === 'image' && type === 'upload' || resourceType === "images") {
      resourceType = null;
      type = null;
    } else {
      throw new Error("Root path only supported for image/upload");
    }
  }
  if (shorten && resourceType === 'image' && type === 'upload') {
    resourceType = 'iu';
    type = null;
  }
  return [resourceType, type].join("/");
}

Return the resource type and action type based on the given configuration
@function Cloudinary#finalizeResourceType
@param {Object|string} resourceType
@param {string} [type='upload']
@param {string} [urlSuffix]
@param {boolean} [useRootPath]
@param {boolean} [shorten]
@returns {string} resource_type/type
@ignore


function Drag(parent, options) {
        _classCallCheck(this, Drag);

        options = options || {};

        var _this = _possibleConstructorReturn(this, (Drag.__proto__ || Object.getPrototypeOf(Drag)).call(this, parent));

        _this.moved = false;
        _this.wheelActive = utils.defaults(options.wheel, true);
        _this.wheelScroll = options.wheelScroll || 1;
        _this.reverse = options.reverse ? 1 : -1;
        _this.clampWheel = options.clampWheel;
        _this.factor = options.factor || 1;
        _this.xDirection = !options.direction || options.direction === 'all' || options.direction === 'x';
        _this.yDirection = !options.direction || options.direction === 'all' || options.direction === 'y';
        _this.parseUnderflow(options.underflow || 'center');
        _this.mouseButtons(options.mouseButtons);
        return _this;
    }

function Drag ( parent , options ) { _classCallCheck ( this , Drag ) ; options = options || { } ; var _this = _possibleConstructorReturn ( this , ( Drag . __proto__ || Object . getPrototypeOf ( Drag ) ) . call ( this , parent ) ) ; _this . moved = false ; _this . wheelActive = utils . defaults ( options . wheel , true ) ; _this . wheelScroll = options . wheelScroll || 1 ; _this . reverse = options . reverse ? 1 : - 1 ; _this . clampWheel = options . clampWheel ; _this . factor = options . factor || 1 ; _this . xDirection = ! options . direction || options . direction === 'all' || options . direction === 'x' ; _this . yDirection = ! options . direction || options . direction === 'all' || options . direction === 'y' ; _this . parseUnderflow ( options . underflow || 'center' ) ; _this . mouseButtons ( options . mouseButtons ) ; return _this ; }

enable one-finger touch to drag
@private
@param {Viewport} parent
@param {object} [options]
@param {string} [options.direction=all] direction to drag (all, x, or y)
@param {boolean} [options.wheel=true] use wheel to scroll in y direction (unless wheel plugin is active)
@param {number} [options.wheelScroll=1] number of pixels to scroll with each wheel spin
@param {boolean} [options.reverse] reverse the direction of the wheel scroll
@param {boolean|string} [options.clampWheel] (true, x, or y) clamp wheel (to avoid weird bounce with mouse wheel)
@param {string} [options.underflow=center] (top/bottom/center and left/right/center, or center) where to place world if too small for screen
@param {number} [options.factor=1] factor to multiply drag to increase the speed of movement
@param {string} [options.mouseButtons=all] changes which mouse buttons trigger drag, use: 'all', 'left', right' 'middle', or some combination, like, 'middle-right'


function each(object, fn) {
  keys(object).forEach(function (key) {
    return fn(object[key], key);
  });
}

function each ( object , fn ) { keys ( object ) . forEach ( function ( key ) { return fn ( object [ key ] , key ) ; } ) ; }

Array-like iteration for objects.

@param {Object} object
The object to iterate over

@param {obj:EachCallback} fn
The callback function which is called for each key in the object.


function reduce(object, fn) {
  var initial = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;

  return keys(object).reduce(function (accum, key) {
    return fn(accum, object[key], key);
  }, initial);
}

function reduce ( object , fn ) { var initial = arguments . length > 2 && arguments [ 2 ] !== undefined ? arguments [ 2 ] : 0 ; return keys ( object ) . reduce ( function ( accum , key ) { return fn ( accum , object [ key ] , key ) ; } , initial ) ; }

Array-like reduce for objects.

@param {Object} object
The Object that you want to reduce.

@param {Function} fn
A callback function which is called for each key in the object. It
receives the accumulated value and the per-iteration value and key
as arguments.

@param {Mixed} [initial = 0]
Starting value

@return {Mixed}
The final accumulated value.


function isPlain(value) {
  return isObject(value) && toString.call(value) === '[object Object]' && value.constructor === Object;
}

function
isPlain
(
value
)
{
return
isObject
(
value
)
&&
toString
.
call
(
value
)
===
'[object Object]'
&&
value
.
constructor
===
Object
;
}

Returns whether an object appears to be a "plain" object - that is, a
direct instance of `Object`.

@param  {Object} value
@return {Boolean}

Returns whether an object appears to be a plain object - that is a direct instance of Object .


function logByType(type, args) {
  var stringify = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : !!IE_VERSION && IE_VERSION < 11;

  var lvl = log.levels[level];
  var lvlRegExp = new RegExp('^(' + lvl + ')$');

  if (type !== 'log') {

    // Add the type to the front of the message when it's not "log".
    args.unshift(type.toUpperCase() + ':');
  }

  // Add a clone of the args at this point to history.
  if (history) {
    history.push([].concat(args));
  }

  // Add console prefix after adding to history.
  args.unshift('VIDEOJS:');

  // If there's no console then don't try to output messages, but they will
  // still be stored in history.
  //
  // Was setting these once outside of this function, but containing them
  // in the function makes it easier to test cases where console doesn't exist
  // when the module is executed.
  var fn = window.console && window.console[type];

  // Bail out if there's no console or if this type is not allowed by the
  // current logging level.
  if (!fn || !lvl || !lvlRegExp.test(type)) {
    return;
  }

  // IEs previous to 11 log objects uselessly as "[object Object]"; so, JSONify
  // objects and arrays for those less-capable browsers.
  if (stringify) {
    args = args.map(function (a) {
      if (isObject(a) || Array.isArray(a)) {
        try {
          return JSON.stringify(a);
        } catch (x) {
          return String(a);
        }
      }

      // Cast to string before joining, so we get null and undefined explicitly
      // included in output (as we would in a modern console).
      return String(a);
    }).join(' ');
  }

  // Old IE versions do not allow .apply() for console methods (they are
  // reported as objects rather than functions).
  if (!fn.apply) {
    fn(args);
  } else {
    fn[Array.isArray(args) ? 'apply' : 'call'](window.console, args);
  }
}

Log messages to the console and history based on the type of message

@private
@param  {string} type
The name of the console method to use.

@param  {Array} args
The arguments to be passed to the matching console method.

@param  {boolean} [stringify]
By default, only old IEs should get console argument stringification,
but this is exposed as a parameter to facilitate testing.


function createEl() {
  var tagName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'div';
  var properties = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  var content = arguments[3];

  var el = document.createElement(tagName);

  Object.getOwnPropertyNames(properties).forEach(function (propName) {
    var val = properties[propName];

    // See #2176
    // We originally were accepting both properties and attributes in the
    // same object, but that doesn't work so well.
    if (propName.indexOf('aria-') !== -1 || propName === 'role' || propName === 'type') {
      log$1.warn(tsml(_templateObject, propName, val));
      el.setAttribute(propName, val);

      // Handle textContent since it's not supported everywhere and we have a
      // method for it.
    } else if (propName === 'textContent') {
      textContent(el, val);
    } else {
      el[propName] = val;
    }
  });

  Object.getOwnPropertyNames(attributes).forEach(function (attrName) {
    el.setAttribute(attrName, attributes[attrName]);
  });

  if (content) {
    appendContent(el, content);
  }

  return el;
}

Creates an element and applies properties.

@param {string} [tagName='div']
Name of tag to be created.

@param {Object} [properties={}]
Element properties to be applied.

@param {Object} [attributes={}]
Element attributes to be applied.

@param {String|Element|TextNode|Array|Function} [content]
Contents for the element (see: {@link dom:normalizeContent})

@return {Element}
The element that was created.

Creates an element and applies properties .


function addClass(element, classToAdd) {
  if (element.classList) {
    element.classList.add(classToAdd);

    // Don't need to `throwIfWhitespace` here because `hasElClass` will do it
    // in the case of classList not being supported.
  } else if (!hasClass(element, classToAdd)) {
    element.className = (element.className + ' ' + classToAdd).trim();
  }

  return element;
}

Add a CSS class name to an element

@param {Element} element
Element to add class name to.

@param {string} classToAdd
Class name to add.

@return {Element}
The dom element with the added class name.


function toggleClass(element, classToToggle, predicate) {

  // This CANNOT use `classList` internally because IE does not support the
  // second parameter to the `classList.toggle()` method! Which is fine because
  // `classList` will be used by the add/remove functions.
  var has = hasClass(element, classToToggle);

  if (typeof predicate === 'function') {
    predicate = predicate(element, classToToggle);
  }

  if (typeof predicate !== 'boolean') {
    predicate = !has;
  }

  // If the necessary class operation matches the current state of the
  // element, no action is required.
  if (predicate === has) {
    return;
  }

  if (predicate) {
    addClass(element, classToToggle);
  } else {
    removeClass(element, classToToggle);
  }

  return element;
}

The callback definition for toggleElClass.

@callback Dom~PredicateCallback
@param {Element} element
The DOM element of the Component.

@param {string} classToToggle
The `className` that wants to be toggled

@return {boolean|undefined}
- If true the `classToToggle` will get added to `element`.
- If false the `classToToggle` will get removed from `element`.
- If undefined this callback will be ignored

Adds or removes a CSS class name on an element depending on an optional
condition or the presence/absence of the class name.

@param {Element} element
The element to toggle a class name on.

@param {string} classToToggle
The class that should be toggled

@param {boolean|PredicateCallback} [predicate]
See the return value for {@link Dom~PredicateCallback}

@return {Element}
The element with a class that has been toggled.

The callback definition for toggleElClass .


function getPointerPosition(el, event) {
  var position = {};
  var box = findPosition(el);
  var boxW = el.offsetWidth;
  var boxH = el.offsetHeight;

  var boxY = box.top;
  var boxX = box.left;
  var pageY = event.pageY;
  var pageX = event.pageX;

  if (event.changedTouches) {
    pageX = event.changedTouches[0].pageX;
    pageY = event.changedTouches[0].pageY;
  }

  position.y = Math.max(0, Math.min(1, (boxY - pageY + boxH) / boxH));
  position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));

  return position;
}

function getPointerPosition ( el , event ) { var position = { } ; var box = findPosition ( el ) ; var boxW = el . offsetWidth ; var boxH = el . offsetHeight ; var boxY = box . top ; var boxX = box . left ; var pageY = event . pageY ; var pageX = event . pageX ; if ( event . changedTouches ) { pageX = event . changedTouches [ 0 ] . pageX ; pageY = event . changedTouches [ 0 ] . pageY ; } position . y = Math . max ( 0 , Math . min ( 1 , ( boxY - pageY + boxH ) / boxH ) ) ; position . x = Math . max ( 0 , Math . min ( 1 , ( pageX - boxX ) / boxW ) ) ; return position ; }

x and y coordinates for a dom element or mouse pointer

@typedef {Object} Dom~Coordinates

@property {number} x
x coordinate in pixels

@property {number} y
y coordinate in pixels

Get pointer position in element
Returns an object with x and y coordinates.
The base on the coordinates are the bottom left of the element.

@param {Element} el
Element on which to get the pointer position on

@param {EventTarget~Event} event
Event object

@return {Dom~Coordinates}
A Coordinates object corresponding to the mouse position.


function appendContent(el, content) {
  normalizeContent(content).forEach(function (node) {
    return el.appendChild(node);
  });
  return el;
}

function appendContent ( el , content ) { normalizeContent ( content ) . forEach ( function ( node ) { return el . appendChild ( node ) ; } ) ; return el ; }

Normalizes and appends content to an element.

@param {Element} el
Element to append normalized content to.

@param {String|Element|TextNode|Array|Function} content
See the `content` argument of {@link dom:normalizeContent}

@return {Element}
The element with appended normalized content.

Normalizes and appends content to an element .


function getData(el) {
  var id = el[elIdAttr];

  if (!id) {
    id = el[elIdAttr] = newGUID();
  }

  if (!elData[id]) {
    elData[id] = {};
  }

  return elData[id];
}

function getData ( el ) { var id = el [ elIdAttr ] ; if ( ! id ) { id = el [ elIdAttr ] = newGUID ( ) ; } if ( ! elData [ id ] ) { elData [ id ] = { } ; } return elData [ id ] ; }

Returns the cache object where data for an element is stored

@param {Element} el
Element to store data for.

@return {Object}
The cache object for that el that was passed in.


function hasData(el) {
  var id = el[elIdAttr];

  if (!id) {
    return false;
  }

  return !!Object.getOwnPropertyNames(elData[id]).length;
}

function hasData ( el ) { var id = el [ elIdAttr ] ; if ( ! id ) { return false ; } return ! ! Object . getOwnPropertyNames ( elData [ id ] ) . length ; }

Returns whether or not an element has cached data

@param {Element} el
Check if this element has cached data.

@return {boolean}
- True if the DOM element has cached data.
- False otherwise.


function removeData(el) {
  var id = el[elIdAttr];

  if (!id) {
    return;
  }

  // Remove all stored data
  delete elData[id];

  // Remove the elIdAttr property from the DOM node
  try {
    delete el[elIdAttr];
  } catch (e) {
    if (el.removeAttribute) {
      el.removeAttribute(elIdAttr);
    } else {
      // IE doesn't appear to support removeAttribute on the document element
      el[elIdAttr] = null;
    }
  }
}

Delete data for the element from the cache and the guid attr from getElementById

@param {Element} el
Remove cached data for this element.


function _handleMultipleEvents(fn, elem, types, callback) {
  types.forEach(function (type) {
    // Call the event method for each one of the types
    fn(elem, type, callback);
  });
}

Loops through an array of event types and calls the requested method for each type.

@param {Function} fn
The event method we want to use.

@param {Element|Object} elem
Element or object to bind listeners to

@param {string} type
Type of event to bind to.

@param {EventTarget~EventListener} callback
Event listener.

Loops through an array of event types and calls the requested method for each type .


function off(elem, type, fn) {
  // Don't want to add a cache object through getElData if not needed
  if (!hasData(elem)) {
    return;
  }

  var data = getData(elem);

  // If no events exist, nothing to unbind
  if (!data.handlers) {
    return;
  }

  if (Array.isArray(type)) {
    return _handleMultipleEvents(off, elem, type, fn);
  }

  // Utility function
  var removeType = function removeType(t) {
    data.handlers[t] = [];
    _cleanUpEvents(elem, t);
  };

  // Are we removing all bound events?
  if (!type) {
    for (var t in data.handlers) {
      removeType(t);
    }
    return;
  }

  var handlers = data.handlers[type];

  // If no handlers exist, nothing to unbind
  if (!handlers) {
    return;
  }

  // If no listener was provided, remove all listeners for type
  if (!fn) {
    removeType(type);
    return;
  }

  // We're only removing a single handler
  if (fn.guid) {
    for (var n = 0; n < handlers.length; n++) {
      if (handlers[n].guid === fn.guid) {
        handlers.splice(n--, 1);
      }
    }
  }

  _cleanUpEvents(elem, type);
}

Removes event listeners from an element

@param {Element|Object} elem
Object to remove listeners from.

@param {string|string[]} [type]
Type of listener to remove. Don't include to remove all events from element.

@param {EventTarget~EventListener} [fn]
Specific listener to remove. Don't include to remove listeners for an event
type.


function one(elem, type, fn) {
  if (Array.isArray(type)) {
    return _handleMultipleEvents(one, elem, type, fn);
  }
  var func = function func() {
    off(elem, type, func);
    fn.apply(this, arguments);
  };

  // copy the guid to the new function so it can removed using the original function's ID
  func.guid = fn.guid = fn.guid || newGUID();
  on(elem, type, func);
}

Trigger a listener only once for an event

@param {Element|Object} elem
Element or object to bind to.

@param {string|string[]} type
Name/type of event

@param {Event~EventListener} fn
Event Listener function


function autoSetup() {

  // Protect against breakage in non-browser environments.
  if (!isReal()) {
    return;
  }

  // One day, when we stop supporting IE8, go back to this, but in the meantime...*hack hack hack*
  // var vids = Array.prototype.slice.call(document.getElementsByTagName('video'));
  // var audios = Array.prototype.slice.call(document.getElementsByTagName('audio'));
  // var mediaEls = vids.concat(audios);

  // Because IE8 doesn't support calling slice on a node list, we need to loop
  // through each list of elements to build up a new, combined list of elements.
  var vids = document.getElementsByTagName('video');
  var audios = document.getElementsByTagName('audio');
  var mediaEls = [];

  if (vids && vids.length > 0) {
    for (var i = 0, e = vids.length; i < e; i++) {
      mediaEls.push(vids[i]);
    }
  }

  if (audios && audios.length > 0) {
    for (var _i = 0, _e = audios.length; _i < _e; _i++) {
      mediaEls.push(audios[_i]);
    }
  }

  // Check if any media elements exist
  if (mediaEls && mediaEls.length > 0) {

    for (var _i2 = 0, _e2 = mediaEls.length; _i2 < _e2; _i2++) {
      var mediaEl = mediaEls[_i2];

      // Check if element exists, has getAttribute func.
      // IE seems to consider typeof el.getAttribute == 'object' instead of
      // 'function' like expected, at least when loading the player immediately.
      if (mediaEl && mediaEl.getAttribute) {

        // Make sure this player hasn't already been set up.
        if (mediaEl.player === undefined) {
          var options = mediaEl.getAttribute('data-setup');

          // Check if data-setup attr exists.
          // We only auto-setup if they've added the data-setup attr.
          if (options !== null) {
            // Create new video.js instance.
            videojs$2(mediaEl);
          }
        }

        // If getAttribute isn't defined, we need to wait for the DOM.
      } else {
        autoSetupTimeout(1);
        break;
      }
    }

    // No videos were found, so keep looping unless page is finished loading.
  } else if (!_windowLoaded) {
    autoSetupTimeout(1);
  }
}

Set up any tags that have a data-setup `attribute` when the player is started.

Set up any tags that have a data - setup attribute when the player is started .


function autoSetupTimeout(wait, vjs) {
  if (vjs) {
    videojs$2 = vjs;
  }

  window.setTimeout(autoSetup, wait);
}

function autoSetupTimeout ( wait , vjs ) { if ( vjs ) { videojs$2 = vjs ; } window . setTimeout ( autoSetup , wait ) ; }

Wait until the page is loaded before running autoSetup. This will be called in
autoSetup if `hasLoaded` returns false.

@param {number} wait
How long to wait in ms

@param {module:videojs} [vjs]
The videojs library function

Wait until the page is loaded before running autoSetup . This will be called in autoSetup if hasLoaded returns false .


function setTextContent(el, content) {
  if (el.styleSheet) {
    el.styleSheet.cssText = content;
  } else {
    el.textContent = content;
  }
}

function setTextContent ( el , content ) { if ( el . styleSheet ) { el . styleSheet . cssText = content ; } else { el . textContent = content ; } }

Add text to a DOM element.

@param {Element} el
The Element to add text content to.

@param {string} content
The text to add to the element.


function throttle(fn, wait) {
  var last = Date.now();

  var throttled = function throttled() {
    var now = Date.now();

    if (now - last >= wait) {
      fn.apply(undefined, arguments);
      last = now;
    }
  };

  return throttled;
}

function throttle ( fn , wait ) { var last = Date . now ( ) ; var throttled = function throttled ( ) { var now = Date . now ( ) ; if ( now - last >= wait ) { fn . apply ( undefined , arguments ) ; last = now ; } } ; return throttled ; }

Wraps the given function, `fn`, with a new function that only invokes `fn`
at most once per every `wait` milliseconds.

@param  {Function} fn
The function to be throttled.

@param  {Number}   wait
The number of milliseconds by which to throttle.

@return {Function}

Wraps the given function fn with a new function that only invokes fn at most once per every wait milliseconds .


function isValidEventType(type) {
  return (
    // The regex here verifies that the `type` contains at least one non-
    // whitespace character.
    typeof type === 'string' && /\S/.test(type) || Array.isArray(type) && !!type.length
  );
}

Whether a value is a valid event type - non-empty string or array.

@private
@param  {string|Array} type
The type value to test.

@return {boolean}
Whether or not the type is a valid event type.

Whether a value is a valid event type - non - empty string or array .


function Component(player, options, ready) {
    classCallCheck(this, Component);

    // The component might be the player itself and we can't pass `this` to super
    if (!player && this.play) {
      this.player_ = player = this; // eslint-disable-line
    } else {
      this.player_ = player;
    }

    // Make a copy of prototype.options_ to protect against overriding defaults
    this.options_ = mergeOptions({}, this.options_);

    // Updated options with supplied options
    options = this.options_ = mergeOptions(this.options_, options);

    // Get ID from options or options element if one is supplied
    this.id_ = options.id || options.el && options.el.id;

    // If there was no ID from the options, generate one
    if (!this.id_) {
      // Don't require the player ID function in the case of mock players
      var id = player && player.id && player.id() || 'no_player';

      this.id_ = id + '_component_' + newGUID();
    }

    this.name_ = options.name || null;

    // Create element if one wasn't provided in options
    if (options.el) {
      this.el_ = options.el;
    } else if (options.createEl !== false) {
      this.el_ = this.createEl();
    }

    // Make this an evented object and use `el_`, if available, as its event bus
    evented(this, { eventBusKey: this.el_ ? 'el_' : null });
    stateful(this, this.constructor.defaultState);

    this.children_ = [];
    this.childIndex_ = {};
    this.childNameIndex_ = {};

    // Add any child components in options
    if (options.initChildren !== false) {
      this.initChildren();
    }

    this.ready(ready);
    // Don't want to trigger ready here or it will before init is actually
    // finished for all children that run this constructor

    if (options.reportTouchActivity !== false) {
      this.enableTouchActivity();
    }
  }

A callback that is called when a component is ready. Does not have any
paramters and any callback value will be ignored.

@callback Component~ReadyCallback
@this Component

Creates an instance of this class.

@param {Player} player
The `Player` that this class should be attached to.

@param {Object} [options]
The key/value store of player options.

@param {Object[]} [options.children]
An array of children objects to intialize this component with. Children objects have
a name property that will be used if more than one component of the same type needs to be
added.

@param {Component~ReadyCallback} [ready]
Function that gets called when the `Component` is ready.

A callback that is called when a component is ready . Does not have any paramters and any callback value will be ignored .


function rangeCheck(fnName, index, maxIndex) {
  if (typeof index !== 'number' || index < 0 || index > maxIndex) {
    throw new Error('Failed to execute \'' + fnName + '\' on \'TimeRanges\': The index provided (' + index + ') is non-numeric or out of bounds (0-' + maxIndex + ').');
  }
}

An object that contains ranges of time for various reasons.

@typedef {Object} TimeRange

@property {number} length
The number of time ranges represented by this Object

@property {time-ranges:indexFunction} start
Returns the time offset at which a specified time range begins.

@property {time-ranges:indexFunction} end
Returns the time offset at which a specified time range begins.

@see https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges

Check if any of the time ranges are over the maximum index.

@param {string} fnName
The function name to use for logging

@param {number} index
The index to check

@param {number} maxIndex
The maximum possible index

@throws {Error} if the timeRanges provided are over the maxIndex

An object that contains ranges of time for various reasons .


function getRange(fnName, valueIndex, ranges, rangeIndex) {
  rangeCheck(fnName, rangeIndex, ranges.length - 1);
  return ranges[rangeIndex][valueIndex];
}

function getRange ( fnName , valueIndex , ranges , rangeIndex ) { rangeCheck ( fnName , rangeIndex , ranges . length - 1 ) ; return ranges [ rangeIndex ] [ valueIndex ] ; }

Check if any of the time ranges are over the maximum index.

@param {string} fnName
The function name to use for logging

@param {string} valueIndex
The proprety that should be used to get the time. should be 'start' or 'end'

@param {Array} ranges
An array of time ranges

@param {Array} [rangeIndex=0]
The index to start the search at

@return {number}
The time that offset at the specified index.

@depricated rangeIndex must be set to a value, in the future this will throw an error.
@throws {Error} if rangeIndex is more than the length of ranges

Check if any of the time ranges are over the maximum index .


function createTimeRangesObj(ranges) {
  if (ranges === undefined || ranges.length === 0) {
    return {
      length: 0,
      start: function start() {
        throw new Error('This TimeRanges object is empty');
      },
      end: function end() {
        throw new Error('This TimeRanges object is empty');
      }
    };
  }
  return {
    length: ranges.length,
    start: getRange.bind(null, 'start', 0, ranges),
    end: getRange.bind(null, 'end', 1, ranges)
  };
}

function
createTimeRangesObj
(
ranges
)
{
if
(
ranges
===
undefined
||
ranges
.
length
===
0
)
{
return
{
length
:
0
,
start
:
function
start
(
)
{
throw
new
Error
(
'This TimeRanges object is empty'
)
;
}
,
end
:
function
end
(
)
{
throw
new
Error
(
'This TimeRanges object is empty'
)
;
}
}
;
}
return
{
length
:
ranges
.
length
,
start
:
getRange
.
bind
(
,
'start'
,
0
,
ranges
)
,
end
:
getRange
.
bind
(
,
'end'
,
1
,
ranges
)
}
;
}

Create a time range object givent ranges of time.

@param {Array} [ranges]
An array of time ranges.

Create a time range object givent ranges of time .


function createTimeRanges(start, end) {
  if (Array.isArray(start)) {
    return createTimeRangesObj(start);
  } else if (start === undefined || end === undefined) {
    return createTimeRangesObj();
  }
  return createTimeRangesObj([[start, end]]);
}

function createTimeRanges ( start , end ) { if ( Array . isArray ( start ) ) { return createTimeRangesObj ( start ) ; } else if ( start === undefined || end === undefined ) { return createTimeRangesObj ( ) ; } return createTimeRangesObj ( [ [ start , end ] ] ) ; }

Should create a fake `TimeRange` object which mimics an HTML5 time range instance.

@param {number|Array} start
The start of a single range or an array of ranges

@param {number} end
The end of a single range.

@private

Should create a fake TimeRange object which mimics an HTML5 time range instance .


function TextTrackCueList(cues) {
    classCallCheck(this, TextTrackCueList);

    var list = this; // eslint-disable-line

    if (IS_IE8) {
      list = document.createElement('custom');

      for (var prop in TextTrackCueList.prototype) {
        if (prop !== 'constructor') {
          list[prop] = TextTrackCueList.prototype[prop];
        }
      }
    }

    TextTrackCueList.prototype.setCues_.call(list, cues);

    /**
     * @memberof TextTrackCueList
     * @member {number} length
     *         The current number of `TextTrackCue`s in the TextTrackCueList.
     * @instance
     */
    Object.defineProperty(list, 'length', {
      get: function get$$1() {
        return this.length_;
      }
    });

    if (IS_IE8) {
      return list;
    }
  }

Create an instance of this class..

@param {Array} cues
A list of cues to be initialized with


function getFileExtension(path) {
  if (typeof path === 'string') {
    var splitPathRe = /^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i;
    var pathParts = splitPathRe.exec(path);

    if (pathParts) {
      return pathParts.pop().toLowerCase();
    }
  }

  return '';
}

Returns the extension of the passed file name. It will return an empty string
if passed an invalid path.

@param {string} path
The fileName path like '/path/to/file.mp4'

@returns {string}
The extension in lower case or an empty string if no
extension could be found.

Returns the extension of the passed file name . It will return an empty string if passed an invalid path .


function loadTrack(src, track) {
  var opts = {
    uri: src
  };
  var crossOrigin = isCrossOrigin(src);

  if (crossOrigin) {
    opts.cors = crossOrigin;
  }

  xhr(opts, bind(this, function (err, response, responseBody) {
    if (err) {
      return log$1.error(err, response);
    }

    track.loaded_ = true;

    // Make sure that vttjs has loaded, otherwise, wait till it finished loading
    // NOTE: this is only used for the alt/video.novtt.js build
    if (typeof window.WebVTT !== 'function') {
      if (track.tech_) {
        var loadHandler = function loadHandler() {
          return parseCues(responseBody, track);
        };

        track.tech_.on('vttjsloaded', loadHandler);
        track.tech_.on('vttjserror', function () {
          log$1.error('vttjs failed to load, stopping trying to process ' + track.src);
          track.tech_.off('vttjsloaded', loadHandler);
        });
      }
    } else {
      parseCues(responseBody, track);
    }
  }));
}

Load a `TextTrack` from a specifed url.

@param {string} src
Url to load track from.

@param {TextTrack} track
Track to add cues to. Comes from the content at the end of `url`.

@private


function constructColor(color, opacity) {
  return 'rgba(' +
  // color looks like "#f0e"
  parseInt(color[1] + color[1], 16) + ',' + parseInt(color[2] + color[2], 16) + ',' + parseInt(color[3] + color[3], 16) + ',' + opacity + ')';
}

function
constructColor
(
color
,
opacity
)
{
return
'rgba('
+
// color looks like "#f0e"
parseInt
(
color
[
1
]
+
color
[
1
]
,
16
)
+
','
+
parseInt
(
color
[
2
]
+
color
[
2
]
,
16
)
+
','
+
parseInt
(
color
[
3
]
+
color
[
3
]
,
16
)
+
','
+
opacity
+
')'
;
}

Construct an rgba color from a given hex color code.

@param {number} color
Hex number for color, like #f0e.

@param {number} opacity
Value for opacity, 0.0 - 1.0.

@return {string}
The rgba color that was created, like 'rgba(255, 0, 0, 0.3)'.

@private

Construct an rgba color from a given hex color code .


function checkVolumeSupport(self, player) {
  // hide volume controls when they're not supported by the current tech
  if (player.tech_ && !player.tech_.featuresVolumeControl) {
    self.addClass('vjs-hidden');
  }

  self.on(player, 'loadstart', function () {
    if (!player.tech_.featuresVolumeControl) {
      self.addClass('vjs-hidden');
    } else {
      self.removeClass('vjs-hidden');
    }
  });
}

Check if volume control is supported and if it isn't hide the
`Component` that was passed  using the `vjs-hidden` class.

@param {Component} self
The component that should be hidden if volume is unsupported

@param {Player} player
A reference to the player

@private

Check if volume control is supported and if it isn t hide the Component that was passed using the vjs - hidden class .


function parseOptionValue(value, parser) {
  if (parser) {
    value = parser(value);
  }

  if (value && value !== 'none') {
    return value;
  }
}

function parseOptionValue ( value , parser ) { if ( parser ) { value = parser ( value ) ; } if ( value && value !== 'none' ) { return value ; } }

Get the actual value of an option.

@param  {string} value
The value to get

@param  {Function} [parser]
Optional function to adjust the value.

@return {Mixed}
- Will be `undefined` if no value exists
- Will be `undefined` if the given value is "none".
- Will be the actual value otherwise.

@private


function checkProgress() {
        if (_this3.el_.currentTime > 0) {
          // Trigger durationchange for genuinely live video
          if (_this3.el_.duration === Infinity) {
            _this3.trigger('durationchange');
          }
          _this3.off('timeupdate', checkProgress);
        }
      }

Wait for the first `timeupdate` with currentTime > 0 - there may be several with 0

Wait for the first timeupdate with currentTime > 0 - there may be several with 0


function findFirstPassingTechSourcePair(outerArray, innerArray, tester) {
      var found = void 0;

      outerArray.some(function (outerChoice) {
        return innerArray.some(function (innerChoice) {
          found = tester(outerChoice, innerChoice);

          if (found) {
            return true;
          }
        });
      });

      return found;
    }

function findFirstPassingTechSourcePair ( outerArray , innerArray , tester ) { var found = void 0 ; outerArray . some ( function ( outerChoice ) { return innerArray . some ( function ( innerChoice ) { found = tester ( outerChoice , innerChoice ) ; if ( found ) { return true ; } } ) ; } ) ; return found ; }

Iterate over each `innerArray` element once per `outerArray` element and execute `tester` with both. If `tester` returns a non-falsy value, exit early and return that value.

Iterate over each innerArray element once per outerArray element and execute tester with both . If tester returns a non - falsy value exit early and return that value .


function markPluginAsActive(player, name) {
  player[PLUGIN_CACHE_KEY] = player[PLUGIN_CACHE_KEY] || {};
  player[PLUGIN_CACHE_KEY][name] = true;
}

function markPluginAsActive ( player , name ) { player [ PLUGIN_CACHE_KEY ] = player [ PLUGIN_CACHE_KEY ] || { } ; player [ PLUGIN_CACHE_KEY ] [ name ] = true ; }

Marks a plugin as "active" on a player.

Also, ensures that the player has an object for tracking active plugins.

@private
@param   {Player} player
A Video.js player instance.

@param   {string} name
The name of a plugin.


function triggerSetupEvent(player, hash, before) {
  var eventName = (before ? 'before' : '') + 'pluginsetup';

  player.trigger(eventName, hash);
  player.trigger(eventName + ':' + hash.name, hash);
}

function triggerSetupEvent ( player , hash , before ) { var eventName = ( before ? 'before' : '' ) + 'pluginsetup' ; player . trigger ( eventName , hash ) ; player . trigger ( eventName + ':' + hash . name , hash ) ; }

Triggers a pair of plugin setup events.

@private
@param  {Player} player
A Video.js player instance.

@param  {Plugin~PluginEventHash} hash
A plugin event hash.

@param  {Boolean} [before]
If true, prefixes the event name with "before". In other words,
use this to trigger "beforepluginsetup" instead of "pluginsetup".

Triggers a pair of plugin setup events .


function createBasicPlugin(name, plugin) {
  var basicPluginWrapper = function basicPluginWrapper() {

    // We trigger the "beforepluginsetup" and "pluginsetup" events on the player
    // regardless, but we want the hash to be consistent with the hash provided
    // for advanced plugins.
    //
    // The only potentially counter-intuitive thing here is the `instance` in
    // the "pluginsetup" event is the value returned by the `plugin` function.
    triggerSetupEvent(this, { name: name, plugin: plugin, instance: null }, true);

    var instance = plugin.apply(this, arguments);

    markPluginAsActive(this, name);
    triggerSetupEvent(this, { name: name, plugin: plugin, instance: instance });

    return instance;
  };

  Object.keys(plugin).forEach(function (prop) {
    basicPluginWrapper[prop] = plugin[prop];
  });

  return basicPluginWrapper;
}

Takes a basic plugin function and returns a wrapper function which marks
on the player that the plugin has been activated.

@private
@param   {string} name
The name of the plugin.

@param   {Function} plugin
The basic plugin.

@returns {Function}
A wrapper function for the given plugin.

Takes a basic plugin function and returns a wrapper function which marks on the player that the plugin has been activated .


function createPluginFactory(name, PluginSubClass) {

  // Add a `name` property to the plugin prototype so that each plugin can
  // refer to itself by name.
  PluginSubClass.prototype.name = name;

  return function () {
    triggerSetupEvent(this, { name: name, plugin: PluginSubClass, instance: null }, true);

    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    var instance = new (Function.prototype.bind.apply(PluginSubClass, [null].concat([this].concat(args))))();

    // The plugin is replaced by a function that returns the current instance.
    this[name] = function () {
      return instance;
    };

    triggerSetupEvent(this, instance.getEventHash());

    return instance;
  };
}

Takes a plugin sub-class and returns a factory function for generating
instances of it.

This factory function will replace itself with an instance of the requested
sub-class of Plugin.

@private
@param   {string} name
The name of the plugin.

@param   {Plugin} PluginSubClass
The advanced plugin.

@returns {Function}

Takes a plugin sub - class and returns a factory function for generating instances of it .


function videojs(id, options, ready) {
  var tag = void 0;

  // Allow for element or ID to be passed in
  // String ID
  if (typeof id === 'string') {
    var players = videojs.getPlayers();

    // Adjust for jQuery ID syntax
    if (id.indexOf('#') === 0) {
      id = id.slice(1);
    }

    // If a player instance has already been created for this ID return it.
    if (players[id]) {

      // If options or ready function are passed, warn
      if (options) {
        log$1.warn('Player "' + id + '" is already initialised. Options will not be applied.');
      }

      if (ready) {
        players[id].ready(ready);
      }

      return players[id];
    }

    // Otherwise get element for ID
    tag = $('#' + id);

    // ID is a media element
  } else {
    tag = id;
  }

  // Check for a useable element
  // re: nodeName, could be a box div also
  if (!tag || !tag.nodeName) {
    throw new TypeError('The element or ID supplied is not valid. (videojs)');
  }

  // Element may have a player attr referring to an already created player instance.
  // If so return that otherwise set up a new player below
  if (tag.player || Player.players[tag.playerId]) {
    return tag.player || Player.players[tag.playerId];
  }

  options = options || {};

  videojs.hooks('beforesetup').forEach(function (hookFunction) {
    var opts = hookFunction(tag, mergeOptions(options));

    if (!isObject(opts) || Array.isArray(opts)) {
      log$1.error('please return an object in beforesetup hooks');
      return;
    }

    options = mergeOptions(options, opts);
  });

  var PlayerComponent = Component.getComponent('Player');
  // If not, set up a new player
  var player = new PlayerComponent(tag, options, ready);

  videojs.hooks('setup').forEach(function (hookFunction) {
    return hookFunction(player);
  });

  return player;
}

Doubles as the main function for users to create a player instance and also
the main library object.
The `videojs` function can be used to initialize or retrieve a player.

@param {string|Element} id
Video element or video element ID

@param {Object} [options]
Optional options object for config/settings

@param {Component~ReadyCallback} [ready]
Optional ready callback

@return {Player}
A player instance

Doubles as the main function for users to create a player instance and also the main library object . The videojs function can be used to initialize or retrieve a player .


function byteCount(testName, len, baseLen) {
  console.log(testName + " Byte Count: " + len + (baseLen ? ', ' + Math.round(len / baseLen * 100) + '%' : ''));
}

function
byteCount
(
testName
,
len
,
baseLen
)
{
console
.
log
(
testName
+
" Byte Count: "
+
len
+
(
baseLen
', '
+
Math
.
round
(
len
/
baseLen
*
100
)
+
'%'
:
''
)
)
;
}

Comment out if you didn't `npm install lz-string`

Comment out if you didn t npm install lz - string


function() {
		var colors = []
		var trs = _$sortableDataList.find("li");
		for (var i=0; i<trs.length; i++) {
			colors.push(utils.rgb2hex($(trs[i]).find(".segmentColor").css("background-color")));
		}
		colors = utils.shuffleArray(colors);
		_setColors(colors);
	}

function ( ) { var colors = [ ] var trs = _$sortableDataList . find ( "li" ) ; for ( var i = 0 ; i < trs . length ; i ++ ) { colors . push ( utils . rgb2hex ( $ ( trs [ i ] ) . find ( ".segmentColor" ) . css ( "background-color" ) ) ) ; } colors = utils . shuffleArray ( colors ) ; _setColors ( colors ) ; }

Randomizes whatever colors are currently being used.
@private

Randomizes whatever colors are currently being used .


function(moduleID, message, data) {
		if (C.DEBUG) {
			console.log("[" + moduleID + "] publish(): ", message, data);
		}

		for (var i in _modules) {
			var subscriptions = _modules[i].subscriptions;

			// if this module has subscribed to this event, call the callback function
			if (subscriptions.hasOwnProperty(message)) {
				subscriptions[message]({
					sender: moduleID,
					data: data
				});
			}
		}
	}

Publishes a message to anyone who's subscribed to it.
@param moduleID
@param message
@param data
@private

Publishes a message to anyone who s subscribed to it .


function() {
		$(document).on("click", ".selectPage", function(e) {
			e.preventDefault();
			_selectPage(this.hash);
		});

		$(window).on("resize", function() {
			var width = $(window).width();
			var height = $(window).height();
			var breakPoint = _updateBodySizeClass(width);
			mediator.publish(_MODULE_ID, C.EVENT.PAGE.RESIZE, {
				width: width,
				height: height,
				breakPoint: breakPoint
			});
		});
	}

function ( ) { $ ( document ) . on ( "click" , ".selectPage" , function ( e ) { e . preventDefault ( ) ; _selectPage ( this . hash ) ; } ) ; $ ( window ) . on ( "resize" , function ( ) { var width = $ ( window ) . width ( ) ; var height = $ ( window ) . height ( ) ; var breakPoint = _updateBodySizeClass ( width ) ; mediator . publish ( _MODULE_ID , C . EVENT . PAGE . RESIZE , { width : width , height : height , breakPoint : breakPoint } ) ; } ) ; }

this catches ALL nav clicks, not just in the main navbar

this catches ALL nav clicks not just in the main navbar


function(width) {
		var breakPointIndex = null;
		for (var i=0; i< C.OTHER.BREAKPOINTS.length; i++) {
			if (width >= C.OTHER.BREAKPOINTS[i]) {
				breakPointIndex = i;
			}
		}

		$("body").removeClass("size768 size992 size1200");
		var breakPoint = null;
		if (breakPointIndex !== null) {
			breakPoint = C.OTHER.BREAKPOINTS[breakPointIndex];
			$("body").addClass("size" + breakPoint);
		}
		return breakPoint;
	}

function
(
width
)
{
var
breakPointIndex
=
;
for
(
var
i
=
0
;
i
<
C
.
OTHER
.
BREAKPOINTS
.
length
;
i
++
)
{
if
(
width
>=
C
.
OTHER
.
BREAKPOINTS
[
i
]
)
{
breakPointIndex
=
i
;
}
}
$
(
"body"
)
.
removeClass
(
"size768 size992 size1200"
)
;
var
breakPoint
=
;
if
(
breakPointIndex
!==
)
{
breakPoint
=
C
.
OTHER
.
BREAKPOINTS
[
breakPointIndex
]
;
$
(
"body"
)
.
addClass
(
"size"
+
breakPoint
)
;
}
return
breakPoint
;
}

This was added to get around some CSS nonsense with the homepage slider script. It adds a class to the body
element that specifies the current viewport width.
@private

This was added to get around some CSS nonsense with the homepage slider script . It adds a class to the body element that specifies the current viewport width .


function() {
			var hb = new base.HandlebarsEnvironment();

			Utils.extend(hb, base);
			hb.SafeString = SafeString;
			hb.Exception = Exception;
			hb.Utils = Utils;

			hb.VM = runtime;
			hb.template = function(spec) {
				return runtime.template(spec, hb);
			};

			return hb;
		}

function ( ) { var hb = new base . HandlebarsEnvironment ( ) ; Utils . extend ( hb , base ) ; hb . SafeString = SafeString ; hb . Exception = Exception ; hb . Utils = Utils ; hb . VM = runtime ; hb . template = function ( spec ) { return runtime . template ( spec , hb ) ; } ; return hb ; }

For compatibility and usage outside of module systems, make the Handlebars object a namespace

For compatibility and usage outside of module systems make the Handlebars object a namespace


function(paramSize, params, useRegister) {
				var options = '{' + this.setupOptions(paramSize, params).join(',') + '}';

				if (useRegister) {
					this.useRegister('options');
					params.push('options');
					return 'options=' + options;
				} else {
					params.push(options);
					return '';
				}
			}

function ( paramSize , params , useRegister ) { var options = '{' + this . setupOptions ( paramSize , params ) . join ( ',' ) + '}' ; if ( useRegister ) { this . useRegister ( 'options' ) ; params . push ( 'options' ) ; return 'options=' + options ; } else { params . push ( options ) ; return '' ; } }

the params and contexts arguments are passed in arrays to fill in


function(msg) {
		_canvasWidth = msg.data.config.size.canvasWidth;
		_canvasHeight = msg.data.config.size.canvasHeight;
	}

function ( msg ) { _canvasWidth = msg . data . config . size . canvasWidth ; _canvasHeight = msg . data . config . size . canvasHeight ; }

Listen for data changes so we can keep track of the current canvas size.
@param msg
@private

Listen for data changes so we can keep track of the current canvas size .


function(number) {
					switch (number) {
						case 1:
							_demoPie2.redraw();
							_demoPie3.redraw();
							break;
						case 2:
							_demoPie1.redraw();
							_demoPie3.redraw();
							break;
						case 3:
							_demoPie1.redraw();
							_demoPie2.redraw();
							break;
					}
				}

function ( number ) { switch ( number ) { case 1 : _demoPie2 . redraw ( ) ; _demoPie3 . redraw ( ) ; break ; case 2 : _demoPie1 . redraw ( ) ; _demoPie3 . redraw ( ) ; break ; case 3 : _demoPie1 . redraw ( ) ; _demoPie2 . redraw ( ) ; break ; } }

bah! God this plugin sucks. Doesn't even pass in the slide number we're going TO.

bah! God this plugin sucks . Doesn t even pass in the slide number we re going TO .


function() {
		config.template.indexFile.options.data.C = _CONSTANTS.DEV;
		config.template.indexFile.options.data.D3PIE_VERSION = packageFile.version;
		config.template.devRequireConfig.options.data.handlebarsLib = _CONSTANTS.DEV.HANDLEBARS_LIB;
		config.template.devRequireConfig.options.data.baseUrl = _CONSTANTS.DEV.BASE_URL;
		var lines = [];
		for (var i in _requireJSModulePaths) {
			var file = _requireJSModulePaths[i].replace(/\.js$/, "");
			lines.push('\t\t"' + i + '": "' + file + '"');
		}
		config.template.devRequireConfig.options.data.moduleStr = lines.join(",\n");
		config.template.constants.options.data.VERSION = packageFile.version;
		config.template.constants.options.data.MINIMIZED = _CONSTANTS.DEV.MINIMIZED;
		config.template.constants.options.data.DEBUG = _CONSTANTS.DEV.DEBUG;
	}

function
(
)
{
config
.
template
.
indexFile
.
options
.
data
.
C
=
_CONSTANTS
.
DEV
;
config
.
template
.
indexFile
.
options
.
data
.
D3PIE_VERSION
=
packageFile
.
version
;
config
.
template
.
devRequireConfig
.
options
.
data
.
handlebarsLib
=
_CONSTANTS
.
DEV
.
HANDLEBARS_LIB
;
config
.
template
.
devRequireConfig
.
options
.
data
.
baseUrl
=
_CONSTANTS
.
DEV
.
BASE_URL
;
var
lines
=
[
]
;
for
(
var
i
in
_requireJSModulePaths
)
{
var
file
=
_requireJSModulePaths
[
i
]
.
replace
(
/
\.js$
/
,
""
)
;
lines
.
push
(
'\t\t"'
+
i
+
'": "'
+
file
+
'"'
)
;
}
config
.
template
.
devRequireConfig
.
options
.
data
.
moduleStr
=
lines
.
join
(
",\n"
)
;
config
.
template
.
constants
.
options
.
data
.
VERSION
=
packageFile
.
version
;
config
.
template
.
constants
.
options
.
data
.
MINIMIZED
=
_CONSTANTS
.
DEV
.
MINIMIZED
;
config
.
template
.
constants
.
options
.
data
.
DEBUG
=
_CONSTANTS
.
DEV
.
DEBUG
;
}

The first step of the build process. This sets various settings in the main grunt config for the current build environment.
These govern how the subsequent tasks behave.

The first step of the build process . This sets various settings in the main grunt config for the current build environment . These govern how the subsequent tasks behave .


function() {
		return {
			header:    titleTab.getTabData(),
			footer:    footerTab.getTabData(),
			size:      sizeTab.getTabData(),
			data:      dataTab.getTabData(),
			labels:    labelsTab.getTabData(),
			tooltips:  tooltipsTab.getTabData(),
			effects:   effectsTab.getTabData(),
			callbacks: eventsTab.getTabData(),
			misc:      miscTab.getTabData()
		};
	}

function ( ) { return { header : titleTab . getTabData ( ) , footer : footerTab . getTabData ( ) , size : sizeTab . getTabData ( ) , data : dataTab . getTabData ( ) , labels : labelsTab . getTabData ( ) , tooltips : tooltipsTab . getTabData ( ) , effects : effectsTab . getTabData ( ) , callbacks : eventsTab . getTabData ( ) , misc : miscTab . getTabData ( ) } ; }

Parses the generator fields and get the latest values.
@private

Parses the generator fields and get the latest values .


function getOrDef(obj, prop) {
        return obj[prop] === undefined ? options[prop] : obj[prop];
    }

function getOrDef ( obj , prop ) { return obj [ prop ] === undefined ? options [ prop ] : obj [ prop ] ; }

Return options.prop if obj.prop is undefined, otherwise return obj.prop
@param {*} obj
@param {*} prop
@returns *

Return options . prop if obj . prop is undefined otherwise return obj . prop


function calcViewport() {
        var scrollTop = $window.scrollTop(),
            scrollLeft = window.pageXOffset || 0,
            edgeX = options.edgeX,
            edgeY = options.edgeY;

        viewportTop = scrollTop - edgeY;
        viewportBottom = scrollTop + (window.innerHeight || $window.height()) + edgeY;
        viewportLeft = scrollLeft - edgeX;
        viewportRight = scrollLeft + (window.innerWidth || $window.width()) + edgeX;
    }

function calcViewport ( ) { var scrollTop = $window . scrollTop ( ) , scrollLeft = window . pageXOffset || 0 , edgeX = options . edgeX , edgeY = options . edgeY ; viewportTop = scrollTop - edgeY ; viewportBottom = scrollTop + ( window . innerHeight || $window . height ( ) ) + edgeY ; viewportLeft = scrollLeft - edgeX ; viewportRight = scrollLeft + ( window . innerWidth || $window . width ( ) ) + edgeX ; }

Save visible viewport boundary to viewportXXX variables


function checkVersion() {
		var nextVersionCheckTimestamp = parseInt(Cookies.get('nextVersionCheckTimestamp')) || 0;

		if (!nextVersionCheckTimestamp || (Date.now() >= nextVersionCheckTimestamp)) {
			$http.get('/api/build-info')
				.then(function success(res) {
					var currentVersion = parseVersion(res.data && res.data.version);

					$http.get('https://api.github.com/repos/mcdcorp/opentest/releases')
						.then(
							function success(res) {
								var eightDaysLater = Date.now() + (8 * 24 * 60 * 60 * 1000);
								Cookies.set('nextVersionCheckTimestamp', eightDaysLater);

								var latestVersionStr = res.data && res.data[0] && res.data[0].tag_name;
								var latestVersionUrl = res.data && res.data[0] && res.data[0].html_url;
								var latestVersion = parseVersion(latestVersionStr);
								if (latestVersion && (compareVersions(latestVersion, currentVersion) === 1)) {
									$.notify(
										{
											message:
												'A new OpenTest version is now available: ' + latestVersionStr + '. ' +
												'You should always stay on the latest version to benefit from new features and security updates.'
										}, {
											type: 'info',
											delay: 0,
											placement: { from: 'bottom' }
										})
								}
							},
							function error(res) {
								var oneHourLater = Date.now() + (60 * 60 * 1000);
								Cookies.set('nextVersionCheckTimestamp', oneHourLater);
							});
				});
		}
	}

'A new OpenTest version is now available: <a href="'

Check the release version in GitHub, compare it with the installed
version and notify the user if a new version is available.

Check the release version in GitHub compare it with the installed version and notify the user if a new version is available .


function parseVersion(versionString) {
		if (typeof versionString !== 'string') {
			return null;
		}

		var versionRegexMatch = versionString.match(/v?(\d+)\.(\d+)\.(\d+)/i);
		if (versionRegexMatch) {
			return [parseInt(versionRegexMatch[1]), parseInt(versionRegexMatch[2]), parseInt(versionRegexMatch[3])];
		} else {
			return null;
		}
	}

function parseVersion ( versionString ) { if ( typeof versionString !== 'string' ) { return null ; } var versionRegexMatch = versionString . match ( / v?(\d+)\.(\d+)\.(\d+) / i ) ; if ( versionRegexMatch ) { return [ parseInt ( versionRegexMatch [ 1 ] ) , parseInt ( versionRegexMatch [ 2 ] ) , parseInt ( versionRegexMatch [ 3 ] ) ] ; } else { return null ; } }

Parses a semantic version string into an array of three integers.

Parses a semantic version string into an array of three integers .


function cellAccessor(row1, col1, row2, col2, isMerged) {
    let theseCells = new cellBlock();
    theseCells.ws = this;

    row2 = row2 ? row2 : row1;
    col2 = col2 ? col2 : col1;

    if (row2 > this.lastUsedRow) {
        this.lastUsedRow = row2;
    }

    if (col2 > this.lastUsedCol) {
        this.lastUsedCol = col2;
    }

    for (let r = row1; r <= row2; r++) {
        for (let c = col1; c <= col2; c++) {
            let ref = `${utils.getExcelAlpha(c)}${r}`;
            if (!this.cells[ref]) {
                this.cells[ref] = new Cell(r, c);
            }
            if (!this.rows[r]) {
                this.rows[r] = new Row(r, this);
            }
            if (this.rows[r].cellRefs.indexOf(ref) < 0) {
                this.rows[r].cellRefs.push(ref);
            }

            theseCells.cells.push(this.cells[ref]);
            theseCells.excelRefs.push(ref);
        }
    }
    if (isMerged) {
        theseCells.merged = true;
        mergeCells(theseCells);
    }

    return theseCells;
}

function cellAccessor ( row1 , col1 , row2 , col2 , isMerged ) { let theseCells = new cellBlock ( ) ; theseCells . ws = this ; row2 = row2 ? row2 : row1 ; col2 = col2 ? col2 : col1 ; if ( row2 > this . lastUsedRow ) { this . lastUsedRow = row2 ; } if ( col2 > this . lastUsedCol ) { this . lastUsedCol = col2 ; } for ( let r = row1 ; r <= row2 ; r ++ ) { for ( let c = col1 ; c <= col2 ; c ++ ) { let ref = ` ${ utils . getExcelAlpha ( c ) } ${ r } ` ; if ( ! this . cells [ ref ] ) { this . cells [ ref ] = new Cell ( r , c ) ; } if ( ! this . rows [ r ] ) { this . rows [ r ] = new Row ( r , this ) ; } if ( this . rows [ r ] . cellRefs . indexOf ( ref ) < 0 ) { this . rows [ r ] . cellRefs . push ( ref ) ; } theseCells . cells . push ( this . cells [ ref ] ) ; theseCells . excelRefs . push ( ref ) ; } } if ( isMerged ) { theseCells . merged = true ; mergeCells ( theseCells ) ; } return theseCells ; }

Module repesenting a Cell Accessor
@alias Worksheet.cell
@namespace
@func Worksheet.cell
@desc Access a range of cells in order to manipulate values
@param {Number} row1 Row of top left cell
@param {Number} col1 Column of top left cell
@param {Number} row2 Row of bottom right cell (optional)
@param {Number} col2 Column of bottom right cell (optional)
@param {Boolean} isMerged Merged the cell range into a single cell
@returns {cellBlock}


function allProjects(done) {
  User.find({}, function (err, users) {
    if (err) return done(err);

    Project.find()
      .sort({_id: -1})
      .exec(function (err, projects) {
        if (err) return done(err);
        done(null, projects.map(function (project) {
          project = utils.sanitizeProject(project);
          project.created_date = utils.timeFromId(project._id);
          project.users = [];
          for (var i = 0; i < users.length; i++) {
            if ('undefined' !== typeof users[i].projects[project.name]) {
              project.users.push({
                email: users[i].email,
                access: users[i].projects[project.name]
              });
            }
          }
          return project;
        }));
      });
  });
}

function allProjects ( done ) { User . find ( { } , function ( err , users ) { if ( err ) return done ( err ) ; Project . find ( ) . sort ( { _id : - 1 } ) . exec ( function ( err , projects ) { if ( err ) return done ( err ) ; done ( null , projects . map ( function ( project ) { project = utils . sanitizeProject ( project ) ; project . created_date = utils . timeFromId ( project . _id ) ; project . users = [ ] ; for ( var i = 0 ; i < users . length ; i ++ ) { if ( 'undefined' !== typeof users [ i ] . projects [ project . name ] ) { project . users . push ( { email : users [ i ] . email , access : users [ i ] . projects [ project . name ] } ) ; } } return project ; } ) ) ; } ) ; } ) ; }

Get a sanitized listing of all projects, along with the users who have access

Get a sanitized listing of all projects along with the users who have access


function getConfig() {
  process.env = filterEnv(deprecated(process.env), envDefaults);
  var rc = require('rc')('strider', defaults);

  if (!rc.smtp) rc.smtp = smtp(rc);
  if (!rc.smtp) rc.stubSmtp = true;

  rc.ldap = getConfigByName('ldap');

  addPlugins(rc, process.env);

  // BACK COMPAT until we get strider config into plugins...
  if (hasGithub) {
    rc.plugins.github = rc.plugins.github || {};
    rc.plugins.github.hostname = rc.server_name;
  }

  debug(rc);

  return rc;
}


function filterEnv(env, defaults) {
  var res = {};
  for (var k in env) {
    if (defaults[k.toLowerCase()] !== undefined) {
      res[`strider_${k.toLowerCase()}`] = env[k];
    } else {
      res[k] = env[k];
    }
  }
  return res;
}

function filterEnv ( env , defaults ) { var res = { } ; for ( var k in env ) { if ( defaults [ k . toLowerCase ( ) ] !== undefined ) { res [ ` ${ k . toLowerCase ( ) } ` ] = env [ k ] ; } else { res [ k ] = env [ k ] ; } } return res ; }

Filter process.env.FOO to process.env.strider_foo for rc's benefit

Filter process . env . FOO to process . env . strider_foo for rc s benefit


function mergePlugins(branch, sjson) {
  if (!branch) return sjson;
  if (!sjson) return branch;
  // if strict_plugins is not turned on, we merge each plugin config instead of overwriting.
  var plugins = [];
  var pluginMap = {};

  for (var pluginIndex = 0; pluginIndex < sjson.length; pluginIndex++) {
    plugins.push(sjson[pluginIndex]);
    pluginMap[sjson[pluginIndex].id] = true;
  }
  for (var branchIndex = 0; branchIndex < branch.length; branchIndex++) {
    if (!pluginMap[branch[branchIndex].id]) plugins.push(branch[branchIndex]);
  }
  return plugins;
}

merge plugins from the DB with ones from strider.json. The latter overrides the former

merge plugins from the DB with ones from strider . json . The latter overrides the former


function registerTemplate(name, template, dir) {
  cache[name] = function (context, cb) {
    if (/\.html$/.test(template)){
      dir = dir || '.';
      template = fs.readFileSync(path.join(dir, template), 'utf8');
    }

    cb(null, template);
  };
}

function registerTemplate ( name , template , dir ) { cache [ name ] = function ( context , cb ) { if ( / \.html$ / . test ( template ) ) { dir = dir || '.' ; template = fs . readFileSync ( path . join ( dir , template ) , 'utf8' ) ; } cb ( null , template ) ; } ; }


function getPluginTemplate(name, context) {
  return function (cb) {
    if (cache[name]){
      cache[name](context, function (err, res) {
        if (err) return cb(err);
        cb(null, [name, res]);
      });
    } else {
      cb(null, null);
    }
  };
}

function getPluginTemplate ( name , context ) { return function ( cb ) { if ( cache [ name ] ) { cache [ name ] ( context , function ( err , res ) { if ( err ) return cb ( err ) ; cb ( null , [ name , res ] ) ; } ) ; } else { cb ( null , null ) ; } } ; }

This generates a generator that will render the appropriate block in a form suitable for async.parallel.

This generates a generator that will render the appropriate block in a form suitable for async . parallel .


function engine(path, options, fn) {
  options.filename = path;

  fs.readFile(path, 'utf8', function (err, str) {
    if (err) return fn(err);
    engine.render(str, options, fn);
  });
}

function engine ( path , options , fn ) { options . filename = path ; fs . readFile ( path , 'utf8' , function ( err , str ) { if ( err ) return fn ( err ) ; engine . render ( str , options , fn ) ; } ) ; }


function (uid, socket) {
    var socks = this.sockets[uid];
    if (!socks) return false;
    return socks.remove(socket);
  }

function ( uid , socket ) { var socks = this . sockets [ uid ] ; if ( ! socks ) return false ; return socks . remove ( socket ) ; }

-> true if the socket was found and removed. false if it wasn't found

- > true if the socket was found and removed . false if it wasn t found


function (socket) {
    var session = socket.handshake.session;

    if (session && session.passport) {
      this.addSocket(session.passport.user, socket);
    } else {
      console.debug('Websocket connection does not have authorization - nothing to do.');
    }
  }


function status(job) {
  if (job.errored) return 'errored';
  if (!job.started) return 'submitted';
  if (!job.finished) return 'running';
  if (job.test_exitcode !== 0) return 'failed';
  if (job.type !== TEST_ONLY && job.deploy_exitcode !== 0) return 'failed';
  return 'passed';
}

function status ( job ) { if ( job . errored ) return 'errored' ; if ( ! job . started ) return 'submitted' ; if ( ! job . finished ) return 'running' ; if ( job . test_exitcode !== 0 ) return 'failed' ; if ( job . type !== TEST_ONLY && job . deploy_exitcode !== 0 ) return 'failed' ; return 'passed' ; }

failed, passed, errored, running, submitted


function prepareJob(emitter, job) {
  Project.findOne({ name: job.project }).populate('creator').exec(function (err, project) {
    if (err || !project) return debug('job.prepare - failed to get project', job.project, err);
    // ok so the project is real, we can go ahead and save this job
    var provider = common.extensions.provider[project.provider.id];

    if (!provider) {
      return debug('job.prepare - provider not found for project', job.project, project.provider.id);
    }

    Job.create(job, function (err, mjob) {
      if (err) return debug('job.prepare - failed to save job', job, err);

      var jjob = mjob.toJSON();

      jjob.project = project;
      jjob.providerConfig = project.provider.config;
      jjob.fromStriderJson = true;

      striderJson(provider, project, job.ref, function (err, config) {
        if (err) {
          if (err.status === 403 || err.statusCode === 403) {
            debug('job.prepare - access to strider.json is forbidden, skipping config merge');
            config = {};
            jjob.fromStriderJson = false;
          } else if (err.status === 404 || err.statusCode === 404) {
            debug('job.prepare - strider.json not found, skipping config merge');
            config = {};
            jjob.fromStriderJson = false;
          } else {
            debug('job.prepare - error opening/processing project\'s `strider.json` file: ', err);
            config = {};
            jjob.fromStriderJson = false;
          }
        } else {
          debug('Using configuration from "strider.json".');
        }

        var branch = project.branch(job.ref.branch || 'master');

        if (!branch) {
          return debug('job.prepare - branch not found', job.ref.branch || 'master', project.name);
        }

        branch = branch.mirror_master ? project.branch('master') : branch;
        jjob.providerConfig = _.extend({}, project.provider.config, config.provider || {});
        config.runner = config.runner || branch.runner;

        if (!common.extensions.runner[config.runner.id]) {
          debug(`Error: A job was registered for a runner that doesn't exist, i.e. "${config.runner.id}". This job will never run!`);
        }

        if (config) {
          delete config.provider;
          config = utils.mergeConfigs(branch, config);
        }

        emitter.emit('job.new', jjob, config);

        if (!mjob.runner) mjob.runner = {};

        mjob.runner.id = config.runner.id;
        mjob.save()
          .then(() => debug('job saved'))
          .catch(e => debug(e));
      });
    });
  });
}

Prepare the job for execution, save to database, and fire off a `job.new` event.

job is expected to be populated with:
- a trigger
- a ref
- the project name
- the user id (if applicable)
- type
- created timestamp

XXX: should this function go in a different file? idk. We'll
definitely move it around when we make strider OO.

Prepare the job for execution save to database and fire off a job . new event .


function killAttrs(model, attrs) {
  for (var i = 0; i < attrs.length; i++) {
    delete model[attrs[i]];
  }
}

function killAttrs ( model , attrs ) { for ( var i = 0 ; i < attrs . length ; i ++ ) { delete model [ attrs [ i ] ] ; } }


function bodySetter(req, res, next) {
  if (req._post_body) {
    return next();
  }

  req.post_body = req.post_body || '';

  if ('POST' !== req.method) {
    return next();
  }

  req._post_body = true;

  req.on('data', function (chunk) {
    req.post_body += chunk;
  });

  next();
}

function bodySetter ( req , res , next ) { if ( req . _post_body ) { return next ( ) ; } req . post_body = req . post_body || '' ; if ( 'POST' !== req . method ) { return next ( ) ; } req . _post_body = true ; req . on ( 'data' , function ( chunk ) { req . post_body += chunk ; } ) ; next ( ) ; }

Custom middleware to save unparsed request body to req.content

Custom middleware to save unparsed request body to req . content


function requireBody(paramsList) {
  return function (req, res, next) {
    var errors = [];
    var status = 'ok';

    for (var i = 0; i < paramsList.length; i++) {
      var val = req.body[paramsList[i]];

      if (!val) {
        errors.push(`required parameter \`${paramsList[i]}\` not found.`);
        status = 'error';
      }
    }

    if (errors.length === 0) {
      next();
    } else {
      return res.status(400).json({
        errors: errors,
        status: status
      });
    }
  };
}

function requireBody ( paramsList ) { return function ( req , res , next ) { var errors = [ ] ; var status = 'ok' ; for ( var i = 0 ; i < paramsList . length ; i ++ ) { var val = req . body [ paramsList [ i ] ] ; if ( ! val ) { errors . push ( ` \` ${ paramsList [ i ] } \` ` ) ; status = 'error' ; } } if ( errors . length === 0 ) { next ( ) ; } else { return res . status ( 400 ) . json ( { errors : errors , status : status } ) ; } } ; }

Require the specified req.body parameters, or else return a 400 with a descriptive JSON body

Require the specified req . body parameters or else return a 400 with a descriptive JSON body


function anonProject(req, res, next) {
  var name = `${req.params.org}/${req.params.repo}`;

  name = name.toLowerCase();

  Project.findOne({name: name})
    .populate('creator')
    .exec(function (err, project) {
      if (err) {
        return res.status(500).send({
          error: 'Failed to find project',
          info: err
        });
      }

      if (!project) {
        return res.status(404).send('Project not found');
      }

      if (!project.creator) {
        return res.status(400).send('Project malformed; project creator user is missing.');
      }

      req.project = project;
      req.accessLevel = User.projectAccessLevel(req.user, project);

      if (req.user && project.creator) {
        req.user.isProjectCreator = project.creator._id.toString() === req.user._id.toString();
      }

      next();
    });
}

just link project but doesn't fail if there's no auth

just link project but doesn t fail if there s no auth


function requireUser(req, res, next) {
  if (req.user) {
    next();
  } else {
    req.session.return_to = req.url;
    res.redirect('/login');
  }
}

function requireUser ( req , res , next ) { if ( req . user ) { next ( ) ; } else { req . session . return_to = req . url ; res . redirect ( '/login' ) ; } }


function requireAdminOr401(req, res, next) {
  if (!req.user || !req.user['account_level'] || req.user.account_level < 1) {
    res.status(401).send('not authorized');
  } else {
    next();
  }
}

function
requireAdminOr401
(
req
,
res
,
next
)
{
if
(
!
req
.
user
||
!
req
.
user
[
'account_level'
]
||
req
.
user
.
account_level
<
1
)
{
res
.
status
(
401
)
.
send
(
'not authorized'
)
;
}
else
{
next
(
)
;
}
}


function pluginBlock(indent, parser) {
  var template = this.args[0];
  var output = '';

  // Register that the template is needed, for 1st pass;
  output += `_context._striderRegister.push('${template}');\n`;

  // Generate code to see if pluginTemplates has block
  output += `var _pg = _context._striderBlocks['${template}'];\n`;
  output += 'if (_pg){ ';
  output += '_output += _pg;';
  output += '} else {\n';
  output += parser.compile.call(this, `${indent} `);
  output += '}\n';

  return output;
}

Plugin block is the tag used to specify that the contents can be overridden by extensions.

Plugin block is the tag used to specify that the contents can be overridden by extensions .


function _findNested (d) {
  let nested = [];
  walk.walkSync(d, (basedir, filename, stat) => {
    const file = path.join(basedir, filename);
    if (file.indexOf('.app/Info.plist') !== -1) {
      const nest = file.lastIndexOf('.app/');
      nested.push(file.substring(0, nest + 4));
    }
  });
  return nested;
}

function _findNested ( d ) { let nested = [ ] ; walk . walkSync ( d , ( basedir , filename , stat ) => { const file = path . join ( basedir , filename ) ; if ( file . indexOf ( '.app/Info.plist' ) !== - 1 ) { const nest = file . lastIndexOf ( '.app/' ) ; nested . push ( file . substring ( 0 , nest + 4 ) ) ; } } ) ; return nested ; }

return an array of strings with the absolute paths of the sub-apps found inside appdir

return an array of strings with the absolute paths of the sub - apps found inside appdir


function binAbsLibs (file, o) {
  try {
    return bin.enumerateLibraries(file)
      .filter((l) => {
        return !(l.startsWith('/'));
      })
      .map((l) => {
        if (l[0] === '@') {
          const ll = depSolver.resolvePath(o.exe, file, l, o.libs);
          if (ll) {
            l = ll;
          } else {
            console.error('Warning: Cannot resolve dependency library: ' + file);
          }
        }
        return l;
      });
  } catch (e) {
    console.error('Warning: missing file:', file);
    return [];
  }
}

return a list of the libs that must be inside the app


function _findLibraries (appdir, appbin, disklibs) {
  const exe = path.join(appdir, appbin);

  const o = {
    exe: exe,
    lib: exe,
    libs: disklibs
  };
  const libraries = [];
  const pending = [exe];
  while (pending.length > 0) {
    const target = pending.pop();
    if (libraries.indexOf(target) === -1) {
      libraries.push(target);
    }
    let res = binAbsLibs(target, o);
    const unexplored = res.filter(l => libraries.indexOf(l) === -1);
    pending.push(...unexplored.filter(l => pending.indexOf(l) === -1));
    libraries.push(...unexplored);
  }
  return libraries;
}

function _findLibraries ( appdir , appbin , disklibs ) { const exe = path . join ( appdir , appbin ) ; const o = { exe : exe , lib : exe , libs : disklibs } ; const libraries = [ ] ; const pending = [ exe ] ; while ( pending . length > 0 ) { const target = pending . pop ( ) ; if ( libraries . indexOf ( target ) === - 1 ) { libraries . push ( target ) ; } let res = binAbsLibs ( target , o ) ; const unexplored = res . filter ( l => libraries . indexOf ( l ) === - 1 ) ; pending . push ( ... unexplored . filter ( l => pending . indexOf ( l ) === - 1 ) ) ; libraries . push ( ... unexplored ) ; } return libraries ; }

get all dependencies from appbin recursively


function fix (file, options, emit) {
  const { appdir, bundleid, forceFamily, allowHttp } = options;
  if (!file || !appdir) {
    throw new Error('Invalid parameters for fixPlist');
  }
  let changed = false;
  const data = plist.readFileSync(file);
  delete data[''];
  if (allowHttp) {
    emit('message', 'Adding NSAllowArbitraryLoads');
    if (!Object.isObject(data['NSAppTransportSecurity'])) {
      data['NSAppTransportSecurity'] = {};
    }
    data['NSAppTransportSecurity']['NSAllowsArbitraryLoads'] = true;
    changed = true;
  }
  if (forceFamily) {
    if (performForceFamily(data, emit)) {
      changed = true;
    }
  }
  if (bundleid) {
    setBundleId(data, bundleid);
    changed = true;
  }
  if (changed) {
    plist.writeFileSync(file, data);
  }
}

function
fix
(
file
,
options
,
emit
)
{
const
{
appdir
,
bundleid
,
forceFamily
,
allowHttp
}
=
options
;
if
(
!
file
||
!
appdir
)
{
throw
new
Error
(
'Invalid parameters for fixPlist'
)
;
}
let
changed
=
false
;
const
data
=
plist
.
readFileSync
(
file
)
;
delete
data
[
''
]
;
if
(
allowHttp
)
{
emit
(
'message'
,
'Adding NSAllowArbitraryLoads'
)
;
if
(
!
Object
.
isObject
(
data
[
'NSAppTransportSecurity'
]
)
)
{
data
[
'NSAppTransportSecurity'
]
=
{
}
;
}
data
[
'NSAppTransportSecurity'
]
[
'NSAllowsArbitraryLoads'
]
=
true
;
changed
=
true
;
}
if
(
forceFamily
)
{
if
(
performForceFamily
(
data
,
emit
)
)
{
changed
=
true
;
}
}
if
(
bundleid
)
{
setBundleId
(
data
,
bundleid
)
;
changed
=
true
;
}
if
(
changed
)
{
plist
.
writeFileSync
(
file
,
data
)
;
}
}