<commit_before>var traverse = require("babel-core").traverse;
var tt       = require("babel-core").acorn.tokTypes;
var t        = require("babel-core").types;

exports.toToken = function (token) {
  var type = token.type;

  if (type === tt.name) {
    token.type = "Identifier";
  } else if (type === tt.semi || type === tt.comma ||
             type === tt.parenL || type === tt.parenR ||
             type === tt.braceL || type === tt.braceR ||
             type === tt.slash || type === tt.dot ||
             type === tt.bracketL || type === tt.bracketR ||
             type === tt.ellipsis || type === tt.arrow ||
             type === tt.star || type === tt.incDec ||
             type === tt.colon || type === tt.question ||
             type === tt.template || type === tt.backQuote ||
             type === tt.dollarBraceL || type === tt.at ||
             type === tt.logicalOR || type === tt.logicalAND ||
             type === tt.bitwiseOR || type === tt.bitwiseXOR ||
             type === tt.bitwiseAND || type === tt.equality ||
             type === tt.relational || type === tt.bitShift ||
             type === tt.plusMin || type === tt.modulo ||
             type === tt.exponent || type === tt.prefix ||
             type === tt.doubleColon ||
             type.isAssign) {
    token.type = "Punctuator";
    if (!token.value) token.value = type.label;
  } else if (type === tt.jsxTagStart) {
    token.type = "Punctuator";
    token.value = "<";
  } else if (type === tt.jsxTagEnd) {
    token.type = "Punctuator";
    token.value = ">";
  } else if (type === tt.jsxName) {
    token.type = "JSXIdentifier";
  } else if (type === tt.jsxText) {
    token.type = "JSXText";
  } else if (type.keyword === "null") {
    token.type = "Null";
  } else if (type.keyword === "false" || type.keyword === "true") {
    token.type = "Boolean";
  } else if (type.keyword) {
    token.type = "Keyword";
  } else if (type === tt.num) {
    token.type = "Numeric";
    token.value = String(token.value);
  } else if (type === tt.string) {
    token.type = "String";
    token.value = JSON.stringify(token.value);
  } else if (type === tt.regexp) {
    token.type = "RegularExpression";
    token.regex = {
      pattern: token.value.pattern,
      flags: token.value.flags
    };
    token.value = String(token.value.value);
  }

  return token;
};

exports.toAST = function (ast) {
  ast.sourceType = "module";
  traverse(ast, astTransformVisitor);
};

exports.toTokens = function (tokens) {
  // transform tokens to type "Template"
  convertTemplateType(tokens);

  return tokens.filter(function (token) {
    return token.type !== "CommentLine" && token.type !== "CommentBlock";
  }).map(exports.toToken);
};

function convertTemplateType(tokens) {
  var startingToken    = 0;
  var currentToken     = 0;
  // track use of {}
  var numBraces        = 0;
  // track number of nested templates
  var numBackQuotes     = 0;

  function isBackQuote(token) {
    return tokens[token].type === tt.backQuote;
  }

  function isTemplateStarter(token) {
    return isBackQuote(token) ||
           // only can be a template starter when in a template already
           tokens[token].type === tt.braceR && numBackQuotes > 0;
  }

  function isTemplateEnder(token) {
    return isBackQuote(token) ||
           tokens[token].type === tt.dollarBraceL;
  }

  // append the values between start and end
  function createTemplateValue(start, end) {
    var value = "";
    while (start <= end) {
      if (tokens[start].value) {
        value += tokens[start].value;
      } else if (tokens[start].type !== tt.template) {
        value += tokens[start].type.label;
      }
      start++;
    }
    return value;
  }

  // create Template token
  function replaceWithTemplateType(start, end) {
    var templateToken = {
      type: "Template",
      value: createTemplateValue(start, end),
      range: [tokens[start].start, tokens[end].end],
      loc: {
        start: tokens[start].loc.start,
        end: tokens[end].loc.end
      }
    };

    // put new token in place of old tokens
    tokens.splice(start, end - start + 1, templateToken);
  }

  function trackNumBraces(token) {
    if (tokens[token].type === tt.braceL) {
      numBraces++;
    } else if (tokens[token].type === tt.braceR) {
      numBraces--;
    }
  }

  while (startingToken < tokens.length) {
    // template start: check if ` or }
    if (isTemplateStarter(startingToken) && numBraces === 0) {
      if (isBackQuote(startingToken)) {
        numBackQuotes++;
      }

      currentToken = startingToken + 1;

      // check if token after template start is "template"
      if (currentToken >= tokens.length - 1 || tokens[currentToken].type !== tt.template) {
        break;
      }

      // template end: find ` or ${
      while (!isTemplateEnder(currentToken)) {
        if (currentToken >= tokens.length - 1) {
          break;
        }
        currentToken++;
      }

      if (isBackQuote(currentToken)) {
        numBackQuotes--;
      }
      // template start and end found: create new token
      replaceWithTemplateType(startingToken, currentToken);
    } else if (numBackQuotes > 0) {
      trackNumBraces(startingToken);
    }
    startingToken++;
  }
}

var astTransformVisitor = {
  noScope: true,
  enter: function (node) {
    // private var to track original node type
    node._babelType = node.type;
  },
  exit: function (node) { /* parent */
    node.range = [node.start, node.end];

    if (this.isSpreadProperty()) {
      node.type = "Property";
      node.kind = "init";
      node.computed = true;
      node.key = node.value = node.argument;
      delete node.argument;
    }

    if (this.isRestElement()) {
      return node.argument;
    }

    // flow: prevent "no-undef"
    // for "Component" in: "let x: React.Component"
    if (this.isQualifiedTypeIdentifier()) {
      delete node.id;
    }
    // for "b" in: "var a: { b: Foo }"
    if (this.isObjectTypeProperty()) {
      delete node.key;
    }
    // for "indexer" in: "var a: {[indexer: string]: number}"
    if (this.isObjectTypeIndexer()) {
      delete node.id;
    }
    // for "param" in: "var a: { func(param: Foo): Bar };"
    if (this.isFunctionTypeParam()) {
      delete node.name;
    }

    // modules

    if (this.isImportDeclaration()) {
      delete node.isType;
    }

    if (this.isExportDeclaration()) {
      var declar = this.get("declaration");
      if (declar.isClassExpression()) {
        node.declaration.type = "ClassDeclaration";
      } else if (declar.isFunctionExpression()) {
        node.declaration.type = "FunctionDeclaration";
      }
    }

    // classes

    if (this.isReferencedIdentifier({ name: "super" })) {
      return t.inherits(t.thisExpression(), node);
    }

    if (this.isClassProperty()) {
      delete node.key;
    }

    // functions

    if (this.isFunction()) {
      if (node.async) node.generator = true;
      delete node.async;
    }

    if (this.isAwaitExpression()) {
      node.type = "YieldExpression";
      node.delegate = node.all;
      delete node.all;
    }

    // template strings

    if (this.isTemplateLiteral()) {
      node.quasis.forEach(function (q) {
        q.range[0] -= 1;
        if (q.tail) {
          q.range[1] += 1;
        } else {
          q.range[1] += 2;
        }
        q.loc.start.column -= 1;
        if (q.tail) {
          q.loc.end.column += 1;
        } else {
          q.loc.end.column += 2;
        }
      });
    }
  }
};
<commit_msg>add missing ranges<commit_after>var traverse = require("babel-core").traverse;
var tt       = require("babel-core").acorn.tokTypes;
var t        = require("babel-core").types;

exports.toToken = function (token) {
  var type = token.type;
  token.range = [token.start, token.end];

  if (type === tt.name) {
    token.type = "Identifier";
  } else if (type === tt.semi || type === tt.comma ||
             type === tt.parenL || type === tt.parenR ||
             type === tt.braceL || type === tt.braceR ||
             type === tt.slash || type === tt.dot ||
             type === tt.bracketL || type === tt.bracketR ||
             type === tt.ellipsis || type === tt.arrow ||
             type === tt.star || type === tt.incDec ||
             type === tt.colon || type === tt.question ||
             type === tt.template || type === tt.backQuote ||
             type === tt.dollarBraceL || type === tt.at ||
             type === tt.logicalOR || type === tt.logicalAND ||
             type === tt.bitwiseOR || type === tt.bitwiseXOR ||
             type === tt.bitwiseAND || type === tt.equality ||
             type === tt.relational || type === tt.bitShift ||
             type === tt.plusMin || type === tt.modulo ||
             type === tt.exponent || type === tt.prefix ||
             type === tt.doubleColon ||
             type.isAssign) {
    token.type = "Punctuator";
    if (!token.value) token.value = type.label;
  } else if (type === tt.jsxTagStart) {
    token.type = "Punctuator";
    token.value = "<";
  } else if (type === tt.jsxTagEnd) {
    token.type = "Punctuator";
    token.value = ">";
  } else if (type === tt.jsxName) {
    token.type = "JSXIdentifier";
  } else if (type === tt.jsxText) {
    token.type = "JSXText";
  } else if (type.keyword === "null") {
    token.type = "Null";
  } else if (type.keyword === "false" || type.keyword === "true") {
    token.type = "Boolean";
  } else if (type.keyword) {
    token.type = "Keyword";
  } else if (type === tt.num) {
    token.type = "Numeric";
    token.value = String(token.value);
  } else if (type === tt.string) {
    token.type = "String";
    token.value = JSON.stringify(token.value);
  } else if (type === tt.regexp) {
    token.type = "RegularExpression";
    token.regex = {
      pattern: token.value.pattern,
      flags: token.value.flags
    };
    token.value = String(token.value.value);
  }

  return token;
};

exports.toAST = function (ast) {
  ast.sourceType = "module";
  ast.range = [ast.start, ast.end];
  traverse(ast, astTransformVisitor);
};

exports.toTokens = function (tokens) {
  // transform tokens to type "Template"
  convertTemplateType(tokens);

  return tokens.filter(function (token) {
    return token.type !== "CommentLine" && token.type !== "CommentBlock";
  }).map(exports.toToken);
};

function convertTemplateType(tokens) {
  var startingToken    = 0;
  var currentToken     = 0;
  // track use of {}
  var numBraces        = 0;
  // track number of nested templates
  var numBackQuotes     = 0;

  function isBackQuote(token) {
    return tokens[token].type === tt.backQuote;
  }

  function isTemplateStarter(token) {
    return isBackQuote(token) ||
           // only can be a template starter when in a template already
           tokens[token].type === tt.braceR && numBackQuotes > 0;
  }

  function isTemplateEnder(token) {
    return isBackQuote(token) ||
           tokens[token].type === tt.dollarBraceL;
  }

  // append the values between start and end
  function createTemplateValue(start, end) {
    var value = "";
    while (start <= end) {
      if (tokens[start].value) {
        value += tokens[start].value;
      } else if (tokens[start].type !== tt.template) {
        value += tokens[start].type.label;
      }
      start++;
    }
    return value;
  }

  // create Template token
  function replaceWithTemplateType(start, end) {
    var templateToken = {
      type: "Template",
      value: createTemplateValue(start, end),
      range: [tokens[start].start, tokens[end].end],
      loc: {
        start: tokens[start].loc.start,
        end: tokens[end].loc.end
      }
    };

    // put new token in place of old tokens
    tokens.splice(start, end - start + 1, templateToken);
  }

  function trackNumBraces(token) {
    if (tokens[token].type === tt.braceL) {
      numBraces++;
    } else if (tokens[token].type === tt.braceR) {
      numBraces--;
    }
  }

  while (startingToken < tokens.length) {
    // template start: check if ` or }
    if (isTemplateStarter(startingToken) && numBraces === 0) {
      if (isBackQuote(startingToken)) {
        numBackQuotes++;
      }

      currentToken = startingToken + 1;

      // check if token after template start is "template"
      if (currentToken >= tokens.length - 1 || tokens[currentToken].type !== tt.template) {
        break;
      }

      // template end: find ` or ${
      while (!isTemplateEnder(currentToken)) {
        if (currentToken >= tokens.length - 1) {
          break;
        }
        currentToken++;
      }

      if (isBackQuote(currentToken)) {
        numBackQuotes--;
      }
      // template start and end found: create new token
      replaceWithTemplateType(startingToken, currentToken);
    } else if (numBackQuotes > 0) {
      trackNumBraces(startingToken);
    }
    startingToken++;
  }
}

