<commit_before>/*eslint-env node, es6 */
/*eslint-disable no-param-reassign, no-magic-numbers */

"use strict";

// load core modules
const path = require("path");

// load modules
const restify = require("restify");

// application modules
const packages = require(path.normalize(path.join("..", "packages")));

let self = null; //eslint-disable-line consistent-this

class Validators {

    constructor() {
        if (self === null) {
            self = this;
            self.requiredParameterList = [ "type", "dist", "vers", "arch" ];
        }
        return self;
    }

    requiredParameters(req, res, next) {
        const req_id = req.id();
        const errors = [];

        //
        // check for missing required parameters
        //
        for (let i = 0; i < self.requiredParameterList.length; i++) {
            const paramName = self.requiredParameterList[i];

            if (req.params.hasOwnProperty(paramName)) {
                if (req.params[paramName] === null || req.params[paramName].length === 0) { //eslint-disable-line no-magic-numbers
                    errors.push(`A value for '${paramName}' is required`);
                }
            }
            else {
                errors.push(`'${paramName}' is required`);
            }
        }

        // short-circuit and send back missing required parameters
        if (errors.length) {
            errors.push(`ref id: ${req_id}`);
            return next(new restify.MissingParameterError(errors.join(", ")));
        }

        const osType = req.params.type;
        const osDist = req.params.dist;
        const osVers = req.params.vers;
        const osArch = req.params.arch;

        //
        // check for present but, invalid parameters
        //
        if (!osType.match(/^[a-z\_\-]+$/i)) {
            errors.push(`Invalid OS type name '${osType}'`);
        }

        if (!osDist.match(/^[a-z]+$/i)) {
            errors.push(`Invalid OS distribution name '${osDist}'`);
        }

        // validate semver (e.g. 14.04, 7.2.1511) and omnios releases (e.g. r151014)
        if (osVers.match(/^[rv]?\d+(\.\d+){0,2}$/)) {
            req.params.ver_info = {
                "clean": osVers.replace(/^[rv]/, ""),
                "major": null,
                "minor": null,
                "patch": null
            };

            const ver_tmp = req.params.ver_info.clean.split(".");

            req.params.ver_info.major = ver_tmp[0];
            if (ver_tmp.length > 1) {
                req.params.ver_info.minor = ver_tmp[1];
            }
            if (ver_tmp.length > 2) {
                req.params.ver_info.patch = ver_tmp[2];
            }
        }
        else {
            errors.push(`Invalid OS distribution version '${osVers}'`);
        }

        if (!osArch.match(/^(i386|i686|x86_64|amd64)$/)) {
            errors.push(`Invalid OS architecture '${osArch}'`);
        }

        // short-circuit and send back invalid required parameters
        if (errors.length) {
            errors.push(`ref id: ${req_id}`);
            return next(new restify.InvalidArgumentError(errors.join(", ")));
        }

        if (!packages.isSupported(req.params.dist, req.params.ver_info.clean, req.params.arch)) {
            return next(new restify.NotFoundError(`${packages.getError(req.params.dist, req.params.ver_info.clean, req.params.arch)}, ref id: ${req_id}`));
        }

        return next();
    }

    agentMode(req, res, next) {
        const reqId = req.id();
        const errors = [];
        const paramName = "mode";

        if (req.params.hasOwnProperty(paramName)) {
            if (req.params[paramName].length === 0) { //eslint-disable-line no-magic-numbers
                errors.push(`A value for '${paramName}' is required`);
            }
        }
        else {
            errors.push(`'${paramName}' is required`);
        }

        // short-circuit and send back missing required parameters
        if (errors.length) {
            errors.push(`ref id: ${reqId}`);
            return next(new restify.MissingParameterError(errors.join(", ")));
        }

        if (!req.params.mode.match(/^(push|pull|reverse)$/)) {
            errors.push(`Invalid Agent mode '${req.params.mode}'`);
        }

        // short-circuit and send back invalid required parameters
        if (errors.length) {
            errors.push(`ref id: ${reqId}`);
            return next(new restify.InvalidArgumentError(errors.join(", ")));
        }

        return next();

    }

    templateId(req, res, next) {
        const reqId = req.id();
        const errors = [];

        if (!req.params.hasOwnProperty("t_cat")) {
            errors.push("A template category is required");
        }

        if (!req.params.hasOwnProperty("t_name")) {
            errors.push("A template name is required");
        }

        // short-circuit and send back missing required parameters
        if (errors.length) {
            errors.push(`ref id: ${reqId}`);
            return next(new restify.MissingParameterError(errors.join(", ")));
        }

        if (!req.params.t_cat.match(/^(check|graph|worksheet)$/i)) {
            errors.push(`Invalid template category '${req.params.t_cat}'`);
        }

        if (!req.params.t_name.match(/^[a-z0-9\_]+$/i)) {
            errors.push(`Invalid template name '${req.params.t_name}'`);
        }

        // short-circuit and send back invalid required parameters
        if (errors.length) {
            errors.push(`ref id: ${reqId}`);
            return next(new restify.InvalidArgumentError(errors.join(", ")));
        }

        return next();
    }
}

module.exports = new Validators();

//. END
<commit_msg>revonly agent mode support<commit_after>/*eslint-env node, es6 */
/*eslint-disable no-param-reassign, no-magic-numbers */

"use strict";

// load core modules
const path = require("path");

// load modules
const restify = require("restify");

// application modules
const packages = require(path.normalize(path.join("..", "packages")));

let self = null; //eslint-disable-line consistent-this

class Validators {

    constructor() {
        if (self === null) {
            self = this;
            self.requiredParameterList = [ "type", "dist", "vers", "arch" ];
        }
        return self;
    }

    requiredParameters(req, res, next) {
        const req_id = req.id();
        const errors = [];

        //
        // check for missing required parameters
        //
        for (let i = 0; i < self.requiredParameterList.length; i++) {
            const paramName = self.requiredParameterList[i];

            if (req.params.hasOwnProperty(paramName)) {
                if (req.params[paramName] === null || req.params[paramName].length === 0) { //eslint-disable-line no-magic-numbers
                    errors.push(`A value for '${paramName}' is required`);
                }
            }
            else {
                errors.push(`'${paramName}' is required`);
            }
        }

        // short-circuit and send back missing required parameters
        if (errors.length) {
            errors.push(`ref id: ${req_id}`);
            return next(new restify.MissingParameterError(errors.join(", ")));
        }

        const osType = req.params.type;
        const osDist = req.params.dist;
        const osVers = req.params.vers;
        const osArch = req.params.arch;

        //
        // check for present but, invalid parameters
        //
        if (!osType.match(/^[a-z\_\-]+$/i)) {
            errors.push(`Invalid OS type name '${osType}'`);
        }

        if (!osDist.match(/^[a-z]+$/i)) {
            errors.push(`Invalid OS distribution name '${osDist}'`);
        }

        // validate semver (e.g. 14.04, 7.2.1511) and omnios releases (e.g. r151014)
        if (osVers.match(/^[rv]?\d+(\.\d+){0,2}$/)) {
            req.params.ver_info = {
                "clean": osVers.replace(/^[rv]/, ""),
                "major": null,
                "minor": null,
                "patch": null
            };

            const ver_tmp = req.params.ver_info.clean.split(".");

            req.params.ver_info.major = ver_tmp[0];
            if (ver_tmp.length > 1) {
                req.params.ver_info.minor = ver_tmp[1];
            }
            if (ver_tmp.length > 2) {
                req.params.ver_info.patch = ver_tmp[2];
            }
        }
        else {
            errors.push(`Invalid OS distribution version '${osVers}'`);
        }

        if (!osArch.match(/^(i386|i686|x86_64|amd64)$/)) {
            errors.push(`Invalid OS architecture '${osArch}'`);
        }

        // short-circuit and send back invalid required parameters
        if (errors.length) {
            errors.push(`ref id: ${req_id}`);
            return next(new restify.InvalidArgumentError(errors.join(", ")));
        }

        if (!packages.isSupported(req.params.dist, req.params.ver_info.clean, req.params.arch)) {
            return next(new restify.NotFoundError(`${packages.getError(req.params.dist, req.params.ver_info.clean, req.params.arch)}, ref id: ${req_id}`));
        }

        return next();
    }

    agentMode(req, res, next) {
        const reqId = req.id();
        const errors = [];
        const paramName = "mode";

        if (req.params.hasOwnProperty(paramName)) {
            if (req.params[paramName].length === 0) { //eslint-disable-line no-magic-numbers
                errors.push(`A value for '${paramName}' is required`);
            }
        }
        else {
            errors.push(`'${paramName}' is required`);
        }

        // short-circuit and send back missing required parameters
        if (errors.length) {
            errors.push(`ref id: ${reqId}`);
            return next(new restify.MissingParameterError(errors.join(", ")));
        }

        if (!req.params.mode.match(/^(push|pull|reverse|revonly)$/)) {
            errors.push(`Invalid Agent mode '${req.params.mode}'`);
        }

        // short-circuit and send back invalid required parameters
        if (errors.length) {
            errors.push(`ref id: ${reqId}`);
            return next(new restify.InvalidArgumentError(errors.join(", ")));
        }

        return next();

    }

    templateId(req, res, next) {
        const reqId = req.id();
        const errors = [];

        if (!req.params.hasOwnProperty("t_cat")) {
            errors.push("A template category is required");
        }

        if (!req.params.hasOwnProperty("t_name")) {
            errors.push("A template name is required");
        }

        // short-circuit and send back missing required parameters
        if (errors.length) {
            errors.push(`ref id: ${reqId}`);
            return next(new restify.MissingParameterError(errors.join(", ")));
        }

        if (!req.params.t_cat.match(/^(check|graph|worksheet)$/i)) {
            errors.push(`Invalid template category '${req.params.t_cat}'`);
        }

        if (!req.params.t_name.match(/^[a-z0-9\_]+$/i)) {
            errors.push(`Invalid template name '${req.params.t_name}'`);
        }

        // short-circuit and send back invalid required parameters
        if (errors.length) {
            errors.push(`ref id: ${reqId}`);
            return next(new restify.InvalidArgumentError(errors.join(", ")));
        }

        return next();
    }
}

module.exports = new Validators();

//. END
<|endoftext|>


<commit_before>var lbry = {
  isConnected: false,
  rootPath: '.',
  daemonConnectionString: 'http://localhost:5279/lbryapi',
  colors: {
    primary: '#155B4A'
  },
  defaultClientSettings: {
    showNsfw: false,
  }
};

lbry.jsonrpc_call = function (connectionString, method, params, callback, errorCallback, connectFailedCallback) {
  var xhr = new XMLHttpRequest;
  xhr.addEventListener('load', function() {
    var response = JSON.parse(xhr.responseText);

    if (response.error) {
      if (errorCallback) {
        errorCallback(response.error);
      }
    } else if (callback) {
      callback(response.result);
    }
  });

  if (connectFailedCallback) {
    xhr.addEventListener('error', function (e) {
      connectFailedCallback(e);
    });
  }

  xhr.open('POST', connectionString, true);
  xhr.send(JSON.stringify({
    'jsonrpc': '2.0',
    'method': method,
    'params': params,
    'id': 0
  }));
}

lbry.call = function (method, params, callback, errorCallback, connectFailedCallback) {
  lbry.jsonrpc_call(lbry.daemonConnectionString, method, [params], callback, errorCallback, connectFailedCallback);
}

//core
lbry.connect = function(callback)
{
  // Check every half second to see if the daemon's running.
  // Returns true to callback once connected, or false if it takes too long and we give up.
  function checkDaemonRunning(tryNum=0) {
    lbry.daemonRunningStatus(function (runningStatus) {
      if (runningStatus) {
        lbry.isConnected = true;
        callback(true);
      } else {
        if (tryNum <= 600) { // Move # of tries into constant or config option
          setTimeout(function () {
            checkDaemonRunning(tryNum + 1);
          }, 500);
        } else {
          callback(false);
        }
      }
    });
  }
  checkDaemonRunning();
}

