<commit_before>// Copyright Jesus Perez <jesusprubio gmail com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

'use strict';

const utils = require('./');

const grammar = {
  versionRE: /(\d{1,2}(\.\d{1,2})?(\.\d{1,2}})?)/,
  portRE: /\d{2,5}/,
  portRangeRE: /(\d{1,5})-(\d{1,5})/,
  extRE: /\d{1,10}/,
  extRangeRE: /\d{1,10}-\d{1,10}/,
  userRE: /User\-Agent:/i,
  serverRE: /Server:/i,
  orgRE: /Organization:/i,
  codeLineRE: /SIP\/2.0/,
  codeRE: /\d{3}/,
  fileRE: /\.txt/,
  authRE: /WWW-Authenticate:/i,
  authProxyRE: /Proxy-Authenticate:/i,
  realmRE: /realm/i,
  nonceRE: /nonce/i,
  httpRE: /http:\/\//,
};

function splitMsg(msg) {
  return msg.toString().split('\r\n');
}

// It parses "User-Agent" string from a packet.
module.exports.userAgent = pkt => {
  const userLine = utils.filter(splitMsg(pkt), line => grammar.userRE.test(line));

  if (userLine[0]) { return (userLine[0]).split(':')[1]; }

  return null;
};

module.exports.code = pkt => {
  const codeLine = utils.filter(splitMsg(pkt), line => grammar.codeLineRE.test(line));

  if (codeLine[0]) { return (codeLine[0]).match(grammar.codeRE)[0]; }

  return null;
};

// It parses "Server" string from a packet.
module.exports.server = pkt => {
  const serverLine = utils.filter(splitMsg(pkt), line => { grammar.serverRE.test(line); });

  if (serverLine[0]) { return (serverLine[0]).split(':')[1]; }

  return null;
};

// It parses "Organization" string from a packet.
module.exports.organization = pkt => {
  const orgLine = utils.filter(splitMsg(pkt), line => grammar.orgRE.test(line));

  if (orgLine[0]) { return (orgLine[0]).split(':')[1]; }

  return null;
};

// It parses the service from a string.
module.exports.service = fprint => {
  let service;
  let cutString;

  // TODO: Refactor this
  const match = /fpbx/i.test(fprint.toString());
  if (match) {
    service = 'FreePBX';
  } else {
    cutString = fprint.split(' ');
    if (cutString[2]) {
      service = cutString[1];
    } else {
      cutString = fprint.split('-');
      if (cutString[1]) {
        service = cutString[0];
      } else {
        cutString = fprint.split('/');
        if (cutString[1]) {
          service = cutString[0];
        } else {
          service = fprint;
        }
      }
    }
  }

  return service;
};

// It parses the service version from a string.
module.exports.version = fprint => {
  if (fprint && fprint.match(grammar.versionRE) &&
      ((fprint.match(grammar.versionRE))[0])) {
    return (fprint.match(grammar.versionRE))[0];
  }

  return null;
};

function parseAuth(line) {
  // It should appears only once
  return (grammar.authRE.test(line) || grammar.authProxyRE.test(line))[0];
}

module.exports.realmNonce = pkt => {
  const splittedMsg = splitMsg(pkt);
  let isProxy = false;
  let authLine = utils.filter(splittedMsg, parseAuth);
  let authSplit;
  let nonce;
  let realm;

  if (grammar.authProxyRE.test(authLine)) { isProxy = true; }
  if (!authLine) {
  // Deleting "Proxy-Authenticate" or "WWW-Authenticate" from the string.
    if (isProxy) {
      authLine = authLine.slice(20);
    } else {
      authLine = authLine.slice(18);
    }
    authSplit = authLine.split(',');

    for (let i = 0; i < authSplit.length; i++) {
      if (grammar.realmRE.test(authSplit[i])) {
        realm = (authSplit[i].split('='))[1].slice(1, -1);
      }
      if (grammar.nonceRE.test(authSplit[i])) {
        nonce = (authSplit[i].split('='))[1].slice(1, -1);
      }
    }

    return { realm, nonce, isProxy };
  }

  return null;
};
<commit_msg>We still don't need this.<commit_after><|endoftext|>


<commit_before>import tap from 'component-tap-event'

const HAS_WINDOWS = typeof window !== 'undefined'
const HAS_NAVIGATOR = typeof navigator !== 'undefined'
const IS_TOUCH =
  HAS_WINDOWS && ('ontouchstart' in window || (HAS_NAVIGATOR && navigator.msMaxTouchPoints > 0))
const EVENTS = IS_TOUCH ? ['touchstart'] : ['click']
const IDENTITY = (item) => item

const directive = {
  instances: [],
}

function processDirectiveArguments(bindingValue) {
  const isFunction = typeof bindingValue === 'function'
  if (!isFunction && typeof bindingValue !== 'object') {
    throw new Error('v-click-outside: Binding value must be a function or an object')
  }

  return {
    handler: isFunction ? bindingValue : bindingValue.handler,
    middleware: bindingValue.middleware || IDENTITY,
    events: bindingValue.events || EVENTS,
    isActive: !(bindingValue.isActive === false),
  }
}

function onEvent({ el, event, handler, middleware }) {
  const isClickOutside = event.target !== el && !el.contains(event.target)

  if (!isClickOutside) {
    return
  }

  if (middleware(event, el)) {
    handler(event, el)
  }
}

function createInstance({ el, events, handler, middleware }) {
  return {
    el,
    eventHandlers: events.map((eventName) => {
      const eventHandler = {
        event: eventName,
        handler: (event) => onEvent({ event, el, handler, middleware }),
      }

      if (IS_TOUCH) {
        eventHandler.handler = tap(eventHandler.handler)
      }

      return eventHandler
    }),
  }
}

function removeInstance(el) {
  const instanceIndex = directive.instances.findIndex((instance) => instance.el === el)
  if (instanceIndex === -1) {
    // Note: This can happen when active status changes from false to false
    return
  }

  const instance = directive.instances[instanceIndex]

  instance.eventHandlers.forEach(({ event, handler }) =>
    document.removeEventListener(event, handler),
  )

  directive.instances.splice(instanceIndex, 1)
}

function bind(el, { value }) {
  const { events, handler, middleware, isActive } = processDirectiveArguments(value)

  if (!isActive) {
    return
  }

  const instance = createInstance({ el, events, handler, middleware })

  instance.eventHandlers.forEach(({ event, handler }) =>
    setTimeout(() => document.addEventListener(event, handler), 0),
  )
  directive.instances.push(instance)
}

function update(el, { value, oldValue }) {
  if (JSON.stringify(value) === JSON.stringify(oldValue)) {
    return
  }

  const { events, handler, middleware, isActive } = processDirectiveArguments(value)

  if (!isActive) {
    removeInstance(el)
    return
  }

  let instance = directive.instances.find((instance) => instance.el === el)

  if (instance) {
    instance.eventHandlers.forEach(({ event, handler }) =>
      document.removeEventListener(event, handler),
    )
    instance.eventHandlers = events.map((eventName) => ({
      event: eventName,
      handler: (event) => onEvent({ event, el, handler, middleware }),
    }))
  } else {
    instance = createInstance({ el, events, handler, middleware })
    directive.instances.push(instance)
  }

  instance.eventHandlers.forEach(({ event, handler }) =>
    setTimeout(() => document.addEventListener(event, handler), 0),
  )
}

directive.bind = bind
directive.update = update
directive.unbind = removeInstance

export default directive
<commit_msg>Revert "properly wrap the actual event handler in the tap function"<commit_after>import tap from 'component-tap-event'

const HAS_WINDOWS = typeof window !== 'undefined'
const HAS_NAVIGATOR = typeof navigator !== 'undefined'
const IS_TOUCH =
  HAS_WINDOWS && ('ontouchstart' in window || (HAS_NAVIGATOR && navigator.msMaxTouchPoints > 0))
const EVENTS = IS_TOUCH ? ['touchstart'] : ['click']
const IDENTITY = (item) => item

const directive = {
  instances: [],
}

function processDirectiveArguments(bindingValue) {
  const isFunction = typeof bindingValue === 'function'
  if (!isFunction && typeof bindingValue !== 'object') {
    throw new Error('v-click-outside: Binding value must be a function or an object')
  }

  return {
    handler: isFunction ? bindingValue : bindingValue.handler,
    middleware: bindingValue.middleware || IDENTITY,
    events: bindingValue.events || EVENTS,
    isActive: !(bindingValue.isActive === false),
  }
}

function onEvent({ el, event, handler, middleware }) {
  const isClickOutside = event.target !== el && !el.contains(event.target)

  if (!isClickOutside) {
    return
  }

  if (middleware(event, el)) {
    handler(event, el)
  }
}

function createInstance({ el, events, handler, middleware }) {
  const instance = {
    el,
    eventHandlers: events.map((eventName) => ({
      event: eventName,
      handler: (event) => onEvent({ event, el, handler, middleware }),
    })),
  }

  if (IS_TOUCH) {
    instance.eventHandlers.handler = tap(handler)
  }

  return instance
}

function removeInstance(el) {
  const instanceIndex = directive.instances.findIndex((instance) => instance.el === el)
  if (instanceIndex === -1) {
    // Note: This can happen when active status changes from false to false
    return
  }

  const instance = directive.instances[instanceIndex]

  instance.eventHandlers.forEach(({ event, handler }) =>
    document.removeEventListener(event, handler),
  )

  directive.instances.splice(instanceIndex, 1)
}

function bind(el, { value }) {
  const { events, handler, middleware, isActive } = processDirectiveArguments(value)

  if (!isActive) {
    return
  }

  const instance = createInstance({ el, events, handler, middleware })

  instance.eventHandlers.forEach(({ event, handler }) =>
    setTimeout(() => document.addEventListener(event, handler), 0),
  )
  directive.instances.push(instance)
}

function update(el, { value, oldValue }) {
  if (JSON.stringify(value) === JSON.stringify(oldValue)) {
    return
  }

  const { events, handler, middleware, isActive } = processDirectiveArguments(value)

  if (!isActive) {
    removeInstance(el)
    return
  }

  let instance = directive.instances.find((instance) => instance.el === el)

  if (instance) {
    instance.eventHandlers.forEach(({ event, handler }) =>
      document.removeEventListener(event, handler),
    )
    instance.eventHandlers = events.map((eventName) => ({
      event: eventName,
      handler: (event) => onEvent({ event, el, handler, middleware }),
    }))
  } else {
    instance = createInstance({ el, events, handler, middleware })
    directive.instances.push(instance)
  }

  instance.eventHandlers.forEach(({ event, handler }) =>
    setTimeout(() => document.addEventListener(event, handler), 0),
  )
}

directive.bind = bind
directive.update = update
directive.unbind = removeInstance

export default directive
<|endoftext|>


<commit_before>'use strict';

var util = require('../util'),
    ono = require('ono'),
    swaggerMethods = require('swagger-methods'),
    primitiveTypes = ['array', 'boolean', 'integer', 'number', 'string'],
    schemaTypes = ['array', 'boolean', 'integer', 'number', 'string', 'object', 'null', undefined];

module.exports = validateSpec;