var astTransformVisitor = {
  noScope: true,
  enter: function (node) {
    // private var to track original node type
    node._babelType = node.type;
  },
  exit: function (node) { /* parent */
    node.range = [node.start, node.end];

    if (this.isSpreadProperty()) {
      node.type = "Property";
      node.kind = "init";
      node.computed = true;
      node.key = node.value = node.argument;
      delete node.argument;
    }

    if (this.isRestElement()) {
      return node.argument;
    }

    // flow: prevent "no-undef"
    // for "Component" in: "let x: React.Component"
    if (this.isQualifiedTypeIdentifier()) {
      delete node.id;
    }
    // for "b" in: "var a: { b: Foo }"
    if (this.isObjectTypeProperty()) {
      delete node.key;
    }
    // for "indexer" in: "var a: {[indexer: string]: number}"
    if (this.isObjectTypeIndexer()) {
      delete node.id;
    }
    // for "param" in: "var a: { func(param: Foo): Bar };"
    if (this.isFunctionTypeParam()) {
      delete node.name;
    }

    // modules

    if (this.isImportDeclaration()) {
      delete node.isType;
    }

    if (this.isExportDeclaration()) {
      var declar = this.get("declaration");
      if (declar.isClassExpression()) {
        node.declaration.type = "ClassDeclaration";
      } else if (declar.isFunctionExpression()) {
        node.declaration.type = "FunctionDeclaration";
      }
    }

    // classes

    if (this.isReferencedIdentifier({ name: "super" })) {
      return t.inherits(t.thisExpression(), node);
    }

    if (this.isClassProperty()) {
      delete node.key;
    }

    // functions

    if (this.isFunction()) {
      if (node.async) node.generator = true;
      delete node.async;
    }

    if (this.isAwaitExpression()) {
      node.type = "YieldExpression";
      node.delegate = node.all;
      delete node.all;
    }

    // template strings

    if (this.isTemplateLiteral()) {
      node.quasis.forEach(function (q) {
        q.range[0] -= 1;
        if (q.tail) {
          q.range[1] += 1;
        } else {
          q.range[1] += 2;
        }
        q.loc.start.column -= 1;
        if (q.tail) {
          q.loc.end.column += 1;
        } else {
          q.loc.end.column += 2;
        }
      });
    }
  }
};
<|endoftext|>


<commit_before>function nullStr(s) {
	if (s) {
		return(s)
	} else {
		return('');
	}
}

function leadingZeros(s) {
    if (s<10) {
    	return '0'+s;
    }
    return s;
}

function sqlCurrentDate() {
    var d = new Date();
    return leadingZeros(d.getFullYear())+'-'+leadingZeros(d.getMonth()+1)+'-'+leadingZeros(d.getDate());
}

function sqlCurrentTime() {
    var d = new Date();
    return leadingZeros(sqlCurrentDate())+' '+leadingZeros(d.getHours())+':'+leadingZeros(d.getMinutes());
}

function fileExt(filename) {
	return filename.split('.').pop().toLowerCase();
}

function baseName(filename) {
	return filename.split('/').pop();
}

function isImage(filename) {
	imgTypes=["jpg", "jpeg", "png", "gif"];
	if (imgTypes.indexOf(fileExt(filename))>=0) {
		return true;
	}
	return false;
}<commit_msg>dateToString function<commit_after>function nullStr(s) {
	if (s) {
		return(s)
	} else {
		return('');
	}
}

function leadingZeros(s) {
    if (s<10) {
    	return '0'+s;
    }
    return s;
}

function sqlCurrentDate() {
    var d = new Date();
    return leadingZeros(d.getFullYear())+'-'+leadingZeros(d.getMonth()+1)+'-'+leadingZeros(d.getDate());
}

function sqlCurrentTime() {
    var d = new Date();
    return leadingZeros(sqlCurrentDate())+' '+leadingZeros(d.getHours())+':'+leadingZeros(d.getMinutes());
}

// Assumes date is Unix timestamp if integer, else assume it's a string
function dateToString(date) {
	if (date == "") return "";
	di = Number(date);
	if (!_.isNaN(di)) {
		var d = new Date(di * 1000); // Javascript to Unix Epoch
	} else {
		var d = new Date(date);
	}
	return d.getFullYear()+"-"+leadingZeros(d.getMonth()+1)+"-"+leadingZeros(d.getDate());
}

function fileExt(filename) {
	return filename.split('.').pop().toLowerCase();
}

function baseName(filename) {
	return filename.split('/').pop();
}

function isImage(filename) {
	imgTypes=["jpg", "jpeg", "png", "gif"];
	if (imgTypes.indexOf(fileExt(filename))>=0) {
		return true;
	}
	return false;
}<|endoftext|>


<commit_before>// Copyright 2002-2015, University of Colorado Boulder
/**
 * @fileoverview Rule to check that a require statement assigns to the correct variable name for the string! plugin.
 * @author Sam Reid (PhET Interactive Simulations)
 * @copyright 2015 University of Colorado Boulder
 */

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function( context ) {
  'use strict';

  // Adapted from Stack Overflow, see http://stackoverflow.com/questions/25085306/javascript-space-separated-string-to-camelcase
  function toCamelCase( string ) {
    var out = '';

    // Add whitespace after each digit so that strings like myString1pattern will get camelcased with uppercase P
    var withWhitespaceAfterDigits = string.replace( /\d/g, function( a ) {return a + ' ';} ).trim();

    // Split on whitespace, remove whitespace and uppercase the first word in each term
    withWhitespaceAfterDigits.split( ' ' ).forEach( function( element, index ) {
      out += (index === 0 ? element : element[ 0 ].toUpperCase() + element.slice( 1 ));
    } );
    return out;
  }

  return {

    // Similar to the require-statement-match.js, please visit that file for AST example
    VariableDeclaration: function requireStatementMatch( node ) {

      if ( node.declarations &&
           node.declarations.length > 0 &&
           node.declarations[ 0 ].init &&
           node.declarations[ 0 ].init.arguments &&
           node.declarations[ 0 ].init.arguments.length > 0 ) {
        if ( node.declarations[ 0 ].init &&
             node.declarations[ 0 ].init.callee.name === 'require' ) {
          var varName = node.declarations[ 0 ].id.name;
          var rhs = node.declarations[ 0 ].init.arguments[ 0 ].value;

          if ( rhs && rhs.indexOf( 'string!' ) === 0 ) {

            var lastSlash = rhs.lastIndexOf( '/' );
            var key = rhs.substring( lastSlash + 1 );

            // Convert various separators to whitespace
            var withWhitespace = key.replace( /\./g, ' ' ).replace( /\-/g, ' ' ).replace( /\_/g, ' ' );

            // Convert whitespace delimited string to camel case and append string suffix
            var desiredVarName = toCamelCase( withWhitespace ) + 'String';

            if ( varName !== desiredVarName ) {
              context.report( {
                node: node,
                loc: node.loc.start,
                message: 'Mismatched var in require(string!), ' +
                         'key=' + key + ', ' +
                         'var=' + varName + ', ' +
                         'desiredVar=' + desiredVarName
              } );
            }
          }
        }
      }
    }
  };
};

module.exports.schema = [
  // JSON Schema for rule options goes here
];<commit_msg>Lowercase the first character, see #396<commit_after>// Copyright 2002-2015, University of Colorado Boulder
/**
 * @fileoverview Rule to check that a require statement assigns to the correct variable name for the string! plugin.
 * @author Sam Reid (PhET Interactive Simulations)
 * @copyright 2015 University of Colorado Boulder
 */

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function( context ) {
  'use strict';

  // Adapted from Stack Overflow, see http://stackoverflow.com/questions/25085306/javascript-space-separated-string-to-camelcase
  function toCamelCase( string ) {
    var out = '';

    // Add whitespace after each digit so that strings like myString1pattern will get camelcased with uppercase P
    var withWhitespaceAfterDigits = string.replace( /\d/g, function( a ) {return a + ' ';} ).trim();

    // Split on whitespace, remove whitespace and uppercase the first word in each term
    withWhitespaceAfterDigits.split( ' ' ).forEach( function( element, index ) {
      out += (index === 0 ? element : element[ 0 ].toUpperCase() + element.slice( 1 ));
    } );

    // lowercase the first character
    if ( out.length > 1 ) {
      out = out.charAt( 0 ).toLowerCase() + out.slice( 1 );
    }
    else if ( out.length === 1 ) {
      out = out.toLowerCase();
    }

    return out;
  }

  return {

    // Similar to the require-statement-match.js, please visit that file for AST example
    VariableDeclaration: function requireStatementMatch( node ) {

      if ( node.declarations &&
           node.declarations.length > 0 &&
           node.declarations[ 0 ].init &&
           node.declarations[ 0 ].init.arguments &&
           node.declarations[ 0 ].init.arguments.length > 0 ) {
        if ( node.declarations[ 0 ].init &&
             node.declarations[ 0 ].init.callee.name === 'require' ) {
          var varName = node.declarations[ 0 ].id.name;
          var rhs = node.declarations[ 0 ].init.arguments[ 0 ].value;

          if ( rhs && rhs.indexOf( 'string!' ) === 0 ) {

            var lastSlash = rhs.lastIndexOf( '/' );
            var key = rhs.substring( lastSlash + 1 );

            // Convert various separators to whitespace
            var withWhitespace = key.replace( /\./g, ' ' ).replace( /\-/g, ' ' ).replace( /\_/g, ' ' );

            // Convert whitespace delimited string to camel case and append string suffix
            var desiredVarName = toCamelCase( withWhitespace ) + 'String';

            if ( varName !== desiredVarName ) {
              context.report( {
                node: node,
                loc: node.loc.start,
                message: 'Mismatched var in require(string!), ' +
                         'key=' + key + ', ' +
                         'var=' + varName + ', ' +
                         'desiredVar=' + desiredVarName
              } );
            }
          }
        }
      }
    }
  };
};

module.exports.schema = [
  // JSON Schema for rule options goes here
];<|endoftext|>


<commit_before>const way = require('senseway')