lbry.daemonRunningStatus = function (callback) {
  // Returns true/false whether the daemon is running (i.e. fully conncected to the network),
  // or null if the AJAX connection to the daemon fails.

  lbry.call('is_running', {}, callback, null, function () {
    callback(null);
  });
};

lbry.getDaemonStatus = function (callback) {
  lbry.call('daemon_status', {}, callback);
};

lbry.getStartNotice = function(callback) {
  lbry.call('get_start_notice', {}, callback);
}

lbry.checkFirstRun = function(callback) {
  lbry.call('is_first_run', {}, callback);
}

lbry.getNewAddress = function(callback) {
  lbry.call('get_new_address', {}, callback);
}

lbry.getDaemonSettings = function(callback) {
  lbry.call('get_settings', {}, callback);
}

lbry.setDaemonSettings = function(settings, callback) {
  lbry.call('set_settings', settings, callback);
}

lbry.setDaemonSetting = function(setting, value, callback) {
  var setSettingsArgs = {};
  setSettingsArgs[setting] = value;
  lbry.call('set_settings', setSettingsArgs, callback)
}

lbry.getBalance = function(callback)
{
  lbry.call("get_balance", {}, callback);
}

lbry.sendToAddress = function(amount, address, callback, errorCallback)
{
  lbry.call("send_amount_to_address", { "amount" : amount, "address": address }, callback, errorCallback);
}

lbry.search = function(query, callback)
{
  lbry.lighthouse.call('search', [query], callback);
}

lbry.resolveName = function(name, callback) {
  lbry.call('resolve_name', { 'name': name }, callback, () => {
    // For now, assume any error means the name was not resolved
    callback(null);
  });
}

lbry.getStream = function(name, callback) {
  lbry.call('get', { 'name': name }, callback);
};

lbry.getClaimInfo = function(name, callback) {
  lbry.call('get_claim_info', { name: name }, callback);
}

lbry.getCostEstimate = function(name, callback) {
  lbry.call('get_est_cost', { name: name }, callback);
}

lbry.getFileStatus = function(name, callback) {
  lbry.call('get_lbry_file', { 'name': name }, callback);
}

lbry.getFilesInfo = function(callback) {
  lbry.call('get_lbry_files', {}, callback);
}

lbry.startFile = function(name, callback) {
  lbry.call('start_lbry_file', { name: name }, callback);
}

lbry.stopFile = function(name, callback) {
  lbry.call('stop_lbry_file', { name: name }, callback);
}

lbry.deleteFile = function(name, deleteTargetFile=true, callback) {
  lbry.call('delete_lbry_file', {
    name: name,
    delete_target_file: deleteTargetFile,
  }, callback);
}

lbry.revealFile = function(path, callback) {
  lbry.call('reveal', { path: path }, callback);
}

lbry.publish = function(params, callback, errorCallback) {
  // Use ES6 named arguments instead of directly passing param dict?
  lbry.call('publish', params, callback, (errorInfo) => {
    errorCallback({
      name: fault.fault,
      message: fault.faultString,
    });
  });
}

lbry.getVersionInfo = function(callback) {
  lbry.call('version', {}, callback);
};

lbry.checkNewVersionAvailable = function(callback) {
  lbry.call('version', {}, function(versionInfo) {
    var ver = versionInfo.lbrynet_version.split('.');

    var maj = parseInt(ver[0]),
        min = parseInt(ver[1]),
        patch = parseInt(ver[2]);

    var remoteVer = versionInfo.remote_lbrynet.split('.');
    var remoteMaj = parseInt(remoteVer[0]),
        remoteMin = parseInt(remoteVer[1]),
        remotePatch = parseInt(remoteVer[2]);

    if (maj < remoteMaj) {
      var newVersionAvailable = true;
    } else if (maj == remoteMaj) {
      if (min < remoteMin) {
        var newVersionAvailable = true;
      } else if (min == remoteMin) {
        var newVersionAvailable = (patch < remotePatch);
      } else {
        var newVersionAvailable = false;
      }
    } else {
      var newVersionAvailable = false;
    }
    callback(newVersionAvailable);
  }, function(err) {
    if (err.fault == 'NoSuchFunction') {
      // Really old daemon that can't report a version
      callback(true);
    }
  });
}

lbry.getClientSettings = function() {
  var outSettings = {};
  for (let setting of Object.keys(lbry.defaultClientSettings)) {
    var localStorageVal = localStorage.getItem('setting_' + setting);
    outSettings[setting] = (localStorageVal === null ? lbry.defaultClientSettings[setting] : JSON.parse(localStorageVal));
  }
  return outSettings;
}

lbry.getClientSetting = function(setting) {
  var localStorageVal = localStorage.getItem('setting_' + setting);
  return (localStorageVal === null ? lbry.defaultClientSettings[setting] : JSON.parse(localStorageVal));
}

lbry.setClientSettings = function(settings) {
  for (let setting of Object.keys(settings)) {
    lbry.setClientSetting(setting, settings[setting]);
  }
}

lbry.setClientSetting = function(setting, value) {
  return localStorage.setItem('setting_' + setting, JSON.stringify(value));
}

lbry.reportBug = function(message, callback) {
  lbry.call('upload_log', {
    name_prefix: 'report',
    exclude_previous: false,
    force: true,
    message: message
  }, callback);
}

//utilities
lbry.formatCredits = function(amount, precision)
{
  return amount.toFixed(precision || 1).replace(/\.?0+$/, '');
}

lbry.formatName = function(name) {
  // Converts LBRY name to standard format (all lower case, no special characters)
  return name.toLowerCase().replace(/[^a-z0-9\-]/, '');
}

lbry.loadJs = function(src, type, onload)
{
  var lbryScriptTag = document.getElementById('lbry'),
      newScriptTag = document.createElement('script'),
      type = type || 'text/javascript';

  newScriptTag.src = src;
  newScriptTag.type = type;
  if (onload)
  {
    newScript.onload = onload;
  }
  lbryScriptTag.parentNode.insertBefore(newScriptTag, lbryScriptTag);
}

lbry.imagePath = function(file)
{
  return lbry.rootPath + '/img/' + file;
}

lbry.getMediaType = function(contentType, fileName) {
  if (contentType) {
    return /^[^/]+/.exec(contentType);
  } else {
    var dotIndex = filename.lastIndexOf('.');
    if (dotIndex == -1) {
      return 'unknown';
    }

    var ext = filename.substr(dotIndex + 1);
    if (/^mp4|mov|m4v|flv|f4v$/i.test(ext)) {
      return 'video';
    } else if (/^mp3|m4a|aac|wav|flac|ogg$/i.test(ext)) {
      return 'audio';
    } else if (/^html|htm|pdf|odf|doc|docx|md|markdown|txt$/i.test(ext)) {
      return 'document';
    } else {
      return 'unknown';
    }
  }
}

lbry.stop = function(callback) {
  lbry.call('stop', {}, callback);
};

<commit_msg>Make lbry.getMediaType() reliably handle malformed and absent input<commit_after>var lbry = {
  isConnected: false,
  rootPath: '.',
  daemonConnectionString: 'http://localhost:5279/lbryapi',
  colors: {
    primary: '#155B4A'
  },
  defaultClientSettings: {
    showNsfw: false,
  }
};

lbry.jsonrpc_call = function (connectionString, method, params, callback, errorCallback, connectFailedCallback) {
  var xhr = new XMLHttpRequest;
  xhr.addEventListener('load', function() {
    var response = JSON.parse(xhr.responseText);

    if (response.error) {
      if (errorCallback) {
        errorCallback(response.error);
      }
    } else if (callback) {
      callback(response.result);
    }
  });

  if (connectFailedCallback) {
    xhr.addEventListener('error', function (e) {
      connectFailedCallback(e);
    });
  }

  xhr.open('POST', connectionString, true);
  xhr.send(JSON.stringify({
    'jsonrpc': '2.0',
    'method': method,
    'params': params,
    'id': 0
  }));
}

lbry.call = function (method, params, callback, errorCallback, connectFailedCallback) {
  lbry.jsonrpc_call(lbry.daemonConnectionString, method, [params], callback, errorCallback, connectFailedCallback);
}

//core
lbry.connect = function(callback)
{
  // Check every half second to see if the daemon's running.
  // Returns true to callback once connected, or false if it takes too long and we give up.
  function checkDaemonRunning(tryNum=0) {
    lbry.daemonRunningStatus(function (runningStatus) {
      if (runningStatus) {
        lbry.isConnected = true;
        callback(true);
      } else {
        if (tryNum <= 600) { // Move # of tries into constant or config option
          setTimeout(function () {
            checkDaemonRunning(tryNum + 1);
          }, 500);
        } else {
          callback(false);
        }
      }
    });
  }
  checkDaemonRunning();
}

lbry.daemonRunningStatus = function (callback) {
  // Returns true/false whether the daemon is running (i.e. fully conncected to the network),
  // or null if the AJAX connection to the daemon fails.

  lbry.call('is_running', {}, callback, null, function () {
    callback(null);
  });
};

lbry.getDaemonStatus = function (callback) {
  lbry.call('daemon_status', {}, callback);
};

lbry.getStartNotice = function(callback) {
  lbry.call('get_start_notice', {}, callback);
}

lbry.checkFirstRun = function(callback) {
  lbry.call('is_first_run', {}, callback);
}

lbry.getNewAddress = function(callback) {
  lbry.call('get_new_address', {}, callback);
}

lbry.getDaemonSettings = function(callback) {
  lbry.call('get_settings', {}, callback);
}

lbry.setDaemonSettings = function(settings, callback) {
  lbry.call('set_settings', settings, callback);
}

lbry.setDaemonSetting = function(setting, value, callback) {
  var setSettingsArgs = {};
  setSettingsArgs[setting] = value;
  lbry.call('set_settings', setSettingsArgs, callback)
}

lbry.getBalance = function(callback)
{
  lbry.call("get_balance", {}, callback);
}

lbry.sendToAddress = function(amount, address, callback, errorCallback)
{
  lbry.call("send_amount_to_address", { "amount" : amount, "address": address }, callback, errorCallback);
}

lbry.search = function(query, callback)
{
  lbry.lighthouse.call('search', [query], callback);
}

lbry.resolveName = function(name, callback) {
  lbry.call('resolve_name', { 'name': name }, callback, () => {
    // For now, assume any error means the name was not resolved
    callback(null);
  });
}

lbry.getStream = function(name, callback) {
  lbry.call('get', { 'name': name }, callback);
};

lbry.getClaimInfo = function(name, callback) {
  lbry.call('get_claim_info', { name: name }, callback);
}

lbry.getCostEstimate = function(name, callback) {
  lbry.call('get_est_cost', { name: name }, callback);
}

lbry.getFileStatus = function(name, callback) {
  lbry.call('get_lbry_file', { 'name': name }, callback);
}

lbry.getFilesInfo = function(callback) {
  lbry.call('get_lbry_files', {}, callback);
}

lbry.startFile = function(name, callback) {
  lbry.call('start_lbry_file', { name: name }, callback);
}

lbry.stopFile = function(name, callback) {
  lbry.call('stop_lbry_file', { name: name }, callback);
}

lbry.deleteFile = function(name, deleteTargetFile=true, callback) {
  lbry.call('delete_lbry_file', {
    name: name,
    delete_target_file: deleteTargetFile,
  }, callback);
}

lbry.revealFile = function(path, callback) {
  lbry.call('reveal', { path: path }, callback);
}

lbry.publish = function(params, callback, errorCallback) {
  // Use ES6 named arguments instead of directly passing param dict?
  lbry.call('publish', params, callback, (errorInfo) => {
    errorCallback({
      name: fault.fault,
      message: fault.faultString,
    });
  });
}