/**
 * Validates parts of the Swagger 2.0 spec that aren't covered by the Swagger 2.0 JSON Schema.
 *
 * @param {SwaggerObject} api
 */
function validateSpec (api) {
  util.debug('Validating against the Swagger 2.0 spec');

  var paths = Object.keys(api.paths || {});
  paths.forEach(function (pathName) {
    var path = api.paths[pathName];
    var pathId = '/paths' + pathName;

    if (path && pathName.indexOf('/') === 0) {
      validatePath(api, path, pathId);
    }
  });
  var definitions = Object.keys(api.definitions || {});
  definitions.forEach(function (definitionName) {
    var definition = api.definitions[definitionName];
    var definitionId = '/definitions/' + definitionName;
    validateRequiredPropertiesExist(definition, definitionId);
  });

  util.debug('    Validated successfully');
}

/**
 * Validates the given path.
 *
 * @param {SwaggerObject} api      - The entire Swagger API object
 * @param {object}        path     - A Path object, from the Swagger API
 * @param {string}        pathId   - A value that uniquely identifies the path
 */
function validatePath (api, path, pathId) {
  swaggerMethods.forEach(function (operationName) {
    var operation = path[operationName];
    var operationId = pathId + '/' + operationName;

    if (operation) {
      validateParameters(api, path, pathId, operation, operationId);

      var responses = Object.keys(operation.responses || {});
      responses.forEach(function (responseName) {
        var response = operation.responses[responseName];
        var responseId = operationId + '/responses/' + responseName;
        validateResponse(responseName, (response || {}), responseId);
      });
    }
  });
}

/**
 * Validates the parameters for the given operation.
 *
 * @param {SwaggerObject} api           - The entire Swagger API object
 * @param {object}        path          - A Path object, from the Swagger API
 * @param {string}        pathId        - A value that uniquely identifies the path
 * @param {object}        operation     - An Operation object, from the Swagger API
 * @param {string}        operationId   - A value that uniquely identifies the operation
 */
function validateParameters (api, path, pathId, operation, operationId) {
  var pathParams = path.parameters || [];
  var operationParams = operation.parameters || [];

  // Check for duplicate path parameters
  try {
    checkForDuplicates(pathParams);
  }
  catch (e) {
    throw ono.syntax(e, 'Validation failed. %s has duplicate parameters', pathId);
  }

  // Check for duplicate operation parameters
  try {
    checkForDuplicates(operationParams);
  }
  catch (e) {
    throw ono.syntax(e, 'Validation failed. %s has duplicate parameters', operationId);
  }

  // Combine the path and operation parameters,
  // with the operation params taking precedence over the path params
  var params = pathParams.reduce(function (combinedParams, value) {
    var duplicate = combinedParams.some(function (param) {
      return param.in === value.in && param.name === value.name;
    });
    if (!duplicate) {
      combinedParams.push(value);
    }
    return combinedParams;
  }, operationParams.slice());

  validateBodyParameters(params, operationId);
  validatePathParameters(params, pathId, operationId);
  validateParameterTypes(params, api, operation, operationId);
}

/**
 * Validates body and formData parameters for the given operation.
 *
 * @param   {object[]}  params       -  An array of Parameter objects
 * @param   {string}    operationId  -  A value that uniquely identifies the operation
 */
function validateBodyParameters (params, operationId) {
  var bodyParams = params.filter(function (param) { return param.in === 'body'; });
  var formParams = params.filter(function (param) { return param.in === 'formData'; });

  // There can only be one "body" parameter
  if (bodyParams.length > 1) {
    throw ono.syntax(
      'Validation failed. %s has %d body parameters. Only one is allowed.',
      operationId, bodyParams.length
    );
  }
  else if (bodyParams.length > 0 && formParams.length > 0) {
    // "body" params and "formData" params are mutually exclusive
    throw ono.syntax(
      'Validation failed. %s has body parameters and formData parameters. Only one or the other is allowed.',
      operationId
    );
  }
}

/**
 * Validates path parameters for the given path.
 *
 * @param   {object[]}  params        - An array of Parameter objects
 * @param   {string}    pathId        - A value that uniquely identifies the path
 * @param   {string}    operationId   - A value that uniquely identifies the operation
 */
function validatePathParameters (params, pathId, operationId) {
  // Find all {placeholders} in the path string
  var placeholders = pathId.match(util.swaggerParamRegExp) || [];

  // Check for duplicates
  for (var i = 0; i < placeholders.length; i++) {
    for (var j = i + 1; j < placeholders.length; j++) {
      if (placeholders[i] === placeholders[j]) {
        throw ono.syntax(
          'Validation failed. %s has multiple path placeholders named %s', operationId, placeholders[i]);
      }
    }
  }

  params
    .filter(function (param) { return param.in === 'path'; })
    .forEach(function (param) {
      if (param.required !== true) {
        throw ono.syntax(
          'Validation failed. Path parameters cannot be optional. Set required=true for the "%s" parameter at %s',
          param.name,
          operationId
        );
      }
      var match = placeholders.indexOf('{' + param.name + '}');
      if (match === -1) {
        throw ono.syntax(
          'Validation failed. %s has a path parameter named "%s", ' +
          'but there is no corresponding {%s} in the path string',
          operationId,
          param.name,
          param.name
        );
      }
      placeholders.splice(match, 1);
    });

  if (placeholders.length > 0) {
    throw ono.syntax('Validation failed. %s is missing path parameter(s) for %s', operationId, placeholders);
  }
}

/**
 * Validates data types of parameters for the given operation.
 *
 * @param   {object[]}  params       -  An array of Parameter objects
 * @param   {object}    api          -  The entire Swagger API object
 * @param   {object}    operation    -  An Operation object, from the Swagger API
 * @param   {string}    operationId  -  A value that uniquely identifies the operation
 */
function validateParameterTypes (params, api, operation, operationId) {
  params.forEach(function (param) {
    var parameterId = operationId + '/parameters/' + param.name;
    var schema, validTypes;

    switch (param.in) {
      case 'body':
        schema = param.schema;
        validTypes = schemaTypes;
        break;
      case 'formData':
        schema = param;
        validTypes = primitiveTypes.concat('file');
        break;
      default:
        schema = param;
        validTypes = primitiveTypes;
    }

    validateSchema(schema, parameterId, validTypes);
    validateRequiredPropertiesExist(schema, parameterId);

    if (schema.type === 'file') {
      // "file" params require specific "consumes" types
      var consumes = operation.consumes || api.consumes || [];
      if (consumes.indexOf('multipart/form-data') === -1 &&
        consumes.indexOf('application/x-www-form-urlencoded') === -1) {
        throw ono.syntax(
          'Validation failed. %s has a file parameter, so it must consume multipart/form-data ' +
          'or application/x-www-form-urlencoded',
          operationId
        );
      }
    }
  });
}

/**
 * Checks the given parameter list for duplicates, and throws an error if found.
 *
 * @param   {object[]}  params  - An array of Parameter objects
 */
function checkForDuplicates (params) {
  for (var i = 0; i < params.length - 1; i++) {
    var outer = params[i];
    for (var j = i + 1; j < params.length; j++) {
      var inner = params[j];
      if (outer.name === inner.name && outer.in === inner.in) {
        throw ono.syntax('Validation failed. Found multiple %s parameters named "%s"', outer.in, outer.name);
      }
    }
  }
}

/**
 * Validates the given response object.
 *
 * @param   {string}    code        -  The HTTP response code (or "default")
 * @param   {object}    response    -  A Response object, from the Swagger API
 * @param   {string}    responseId  -  A value that uniquely identifies the response
 */
function validateResponse (code, response, responseId) {
  if (code !== 'default' && (code < 100 || code > 599)) {
    throw ono.syntax('Validation failed. %s has an invalid response code (%s)', responseId, code);
  }

  var headers = Object.keys(response.headers || {});
  headers.forEach(function (headerName) {
    var header = response.headers[headerName];
    var headerId = responseId + '/headers/' + headerName;
    validateSchema(header, headerId, primitiveTypes);
  });

  if (response.schema) {
    var validTypes = schemaTypes.concat('file');
    if (validTypes.indexOf(response.schema.type) === -1) {
      throw ono.syntax(
        'Validation failed. %s has an invalid response schema type (%s)', responseId, response.schema.type);
    }
  }
}

/**
 * Validates the given Swagger schema object.
 *
 * @param {object}    schema      - A Schema object, from the Swagger API
 * @param {string}    schemaId    - A value that uniquely identifies the schema object
 * @param {string[]}  validTypes  - An array of the allowed schema types
 */
function validateSchema (schema, schemaId, validTypes) {
  if (validTypes.indexOf(schema.type) === -1) {
    throw ono.syntax(
      'Validation failed. %s has an invalid type (%s)', schemaId, schema.type);
  }

  if (schema.type === 'array' && !schema.items) {
    throw ono.syntax('Validation failed. %s is an array, so it must include an "items" schema', schemaId);
  }
}

/**
 * Validates that the declared properties of the given Swagger schema object actually exist.
 *
 * @param {object}    schema      - A Schema object, from the Swagger API
 * @param {string}    schemaId    - A value that uniquely identifies the schema object
 */
function validateRequiredPropertiesExist (schema, schemaId) {
  /**
   * Recursively collects all properties of the schema and its ancestors. They are added to the props object.
   */
  function collectProperties (schemaObj, props) {
    if (schemaObj.properties) {
      for (var property in schemaObj.properties) {
        if (schemaObj.properties.hasOwnProperty(property)) {
          props[property] = schemaObj.properties[property];
        }
      }
    }
    if (schemaObj.allOf) {
      schemaObj.allOf.forEach(function (parent) {
        collectProperties(parent, props);
      });
    }
  }

  if (schema.required && Array.isArray(schema.required)) {
    var props = {};
    collectProperties(schema, props);
    schema.required.forEach(function (requiredProperty) {
      if (!props[requiredProperty]) {
        throw ono.syntax('Validation failed. Property \'%s\' listed as required but does not exist in \'%s\'',
          requiredProperty, schemaId);
      }
    });
  }
}

<commit_msg>Validating against the OpenAPI spec is not (yet) supported<commit_after>'use strict';

var util = require('../util'),
    ono = require('ono'),
    swaggerMethods = require('swagger-methods'),
    primitiveTypes = ['array', 'boolean', 'integer', 'number', 'string'],
    schemaTypes = ['array', 'boolean', 'integer', 'number', 'string', 'object', 'null', undefined];

module.exports = validateSpec;

/**
 * Validates parts of the Swagger 2.0 spec that aren't covered by the Swagger 2.0 JSON Schema.
 *
 * @param {SwaggerObject} api
 */
function validateSpec (api) {
  if (api.openapi) {
    // We don't (yet) support validating against the OpenAPI spec
    return;
  }

  util.debug('Validating against the Swagger spec');

  var paths = Object.keys(api.paths || {});
  paths.forEach(function (pathName) {
    var path = api.paths[pathName];
    var pathId = '/paths' + pathName;

    if (path && pathName.indexOf('/') === 0) {
      validatePath(api, path, pathId);
    }
  });
  var definitions = Object.keys(api.definitions || {});
  definitions.forEach(function (definitionName) {
    var definition = api.definitions[definitionName];
    var definitionId = '/definitions/' + definitionName;
    validateRequiredPropertiesExist(definition, definitionId);
  });

  util.debug('    Validated successfully');
}