exports.averageContext = (history, values, mask) => {
  // Sum over history
  //
  // Params:
  //   history, a way. Full history where to search the pattern.
  //   values, a way. Values for the pattern.
  //   mask, a way. Which values of the pattern are meaningful
  //

  if (way.len(values) !== way.len(mask)) {
    throw new Error('Way length mismatch. Values and mask must be same size.')
  }

  // Lengths
  const len = way.len(mask)
  const hlen = way.len(history)

  // Compute mask mass to compare later how perfectly a time slice matches.
  const maskMass = way.reduce(mask, (acc, q) => acc + q, 0)

  // We add up the matching parts of the history to see what
  // happens around the pattern. Let us init the sum with zeros.
  let sliceSum = way.map(mask, q => 0)
  let supportSum = 0

  for (let t = -len; t < hlen; t += 1) {
    // Take a slice of history at time t.
    let tslice = way.slice(history, Math.max(0, t), t + len)
    // A mask for this t.
    let tmask = mask

    // We do not want bias near the edges.
    // Deal with the edges by padding the slice so that size matches the mask.
    // The equal sizes are needed for math operations.
    // However we do not want the padded values have any weight.
    // Therefore we mask the padded values out
    // by setting this area in mask to zero.
    if (t < 0) {
      // Pad at begin
      tslice = way.padLeft(tslice, len, 0)
      tmask = way.padLeft(way.slice(tmask, -t, len), len, 0)
      // For example, with mask length 4:
      //   t = -4: padLeft(slice(tmask, 4, 4), 4, 0)
      //   t = -2: padLeft(slice(tmask, 2, 4), 4, 0)
      //   t = 0: padLeft(slice(tmask, 0, 4), 4, 0)
    } else if (t > hlen - len) {
      // For example, len = 4, hlen = 8:
      //   t = 4: 4 > 8 - 4 === false
      //   t = 5: 5 > 8 - 4 === true

      // Pad at end
      tslice = way.padRight(tslice, len, 0)
      tmask = way.padRight(way.slice(tmask, 0, hlen - t), len, 0)
      // For example, len = 4, hlen = 8:
      //   t = 5: padRight(slice(tmask, 0, 3), 4, 0)
      //   t = 7: padRight(slice(tmask, 0, 1), 4, 0)
      //   t = 8: padRight(slice(tmask, 0, 0), 4, 0)
    }

    // Compute how much the slice resembles the pattern.
    // 0 & 0 => 1
    // 0 & 1 => 0
    // 1 & 1 => 1
    // 0.5 & 0.5 => 1
    const match = way.map2(values, tslice, (a, b) => 1 - Math.abs(a - b))
    // Mask out those resemblances that are not part of the pattern.
    // We do not care about them.
    const masked = way.map2(match, tmask, (d, m) => d * m)
    // Measure how much the slice resembles the pattern
    // by summing up the matches after masking.
    let support = way.reduce(masked, (acc, q) => acc + q, 0)
    // If the pattern exists in the slice, support is high.
    // To make the existence test more crispier, use only perfect matches.
    if (support < maskMass) {
      support = 0
    }
    // Lets add up the supporting slices by taking
    // a weighted average of the slices.
    const weightedSlice = way.scale(tslice, support)
    sliceSum = way.add(sliceSum, weightedSlice)
    supportSum = supportSum + support
  }

  // Normalise to get the weighted average.
  // Take care of possible division by zero.
  let sliceAverage = way.scale(sliceSum, supportSum > 0 ? 1 / supportSum : 0)

  // If sum of support is 0, there is absolutely no matching pattern.
  // Then we just need to use our best knowledge, a priori.
  if (supportSum === 0) {
    const prior = way.mean(history)
    sliceAverage = way.map(sliceAverage, (zero, c) => prior[c][0])
    // TODO way.repeat(way.mean(history), way.len(sliceAverage))
  }

  return sliceAverage
}

// TODO
// probability (history, pattern)
// mutualInformation (history, patternA, patternB)
// pointwiseMutualInformation (history, patternA, patternB)

const informationGain = (prior, posterior) => {
  // Parameters:
  //   prior
  //     Prior probabilities. Probs for a slice before knowledge about an event.
  //   posterior
  //     Posterior probabilities. Probs for a slice given the event.
  //
  // Returns:
  //   a way, having same sizes as the posterior, where every element
  //   equals the number of bits the event gave about the value of the element.
  //
  // Each element in the average slice tells us the probability of value 1
  // happening on that same position next to where the pattern exists.
  // In other words, the average slice gives the probability distribution
  // given the pattern. This distribution can be used for prediction.

  // However, it does not directly reveal the statistical dependecies between
  // the elements and the pattern. For example, consider a dependent element
  // that occurs rarely and compare it to an independent element (given
  // the pattern) that occurs often. The latter will have higher probability
  // in the average slice.

  // To map the dependencies between elements (i.e. events; random variables)
  // we take into account their probability in general, a priori.
  // If the probability of an element in the avg slice differs from a priori,
  // then the pattern and the element are dependent.
  const priorSum = way.reduce(prior, (acc, q) => acc + q, 0)

  const gain = way.map(posterior, (pr, c) => {
    // pr = probability of x given y, where y is our pattern
    // pri = probability of x in general
    // NOTE a little bias in prior caused by the edges.
    const pri = prior[c][0]
    // Kullback-Leibler divergence
    const x0 = (pr === 1) ? 0 : (1 - pr) * Math.log2((1 - pr) / (1 - pri))
    const x1 = (pr === 0) ? 0 : pr * Math.log2(pr / pri)
    return x0 + x1
  });

  return gain
}

exports.dependent = (history, values, mask) => {
  const averageContext = exports.averageContext(history, values, mask)
  const prior = way.mean(history)
  return informationGain(prior, averageContext)
}

exports.firstOrderPatterns = (history, patternLen) => {
  const width = history.length
  const prior = way.mean(history)
  const zeros = way.create(width, patternLen, 0)
  const ones = way.create(width, patternLen, 1)

  // Precompute 1st order patterns.
  // For every channel get a pattern for single zero
  // and a pattern for single one.
  return history.map((ch, c) => {
    // Build mask by setting one cell to one.
    // Note that t=0, thus we get the avgContext
    // towards the future. TODO We might benefit
    // from past context too when weighting how
    // well the pattern matches the context.
    const mask = way.set(zeros, c, 0, 1)

    const avgZero = exports.averageContext(history, zeros, mask)
    const depZero = informationGain(prior, avgZero)
    const avgOne = exports.averageContext(history, ones, mask)
    const depOne = informationGain(prior, avgOne)

    return [
      // Pattern for 0
      {
        source: {
          values: zeros,
          mask: mask
        },
        values: avgZero,
        mask: depZero
      },
      // Pattern for 1
      {
        source: {
          values: ones,
          mask: mask
        },
        values: avgOne,
        mask: depOne
      }
    ]
  })
}

exports.firstOrderPredict = (history, context, distance) => {
  const width = way.width(context)
  const len = way.len(context) + distance
  const firstOrder = exports.firstOrderPatterns(history, len)

  // For every event in the context, select the first order pattern.
  // firstPatterns has dimensions of context.
  // Each element is a pattern { values, mask }.
  const firstPatterns = way.map(context, (q, c, t) => {
    const v = Math.round(q) // To deal with fuzzy binary TODO not needed?
    return Object.assign({
      timeOffset: t
    }, firstOrder[c][v])
  })

  // For each element in prediction we
  // choose the corresponding value from
  // the pattern that gave most information at this cell.
  // maxMask = find pattern where the mask has max value
  // includes area for the prediction.
  const prediction = way.map(way.create(width, len, 0), (q, c, t) => {
    // Find pattern that has the largest information gain for this cell.
    let maxGain = 0
    let valueOfMaxGain = 0 // TODO init from first
    way.each(firstPatterns, (patt) => {
      if (t - patt.timeOffset >= 0) {
        const prob = patt.values[c][t - patt.timeOffset]
        const gain = patt.mask[c][t - patt.timeOffset]

        if (gain > maxGain) {
          maxGain = gain
          valueOfMaxGain = prob
        }
      }
    })

    return valueOfMaxGain
  })

  return prediction

  // Merge the predictions of the patterns.
  // The values without any support from the patterns should
  // be predicted by the prior distribution.
  // TODO How to mix prior with the predicted?
  // Naive try: sum up the masks and invert the values.
  // Add prior probabilities masked with these values to the result.

  // // Add information gains together
  // let mergedMask = way.create(width, len, 0)
  // mergedMask = way.reduce(firstPatterns, (acc, patt, c, t) => {
  //   return way.add(acc, patt.mask)
  // }, mergedMask)
  //
  // const mergedMaskMax = way.max(mergedMask)
  //
  // // Add probabilities together
  // let mergedValues = way.create(width, len, 0)
  // mergedValues = way.reduce(firstPatterns, (acc, patt, c, t) => {
  //   return way.add(acc, way.multiply(patt.values, patt.mask))
  // }, mergedValues)
  //
  // // Normalise values
  // // const scaledMergedValues = way.scale(mergedValues, 1 / mergedMaskMax)
  //
  // const mergedMaskNegative = way.map(mergedMask, q => mergedMaskMax - q)
  //
  // const prior = way.mean(history)
  // const priorValues = way.map(mergedValues, (q, c) => prior[c][0])
  // const priorValuesMasked = way.multiply(priorValues, mergedMaskNegative)
  //
  // const combinedValues = way.add(priorValuesMasked, mergedValues)
  // const normCombValues = way.scale(combinedValues, 1 / mergedMaskMax)
  //
  //
  //
  // return normCombValues
}
<commit_msg>Initial work on 2nd order prediction<commit_after>const way = require('senseway')

exports.averageContext = (history, values, mask) => {
  // Sum over history
  //
  // Params:
  //   history, a way. Full history where to search the pattern.
  //   values, a way. Values for the pattern.
  //   mask, a way. Which values of the pattern are meaningful
  //

  if (way.len(values) !== way.len(mask)) {
    throw new Error('Way length mismatch. Values and mask must be same size.')
  }

  // Lengths
  const len = way.len(mask)
  const hlen = way.len(history)

  // Compute mask mass to compare later how perfectly a time slice matches.
  const maskMass = way.reduce(mask, (acc, q) => acc + q, 0)

  // We add up the matching parts of the history to see what
  // happens around the pattern. Let us init the sum with zeros.
  let sliceSum = way.map(mask, q => 0)
  let supportSum = 0

  for (let t = -len; t < hlen; t += 1) {
    // Take a slice of history at time t.
    let tslice = way.slice(history, Math.max(0, t), t + len)
    // A mask for this t.
    let tmask = mask

    // We do not want bias near the edges.
    // Deal with the edges by padding the slice so that size matches the mask.
    // The equal sizes are needed for math operations.
    // However we do not want the padded values have any weight.
    // Therefore we mask the padded values out
    // by setting this area in mask to zero.
    if (t < 0) {
      // Pad at begin
      tslice = way.padLeft(tslice, len, 0)
      tmask = way.padLeft(way.slice(tmask, -t, len), len, 0)
      // For example, with mask length 4:
      //   t = -4: padLeft(slice(tmask, 4, 4), 4, 0)
      //   t = -2: padLeft(slice(tmask, 2, 4), 4, 0)
      //   t = 0: padLeft(slice(tmask, 0, 4), 4, 0)
    } else if (t > hlen - len) {
      // For example, len = 4, hlen = 8:
      //   t = 4: 4 > 8 - 4 === false
      //   t = 5: 5 > 8 - 4 === true

      // Pad at end
      tslice = way.padRight(tslice, len, 0)
      tmask = way.padRight(way.slice(tmask, 0, hlen - t), len, 0)
      // For example, len = 4, hlen = 8:
      //   t = 5: padRight(slice(tmask, 0, 3), 4, 0)
      //   t = 7: padRight(slice(tmask, 0, 1), 4, 0)
      //   t = 8: padRight(slice(tmask, 0, 0), 4, 0)
    }

    // Compute how much the slice resembles the pattern.
    // 0 & 0 => 1
    // 0 & 1 => 0
    // 1 & 1 => 1
    // 0.5 & 0.5 => 1
    const match = way.map2(values, tslice, (a, b) => 1 - Math.abs(a - b))
    // Mask out those resemblances that are not part of the pattern.
    // We do not care about them.
    const masked = way.map2(match, tmask, (d, m) => d * m)
    // Measure how much the slice resembles the pattern
    // by summing up the matches after masking.
    let support = way.reduce(masked, (acc, q) => acc + q, 0)
    // If the pattern exists in the slice, support is high.
    // To make the existence test more crispier, use only perfect matches.
    if (support < maskMass) {
      support = 0
    }
    // Lets add up the supporting slices by taking
    // a weighted average of the slices.
    const weightedSlice = way.scale(tslice, support)
    sliceSum = way.add(sliceSum, weightedSlice)
    supportSum = supportSum + support
  }

  // Normalise to get the weighted average.
  // Take care of possible division by zero.
  let sliceAverage = way.scale(sliceSum, supportSum > 0 ? 1 / supportSum : 0)

  // If sum of support is 0, there is absolutely no matching pattern.
  // Then we just need to use our best knowledge, a priori.
  if (supportSum === 0) {
    const prior = way.mean(history)
    sliceAverage = way.map(sliceAverage, (zero, c) => prior[c][0])
    // TODO way.repeat(way.mean(history), way.len(sliceAverage))
  }

  return sliceAverage
}

// TODO
// mutualInformation (history, patternA, patternB)
// pointwiseMutualInformation (history, patternA, patternB)

const occurrences = (history, pattern) => {
  return [{
    time:
    context:
  }]
}