lbry.getVersionInfo = function(callback) {
  lbry.call('version', {}, callback);
};

lbry.checkNewVersionAvailable = function(callback) {
  lbry.call('version', {}, function(versionInfo) {
    var ver = versionInfo.lbrynet_version.split('.');

    var maj = parseInt(ver[0]),
        min = parseInt(ver[1]),
        patch = parseInt(ver[2]);

    var remoteVer = versionInfo.remote_lbrynet.split('.');
    var remoteMaj = parseInt(remoteVer[0]),
        remoteMin = parseInt(remoteVer[1]),
        remotePatch = parseInt(remoteVer[2]);

    if (maj < remoteMaj) {
      var newVersionAvailable = true;
    } else if (maj == remoteMaj) {
      if (min < remoteMin) {
        var newVersionAvailable = true;
      } else if (min == remoteMin) {
        var newVersionAvailable = (patch < remotePatch);
      } else {
        var newVersionAvailable = false;
      }
    } else {
      var newVersionAvailable = false;
    }
    callback(newVersionAvailable);
  }, function(err) {
    if (err.fault == 'NoSuchFunction') {
      // Really old daemon that can't report a version
      callback(true);
    }
  });
}

lbry.getClientSettings = function() {
  var outSettings = {};
  for (let setting of Object.keys(lbry.defaultClientSettings)) {
    var localStorageVal = localStorage.getItem('setting_' + setting);
    outSettings[setting] = (localStorageVal === null ? lbry.defaultClientSettings[setting] : JSON.parse(localStorageVal));
  }
  return outSettings;
}

lbry.getClientSetting = function(setting) {
  var localStorageVal = localStorage.getItem('setting_' + setting);
  return (localStorageVal === null ? lbry.defaultClientSettings[setting] : JSON.parse(localStorageVal));
}

lbry.setClientSettings = function(settings) {
  for (let setting of Object.keys(settings)) {
    lbry.setClientSetting(setting, settings[setting]);
  }
}

lbry.setClientSetting = function(setting, value) {
  return localStorage.setItem('setting_' + setting, JSON.stringify(value));
}

lbry.reportBug = function(message, callback) {
  lbry.call('upload_log', {
    name_prefix: 'report',
    exclude_previous: false,
    force: true,
    message: message
  }, callback);
}

//utilities
lbry.formatCredits = function(amount, precision)
{
  return amount.toFixed(precision || 1).replace(/\.?0+$/, '');
}

lbry.formatName = function(name) {
  // Converts LBRY name to standard format (all lower case, no special characters)
  return name.toLowerCase().replace(/[^a-z0-9\-]/, '');
}

lbry.loadJs = function(src, type, onload)
{
  var lbryScriptTag = document.getElementById('lbry'),
      newScriptTag = document.createElement('script'),
      type = type || 'text/javascript';

  newScriptTag.src = src;
  newScriptTag.type = type;
  if (onload)
  {
    newScript.onload = onload;
  }
  lbryScriptTag.parentNode.insertBefore(newScriptTag, lbryScriptTag);
}

lbry.imagePath = function(file)
{
  return lbry.rootPath + '/img/' + file;
}

lbry.getMediaType = function(contentType, fileName) {
  if (contentType) {
    return /^[^/]+/.exec(contentType);
  } else if (fileName) {
    var dotIndex = fileName.lastIndexOf('.');
    if (dotIndex == -1) {
      return 'unknown';
    }

    var ext = fileName.substr(dotIndex + 1);
    if (/^mp4|mov|m4v|flv|f4v$/i.test(ext)) {
      return 'video';
    } else if (/^mp3|m4a|aac|wav|flac|ogg$/i.test(ext)) {
      return 'audio';
    } else if (/^html|htm|pdf|odf|doc|docx|md|markdown|txt$/i.test(ext)) {
      return 'document';
    } else {
      return 'unknown';
    }
  } else {
    return 'unknown';
  }
}

lbry.stop = function(callback) {
  lbry.call('stop', {}, callback);
};

<|endoftext|>


<commit_before>/*!
 * Start Bootstrap - Freelancer Bootstrap Theme (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */

// jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
  $('.page-scroll a').bind('click', function(event) {
    var $anchor = $(this);
    $('html, body').stop().animate({
      scrollTop: $($anchor.attr('href')).offset().top
    }, 1500, 'easeInOutExpo');
    event.preventDefault();
  });
});

// Floating label headings for the contact form
$(function() {
  $("body").on("input propertychange", ".floating-label-form-group", function(e) {
    $(this).toggleClass("floating-label-form-group-with-value", !!$(e.target).val());
  }).on("focus", ".floating-label-form-group", function() {
    $(this).addClass("floating-label-form-group-with-focus");
  }).on("blur", ".floating-label-form-group", function() {
    $(this).removeClass("floating-label-form-group-with-focus");
  });
});

// Highlight the top nav as scrolling occurs
$('body').scrollspy({
  target: '.navbar-fixed-top'
})

// Closes the Responsive Menu on Menu Item Click
$('.navbar-collapse ul li a').click(function() {
  $('.navbar-toggle:visible').click();
});

// Add Email Method to Validation
$.validator.addMethod("email", function(value, element) {
  return this.optional(element) || /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/i.test(value);
}, "Please enter a valid email address.");

// Define Form Success
function formSuccess() {
  $('#contact-form').slideUp();
  $('#contact-success').slideDown();
};

// Validate & Submit Form via Ajax
$('#contact-form').validate({
  rules: {
    Field1: {
      required: true,
      minlength: 2
    },
    Field3: {
      required: true,
      minlength: 6,
      email: true
    },
    Field4: {
      required: true,
      minlength: 6,
      number: true
    },
    Field6: {
      required: true,
      minlength: 6
    },
  },
  invalidHandler: function(event, validator) {
    var errors = validator.numberOfInvalids();
    if (errors) {
      var message = errors == 1 ?
        'You missed 1 field. It has been highlighted' :
        'You missed ' + errors + ' fields. They have been highlighted';
      $("div.error span").html(message);
      $("div.error").show();

      ga('send', 'event', 'Form', 'submit', errors + 'errors');
    } else {
      $("div.error").hide();
    }
  },
  submitHandler: function(form) {
    event.preventDefault();
    $.post($(form).attr('action'), $(form).serialize());
    formSuccess();
    ga('send', 'event', 'Form', 'submit', 'success');
  }
});

// Match More Brands to Main Brands
var moreBrands_pad = 0;

function resizeMoreBrands() {
  var dif = $('.brands-item img:visible:last').height() - $('.brands-item:last-child .anchor').height();
  if (dif / 2 !== moreBrands_pad) {
    moreBrands_pad = dif / 2;
    $('.brands-item:last-child .anchor').css('padding', moreBrands_pad + 'px 0');
  } else return;
}

resizeMoreBrands();
window.addEventListener('resize', function() {
  resizeMoreBrands();
}, false);

// Update copyright year
$('footer .curYr').text(new Date().getFullYear());

// Brand GA Events
$('.brands-link').click(function() {
  var brandHdrTxt = $($(this).attr('href')).find('h2').text();
  ga('send', 'event', 'Brands', 'click', brandHdrTxt);
});

// Phone GA Events
$('a.phone').click(function() {
  ga('send', 'event', 'Phone', 'click', $(this).attr('data-label'));
});<commit_msg>added space for event readability<commit_after>/*!
 * Start Bootstrap - Freelancer Bootstrap Theme (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */

// jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
  $('.page-scroll a').bind('click', function(event) {
    var $anchor = $(this);
    $('html, body').stop().animate({
      scrollTop: $($anchor.attr('href')).offset().top
    }, 1500, 'easeInOutExpo');
    event.preventDefault();
  });
});

// Floating label headings for the contact form
$(function() {
  $("body").on("input propertychange", ".floating-label-form-group", function(e) {
    $(this).toggleClass("floating-label-form-group-with-value", !!$(e.target).val());
  }).on("focus", ".floating-label-form-group", function() {
    $(this).addClass("floating-label-form-group-with-focus");
  }).on("blur", ".floating-label-form-group", function() {
    $(this).removeClass("floating-label-form-group-with-focus");
  });
});

// Highlight the top nav as scrolling occurs
$('body').scrollspy({
  target: '.navbar-fixed-top'
})

// Closes the Responsive Menu on Menu Item Click
$('.navbar-collapse ul li a').click(function() {
  $('.navbar-toggle:visible').click();
});

// Add Email Method to Validation
$.validator.addMethod("email", function(value, element) {
  return this.optional(element) || /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/i.test(value);
}, "Please enter a valid email address.");

// Define Form Success
function formSuccess() {
  $('#contact-form').slideUp();
  $('#contact-success').slideDown();
};

// Validate & Submit Form via Ajax
$('#contact-form').validate({
  rules: {
    Field1: {
      required: true,
      minlength: 2
    },
    Field3: {
      required: true,
      minlength: 6,
      email: true
    },
    Field4: {
      required: true,
      minlength: 6,
      number: true
    },
    Field6: {
      required: true,
      minlength: 6
    },
  },
  invalidHandler: function(event, validator) {
    var errors = validator.numberOfInvalids();
    if (errors) {
      var message = errors == 1 ?
        'You missed 1 field. It has been highlighted' :
        'You missed ' + errors + ' fields. They have been highlighted';
      $("div.error span").html(message);
      $("div.error").show();

      ga('send', 'event', 'Form', 'submit', errors + ' errors');
    } else {
      $("div.error").hide();
    }
  },
  submitHandler: function(form) {
    event.preventDefault();
    $.post($(form).attr('action'), $(form).serialize());
    formSuccess();
    ga('send', 'event', 'Form', 'submit', 'success');
  }
});

// Match More Brands to Main Brands
var moreBrands_pad = 0;

function resizeMoreBrands() {
  var dif = $('.brands-item img:visible:last').height() - $('.brands-item:last-child .anchor').height();
  if (dif / 2 !== moreBrands_pad) {
    moreBrands_pad = dif / 2;
    $('.brands-item:last-child .anchor').css('padding', moreBrands_pad + 'px 0');
  } else return;
}

resizeMoreBrands();
window.addEventListener('resize', function() {
  resizeMoreBrands();
}, false);

// Update copyright year
$('footer .curYr').text(new Date().getFullYear());

// Brand GA Events
$('.brands-link').click(function() {
  var brandHdrTxt = $($(this).attr('href')).find('h2').text();
  ga('send', 'event', 'Brands', 'click', brandHdrTxt);
});

// Phone GA Events
$('a.phone').click(function() {
  ga('send', 'event', 'Phone', 'click', $(this).attr('data-label'));
});<|endoftext|>