/**
 * Validates the given path.
 *
 * @param {SwaggerObject} api      - The entire Swagger API object
 * @param {object}        path     - A Path object, from the Swagger API
 * @param {string}        pathId   - A value that uniquely identifies the path
 */
function validatePath (api, path, pathId) {
  swaggerMethods.forEach(function (operationName) {
    var operation = path[operationName];
    var operationId = pathId + '/' + operationName;

    if (operation) {
      validateParameters(api, path, pathId, operation, operationId);

      var responses = Object.keys(operation.responses || {});
      responses.forEach(function (responseName) {
        var response = operation.responses[responseName];
        var responseId = operationId + '/responses/' + responseName;
        validateResponse(responseName, (response || {}), responseId);
      });
    }
  });
}

/**
 * Validates the parameters for the given operation.
 *
 * @param {SwaggerObject} api           - The entire Swagger API object
 * @param {object}        path          - A Path object, from the Swagger API
 * @param {string}        pathId        - A value that uniquely identifies the path
 * @param {object}        operation     - An Operation object, from the Swagger API
 * @param {string}        operationId   - A value that uniquely identifies the operation
 */
function validateParameters (api, path, pathId, operation, operationId) {
  var pathParams = path.parameters || [];
  var operationParams = operation.parameters || [];

  // Check for duplicate path parameters
  try {
    checkForDuplicates(pathParams);
  }
  catch (e) {
    throw ono.syntax(e, 'Validation failed. %s has duplicate parameters', pathId);
  }

  // Check for duplicate operation parameters
  try {
    checkForDuplicates(operationParams);
  }
  catch (e) {
    throw ono.syntax(e, 'Validation failed. %s has duplicate parameters', operationId);
  }

  // Combine the path and operation parameters,
  // with the operation params taking precedence over the path params
  var params = pathParams.reduce(function (combinedParams, value) {
    var duplicate = combinedParams.some(function (param) {
      return param.in === value.in && param.name === value.name;
    });
    if (!duplicate) {
      combinedParams.push(value);
    }
    return combinedParams;
  }, operationParams.slice());

  validateBodyParameters(params, operationId);
  validatePathParameters(params, pathId, operationId);
  validateParameterTypes(params, api, operation, operationId);
}

/**
 * Validates body and formData parameters for the given operation.
 *
 * @param   {object[]}  params       -  An array of Parameter objects
 * @param   {string}    operationId  -  A value that uniquely identifies the operation
 */
function validateBodyParameters (params, operationId) {
  var bodyParams = params.filter(function (param) { return param.in === 'body'; });
  var formParams = params.filter(function (param) { return param.in === 'formData'; });

  // There can only be one "body" parameter
  if (bodyParams.length > 1) {
    throw ono.syntax(
      'Validation failed. %s has %d body parameters. Only one is allowed.',
      operationId, bodyParams.length
    );
  }
  else if (bodyParams.length > 0 && formParams.length > 0) {
    // "body" params and "formData" params are mutually exclusive
    throw ono.syntax(
      'Validation failed. %s has body parameters and formData parameters. Only one or the other is allowed.',
      operationId
    );
  }
}

/**
 * Validates path parameters for the given path.
 *
 * @param   {object[]}  params        - An array of Parameter objects
 * @param   {string}    pathId        - A value that uniquely identifies the path
 * @param   {string}    operationId   - A value that uniquely identifies the operation
 */
function validatePathParameters (params, pathId, operationId) {
  // Find all {placeholders} in the path string
  var placeholders = pathId.match(util.swaggerParamRegExp) || [];

  // Check for duplicates
  for (var i = 0; i < placeholders.length; i++) {
    for (var j = i + 1; j < placeholders.length; j++) {
      if (placeholders[i] === placeholders[j]) {
        throw ono.syntax(
          'Validation failed. %s has multiple path placeholders named %s', operationId, placeholders[i]);
      }
    }
  }

  params
    .filter(function (param) { return param.in === 'path'; })
    .forEach(function (param) {
      if (param.required !== true) {
        throw ono.syntax(
          'Validation failed. Path parameters cannot be optional. Set required=true for the "%s" parameter at %s',
          param.name,
          operationId
        );
      }
      var match = placeholders.indexOf('{' + param.name + '}');
      if (match === -1) {
        throw ono.syntax(
          'Validation failed. %s has a path parameter named "%s", ' +
          'but there is no corresponding {%s} in the path string',
          operationId,
          param.name,
          param.name
        );
      }
      placeholders.splice(match, 1);
    });

  if (placeholders.length > 0) {
    throw ono.syntax('Validation failed. %s is missing path parameter(s) for %s', operationId, placeholders);
  }
}

/**
 * Validates data types of parameters for the given operation.
 *
 * @param   {object[]}  params       -  An array of Parameter objects
 * @param   {object}    api          -  The entire Swagger API object
 * @param   {object}    operation    -  An Operation object, from the Swagger API
 * @param   {string}    operationId  -  A value that uniquely identifies the operation
 */
function validateParameterTypes (params, api, operation, operationId) {
  params.forEach(function (param) {
    var parameterId = operationId + '/parameters/' + param.name;
    var schema, validTypes;

    switch (param.in) {
      case 'body':
        schema = param.schema;
        validTypes = schemaTypes;
        break;
      case 'formData':
        schema = param;
        validTypes = primitiveTypes.concat('file');
        break;
      default:
        schema = param;
        validTypes = primitiveTypes;
    }

    validateSchema(schema, parameterId, validTypes);
    validateRequiredPropertiesExist(schema, parameterId);

    if (schema.type === 'file') {
      // "file" params require specific "consumes" types
      var consumes = operation.consumes || api.consumes || [];
      if (consumes.indexOf('multipart/form-data') === -1 &&
        consumes.indexOf('application/x-www-form-urlencoded') === -1) {
        throw ono.syntax(
          'Validation failed. %s has a file parameter, so it must consume multipart/form-data ' +
          'or application/x-www-form-urlencoded',
          operationId
        );
      }
    }
  });
}

/**
 * Checks the given parameter list for duplicates, and throws an error if found.
 *
 * @param   {object[]}  params  - An array of Parameter objects
 */
function checkForDuplicates (params) {
  for (var i = 0; i < params.length - 1; i++) {
    var outer = params[i];
    for (var j = i + 1; j < params.length; j++) {
      var inner = params[j];
      if (outer.name === inner.name && outer.in === inner.in) {
        throw ono.syntax('Validation failed. Found multiple %s parameters named "%s"', outer.in, outer.name);
      }
    }
  }
}

/**
 * Validates the given response object.
 *
 * @param   {string}    code        -  The HTTP response code (or "default")
 * @param   {object}    response    -  A Response object, from the Swagger API
 * @param   {string}    responseId  -  A value that uniquely identifies the response
 */
function validateResponse (code, response, responseId) {
  if (code !== 'default' && (code < 100 || code > 599)) {
    throw ono.syntax('Validation failed. %s has an invalid response code (%s)', responseId, code);
  }

  var headers = Object.keys(response.headers || {});
  headers.forEach(function (headerName) {
    var header = response.headers[headerName];
    var headerId = responseId + '/headers/' + headerName;
    validateSchema(header, headerId, primitiveTypes);
  });

  if (response.schema) {
    var validTypes = schemaTypes.concat('file');
    if (validTypes.indexOf(response.schema.type) === -1) {
      throw ono.syntax(
        'Validation failed. %s has an invalid response schema type (%s)', responseId, response.schema.type);
    }
  }
}

/**
 * Validates the given Swagger schema object.
 *
 * @param {object}    schema      - A Schema object, from the Swagger API
 * @param {string}    schemaId    - A value that uniquely identifies the schema object
 * @param {string[]}  validTypes  - An array of the allowed schema types
 */
function validateSchema (schema, schemaId, validTypes) {
  if (validTypes.indexOf(schema.type) === -1) {
    throw ono.syntax(
      'Validation failed. %s has an invalid type (%s)', schemaId, schema.type);
  }

  if (schema.type === 'array' && !schema.items) {
    throw ono.syntax('Validation failed. %s is an array, so it must include an "items" schema', schemaId);
  }
}

/**
 * Validates that the declared properties of the given Swagger schema object actually exist.
 *
 * @param {object}    schema      - A Schema object, from the Swagger API
 * @param {string}    schemaId    - A value that uniquely identifies the schema object
 */
function validateRequiredPropertiesExist (schema, schemaId) {
  /**
   * Recursively collects all properties of the schema and its ancestors. They are added to the props object.
   */
  function collectProperties (schemaObj, props) {
    if (schemaObj.properties) {
      for (var property in schemaObj.properties) {
        if (schemaObj.properties.hasOwnProperty(property)) {
          props[property] = schemaObj.properties[property];
        }
      }
    }
    if (schemaObj.allOf) {
      schemaObj.allOf.forEach(function (parent) {
        collectProperties(parent, props);
      });
    }
  }

  if (schema.required && Array.isArray(schema.required)) {
    var props = {};
    collectProperties(schema, props);
    schema.required.forEach(function (requiredProperty) {
      if (!props[requiredProperty]) {
        throw ono.syntax('Validation failed. Property \'%s\' listed as required but does not exist in \'%s\'',
          requiredProperty, schemaId);
      }
    });
  }
}
<|endoftext|>