const probability = (history, pattern) => {

}

const informationGain = (prior, posterior) => {
  // Parameters:
  //   prior
  //     Prior probabilities. Probs for a slice before knowledge about an event.
  //   posterior
  //     Posterior probabilities. Probs for a slice given the event.
  //
  // Returns:
  //   a way, having same sizes as the posterior, where every element
  //   equals the number of bits the event gave about the value of the element.
  //
  // Each element in the average slice tells us the probability of value 1
  // happening on that same position next to where the pattern exists.
  // In other words, the average slice gives the probability distribution
  // given the pattern. This distribution can be used for prediction.

  // However, it does not directly reveal the statistical dependecies between
  // the elements and the pattern. For example, consider a dependent element
  // that occurs rarely and compare it to an independent element (given
  // the pattern) that occurs often. The latter will have higher probability
  // in the average slice.

  // To map the dependencies between elements (i.e. events; random variables)
  // we take into account their probability in general, a priori.
  // If the probability of an element in the avg slice differs from a priori,
  // then the pattern and the element are dependent.
  const priorSum = way.reduce(prior, (acc, q) => acc + q, 0)

  const gain = way.map(posterior, (pr, c) => {
    // pr = probability of x given y, where y is our pattern
    // pri = probability of x in general
    // NOTE a little bias in prior caused by the edges.
    const pri = prior[c][0]
    // Kullback-Leibler divergence
    const x0 = (pr === 1) ? 0 : (1 - pr) * Math.log2((1 - pr) / (1 - pri))
    const x1 = (pr === 0) ? 0 : pr * Math.log2(pr / pri)
    return x0 + x1
  });

  return gain
}

exports.dependent = (history, values, mask) => {
  const averageContext = exports.averageContext(history, values, mask)
  const prior = way.mean(history)
  return informationGain(prior, averageContext)
}

exports.firstOrderPatterns = (history, patternLen) => {
  const width = history.length
  const prior = way.mean(history)
  const zeros = way.create(width, patternLen, 0)
  const ones = way.create(width, patternLen, 1)

  // Precompute 1st order patterns.
  // For every channel get a pattern for single zero
  // and a pattern for single one.
  return history.map((ch, c) => {
    // Build mask by setting one cell to one.
    // Note that t=0, thus we get the avgContext
    // towards the future. TODO We might benefit
    // from past context too when weighting how
    // well the pattern matches the context.
    const mask = way.set(zeros, c, 0, 1)

    const avgZero = exports.averageContext(history, zeros, mask)
    const depZero = informationGain(prior, avgZero)
    const avgOne = exports.averageContext(history, ones, mask)
    const depOne = informationGain(prior, avgOne)

    return [
      // Pattern for 0
      {
        source: {
          values: zeros,
          mask: mask
        },
        values: avgZero,
        mask: depZero
      },
      // Pattern for 1
      {
        source: {
          values: ones,
          mask: mask
        },
        values: avgOne,
        mask: depOne
      }
    ]
  })
}

exports.firstOrderPredict = (history, context, distance) => {
  const width = way.width(context)
  const len = way.len(context) + distance
  const firstOrder = exports.firstOrderPatterns(history, len)

  // For every event in the context, select the first order pattern.
  // firstPatterns has dimensions of context.
  // Each element is a pattern { values, mask }.
  const firstPatterns = way.map(context, (q, c, t) => {
    const v = Math.round(q) // To deal with fuzzy binary TODO not needed?
    return Object.assign({
      timeOffset: t
    }, firstOrder[c][v])
  })

  // For each element in prediction we
  // choose the corresponding value from
  // the pattern that gave most information at this cell.
  // maxMask = find pattern where the mask has max value
  // includes area for the prediction.
  const prediction = way.map(way.create(width, len, 0), (q, c, t) => {
    // Find pattern that has the largest information gain for this cell.
    let maxGain = 0
    let valueOfMaxGain = 0 // TODO init from first
    way.each(firstPatterns, (patt) => {
      if (t - patt.timeOffset >= 0) {
        const prob = patt.values[c][t - patt.timeOffset]
        const gain = patt.mask[c][t - patt.timeOffset]

        if (gain > maxGain) {
          maxGain = gain
          valueOfMaxGain = prob
        }
      }
    })

    return valueOfMaxGain
  })

  return prediction
  // Alternative:
  // The values without any support from the patterns should
  // be predicted by the prior distribution.
  // How to mix prior with the predicted?
  //   Try: sum up the masks and invert the values.
  //   Add prior probabilities masked with these values to the result.
}

exports.secondOrderPatterns = (history, context) => {
  const width = way.width(history)
  const prior = way.mean(history)
  const len = way.len(context)
  const zeros = way.create(width, patternLen, 0)
  const ones = way.create(width, patternLen, 1)

  // Find every 2nd-order pattern within the context.
  // We only need to create masks, context provides the values.
  const masks = []
  for (let ca = 0; ca < width; ca += 1) {
    for (let ta = 0; ta < len; ta += 1) {
      for (let cb = ca; cb < width; cb += 1) {
        for (let tb = ta; tb < len; tb += 1) {
          let mask = way.create(width, len, 0)
          mask[ca][ta] = 1
          mask[cb][tb] = 1
          masks.push(mask)
        }
      }
    }
  }

  // For every found pattern, compute:
  // - number of occurrences in the history (prior for the pattern)
  // - average around the pattern
  // - deviation from base prior probabilities (dependent)
  // - how much the average differs from the context in general
  // - how much the average of dependent differs from the context

  return masks
}
<|endoftext|>