<commit_before>define(['./counter', './template', './storage'], function (counter, template, storage) {
    // Task constructor
    var Task = function (description, status) {
        this.description = description;
        if (status) {
          this.isComplete = status;
        } else {
          this.isComplete = false;
        }
    };
    var allTasks = [];
    if (storage.getData().length > 0) {
        storage.getData().forEach(function (item) {
            addNewTask(item.description, item.isComplete);
        })
    }
    function addNewTask(description, status) {
        var newTask;
        var taskElement;
        // create HTML with template
        template(description);
        // Set task element and remove temp class
        taskElement = document.querySelector('.new-temporary-class');
        // Check status and set to complete if Complete
        if (status) {
            taskElement.classList.add('completed');
            taskElement.querySelector('.toggle').click();
        }
        document.querySelector('.new-temporary-class').classList.remove('new-temporary-class');
        // Add task to Array
        newTask = new Task(description, status);
        // Add to local Array with tasks
        allTasks.push(newTask);
        // Add events
        addDeleteHandler(newTask, taskElement);
        addEditHandler(newTask, taskElement);
        addSwitch(newTask, taskElement);
        // Update counter
        counter();
        // Update localSorage
        storage.saveData(allTasks);
    }
    function addDeleteHandler (item, element) {
        element.querySelector('.destroy').addEventListener('click', function () {
            removeTask(item, element);
        });
    }
    function addSwitch (item, element) {
        element.querySelector('.toggle').addEventListener('click', function () {
            changeStatus(item, element);
        });
    }
    function removeTask (item, element) {
        var temp = allTasks.indexOf(item)
        if (temp > -1) {
          // If item is on list remove it
            allTasks.splice(temp, 1);
        }
        // Remove item from DOM
        element.parentNode.removeChild(element);
        // Update counter
        counter();
        // Update localSorage
        storage.saveData(allTasks);
    }
    function changeStatus (item, element) {
        // Toggle clas 'completed' on task
        element.classList.toggle('completed');
        // change Status of element on Array
        item.isComplete = !item.isComplete;
        // update counter
        counter();
        // Update localSorage
        storage.saveData(allTasks);
    }
    function addEditHandler (item, element) {
        element.querySelector('label').addEventListener('dblclick', function () {
            editTask(item, element);
        })
    }
    function editTask (item) {
        item.element.classList.add('editing');
        // Focus the input
        item.element.querySelector('.edit').focus();
        // Save on /enter
        item.element.querySelector('.edit').addEventListener('keypress', function (e) {
            if (e.keyCode === 13) {
                // Set description to the input value
                item.description = e.target.value;
                // Set description in DOM
                item.element.querySelector('label').innerHTML = item.description;
                // Remove editing class
                item.element.classList.remove('editing');
                // Update localSorage
                storage.saveData(allTasks);
            }
        });
        item.element.querySelector('.edit').addEventListener('focusout', function (e) {
            item.description = e.target.value;
            item.element.querySelector('label').innerHTML = item.description;
            item.element.classList.remove('editing');
            // Update localSorage
            storage.saveData(allTasks);
        });
    }
    document.querySelector('.new-todo').addEventListener('keypress', function (e) {
        if (e.keyCode === 13) {
            addNewTask(e.target.value);
            e.target.value = '';
        }
    });
    return {
        add: addNewTask,
        remove: removeTask,
        edit: editTask,
        taskList: allTasks
    };
});
<commit_msg>fixed edition<commit_after>define(['./counter', './template', './storage'], function (counter, template, storage) {
    // Task constructor
    var Task = function (description, status) {
        this.description = description;
        if (status) {
          this.isComplete = status;
        } else {
          this.isComplete = false;
        }
    };
    var allTasks = [];
    if (storage.getData().length > 0) {
        storage.getData().forEach(function (item) {
            addNewTask(item.description, item.isComplete);
        })
    }
    function addNewTask(description, status) {
        var newTask;
        var taskElement;
        // create HTML with template
        template(description);
        // Set task element and remove temp class
        taskElement = document.querySelector('.new-temporary-class');
        // Check status and set to complete if Complete
        if (status) {
            taskElement.classList.add('completed');
            taskElement.querySelector('.toggle').click();
        }
        document.querySelector('.new-temporary-class').classList.remove('new-temporary-class');
        // Add task to Array
        newTask = new Task(description, status);
        // Add to local Array with tasks
        allTasks.push(newTask);
        // Add events
        addDeleteHandler(newTask, taskElement);
        addEditHandler(newTask, taskElement);
        addSwitch(newTask, taskElement);
        // Update counter
        counter();
        // Update localSorage
        storage.saveData(allTasks);
    }
    function addDeleteHandler (item, element) {
        element.querySelector('.destroy').addEventListener('click', function () {
            removeTask(item, element);
        });
    }
    function addSwitch (item, element) {
        element.querySelector('.toggle').addEventListener('click', function () {
            changeStatus(item, element);
        });
    }
    function removeTask (item, element) {
        var temp = allTasks.indexOf(item)
        if (temp > -1) {
          // If item is on list remove it
            allTasks.splice(temp, 1);
        }
        // Remove item from DOM
        element.parentNode.removeChild(element);
        // Update counter
        counter();
        // Update localSorage
        storage.saveData(allTasks);
    }
    function changeStatus (item, element) {
        // Toggle clas 'completed' on task
        element.classList.toggle('completed');
        // change Status of element on Array
        item.isComplete = !item.isComplete;
        // update counter
        counter();
        // Update localSorage
        storage.saveData(allTasks);
    }
    function addEditHandler (item, element) {
        element.querySelector('label').addEventListener('dblclick', function () {
            editTask(item, element);
        })
    }
    function editTask (item, element) {
        element.classList.add('editing');
        // Focus the input
        element.querySelector('.edit').focus();
        // Save on /enter
        element.querySelector('.edit').addEventListener('keypress', function (e) {
            if (e.keyCode === 13) {
                // Set description to the input value
                item.description = e.target.value;
                // Set description in DOM
                element.querySelector('label').innerHTML = item.description;
                // Remove editing class
                element.classList.remove('editing');
                // Update localSorage
                storage.saveData(allTasks);
            }
        });
        element.querySelector('.edit').addEventListener('focusout', function (e) {
            item.description = e.target.value;
            element.querySelector('label').innerHTML = item.description;
            element.classList.remove('editing');
            // Update localSorage
            storage.saveData(allTasks);
        });
    }
    document.querySelector('.new-todo').addEventListener('keypress', function (e) {
        if (e.keyCode === 13) {
            addNewTask(e.target.value);
            e.target.value = '';
        }
    });
    return {
        add: addNewTask,
        remove: removeTask,
        edit: editTask,
        taskList: allTasks
    };
});
<|endoftext|>


<commit_before>function HTMLActuator() {
  this.tileContainer    = document.querySelector(".tile-container");
  this.scoreContainer   = document.querySelector(".score-container");
  this.bestContainer    = document.querySelector(".best-container");
  this.messageContainer = document.querySelector(".game-message");

  this.score = 0;
}

HTMLActuator.prototype.actuate = function (grid, metadata) {
  var self = this;

  window.requestAnimationFrame(function () {
    self.clearContainer(self.tileContainer);

    grid.cells.forEach(function (column) {
      column.forEach(function (cell) {
        if (cell) {
          self.addTile(cell);
        }
      });
    });

    self.updateScore(metadata.score);
    self.updateBestScore(metadata.bestScore);

    if (metadata.terminated) {
      if (metadata.over) {
        self.message(false); // You lose
      } else if (metadata.won) {
        self.message(true); // You win!
      }
    }

  });
};

// Continues the game (both restart and keep playing)
HTMLActuator.prototype.continueGame = function () {
  this.clearMessage();
};

HTMLActuator.prototype.clearContainer = function (container) {
  while (container.firstChild) {
    container.removeChild(container.firstChild);
  }
};

HTMLActuator.prototype.addTile = function (tile) {
  var self = this;

  var wrapper   = document.createElement("div");
  var inner     = document.createElement("div");
  var position  = tile.previousPosition || { x: tile.x, y: tile.y };
  var positionClass = this.positionClass(position);

  // We can't use classlist because it somehow glitches when replacing classes
  var classes = ["tile", "tile-" + tile.value, positionClass];

  if (tile.value > 2048) classes.push("tile-super");

  this.applyClasses(wrapper, classes);

  inner.classList.add("tile-inner");
  inner.textContent = tile.value;

  if (tile.previousPosition) {
    // Make sure that the tile gets rendered in the previous position first
    window.requestAnimationFrame(function () {
      classes[2] = self.positionClass({ x: tile.x, y: tile.y });
      self.applyClasses(wrapper, classes); // Update the position
    });
  } else if (tile.mergedFrom) {
    classes.push("tile-merged");
    this.applyClasses(wrapper, classes);

    // Render the tiles that merged
    tile.mergedFrom.forEach(function (merged) {
      self.addTile(merged);
    });
  } else {
    classes.push("tile-new");
    this.applyClasses(wrapper, classes);
  }

  // Add the inner part of the tile to the wrapper
  wrapper.appendChild(inner);

  // Put the tile on the board
  this.tileContainer.appendChild(wrapper);
};

HTMLActuator.prototype.applyClasses = function (element, classes) {
  element.setAttribute("class", classes.join(" "));
};

HTMLActuator.prototype.normalizePosition = function (position) {
  return { x: position.x + 1, y: position.y + 1 };
};

HTMLActuator.prototype.positionClass = function (position) {
  position = this.normalizePosition(position);
  return "tile-position-" + position.x + "-" + position.y;
};

HTMLActuator.prototype.updateScore = function (score) {
  this.clearContainer(this.scoreContainer);

  var difference = score - this.score;
  this.score = score;

  this.scoreContainer.textContent = this.score;

  if (difference > 0) {
    var addition = document.createElement("div");
    addition.classList.add("score-addition");
    addition.textContent = "+" + difference;

    this.scoreContainer.appendChild(addition);
  }
};

HTMLActuator.prototype.updateBestScore = function (bestScore) {
  this.bestContainer.textContent = bestScore;
};

HTMLActuator.prototype.message = function (won) {
  var type    = won ? "game-won" : "game-over";
  var message = won ? "You win!" : "Game over!";

  this.messageContainer.classList.add(type);
  this.messageContainer.getElementsByTagName("p")[0].textContent = message;
};

HTMLActuator.prototype.promptRestart = function () {
  var message = "Start a new game?";
  this.messageContainer.classList.add("restart-game");
  this.messageContainer.getElementsByTagName("p")[0].textContent = message;
};

HTMLActuator.prototype.clearMessage = function () {
  // IE only takes one value to remove at a time.
  this.messageContainer.classList.remove("game-won");
  this.messageContainer.classList.remove("game-over");
  this.messageContainer.classList.remove("restart-game");
};
<commit_msg>Prevent unnecessary calls (by peinguin)<commit_after>function HTMLActuator() {
  this.tileContainer    = document.querySelector(".tile-container");
  this.scoreContainer   = document.querySelector(".score-container");
  this.bestContainer    = document.querySelector(".best-container");
  this.messageContainer = document.querySelector(".game-message");

  this.score = 0;
}

HTMLActuator.prototype.actuate = function (grid, metadata) {
  var self = this;

  window.requestAnimationFrame(function () {
    self.clearContainer(self.tileContainer);

    grid.cells.forEach(function (column) {
      column.forEach(function (cell) {
        if (cell) {
          self.addTile(cell);
        }
      });
    });

    self.updateScore(metadata.score);
    self.updateBestScore(metadata.bestScore);

    if (metadata.terminated) {
      if (metadata.over) {
        self.message(false); // You lose
      } else if (metadata.won) {
        self.message(true); // You win!
      }
    }

  });
};

// Continues the game (both restart and keep playing)
HTMLActuator.prototype.continueGame = function () {
  this.clearMessage();
};

HTMLActuator.prototype.clearContainer = function (container) {
  while (container.firstChild) {
    container.removeChild(container.firstChild);
  }
};

HTMLActuator.prototype.addTile = function (tile) {
  var self = this;

  var wrapper   = document.createElement("div");
  var inner     = document.createElement("div");
  var position  = tile.previousPosition || { x: tile.x, y: tile.y };
  var positionClass = this.positionClass(position);

  // We can't use classlist because it somehow glitches when replacing classes
  var classes = ["tile", "tile-" + tile.value, positionClass];

  if (tile.value > 2048) classes.push("tile-super");

  this.applyClasses(wrapper, classes);

  inner.classList.add("tile-inner");
  inner.textContent = tile.value;

  if (tile.previousPosition) {
    // Make sure that the tile gets rendered in the previous position first
    var newPosClass = self.positionClass({ x: tile.x, y: tile.y });
    if (newPosClass !== classes[2]) {
        window.requestAnimationFrame(function () {
            classes[2] = newPosClass;
            self.applyClasses(wrapper, classes); // Update the position
        });
    }
  } else if (tile.mergedFrom) {
    classes.push("tile-merged");
    this.applyClasses(wrapper, classes);

    // Render the tiles that merged
    tile.mergedFrom.forEach(function (merged) {
      self.addTile(merged);
    });
  } else {
    classes.push("tile-new");
    this.applyClasses(wrapper, classes);
  }

  // Add the inner part of the tile to the wrapper
  wrapper.appendChild(inner);

  // Put the tile on the board
  this.tileContainer.appendChild(wrapper);
};