<commit_before>/*global Backbone, _, window, Promise, $ */
"use strict";
(function(NS) {
    //Filename: views/core-view.js
    NS = NS || {};
    var isInBrowser = typeof module === 'undefined' && typeof window !== 'undefined';
    var postRenderingBuilder = isInBrowser ? NS.Helpers.postRenderingBuilder : require('../helpers/post_rendering_builder');
    var ErrorHelper = isInBrowser ? NS.Helpers.errorHelper : require('../helpers/error_helper');
    var RefHelper = isInBrowser ? NS.Helpers.referenceHelper : require('../helpers/reference_helper');
    var ArgumentNullException = isInBrowser ? NS.Helpers.Exceptions.ArgumentNullException : require("../helpers/custom_exception").ArgumentNullException;
    var Model = isInBrowser ? NS.Models.Model : require("../models/model");
    var PaginatedCollection = isInBrowser ? NS.Models.PaginatedCollection : require("../models/paginatedCollection");
    var UtilHelper = isInBrowser ? NS.Helpers.utilHelper : require('../helpers/util_helper');
    var sessionHelper = isInBrowser ? NS.Helpers.sessionHelper : require('../helpers/session_helper');
    var templateSpinner = isInBrowser ? NS.templates.spinner : function() {
        return "Template spinner to define...";
    };
    //View which is the default view for each view.
    //This view is able to deal with errors and to render the default json moodel.
    var CoreView = Backbone.View.extend({
        toogleIsHidden: function(options) {
            this.isHidden = !this.isHidden;
            this.render(options);
        },
        //Reference lists names.
        //These _names_, must have been registered inside the the application to be used.
        referenceNames: undefined,

        //Options define by default for the view.
        defaultOptions: {
            isElementRedefinition: false, //This options is use in order to not have a tag container generated by Backbone arround the view.
            isReadyReferences: true
        },
        //Options overriden By the instanciate view.
        customOptions: {},

        //This property is use in order to create a new Model if no model are define in the view.
        modelName: undefined,

        //Initialization of the coreview.
        initialize: function initializeCoreView(options) {
            options = options || {};
            //Define default options foreach _core_ view, and override these options for each _project view_.
            //Then each view will have access to options in any methods.
            this.opts = _.extend({}, this.defaultOptions, this.customOptions, options);

            this.on('toogleIsHidden', this.toogleIsHidden);
            this.initializeModel();

            /*Register after renger.*/
            _.bindAll(this, 'render', 'afterRender');
            var _this = this;
            this.render = _.wrap(this.render, function(render, options) {
                //If the view is ready perform the standard render.
                if (_this.isReady()) {
                    render(options);
                    _this.afterRender();
                } else {
                    //Else render the spinner.
                    this.renderSpinner();
                }
                return _this;
            });

            //Listen to the reference list loading.
            this.listenTo(this.model, "references:loaded", this.render, this);

            //Load all the references lists which are defined in referenceNames.
            var currentView = this;
            if (_.isArray(this.referenceNames) && this.referenceNames.length > 0) {
                this.opts.isReadyReferences = false;
                Promise.all(RefHelper.loadMany(this.referenceNames)).then(function(results) {
                    currentView.opts.isReadyReferences = true;
                    //console.log('resultsreferenceNames', results);
                    var res = {}; //Container for all the results.
                    for (var i = 0, l = results.length; i < l; i++) {
                        res[currentView.referenceNames[i]] = results[i];
                        //The results are save into an object with a name for each reference list.
                    }
                    //Add the reference lists as model properties.
                    _.extend(currentView.model, res);
                    currentView.model.trigger('references:loaded');
                    //Inform the view that we are ready to render well.
                }).then(null, function(error) {
                    currentView.opts.isReadyReferences = true;
                    currentView.render();
                    ErrorHelper.manageResponseErrors(error, {
                        isDisplay: true
                    });
                });
            }

        },

        //Initialize the model of the view.
        //In order to be able to be initialize, a view must have a _model_ or a _modelName_.
        initializeModel: function initializeModelCoreView() {
            if (this.model) {
                return;
            } else if (this.opts.modelName) {
                //Création d'une collection et d'un model
                var ModelCreated = Model.extend({
                    modelName: this.opts.modelName
                });
                //Case of a collection.
                if (this.opts.modelType !== undefined && this.opts.modelType === "collection") {
                    var CollectionCreated = PaginatedCollection.extend({
                        modelName: this.opts.modelName,
                        model: ModelCreated
                    });
                    this.model = new CollectionCreated();
                } else {
                    //Case of a model.
                    this.model = new ModelCreated();

                }
            } else {
                throw new ArgumentNullException("The view must have a model or a model name.", this);
            }
        },
        //The handlebars template has to be defined here.
        template: function emptyTemplate(json) {
            console.log("templateData", json);
            return "
Your template has to be implemented.
";
        }, // Example: require('./templates/coreView'),
        templateSpinner: templateSpinner,
        //Defaults events.
        events: {
            "focus input": "inputFocus", //Deal with the focus in the field.
            "blur input": "inputBlur", //Deal with the focus out of the field.
            "click .panel-collapse.in": "hideCollapse",
            "click .panel-collapse:not('.in')": "showCollapse",
            "click button[data-loading]": "loadingButton"
        },
        //Input focus event.
        inputFocus: function coreViewInputFocus(event) {
            if (!this.model.has('errors')) {
                return;
            }
            //Remove the input hidden attribute.
            return event.target.parentElement.parentElement.childNodes[5].removeAttribute('hidden');
        },
        //Input blur event gestion
        inputBlur: function coreViewInputBlur(event) {
            if (!this.model.has('errors')) {
                return;
            }
            //If there is an error add the hidden attribute into it in odere to hide the errors.
            return event.target.parentElement.parentElement.childNodes[5].setAttribute("hidden", "hidden");
        },
        //This method is use in order to inject json data to the template. By default, the this.model.toJSON() is called.
        getRenderData: function getCoreViewRenderData() {
            return this.model.toJSON();
        },
        showCollapse: function showCollapseCoreView() {
            $('.collapse', this.$el).collapse('show');
        },
        hideCollapse: function hideCollapseCoreView() {
            $('.collapse', this.$el).collapse('hide');
        },
        toogleCollapse: function toogleCollapseCoreView(event) {
            $(".panel-collapse.in", event.target.parentNode.parentNode).collapse('hide'); //todo: change the selector
            $(".panel-collapse:not('.in')", event.target.parentNode.parentNode).collapse('show');
        },
        //Render function  by default call the getRenderData and inject it into the view dom element.
        render: function renderCoreView() {
            //If the view is not ready.
            this.$el.html(this.template(this.getRenderData()));

            //_.defer(this.afterRender, this);
            return this;
        },
        afterRender: function afterRenderCoreView() {
            //Eventually pass the currentview as argument for this binding.
            postRenderingBuilder({
                model: this.model,
                viewSelector: this.$el
            });
            $('.collapse', this.$el).collapse({
                toogle: true
            });
        },
        //Get the criteria from the session storage if exists.
        getSessionCriteria: function getCriteria() {
            return sessionHelper.getItem(this.getCriteriaId());
        },
        //Save the criteria in the session storage.
        saveSessionCriteria: function saveSessionCriteria(criteria) {
            return sessionHelper.saveItem(this.getCriteriaId(), criteria);
        },
        // Get the id of the criteria.
        getCriteriaId: function getCriteriaId() {
            var hash = window.location.hash;
            if (this.model.modelName !== undefined) {
                hash += this.model.modelName;
            }
            if (this.opts.criteriaId !== undefined) {
                hash += this.opts.criteriaId;
            }
            return hash;
        },
        //Call the history back.
        back: function back() {
            Backbone.history.history.back();
        },
        //Function which tells if the view is ready to be display.
        isReady: function isReady() {
            return this.opts.isReadyReferences === true;
        },
        //renderSpinner
        renderSpinner: function renderSpinner() {
            this.$el.html(this.templateSpinner(this.getRenderData()));
            return this;
        }
    });

    // Differenciating export for node or browser.
    if (isInBrowser) {
        NS.Views = NS.Views || {};
        NS.Views.CoreView = CoreView;
    } else {
        module.exports = CoreView;
    }
})(typeof module === 'undefined' && typeof window !== 'undefined' ? window.Fmk : module.exports);
// ## Example calll:
// ```javascript
// var CoreView = require('./views/core-view');
// new CoreView({model: new Model({firstName: "first name", lastName: "last name"}).render().el //Get the dom element of the view.
//```<commit_msg>Add a changeState button<commit_after>/*global Backbone, _, window, Promise, $ */
"use strict";
(function(NS) {
    //Filename: views/core-view.js
    NS = NS || {};
    var isInBrowser = typeof module === 'undefined' && typeof window !== 'undefined';
    var postRenderingBuilder = isInBrowser ? NS.Helpers.postRenderingBuilder : require('../helpers/post_rendering_builder');
    var ErrorHelper = isInBrowser ? NS.Helpers.errorHelper : require('../helpers/error_helper');
    var RefHelper = isInBrowser ? NS.Helpers.referenceHelper : require('../helpers/reference_helper');
    var ArgumentNullException = isInBrowser ? NS.Helpers.Exceptions.ArgumentNullException : require("../helpers/custom_exception").ArgumentNullException;
    var Model = isInBrowser ? NS.Models.Model : require("../models/model");
    var PaginatedCollection = isInBrowser ? NS.Models.PaginatedCollection : require("../models/paginatedCollection");
    var UtilHelper = isInBrowser ? NS.Helpers.utilHelper : require('../helpers/util_helper');
    var sessionHelper = isInBrowser ? NS.Helpers.sessionHelper : require('../helpers/session_helper');
    var templateSpinner = isInBrowser ? NS.templates.spinner : function() {
        return "Template spinner to define...";
    };
    //View which is the default view for each view.
    //This view is able to deal with errors and to render the default json moodel.
    var CoreView = Backbone.View.extend({
        toogleIsHidden: function(options) {
            this.isHidden = !this.isHidden;
            this.render(options);
        },
        //Reference lists names.
        //These _names_, must have been registered inside the the application to be used.
        referenceNames: undefined,

        //Options define by default for the view.
        defaultOptions: {
            isElementRedefinition: false, //This options is use in order to not have a tag container generated by Backbone arround the view.
            isReadyReferences: true
        },
        //Options overriden By the instanciate view.
        customOptions: {},

        //This property is use in order to create a new Model if no model are define in the view.
        modelName: undefined,

        //Initialization of the coreview.
        initialize: function initializeCoreView(options) {
            options = options || {};
            //Define default options foreach _core_ view, and override these options for each _project view_.
            //Then each view will have access to options in any methods.
            this.opts = _.extend({}, this.defaultOptions, this.customOptions, options);

            this.on('toogleIsHidden', this.toogleIsHidden);
            this.initializeModel();

            /*Register after renger.*/
            _.bindAll(this, 'render', 'afterRender');
            var _this = this;
            this.render = _.wrap(this.render, function(render, options) {
                //If the view is ready perform the standard render.
                if (_this.isReady()) {
                    render(options);
                    _this.afterRender();
                } else {
                    //Else render the spinner.
                    this.renderSpinner();
                }
                return _this;
            });

            //Listen to the reference list loading.
            this.listenTo(this.model, "references:loaded", this.render, this);

            //Load all the references lists which are defined in referenceNames.
            var currentView = this;
            if (_.isArray(this.referenceNames) && this.referenceNames.length > 0) {
                this.opts.isReadyReferences = false;
                Promise.all(RefHelper.loadMany(this.referenceNames)).then(function(results) {
                    currentView.opts.isReadyReferences = true;
                    //console.log('resultsreferenceNames', results);
                    var res = {}; //Container for all the results.
                    for (var i = 0, l = results.length; i < l; i++) {
                        res[currentView.referenceNames[i]] = results[i];
                        //The results are save into an object with a name for each reference list.
                    }
                    //Add the reference lists as model properties.
                    _.extend(currentView.model, res);
                    currentView.model.trigger('references:loaded');
                    //Inform the view that we are ready to render well.
                }).then(null, function(error) {
                    currentView.opts.isReadyReferences = true;
                    currentView.render();
                    ErrorHelper.manageResponseErrors(error, {
                        isDisplay: true
                    });
                });
            }

        },

        //Initialize the model of the view.
        //In order to be able to be initialize, a view must have a _model_ or a _modelName_.
        initializeModel: function initializeModelCoreView() {
            if (this.model) {
                return;
            } else if (this.opts.modelName) {
                //Création d'une collection et d'un model
                var ModelCreated = Model.extend({
                    modelName: this.opts.modelName
                });
                //Case of a collection.
                if (this.opts.modelType !== undefined && this.opts.modelType === "collection") {
                    var CollectionCreated = PaginatedCollection.extend({
                        modelName: this.opts.modelName,
                        model: ModelCreated
                    });
                    this.model = new CollectionCreated();
                } else {
                    //Case of a model.
                    this.model = new ModelCreated();

                }
            } else {
                throw new ArgumentNullException("The view must have a model or a model name.", this);
            }
        },
        //The handlebars template has to be defined here.
        template: function emptyTemplate(json) {
            console.log("templateData", json);
            return "
Your template has to be implemented.
";
        }, // Example: require('./templates/coreView'),
        templateSpinner: templateSpinner,
        //Defaults events.
        events: {
            "focus input": "inputFocus", //Deal with the focus in the field.
            "blur input": "inputBlur", //Deal with the focus out of the field.
            "click .panel-collapse.in": "hideCollapse",
            "click .panel-collapse:not('.in')": "showCollapse",
            "click button[data-loading]": "loadingButton"
        },
        //Input focus event.
        inputFocus: function coreViewInputFocus(event) {
            if (!this.model.has('errors')) {
                return;
            }
            //Remove the input hidden attribute.
            return event.target.parentElement.parentElement.childNodes[5].removeAttribute('hidden');
        },
        //Input blur event gestion
        inputBlur: function coreViewInputBlur(event) {
            if (!this.model.has('errors')) {
                return;
            }
            //If there is an error add the hidden attribute into it in odere to hide the errors.
            return event.target.parentElement.parentElement.childNodes[5].setAttribute("hidden", "hidden");
        },
        //This method is use in order to inject json data to the template. By default, the this.model.toJSON() is called.
        getRenderData: function getCoreViewRenderData() {
            return this.model.toJSON();
        },
        showCollapse: function showCollapseCoreView() {
            $('.collapse', this.$el).collapse('show');
        },
        hideCollapse: function hideCollapseCoreView() {
            $('.collapse', this.$el).collapse('hide');
        },
        toogleCollapse: function toogleCollapseCoreView(event) {
            $(".panel-collapse.in", event.target.parentNode.parentNode).collapse('hide'); //todo: change the selector
            $(".panel-collapse:not('.in')", event.target.parentNode.parentNode).collapse('show');
        },
        //Render function  by default call the getRenderData and inject it into the view dom element.
        render: function renderCoreView() {
            //If the view is not ready.
            this.$el.html(this.template(this.getRenderData()));

            //_.defer(this.afterRender, this);
            return this;
        },
        afterRender: function afterRenderCoreView() {
            //Eventually pass the currentview as argument for this binding.
            postRenderingBuilder({
                model: this.model,
                viewSelector: this.$el
            });
            $('.collapse', this.$el).collapse({
                toogle: true
            });
        },
        //Get the criteria from the session storage if exists.
        getSessionCriteria: function getCriteria() {
            return sessionHelper.getItem(this.getCriteriaId());
        },
        //Save the criteria in the session storage.
        saveSessionCriteria: function saveSessionCriteria(criteria) {
            return sessionHelper.saveItem(this.getCriteriaId(), criteria);
        },
        // Get the id of the criteria.
        getCriteriaId: function getCriteriaId() {
            var hash = window.location.hash;
            if (this.model.modelName !== undefined) {
                hash += this.model.modelName;
            }
            if (this.opts.criteriaId !== undefined) {
                hash += this.opts.criteriaId;
            }
            return hash;
        },
        //Call the history back.
        back: function back() {
            Backbone.history.history.back();
        },
        //Function which tells if the view is ready to be display.
        isReady: function isReady() {
            return this.opts.isReadyReferences === true;
        },
        //renderSpinner
        renderSpinner: function renderSpinner() {
            this.$el.html(this.templateSpinner(this.getRenderData()));
            return this;
        },
        /**
         * Change the button state (loading, reset) ...
         * @param  {string} selector - CSS selector for the button.
         * @param  {string} state    - The new state you want for the button.
         * @return {undefined}
         */
        changeButtonState: function changeButtonState(selector, state){
            $(selector, this.$el).button(state);
        }
    });

    // Differenciating export for node or browser.
    if (isInBrowser) {
        NS.Views = NS.Views || {};
        NS.Views.CoreView = CoreView;
    } else {
        module.exports = CoreView;
    }
})(typeof module === 'undefined' && typeof window !== 'undefined' ? window.Fmk : module.exports);
// ## Example calll:
// ```javascript
// var CoreView = require('./views/core-view');
// new CoreView({model: new Model({firstName: "first name", lastName: "last name"}).render().el //Get the dom element of the view.
//```<|endoftext|>