<commit_before>function FightQueen(session){
	this.canRepeat = true;
	this.session = session;
	this.playerList = [];  //what players are already in the medium when i trigger?

	this.trigger = function(playerList){
		this.playerList = playerList;
		return (this.session.queen.getHP() > 0) &&  (findLivingPlayers(this.session.players).length != 0) ;
	}

//includes time clones
	this.getGoodGuys = function(){
		var living = findLivingPlayers(this.session.players);
		var timePlayer = findAspectPlayer(this.session.players, "Time");

		for(var i = 0; i<timePlayer.doomedTimeClones.length; i++){
			var timeClone = timePlayer.doomedTimeClones[i];
			living.push(timeClone);
		}
		return living;
	}

	//render each living player, each time clone, and some dersites/prospitan rabble (maybe)
	this.renderGoodguys = function(div){
		var repeatTime = 1000;
		var divID = (div.attr("id")) + "_final_boss";
		var ch = canvasHeight;
		var fightingPlayers = this.getGoodGuys();
		if(fightingPlayers.length > 6){
			ch = canvasHeight*1.5; //a little bigger than two rows, cause time clones
		}
		var canvasHTML = "
<canvas id='canvas" + divID+"' width='" +canvasWidth + "' height="+ch + "'>  </canvas>";
		div.append(canvasHTML);
		//different format for canvas code
		var canvasDiv = document.getElementById("canvas"+ divID);
		poseAsATeam(canvasDiv, fightingPlayers, 2000);
	}

	this.renderContent = function(div){
		if(this.session.queen.getPower() < 0) console.log("rendering fight queen with negative power " +this.session.session_id)
		div.append("
  ");
		div.append(this.content());

		this.renderGoodguys(div); //pose as a team BEFORE getting your ass handed to you.
		var fighting = this.getGoodGuys()
		if(this.session.democraticArmy.getHP() > 0) fighting.push(this.session.democraticArmy)
		this.session.queen.strife(div, fighting,0)

	}

	this.minorLevelPlayers = function(stabbings){
		for(var i = 0; i<stabbings.length; i++){
			stabbings[i].increasePower();
		}
	}

	this.setPlayersUnavailable = function(stabbings){
		for(var i = 0; i<stabbings.length; i++){
			removeFromArray(stabbings[i], this.session.availablePlayers);
		}
	}

	this.getDeadList = function(living){
		var numStabbings = getRandomInt(0,living.length);
		var timePlayer = findAspectPlayer(this.session.players, "Time");
		var ret = [];
		//doomed time clones absorb some of the hits.
		for(var i = 0; i<timePlayer.doomedTimeClones.length; i++){
				ret.push(timePlayer.doomedTimeClones[i]);
				removeFromArray(timePlayer.doomedTimeClones[i], timePlayer.doomedTimeClones)
		}

		if(living.length == 0){
			return ret;
		}
		for(var i = ret.length; i<=numStabbings; i++){
			ret.push(getRandomElementFromArray(living));
		}
		return Array.from(new Set(ret));
	}

	this.content = function(){
		//console.log("Queen Strength : " + this.session.queenStrength)
		var badPrototyping = findBadPrototyping(this.playerList);
		var living = findLivingPlayers(this.session.players);
		var ret = " Before the players can reach the Black King, they are intercepted by the Black Queen. ";
		if(badPrototyping){
			ret += " She is made especially ferocious with the addition of the " + badPrototyping + ". ";
		}

		this.setPlayersUnavailable(living);

		return ret;

	}
}
<commit_msg>armless prototyping<commit_after>function FightQueen(session){
	this.canRepeat = true;
	this.session = session;
	this.playerList = [];  //what players are already in the medium when i trigger?

	this.trigger = function(playerList){
		this.playerList = playerList;
		return (this.session.queen.getHP() > 0) &&  (findLivingPlayers(this.session.players).length != 0) ;
	}

//includes time clones
	this.getGoodGuys = function(){
		var living = findLivingPlayers(this.session.players);
		var timePlayer = findAspectPlayer(this.session.players, "Time");

		for(var i = 0; i<timePlayer.doomedTimeClones.length; i++){
			var timeClone = timePlayer.doomedTimeClones[i];
			living.push(timeClone);
		}
		return living;
	}

	//render each living player, each time clone, and some dersites/prospitan rabble (maybe)
	this.renderGoodguys = function(div){
		var repeatTime = 1000;
		var divID = (div.attr("id")) + "_final_boss";
		var ch = canvasHeight;
		var fightingPlayers = this.getGoodGuys();
		if(fightingPlayers.length > 6){
			ch = canvasHeight*1.5; //a little bigger than two rows, cause time clones
		}
		var canvasHTML = "
<canvas id='canvas" + divID+"' width='" +canvasWidth + "' height="+ch + "'>  </canvas>";
		div.append(canvasHTML);
		//different format for canvas code
		var canvasDiv = document.getElementById("canvas"+ divID);
		poseAsATeam(canvasDiv, fightingPlayers, 2000);
	}

	this.renderContent = function(div){
		if(this.session.queen.getPower() < 0) console.log("rendering fight queen with negative power " +this.session.session_id)
		div.append("
  ");
		div.append(this.content());

		this.renderGoodguys(div); //pose as a team BEFORE getting your ass handed to you.
		var fighting = this.getGoodGuys()
		if(this.session.democraticArmy.getHP() > 0) fighting.push(this.session.democraticArmy)
		this.session.queen.strife(div, fighting,0)

	}

	this.minorLevelPlayers = function(stabbings){
		for(var i = 0; i<stabbings.length; i++){
			stabbings[i].increasePower();
		}
	}

	this.setPlayersUnavailable = function(stabbings){
		for(var i = 0; i<stabbings.length; i++){
			removeFromArray(stabbings[i], this.session.availablePlayers);
		}
	}

	this.getDeadList = function(living){
		var numStabbings = getRandomInt(0,living.length);
		var timePlayer = findAspectPlayer(this.session.players, "Time");
		var ret = [];
		//doomed time clones absorb some of the hits.
		for(var i = 0; i<timePlayer.doomedTimeClones.length; i++){
				ret.push(timePlayer.doomedTimeClones[i]);
				removeFromArray(timePlayer.doomedTimeClones[i], timePlayer.doomedTimeClones)
		}

		if(living.length == 0){
			return ret;
		}
		for(var i = ret.length; i<=numStabbings; i++){
			ret.push(getRandomElementFromArray(living));
		}
		return Array.from(new Set(ret));
	}

	this.content = function(){
		//console.log("Queen Strength : " + this.session.queenStrength)
		var badPrototyping = findBadPrototyping(this.playerList);
		var living = findLivingPlayers(this.session.players);
		var ret = " Before the players can reach the Black King, they are intercepted by the Black Queen. ";
		if(badPrototyping && this.session.queen.crowned){
			ret += " She is made especially ferocious with the addition of the " + badPrototyping + ". ";
		}else if(!this.session.queen.crowned){
			ret += "She may no longer have her RING OF ORBS " +this.session.convertPlayerNumberToWords() + "FOLD, but she is dedicated to her duty and will fight the Players to the bitter end."
		}

		this.setPlayersUnavailable(living);

		return ret;

	}
}
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';

import * as actions from 'reduxes/actions';

import NavMenuItem from './NavMenuItem';

class NavMenuList extends Component {

    constructor(props) {
        super(props);
    }

    render() {

        const {$navMenu, $expandMenuName, $activatedMenu, expandMenu, updateActivatedMenu} = this.props;

        return (

                    {
                        $navMenu.map((menu, index) => {
                            return (
                                <NavMenuItem key={(menu && menu.text) || index}
                                             expandMenuName={$expandMenuName}
                                             activatedMenu={$activatedMenu}
                                             options={menu}
                                             expandMenu={expandMenu}
                                             updateActivatedMenu={updateActivatedMenu}/>
                            );
                        })
                    }

        );

    }
}

NavMenuList.propTypes = {

    $navMenu: PropTypes.array,
    $expandMenuName: PropTypes.string,
    $activatedMenu: PropTypes.object,

    expandMenu: PropTypes.func,
    updateActivatedMenu: PropTypes.func

};

function mapStateToProps(state, ownProps) {
    return {
        $navMenu: state.navMenu.menu,
        $expandMenuName: state.navMenu.expandMenuName,
        $activatedMenu: state.navMenu.activatedMenu
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(actions, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(NavMenuList);<commit_msg>prevent body scroll when scroll menu<commit_after>import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';

import * as actions from 'reduxes/actions';

import NavMenuItem from './NavMenuItem';

class NavMenuList extends Component {

    constructor(props) {

        super(props);

        this.wheelHandler = this::this.wheelHandler;

    }

    wheelHandler(e) {

        const {currentTarget, deltaY} = e,
            {clientHeight, scrollHeight, scrollTop} = currentTarget;

        if ((deltaY < 0 && scrollTop <= 0)
            || (deltaY > 0 && scrollTop >= scrollHeight - clientHeight)) {
            e.preventDefault();
        }
    }

    render() {

        const {$navMenu, $expandMenuName, $activatedMenu, expandMenu, updateActivatedMenu} = this.props;

        return (

                    {
                        $navMenu.map((menu, index) => {
                            return (
                                <NavMenuItem key={(menu && menu.text) || index}
                                             expandMenuName={$expandMenuName}
                                             activatedMenu={$activatedMenu}
                                             options={menu}
                                             expandMenu={expandMenu}
                                             updateActivatedMenu={updateActivatedMenu}/>
                            );
                        })
                    }

        );

    }
}

NavMenuList.propTypes = {

    $navMenu: PropTypes.array,
    $expandMenuName: PropTypes.string,
    $activatedMenu: PropTypes.object,

    expandMenu: PropTypes.func,
    updateActivatedMenu: PropTypes.func

};

function mapStateToProps(state, ownProps) {
    return {
        $navMenu: state.navMenu.menu,
        $expandMenuName: state.navMenu.expandMenuName,
        $activatedMenu: state.navMenu.activatedMenu
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(actions, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(NavMenuList);<|endoftext|>


<commit_before>// Globals.
var GM_config = GM_getConfig();
var GM_uninstallQueue = {};
var gUserscriptsView = null;

(function() {
// Override some built-in functions, with a closure reference to the original
// function, to either handle or delegate the call.
var _origShowView = showView;
showView = function(aView) {
  if ('userscripts' == aView) {
    greasemonkeyAddons.showView();
  } else {
    greasemonkeyAddons.hideView();

    // Native code will break us, so hide from it before running it.
    if ('userscripts' == gView) gView = null;

    _origShowView(aView);
  }
};

// Set up an "observer" on the config, to keep the displayed items up to date
// with their actual state.
var observer = {
  notifyEvent: function(script, event, data) {
    if (event == "install") {
      var item = greasemonkeyAddons.addScriptToList(script);
      if (gView == "userscripts") gUserscriptsView.selectedItem = item;
      item.setAttribute('newAddon', 'true');
      return;
    }

    // find the script's node
    var node = document.getElementById('urn:greasemonkey:item:'+script.id);
    if (!node) return;

    switch (event) {
      case "edit-enabled":
        node.setAttribute('isDisabled', !data);
        break;
      case "uninstall":
        gUserscriptsView.removeChild(node);
        break;
      case "move":
        gUserscriptsView.removeChild(node);
        gUserscriptsView.insertBefore(node, gUserscriptsView.childNodes[data]);
        greasemonkeyAddons.reselectLastSelected();
        break;
      case "modified":
        var item = greasemonkeyAddons.listitemForScript(script);
        gUserscriptsView.replaceChild(item, node);
        break;
    }
  }
};

// Set event listeners.
window.addEventListener('load', function() {
  gUserscriptsView = document.getElementById('userscriptsView');
  greasemonkeyAddons.fillList();
  greasemonkeyAddons.fixButtonOrder();

  gUserscriptsView.addEventListener(
      'select', greasemonkeyAddons.updateLastSelected, false);
  gUserscriptsView.addEventListener(
      'keypress', greasemonkeyAddons.onKeypress, false);

  window.addEventListener(
      'dragover', greasemonkeyAddons.onDragOver, false);
  window.addEventListener(
      'drop', greasemonkeyAddons.onDrop, false);

  GM_config.addObserver(observer);

  // Work-around for Stylish compatibility, which does not update gView in
  // its overridden showView() function.
  var stylishRadio = document.getElementById('userstyles-view');
  if (stylishRadio) {
    stylishRadio.addEventListener(
        'command',
        function() {
          greasemonkeyAddons.hideView();
          gView = 'userstyles';
        },
        false);
  }
}, false);

window.addEventListener('unload', function() {
  GM_config.removeObserver(observer);

  for (var id in GM_uninstallQueue) {
    GM_config.uninstall(GM_uninstallQueue[id]);
    delete(GM_uninstallQueue[id]);
  }
  // Guarantee that the config.xml is saved to disk.
  // Todo: This without dipping into private members.
  GM_config._save(true);
}, false);
})();

var greasemonkeyAddons = {
  showView: function() {
    gUserscriptsView = document.getElementById('userscriptsView');
    if ('userscripts' == gView) return;

    document.getElementById('viewGroup')
        .setAttribute('last-selected', 'userscripts');
    var userscriptsRadio = document.getElementById('userscripts-view');
    var viewGroup = document.getElementById("viewGroup");
    viewGroup.selectedItem = userscriptsRadio;
    greasemonkeyAddons.reselectLastSelected();
    gView='userscripts';
    document.documentElement.className += ' userscripts';

    GM_config.updateModifiedScripts();
    gUserscriptsView.focus();
  },

  hideView: function() {
    if ('userscripts' != gView) return;
    document.documentElement.className =
      document.documentElement.className.replace(/ *\buserscripts\b/g, '');
    gExtensionsView.focus();
  },

  urlFromDragEvent: function(event) {
    var types = event.dataTransfer.types;
    var url = null;
    if (types.contains('text/uri-list')) {
      url = event.dataTransfer.mozGetDataAt('text/uri-list', 0);
    } else if (types.contains('application/x-moz-file')) {
      var file = event.dataTransfer
          .mozGetDataAt('application/x-moz-file', 0)
          .QueryInterface(Components.interfaces.nsIFile);
      url = GM_getUriFromFile(file).spec;
    }
    return url;
  },

  onDragOver: function(event) {
    var url = greasemonkeyAddons.urlFromDragEvent(event);
    if (url && url.match(/\.user\.js$/)) {
      // Cancel the default do-not-allow behavior.
      event.preventDefault();
    }
  },

  onDrop: function(event) {
    var uri = GM_uriFromUrl(greasemonkeyAddons.urlFromDragEvent(event));
    // TODO: Make this UI appear attached to addons, rather than the browser?
    GM_installUri(uri);
  },

  updateLastSelected: function() {
    if (!gUserscriptsView.selectedItem) return;
    var userscriptsRadio = document.getElementById('userscripts-view');
    var selectedId = gUserscriptsView.selectedItem.getAttribute('id');
    if (selectedId) {
      userscriptsRadio.setAttribute('last-selected', selectedId);
    }
  },

  fillList: function() {
    // Remove any pre-existing contents.
    while (gUserscriptsView.firstChild) {
      gUserscriptsView.removeChild(gUserscriptsView.firstChild);
    }

    // Add a list item for each script.
    for (var i = 0, script = null; script = GM_config.scripts[i]; i++) {
      greasemonkeyAddons.addScriptToList(script);
    }

    greasemonkeyAddons.reselectLastSelected();
  },

  reselectLastSelected: function() {
    if (!gUserscriptsView) return;

    var userscriptsRadio = document.getElementById('userscripts-view');
    var lastId = userscriptsRadio.getAttribute('last-selected');

    // I have no idea why, but this setTimeout makes it work.
    setTimeout(function() {
          if ('userscripts' == gView) {
            if (lastId) {
              gUserscriptsView.selectedItem = document.getElementById(lastId);
            }
            if (gUserscriptsView.selectedItem) {
              gUserscriptsView.scrollBoxObject
                  .scrollToElement(gUserscriptsView.selectedItem);
            }
          }
        }, 0);
  },

  listitemForScript: function(script) {
    var item = document.createElement('richlistitem');

    // Setting these attributes inherits the values into the same place they
    // would go for extensions.
    item.setAttribute('addonId', script.id);
    item.setAttribute('name', script.name);
    item.setAttribute('description', script.description);
    item.setAttribute('version', script.version);
    item.setAttribute('id', 'urn:greasemonkey:item:'+script.id);
    item.setAttribute('isDisabled', !script.enabled);
    if (script.id in GM_uninstallQueue) {
      item.setAttribute('opType', 'needs-uninstall');
    }

    return item;
  },

  addScriptToList: function(script, beforeNode) {
    var item = greasemonkeyAddons.listitemForScript(script);
    gUserscriptsView.insertBefore(item, beforeNode || null);
    return item;
  },

  findSelectedScript: function() {
    if (!gUserscriptsView.selectedItem) return null;
    var scripts = GM_config.scripts;
    var selectedScriptId = gUserscriptsView.selectedItem.getAttribute('addonId');
    for (var i = 0, script = null; script = scripts[i]; i++) {
      if (selectedScriptId == script.id) {
        return script;
      }
    }
    return null;
  },

  doCommand: function(command) {
    var script = greasemonkeyAddons.findSelectedScript();
    if (!script) {
      dump("greasemonkeyAddons.doCommand() could not find selected script.\n");
      return;
    }

    var selectedListitem = gUserscriptsView.selectedItem;
    switch (command) {
    case 'cmd_userscript_edit':
      GM_openInEditor(script);
      break;
    case 'cmd_userscript_show':
      GM_openFolder(script._file);
      break;
    case 'cmd_userscript_enable':
      script.enabled = true;
      break;
    case 'cmd_userscript_disable':
      script.enabled = false;
      break;
    case 'cmd_userscript_move_down':
      GM_config.move(script, 1);
      break;
    case 'cmd_userscript_move_bottom':
      GM_config.move(script, GM_config.scripts.length);
      break;
    case 'cmd_userscript_move_up':
      GM_config.move(script, -1);
      break;
    case 'cmd_userscript_move_top':
      GM_config.move(script, -1 * GM_config.scripts.length);
      break;
    case 'cmd_userscript_sort':
      function scriptCmp(a, b) {
        return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
      }
      GM_config._scripts.sort(scriptCmp);
      GM_config._save();
      greasemonkeyAddons.fillList();
      greasemonkeyAddons.reselectLastSelected();
      break;
    case 'cmd_userscript_uninstall':
      GM_uninstallQueue[script.id] = script;
      script.needsUninstall = true;
      selectedListitem.setAttribute('opType', 'needs-uninstall');
      break;
    case 'cmd_userscript_uninstall_cancel':
      delete(GM_uninstallQueue[script.id]);
      script.needsUninstall = false;
      selectedListitem.removeAttribute('opType');
      break;
    case 'cmd_userscript_uninstall_now':
      delete(GM_uninstallQueue[script.id]);
      GM_config.uninstall(script);
      break;
    }
  },

  buildContextMenu: function(aEvent) {
    var script = greasemonkeyAddons.findSelectedScript();
    if (!script) {
      dump("greasemonkeyAddons.buildContextMenu() could not find selected script.\n");
      return;
    }

    function $(id) { return document.getElementById(id); }
    function setItemsHidden(hidden, idList) {
      if (idList) {
        var items = idList.map(function(id) {
          return $('userscript_context_' + id);
        });
      } else {
        var items = $('userscriptContextMenu').childNodes;
        items = Array.prototype.slice.call(items);
      }
      items.forEach(function(item) {
        item.setAttribute('hidden', hidden);
      });
    }

    var standardItems = [
      'move_up', 'move_down', 'move_top', 'move_bottom', 'sort',
      'move_separator',
      'edit', 'show',
      'edit_separator',
      'uninstall'];
    var uninstallItems = ['uninstall_now', 'cancelUninstall'];

    // Set everything hidden now, reveal the right selection below.
    setItemsHidden(true);

    var selectedItem = gUserscriptsView.selectedItem;
    if ('needs-uninstall' == selectedItem.getAttribute('opType')) {
      setItemsHidden(false, uninstallItems);
    } else {
      // Set visibility.
      setItemsHidden(false, standardItems);
      setItemsHidden(false, script.enabled ? ['disable'] : ['enable']);
      // Set disabled.
      var atBottom = !selectedItem.nextSibling;
      var atTop = !selectedItem.previousSibling;
      // This setTimeout moves to after whatever black magic is removing
      // these values.
      // Todo: better fix.
      setTimeout(function() {
            setElementDisabledByID('userscript_context_move_up', atTop);
            setElementDisabledByID('userscript_context_move_down', atBottom);
            setElementDisabledByID('userscript_context_move_top', atTop);
            setElementDisabledByID('userscript_context_move_bottom', atBottom);
            setElementDisabledByID('userscript_context_sort', (atTop && atBottom));
          }, 0);
    }
  },

  onKeypress: function(aEvent) {
    var viewGroup = document.getElementById("viewGroup");
    switch (aEvent.keyCode) {
      case aEvent.DOM_VK_LEFT:
      case aEvent.DOM_VK_RIGHT:
        let nextFlag = (aEvent.keyCode == aEvent.DOM_VK_RIGHT);
        if (getComputedStyle(viewGroup, "").direction == "rtl")
          nextFlag = !nextFlag;
        viewGroup.checkAdjacentElement(nextFlag);
        break;
      default:
        return; // don't consume the event
    }
    aEvent.stopPropagation();
    aEvent.preventDefault();
  },

  // See: http://github.com/greasemonkey/greasemonkey/issues/#issue/1149
  // Since every Firefox version/platform has a different order of controls
  // in this dialog, rearrange ours to blend in with that scheme.
  fixButtonOrder: function() {
    function $(id) { return document.getElementById(id); }

    var appInfo = Components
        .classes["@mozilla.org/xre/app-info;1"]
        .getService(Components.interfaces.nsIXULAppInfo);
    var versionChecker = Components
        .classes["@mozilla.org/xpcom/version-comparator;1"]
        .getService(Components.interfaces.nsIVersionComparator);
    var osString = Components
        .classes["@mozilla.org/xre/app-info;1"]
        .getService(Components.interfaces.nsIXULRuntime)
        .OS;

    if (versionChecker.compare(appInfo.version, '3.5') < 0) {
      // All platforms, Firefox 3.0
      $('commandBarBottom').appendChild($('newUserscript'));
    } else if ('WINNT' == osString) {
      if (versionChecker.compare(appInfo.version, '3.6') < 0) {
        // Windows, Firefox 3.5
        $('commandBarBottom').insertBefore(
            $('getMoreUserscripts'), $('newUserscript').nextSibling);
      }
    } else {
      if (versionChecker.compare(appInfo.version, '3.6') < 0) {
        // Mac/Linux, Firefox 3.5
        $('commandBarBottom').insertBefore(
            $('getMoreUserscripts'), $('skipDialogButton'));
      }
      // Mac/Linux, Firefox 3.5 and 3.6
      $('commandBarBottom').insertBefore(
          $('newUserscript'), $('skipDialogButton'));
    }
  }
};
<commit_msg>Repair keyboard navigation for addons.<commit_after>// Globals.
var GM_config = GM_getConfig();
var GM_uninstallQueue = {};
var gUserscriptsView = null;

var GM_firefoxVersion;
var GM_os;
(function() {
var appInfo = Components
    .classes["@mozilla.org/xre/app-info;1"]
    .getService(Components.interfaces.nsIXULAppInfo);
var versionChecker = Components
    .classes["@mozilla.org/xpcom/version-comparator;1"]
    .getService(Components.interfaces.nsIVersionComparator);
var xulRuntime = Components
    .classes["@mozilla.org/xre/app-info;1"]
    .getService(Components.interfaces.nsIXULRuntime);

// Detect fixed possible compatible Firefox versions.
if (versionChecker.compare(appInfo.version, '3.5') < 0) {
  GM_firefoxVersion = '3.0';
} else if (versionChecker.compare(appInfo.version, '3.6') < 0) {
  GM_firefoxVersion = '3.5';
} else {
  GM_firefoxVersion = '3.6';
}

GM_os = xulRuntime.OS;
})();

(function() {
// Override some built-in functions, with a closure reference to the original
// function, to either handle or delegate the call.
var _origShowView = showView;
showView = function(aView) {
  if ('userscripts' == aView) {
    greasemonkeyAddons.showView();
  } else {
    greasemonkeyAddons.hideView();

    // Native code will break us, so hide from it before running it.
    if ('userscripts' == gView) gView = null;

    _origShowView(aView);
  }
};

// Set up an "observer" on the config, to keep the displayed items up to date
// with their actual state.
var observer = {
  notifyEvent: function(script, event, data) {
    if (event == "install") {
      var item = greasemonkeyAddons.addScriptToList(script);
      if (gView == "userscripts") gUserscriptsView.selectedItem = item;
      item.setAttribute('newAddon', 'true');
      return;
    }

    // find the script's node
    var node = document.getElementById('urn:greasemonkey:item:'+script.id);
    if (!node) return;

    switch (event) {
      case "edit-enabled":
        node.setAttribute('isDisabled', !data);
        break;
      case "uninstall":
        gUserscriptsView.removeChild(node);
        break;
      case "move":
        gUserscriptsView.removeChild(node);
        gUserscriptsView.insertBefore(node, gUserscriptsView.childNodes[data]);
        greasemonkeyAddons.reselectLastSelected();
        break;
      case "modified":
        var item = greasemonkeyAddons.listitemForScript(script);
        gUserscriptsView.replaceChild(item, node);
        break;
    }
  }
};

// Set event listeners.
window.addEventListener('load', function() {
  gUserscriptsView = document.getElementById('userscriptsView');
  greasemonkeyAddons.fillList();
  greasemonkeyAddons.fixButtonOrder();

  gUserscriptsView.addEventListener(
      'select', greasemonkeyAddons.updateLastSelected, false);
  if ('3.6' == GM_firefoxVersion) {
    gUserscriptsView.addEventListener(
        'keypress', greasemonkeyAddons.onKeypress, false);
  }

  window.addEventListener(
      'dragover', greasemonkeyAddons.onDragOver, false);
  window.addEventListener(
      'drop', greasemonkeyAddons.onDrop, false);

  GM_config.addObserver(observer);

  // Work-around for Stylish compatibility, which does not update gView in
  // its overridden showView() function.
  var stylishRadio = document.getElementById('userstyles-view');
  if (stylishRadio) {
    stylishRadio.addEventListener(
        'command',
        function() {
          greasemonkeyAddons.hideView();
          gView = 'userstyles';
        },
        false);
  }
}, false);

window.addEventListener('unload', function() {
  GM_config.removeObserver(observer);

  for (var id in GM_uninstallQueue) {
    GM_config.uninstall(GM_uninstallQueue[id]);
    delete(GM_uninstallQueue[id]);
  }
  // Guarantee that the config.xml is saved to disk.
  // Todo: This without dipping into private members.
  GM_config._save(true);
}, false);
})();

var greasemonkeyAddons = {
  showView: function() {
    gUserscriptsView = document.getElementById('userscriptsView');
    if ('userscripts' == gView) return;

    document.getElementById('viewGroup')
        .setAttribute('last-selected', 'userscripts');
    var userscriptsRadio = document.getElementById('userscripts-view');
    var viewGroup = document.getElementById("viewGroup");
    viewGroup.selectedItem = userscriptsRadio;
    greasemonkeyAddons.reselectLastSelected();
    gView='userscripts';
    document.documentElement.className += ' userscripts';

    GM_config.updateModifiedScripts();
    if ('3.6' == GM_firefoxVersion) gUserscriptsView.focus();
  },

  hideView: function() {
    if ('userscripts' != gView) return;
    document.documentElement.className =
      document.documentElement.className.replace(/ *\buserscripts\b/g, '');
    if ('3.6' == GM_firefoxVersion) gExtensionsView.focus();
  },

  urlFromDragEvent: function(event) {
    var types = event.dataTransfer.types;
    var url = null;
    if (types.contains('text/uri-list')) {
      url = event.dataTransfer.mozGetDataAt('text/uri-list', 0);
    } else if (types.contains('application/x-moz-file')) {
      var file = event.dataTransfer
          .mozGetDataAt('application/x-moz-file', 0)
          .QueryInterface(Components.interfaces.nsIFile);
      url = GM_getUriFromFile(file).spec;
    }
    return url;
  },

  onDragOver: function(event) {
    var url = greasemonkeyAddons.urlFromDragEvent(event);
    if (url && url.match(/\.user\.js$/)) {
      // Cancel the default do-not-allow behavior.
      event.preventDefault();
    }
  },

  onDrop: function(event) {
    var uri = GM_uriFromUrl(greasemonkeyAddons.urlFromDragEvent(event));
    // TODO: Make this UI appear attached to addons, rather than the browser?
    GM_installUri(uri);
  },

  updateLastSelected: function() {
    if (!gUserscriptsView.selectedItem) return;
    var userscriptsRadio = document.getElementById('userscripts-view');
    var selectedId = gUserscriptsView.selectedItem.getAttribute('id');
    if (selectedId) {
      userscriptsRadio.setAttribute('last-selected', selectedId);
    }
  },

  fillList: function() {
    // Remove any pre-existing contents.
    while (gUserscriptsView.firstChild) {
      gUserscriptsView.removeChild(gUserscriptsView.firstChild);
    }

    // Add a list item for each script.
    for (var i = 0, script = null; script = GM_config.scripts[i]; i++) {
      greasemonkeyAddons.addScriptToList(script);
    }

    greasemonkeyAddons.reselectLastSelected();
  },

  reselectLastSelected: function() {
    if (!gUserscriptsView) return;

    var userscriptsRadio = document.getElementById('userscripts-view');
    var lastId = userscriptsRadio.getAttribute('last-selected');

    // I have no idea why, but this setTimeout makes it work.
    setTimeout(function() {
          if ('userscripts' == gView) {
            if (lastId) {
              gUserscriptsView.selectedItem = document.getElementById(lastId);
            }
            if (gUserscriptsView.selectedItem) {
              gUserscriptsView.scrollBoxObject
                  .scrollToElement(gUserscriptsView.selectedItem);
            }
          }
        }, 0);
  },

  listitemForScript: function(script) {
    var item = document.createElement('richlistitem');

    // Setting these attributes inherits the values into the same place they
    // would go for extensions.
    item.setAttribute('addonId', script.id);
    item.setAttribute('name', script.name);
    item.setAttribute('description', script.description);
    item.setAttribute('version', script.version);
    item.setAttribute('id', 'urn:greasemonkey:item:'+script.id);
    item.setAttribute('isDisabled', !script.enabled);
    if (script.id in GM_uninstallQueue) {
      item.setAttribute('opType', 'needs-uninstall');
    }

    return item;
  },

  addScriptToList: function(script, beforeNode) {
    var item = greasemonkeyAddons.listitemForScript(script);
    gUserscriptsView.insertBefore(item, beforeNode || null);
    return item;
  },

  findSelectedScript: function() {
    if (!gUserscriptsView.selectedItem) return null;
    var scripts = GM_config.scripts;
    var selectedScriptId = gUserscriptsView.selectedItem.getAttribute('addonId');
    for (var i = 0, script = null; script = scripts[i]; i++) {
      if (selectedScriptId == script.id) {
        return script;
      }
    }
    return null;
  },

  doCommand: function(command) {
    var script = greasemonkeyAddons.findSelectedScript();
    if (!script) {
      dump("greasemonkeyAddons.doCommand() could not find selected script.\n");
      return;
    }

    var selectedListitem = gUserscriptsView.selectedItem;
    switch (command) {
    case 'cmd_userscript_edit':
      GM_openInEditor(script);
      break;
    case 'cmd_userscript_show':
      GM_openFolder(script._file);
      break;
    case 'cmd_userscript_enable':
      script.enabled = true;
      break;
    case 'cmd_userscript_disable':
      script.enabled = false;
      break;
    case 'cmd_userscript_move_down':
      GM_config.move(script, 1);
      break;
    case 'cmd_userscript_move_bottom':
      GM_config.move(script, GM_config.scripts.length);
      break;
    case 'cmd_userscript_move_up':
      GM_config.move(script, -1);
      break;
    case 'cmd_userscript_move_top':
      GM_config.move(script, -1 * GM_config.scripts.length);
      break;
    case 'cmd_userscript_sort':
      function scriptCmp(a, b) {
        return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
      }
      GM_config._scripts.sort(scriptCmp);
      GM_config._save();
      greasemonkeyAddons.fillList();
      greasemonkeyAddons.reselectLastSelected();
      break;
    case 'cmd_userscript_uninstall':
      GM_uninstallQueue[script.id] = script;
      script.needsUninstall = true;
      selectedListitem.setAttribute('opType', 'needs-uninstall');
      break;
    case 'cmd_userscript_uninstall_cancel':
      delete(GM_uninstallQueue[script.id]);
      script.needsUninstall = false;
      selectedListitem.removeAttribute('opType');
      break;
    case 'cmd_userscript_uninstall_now':
      delete(GM_uninstallQueue[script.id]);
      GM_config.uninstall(script);
      break;
    }
  },

  buildContextMenu: function(aEvent) {
    var script = greasemonkeyAddons.findSelectedScript();
    if (!script) {
      dump("greasemonkeyAddons.buildContextMenu() could not find selected script.\n");
      return;
    }

    function $(id) { return document.getElementById(id); }
    function setItemsHidden(hidden, idList) {
      if (idList) {
        var items = idList.map(function(id) {
          return $('userscript_context_' + id);
        });
      } else {
        var items = $('userscriptContextMenu').childNodes;
        items = Array.prototype.slice.call(items);
      }
      items.forEach(function(item) {
        item.setAttribute('hidden', hidden);
      });
    }

    var standardItems = [
      'move_up', 'move_down', 'move_top', 'move_bottom', 'sort',
      'move_separator',
      'edit', 'show',
      'edit_separator',
      'uninstall'];
    var uninstallItems = ['uninstall_now', 'cancelUninstall'];

    // Set everything hidden now, reveal the right selection below.
    setItemsHidden(true);

    var selectedItem = gUserscriptsView.selectedItem;
    if ('needs-uninstall' == selectedItem.getAttribute('opType')) {
      setItemsHidden(false, uninstallItems);
    } else {
      // Set visibility.
      setItemsHidden(false, standardItems);
      setItemsHidden(false, script.enabled ? ['disable'] : ['enable']);
      // Set disabled.
      var atBottom = !selectedItem.nextSibling;
      var atTop = !selectedItem.previousSibling;
      // This setTimeout moves to after whatever black magic is removing
      // these values.
      // Todo: better fix.
      setTimeout(function() {
            setElementDisabledByID('userscript_context_move_up', atTop);
            setElementDisabledByID('userscript_context_move_down', atBottom);
            setElementDisabledByID('userscript_context_move_top', atTop);
            setElementDisabledByID('userscript_context_move_bottom', atBottom);
            setElementDisabledByID('userscript_context_sort', (atTop && atBottom));
          }, 0);
    }
  },

  onKeypress: function(aEvent) {
    var viewGroup = document.getElementById("viewGroup");
    switch (aEvent.keyCode) {
      case aEvent.DOM_VK_LEFT:
      case aEvent.DOM_VK_RIGHT:
        let nextFlag = (aEvent.keyCode == aEvent.DOM_VK_RIGHT);
        if (getComputedStyle(viewGroup, "").direction == "rtl")
          nextFlag = !nextFlag;
        viewGroup.checkAdjacentElement(nextFlag);
        break;
      default:
        return; // don't consume the event
    }
    aEvent.stopPropagation();
    aEvent.preventDefault();
  },

  // See: http://github.com/greasemonkey/greasemonkey/issues/#issue/1149
  // Since every Firefox version/platform has a different order of controls
  // in this dialog, rearrange ours to blend in with that scheme.
  fixButtonOrder: function() {
    function $(id) { return document.getElementById(id); }

    if ('3.0' == GM_firefoxVersion) {
      // All platforms, Firefox 3.0
      $('commandBarBottom').appendChild($('newUserscript'));
    } else if ('WINNT' == GM_os) {
      if ('3.5' == GM_firefoxVersion) {
        // Windows, Firefox 3.5
        $('commandBarBottom').insertBefore(
            $('getMoreUserscripts'), $('newUserscript').nextSibling);
      }
    } else {
      if ('3.5' == GM_firefoxVersion) {
        // Mac/Linux, Firefox 3.5
        $('commandBarBottom').insertBefore(
            $('getMoreUserscripts'), $('skipDialogButton'));
      }
      // Mac/Linux, Firefox 3.5 and 3.6
      $('commandBarBottom').insertBefore(
          $('newUserscript'), $('skipDialogButton'));
    }
  }
};
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Frank Breedijk
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
steal(
	'jquery/controller',
	'jquery/view/ejs',
	'jquery/controller/view',
	'jquery/dom/form_params',
	'seccubus/models',
	'seccubus/finding/table',
	'seccubus/severity/select'
).then( './views/init.ejs',
function($){

/**
 * @class Seccubus.Issue.Edit
 * @parent Issue
 * @inherits jQuery.Controller
 * Generates an dialog to show/edit one or more issues
 *
 * Story
 * -----
 *  As a user I would like to be able to have a detailed view and edit
 *  posibility for issues
 */
$.Controller('Seccubus.Issue.Edit',
/** @Static */
{
	/*
	 * @attribute options
	 * Object that contains the options
	 */
	defaults : {
		/* @attribute options.issues
		 * Issue object to edit
		 */
		issue : null,
		/* @attribute options.findings
		 * jQuery query that defines where the findings table will be displayed
		 * Default : null
		 * If this attribute is null there will be no history displayed
		 */
		findings : null,
		/* @attribute options.workspace
		 * Id of the current workspace
		 */
		workspace : -1,
		/* @attribute options.onClear
		 * Function that is called when the cancel button is clicked
		 */
		onClear : function() {
			console.warn("Seccubus.Issue.Edit onClear function called but not set");
		}

	}
},
/** @Prototype */
{
	init : function(){
		this.updateView();
	},
	updateView : function() {
		if ( this.options.workspace == -1 ) {
			alert("Seccubus.Issues.Edit : Workspace not set");
		} else if ( this.options.issue == null ) {
			alert("Seccubus.Issues.Edit : Issue not set");
		} else {
			this.element.html(
				this.view(
					'init',
					this.options.issue
				)
			);
			$('#editIssueSeverity').seccubus_severity_select({
				selected : this.options.issue.severity
			});
		}

		if ( this.options.findings != null ) {
			/* Display the findings for this issue */
			$(this.options.findings).seccubus_finding_table({
				workspace	: this.options.workspace,
				issue		: this.options.issue.id,
				noLink 		: true,
				status 		: "*",
				columns		: [
					"host", "IP",
					"hostName", "HostName",
					"port", "Port",
					"plugin", "Plugin",
					"scanName","ScanName",
					"severity", "Severity",
					"find", "Finding",
					"remark", "Remark",
					"status", "Status",
					"", "Action"
				],
				noEdit		: true,
				noLink		: true,
				noFindingUnlink
							: false,
				noIssueUnlink
							: true
			});
		}
	},
	".editSetStatus click" : function(el,ev) {
		ev.preventDefault();

		var newState = $(el).attr("newstatus");
		var param = this.element.formParams();
		var issue = this.options.issue;

		// Check form
		var ok = true;
		var elements = [];
		if ( param.name == '' ) {
			elements.push("#editIssueName");
			ok = false;
		}

		if ( ok ) {
			issue.attr("name",param.name);
			issue.attr("description",param.description);
			issue.attr("ext_ref",param.ext_ref);
			issue.attr("status",newState)
			issue.attr("workspaceId",this.options.workspace);
			issue.attr("issueId",issue.id);
			issue.attr("severity",param.severity);
			issue.save();
			this.options.onClear();
		} else {
			this.nok(elements);
		}
	},
	nok : function(elements) {
		this.element.children(".nok").removeClass("nok");
		for(i=0;i<elements.length;i++) {
			$(elements[i]).addClass("nok");
		}
		this.element.css({position : "absolute"});
		this.element.animate({left : '+=10'},100);
		this.element.animate({left : '-=20'},100);
		this.element.animate({left : '+=20'},100);
		this.element.animate({left : '-=20'},100);
		this.element.animate({left : '+=20'},100);
		this.element.animate({left : '-=10'},100);
		this.element.css({position : "relative"});
	},
	/*
	".move click" : function(el,ev) {
		ev.preventDefault();
		this.options.index = $(el).attr("index");
		this.updateView();
	},
	*/
	"{Seccubus.Models.Issue} updated" : function(Issue, ev, issue) {
		this.updateView();
	},
	/*
	 * Update, overloaded to reder the control after and update even
	 */
	// Autoclear nok status
	".nok change" : function(el) {
		el.removeClass("nok");
	},
	".cancel click" : function(el, ev) {
		ev.preventDefault();
		this.options.onClear();
	},
	update : function(options) {
		this._super(options);
		this.updateView();
	}
})

});
<commit_msg>Copyright fix<commit_after>/*
 * Copyright 2016 Frank Breedijk
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
steal(
	'jquery/controller',
	'jquery/view/ejs',
	'jquery/controller/view',
	'jquery/dom/form_params',
	'seccubus/models',
	'seccubus/finding/table',
	'seccubus/severity/select'
).then( './views/init.ejs',
function($){

/**
 * @class Seccubus.Issue.Edit
 * @parent Issue
 * @inherits jQuery.Controller
 * Generates an dialog to show/edit one or more issues
 *
 * Story
 * -----
 *  As a user I would like to be able to have a detailed view and edit
 *  posibility for issues
 */
$.Controller('Seccubus.Issue.Edit',
/** @Static */
{
	/*
	 * @attribute options
	 * Object that contains the options
	 */
	defaults : {
		/* @attribute options.issues
		 * Issue object to edit
		 */
		issue : null,
		/* @attribute options.findings
		 * jQuery query that defines where the findings table will be displayed
		 * Default : null
		 * If this attribute is null there will be no history displayed
		 */
		findings : null,
		/* @attribute options.workspace
		 * Id of the current workspace
		 */
		workspace : -1,
		/* @attribute options.onClear
		 * Function that is called when the cancel button is clicked
		 */
		onClear : function() {
			console.warn("Seccubus.Issue.Edit onClear function called but not set");
		}

	}
},
/** @Prototype */
{
	init : function(){
		this.updateView();
	},
	updateView : function() {
		if ( this.options.workspace == -1 ) {
			alert("Seccubus.Issues.Edit : Workspace not set");
		} else if ( this.options.issue == null ) {
			alert("Seccubus.Issues.Edit : Issue not set");
		} else {
			this.element.html(
				this.view(
					'init',
					this.options.issue
				)
			);
			$('#editIssueSeverity').seccubus_severity_select({
				selected : this.options.issue.severity
			});
		}

		if ( this.options.findings != null ) {
			/* Display the findings for this issue */
			$(this.options.findings).seccubus_finding_table({
				workspace	: this.options.workspace,
				issue		: this.options.issue.id,
				noLink 		: true,
				status 		: "*",
				columns		: [
					"host", "IP",
					"hostName", "HostName",
					"port", "Port",
					"plugin", "Plugin",
					"scanName","ScanName",
					"severity", "Severity",
					"find", "Finding",
					"remark", "Remark",
					"status", "Status",
					"", "Action"
				],
				noEdit		: true,
				noLink		: true,
				noFindingUnlink
							: false,
				noIssueUnlink
							: true
			});
		}
	},
	".editSetStatus click" : function(el,ev) {
		ev.preventDefault();

		var newState = $(el).attr("newstatus");
		var param = this.element.formParams();
		var issue = this.options.issue;

		// Check form
		var ok = true;
		var elements = [];
		if ( param.name == '' ) {
			elements.push("#editIssueName");
			ok = false;
		}

		if ( ok ) {
			issue.attr("name",param.name);
			issue.attr("description",param.description);
			issue.attr("ext_ref",param.ext_ref);
			issue.attr("status",newState)
			issue.attr("workspaceId",this.options.workspace);
			issue.attr("issueId",issue.id);
			issue.attr("severity",param.severity);
			issue.save();
			this.options.onClear();
		} else {
			this.nok(elements);
		}
	},
	nok : function(elements) {
		this.element.children(".nok").removeClass("nok");
		for(i=0;i<elements.length;i++) {
			$(elements[i]).addClass("nok");
		}
		this.element.css({position : "absolute"});
		this.element.animate({left : '+=10'},100);
		this.element.animate({left : '-=20'},100);
		this.element.animate({left : '+=20'},100);
		this.element.animate({left : '-=20'},100);
		this.element.animate({left : '+=20'},100);
		this.element.animate({left : '-=10'},100);
		this.element.css({position : "relative"});
	},
	/*
	".move click" : function(el,ev) {
		ev.preventDefault();
		this.options.index = $(el).attr("index");
		this.updateView();
	},
	*/
	"{Seccubus.Models.Issue} updated" : function(Issue, ev, issue) {
		this.updateView();
	},
	/*
	 * Update, overloaded to reder the control after and update even
	 */
	// Autoclear nok status
	".nok change" : function(el) {
		el.removeClass("nok");
	},
	".cancel click" : function(el, ev) {
		ev.preventDefault();
		this.options.onClear();
	},
	update : function(options) {
		this._super(options);
		this.updateView();
	}
})

});
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 License, v. 2.0. If a copy of the MPL was not distributed with this
 file, You can obtain one at http://mozilla.org/MPL/2.0/. */

var CMD = (function() {
  /* Wifi cmds */
  var CMD_MANAGE_DEVICE    = 'manageDevice';

  var CMD_DEVICE_GETINFO   = 'getdeviceinfo';

  /* Contacts cmds */
  var CMD_GET_ALL_CONTACTS = 'getAllContacts';
  var CMD_UPDATE_CONTACTS  = 'updateContacts';
  var CMD_ADD_CONTACTS     = 'addContacts';
  var CMD_REMOVE_CONTACTS  = 'removeContacts';

  var CMD_SMS_GETMESSAGES  = 'getMessages';
  var CMD_SMS_SENTMESSAGE  = 'sendsms';
  var CMD_SMS_MARK_READ    = 'markMessagesRead';
  var CMD_SMS_DELETE       = 'deletesms';

  var CMD_PIC_GETALLINFO   = 'getAllPicsInfo';
  var CMD_PIC_GETCONTENT   = 'getPics';
  var CMD_PIC_DELETE       = 'deletePics';
  var CMD_PIC_ADD          = 'addPics';
  var CMD_PIC_RENAME       = 'renamePic';

  /**
   * Return function with three parameters:
   *  - data
   *    the data object will be sent
   *  - onresponse
   *    the callback function when response is back
   *  - onerror
   *    the callback function when error occurs
   */
  function createCommand(target, command) {
    return function(data, onresponse, onerror) {
      FFOSAssistant.sendRequest({
        target: target,
        command: command,
        data: data
      }, onresponse, onerror);
    };
  }

  /**
   * Return function only with onresponse and onerror callbacks
   */
  function createCommandWithNonData(target, command) {
    return function(onresponse, onerror) {
      FFOSAssistant.sendRequest({
        target: target,
        command: command,
        data: null
      }, onresponse, onerror);
    };
  }

  /**
   * All the available commands grouped by target.
   */
  return {
    manageDevice:      createCommand('init', CMD_MANAGE_DEVICE),

    Device: {
      /**
       * get the summary info of the device
       */
      getDeviceInfo:   createCommandWithNonData('device', CMD_DEVICE_GETINFO),
    },

    /***** Contacts commands *****/
    Contacts: {
      getAllContacts:  createCommandWithNonData('contact', CMD_GET_ALL_CONTACTS),
      /**
       * data:
       *   contact array
       */
      updateContacts:  createCommand('contact', CMD_UPDATE_CONTACTS),
      /**
       * data:
       *   contact array
       */
      addContacts:     createCommand('contact', CMD_ADD_CONTACTS),
      /**
       * data:
       *   contact id array
       */
      removeContacts:  createCommand('contact', CMD_REMOVE_CONTACTS),
    },

    /***** Picture commands ******/
    Pictures: {
      getAllPicsInfo:  createCommandWithNonData('pictures', CMD_PIC_GETALLINFO),
      /**
       * data:
       *   [fileName1, fileName2]
       */
      getPicsContent:  createCommand('pictures', CMD_PIC_GETCONTENT),
      /**
       * data:
       *   [fileName1, fileName2]
       */
      deletePics:      createCommand('pictures', CMD_PIC_DELETE),
      /**
       * data:
       *   [{
       *     fileName1: content
       *   }, {
       *     fileName2: content
       *   }]
       */
      addPics:         createCommand('pictures'. CMD_PIC_ADD),
      /**
       * data:
       *   [oldName, newName]
       */
      renamePic:       createCommand('pictures'. CMD_PIC_RENAME),
    },

    /***** SMS commands *****/
    SMS: {
      /**
       * data:
       *   SMS Filter
       */
      getMessages:    createCommand('sms', CMD_SMS_GETMESSAGES),
      /**
       * data:
       *   {
       *     id: ['10086', '10010'],
       *     message: 'Here is the message content'
       *   }
       */
      sendMessage:     createCommand('sms', CMD_SMS_SENTMESSAGE),
      /**
       * data:
       *   {
       *     id: [id1, id2],
       *     readbool: true   // or false
       *   }
       */
      markMessageRead: createCommand('sms', CMD_SMS_MARK_READ),
      /**
       * data:
       *   [id1, id2]
       */
      deleteMessages:  createCommand('sms', CMD_SMS_DELETE)
    }
  };
})();

<commit_msg>Rename command name<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 License, v. 2.0. If a copy of the MPL was not distributed with this
 file, You can obtain one at http://mozilla.org/MPL/2.0/. */

var CMD = (function() {
  /* Wifi cmds */
  var CMD_MANAGE_DEVICE    = 'manageDevice';

  var CMD_DEVICE_GETINFO   = 'getdeviceinfo';

  /* Contacts cmds */
  var CMD_CONTACT_GET_ALL  = 'getAllContacts';
  var CMD_CONTACT_UPDATE   = 'updateContacts';
  var CMD_CONTACT_ADD      = 'addContacts';
  var CMD_CONTACT_REMOVE   = 'removeContacts';

  var CMD_SMS_GETMESSAGES  = 'getMessages';
  var CMD_SMS_SENTMESSAGE  = 'sendsms';
  var CMD_SMS_MARK_READ    = 'markMessagesRead';
  var CMD_SMS_DELETE       = 'deletesms';

  var CMD_PIC_GETALLINFO   = 'getAllPicsInfo';
  var CMD_PIC_GETCONTENT   = 'getPics';
  var CMD_PIC_DELETE       = 'deletePics';
  var CMD_PIC_ADD          = 'addPics';
  var CMD_PIC_RENAME       = 'renamePic';

  /**
   * Return function with three parameters:
   *  - data
   *    the data object will be sent
   *  - onresponse
   *    the callback function when response is back
   *  - onerror
   *    the callback function when error occurs
   */
  function createCommand(target, command) {
    return function(data, onresponse, onerror) {
      FFOSAssistant.sendRequest({
        target: target,
        command: command,
        data: data
      }, onresponse, onerror);
    };
  }

  /**
   * Return function only with onresponse and onerror callbacks
   */
  function createCommandWithNonData(target, command) {
    return function(onresponse, onerror) {
      FFOSAssistant.sendRequest({
        target: target,
        command: command,
        data: null
      }, onresponse, onerror);
    };
  }

  /**
   * All the available commands grouped by target.
   */
  return {
    manageDevice:      createCommand('init', CMD_MANAGE_DEVICE),

    Device: {
      /**
       * get the summary info of the device
       */
      getDeviceInfo:   createCommandWithNonData('device', CMD_DEVICE_GETINFO),
    },

    /***** Contacts commands *****/
    Contacts: {
      getAllContacts:  createCommandWithNonData('contact', CMD_CONTACT_GET_ALL),
      /**
       * data:
       *   contact array
       */
      updateContacts:  createCommand('contact', CMD_CONTACT_UPDATE),
      /**
       * data:
       *   contact array
       */
      addContacts:     createCommand('contact', CMD_CONTACT_ADD),
      /**
       * data:
       *   contact id array
       */
      removeContacts:  createCommand('contact', CMD_CONTACT_REMOVE),
    },

    /***** Picture commands ******/
    Pictures: {
      getAllPicsInfo:  createCommandWithNonData('pictures', CMD_PIC_GETALLINFO),
      /**
       * data:
       *   [fileName1, fileName2]
       */
      getPicsContent:  createCommand('pictures', CMD_PIC_GETCONTENT),
      /**
       * data:
       *   [fileName1, fileName2]
       */
      deletePics:      createCommand('pictures', CMD_PIC_DELETE),
      /**
       * data:
       *   [{
       *     fileName1: content
       *   }, {
       *     fileName2: content
       *   }]
       */
      addPics:         createCommand('pictures'. CMD_PIC_ADD),
      /**
       * data:
       *   [oldName, newName]
       */
      renamePic:       createCommand('pictures'. CMD_PIC_RENAME),
    },

    /***** SMS commands *****/
    SMS: {
      /**
       * data:
       *   SMS Filter
       */
      getMessages:    createCommand('sms', CMD_SMS_GETMESSAGES),
      /**
       * data:
       *   {
       *     id: ['10086', '10010'],
       *     message: 'Here is the message content'
       *   }
       */
      sendMessage:     createCommand('sms', CMD_SMS_SENTMESSAGE),
      /**
       * data:
       *   {
       *     id: [id1, id2],
       *     readbool: true   // or false
       *   }
       */
      markMessageRead: createCommand('sms', CMD_SMS_MARK_READ),
      /**
       * data:
       *   [id1, id2]
       */
      deleteMessages:  createCommand('sms', CMD_SMS_DELETE)
    }
  };
})();

<|endoftext|>