HTMLActuator.prototype.applyClasses = function (element, classes) {
  element.setAttribute("class", classes.join(" "));
};

HTMLActuator.prototype.normalizePosition = function (position) {
  return { x: position.x + 1, y: position.y + 1 };
};

HTMLActuator.prototype.positionClass = function (position) {
  position = this.normalizePosition(position);
  return "tile-position-" + position.x + "-" + position.y;
};

HTMLActuator.prototype.updateScore = function (score) {
  this.clearContainer(this.scoreContainer);

  var difference = score - this.score;
  this.score = score;

  this.scoreContainer.textContent = this.score;

  if (difference > 0) {
    var addition = document.createElement("div");
    addition.classList.add("score-addition");
    addition.textContent = "+" + difference;

    this.scoreContainer.appendChild(addition);
  }
};

HTMLActuator.prototype.updateBestScore = function (bestScore) {
  this.bestContainer.textContent = bestScore;
};

HTMLActuator.prototype.message = function (won) {
  var type    = won ? "game-won" : "game-over";
  var message = won ? "You win!" : "Game over!";

  this.messageContainer.classList.add(type);
  this.messageContainer.getElementsByTagName("p")[0].textContent = message;
};

HTMLActuator.prototype.promptRestart = function () {
  var message = "Start a new game?";
  this.messageContainer.classList.add("restart-game");
  this.messageContainer.getElementsByTagName("p")[0].textContent = message;
};

HTMLActuator.prototype.clearMessage = function () {
  // IE only takes one value to remove at a time.
  this.messageContainer.classList.remove("game-won");
  this.messageContainer.classList.remove("game-over");
  this.messageContainer.classList.remove("restart-game");
};
<|endoftext|>


<commit_before>/*
 * Mixcloud Tracklist browser extension
 *
 * Copyright (c) 2015 Andrew Lawson <http://adlawson.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link https://github.com/adlawson/mixcloud-tracklist
 */

'use strict';

const dust = require('dustjs-linkedin');
const request = require('request');
const browser = require('./browser');

main();
browser.onChange(browser.querySelector('[m-contents="maincontent"]'), main);

function main() {
    const parent = browser.querySelector('[ng-controller="CloudcastHeaderCtrl"]');
    const empty = parent.querySelector('[ng-init]');
    if (parent !== null) {
        fetchData(window.location, (data) => {
            const tracklistTemplate = require('./templates/tracklist')(dust); // Required by both new and legacy
            if (isLegacy()) {
                render(require('./templates/legacy')(dust), data.cloudcast, html => {
                    browser.replace(parent, empty, html);
                    toggleEvents(parent, parent);
                });
            } else {
                const toggleContainer = browser.querySelector('footer.mz-actions');
                const moreButton = toggleContainer.querySelector('[ng-controller="DropdownCtrl"]');
                render(tracklistTemplate, data.cloudcast, tracklistHtml => {
                    browser.insert(empty, tracklistHtml);
                    render(require('./templates/toggle')(dust), {}, toggleHtml => {
                        browser.insertBefore(toggleContainer, moreButton, toggleHtml);
                        toggleEvents(empty, toggleContainer);
                    });
                });
            }
        });
    }
}

function fetchData(location, fn) {
    request({
        "uri": "/player/details",
        "baseUrl": location.protocol + "//" + location.hostname,
        "qs": { "key": encodeURIComponent(location.pathname) },
        "json": true
    }, (error, response, data) => {
        if (!error && response.statusCode === 200 && data.cloudcast.sections.length > 0) {
            fn(insertTrackNumber(data));
        } else {
            console.error(error);
        }
    });
}

function insertTrackNumber(data) {
    data.cloudcast.sections.forEach((section, i) => {
        section.track_number = i + 1;
    });
    return data;
}

function isLegacy() {
    return browser.querySelector('.mz-site-wrapper') === null;
}

function render(source, data, fn) {
    dust.render(source, data, (error, html) => {
        if (!error) fn(html);
        else console.error(error);
    });
}

function toggleEvents(tracklistContainer, toggleContainer) {
    const button = toggleContainer.querySelector('.tracklist-toggle-text');
    const tracklist = tracklistContainer.querySelector('.cloudcast-tracklist');
    button.addEventListener('click', event => {
        const hide = button.querySelector('[ng-show="tracklistShown"]');
        const show = button.querySelector('[ng-show="!tracklistShown"]');
        hide.classList.toggle('ng-hide');
        show.classList.toggle('ng-hide');
        tracklist.classList.toggle('open');
    });
}
<commit_msg>Fix bug querying null parent element<commit_after>/*
 * Mixcloud Tracklist browser extension
 *
 * Copyright (c) 2015 Andrew Lawson <http://adlawson.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @link https://github.com/adlawson/mixcloud-tracklist
 */

'use strict';

const dust = require('dustjs-linkedin');
const request = require('request');
const browser = require('./browser');

main();
browser.onChange(browser.querySelector('[m-contents="maincontent"]'), main);

function main() {
    const parent = browser.querySelector('[ng-controller="CloudcastHeaderCtrl"]');
    if (parent !== null) {
        fetchData(window.location, (data) => {
            const tracklistTemplate = require('./templates/tracklist')(dust); // Required by both new and legacy
            const empty = parent.querySelector('[ng-init]');
            if (isLegacy()) {
                render(require('./templates/legacy')(dust), data.cloudcast, html => {
                    browser.replace(parent, empty, html);
                    toggleEvents(parent, parent);
                });
            } else {
                const toggleContainer = browser.querySelector('footer.mz-actions');
                const moreButton = toggleContainer.querySelector('[ng-controller="DropdownCtrl"]');
                render(tracklistTemplate, data.cloudcast, tracklistHtml => {
                    browser.insert(empty, tracklistHtml);
                    render(require('./templates/toggle')(dust), {}, toggleHtml => {
                        browser.insertBefore(toggleContainer, moreButton, toggleHtml);
                        toggleEvents(empty, toggleContainer);
                    });
                });
            }
        });
    }
}

function fetchData(location, fn) {
    request({
        "uri": "/player/details",
        "baseUrl": location.protocol + "//" + location.hostname,
        "qs": { "key": encodeURIComponent(location.pathname) },
        "json": true
    }, (error, response, data) => {
        if (!error && response.statusCode === 200 && data.cloudcast.sections.length > 0) {
            fn(insertTrackNumber(data));
        } else {
            console.error(error);
        }
    });
}

function insertTrackNumber(data) {
    data.cloudcast.sections.forEach((section, i) => {
        section.track_number = i + 1;
    });
    return data;
}

function isLegacy() {
    return browser.querySelector('.mz-site-wrapper') === null;
}

function render(source, data, fn) {
    dust.render(source, data, (error, html) => {
        if (!error) fn(html);
        else console.error(error);
    });
}

function toggleEvents(tracklistContainer, toggleContainer) {
    const button = toggleContainer.querySelector('.tracklist-toggle-text');
    const tracklist = tracklistContainer.querySelector('.cloudcast-tracklist');
    button.addEventListener('click', event => {
        const hide = button.querySelector('[ng-show="tracklistShown"]');
        const show = button.querySelector('[ng-show="!tracklistShown"]');
        hide.classList.toggle('ng-hide');
        show.classList.toggle('ng-hide');
        tracklist.classList.toggle('open');
    });
}
<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.ObjectLoader = function ( manager ) {

	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
	this.texturePath = '';

};