<commit_before>import Ember from 'ember';
import { test, moduleFor, moduleForComponent } from 'ember-qunit';
import startApp from '../../helpers/start-app';
import SlMenu from 'sl-ember-components/components/sl-menu';

var clickCounter = 0,
    modelStub = {
        label: null,
        pages: [
            { label: 'Top Level A', pages: [
                { label: 'Option A1', action: 'MyAction' },
                { label: 'Option A2', action: function(){ clickCounter = 0; clickCounter++; }},
                { label: 'Option A3', action: { actionName: 'MyAction', data: { name: 'Joe' }}},
                { label: 'Sub Menu A3', pages: [
                    { label: 'Sub Sub Menu A3.1' },
                    { label: 'Sub Sub Menu A3.2' },
                    { label: 'Sub Sub Menu A3.3' },
                    { label: 'Sub Sub Menu A3.4' }
                ]}
            ]},
            { label: 'Top Level B' },
            { label: 'Top Level C' }
        ]
    },
    App;

moduleForComponent( 'sl-menu', 'Component: Sl-Menu', {
    setup: function() {
        App = startApp();
    },

    teardown: function() {
        Ember.run( App, App.destroy );
    }
});

test( 'Menu creates correct DOM structure', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append();

    expect( 1 );

    equal( $component.find( 'li' ).length, 11 );
});

test( 'Menu properly hides all but root list', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append();

    expect( 1 );

    equal( $component.find( 'li:visible' ).length, 3 );
});

test( 'Menu shows child on hover', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append();

    expect( 2 );

    equal( $component.find( 'li:visible' ).length, 3 );

    $component.find( 'li:visible' ).first().mouseenter();
    equal( $component.find( 'li:visible' ).length, 7 );
});

test( 'Menu closes child on mouse exit', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append(),
        child = $component.find( 'li:visible' ).first();

    expect( 3 );

    equal( $component.find( 'li:visible' ).length, 3 );

    child.mouseenter();
    equal( $component.find( 'li:visible' ).length, 7 );

    child.mouseleave();
    equal( $component.find( 'li:visible' ).length, 3 );
});

test( 'Menu click supports native function', function() {
    expect( 1 );

    var spy = sinon.spy(),
        component,
        $component,
        child;

    modelStub.pages[0].pages[1]['action'] = spy;

    component = this.subject({ menu: modelStub });

    $component = this.append();

    child = $component.find( 'li:visible' ).first();

    triggerEvent( child, 'mouseenter' );

    click( child.find( 'li:visible' )[ 1 ] );

    andThen( function() {
        equal( spy.calledOnce, true );
    });
});

test( 'Menu click supports action names', function() {
    expect( 1 );

    var component    = this.subject({ menu: modelStub }),
        $component   = this.append(),
        child        = $component.find( 'li:visible' ).first(),
        spy          = sinon.spy(),
        targetObject = {
            actionHandler: spy
        };

    component.set( 'actionInitiated', 'actionHandler' );
    component.set( 'targetObject', targetObject );

    triggerEvent( child, 'mouseenter' );

    click( child.find( 'li:visible' )[ 0 ] );

    andThen( function() {
        equal( spy.args[0][0], 'MyAction' );
    });
});

test( 'Menu click supports action names with supporting data', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append(),
        child = $component.find( 'li:visible' ).first(),
        targetObject = {
            actionHandler: function( actionName, data ) {
                equal( actionName, 'MyAction' );
                equal( data.name, 'Joe' );
            }
        };

    expect( 2 );

    child.mouseenter();
    component.set( 'actionInitiated', 'actionHandler' );
    component.set( 'targetObject', targetObject );
    child.find( 'li:visible' )[ 2 ].click();
});

test( 'Menu selection fires proper selection event', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append(),
        selectionCounter = 0,
        targetObject = {
            selectionHandler: function( path ) {
                selectionCounter++;
            }
        },
        child1,
        child2,
        child3;

    expect( 1 );

    component.set( 'selectionMade', 'selectionHandler' );
    component.set( 'targetObject', targetObject );

    child1 = $component.find( 'li:visible' ).first();
    child1.trigger( 'mouseenter' );
    child1.trigger( 'click' );

    child2 = child1.find( 'li:visible' ).last();
    child2.trigger( 'mouseenter' );
    child2.trigger( 'click' );

    child3 = child2.find( 'li:visible' ).first();
    child3.trigger( 'mouseenter' );
    child3.trigger( 'click' );

    equal( selectionCounter, 3 );
});
<commit_msg>Closes softlayer/sl-ember-components#173<commit_after>import Ember from 'ember';
import { test, moduleFor, moduleForComponent } from 'ember-qunit';
import startApp from '../../helpers/start-app';
import SlMenu from 'sl-ember-components/components/sl-menu';

var clickCounter = 0,
    modelStub = {
        label: null,
        pages: [
            { label: 'Top Level A', pages: [
                { label: 'Option A1', action: 'MyAction' },
                { label: 'Option A2', action: function(){ clickCounter = 0; clickCounter++; }},
                { label: 'Option A3', action: { actionName: 'MyAction', data: { name: 'Joe' }}},
                { label: 'Sub Menu A3', pages: [
                    { label: 'Sub Sub Menu A3.1' },
                    { label: 'Sub Sub Menu A3.2' },
                    { label: 'Sub Sub Menu A3.3' },
                    { label: 'Sub Sub Menu A3.4' }
                ]}
            ]},
            { label: 'Top Level B' },
            { label: 'Top Level C' }
        ]
    },
    App;

moduleForComponent( 'sl-menu', 'Component: Sl-Menu', {
    setup: function() {
        App = startApp();
    },

    teardown: function() {
        Ember.run( App, App.destroy );
    }
});

test( 'Menu creates correct DOM structure', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append();

    expect( 1 );

    equal( $component.find( 'li' ).length, 11 );
});

test( 'Menu properly hides all but root list', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append();

    expect( 1 );

    equal( $component.find( 'li:visible' ).length, 3 );
});

test( 'Menu shows child on hover', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append();

    expect( 2 );

    equal( $component.find( 'li:visible' ).length, 3 );

    $component.find( 'li:visible' ).first().mouseenter();
    equal( $component.find( 'li:visible' ).length, 7 );
});

test( 'Menu closes child on mouse exit', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append(),
        child = $component.find( 'li:visible' ).first();

    expect( 3 );

    equal( $component.find( 'li:visible' ).length, 3 );

    child.mouseenter();
    equal( $component.find( 'li:visible' ).length, 7 );

    child.mouseleave();
    equal( $component.find( 'li:visible' ).length, 3 );
});

test( 'Menu click supports native function', function() {
    expect( 1 );

    var spy = sinon.spy(),
        component,
        $component,
        child;

    modelStub.pages[0].pages[1]['action'] = spy;

    component = this.subject({ menu: modelStub });

    $component = this.append();

    child = $component.find( 'li:visible' ).first();

    triggerEvent( child, 'mouseenter' );

    click( child.find( 'li:visible' )[ 1 ] );

    andThen( function() {
        equal( spy.calledOnce, true );
    });
});

test( 'Menu click supports action names', function() {
    expect( 1 );

    var component    = this.subject({ menu: modelStub }),
        $component   = this.append(),
        child        = $component.find( 'li:visible' ).first(),
        spy          = sinon.spy(),
        targetObject = {
            actionHandler: spy
        };

    component.set( 'actionInitiated', 'actionHandler' );
    component.set( 'targetObject', targetObject );

    triggerEvent( child, 'mouseenter' );

    click( child.find( 'li:visible' )[ 0 ] );

    andThen( function() {
        equal( spy.args[0][0], 'MyAction' );
    });
});

test( 'Menu click supports action names with supporting data', function() {
    expect( 2 );

    var component    = this.subject({ menu: modelStub }),
        $component   = this.append(),
        child        = $component.find( 'li:visible' ).first(),
        spy          = sinon.spy(),
        targetObject = {
            actionHandler: spy
        };

    component.set( 'actionInitiated', 'actionHandler' );
    component.set( 'targetObject', targetObject );

    triggerEvent( child, 'mouseenter' );

    click( child.find( 'li:visible' )[ 2 ] );

    andThen( function() {
        equal( spy.args[0][0], 'MyAction' );
        equal( spy.args[0][1]['name'], 'Joe' );
    });
});

test( 'Menu selection fires proper selection event', function() {
    var component = this.subject({ menu: modelStub }),
        $component = this.append(),
        selectionCounter = 0,
        targetObject = {
            selectionHandler: function( path ) {
                selectionCounter++;
            }
        },
        child1,
        child2,
        child3;

    expect( 1 );

    component.set( 'selectionMade', 'selectionHandler' );
    component.set( 'targetObject', targetObject );

    child1 = $component.find( 'li:visible' ).first();
    child1.trigger( 'mouseenter' );
    child1.trigger( 'click' );

    child2 = child1.find( 'li:visible' ).last();
    child2.trigger( 'mouseenter' );
    child2.trigger( 'click' );

    child3 = child2.find( 'li:visible' ).first();
    child3.trigger( 'mouseenter' );
    child3.trigger( 'click' );

    equal( selectionCounter, 3 );
});
<|endoftext|>


<commit_before>/**
 * jquery.pager.js v0.1.0
 * MIT License
 * author info pls visit: http://luopq.com
 * for more info pls visit: https://github.com/LuoPQ/jquery.pager.js
 */
; (function ($, window, document, undefined) {
    "use strict";
    var defaults = {
        pageIndex: 0,
        pageSize: 6,
        itemCount: 50,
        maxButtonCount: 7,
        prevText: "上一页",
        nextText: "下一页",
        buildPageUrl: null,
        onPageChanged: null
    };

    function Pager($ele, options) {
        this.$ele = $ele;
        this.options = options = $.extend(defaults, options || {});
        this.init();
    }
    Pager.prototype = {
        constructor: Pager,
        init: function () {
            this.renderHtml();
            this.bindEvent();
        },
        renderHtml: function () {
            var options = this.options;

            options.pageCount = Math.ceil(options.itemCount / options.pageSize);
            var html = [];

            //生成上一页的按钮
            if (options.pageIndex > 0) {
                html.push('' + options.prevText + '');
            } else {
                html.push('' + options.prevText + '');
            }

            //这里是关键
            //临时的起始页码中间页码，当页码数量大于显示的最大按钮数时使用
            var tempStartIndex = options.pageIndex - Math.floor(options.maxButtonCount / 2) + 1;

            //计算终止页码，通过max计算一排按钮中的第一个按钮的页码，然后计算出页数量
            var endIndex = Math.min(options.pageCount, Math.max(0, tempStartIndex) + options.maxButtonCount) - 1;
            var startIndex = Math.max(0, endIndex - options.maxButtonCount + 1);

            // 第一页
            if (startIndex > 0) {
                html.push("1 ");
                html.push("...");
            }

            //生成页码按钮
            for (var i = startIndex; i <= endIndex; i++) {
                if (options.pageIndex == i) {
                    html.push('' + (i + 1) + '');
                } else {
                    html.push('' + (i + 1) + '');
                }
            }

            // 最后一页
            if (endIndex < options.pageCount - 1) {
                html.push("... ");
                html.push("" + options.pageCount + " ");
            }

            //生成下一页的按钮
            if (options.pageIndex < options.pageCount - 1) {
                html.push('' + options.nextText + '');
            } else {
                html.push('' + options.nextText + '');
            }

            this.$ele.html(html.join(""));
        },
        bindEvent: function () {
            var that = this;
            that.$ele.on("click", "a", function () {
                that.options.pageIndex = parseInt($(this).attr("page"), 10);
                that.renderHtml();
                that.options.onPageChanged && that.options.onPageChange(that.options.pageIndex);
            })
        },
        buildPageUrl: function () {
            if ($.isFunction(this.options.buildPageUrl)) {
                return this.options.buildPageUrl(pageIndex);
            }
            return "javascript:;";
        },
        getPageIndex: function () {
            return this.options.pageIndex;
        },
        setPageIndex: function (pageIndex) {
            this.options.pageIndex = pageIndex;
            this.renderHtml();
        },
        setItemCount: function (itemCount) {
            this.options.pageIndex = 0;
            this.options.itemCount = itemCount;
            this.renderHtml();
        }
    };

    $.fn.pager = function (options) {
        options = $.extend(defaults, options || {});

        return new Pager($(this), options);
    }

})(jQuery, window, document);<commit_msg>onPageChanged<commit_after>/**
 * jquery.pager.js v0.1.0
 * MIT License
 * author info pls visit: http://luopq.com
 * for more info pls visit: https://github.com/LuoPQ/jquery.pager.js
 */
; (function ($, window, document, undefined) {
    "use strict";
    var defaults = {
        pageIndex: 0,
        pageSize: 6,
        itemCount: 50,
        maxButtonCount: 7,
        prevText: "上一页",
        nextText: "下一页",
        buildPageUrl: null,
        onPageChanged: null
    };

    function Pager($ele, options) {
        this.$ele = $ele;
        this.options = options = $.extend(defaults, options || {});
        this.init();
    }
    Pager.prototype = {
        constructor: Pager,
        init: function () {
            this.renderHtml();
            this.bindEvent();
        },
        renderHtml: function () {
            var options = this.options;

            options.pageCount = Math.ceil(options.itemCount / options.pageSize);
            var html = [];

            //生成上一页的按钮
            if (options.pageIndex > 0) {
                html.push('' + options.prevText + '');
            } else {
                html.push('' + options.prevText + '');
            }

            //这里是关键
            //临时的起始页码中间页码，当页码数量大于显示的最大按钮数时使用
            var tempStartIndex = options.pageIndex - Math.floor(options.maxButtonCount / 2) + 1;

            //计算终止页码，通过max计算一排按钮中的第一个按钮的页码，然后计算出页数量
            var endIndex = Math.min(options.pageCount, Math.max(0, tempStartIndex) + options.maxButtonCount) - 1;
            var startIndex = Math.max(0, endIndex - options.maxButtonCount + 1);

            // 第一页
            if (startIndex > 0) {
                html.push("1 ");
                html.push("...");
            }

            //生成页码按钮
            for (var i = startIndex; i <= endIndex; i++) {
                if (options.pageIndex == i) {
                    html.push('' + (i + 1) + '');
                } else {
                    html.push('' + (i + 1) + '');
                }
            }

            // 最后一页
            if (endIndex < options.pageCount - 1) {
                html.push("... ");
                html.push("" + options.pageCount + " ");
            }

            //生成下一页的按钮
            if (options.pageIndex < options.pageCount - 1) {
                html.push('' + options.nextText + '');
            } else {
                html.push('' + options.nextText + '');
            }

            this.$ele.html(html.join(""));
        },
        bindEvent: function () {
            var that = this;
            that.$ele.on("click", "a", function () {
                that.options.pageIndex = parseInt($(this).attr("page"), 10);
                that.renderHtml();
                that.options.onPageChanged && that.options.onPageChanged(that.options.pageIndex);
            })
        },
        buildPageUrl: function () {
            if ($.isFunction(this.options.buildPageUrl)) {
                return this.options.buildPageUrl(pageIndex);
            }
            return "javascript:;";
        },
        getPageIndex: function () {
            return this.options.pageIndex;
        },
        setPageIndex: function (pageIndex) {
            this.options.pageIndex = pageIndex;
            this.renderHtml();
        },
        setItemCount: function (itemCount) {
            this.options.pageIndex = 0;
            this.options.itemCount = itemCount;
            this.renderHtml();
        }
    };

    $.fn.pager = function (options) {
        options = $.extend(defaults, options || {});

        return new Pager($(this), options);
    }

})(jQuery, window, document);
<|endoftext|>


<commit_before>var net = require('net');
var sys = require('sys');
var expat = require('expat');
var xml = require('./xml');

var NS_XMPP_TLS = exports.NS_XMPP_TLS = 'urn:ietf:params:xml:ns:xmpp-tls';
var NS_STREAM = exports.NS_STREAM = 'http://etherx.jabber.org/streams';

/** A note on events: this base class will emit 'rawStanza' and leaves
    'stanza' to Client & Component. Therefore we won't confuse the
    user with stanzas before authentication has finished.
*/
function Connection() {
    net.Stream.call(this);

    this.charset = 'UTF-8';
    this.allowTLS = true;  /* can be set by user */
    this.addListener('connect', this.startStream);
    this.addListener('data', this.onData);
//    this.addListener('end', this.onEnd);
//    this.addListener('error', this.onError);
}

sys.inherits(Connection, net.Stream);
exports.Connection = Connection;

Connection.prototype.send = function(stanza) {
    if (!this.writable) {
	this.end();
	return;
    }

    if (stanza.root) {
	var el = this.rmStreamNs(stanza.root());
	var self = this;
	el.write(function(s) { self.write(s); });
    }
    else
	this.write(stanza);
};

Connection.prototype.startParser = function() {
    var self = this;
    self.element = null;
    self.parser = new expat.Parser(self.charset);

    self.parser.addListener('startElement', function(name, attrs) {
	if (!self.element && name == 'stream:stream') {
	    self.streamAttrs = attrs;
	    /* We need those xmlns often, store them extra */
	    self.streamNsAttrs = {};
	    for(var k in attrs) {
		if (k == 'xmlns' ||
		    k.substr(0, 6) == 'xmlns:')
		    self.streamNsAttrs[k] = attrs[k];
	    }

	    /* Notify in case we don't wait for <stream:features/> (Component)
	     */
	    self.emit('streamStart', attrs);
	     } else {
	    var child = new xml.Element(name, attrs);
	    if (!self.element) {
		/* A new stanza */
		self.element = self.addStreamNs(child);
	    } else {
		/* A child element of a stanza */
		self.element = self.element.cnode(child);
	    }
	}
    });
    self.parser.addListener('endElement', function(name, attrs) {
	if (!self.element && name == 'stream:stream') {
	    self.end();
	} else if (self.element && name == self.element.name) {
	    if (self.element.parent)
		self.element = self.element.parent;
	    else {
		/* Stanza complete */
		self.onStanza(self.element);
		self.element = null;
	    }
	} else {
	    self.emit('parseError');
	    self.end();
	}
    });
    self.parser.addListener('text', function(str) {
	if (self.element)
	    self.element.t(str);
    });
};