THREE.ObjectLoader.prototype = {

	constructor: THREE.ObjectLoader,

	load: function ( url, onLoad, onProgress, onError ) {

		if ( this.texturePath === '' ) {

			this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );

		}

		var scope = this;

		var loader = new THREE.XHRLoader( scope.manager );
		loader.setCrossOrigin( this.crossOrigin );
		loader.load( url, function ( text ) {

			scope.parse( JSON.parse( text ), onLoad );

		}, onProgress, onError );

	},

	setTexturePath: function ( value ) {

		this.texturePath = value;

	},

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;

	},

	parse: function ( json, onLoad ) {

		var geometries = this.parseGeometries( json.geometries );

		var images = this.parseImages( json.images, function () {

			if ( onLoad !== undefined ) onLoad( object );

		} );

		var textures  = this.parseTextures( json.textures, images );
		var materials = this.parseMaterials( json.materials, textures );

		var tracks = [];

		var object = this.parseObject( json.object, geometries, materials, tracks );

		if( tracks.length > 0 ) {

			object.animationClips = [ new THREE.AnimationClip( "default", -1, tracks ) ];

		}

		if ( json.images === undefined || json.images.length === 0 ) {

			if ( onLoad !== undefined ) onLoad( object );

		}

		return object;

	},

	parseGeometries: function ( json ) {

		var geometries = {};

		if ( json !== undefined ) {

			var geometryLoader = new THREE.JSONLoader();
			var bufferGeometryLoader = new THREE.BufferGeometryLoader();

			for ( var i = 0, l = json.length; i < l; i ++ ) {

				var geometry;
				var data = json[ i ];

				switch ( data.type ) {

					case 'PlaneGeometry':
					case 'PlaneBufferGeometry':

						geometry = new THREE[ data.type ](
							data.width,
							data.height,
							data.widthSegments,
							data.heightSegments
						);

						break;

					case 'BoxGeometry':
					case 'CubeGeometry': // backwards compatible

						geometry = new THREE.BoxGeometry(
							data.width,
							data.height,
							data.depth,
							data.widthSegments,
							data.heightSegments,
							data.depthSegments
						);

						break;

					case 'CircleBufferGeometry':

						geometry = new THREE.CircleBufferGeometry(
							data.radius,
							data.segments,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'CircleGeometry':

						geometry = new THREE.CircleGeometry(
							data.radius,
							data.segments,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'CylinderGeometry':

						geometry = new THREE.CylinderGeometry(
							data.radiusTop,
							data.radiusBottom,
							data.height,
							data.radialSegments,
							data.heightSegments,
							data.openEnded,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'SphereGeometry':

						geometry = new THREE.SphereGeometry(
							data.radius,
							data.widthSegments,
							data.heightSegments,
							data.phiStart,
							data.phiLength,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'SphereBufferGeometry':

						geometry = new THREE.SphereBufferGeometry(
							data.radius,
							data.widthSegments,
							data.heightSegments,
							data.phiStart,
							data.phiLength,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'DodecahedronGeometry':

						geometry = new THREE.DodecahedronGeometry(
							data.radius,
							data.detail
						);

						break;

					case 'IcosahedronGeometry':

						geometry = new THREE.IcosahedronGeometry(
							data.radius,
							data.detail
						);

						break;

					case 'OctahedronGeometry':

						geometry = new THREE.OctahedronGeometry(
							data.radius,
							data.detail
						);

						break;

					case 'TetrahedronGeometry':

						geometry = new THREE.TetrahedronGeometry(
							data.radius,
							data.detail
						);

						break;

					case 'RingGeometry':

						geometry = new THREE.RingGeometry(
							data.innerRadius,
							data.outerRadius,
							data.thetaSegments,
							data.phiSegments,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'TorusGeometry':

						geometry = new THREE.TorusGeometry(
							data.radius,
							data.tube,
							data.radialSegments,
							data.tubularSegments,
							data.arc
						);

						break;

					case 'TorusKnotGeometry':

						geometry = new THREE.TorusKnotGeometry(
							data.radius,
							data.tube,
							data.radialSegments,
							data.tubularSegments,
							data.p,
							data.q,
							data.heightScale
						);

						break;

					case 'BufferGeometry':

						geometry = bufferGeometryLoader.parse( data );

						break;

					case 'Geometry':

						geometry = geometryLoader.parse( data.data, this.texturePath ).geometry;

						break;

					case 'TextGeometry':

						geometry = new THREE.TextGeometry(
							data.text,
							data.data
						);

						break;

				}

				geometry.uuid = data.uuid;

				if ( data.name !== undefined ) geometry.name = data.name;

				geometries[ data.uuid ] = geometry;

			}

		}

		return geometries;

	},

	parseMaterials: function ( json, textures ) {

		var materials = {};

		if ( json !== undefined ) {

			var getTexture = function ( name ) {

				if ( textures[ name ] === undefined ) {

					console.warn( 'THREE.ObjectLoader: Undefined texture', name );

				}

				return textures[ name ];

			};

			var loader = new THREE.MaterialLoader();

			for ( var i = 0, l = json.length; i < l; i ++ ) {

				var data = json[ i ];
				var material = loader.parse( data );

				material.uuid = data.uuid;

				if ( data.depthTest !== undefined ) material.depthTest = data.depthTest;
				if ( data.depthWrite !== undefined ) material.depthWrite = data.depthWrite;

				if ( data.name !== undefined ) material.name = data.name;

				if ( data.map !== undefined ) material.map = getTexture( data.map );

				if ( data.alphaMap !== undefined ) {

					material.alphaMap = getTexture( data.alphaMap );
					material.transparent = true;

				}

				if ( data.bumpMap !== undefined ) material.bumpMap = getTexture( data.bumpMap );
				if ( data.bumpScale !== undefined ) material.bumpScale = data.bumpScale;

				if ( data.normalMap !== undefined ) material.normalMap = getTexture( data.normalMap );
				if ( data.normalScale )	material.normalScale = new THREE.Vector2( data.normalScale, data.normalScale );

				if ( data.specularMap !== undefined ) material.specularMap = getTexture( data.specularMap );

				if ( data.envMap !== undefined ) {

					material.envMap = getTexture( data.envMap );
					material.combine = THREE.MultiplyOperation;

				}

				if ( data.reflectivity ) material.reflectivity = data.reflectivity;

				if ( data.lightMap !== undefined ) material.lightMap = getTexture( data.lightMap );
				if ( data.lightMapIntensity !== undefined ) material.lightMapIntensity = data.lightMapIntensity;

				if ( data.aoMap !== undefined ) material.aoMap = getTexture( data.aoMap );
				if ( data.aoMapIntensity !== undefined ) material.aoMapIntensity = data.aoMapIntensity;

				materials[ data.uuid ] = material;

			}

		}

		return materials;

	},

	parseImages: function ( json, onLoad ) {

		var scope = this;
		var images = {};

		if ( json !== undefined && json.length > 0 ) {

			var manager = new THREE.LoadingManager( onLoad );

			var loader = new THREE.ImageLoader( manager );
			loader.setCrossOrigin( this.crossOrigin );

			var loadImage = function ( url ) {

				url = scope.texturePath + url;

				scope.manager.itemStart( url );

				return loader.load( url, function () {

					scope.manager.itemEnd( url );

				} );

			};

			for ( var i = 0, l = json.length; i < l; i ++ ) {

				var image = json[ i ];
				images[ image.uuid ] = loadImage( image.url );

			}

		}

		return images;

	},

	parseTextures: function ( json, images ) {

		function parseConstant( value ) {

			if ( typeof( value ) === 'number' ) return value;

			console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );

			return THREE[ value ];

		}

		var textures = {};

		if ( json !== undefined ) {

			for ( var i = 0, l = json.length; i < l; i ++ ) {

				var data = json[ i ];

				if ( data.image === undefined ) {

					console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );

				}

				if ( images[ data.image ] === undefined ) {

					console.warn( 'THREE.ObjectLoader: Undefined image', data.image );

				}

				var texture = new THREE.Texture( images[ data.image ] );
				texture.needsUpdate = true;

				texture.uuid = data.uuid;

				if ( data.name !== undefined ) texture.name = data.name;
				if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping );
				if ( data.repeat !== undefined ) texture.repeat = new THREE.Vector2( data.repeat[ 0 ], data.repeat[ 1 ] );
				if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter );
				if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter );
				if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
				if ( Array.isArray( data.wrap ) ) {

					texture.wrapS = parseConstant( data.wrap[ 0 ] );
					texture.wrapT = parseConstant( data.wrap[ 1 ] );

				}

				textures[ data.uuid ] = texture;

			}

		}

		return textures;

	},

	parseObject: function () {

		var matrix = new THREE.Matrix4();

		return function ( data, geometries, materials, tracks ) {

			var object;

			var getGeometry = function ( name ) {

				if ( geometries[ name ] === undefined ) {

					console.warn( 'THREE.ObjectLoader: Undefined geometry', name );

				}

				return geometries[ name ];

			};

			var getMaterial = function ( name ) {

				if ( materials[ name ] === undefined ) {

					console.warn( 'THREE.ObjectLoader: Undefined material', name );

				}

				return materials[ name ];

			};

			switch ( data.type ) {

				case 'Scene':

					object = new THREE.Scene();

					break;

				case 'PerspectiveCamera':

					object = new THREE.PerspectiveCamera( data.fov, data.aspect, data.near, data.far );

					break;

				case 'OrthographicCamera':

					object = new THREE.OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );

					break;

				case 'AmbientLight':

					object = new THREE.AmbientLight( data.color );

					break;

				case 'AreaLight':

					object = new THREE.AreaLight( data.color, data.intensity );

					break;

				case 'DirectionalLight':

					object = new THREE.DirectionalLight( data.color, data.intensity );

					break;

				case 'PointLight':

					object = new THREE.PointLight( data.color, data.intensity, data.distance, data.decay );

					break;

				case 'SpotLight':

					object = new THREE.SpotLight( data.color, data.intensity, data.distance, data.angle, data.exponent, data.decay );

					break;

				case 'HemisphereLight':

					object = new THREE.HemisphereLight( data.color, data.groundColor, data.intensity );

					break;

				case 'Mesh':

					object = new THREE.Mesh( getGeometry( data.geometry ), getMaterial( data.material ) );

					break;

				case 'Line':

					object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );

					break;

				case 'PointCloud':

					object = new THREE.PointCloud( getGeometry( data.geometry ), getMaterial( data.material ) );

					break;

				case 'Sprite':

					object = new THREE.Sprite( getMaterial( data.material ) );

					break;

				case 'Group':

					object = new THREE.Group();

					break;

				default:

					object = new THREE.Object3D();

			}

			object.uuid = data.uuid;

			if ( data.name !== undefined ) object.name = data.name;
			if ( data.matrix !== undefined ) {

				matrix.fromArray( data.matrix );
				matrix.decompose( object.position, object.quaternion, object.scale );

			} else {

				if ( data.position !== undefined ) object.position.fromArray( data.position );
				if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
				if ( data.scale !== undefined ) object.scale.fromArray( data.scale );

			}

			if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
			if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;

			if ( data.visible !== undefined ) object.visible = data.visible;
			if ( data.userData !== undefined ) object.userData = data.userData;

			if ( data.children !== undefined ) {

				for ( var child in data.children ) {

					object.add( this.parseObject( data.children[ child ], geometries, materials, tracks ) );

				}

			}

			if( data.animations && data.animations.tracks ) {

				var dataTracks = data.animations.tracks;

				var fpsToSeconds = ( data.animations.fps !== undefined ) ? ( 1.0 / data.animations.fps ) : 1.0;

				if( dataTracks.position ) {

					tracks.push( THREE.VectorKeyframeTrack.parse( object.uuid + '.position', dataTracks.position ).scale( fpsToSeconds ) );

				}

				if( dataTracks.quaternion ) {

					tracks.push( THREE.QuaternionKeyframeTrack.parse( object.uuid + '.quaternion', dataTracks.quaternion ).scale( fpsToSeconds ) );

				}

				if( dataTracks.scale ) {

					tracks.push( THREE.VectorKeyframeTrack.parse( object.uuid + '.scale', dataTracks.scale ).scale( fpsToSeconds ) );

				}
			}

			return object;

		}

	}()

};
<commit_msg>playing around with getting node animations oriented the right way.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.ObjectLoader = function ( manager ) {

	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
	this.texturePath = '';

};

THREE.ObjectLoader.prototype = {

	constructor: THREE.ObjectLoader,

	load: function ( url, onLoad, onProgress, onError ) {

		if ( this.texturePath === '' ) {

			this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );

		}

		var scope = this;

		var loader = new THREE.XHRLoader( scope.manager );
		loader.setCrossOrigin( this.crossOrigin );
		loader.load( url, function ( text ) {

			scope.parse( JSON.parse( text ), onLoad );

		}, onProgress, onError );

	},

	setTexturePath: function ( value ) {

		this.texturePath = value;

	},

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;

	},

	parse: function ( json, onLoad ) {

		var geometries = this.parseGeometries( json.geometries );

		var images = this.parseImages( json.images, function () {

			if ( onLoad !== undefined ) onLoad( object );

		} );

		var textures  = this.parseTextures( json.textures, images );
		var materials = this.parseMaterials( json.materials, textures );

		var tracks = [];

		var object = this.parseObject( json.object, geometries, materials, tracks );

		if( tracks.length > 0 ) {

			object.animationClips = [ new THREE.AnimationClip( "default", -1, tracks ) ];

		}

		if ( json.images === undefined || json.images.length === 0 ) {

			if ( onLoad !== undefined ) onLoad( object );

		}

		return object;

	},

	parseGeometries: function ( json ) {

		var geometries = {};

		if ( json !== undefined ) {

			var geometryLoader = new THREE.JSONLoader();
			var bufferGeometryLoader = new THREE.BufferGeometryLoader();

			for ( var i = 0, l = json.length; i < l; i ++ ) {

				var geometry;
				var data = json[ i ];

				switch ( data.type ) {

					case 'PlaneGeometry':
					case 'PlaneBufferGeometry':

						geometry = new THREE[ data.type ](
							data.width,
							data.height,
							data.widthSegments,
							data.heightSegments
						);

						break;

					case 'BoxGeometry':
					case 'CubeGeometry': // backwards compatible

						geometry = new THREE.BoxGeometry(
							data.width,
							data.height,
							data.depth,
							data.widthSegments,
							data.heightSegments,
							data.depthSegments
						);

						break;

					case 'CircleBufferGeometry':

						geometry = new THREE.CircleBufferGeometry(
							data.radius,
							data.segments,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'CircleGeometry':

						geometry = new THREE.CircleGeometry(
							data.radius,
							data.segments,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'CylinderGeometry':

						geometry = new THREE.CylinderGeometry(
							data.radiusTop,
							data.radiusBottom,
							data.height,
							data.radialSegments,
							data.heightSegments,
							data.openEnded,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'SphereGeometry':

						geometry = new THREE.SphereGeometry(
							data.radius,
							data.widthSegments,
							data.heightSegments,
							data.phiStart,
							data.phiLength,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'SphereBufferGeometry':

						geometry = new THREE.SphereBufferGeometry(
							data.radius,
							data.widthSegments,
							data.heightSegments,
							data.phiStart,
							data.phiLength,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'DodecahedronGeometry':

						geometry = new THREE.DodecahedronGeometry(
							data.radius,
							data.detail
						);

						break;

					case 'IcosahedronGeometry':

						geometry = new THREE.IcosahedronGeometry(
							data.radius,
							data.detail
						);

						break;

					case 'OctahedronGeometry':

						geometry = new THREE.OctahedronGeometry(
							data.radius,
							data.detail
						);

						break;

					case 'TetrahedronGeometry':

						geometry = new THREE.TetrahedronGeometry(
							data.radius,
							data.detail
						);

						break;

					case 'RingGeometry':

						geometry = new THREE.RingGeometry(
							data.innerRadius,
							data.outerRadius,
							data.thetaSegments,
							data.phiSegments,
							data.thetaStart,
							data.thetaLength
						);

						break;

					case 'TorusGeometry':

						geometry = new THREE.TorusGeometry(
							data.radius,
							data.tube,
							data.radialSegments,
							data.tubularSegments,
							data.arc
						);

						break;

					case 'TorusKnotGeometry':

						geometry = new THREE.TorusKnotGeometry(
							data.radius,
							data.tube,
							data.radialSegments,
							data.tubularSegments,
							data.p,
							data.q,
							data.heightScale
						);

						break;

					case 'BufferGeometry':

						geometry = bufferGeometryLoader.parse( data );

						break;

					case 'Geometry':

						geometry = geometryLoader.parse( data.data, this.texturePath ).geometry;

						break;

					case 'TextGeometry':

						geometry = new THREE.TextGeometry(
							data.text,
							data.data
						);

						break;

				}

				geometry.uuid = data.uuid;

				if ( data.name !== undefined ) geometry.name = data.name;

				geometries[ data.uuid ] = geometry;

			}

		}

		return geometries;

	},

	parseMaterials: function ( json, textures ) {

		var materials = {};

		if ( json !== undefined ) {

			var getTexture = function ( name ) {

				if ( textures[ name ] === undefined ) {

					console.warn( 'THREE.ObjectLoader: Undefined texture', name );

				}

				return textures[ name ];

			};

			var loader = new THREE.MaterialLoader();

			for ( var i = 0, l = json.length; i < l; i ++ ) {

				var data = json[ i ];
				var material = loader.parse( data );

				material.uuid = data.uuid;

				if ( data.depthTest !== undefined ) material.depthTest = data.depthTest;
				if ( data.depthWrite !== undefined ) material.depthWrite = data.depthWrite;

				if ( data.name !== undefined ) material.name = data.name;

				if ( data.map !== undefined ) material.map = getTexture( data.map );

				if ( data.alphaMap !== undefined ) {

					material.alphaMap = getTexture( data.alphaMap );
					material.transparent = true;

				}

				if ( data.bumpMap !== undefined ) material.bumpMap = getTexture( data.bumpMap );
				if ( data.bumpScale !== undefined ) material.bumpScale = data.bumpScale;

				if ( data.normalMap !== undefined ) material.normalMap = getTexture( data.normalMap );
				if ( data.normalScale )	material.normalScale = new THREE.Vector2( data.normalScale, data.normalScale );

				if ( data.specularMap !== undefined ) material.specularMap = getTexture( data.specularMap );

				if ( data.envMap !== undefined ) {

					material.envMap = getTexture( data.envMap );
					material.combine = THREE.MultiplyOperation;

				}

				if ( data.reflectivity ) material.reflectivity = data.reflectivity;

				if ( data.lightMap !== undefined ) material.lightMap = getTexture( data.lightMap );
				if ( data.lightMapIntensity !== undefined ) material.lightMapIntensity = data.lightMapIntensity;

				if ( data.aoMap !== undefined ) material.aoMap = getTexture( data.aoMap );
				if ( data.aoMapIntensity !== undefined ) material.aoMapIntensity = data.aoMapIntensity;

				materials[ data.uuid ] = material;

			}

		}

		return materials;

	},

	parseImages: function ( json, onLoad ) {

		var scope = this;
		var images = {};

		if ( json !== undefined && json.length > 0 ) {

			var manager = new THREE.LoadingManager( onLoad );

			var loader = new THREE.ImageLoader( manager );
			loader.setCrossOrigin( this.crossOrigin );

			var loadImage = function ( url ) {

				url = scope.texturePath + url;

				scope.manager.itemStart( url );

				return loader.load( url, function () {

					scope.manager.itemEnd( url );

				} );

			};

			for ( var i = 0, l = json.length; i < l; i ++ ) {

				var image = json[ i ];
				images[ image.uuid ] = loadImage( image.url );

			}

		}

		return images;

	},

	parseTextures: function ( json, images ) {

		function parseConstant( value ) {

			if ( typeof( value ) === 'number' ) return value;

			console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );

			return THREE[ value ];

		}

		var textures = {};

		if ( json !== undefined ) {

			for ( var i = 0, l = json.length; i < l; i ++ ) {

				var data = json[ i ];

				if ( data.image === undefined ) {

					console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );

				}

				if ( images[ data.image ] === undefined ) {

					console.warn( 'THREE.ObjectLoader: Undefined image', data.image );

				}

				var texture = new THREE.Texture( images[ data.image ] );
				texture.needsUpdate = true;

				texture.uuid = data.uuid;

				if ( data.name !== undefined ) texture.name = data.name;
				if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping );
				if ( data.repeat !== undefined ) texture.repeat = new THREE.Vector2( data.repeat[ 0 ], data.repeat[ 1 ] );
				if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter );
				if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter );
				if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
				if ( Array.isArray( data.wrap ) ) {

					texture.wrapS = parseConstant( data.wrap[ 0 ] );
					texture.wrapT = parseConstant( data.wrap[ 1 ] );

				}

				textures[ data.uuid ] = texture;

			}

		}

		return textures;

	},

	parseObject: function () {

		var matrix = new THREE.Matrix4();

		return function ( data, geometries, materials, tracks ) {

			var object;

			var getGeometry = function ( name ) {

				if ( geometries[ name ] === undefined ) {

					console.warn( 'THREE.ObjectLoader: Undefined geometry', name );

				}

				return geometries[ name ];

			};

			var getMaterial = function ( name ) {

				if ( materials[ name ] === undefined ) {

					console.warn( 'THREE.ObjectLoader: Undefined material', name );

				}

				return materials[ name ];

			};

			switch ( data.type ) {

				case 'Scene':

					object = new THREE.Scene();

					break;

				case 'PerspectiveCamera':

					object = new THREE.PerspectiveCamera( data.fov, data.aspect, data.near, data.far );

					break;

				case 'OrthographicCamera':

					object = new THREE.OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );

					break;

				case 'AmbientLight':

					object = new THREE.AmbientLight( data.color );

					break;

				case 'AreaLight':

					object = new THREE.AreaLight( data.color, data.intensity );

					break;

				case 'DirectionalLight':

					object = new THREE.DirectionalLight( data.color, data.intensity );

					break;

				case 'PointLight':

					object = new THREE.PointLight( data.color, data.intensity, data.distance, data.decay );

					break;

				case 'SpotLight':

					object = new THREE.SpotLight( data.color, data.intensity, data.distance, data.angle, data.exponent, data.decay );

					break;

				case 'HemisphereLight':

					object = new THREE.HemisphereLight( data.color, data.groundColor, data.intensity );

					break;

				case 'Mesh':

					object = new THREE.Mesh( getGeometry( data.geometry ), getMaterial( data.material ) );

					break;

				case 'Line':

					object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );

					break;

				case 'PointCloud':

					object = new THREE.PointCloud( getGeometry( data.geometry ), getMaterial( data.material ) );

					break;

				case 'Sprite':

					object = new THREE.Sprite( getMaterial( data.material ) );

					break;

				case 'Group':

					object = new THREE.Group();

					break;

				default:

					object = new THREE.Object3D();

			}

			object.uuid = data.uuid;

			if ( data.name !== undefined ) object.name = data.name;
			if ( data.matrix !== undefined ) {

				matrix.fromArray( data.matrix );
				matrix.decompose( object.position, object.quaternion, object.scale );

			} else {

				if ( data.position !== undefined ) object.position.fromArray( data.position );
				if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
				if ( data.scale !== undefined ) object.scale.fromArray( data.scale );

			}

			if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
			if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;

			if ( data.visible !== undefined ) object.visible = data.visible;
			if ( data.userData !== undefined ) object.userData = data.userData;

			if ( data.children !== undefined ) {

				for ( var child in data.children ) {

					object.add( this.parseObject( data.children[ child ], geometries, materials, tracks ) );

				}

			}

			if( data.animations && data.animations.tracks ) {

				var dataTracks = data.animations.tracks;

				var fpsToSeconds = ( data.animations.fps !== undefined ) ? ( 1.0 / data.animations.fps ) : 1.0;

				if( dataTracks.position ) {

					tracks.push( THREE.VectorKeyframeTrack.parse( object.uuid + '.position', dataTracks.position ).scale( fpsToSeconds ) );

				}

				if( dataTracks.quaternion ) {

					var trackQuaternion = THREE.QuaternionKeyframeTrack.parse( object.uuid + '.quaternion', dataTracks.quaternion ).scale( fpsToSeconds );

					trackQuaternion.multiply( trackQuaternion.keys[0].value.clone().inverse() );
					trackQuaternion.multiply( object.quaternion );

					tracks.push( trackQuaternion );

				}

				if( dataTracks.scale ) {

					tracks.push( THREE.VectorKeyframeTrack.parse( object.uuid + '.scale', dataTracks.scale ).scale( fpsToSeconds ) );

				}
			}

			return object;

		}

	}()

};
<|endoftext|>


<commit_before>'use strict';
var estraverse = require('estraverse');

// Node type unknown to estraverse
var keys = {
	ParenthesizedExpression: [
		'expression',
	],
};

function brace(a) {
	if (!a) {
		return a;
	}
	switch (a.type) {
	case 'BlockStatement':
		return a;
	case 'EmptyStatement':
		a.body = [];
		a.type = 'BlockStatement';
		return a;
	default:
		return {
			body: [
				a,
			],
			type: 'BlockStatement',
		};
	}
}

function cmp(a, b) {
	if (a < b) {
		return -1;
	}
	if (a > b) {
		return 1;
	}
	return 0;
}

function hasTerminator(c) {
	var a = c.consequent;
	if (!a.length) {
		return false;
	}
	return isTerminator(last(a));
}

function isTerminator(a) {
	switch (a.type) {
	case 'BreakStatement':
	case 'ContinueStatement':
	case 'ReturnStatement':
	case 'ThrowStatement':
		return true;
	}
}

function last(a) {
	return a[a.length - 1];
}

function sortSlices(a, isSortableStart, isSortablePart, cmp, post) {
	for (var i = 0; i < a.length; ) {
		if (!isSortableStart(a[i])) {
			i++;
			continue;
		}
		for (var j = i + 1; j < a.length; j++) {
			if (!isSortablePart(a[j])) {
				break;
			}
		}
		var sorted = a.slice(i, j).sort(cmp);
		if (post) {
			post(sorted);
		}
		a.splice.apply(a, [
			i,
			j - i,
		].concat(sorted));
		i = j;
	}
}

// Exports