Connection.prototype.startStream = function() {
    this.startParser();

    var tag = "<stream:stream xmlns='" + this.xmlns +
	"' xmlns:stream='" + NS_STREAM + "'" +
	" to='" + this.streamTo + "'";
    if (this.xmppVersion)
	tag += " version='" + this.xmppVersion + "'";
    tag += ">";
    this.send(tag);
};

Connection.prototype.onData = function(data) {
    if (this.parser) {
	if (!this.parser.parse(data, false)) {
	    this.emit('parseError');
	    this.end();
	}
    }
};

/**
 * This is not an event listener, but takes care of the TLS handshake
 * before 'rawStanza' events are emitted to the derived classes.
 */
Connection.prototype.onStanza = function(stanza) {
    if (stanza.is('error', NS_STREAM)) {
	/* TODO: extract error text */
	this.emit('error', stanza);
    } else if (stanza.is('features', NS_STREAM) &&
	       this.allowTLS &&
	       stanza.getChild('starttls', NS_XMPP_TLS)) {
	/* Signal willingness to perform TLS handshake */
	this.send(new xml.Element('starttls', { xmlns: NS_XMPP_TLS }));
    } else if (this.allowTLS &&
	       stanza.is('proceed', NS_XMPP_TLS)) {
	/* Server is waiting for TLS handshake */
	this.setSecure();
	this.addListener('secure', this.startStream);
    } else {
	this.emit('rawStanza', stanza);
    }
};

/**
 *  Add stream xmlns to a stanza, so the user can check for
 * 'jabber:client' etc.
 */
Connection.prototype.addStreamNs = function(stanza) {
    for(var k in this.streamNsAttrs) {
	if (!stanza.attrs[k])
	    stanza.attrs[k] = this.streamNsAttrs[k];
    }
    return stanza;
};

/**
 * Remove superfluous xmlns that were aleady declared in
 * <stream:stream>
 */
Connection.prototype.rmStreamNs = function(stanza) {
    for(var k in this.streamNsAttrs) {
	if (stanza.attrs[k] == this.streamNsAttrs[k])
	    delete stanza.attrs[k];
    }
    return stanza;
};

<commit_msg>Connection: Return stanza on send for debugging<commit_after>var net = require('net');
var sys = require('sys');
var expat = require('expat');
var xml = require('./xml');

var NS_XMPP_TLS = exports.NS_XMPP_TLS = 'urn:ietf:params:xml:ns:xmpp-tls';
var NS_STREAM = exports.NS_STREAM = 'http://etherx.jabber.org/streams';

/** A note on events: this base class will emit 'rawStanza' and leaves
    'stanza' to Client & Component. Therefore we won't confuse the
    user with stanzas before authentication has finished.
*/
function Connection() {
    net.Stream.call(this);

    this.charset = 'UTF-8';
    this.allowTLS = true;  /* can be set by user */
    this.addListener('connect', this.startStream);
    this.addListener('data', this.onData);
//    this.addListener('end', this.onEnd);
//    this.addListener('error', this.onError);
}

sys.inherits(Connection, net.Stream);
exports.Connection = Connection;

Connection.prototype.send = function(stanza) {
    if (!this.writable) {
	this.end();
	return;
    }

    if (stanza.root) {
	var el = this.rmStreamNs(stanza.root());
	var self = this;
	el.write(function(s) { self.write(s); });
	return el;
    }
    else {
	this.write(stanza);
	return stanza;
    }
};

Connection.prototype.startParser = function() {
    var self = this;
    self.element = null;
    self.parser = new expat.Parser(self.charset);

    self.parser.addListener('startElement', function(name, attrs) {
	if (!self.element && name == 'stream:stream') {
	    self.streamAttrs = attrs;
	    /* We need those xmlns often, store them extra */
	    self.streamNsAttrs = {};
	    for(var k in attrs) {
		if (k == 'xmlns' ||
		    k.substr(0, 6) == 'xmlns:')
		    self.streamNsAttrs[k] = attrs[k];
	    }

	    /* Notify in case we don't wait for <stream:features/> (Component)
	     */
	    self.emit('streamStart', attrs);
	     } else {
	    var child = new xml.Element(name, attrs);
	    if (!self.element) {
		/* A new stanza */
		self.element = self.addStreamNs(child);
	    } else {
		/* A child element of a stanza */
		self.element = self.element.cnode(child);
	    }
	}
    });
    self.parser.addListener('endElement', function(name, attrs) {
	if (!self.element && name == 'stream:stream') {
	    self.end();
	} else if (self.element && name == self.element.name) {
	    if (self.element.parent)
		self.element = self.element.parent;
	    else {
		/* Stanza complete */
		self.onStanza(self.element);
		self.element = null;
	    }
	} else {
	    self.emit('parseError');
	    self.end();
	}
    });
    self.parser.addListener('text', function(str) {
	if (self.element)
	    self.element.t(str);
    });
};

Connection.prototype.startStream = function() {
    this.startParser();

    var tag = "<stream:stream xmlns='" + this.xmlns +
	"' xmlns:stream='" + NS_STREAM + "'" +
	" to='" + this.streamTo + "'";
    if (this.xmppVersion)
	tag += " version='" + this.xmppVersion + "'";
    tag += ">";
    this.send(tag);
};

Connection.prototype.onData = function(data) {
    if (this.parser) {
	if (!this.parser.parse(data, false)) {
	    this.emit('parseError');
	    this.end();
	}
    }
};

/**
 * This is not an event listener, but takes care of the TLS handshake
 * before 'rawStanza' events are emitted to the derived classes.
 */
Connection.prototype.onStanza = function(stanza) {
    if (stanza.is('error', NS_STREAM)) {
	/* TODO: extract error text */
	this.emit('error', stanza);
    } else if (stanza.is('features', NS_STREAM) &&
	       this.allowTLS &&
	       stanza.getChild('starttls', NS_XMPP_TLS)) {
	/* Signal willingness to perform TLS handshake */
	this.send(new xml.Element('starttls', { xmlns: NS_XMPP_TLS }));
    } else if (this.allowTLS &&
	       stanza.is('proceed', NS_XMPP_TLS)) {
	/* Server is waiting for TLS handshake */
	this.setSecure();
	this.addListener('secure', this.startStream);
    } else {
	this.emit('rawStanza', stanza);
    }
};

/**
 *  Add stream xmlns to a stanza, so the user can check for
 * 'jabber:client' etc.
 */
Connection.prototype.addStreamNs = function(stanza) {
    for(var k in this.streamNsAttrs) {
	if (!stanza.attrs[k])
	    stanza.attrs[k] = this.streamNsAttrs[k];
    }
    return stanza;
};

/**
 * Remove superfluous xmlns that were aleady declared in
 * <stream:stream>
 */
Connection.prototype.rmStreamNs = function(stanza) {
    for(var k in this.streamNsAttrs) {
	if (stanza.attrs[k] == this.streamNsAttrs[k])
	    delete stanza.attrs[k];
    }
    return stanza;
};

<|endoftext|>


<commit_before><commit_msg>Removing empty file that is unused<commit_after><|endoftext|>


<commit_before>import journey from 'lib/journey/journey.js';
import events from "lib/journey/utils/events";
import Ractive from "Ractive.js";
import fade from "lib/fade.js";
import 'lib/prism.js';
import "./config/routes.js";
import menu from "./menu/menu.js";
import "lib/bootstrap.js";
import "./animationMonitor.js";

//let contextPath = "/build";
//let contextPath = "/journey-examples/";
let contextPath = "";

menu.init( { target: "#menu", fallbackMenu: "#menu-home" } );

if (location.pathname == "/" || location.pathname == contextPath || location.pathname == "") {
	//history.replaceState(null, null, "/home"); // change url to /home as a default
}

Ractive.transitions = {
	fade
};

journey.on( events.ENTERED, function ( options ) {
	Prism.highlightAll();
} );

journey.start( {
	target: "#container",
	debug: Ractive.DEBUG = true,
	fallback: '/notFound',
	base: contextPath,
	defaultRoute: '/home',
	useOnHashChange: false,
	useHash: false,
	hash: '#!'
} );
<commit_msg>use correct base for online examples<commit_after>import journey from 'lib/journey/journey.js';
import events from "lib/journey/utils/events";
import Ractive from "Ractive.js";
import fade from "lib/fade.js";
import 'lib/prism.js';
import "./config/routes.js";
import menu from "./menu/menu.js";
import "lib/bootstrap.js";
import "./animationMonitor.js";

//let contextPath = "/build";
let contextPath = "/journey-examples/";
//let contextPath = "";

menu.init( { target: "#menu", fallbackMenu: "#menu-home" } );

if (location.pathname == "/" || location.pathname == contextPath || location.pathname == "") {
	//history.replaceState(null, null, "/home"); // change url to /home as a default
}

Ractive.transitions = {
	fade
};

journey.on( events.ENTERED, function ( options ) {
	Prism.highlightAll();
} );

journey.start( {
	target: "#container",
	debug: Ractive.DEBUG = true,
	fallback: '/notFound',
	base: contextPath,
	defaultRoute: '/home',
	useOnHashChange: false,
	useHash: false,
	hash: '#!'
} );
<|endoftext|>


<commit_before>// Copyright (c) 2016, Regents of the University of Michigan.
// All rights reserved. See LICENSE.txt for details.

// Authored by Jon Earley (earleyj@umich.edu)

var app = app || {};

app.searchables = m.prop()
app.search_switcher = m.prop()
app.data = m.prop()

app.state = {

  // Initialize Mithril
  init: function() {
    var mount_element = document.getElementById('mount-container')

    m.route(mount_element, "/", {
      "/": app.Home,
      "/search/:searchable_uid": app.Home,
      "/search/:searchable_uid/field/:field_uid": app.Home,
      "/search/:searchable_uid/field/:field_uid/query/:query": app.Home,
      "/search/:searchable_uid/field/:field_uid/query/:query/facets/:facets.../": app.Home,
      "/search/:searchable_uid/field/:field_uid/query/:query/page/:page": app.Home,
    });
  },

  // Initialize Pride and related components.
  initPride: function() {
    var searchables = []
    var search_objects = []

    _.each(app.settings.datastores, function(ds) {
      var datastore = app.getDatastore(ds)

      if (datastore) {
        searchables.push({
          uid: datastore.get('uid'),
          name: datastore.get('metadata').name
        })

        search_objects.push(datastore.baseSearch())
      }
    })

    // Add results observers to each search object.
    _.each(search_objects, function(search_object) {
      search_object.setMute(true)

      // results records observer
      search_object.resultsObservers.add(function(data) {
        app.setSearchableObservers(search_object.uid, data, 'records')
      })

      // Set data observer
      search_object.setDataObservers.add(function(data) {
        app.setSearchableObservers(search_object.uid, data, 'metadata')
      })

      // run data observer
      search_object.runDataObservers.add(function(data) {
        app.setSearchableObservers(search_object.uid, data, 'metadata')
      })

      search_object.set({count: 10})

      // search object facets observer
      search_object.facetsObservers.add(function(facets_data) {
        _.each(facets_data, function(facet) {

          facet.resultsObservers.add(function(results) {
            app.setFacetObservers(search_object.uid, facet, 'results', results) // searchable_uid, facet_object, type, data
          })

          facet.setDataObservers.add(function(data) {
            app.setFacetObservers(search_object.uid, facet, 'data', data)
          })
        })
      })

    })

    _.each(app.settings.multisearches, function(ms) {
      var multisearch = app.createMultiSearch(ms)

      multisearch.set({count: 3})

      if (multisearch) {
        search_objects.push(multisearch)

        searchables.push({
          uid: ms.uid,
          name: ms.name
        })
      }
    })

    app.selected_field('all_fields') // TODO temp, replace with first field

    var sorted_searchables = []

    _.each(app.settings.searchables_order, function(searchable) {
      sorted_searchables.push(_.findWhere(searchables, {uid: searchable}))
    })

    app.search_switcher(new Pride.Util.SearchSwitcher(
      search_objects[0],
      search_objects.slice(1)
    ))

    app.searchables(sorted_searchables)
    m.redraw()

    app.updateRoute()

    Pride.Messenger.addObserver(function(message) {
      app.Messages.add(message);
      m.redraw()
    })

    app.switchToSearchable('quicksearch-bento') // TODO this is temporary solution to defaulting to quicksearch
  }
}