function run(ast) {
	// ===
	estraverse.traverse(ast, {
		enter: function (ast) {
			if (ast.type !== 'BinaryExpression') {
				return;
			}
			if (ast.left.value !== null && ast.right.value !== null) {
				switch (ast.operator) {
				case '!=':
					ast.operator = '!==';
					break;
				case '==':
					ast.operator = '===';
					break;
				}
			}
		},
		keys: keys,
	});

	// Braces
	estraverse.traverse(ast, {
		enter: function (ast) {
			switch (ast.type) {
			case 'DoWhileStatement':
			case 'ForInStatement':
			case 'ForOfStatement':
			case 'ForStatement':
			case 'WhileStatement':
				ast.body = brace(ast.body);
				break;
			case 'IfStatement':
				ast.consequent = brace(ast.consequent);
				ast.alternate = brace(ast.alternate);
				break;
			}
		},
		keys: keys,
	});

	// Break
	estraverse.traverse(ast, {
		enter: function (ast) {
			if (ast.type !== 'SwitchStatement') {
				return;
			}
			if (!ast.cases.length) {
				return;
			}
			var c = last(ast.cases);
			if (hasTerminator(c)) {
				return;
			}
			c.consequent.push({
				loc: ast.loc,
				type: 'BreakStatement',
			});
		},
		keys: keys,
	});

	// Comments
	estraverse.traverse(ast, {
		enter: function (ast) {
			if (!ast.leadingComments) {
				return;
			}
			for (var c of ast.leadingComments) {
				if (c.type !== 'Line') {
					continue;
				}
				var s = c.value;
				for (var i = 0; i < s.length; i++) {
					if (s[i] !== ' ') {
						c.value = s.slice(0, i) + s[i].toUpperCase() + s.slice(i + 1);
						break;
					}
				}
			}
		},
		keys: keys,
	});

	// Vars
	estraverse.traverse(ast, {
		enter: function (ast, parent) {
			if (ast.type !== 'VariableDeclaration') {
				return;
			}
			switch (parent.type) {
			case 'BlockStatement':
			case 'Program':
				var body = parent.body;
				break;
			case 'SwitchCase':
				body = parent.consequent;
				break;
			default:
				return;
			}
			var vars = ast.declarations;
			if (ast.leadingComments) {
				vars[0].leadingComments = (vars[0].leadingComments || []).concat(ast.leadingComments);
			}
			for (var i = 0; i < vars.length; i++) {
				vars[i] = {
					declarations: [
						vars[i],
					],
					type: ast.type,
				};
			}
			body.splice.apply(body, [
				body.indexOf(ast),
				1,
			].concat(vars));
		},
		keys: keys,
	});

	// Sort cases
	estraverse.traverse(ast, {
		enter: function (ast) {
			if (ast.type !== 'SwitchStatement') {
				return;
			}

			// Get blocks of cases
			var block = [];
			var blocks = [];
			for (var c of ast.cases) {
				block.push(c);
				if (hasTerminator(c)) {
					blocks.push(block);
					block = [];
				}
			}
			if (block.length) {
				blocks.push(block);
			}

			// Sort cases within block
			blocks: for (var block of blocks) {
				for (var i = 0; i < block.length - 1; i++) {
					if (block[i].consequent.length) {
						continue blocks;
					}
				}
				var consequent = last(block).consequent;
				last(block).consequent = [];
				block.sort(
					function (a, b) {
						function key(x) {
							x = x.test;
							if (!x) {
								return '\uffff';
							}
							switch (x.type) {
							case 'Identifier':
								return x.name;
							case 'Literal':
								return x.value;
							}
						}

						return cmp(key(a), key(b));
					});
				last(block).consequent = consequent;
			}

			// Sort blocks
			blocks.sort(
				function (a, b) {
					function key(block) {
						var x = block[0].test;
						if (!x) {
							return '\uffff';
						}
						switch (x.type) {
						case 'Identifier':
							return x.name;
						case 'Literal':
							return x.value;
						}
					}

					return cmp(key(a), key(b));
				});

			// Put blocks of cases
			ast.cases = [];
			for (var block of blocks) {
				for (var c of block) {
					ast.cases.push(c);
				}
			}
		},
		keys: keys,
	});

	// Sort functions
	estraverse.traverse(ast, {
		enter: function (ast) {
			if (!ast.body) {
				return;
			}
			sortSlices(
				ast.body,
				function (a) {
					return a.type === 'FunctionDeclaration' && a.id;
				},
				function (a) {
					return a.type === 'FunctionDeclaration' && a.id && !a.leadingComments;
				},
				function (a, b) {
					function key(x) {
						return x.id.name;
					}

					return cmp(key(a), key(b));
				},
				function (a) {
					var comment;
					for (var i = 0; i < a.length; i++) {
						if (a[i].leadingComments) {
							comment = a[i].leadingComments;
							delete a[i].leadingComments;
						}
						a[0].leadingComments = comment;
					}
				});
		},
		keys: keys,
	});

	// Sort properties
	estraverse.traverse(ast, {
		enter: function (ast) {
			if (ast.type !== 'ObjectExpression') {
				return;
			}
			ast.properties.sort(
				function (a, b) {
					function key(x) {
						x = x.key;
						switch (x.type) {
						case 'Identifier':
							return x.name;
						case 'Literal':
							return x.value;
						}
					}

					return cmp(key(a), key(b));
				});
		},
		keys: keys,
	});
}

exports.run = run;
<commit_msg>refactor<commit_after>'use strict';
var estraverse = require('estraverse');

// Node type unknown to estraverse
var keys = {
	ParenthesizedExpression: [
		'expression',
	],
};

function brace(a) {
	if (!a) {
		return a;
	}
	switch (a.type) {
	case 'BlockStatement':
		return a;
	case 'EmptyStatement':
		a.body = [];
		a.type = 'BlockStatement';
		return a;
	default:
		return {
			body: [
				a,
			],
			type: 'BlockStatement',
		};
	}
}

function cmp(a, b) {
	if (a < b) {
		return -1;
	}
	if (a > b) {
		return 1;
	}
	return 0;
}

function hasTerminator(c) {
	var a = c.consequent;
	if (!a.length) {
		return false;
	}
	return isTerminator(last(a));
}

function isTerminator(a) {
	switch (a.type) {
	case 'BreakStatement':
	case 'ContinueStatement':
	case 'ReturnStatement':
	case 'ThrowStatement':
		return true;
	}
}

function last(a) {
	return a[a.length - 1];
}

function sortSlices(a, isSortableStart, isSortablePart, cmp, post) {
	for (var i = 0; i < a.length; ) {
		if (!isSortableStart(a[i])) {
			i++;
			continue;
		}
		for (var j = i + 1; j < a.length; j++) {
			if (!isSortablePart(a[j])) {
				break;
			}
		}
		var sorted = a.slice(i, j).sort(cmp);
		if (post) {
			post(sorted);
		}
		a.splice.apply(a, [
			i,
			j - i,
		].concat(sorted));
		i = j;
	}
}

// Exports

function run(ast) {
	// ===
	estraverse.traverse(ast, {
		enter: function (a) {
			if (a.type !== 'BinaryExpression') {
				return;
			}
			if (a.left.value !== null && a.right.value !== null) {
				switch (a.operator) {
				case '!=':
					a.operator = '!==';
					break;
				case '==':
					a.operator = '===';
					break;
				}
			}
		},
		keys: keys,
	});

	// Braces
	estraverse.traverse(ast, {
		enter: function (a) {
			switch (a.type) {
			case 'DoWhileStatement':
			case 'ForInStatement':
			case 'ForOfStatement':
			case 'ForStatement':
			case 'WhileStatement':
				a.body = brace(a.body);
				break;
			case 'IfStatement':
				a.consequent = brace(a.consequent);
				a.alternate = brace(a.alternate);
				break;
			}
		},
		keys: keys,
	});

	// Break
	estraverse.traverse(ast, {
		enter: function (a) {
			if (a.type !== 'SwitchStatement') {
				return;
			}
			if (!a.cases.length) {
				return;
			}
			var c = last(a.cases);
			if (hasTerminator(c)) {
				return;
			}
			c.consequent.push({
				loc: a.loc,
				type: 'BreakStatement',
			});
		},
		keys: keys,
	});

	// Comments
	estraverse.traverse(ast, {
		enter: function (a) {
			if (!a.leadingComments) {
				return;
			}
			for (var c of a.leadingComments) {
				if (c.type !== 'Line') {
					continue;
				}
				var s = c.value;
				for (var i = 0; i < s.length; i++) {
					if (s[i] !== ' ') {
						c.value = s.slice(0, i) + s[i].toUpperCase() + s.slice(i + 1);
						break;
					}
				}
			}
		},
		keys: keys,
	});

	// Vars
	estraverse.traverse(ast, {
		enter: function (a, parent) {
			if (a.type !== 'VariableDeclaration') {
				return;
			}
			switch (parent.type) {
			case 'BlockStatement':
			case 'Program':
				var body = parent.body;
				break;
			case 'SwitchCase':
				body = parent.consequent;
				break;
			default:
				return;
			}
			var vars = a.declarations;
			if (a.leadingComments) {
				vars[0].leadingComments = (vars[0].leadingComments || []).concat(a.leadingComments);
			}
			for (var i = 0; i < vars.length; i++) {
				vars[i] = {
					declarations: [
						vars[i],
					],
					type: a.type,
				};
			}
			body.splice.apply(body, [
				body.indexOf(a),
				1,
			].concat(vars));
		},
		keys: keys,
	});

	// Sort cases
	estraverse.traverse(ast, {
		enter: function (ast) {
			if (ast.type !== 'SwitchStatement') {
				return;
			}

			// Get blocks of cases
			var block = [];
			var blocks = [];
			for (var c of ast.cases) {
				block.push(c);
				if (hasTerminator(c)) {
					blocks.push(block);
					block = [];
				}
			}
			if (block.length) {
				blocks.push(block);
			}

			// Sort cases within block
			blocks: for (var block of blocks) {
				for (var i = 0; i < block.length - 1; i++) {
					if (block[i].consequent.length) {
						continue blocks;
					}
				}
				var consequent = last(block).consequent;
				last(block).consequent = [];
				block.sort(
					function (a, b) {
						function key(x) {
							x = x.test;
							if (!x) {
								return '\uffff';
							}
							switch (x.type) {
							case 'Identifier':
								return x.name;
							case 'Literal':
								return x.value;
							}
						}

						return cmp(key(a), key(b));
					});
				last(block).consequent = consequent;
			}

			// Sort blocks
			blocks.sort(
				function (a, b) {
					function key(block) {
						var x = block[0].test;
						if (!x) {
							return '\uffff';
						}
						switch (x.type) {
						case 'Identifier':
							return x.name;
						case 'Literal':
							return x.value;
						}
					}

					return cmp(key(a), key(b));
				});

			// Put blocks of cases
			ast.cases = [];
			for (var block of blocks) {
				for (var c of block) {
					ast.cases.push(c);
				}
			}
		},
		keys: keys,
	});

	// Sort functions
	estraverse.traverse(ast, {
		enter: function (ast) {
			if (!ast.body) {
				return;
			}
			sortSlices(
				ast.body,
				function (a) {
					return a.type === 'FunctionDeclaration' && a.id;
				},
				function (a) {
					return a.type === 'FunctionDeclaration' && a.id && !a.leadingComments;
				},
				function (a, b) {
					function key(x) {
						return x.id.name;
					}

					return cmp(key(a), key(b));
				},
				function (a) {
					var comment;
					for (var i = 0; i < a.length; i++) {
						if (a[i].leadingComments) {
							comment = a[i].leadingComments;
							delete a[i].leadingComments;
						}
						a[0].leadingComments = comment;
					}
				});
		},
		keys: keys,
	});

	// Sort properties
	estraverse.traverse(ast, {
		enter: function (ast) {
			if (ast.type !== 'ObjectExpression') {
				return;
			}
			ast.properties.sort(
				function (a, b) {
					function key(x) {
						x = x.key;
						switch (x.type) {
						case 'Identifier':
							return x.name;
						case 'Literal':
							return x.value;
						}
					}

					return cmp(key(a), key(b));
				});
		},
		keys: keys,
	});
}

exports.run = run;
<|endoftext|>


<commit_before>var startDate = 3;
var endDate = 11;

var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!

if (mm == 6) {
  if (dd >= startDate && dd <= endDate) {
    document.write("YES!")
  }
} else {
  document.write("no.")
}<commit_msg>Fix issue where the else block of isitriverfest.js was not being executed outside of riverfest dates.<commit_after>var startDate = 3;
var endDate = 11;

var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!

if (mm == 6 && dd >= startDate && dd <= endDate) {
  document.write("YES!")
} else {
  document.write("no.")
}<|endoftext|>