window.onload = function() {
  app.state.init()
  initPride()
}

app.createMultiSearch = function(ms) {
  var is_valid = false
  var ms_search_array = []

  _.each(ms.datastores, function(ds_uid) {
    var ds = app.getDatastore(ds_uid)
    if (ds) {
      var search_object = ds.baseSearch()

      ms_search_array.push(search_object)
      is_valid = true
    }
  })

  _.each(ms_search_array, function(search_object) {
    search_object.resultsObservers.add(function(records) {
      app.setSearchableObservers(search_object.uid, records, 'records', ms)
    })

    search_object.setDataObservers.add(function(data) {
      app.setSearchableObservers(search_object.uid, data, 'metadata', ms)
    })

    search_object.runDataObservers.add(function(data) {
      app.setSearchableObservers(search_object.uid, data, 'metadata', ms)
    })
  })

  if (is_valid) {
    return new Pride.Util.MultiSearch(ms.uid, true, ms_search_array)
  } else {
    return false
  }

}

app.getDatastore = function(uid) {
  var is_datastore = false

  Pride.AllDatastores.each(function(ds) {
    if (uid == ds.get('uid')) {
      is_datastore = ds
    }
  })

  return is_datastore
}

app.getSelectedDatastore = function() {
  var uid = undefined

  if (app.search_switcher()) {
    uid = app.search_switcher().uid
  }

  return uid
}

/*
  uid:           datastore uid
  observer_data: observer results/data
  type:          "records" or "metadata"
  multisearch:   true or false
*/
app.setSearchableObservers = function(searchable_uid, observer_data, type, multisearch) {
  var data = app.data()
  var path = searchable_uid + "." + type

  if (!data) {
    data = {}
  }

  if (multisearch) {
    path = multisearch.uid + ".datastores." + searchable_uid + "." + type
    setValue(data, multisearch.uid + ".is_multisearch", true)
  } else {
    setValue(data, searchable_uid + ".is_multisearch", false)
  }

  setValue(data, path, observer_data)
  app.data(data)

  m.redraw()
}

/*
  searchable_uid:
  facet_object
  type:            facet name or "results"
  data:            facet data
*/
app.setFacetObservers = function(searchable_uid, facet_object, type, observer_data) {

  /*
    // example of data/model structure for facets

    databases = {
      facets: [
        author: {
          facet_object: {}
          results: [
            /... facets results
          ]
          data: {}
        },
        new: {
          // facet_object
          results: [
            /... facets results
          ],
          data {}
        }
      ]
    }
  */

  var path = searchable_uid + ".facets"
  var data = app.data()

  if (!data[searchable_uid].facets) {
    // if the datastore doesn't have facets as a key, create an empty
    // array and initialize
    setValue(data, path, {})
  }

  if (type == 'results') {
    path = path + "." + facet_object.uid + ".results"
    setValue(data, path, observer_data)
  } else {
    path = path + "." + facet_object.uid + ".metadata"
    setValue(data, path, observer_data)
  }

  app.data(data)
  m.redraw()
}

app.isMultisearch = function(uid) {
  if (!uid) {
    if (app.search_switcher()) {
      uid = app.search_switcher().uid
    } else {
      return undefined
    }
  }

  if (app.data() && app.data()[uid] && app.data()[uid].is_multisearch) {
    return true
  }

  return false
}<commit_msg>route quickfix<commit_after>// Copyright (c) 2016, Regents of the University of Michigan.
// All rights reserved. See LICENSE.txt for details.

// Authored by Jon Earley (earleyj@umich.edu)

var app = app || {};

app.searchables = m.prop()
app.search_switcher = m.prop()
app.data = m.prop()

app.state = {

  // Initialize Mithril
  init: function() {
    var mount_element = document.getElementById('mount-container')

    m.route(mount_element, "/", {
      "/": app.Home,
      "/search/:searchable_uid": app.Home,
      "/search/:searchable_uid/field/:field_uid": app.Home,
      "/search/:searchable_uid/field/:field_uid/query/:query": app.Home,
      "/search/:searchable_uid/field/:field_uid/query/:query/facets/:facets.../": app.Home,
      "/search/:searchable_uid/field/:field_uid/query/:query/page/:page": app.Home,
    });
  },

  // Initialize Pride and related components.
  initPride: function() {
    var searchables = []
    var search_objects = []

    _.each(app.settings.datastores, function(ds) {
      var datastore = app.getDatastore(ds)

      if (datastore) {
        searchables.push({
          uid: datastore.get('uid'),
          name: datastore.get('metadata').name
        })

        search_objects.push(datastore.baseSearch())
      }
    })

    // Add results observers to each search object.
    _.each(search_objects, function(search_object) {
      search_object.setMute(true)

      // results records observer
      search_object.resultsObservers.add(function(data) {
        app.setSearchableObservers(search_object.uid, data, 'records')
      })

      // Set data observer
      search_object.setDataObservers.add(function(data) {
        app.setSearchableObservers(search_object.uid, data, 'metadata')
      })

      // run data observer
      search_object.runDataObservers.add(function(data) {
        app.setSearchableObservers(search_object.uid, data, 'metadata')
      })

      search_object.set({count: 10})

      // search object facets observer
      search_object.facetsObservers.add(function(facets_data) {
        _.each(facets_data, function(facet) {

          facet.resultsObservers.add(function(results) {
            app.setFacetObservers(search_object.uid, facet, 'results', results) // searchable_uid, facet_object, type, data
          })

          facet.setDataObservers.add(function(data) {
            app.setFacetObservers(search_object.uid, facet, 'data', data)
          })
        })
      })

    })

    _.each(app.settings.multisearches, function(ms) {
      var multisearch = app.createMultiSearch(ms)

      multisearch.set({count: 3})

      if (multisearch) {
        search_objects.push(multisearch)

        searchables.push({
          uid: ms.uid,
          name: ms.name
        })
      }
    })

    app.selected_field('all_fields') // TODO temp, replace with first field

    var sorted_searchables = []

    _.each(app.settings.searchables_order, function(searchable) {
      sorted_searchables.push(_.findWhere(searchables, {uid: searchable}))
    })

    app.search_switcher(new Pride.Util.SearchSwitcher(
      search_objects[0],
      search_objects.slice(1)
    ))

    app.searchables(sorted_searchables)
    m.redraw()

    Pride.Messenger.addObserver(function(message) {
      app.Messages.add(message);
      m.redraw()
    })

    app.switchToSearchable('quicksearch-bento') // TODO this is temporary solution to defaulting to quicksearch

    app.updateRoute()
  }
}

window.onload = function() {
  app.state.init()
  initPride()
}

app.createMultiSearch = function(ms) {
  var is_valid = false
  var ms_search_array = []

  _.each(ms.datastores, function(ds_uid) {
    var ds = app.getDatastore(ds_uid)
    if (ds) {
      var search_object = ds.baseSearch()

      ms_search_array.push(search_object)
      is_valid = true
    }
  })

  _.each(ms_search_array, function(search_object) {
    search_object.resultsObservers.add(function(records) {
      app.setSearchableObservers(search_object.uid, records, 'records', ms)
    })

    search_object.setDataObservers.add(function(data) {
      app.setSearchableObservers(search_object.uid, data, 'metadata', ms)
    })

    search_object.runDataObservers.add(function(data) {
      app.setSearchableObservers(search_object.uid, data, 'metadata', ms)
    })
  })

  if (is_valid) {
    return new Pride.Util.MultiSearch(ms.uid, true, ms_search_array)
  } else {
    return false
  }

}

app.getDatastore = function(uid) {
  var is_datastore = false

  Pride.AllDatastores.each(function(ds) {
    if (uid == ds.get('uid')) {
      is_datastore = ds
    }
  })

  return is_datastore
}

app.getSelectedDatastore = function() {
  var uid = undefined

  if (app.search_switcher()) {
    uid = app.search_switcher().uid
  }

  return uid
}

/*
  uid:           datastore uid
  observer_data: observer results/data
  type:          "records" or "metadata"
  multisearch:   true or false
*/
app.setSearchableObservers = function(searchable_uid, observer_data, type, multisearch) {
  var data = app.data()
  var path = searchable_uid + "." + type

  if (!data) {
    data = {}
  }

  if (multisearch) {
    path = multisearch.uid + ".datastores." + searchable_uid + "." + type
    setValue(data, multisearch.uid + ".is_multisearch", true)
  } else {
    setValue(data, searchable_uid + ".is_multisearch", false)
  }

  setValue(data, path, observer_data)
  app.data(data)

  m.redraw()
}

/*
  searchable_uid:
  facet_object
  type:            facet name or "results"
  data:            facet data
*/
app.setFacetObservers = function(searchable_uid, facet_object, type, observer_data) {

  /*
    // example of data/model structure for facets

    databases = {
      facets: [
        author: {
          facet_object: {}
          results: [
            /... facets results
          ]
          data: {}
        },
        new: {
          // facet_object
          results: [
            /... facets results
          ],
          data {}
        }
      ]
    }
  */

  var path = searchable_uid + ".facets"
  var data = app.data()

  if (!data[searchable_uid].facets) {
    // if the datastore doesn't have facets as a key, create an empty
    // array and initialize
    setValue(data, path, {})
  }

  if (type == 'results') {
    path = path + "." + facet_object.uid + ".results"
    setValue(data, path, observer_data)
  } else {
    path = path + "." + facet_object.uid + ".metadata"
    setValue(data, path, observer_data)
  }

  app.data(data)
  m.redraw()
}

app.isMultisearch = function(uid) {
  if (!uid) {
    if (app.search_switcher()) {
      uid = app.search_switcher().uid
    } else {
      return undefined
    }
  }

  if (app.data() && app.data()[uid] && app.data()[uid].is_multisearch) {
    return true
  }

  return false
}<|endoftext|>