<commit_before>import {
  Permissions,
  Groups,
  AccessMasks,
  PrivilegesSchema,
  PermissionsSchema,
} from '../organization';
/* eslint-disable no-bitwise */
// TODO make object
export const Models = {
  USER: 1,
  PROPOSAL: 2,
  STATEMENT: 4,
  FLAG: 8,
  S_LIKE: 16,
  POLL: 32,
  VOTE: 64,
  NOTIFICATION: 128,
  WORKTEAM: 256,
  ACTIVITY: 512,
  DISCUSSION: 1024,
  COMMENT: 2048,
  REQUEST: 4096,
  TAG: 8192,
};

/* GENERATOR_FN */
/* eslint-disable no-unused-vars */
function tagReadControl(viewer, data) {
  console.error('Access control for Tag not implemented');
  return true;
}
function tagWriteControl(viewer, data) {
  console.error('Access control for Tag not implemented');
  return true;
}
function requestReadControl(viewer, data) {
  console.error('Access control not implemented');
  return true;
}
function requestWriteControl(viewer, data) {
  console.error('Access control not implemented');
  return true;
}

function checkIfMember(viewer, resource) {
  if (resource) {
    if (resource.workTeamId) {
      // assumes there exist only workteams
      if (viewer.groups & Groups.SYSTEM) {
        return true;
      }
      return (
        viewer.wtMemberships &&
        viewer.wtMemberships.includes(resource.workTeamId)
      );
    }
    return true; // is not owned by wt/group
  }
  return false; // since no membership is required
}

function userWriteControl(viewer, data) {
  if (data.id && Object.keys(data).length === 1) {
    if ((viewer.permissions & Permissions.DELETE_ACCOUNTS) > 0) {
      return true;
    }
    return false;
  }
  // own data can be changed
  if (
    viewer &&
    viewer.id == data.id // eslint-disable-line eqeqeq
  ) {
    if (!(viewer.permissions & Permissions.CHANGE_OWN_PROFILE)) {
      return false;
    }
    if (data.name || data.surname) {
      return viewer.groups === Groups.GUEST;
    }
    if (data.groups == null) {
      return true; // Nobody can change his own memberships
    }
  }
  if ((viewer.groups & Groups.SYSTEM) > 0) {
    // to set email as verified, reset password,
    if (data.email || data.password) {
      return true;
    }
  }
  if (viewer.permissions & Permissions.MUTATE_PROFILES) {
    if (data.thumbnail || data.dataUrl || data.name || data.surname) {
      return true;
    }
    if (data.groups != null) {
      if (
        viewer.privileges &
        (PrivilegesSchema[Groups.ADMIN] | PrivilegesSchema[Groups.SUPER_USER])
      ) {
        return true;
        // TODO further checks!
      }
    }
  }
  if (data.userId && (viewer.permissions & Permissions.DELETE_ACCOUNTS) > 0) {
    return true;
  }

  return false;
}

function userReadControl(viewer, data) {
  return (
    // eslint-disable-next-line eqeqeq
    viewer.id == data.id ||
    viewer.groups === Groups.SYSTEM ||
    (viewer.permissions & AccessMasks.LEVEL_1) > 0
  );
}

function proposalReadControl(viewer, data) {
  if (viewer.permissions & Permissions.VIEW_PROPOSALS) {
    return checkIfMember(viewer, data);
  }
  return false;
}

function proposalWriteControl(viewer, data) {
  if (data.workTeamId) {
    if (data.isCoordinator) {
      return true;
    }
    return viewer.permissions & PermissionsSchema[Groups.ADMIN];
  } else if (viewer.permissions & PermissionsSchema[Groups.RELATOR]) {
    if (data.id && data.state) {
      // updates
      if (viewer.permissions & Permissions.MODIFY_PROPOSALS) {
        return true;
      }
      return false;
    }
    return true;
  } else if (data.state === 'survey') {
    if (viewer.permissions & Permissions.PUBLISH_SURVEYS) {
      return true;
    }
  }
  return false;
}

function statementReadControl(viewer, data) {
  if (viewer.permissions & Permissions.VIEW_STATEMENTS) {
    return checkIfMember(viewer, data.proposal);
  }
  return false;
}

function statementWriteControl(viewer, data) {
  if (viewer.permissions & Permissions.MODIFY_OWN_STATEMENTS) {
    return checkIfMember(viewer, data.proposal);
  }
  return false;
}

function flagReadControl(viewer, data) {
  if (viewer.permissions & Permissions.DELETE_STATEMENTS) {
    return true;
  }
  return false;
}

function flagWriteControl(viewer, data) {
  if (data.content) {
    // = flagging
    if (viewer.permissions & Permissions.FLAG_STATEMENTS) {
      return true;
    }
  } else if (viewer.permissions & Permissions.DELETE_STATEMENTS) {
    return true;
  }
  return false;
}

function stmtLikeReadControl(viewer, data) {
  if (viewer.permissions & AccessMasks.LEVEL_1) {
    return true;
  }
  return false;
}
function stmtLikeWriteControl(viewer, data) {
  if (viewer.permissions & Permissions.LIKE) {
    return true;
  }
  return false;
}

function pollReadControl(viewer, data) {
  if (
    viewer.permissions &
    (AccessMasks.LEVEL_1 | Permissions.PUBLISH_PROPOSALS)
  ) {
    return true;
  }
  return false;
}
function pollWriteControl(viewer, data) {
  if (viewer.permissions & PermissionsSchema[Groups.RELATOR]) {
    if (data.closedAt) {
      if (viewer.permissions & Permissions.CLOSE_POLLS) {
        return true;
      }
      return false;
    }
    return true;
  } else if (data.isCoordinator) {
    return true;
  }
  return viewer.permissions & PermissionsSchema[Groups.ADMIN];
}

function voteReadControl(viewer, data) {
  if (viewer.permissions & AccessMasks.LEVEL_1) {
    return checkIfMember(viewer, data.proposal);
  }
  return false;
}
function voteWriteControl(viewer, data) {
  if (data.proposal.state === 'survey') {
    if (viewer.permissions & Permissions.TAKE_SURVEYS) {
      return checkIfMember(viewer, data.proposal);
    }
  } else if (viewer.permissions & Permissions.VOTE) {
    return checkIfMember(viewer, data.proposal);
  }
  return false;
}

function notificationReadControl(viewer, data) {
  if (viewer.permissions & AccessMasks.LEVEL_0) {
    return true;
  }
  return false;
}
function notificationWriteControl(viewer, data) {
  if (
    viewer.permissions &
    (Permissions.NOTIFY_GROUPS | Permissions.NOTIFY_ALL)
  ) {
    return true;
  }
  return false;
}

function activityReadControl(viewer, data) {
  if (viewer.permissions & AccessMasks.LEVEL_0) {
    return true;
  }
  return false;
}
function activityWriteControl(viewer, data) {
  if (
    (viewer.permissions & AccessMasks.LEVEL_0) > 0 ||
    (viewer.groups & Groups.SYSTEM) > 0
  ) {
    return true;
  }
  return false;
}

function workTeamReadControl(viewer, data) {
  if (viewer.permissions & AccessMasks.LEVEL_0) {
    return true;
  }
  return false;
}
function workTeamWriteControl(viewer, data) {
  if (viewer.permissions & Permissions.CREATE_WORKTEAMS) {
    if (data.coordinatorId || data.name) {
      if (viewer.permissions & Permissions.CREATE_WORKTEAMS) {
        return true;
      }
      return false;
    }
    return true;
  }
  return false;
}

function discussionReadControl(viewer, data) {
  if (viewer.wtMemberships.includes(data.work_team_id)) {
    return true;
  }
  return false;
}
function discussionWriteControl(viewer, data) {
  if (data.workTeamId) {
    if (data.isCoordinator) {
      return true;
    }
    return viewer.permissions & PermissionsSchema[Groups.ADMIN];
  } else if (viewer.permissions & Permissions.PUBLISH_DISCUSSIONS) {
    return true;
  }
  return false;
}
function commentReadControl(viewer, data) {
  if (viewer.wtMemberships.includes(data.discussion.workTeamId)) {
    // eslint-disable-line
    return true;
  }
  return false;
}
function commentWriteControl(viewer, data) {
  if (data.discussion.closedAt) {
    return false;
  }
  if (data.creating) {
    // TODO check group etc
    if (viewer.wtMemberships.includes(data.discussion.workTeamId)) {
      // eslint-disable-line
      return (viewer.permissions & Permissions.MAKE_COMMENT) > 0;
    }
  }
  // eslint-disable-next-line eqeqeq
  return viewer.id && viewer.id == data.authorId;
}

/* eslint-enable no-unused-vars */

const ATypes = {
  WRITE: 1,
  READ: 2,
};
const accessFilter = {
  /* GENERATOR_FILTER */
  [Models.TAG]: {
    [ATypes.WRITE]: tagWriteControl,
    [ATypes.READ]: tagReadControl,
  },
  [Models.REQUEST]: {
    [ATypes.WRITE]: requestWriteControl,
    [ATypes.READ]: requestReadControl,
  },
  [Models.USER]: {
    [ATypes.WRITE]: userWriteControl,
    [ATypes.READ]: userReadControl,
  },
  [Models.PROPOSAL]: {
    [ATypes.WRITE]: proposalWriteControl,
    [ATypes.READ]: proposalReadControl,
  },
  [Models.STATEMENT]: {
    [ATypes.WRITE]: statementWriteControl,
    [ATypes.READ]: statementReadControl,
  },
  [Models.FLAG]: {
    [ATypes.WRITE]: flagWriteControl,
    [ATypes.READ]: flagReadControl,
  },
  [Models.S_LIKE]: {
    [ATypes.WRITE]: stmtLikeWriteControl,
    [ATypes.READ]: stmtLikeReadControl,
  },
  [Models.POLL]: {
    [ATypes.WRITE]: pollWriteControl,
    [ATypes.READ]: pollReadControl,
  },
  [Models.VOTE]: {
    [ATypes.WRITE]: voteWriteControl,
    [ATypes.READ]: voteReadControl,
  },
  [Models.NOTIFICATION]: {
    [ATypes.WRITE]: notificationWriteControl,
    [ATypes.READ]: notificationReadControl,
  },
  [Models.ACTIVITY]: {
    [ATypes.WRITE]: activityWriteControl,
    [ATypes.READ]: activityReadControl,
  },
  [Models.WORKTEAM]: {
    [ATypes.WRITE]: workTeamWriteControl,
    [ATypes.READ]: workTeamReadControl,
  },
  [Models.DISCUSSION]: {
    [ATypes.WRITE]: discussionWriteControl,
    [ATypes.READ]: discussionReadControl,
  },
  [Models.COMMENT]: {
    [ATypes.WRITE]: commentWriteControl,
    [ATypes.READ]: commentReadControl,
  },
};

export const canMutate = (viewer, data, model) =>
  accessFilter[model][ATypes.WRITE](viewer, data);

export const canSee = (viewer, data, model) =>
  accessFilter[model][ATypes.READ](viewer, data);
<commit_msg>allowed viewer to create statements on surveys<commit_after>import {
  Permissions,
  Groups,
  AccessMasks,
  PrivilegesSchema,
  PermissionsSchema,
} from '../organization';
/* eslint-disable no-bitwise */
// TODO make object
export const Models = {
  USER: 1,
  PROPOSAL: 2,
  STATEMENT: 4,
  FLAG: 8,
  S_LIKE: 16,
  POLL: 32,
  VOTE: 64,
  NOTIFICATION: 128,
  WORKTEAM: 256,
  ACTIVITY: 512,
  DISCUSSION: 1024,
  COMMENT: 2048,
  REQUEST: 4096,
  TAG: 8192,
};

/* GENERATOR_FN */
/* eslint-disable no-unused-vars */
function tagReadControl(viewer, data) {
  console.error('Access control for Tag not implemented');
  return true;
}
function tagWriteControl(viewer, data) {
  console.error('Access control for Tag not implemented');
  return true;
}
function requestReadControl(viewer, data) {
  console.error('Access control not implemented');
  return true;
}
function requestWriteControl(viewer, data) {
  console.error('Access control not implemented');
  return true;
}

function checkIfMember(viewer, resource) {
  if (resource) {
    if (resource.workTeamId) {
      // assumes there exist only workteams
      if (viewer.groups & Groups.SYSTEM) {
        return true;
      }
      return (
        viewer.wtMemberships &&
        viewer.wtMemberships.includes(resource.workTeamId)
      );
    }
    return true; // is not owned by wt/group
  }
  return false; // since no membership is required
}

function userWriteControl(viewer, data) {
  if (data.id && Object.keys(data).length === 1) {
    if ((viewer.permissions & Permissions.DELETE_ACCOUNTS) > 0) {
      return true;
    }
    return false;
  }
  // own data can be changed
  if (
    viewer &&
    viewer.id == data.id // eslint-disable-line eqeqeq
  ) {
    if (!(viewer.permissions & Permissions.CHANGE_OWN_PROFILE)) {
      return false;
    }
    if (data.name || data.surname) {
      return viewer.groups === Groups.GUEST;
    }
    if (data.groups == null) {
      return true; // Nobody can change his own memberships
    }
  }
  if ((viewer.groups & Groups.SYSTEM) > 0) {
    // to set email as verified, reset password,
    if (data.email || data.password) {
      return true;
    }
  }
  if (viewer.permissions & Permissions.MUTATE_PROFILES) {
    if (data.thumbnail || data.dataUrl || data.name || data.surname) {
      return true;
    }
    if (data.groups != null) {
      if (
        viewer.privileges &
        (PrivilegesSchema[Groups.ADMIN] | PrivilegesSchema[Groups.SUPER_USER])
      ) {
        return true;
        // TODO further checks!
      }
    }
  }
  if (data.userId && (viewer.permissions & Permissions.DELETE_ACCOUNTS) > 0) {
    return true;
  }

  return false;
}

function userReadControl(viewer, data) {
  return (
    // eslint-disable-next-line eqeqeq
    viewer.id == data.id ||
    viewer.groups === Groups.SYSTEM ||
    (viewer.permissions & AccessMasks.LEVEL_1) > 0
  );
}

function proposalReadControl(viewer, data) {
  if (viewer.permissions & Permissions.VIEW_PROPOSALS) {
    return checkIfMember(viewer, data);
  }
  return false;
}

function proposalWriteControl(viewer, data) {
  if (data.workTeamId) {
    if (data.isCoordinator) {
      return true;
    }
    return viewer.permissions & PermissionsSchema[Groups.ADMIN];
  } else if (viewer.permissions & PermissionsSchema[Groups.RELATOR]) {
    if (data.id && data.state) {
      // updates
      if (viewer.permissions & Permissions.MODIFY_PROPOSALS) {
        return true;
      }
      return false;
    }
    return true;
  } else if (data.state === 'survey') {
    if (viewer.permissions & Permissions.PUBLISH_SURVEYS) {
      return true;
    }
  }
  return false;
}

function statementReadControl(viewer, data) {
  if (viewer.permissions & Permissions.VIEW_STATEMENTS) {
    return checkIfMember(viewer, data.proposal);
  }
  return false;
}

function statementWriteControl(viewer, data) {
  if (
    data.proposal.state === 'survey' &&
    viewer.permissions & Permissions.TAKE_SURVEYS
  ) {
    return checkIfMember(viewer, data.proposal);
  }
  if (viewer.permissions & Permissions.MODIFY_OWN_STATEMENTS) {
    return checkIfMember(viewer, data.proposal);
  }
  return false;
}

function flagReadControl(viewer, data) {
  if (viewer.permissions & Permissions.DELETE_STATEMENTS) {
    return true;
  }
  return false;
}

function flagWriteControl(viewer, data) {
  if (data.content) {
    // = flagging
    if (viewer.permissions & Permissions.FLAG_STATEMENTS) {
      return true;
    }
  } else if (viewer.permissions & Permissions.DELETE_STATEMENTS) {
    return true;
  }
  return false;
}

function stmtLikeReadControl(viewer, data) {
  if (viewer.permissions & AccessMasks.LEVEL_1) {
    return true;
  }
  return false;
}
function stmtLikeWriteControl(viewer, data) {
  if (viewer.permissions & Permissions.LIKE) {
    return true;
  }
  return false;
}

function pollReadControl(viewer, data) {
  if (
    viewer.permissions &
    (AccessMasks.LEVEL_1 | Permissions.PUBLISH_PROPOSALS)
  ) {
    return true;
  }
  return false;
}
function pollWriteControl(viewer, data) {
  if (viewer.permissions & PermissionsSchema[Groups.RELATOR]) {
    if (data.closedAt) {
      if (viewer.permissions & Permissions.CLOSE_POLLS) {
        return true;
      }
      return false;
    }
    return true;
  } else if (data.isCoordinator) {
    return true;
  }
  return viewer.permissions & PermissionsSchema[Groups.ADMIN];
}

function voteReadControl(viewer, data) {
  if (viewer.permissions & AccessMasks.LEVEL_1) {
    return checkIfMember(viewer, data.proposal);
  }
  return false;
}
function voteWriteControl(viewer, data) {
  if (data.proposal.state === 'survey') {
    if (viewer.permissions & Permissions.TAKE_SURVEYS) {
      return checkIfMember(viewer, data.proposal);
    }
  } else if (viewer.permissions & Permissions.VOTE) {
    return checkIfMember(viewer, data.proposal);
  }
  return false;
}

function notificationReadControl(viewer, data) {
  if (viewer.permissions & AccessMasks.LEVEL_0) {
    return true;
  }
  return false;
}
function notificationWriteControl(viewer, data) {
  if (
    viewer.permissions &
    (Permissions.NOTIFY_GROUPS | Permissions.NOTIFY_ALL)
  ) {
    return true;
  }
  return false;
}

function activityReadControl(viewer, data) {
  if (viewer.permissions & AccessMasks.LEVEL_0) {
    return true;
  }
  return false;
}
function activityWriteControl(viewer, data) {
  if (
    (viewer.permissions & AccessMasks.LEVEL_0) > 0 ||
    (viewer.groups & Groups.SYSTEM) > 0
  ) {
    return true;
  }
  return false;
}

function workTeamReadControl(viewer, data) {
  if (viewer.permissions & AccessMasks.LEVEL_0) {
    return true;
  }
  return false;
}
function workTeamWriteControl(viewer, data) {
  if (viewer.permissions & Permissions.CREATE_WORKTEAMS) {
    if (data.coordinatorId || data.name) {
      if (viewer.permissions & Permissions.CREATE_WORKTEAMS) {
        return true;
      }
      return false;
    }
    return true;
  }
  return false;
}

function discussionReadControl(viewer, data) {
  if (viewer.wtMemberships.includes(data.work_team_id)) {
    return true;
  }
  return false;
}
function discussionWriteControl(viewer, data) {
  if (data.workTeamId) {
    if (data.isCoordinator) {
      return true;
    }
    return viewer.permissions & PermissionsSchema[Groups.ADMIN];
  } else if (viewer.permissions & Permissions.PUBLISH_DISCUSSIONS) {
    return true;
  }
  return false;
}
function commentReadControl(viewer, data) {
  if (viewer.wtMemberships.includes(data.discussion.workTeamId)) {
    // eslint-disable-line
    return true;
  }
  return false;
}
function commentWriteControl(viewer, data) {
  if (data.discussion.closedAt) {
    return false;
  }
  if (data.creating) {
    // TODO check group etc
    if (viewer.wtMemberships.includes(data.discussion.workTeamId)) {
      // eslint-disable-line
      return (viewer.permissions & Permissions.MAKE_COMMENT) > 0;
    }
  }
  // eslint-disable-next-line eqeqeq
  return viewer.id && viewer.id == data.authorId;
}

/* eslint-enable no-unused-vars */

const ATypes = {
  WRITE: 1,
  READ: 2,
};
const accessFilter = {
  /* GENERATOR_FILTER */
  [Models.TAG]: {
    [ATypes.WRITE]: tagWriteControl,
    [ATypes.READ]: tagReadControl,
  },
  [Models.REQUEST]: {
    [ATypes.WRITE]: requestWriteControl,
    [ATypes.READ]: requestReadControl,
  },
  [Models.USER]: {
    [ATypes.WRITE]: userWriteControl,
    [ATypes.READ]: userReadControl,
  },
  [Models.PROPOSAL]: {
    [ATypes.WRITE]: proposalWriteControl,
    [ATypes.READ]: proposalReadControl,
  },
  [Models.STATEMENT]: {
    [ATypes.WRITE]: statementWriteControl,
    [ATypes.READ]: statementReadControl,
  },
  [Models.FLAG]: {
    [ATypes.WRITE]: flagWriteControl,
    [ATypes.READ]: flagReadControl,
  },
  [Models.S_LIKE]: {
    [ATypes.WRITE]: stmtLikeWriteControl,
    [ATypes.READ]: stmtLikeReadControl,
  },
  [Models.POLL]: {
    [ATypes.WRITE]: pollWriteControl,
    [ATypes.READ]: pollReadControl,
  },
  [Models.VOTE]: {
    [ATypes.WRITE]: voteWriteControl,
    [ATypes.READ]: voteReadControl,
  },
  [Models.NOTIFICATION]: {
    [ATypes.WRITE]: notificationWriteControl,
    [ATypes.READ]: notificationReadControl,
  },
  [Models.ACTIVITY]: {
    [ATypes.WRITE]: activityWriteControl,
    [ATypes.READ]: activityReadControl,
  },
  [Models.WORKTEAM]: {
    [ATypes.WRITE]: workTeamWriteControl,
    [ATypes.READ]: workTeamReadControl,
  },
  [Models.DISCUSSION]: {
    [ATypes.WRITE]: discussionWriteControl,
    [ATypes.READ]: discussionReadControl,
  },
  [Models.COMMENT]: {
    [ATypes.WRITE]: commentWriteControl,
    [ATypes.READ]: commentReadControl,
  },
};

export const canMutate = (viewer, data, model) =>
  accessFilter[model][ATypes.WRITE](viewer, data);

export const canSee = (viewer, data, model) =>
  accessFilter[model][ATypes.READ](viewer, data);
<|endoftext|>


<commit_before>import Device from '../device';
import Logger from '../../service/logger';

const WebOsLibrary = require('../../helpers/WebOS.js');

class DeviceWebOs extends Device {

  /**
   * This is extendable class for LG WebOs devices
   *
   * @class Device_WebOs
   * @extends Device
   * @constructor
   */
  constructor(config) {
    super();
    this.initEvents();
    this.initPlayerClass();
    this.initNetworkClass();
    this.initKeyListener();
    Logger.addLog('Device_WebOs', 'info', 'WebOs Device Initialized');
    this.Player.createVideoElement = this.createVideoElement;
    this.Config = Object.assign(this.Config, config); // Merges default config with user config
    window.isDebugEnabled = this.Config.debug;
    this.constructor.addWebOSLib();
  }

  /**
   * WebOs native api's are required to use webos.js file.
   * This method provides necessary libraries.
   *
   * @for Device_WebOs
   * @method addWebOsLib
   * @return {Boolean} true
   */
  static addWebOSLib() {
    WebOsLibrary();
    Logger.addLog('Device_WebOs', 'info', 'WebOs Library loaded successfully', window.webOS);
  }

  /**
   * Abstract Player createVideoElement function.
   *
   * @abstract
   * @for Device_WebOs
   * @method createVideoElement
   * @return {Boolean} true
   */
  createVideoElement() {
    if (this.videoElement) {
      this.deleteVideoElement();
    }
    this.videoElement = document.createElement('video');
    this.videoElement.style.position = 'absolute';
    this.videoElement.setAttribute('width', this.Config.width);
    this.videoElement.setAttribute('height', this.Config.height);
    this.videoElement.setAttribute('id', this.Config.videoPlayerId);
    this.videoElement.setAttribute('class', 'player');
    this.videoElement.style.visibility = 'hidden';
    document.body.appendChild(this.videoElement);
    this.setPlayerInfo('playready', 'WEBOS');
    this.registerVideoEvents();
    Logger.addLog('Device_WebOs', 'info', 'Player Element Created and Registered Video Events');
    this.initAudioClass();
  }
}

export default DeviceWebOs;
<commit_msg>fixed webos opening issue on old lg<commit_after>import Device from '../device';
import Logger from '../../service/logger';

class DeviceWebOs extends Device {

  /**
   * This is extendable class for LG WebOs devices
   *
   * @class Device_WebOs
   * @extends Device
   * @constructor
   */
  constructor(config) {
    super();
    this.initEvents();
    this.initPlayerClass();
    this.initNetworkClass();
    this.initKeyListener();
    Logger.addLog('Device_WebOs', 'info', 'WebOs Device Initialized');
    this.Player.createVideoElement = this.createVideoElement;
    this.Config = Object.assign(this.Config, config); // Merges default config with user config
    window.isDebugEnabled = this.Config.debug;
    this.constructor.addWebOSLib();
  }

  /**
   * WebOs native api's are required to use webos.js file.
   * This method provides necessary libraries.
   *
   * @for Device_WebOs
   * @method addWebOsLib
   * @return {Boolean} true
   */
  static addWebOSLib() {
    window.webOS=window.webOS||{},"object"==typeof module&&module.exports&&(module.exports=window.webOS),function(){if(webOS.platform={},window.PalmSystem)if(-1<navigator.userAgent.indexOf("SmartWatch"))webOS.platform.watch=!0;else if(-1<navigator.userAgent.indexOf("SmartTV")||-1<navigator.userAgent.indexOf("Large Screen"))webOS.platform.tv=!0;else{try{var e=JSON.parse(PalmSystem.deviceInfo||"{}");if(e.platformVersionMajor&&e.platformVersionMinor){var t=parseInt(e.platformVersionMajor),o=parseInt(e.platformVersionMinor);t<3||3==t&&o<=0?webOS.platform.legacy=!0:webOS.platform.open=!0}}catch(e){webOS.platform.open=!0}window.Mojo=window.Mojo||{relaunch:function(e){}},window.PalmSystem&&PalmSystem.stageReady&&PalmSystem.stageReady()}else webOS.platform.unknown=!0}(),webOS.fetchAppId=function(){if(window.PalmSystem&&PalmSystem.identifier)return PalmSystem.identifier.split(" ")[0]},webOS.fetchAppInfo=function(o,e){if(webOS.appInfo)o&&o(webOS.appInfo);else{var t=function(e,t){if(!e&&t)try{webOS.appInfo=JSON.parse(t),o&&o(webOS.appInfo)}catch(e){console.error("Unable to parse appinfo.json file for "+appID),o&&o()}else o&&o()},i=new XMLHttpRequest;i.onreadystatechange=function(){4==i.readyState&&(200<=i.status&&i.status<300||0===i.status?t(void 0,i.responseText):t({status:404}))};try{i.open("GET",e||"appinfo.json",!0),i.send(null)}catch(e){t({status:404})}}},webOS.fetchAppRootPath=function(){var e=window.location.href;if("baseURI"in window.document)e=window.document.baseURI;else{var t=window.document.getElementsByTagName("base");0<t.length&&(e=t[0].href)}var o=e.match(new RegExp(".*://[^#]*/"));return o?o[0]:""},webOS.platformBack=function(){if(window.PalmSystem&&PalmSystem.platformBack)return PalmSystem.platformBack()},webOS.deviceInfo=function(s){if(this.device)s(this.device);else{this.device={};try{var e=JSON.parse(PalmSystem.deviceInfo);this.device.modelName=e.modelName,this.device.modelNameAscii=e.modelNameAscii,this.device.version=e.platformVersion,this.device.versionMajor=e.platformVersionMajor,this.device.versionMinor=e.platformVersionMinor,this.device.versionDot=e.platformVersionDot,this.device.sdkVersion=e.platformVersion,this.device.screenWidth=e.screenWidth,this.device.screenHeight=e.screenHeight}catch(e){this.device.modelName=this.device.modelNameAscii="webOS Device"}this.device.screenHeight=this.device.screenHeight||screen.height,this.device.screenWidth=this.device.screenWidth||screen.width;var r=this;webOS.platform.tv?webOS.service.request("luna://com.webos.service.tv.systemproperty",{method:"getSystemInfo",parameters:{keys:["firmwareVersion","modelName","sdkVersion","UHD"]},onSuccess:function(e){if(r.device.modelName=e.modelName||r.device.modelName,r.device.modelNameAscii=e.modelName||r.device.modelNameAscii,r.device.sdkVersion=e.sdkVersion||r.device.sdkVersion,r.device.uhd="true"===e.UHD,e.firmwareVersion&&"0.0.0"!==e.firmwareVersion||(e.firmwareVersion=e.sdkVersion),e.firmwareVersion){r.device.version=e.firmwareVersion;for(var t=r.device.version.split("."),o=["versionMajor","versionMinor","versionDot"],i=0;i<o.length;i++)try{r.device[o[i]]=parseInt(t[i])}catch(e){r.device[o[i]]=t[i]}}s(r.device)},onFailure:function(e){s(r.device)}}):(webOS.platform.watch&&(this.device.modelName=this.device.modelNameAscii="webOS Watch"),s(this.device))}},webOS.feedback={play:function(e){if(webOS&&webOS.platform&&webOS.platform.watch){var t={name:e||"touch",sink:"pfeedback"};if(!window.PalmServiceBridge)return;webOS.service.request("luna://com.palm.audio/systemsounds",{method:"playFeedback",parameters:t,subscribe:!1,resubscribe:!1})}}},webOS.keyboard={isShowing:function(){return!!(PalmSystem&&PalmSystem.isKeyboardVisible&&PalmSystem.isKeyboardVisible())}},webOS.notification={showToast:function(e,t){var o=e.message||"",i=e.icon||"",s=webOS.fetchAppId(),r=e.appId||s,n=e.appParams||{},a=e.target,c=e.noaction,l=e.stale||!1,m=e.soundClass||"",d=e.soundFile||"",u=e.soundDurationMs||"";if(webOS.platform.legacy||webOS.platform.open){var f=(e.response,PalmSystem.addBannerMessage(o,JSON.stringify(n),i,m,d,u));t&&t(f)}else{60<o.length&&console.warn("Toast notification message is longer than recommended. May not display as intended");var b={sourceId:s,message:o,stale:l,noaction:c};i&&0<i.length&&(b.iconUrl=i),c||(b.onclick=a?{target:a}:{appId:r,params:n}),this.showToastRequest=webOS.service.request("palm://com.webos.notification",{method:"createToast",parameters:b,onSuccess:function(e){t&&t(e.toastId)},onFailure:function(e){console.error("Failed to create toast: "+JSON.stringify(e)),t&&t()}})}},removeToast:function(e){if(webOS.platform.legacy||webOS.platform.open)try{PalmSystem.removeBannerMessage(e)}catch(e){console.warn(e),PalmSystem.clearBannerMessage()}else this.removeToastRequest=webOS.service.request("palm://com.webos.notification",{method:"closeToast",parameters:{toastId:e}})},supportsDashboard:function(){return webOS.platform.legacy||webOS.platform.open},showDashboard:function(e,t){if(webOS.platform.legacy||webOS.platform.open){var o=window.open(e,"_blank",'attributes={"window":"dashboard"}');return t&&o.document.write(t),o.PalmSystem&&o.PalmSystem.stageReady(),o}console.warn("Dashboards are not supported on this version of webOS.")}},function(){var i=function(e,t,o,i){var s;window.PalmSystem&&(o&&!((s=o)&&"object"==typeof s&&"[object Array]"!==Object.prototype.toString.call(s))&&(e=3,o={msgid:t},t="MISMATCHED_FMT",i=null,console.warn("webOSLog called with invalid format: keyVals must be an object")),t||7==e||console.warn("webOSLog called with invalid format: messageId was empty"),o&&(o=JSON.stringify(o)),window.PalmSystem.PmLogString?7==e?window.PalmSystem.PmLogString(e,null,null,i):window.PalmSystem.PmLogString(e,t,o,i):console.error("Unable to send log; PmLogString not found in this version of PalmSystem"))};webOS.emergency=function(e,t,o){i(0,e,t,o)},webOS.alert=function(e,t,o){i(1,e,t,o)},webOS.critical=function(e,t,o){i(2,e,t,o)},webOS.error=function(e,t,o){i(3,e,t,o)},webOS.warning=function(e,t,o){i(4,e,t,o)},webOS.notice=function(e,t,o){i(5,e,t,o)},webOS.info=function(e,t,o){i(6,e,t,o)},webOS.debug=function(e){i(7,"","",e)}}(),function(){function i(e,t){this.uri=e,(t=t||{}).method&&("/"!=this.uri.charAt(this.uri.length-1)&&(this.uri+="/"),this.uri+=t.method),"function"==typeof t.onSuccess&&(this.onSuccess=t.onSuccess),"function"==typeof t.onFailure&&(this.onFailure=t.onFailure),"function"==typeof t.onComplete&&(this.onComplete=t.onComplete),this.params="object"==typeof t.parameters?t.parameters:{},this.subscribe=t.subscribe||!1,this.subscribe&&(this.params.subscribe=t.subscribe),this.params.subscribe&&(this.subscribe=this.params.subscribe),this.resubscribe=t.resubscribe||!1,this.send()}i.prototype.send=function(){if(!window.PalmServiceBridge)return this.onFailure&&this.onFailure({errorCode:-1,errorText:"PalmServiceBridge not found.",returnValue:!1}),this.onComplete&&this.onComplete({errorCode:-1,errorText:"PalmServiceBridge not found.",returnValue:!1}),void console.error("PalmServiceBridge not found.");this.bridge=new PalmServiceBridge;var e=this;this.bridge.onservicecallback=this.callback=function(t){var o;if(!e.cancelled){try{o=JSON.parse(t)}catch(e){o={errorCode:-1,errorText:t,returnValue:!1}}(o.errorCode||0==o.returnValue)&&e.onFailure?(e.onFailure(o),e.resubscribe&&e.subscribe&&(e.delayID=setTimeout(function(){e.send()},i.resubscribeDelay))):e.onSuccess&&e.onSuccess(o),e.onComplete&&e.onComplete(o),e.subscribe||e.cancel()}},this.bridge.call(this.uri,JSON.stringify(this.params))},i.prototype.cancel=function(){this.cancelled=!0,this.resubscribeJob&&clearTimeout(this.delayID),this.bridge&&(this.bridge.cancel(),this.bridge=void 0)},i.prototype.toString=function(){return"[LS2Request]"},i.resubscribeDelay=1e4,webOS.service={request:function(e,t){return new i(e,t)},systemPrefix:"com.webos.",protocol:"luna://"},navigator.service={request:webOS.service.request},navigator.service.Request=navigator.service.request}(),webOS.libVersion="0.1.0",webOS.voicereadout={readAlert:function(e,t){var o,i,s="boolean"!=typeof t||t;if(webOS&&webOS.platform&&webOS.platform.watch){var r,n,a=function(){webOS.service.request("luna://com.lge.service.tts",{method:"speak",parameters:{locale:r,text:e,speechRate:n}})};i=function(){var t;t=function(){var t;t=a,webOS.service.request("luna://com.webos.settingsservice",{method:"getSystemSettings",parameters:{category:"option",key:"ttsSpeechRate"},onSuccess:function(e){n=Number(e.settings.ttsSpeechRate),t()},onFailure:function(e){console.error("Failed to get system speechRate settings: "+JSON.stringify(e))}})},webOS.service.request("luna://com.webos.settingsservice",{method:"getSystemSettings",parameters:{keys:["localeInfo"]},onSuccess:function(e){r=e.settings.localeInfo.locales.TTS,t()},onFailure:function(e){console.error("Failed to get system localeInfo settings: "+JSON.stringify(e))}})},webOS.service.request("luna://com.webos.settingsservice",{method:"getSystemSettings",parameters:{category:"VoiceReadOut"},onSuccess:function(e){e&&e.settings.talkbackEnable&&i()},onFailure:function(e){console.error("Failed to get system VoiceReadOut settings: "+JSON.stringify(e))}})}else webOS&&webOS.platform&&webOS.platform.tv?(o=a=function(){webOS.service.request("luna://com.webos.service.tts",{method:"speak",parameters:{text:e,clear:s},onFailure:function(e){console.error("Failed to readAlertMessage: "+JSON.stringify(e))}})},webOS.service.request("luna://com.webos.settingsservice",{method:"getSystemSettings",parameters:{keys:["audioGuidance"],category:"option"},onSuccess:function(e){e&&"on"===e.settings.audioGuidance&&o()},onFailure:function(e){console.error("Failed to get system AudioGuidance settings: "+JSON.stringify(e))}})):console.warn("Platform doesn't support TTS api.")}};
    Logger.addLog('Device_WebOs', 'info', 'WebOs Library loaded successfully', window.webOS);
  }

  /**
   * Abstract Player createVideoElement function.
   *
   * @abstract
   * @for Device_WebOs
   * @method createVideoElement
   * @return {Boolean} true
   */
  createVideoElement() {
    if (this.videoElement) {
      this.deleteVideoElement();
    }
    this.videoElement = document.createElement('video');
    this.videoElement.style.position = 'absolute';
    this.videoElement.setAttribute('width', this.Config.width);
    this.videoElement.setAttribute('height', this.Config.height);
    this.videoElement.setAttribute('id', this.Config.videoPlayerId);
    this.videoElement.setAttribute('class', 'player');
    this.videoElement.style.visibility = 'hidden';
    document.body.appendChild(this.videoElement);
    this.setPlayerInfo('playready', 'WEBOS');
    this.registerVideoEvents();
    Logger.addLog('Device_WebOs', 'info', 'Player Element Created and Registered Video Events');
    this.initAudioClass();
  }
}

export default DeviceWebOs;
<|endoftext|>


<commit_before>/**
 * @for p5
 * @requires core
 */

'use strict';

var p5 = require('./core');
var doFriendlyWelcome = false; // TEMP until we get it all working LM

// -- Borrowed from jQuery 1.11.3 --
var class2type = {};
var toString = class2type.toString;
var names = ['Boolean', 'Number', 'String', 'Function',
             'Array', 'Date', 'RegExp', 'Object', 'Error'];
for (var n=0; n<names.length; n++) {
  class2type[ '[object ' + names[n] + ']' ] = names[n].toLowerCase();
}
var getType = function( obj ) {
  if ( obj == null ) {
    return obj + '';
  }
  return typeof obj === 'object' || typeof obj === 'function' ?
    class2type[ toString.call(obj) ] || 'object' :
    typeof obj;
};

// -- End borrow --

/**
 * Prints out a fancy, colorful message to the console log
 *
 * @param  {String}               message the words to be said
 * @param  {String}               func    the name of the function to link
 * @param  {Integer/Color String} color   CSS color string or error type
 *
 * @return console logs
 */
// Wrong number of params, undefined param, wrong type
var FILE_LOAD = 3;
// p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta
// See testColors below for all the color codes and names
var typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00'];
function report(message, func, color) {
  if(doFriendlyWelcome){
    friendlyWelcome();
    doFriendlyWelcome =false;
  }
  if ('undefined' === getType(color)) {
    color   = '#B40033'; // dark magenta
  } else if (getType(color) === 'number') { // Type to color
    color = typeColors[color];
  }
  // LM TEMP commenting this out until we get the whole system working
  // if (func.substring(0,4) === 'load'){
  //   console.log(
  //     '%c> p5.js says: '+message+'%c'+
  //     '[https://github.com/processing/p5.js/wiki/Local-server]',
  //     'background-color:' + color + ';color:#FFF;',
  //     'background-color:transparent;color:' + color +';',
  //     'background-color:' + color + ';color:#FFF;',
  //     'background-color:transparent;color:' + color +';'
  //   );
  // }
  // else{
  //   console.log(
  //     '%c> p5.js says: '+message+'%c [http://p5js.org/reference/#p5/'+func+
  //     ']', 'background-color:' + color + ';color:#FFF;',
  //     'background-color:transparent;color:' + color +';'
  //   );
  // }
}

var errorCases = {
  '0': {
    fileType: 'image',
    method: 'loadImage',
    message: ' hosting the image online,'
  },
  '1': {
    fileType: 'XML file',
    method: 'loadXML'
  },
  '2': {
    fileType: 'table file',
    method: 'loadTable'
  },
  '3': {
    fileType: 'text file',
    method: 'loadStrings'
  },
  '4': {
    fileType: 'font',
    method: 'loadFont',
    message: ' hosting the font online,'
  },
};
p5._friendlyFileLoadError = function (errorType, filePath) {
  var errorInfo = errorCases[ errorType ];
  var message = 'It looks like there was a problem' +
  ' loading your ' + errorInfo.fileType + '.' +
  ' Try checking if the file path%c [' + filePath + '] %cis correct,' +
  (errorInfo.message || '') + ' or running a local server.';
  report(message, errorInfo.method, FILE_LOAD);
};

/**
* Validates Number type parameters
* param  {String}               message the words to be said
* param  {String}               func    the name of the function to link
* param  {Integer/Color String} color   CSS color string or error type
*
* return  {boolean}             message the words to be said
* return  {String}              err     the type of error
* return  {Integer}             index   the location of error
* return  {String}              message friendly err console log
*
* example:
*  var a;
*  ellipse(10,10,a,5);
* console ouput:
*  "It looks like ellipse received an empty variable in spot #2."
*
* example:
*  ellipse(10,"foo",5,5);
* console output:
*  "ellipse was expecting a number for parameter #1,
*           received "foo" instead."
*/
function validateNumParameters(func, input, length) {
  var message;
  if (arguments.length < 3) {
    message = 'Missing input values for validating numeric parameters';
    return [false, 'INIT_VALNUMPAR_FAIL', 0, message];
  }
  var args = new Array(length);
  for (var i = 0; i < input.length; ++i) {
    args[i] = input[i];
  }
  for (var p = 0; p < length; p++) {
    var argType = typeof(args[p]);
    message = '';
    if ('undefined' === argType || null === argType) {
      message = 'FES: It looks like ' + func +
        ' received an empty variable in spot #' + p +
        ' (zero-based index). If not intentional, this is often a problem' +
        ' with scope: [link to scope].';
      return [false, 'EMPTY_VAR', p, message];
    } else if (argType !== 'number') {
      message = 'FES: ' + func + ' was expecting a number' +
        ' for parameter #' + p + ' (zero-based index), received ';
      // Wrap strings in quotes
      message += 'string' === argType ? '"' + args[p] + '"' : args[p];
      message += ' instead.';
      return [false, 'WRONG_TYPE', p, message];
    }
  }
  return [true];
}
function friendlyWelcome() {
  // p5.js brand - magenta: #ED225D
  var astrixBgColor = 'transparent';
  var astrixTxtColor = '#ED225D';
  var welcomeBgColor = '#ED225D';
  var welcomeTextColor = 'white';
  console.log(
  '%c    _ \n'+
  ' /\\| |/\\ \n'+
  ' \\ ` \' /  \n'+
  ' / , . \\  \n'+
  ' \\/|_|\\/ '+
  '\n\n%c> p5.js says: Welcome! '+
  'This is your friendly debugger. ' +
  'To turn me off switch to using “p5.min.js”.',
  'background-color:'+astrixBgColor+';color:' + astrixTxtColor +';',
  'background-color:'+welcomeBgColor+';color:' + welcomeTextColor +';'
  );
}

/**
 * Prints out all the colors in the color pallete with white text.
 * For color blindness testing.
 */
/* function testColors() {
  var str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer';
  report(str, 'print', '#ED225D'); // p5.js magenta
  report(str, 'print', '#2D7BB6'); // p5.js blue
  report(str, 'print', '#EE9900'); // p5.js orange
  report(str, 'print', '#A67F59'); // p5.js light brown
  report(str, 'print', '#704F21'); // p5.js gold
  report(str, 'print', '#1CC581'); // auto cyan
  report(str, 'print', '#FF6625'); // auto orange
  report(str, 'print', '#79EB22'); // auto green
  report(str, 'print', '#B40033'); // p5.js darkened magenta
  report(str, 'print', '#084B7F'); // p5.js darkened blue
  report(str, 'print', '#945F00'); // p5.js darkened orange
  report(str, 'print', '#6B441D'); // p5.js darkened brown
  report(str, 'print', '#2E1B00'); // p5.js darkened gold
  report(str, 'print', '#008851'); // auto dark cyan
  report(str, 'print', '#C83C00'); // auto dark orange
  report(str, 'print', '#4DB200'); // auto dark green
} */

// This is a lazily-defined list of p5 symbols that may be
// misused by beginners at top-level code, outside of setup/draw. We'd like
// to detect these errors and help the user by suggesting they move them
// into setup/draw.
//
// For more details, see https://github.com/processing/p5.js/issues/1121.
var misusedAtTopLevelCode = null;
var FAQ_URL = 'https://github.com/processing/p5.js/wiki/' +
              'Frequently-Asked-Questions' +
              '#why-cant-i-assign-variables-using-p5-functions-and-' +
              'variables-before-setup';

function defineMisusedAtTopLevelCode() {
  var uniqueNamesFound = {};

  var getSymbols = function(obj) {
    return Object.getOwnPropertyNames(obj).filter(function(name) {
      if (name[0] === '_') {
        return false;
      }
      if (name in uniqueNamesFound) {
        return false;
      }

      uniqueNamesFound[name] = true;

      return true;
    }).map(function(name) {
      var type;

      if (typeof(obj[name]) === 'function') {
        type = 'function';
      } else if (name === name.toUpperCase()) {
        type = 'constant';
      } else {
        type = 'variable';
      }

      return {name: name, type: type};
    });
  };

  misusedAtTopLevelCode = [].concat(
    getSymbols(p5.prototype),
    // At present, p5 only adds its constants to p5.prototype during
    // construction, which may not have happened at the time a
    // ReferenceError is thrown, so we'll manually add them to our list.
    getSymbols(require('./constants'))
  );

  // This will ultimately ensure that we report the most specific error
  // possible to the user, e.g. advising them about HALF_PI instead of PI
  // when their code misuses the former.
  misusedAtTopLevelCode.sort(function(a, b) {
    return b.name.length - a.name.length;
  });
}

function helpForMisusedAtTopLevelCode(e, log) {
  if (!log) {
    log = console.log.bind(console);
  }

  if (!misusedAtTopLevelCode) {
    defineMisusedAtTopLevelCode();
  }

  // If we find that we're logging lots of false positives, we can
  // uncomment the following code to avoid displaying anything if the
  // user's code isn't likely to be using p5's global mode. (Note that
  // setup/draw are more likely to be defined due to JS function hoisting.)
  //
  //if (!('setup' in window || 'draw' in window)) {
  //  return;
  //}

  misusedAtTopLevelCode.some(function(symbol) {
    // Note that while just checking for the occurrence of the
    // symbol name in the error message could result in false positives,
    // a more rigorous test is difficult because different browsers
    // log different messages, and the format of those messages may
    // change over time.
    //
    // For example, if the user uses 'PI' in their code, it may result
    // in any one of the following messages:
    //
    //   * 'PI' is undefined                           (Microsoft Edge)
    //   * ReferenceError: PI is undefined             (Firefox)
    //   * Uncaught ReferenceError: PI is not defined  (Chrome)

    if (e.message && e.message.match('\\W?'+symbol.name+'\\W') !== null) {
      log('%cDid you just try to use p5.js\'s ' + symbol.name +
          (symbol.type === 'function' ? '() ' : ' ') + symbol.type +
          '? If so, you may want to ' +
          'move it into your sketch\'s setup() function.\n\n' +
          'For more details, see: ' + FAQ_URL,
          'color: #B40033' /* Dark magenta */);
      return true;
    }
  });
}

// Exposing this primarily for unit testing.
p5.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode;
p5.prototype._validateNumParameters = validateNumParameters;

if (document.readyState !== 'complete') {
  window.addEventListener('error', helpForMisusedAtTopLevelCode, false);

  // Our job is only to catch ReferenceErrors that are thrown when
  // global (non-instance mode) p5 APIs are used at the top-level
  // scope of a file, so we'll unbind our error listener now to make
  // sure we don't log false positives later.
  window.addEventListener('load', function() {
    window.removeEventListener('error', helpForMisusedAtTopLevelCode, false);
  });
}

module.exports = p5;
<commit_msg>parameter checking based on data.json<commit_after>/**
 * @for p5
 * @requires core
 */

'use strict';

var p5 = require('./core');
var doFriendlyWelcome = false; // TEMP until we get it all working LM

// -- Borrowed from jQuery 1.11.3 --
var class2type = {};
var toString = class2type.toString;
var names = ['Boolean', 'Number', 'String', 'Function',
             'Array', 'Date', 'RegExp', 'Object', 'Error'];
for (var n=0; n<names.length; n++) {
  class2type[ '[object ' + names[n] + ']' ] = names[n].toLowerCase();
}
var getType = function( obj ) {
  if ( obj == null ) {
    return obj + '';
  }
  return typeof obj === 'object' || typeof obj === 'function' ?
    class2type[ toString.call(obj) ] || 'object' :
    typeof obj;
};

// -- End borrow --

/**
 * Prints out a fancy, colorful message to the console log
 *
 * @param  {String}               message the words to be said
 * @param  {String}               func    the name of the function to link
 * @param  {Integer/Color String} color   CSS color string or error type
 *
 * @return console logs
 */
// Wrong number of params, undefined param, wrong type
var FILE_LOAD = 3;
// p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta
// See testColors below for all the color codes and names
var typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00'];
function report(message, func, color) {
  if(doFriendlyWelcome){
    friendlyWelcome();
    doFriendlyWelcome =false;
  }
  if ('undefined' === getType(color)) {
    color   = '#B40033'; // dark magenta
  } else if (getType(color) === 'number') { // Type to color
    color = typeColors[color];
  }
  // LM TEMP commenting this out until we get the whole system working
  // if (func.substring(0,4) === 'load'){
  //   console.log(
  //     '%c> p5.js says: '+message+'%c'+
  //     '[https://github.com/processing/p5.js/wiki/Local-server]',
  //     'background-color:' + color + ';color:#FFF;',
  //     'background-color:transparent;color:' + color +';',
  //     'background-color:' + color + ';color:#FFF;',
  //     'background-color:transparent;color:' + color +';'
  //   );
  // }
  // else{
  //   console.log(
  //     '%c> p5.js says: '+message+'%c [http://p5js.org/reference/#p5/'+func+
  //     ']', 'background-color:' + color + ';color:#FFF;',
  //     'background-color:transparent;color:' + color +';'
  //   );
  // }
}

var errorCases = {
  '0': {
    fileType: 'image',
    method: 'loadImage',
    message: ' hosting the image online,'
  },
  '1': {
    fileType: 'XML file',
    method: 'loadXML'
  },
  '2': {
    fileType: 'table file',
    method: 'loadTable'
  },
  '3': {
    fileType: 'text file',
    method: 'loadStrings'
  },
  '4': {
    fileType: 'font',
    method: 'loadFont',
    message: ' hosting the font online,'
  },
};
p5._friendlyFileLoadError = function (errorType, filePath) {
  var errorInfo = errorCases[ errorType ];
  var message = 'It looks like there was a problem' +
  ' loading your ' + errorInfo.fileType + '.' +
  ' Try checking if the file path%c [' + filePath + '] %cis correct,' +
  (errorInfo.message || '') + ' or running a local server.';
  report(message, errorInfo.method, FILE_LOAD);
};

/**
* Validates Number type parameters
* param  {String}               func    the name of the function
* param  {String}               input   the input of the function
* param  {Integer}              length  number of parameters to check
*
* return  {boolean}             message returns true if validated
* return  {String}              err     the type of error
* return  {Integer}             index   the location of error
* return  {String}              message friendly err console log
*
* example:
*  var a;
*  ellipse(10,10,a,5);
* console ouput:
*  "It looks like ellipse received an empty variable in spot #2."
*
* example:
*  ellipse(10,"foo",5,5);
* console output:
*  "ellipse was expecting a number for parameter #1,
*           received "foo" instead."
*/
function validateNumParameters(func, input, length) {
  var message;
  if (arguments.length < 3) {
    message = 'Missing input values for validating numeric parameters';
    return [false, 'INIT_VALNUMPAR_FAIL', 0, message];
  }
  for (var i = 0; i < input.length; ++i) {
    args[i] = input[i];
  }
  for (var p = 0; p < length; p++) {
    var argType = typeof(args[p]);
    message = '';
    if ('undefined' === argType || null === argType) {
      message = 'FES: It looks like ' + func +
        ' received an empty variable in spot #' + p +
        ' (zero-based index). If not intentional, this is often a problem' +
        ' with scope: [link to scope].';
      return [false, 'EMPTY_VAR', p, message];
    } else if (argType !== 'number') {
      message = 'FES: ' + func + ' was expecting a number' +
        ' for parameter #' + p + ' (zero-based index), received ';
      // Wrap strings in quotes
      message += 'string' === argType ? '"' + args[p] + '"' : args[p];
      message += ' instead.';
      return [false, 'WRONG_TYPE', p, message];
    }
  }
  return [true];
}
function validateParameters(func){
  var message;
  var queryResult = jsonArray.
    filter(function (x) { return x.name == func && x.itemtype == "method"; });
  console.log(queryResult);
}
function friendlyWelcome() {
  // p5.js brand - magenta: #ED225D
  var astrixBgColor = 'transparent';
  var astrixTxtColor = '#ED225D';
  var welcomeBgColor = '#ED225D';
  var welcomeTextColor = 'white';
  console.log(
  '%c    _ \n'+
  ' /\\| |/\\ \n'+
  ' \\ ` \' /  \n'+
  ' / , . \\  \n'+
  ' \\/|_|\\/ '+
  '\n\n%c> p5.js says: Welcome! '+
  'This is your friendly debugger. ' +
  'To turn me off switch to using “p5.min.js”.',
  'background-color:'+astrixBgColor+';color:' + astrixTxtColor +';',
  'background-color:'+welcomeBgColor+';color:' + welcomeTextColor +';'
  );
}

/**
 * Prints out all the colors in the color pallete with white text.
 * For color blindness testing.
 */
/* function testColors() {
  var str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer';
  report(str, 'print', '#ED225D'); // p5.js magenta
  report(str, 'print', '#2D7BB6'); // p5.js blue
  report(str, 'print', '#EE9900'); // p5.js orange
  report(str, 'print', '#A67F59'); // p5.js light brown
  report(str, 'print', '#704F21'); // p5.js gold
  report(str, 'print', '#1CC581'); // auto cyan
  report(str, 'print', '#FF6625'); // auto orange
  report(str, 'print', '#79EB22'); // auto green
  report(str, 'print', '#B40033'); // p5.js darkened magenta
  report(str, 'print', '#084B7F'); // p5.js darkened blue
  report(str, 'print', '#945F00'); // p5.js darkened orange
  report(str, 'print', '#6B441D'); // p5.js darkened brown
  report(str, 'print', '#2E1B00'); // p5.js darkened gold
  report(str, 'print', '#008851'); // auto dark cyan
  report(str, 'print', '#C83C00'); // auto dark orange
  report(str, 'print', '#4DB200'); // auto dark green
} */

// This is a lazily-defined list of p5 symbols that may be
// misused by beginners at top-level code, outside of setup/draw. We'd like
// to detect these errors and help the user by suggesting they move them
// into setup/draw.
//
// For more details, see https://github.com/processing/p5.js/issues/1121.
var misusedAtTopLevelCode = null;
var FAQ_URL = 'https://github.com/processing/p5.js/wiki/' +
              'Frequently-Asked-Questions' +
              '#why-cant-i-assign-variables-using-p5-functions-and-' +
              'variables-before-setup';

function defineMisusedAtTopLevelCode() {
  var uniqueNamesFound = {};

  var getSymbols = function(obj) {
    return Object.getOwnPropertyNames(obj).filter(function(name) {
      if (name[0] === '_') {
        return false;
      }
      if (name in uniqueNamesFound) {
        return false;
      }

      uniqueNamesFound[name] = true;

      return true;
    }).map(function(name) {
      var type;

      if (typeof(obj[name]) === 'function') {
        type = 'function';
      } else if (name === name.toUpperCase()) {
        type = 'constant';
      } else {
        type = 'variable';
      }

      return {name: name, type: type};
    });
  };

  misusedAtTopLevelCode = [].concat(
    getSymbols(p5.prototype),
    // At present, p5 only adds its constants to p5.prototype during
    // construction, which may not have happened at the time a
    // ReferenceError is thrown, so we'll manually add them to our list.
    getSymbols(require('./constants'))
  );

  // This will ultimately ensure that we report the most specific error
  // possible to the user, e.g. advising them about HALF_PI instead of PI
  // when their code misuses the former.
  misusedAtTopLevelCode.sort(function(a, b) {
    return b.name.length - a.name.length;
  });
}

function helpForMisusedAtTopLevelCode(e, log) {
  if (!log) {
    log = console.log.bind(console);
  }

  if (!misusedAtTopLevelCode) {
    defineMisusedAtTopLevelCode();
  }

  // If we find that we're logging lots of false positives, we can
  // uncomment the following code to avoid displaying anything if the
  // user's code isn't likely to be using p5's global mode. (Note that
  // setup/draw are more likely to be defined due to JS function hoisting.)
  //
  //if (!('setup' in window || 'draw' in window)) {
  //  return;
  //}

  misusedAtTopLevelCode.some(function(symbol) {
    // Note that while just checking for the occurrence of the
    // symbol name in the error message could result in false positives,
    // a more rigorous test is difficult because different browsers
    // log different messages, and the format of those messages may
    // change over time.
    //
    // For example, if the user uses 'PI' in their code, it may result
    // in any one of the following messages:
    //
    //   * 'PI' is undefined                           (Microsoft Edge)
    //   * ReferenceError: PI is undefined             (Firefox)
    //   * Uncaught ReferenceError: PI is not defined  (Chrome)

    if (e.message && e.message.match('\\W?'+symbol.name+'\\W') !== null) {
      log('%cDid you just try to use p5.js\'s ' + symbol.name +
          (symbol.type === 'function' ? '() ' : ' ') + symbol.type +
          '? If so, you may want to ' +
          'move it into your sketch\'s setup() function.\n\n' +
          'For more details, see: ' + FAQ_URL,
          'color: #B40033' /* Dark magenta */);
      return true;
    }
  });
}

// Exposing this primarily for unit testing.
p5.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode;
p5.prototype._validateNumParameters = validateNumParameters;

if (document.readyState !== 'complete') {
  window.addEventListener('error', helpForMisusedAtTopLevelCode, false);

  // Our job is only to catch ReferenceErrors that are thrown when
  // global (non-instance mode) p5 APIs are used at the top-level
  // scope of a file, so we'll unbind our error listener now to make
  // sure we don't log false positives later.
  window.addEventListener('load', function() {
    window.removeEventListener('error', helpForMisusedAtTopLevelCode, false);
  });
}

module.exports = p5;
<|endoftext|>


<commit_before>/* Copyright 2021 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Dict, isStream, Ref, RefSet } from "./primitives.js";
import { MissingDataException } from "./core_utils.js";
import { warn } from "../shared/util.js";

/**
 * A helper for loading missing data in `Dict` graphs. It traverses the graph
 * depth first and queues up any objects that have missing data. Once it has
 * has traversed as many objects that are available it attempts to bundle the
 * missing data requests and then resume from the nodes that weren't ready.
 *
 * NOTE: It provides protection from circular references by keeping track of
 * loaded references. However, you must be careful not to load any graphs
 * that have references to the catalog or other pages since that will cause the
 * entire PDF document object graph to be traversed.
 */
const ObjectLoader = (function () {
  function mayHaveChildren(value) {
    return (
      value instanceof Ref ||
      value instanceof Dict ||
      Array.isArray(value) ||
      isStream(value)
    );
  }

  function addChildren(node, nodesToVisit) {
    if (node instanceof Dict) {
      node = node.getRawValues();
    } else if (isStream(node)) {
      node = node.dict.getRawValues();
    } else if (!Array.isArray(node)) {
      return;
    }
    for (const rawValue of node) {
      if (mayHaveChildren(rawValue)) {
        nodesToVisit.push(rawValue);
      }
    }
  }

  // eslint-disable-next-line no-shadow
  function ObjectLoader(dict, keys, xref) {
    this.dict = dict;
    this.keys = keys;
    this.xref = xref;
    this.refSet = null;
  }

  ObjectLoader.prototype = {
    async load() {
      // Don't walk the graph if all the data is already loaded; note that only
      // `ChunkedStream` instances have a `allChunksLoaded` method.
      if (
        !this.xref.stream.allChunksLoaded ||
        this.xref.stream.allChunksLoaded()
      ) {
        return undefined;
      }

      const { keys, dict } = this;
      this.refSet = new RefSet();
      // Setup the initial nodes to visit.
      const nodesToVisit = [];
      for (let i = 0, ii = keys.length; i < ii; i++) {
        const rawValue = dict.getRaw(keys[i]);
        // Skip nodes that are guaranteed to be empty.
        if (rawValue !== undefined) {
          nodesToVisit.push(rawValue);
        }
      }
      return this._walk(nodesToVisit);
    },

    async _walk(nodesToVisit) {
      const nodesToRevisit = [];
      const pendingRequests = [];
      // DFS walk of the object graph.
      while (nodesToVisit.length) {
        let currentNode = nodesToVisit.pop();

        // Only references or chunked streams can cause missing data exceptions.
        if (currentNode instanceof Ref) {
          // Skip nodes that have already been visited.
          if (this.refSet.has(currentNode)) {
            continue;
          }
          try {
            this.refSet.put(currentNode);
            currentNode = this.xref.fetch(currentNode);
          } catch (ex) {
            if (!(ex instanceof MissingDataException)) {
              warn(`ObjectLoader._walk - requesting all data: "${ex}".`);
              this.refSet = null;

              const { manager } = this.xref.stream;
              return manager.requestAllChunks();
            }
            nodesToRevisit.push(currentNode);
            pendingRequests.push({ begin: ex.begin, end: ex.end });
          }
        }
        if (currentNode && currentNode.getBaseStreams) {
          const baseStreams = currentNode.getBaseStreams();
          let foundMissingData = false;
          for (let i = 0, ii = baseStreams.length; i < ii; i++) {
            const stream = baseStreams[i];
            if (stream.allChunksLoaded && !stream.allChunksLoaded()) {
              foundMissingData = true;
              pendingRequests.push({ begin: stream.start, end: stream.end });
            }
          }
          if (foundMissingData) {
            nodesToRevisit.push(currentNode);
          }
        }

        addChildren(currentNode, nodesToVisit);
      }

      if (pendingRequests.length) {
        await this.xref.stream.manager.requestRanges(pendingRequests);

        for (let i = 0, ii = nodesToRevisit.length; i < ii; i++) {
          const node = nodesToRevisit[i];
          // Remove any reference nodes from the current `RefSet` so they
          // aren't skipped when we revist them.
          if (node instanceof Ref) {
            this.refSet.remove(node);
          }
        }
        return this._walk(nodesToRevisit);
      }
      // Everything is loaded.
      this.refSet = null;
      return undefined;
    },
  };

  return ObjectLoader;
})();

export { ObjectLoader };
<commit_msg>Covert the `ObjectLoader` to a "normal" class<commit_after>/* Copyright 2021 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Dict, isStream, Ref, RefSet } from "./primitives.js";
import { MissingDataException } from "./core_utils.js";
import { warn } from "../shared/util.js";

function mayHaveChildren(value) {
  return (
    value instanceof Ref ||
    value instanceof Dict ||
    Array.isArray(value) ||
    isStream(value)
  );
}

function addChildren(node, nodesToVisit) {
  if (node instanceof Dict) {
    node = node.getRawValues();
  } else if (isStream(node)) {
    node = node.dict.getRawValues();
  } else if (!Array.isArray(node)) {
    return;
  }
  for (const rawValue of node) {
    if (mayHaveChildren(rawValue)) {
      nodesToVisit.push(rawValue);
    }
  }
}

/**
 * A helper for loading missing data in `Dict` graphs. It traverses the graph
 * depth first and queues up any objects that have missing data. Once it has
 * has traversed as many objects that are available it attempts to bundle the
 * missing data requests and then resume from the nodes that weren't ready.
 *
 * NOTE: It provides protection from circular references by keeping track of
 * loaded references. However, you must be careful not to load any graphs
 * that have references to the catalog or other pages since that will cause the
 * entire PDF document object graph to be traversed.
 */
class ObjectLoader {
  constructor(dict, keys, xref) {
    this.dict = dict;
    this.keys = keys;
    this.xref = xref;
    this.refSet = null;
  }

  async load() {
    // Don't walk the graph if all the data is already loaded; note that only
    // `ChunkedStream` instances have a `allChunksLoaded` method.
    if (
      !this.xref.stream.allChunksLoaded ||
      this.xref.stream.allChunksLoaded()
    ) {
      return undefined;
    }

    const { keys, dict } = this;
    this.refSet = new RefSet();
    // Setup the initial nodes to visit.
    const nodesToVisit = [];
    for (let i = 0, ii = keys.length; i < ii; i++) {
      const rawValue = dict.getRaw(keys[i]);
      // Skip nodes that are guaranteed to be empty.
      if (rawValue !== undefined) {
        nodesToVisit.push(rawValue);
      }
    }
    return this._walk(nodesToVisit);
  }

  async _walk(nodesToVisit) {
    const nodesToRevisit = [];
    const pendingRequests = [];
    // DFS walk of the object graph.
    while (nodesToVisit.length) {
      let currentNode = nodesToVisit.pop();

      // Only references or chunked streams can cause missing data exceptions.
      if (currentNode instanceof Ref) {
        // Skip nodes that have already been visited.
        if (this.refSet.has(currentNode)) {
          continue;
        }
        try {
          this.refSet.put(currentNode);
          currentNode = this.xref.fetch(currentNode);
        } catch (ex) {
          if (!(ex instanceof MissingDataException)) {
            warn(`ObjectLoader._walk - requesting all data: "${ex}".`);
            this.refSet = null;

            const { manager } = this.xref.stream;
            return manager.requestAllChunks();
          }
          nodesToRevisit.push(currentNode);
          pendingRequests.push({ begin: ex.begin, end: ex.end });
        }
      }
      if (currentNode && currentNode.getBaseStreams) {
        const baseStreams = currentNode.getBaseStreams();
        let foundMissingData = false;
        for (let i = 0, ii = baseStreams.length; i < ii; i++) {
          const stream = baseStreams[i];
          if (stream.allChunksLoaded && !stream.allChunksLoaded()) {
            foundMissingData = true;
            pendingRequests.push({ begin: stream.start, end: stream.end });
          }
        }
        if (foundMissingData) {
          nodesToRevisit.push(currentNode);
        }
      }

      addChildren(currentNode, nodesToVisit);
    }

    if (pendingRequests.length) {
      await this.xref.stream.manager.requestRanges(pendingRequests);

      for (let i = 0, ii = nodesToRevisit.length; i < ii; i++) {
        const node = nodesToRevisit[i];
        // Remove any reference nodes from the current `RefSet` so they
        // aren't skipped when we revist them.
        if (node instanceof Ref) {
          this.refSet.remove(node);
        }
      }
      return this._walk(nodesToRevisit);
    }
    // Everything is loaded.
    this.refSet = null;
    return undefined;
  }
}

export { ObjectLoader };
<|endoftext|>


<commit_before>/* Copyright (c) 2016 Dmitri Kourennyi
   See the file COPYING for copying permission.
*/
/* jshint moz: true, strict: global, browser: true, devel:true */
/* globals self, getDefaultComputedStyle*/
'use strict';

var darkColor;
var lightColor;
var allColors;

var defaultFg;

const kInputElems = ["INPUT", "TEXTAREA", "SELECT", "BUTTON", "TOOLBARBUTTON"];

function isInputNode(node) {
    return kInputElems.indexOf(node.nodeName) > -1;
}

self.port.on("colors", function (colors) {
    darkColor = colors[0];
    lightColor = colors[1];
    allColors = colors[2];

    // Get default fg as computed style by making a dummy element
    var dummy = document.createElement('p');
    defaultFg = getDefaultComputedStyle(dummy).color;

    checkInputs();
    if (allColors === true) {
        checkDoc();
    }

    var observer = new MutationObserver(function (mutations) {
        mutations.forEach(function (mutation) {
            for (var newNode of mutation.addedNodes) {
                // Get all input-like elements
                var nodeIterator = document.createNodeIterator(
                    newNode, NodeFilter.SHOW_ELEMENT, {
                        acceptNode: isInputNode
                    });
                var node;
                while ((node = nodeIterator.nextNode())) {
                    checkElementContrast(node);
                }

                if (allColors === true) {
                    var parent = newNode.parentElement;
                    var defined = false;
                    while (parent !== null) {
                        if (is_fg_defined(parent) ||
                            is_bg_defined(parent) ||
                            is_bg_img_defined(parent)) {
                            // If any parents' color property is defined,
                            // new elements don't need recolor.
                            defined = true;
                            break;
                        }
                        parent = parent.parentElement;
                    }
                    if (!defined) {
                        checkElementContrast(newNode);
                    }
                }
            }
        });
    });
    var config = {
        childList: true,
        subtree: true,
    };
    observer.observe(document, config);
});

function checkDoc() {
    checkElementContrast(document.all[0]);

    // Other checks required when browser is in quirks mode
    if (document.compatMode == "BackCompat") {
        // tables don't inherit color
        var tables = document.getElementsByTagName("table");
        for (var i = 0; i < tables.length; i++) {
            if (getComputedStyle(tables[i]).color ==
                getDefaultComputedStyle(tables[i]).color) {
                //if color has not been set explicitely, then force inherit
                tables[i].style.color = "inherit";
            }
        }
    }
}

function checkInputs() {
    kInputElems.forEach(
        function (val) {
            var elements = document.getElementsByTagName(val),
                i;
            for (i = 0; i < elements.length; i += 1) {
                checkElementContrast(elements[i]);
            }
        });
}

function is_fg_defined(e) {
    return (getComputedStyle(e).color != getDefaultComputedStyle(e).color) &&
        (getComputedStyle(e).color != defaultFg);
}

function is_bg_defined(e) {
    return (getComputedStyle(e).backgroundColor !=
        getDefaultComputedStyle(e).backgroundColor);
}

function is_bg_img_defined(e) {
    return (getComputedStyle(e).backgroundImage != 'none');
}

function colorstyle_to_rgb(s) {
    var color = {};
    if (s == 'transparent') {
        color.r = 0;
        color.g = 0;
        color.b = 0;
        color.a = 0;
        return color;
    }
    var parts = s.split(',', 3);
    color.r = parseInt(parts[0].substr(parts[0].indexOf('(', 3) + 1));
    color.g = parseInt(parts[1].trim());
    color.b = parseInt(parts[2].trim());
    color.a = 1;
    return color;
}

function get_intensity(rgb) {
    // Use Rec. 709 chromaticity luma, matching sRGB
    return Math.round(0.21 * rgb.r + 0.72 * rgb.g + 0.07 * rgb.b);
}

function is_dark(rgb) {
    return get_intensity(rgb) < 75;
}

function is_light(rgb) {
    return get_intensity(rgb) > 180;
}

function is_transparent(rgb) {
    return rgb.a === 0;
}

function checkElementContrast(element) {
    var fg_color_defined = is_fg_defined(element);
    var bg_color_defined = is_bg_defined(element);
    var bg_img_defined = is_bg_img_defined(element);

    if (fg_color_defined && bg_color_defined) {
        //Both colors explicitely defined, nothing to do
        return;
    }

    if (!fg_color_defined && bg_color_defined) {
        // only set fg if it will improve contrast
        var bg_color = colorstyle_to_rgb(getComputedStyle(element).backgroundColor);
        if (is_light(bg_color) || is_transparent(bg_color)) {
            element.style.color = darkColor;
        }
        return;
    }

    if (fg_color_defined && !bg_color_defined) {
        // only set bg if it will improve contrast
        var fg_color = colorstyle_to_rgb(getComputedStyle(element).color);
        if (is_dark(fg_color)) {
            element.style.backgroundColor = lightColor;
        }
        return;
    }

    if (bg_img_defined) {
        //No FG or BG color, but possibly transparent image, so need
        //to set both
        element.style.color = darkColor;
        element.style.backgroundColor = lightColor;
        return;
    }

    //Nothing defined, recurse through children
    var children = element.children;
    for (var i = 0; i < children.length; i++) {
        // Don't look at non-renderable elements
        switch (element.children[i].nodeName) {
        case "HEAD":
        case "TITLE":
        case "META":
        case "SCRIPT":
        case "IMG":
        case "STYLE":
            break;
        default:
            checkElementContrast(element.children[i]);
        }
    }
    return;
}
<commit_msg>Increase range of luminosities considered dark or light<commit_after>/* Copyright (c) 2016 Dmitri Kourennyi
   See the file COPYING for copying permission.
*/
/* jshint moz: true, strict: global, browser: true, devel:true */
/* globals self, getDefaultComputedStyle*/
'use strict';

var darkColor;
var lightColor;
var allColors;

var defaultFg;

const kInputElems = ["INPUT", "TEXTAREA", "SELECT", "BUTTON", "TOOLBARBUTTON"];

function isInputNode(node) {
    return kInputElems.indexOf(node.nodeName) > -1;
}

self.port.on("colors", function (colors) {
    darkColor = colors[0];
    lightColor = colors[1];
    allColors = colors[2];

    // Get default fg as computed style by making a dummy element
    var dummy = document.createElement('p');
    defaultFg = getDefaultComputedStyle(dummy).color;

    checkInputs();
    if (allColors === true) {
        checkDoc();
    }

    var observer = new MutationObserver(function (mutations) {
        mutations.forEach(function (mutation) {
            for (var newNode of mutation.addedNodes) {
                // Get all input-like elements
                var nodeIterator = document.createNodeIterator(
                    newNode, NodeFilter.SHOW_ELEMENT, {
                        acceptNode: isInputNode
                    });
                var node;
                while ((node = nodeIterator.nextNode())) {
                    checkElementContrast(node);
                }

                if (allColors === true) {
                    var parent = newNode.parentElement;
                    var defined = false;
                    while (parent !== null) {
                        if (is_fg_defined(parent) ||
                            is_bg_defined(parent) ||
                            is_bg_img_defined(parent)) {
                            // If any parents' color property is defined,
                            // new elements don't need recolor.
                            defined = true;
                            break;
                        }
                        parent = parent.parentElement;
                    }
                    if (!defined) {
                        checkElementContrast(newNode);
                    }
                }
            }
        });
    });
    var config = {
        childList: true,
        subtree: true,
    };
    observer.observe(document, config);
});

function checkDoc() {
    checkElementContrast(document.all[0]);

    // Other checks required when browser is in quirks mode
    if (document.compatMode == "BackCompat") {
        // tables don't inherit color
        var tables = document.getElementsByTagName("table");
        for (var i = 0; i < tables.length; i++) {
            if (getComputedStyle(tables[i]).color ==
                getDefaultComputedStyle(tables[i]).color) {
                //if color has not been set explicitely, then force inherit
                tables[i].style.color = "inherit";
            }
        }
    }
}

function checkInputs() {
    kInputElems.forEach(
        function (val) {
            var elements = document.getElementsByTagName(val),
                i;
            for (i = 0; i < elements.length; i += 1) {
                checkElementContrast(elements[i]);
            }
        });
}

function is_fg_defined(e) {
    return (getComputedStyle(e).color != getDefaultComputedStyle(e).color) &&
        (getComputedStyle(e).color != defaultFg);
}

function is_bg_defined(e) {
    return (getComputedStyle(e).backgroundColor !=
        getDefaultComputedStyle(e).backgroundColor);
}

function is_bg_img_defined(e) {
    return (getComputedStyle(e).backgroundImage != 'none');
}

function colorstyle_to_rgb(s) {
    var color = {};
    if (s == 'transparent') {
        color.r = 0;
        color.g = 0;
        color.b = 0;
        color.a = 0;
        return color;
    }
    var parts = s.split(',', 3);
    color.r = parseInt(parts[0].substr(parts[0].indexOf('(', 3) + 1));
    color.g = parseInt(parts[1].trim());
    color.b = parseInt(parts[2].trim());
    color.a = 1;
    return color;
}

function get_intensity(rgb) {
    // Use Rec. 709 chromaticity luma, matching sRGB
    return Math.round(0.21 * rgb.r + 0.72 * rgb.g + 0.07 * rgb.b);
}

function is_dark(rgb) {
    return get_intensity(rgb) < 94;
}

function is_light(rgb) {
    return get_intensity(rgb) > 145;
}

function is_transparent(rgb) {
    return rgb.a === 0;
}

function checkElementContrast(element) {
    var fg_color_defined = is_fg_defined(element);
    var bg_color_defined = is_bg_defined(element);
    var bg_img_defined = is_bg_img_defined(element);

    if (fg_color_defined && bg_color_defined) {
        //Both colors explicitely defined, nothing to do
        return;
    }

    if (!fg_color_defined && bg_color_defined) {
        // only set fg if it will improve contrast
        var bg_color = colorstyle_to_rgb(getComputedStyle(element).backgroundColor);
        if (is_light(bg_color) || is_transparent(bg_color)) {
            element.style.color = darkColor;
        }
        return;
    }

    if (fg_color_defined && !bg_color_defined) {
        // only set bg if it will improve contrast
        var fg_color = colorstyle_to_rgb(getComputedStyle(element).color);
        if (is_dark(fg_color)) {
            element.style.backgroundColor = lightColor;
        }
        return;
    }

    if (bg_img_defined) {
        //No FG or BG color, but possibly transparent image, so need
        //to set both
        element.style.color = darkColor;
        element.style.backgroundColor = lightColor;
        return;
    }

    //Nothing defined, recurse through children
    var children = element.children;
    for (var i = 0; i < children.length; i++) {
        // Don't look at non-renderable elements
        switch (element.children[i].nodeName) {
        case "HEAD":
        case "TITLE":
        case "META":
        case "SCRIPT":
        case "IMG":
        case "STYLE":
            break;
        default:
            checkElementContrast(element.children[i]);
        }
    }
    return;
}
<|endoftext|>


<commit_before>(function(dataDash){

    /**
     * Round a value to certain decimal places
     * @param value
     * @param factor
     * @returns {number}
     */
    var _roundBy = function(value, factor){
        return +(parseFloat(value).toFixed(factor)) || 0;
    };

    /**
     * Translate a number to exponential form (e.g.: 1.67e10)
     * @param val
     * @private
     */
    var _toExponential = function(val){
        val += "";
        var e_index = val.indexOf("e+");

        // If it's already in exponential, strip out the plus sign
        if(e_index >= 0){
            var exponent_part = "";
            for(var i=e_index+2; i<val.length; i++){
                exponent_part += val[i];
            }
            val = val[0] + "." + val[2] + val[3] + "e" + exponent_part;
        } else {
            val = val[0] + "." + val[1] + val[2] + "e" + (val.length - 1);
        }

        return val;
    };

    /**
     * Convert number to negative exponential form
     * @param val
     * @private
     */
    var _toNegativeExponential = function(val){
        // Less than 0.000001 uses exponential form
        if(val!==0){
            val = val + "";
            if(val.indexOf("e") < 0){
                for(var i=0 ; i<val.length; i++){
                    if(val[i] !== 0 && val[i] !== "."){
                        break;
                    }
                }

                var negExp = -(i - 2);
                var out = val[i];
                if(val[i+1]) out += "." + val[i+1];
                if(val[i+2]) out += val[i+2];

                val = out + "e" + negExp;
            } else {
                var e_index = val.indexOf("e");
                var exponent_part = "";
                for(var i2=e_index+2; i2<val.length; i2++){
                    exponent_part += val[i2];
                }

                var output = val[0];
                if(val[1]=="."){
                    output += "." + val[2];
                    if(val[3]){
                        output += val[3];
                    }
                }

                val = output + "e-" + exponent_part;
            }
        }

        return val;
    };

    /**
     * For numbers less than zero, leave only three trailing digits
     * @param val
     * @private
     */
    var _toShorthandLessThanZero = function(val){

        // Anything else less than 1 rounds to maximum three digits
        val = val + "";
        var i = val.length - 1;
        var trailing_chars = 0;
        for( ; i>=0; i--){
            if(val[i]=="0")
                break;
            trailing_chars++;
        }

        if(trailing_chars<=3){
            val = val;
        } else {
            val = val.substr(0, val.length - trailing_chars + 3);
        }

        return val;
    };

    /**
     * Convert value to shorthand form
     * @param val {number}
     * @returns {string}  Shorthand form
     * @private
     */
    var _toShorthand = function(val){
        val = parseFloat(val) || 0;

        // Use an absolute value, we'll restore the sign at the end
        var isNegative = val < 0;
        val = Math.abs(val);

        if(val >= 1000000000000){
            val = _toExponential(val);
        } else if(val >= Math.pow(10,9)){
            val = _roundBy(val / 1000000000, 2) + "b";
        } else if(val >= Math.pow(10,6)){
            val = _roundBy(val / 1000000, 2) + "m";
        } else if (val < 0.000001){
            val = _toNegativeExponential(val);
        } else if(val < 1){
            val = _toShorthandLessThanZero(val);
        } else {
            val = _roundBy(val, 2);
        }

        // Return the value with the sign restored
        return (isNegative ? "-" : "") + val;
    };

    /**
     * Callback that binds the 'shorthand' behavior
     */
    var shorthandFormCallback = function(){
        var makeShorthandCallback = function(ctx){
            return function(e, val){

                val = val || (e && e.data);

                // Get the current value of the element
                var curr_value = $.dataDash(ctx).getValOrHtml();

                // Set the value to the shorthand form
                $.dataDash(ctx).setValOrHtml(_toShorthand(curr_value), true);

                // If it's an event callback, backup the value that the element was set to
                if(typeof(val)!="undefined"){
                    $.dataDash(ctx).backupValue(val);
                }
            };
        }(this);

        $.dataDash(this).change(makeShorthandCallback);
        makeShorthandCallback();
    };

    /**
     * 'productOf' behavior that is bound to element(s)
     * @param attrValue {string} Value of 'data-dg-productOf' which is used as a CSS selector
     * @returns {*}
     */
    var productOfCallback = function(attrValue){

        // Whenever any elements targeted by attrValue change, update the product of this
        var prodOfFunc = function(ctx){
            return function(){

                // Product starts at 1, multiply each value one-by-one
                var product = 1;
                $(attrValue).each(function(idx, element){
                    product = product * parseFloat($.dataDash(element).getValOrHtml() || 1);
                });

                // Set the new value
                ctx.setValOrHtml(product);
            };
        }(this);

        // Bind to change event but also call immediately
        $(attrValue).change(prodOfFunc);
        prodOfFunc.call();

        return this;
    };

    /**
     * 'sumOf' behavior that is bound to element(s)
     * @param attrValue {string} Value of 'data-dg-sumOf' which is used as a CSS selector
     * @returns {*}
     */
    var sumOfCallback = function(attrValue){

        // Whenever any elements targeted by attrValue change, update the product of this
        var sumOfFunc = function(ctx){
            return function(){

                // Sum starts at 0, multiply each value one-by-one
                var sum = 0;
                $(attrValue).each(function(idx, element){
                    sum += parseFloat($.dataDash(element).getValOrHtml() || 0);
                });

                // Set the new value
                ctx.setValOrHtml(sum);
            };
        }(this);

        // Bind to change event but also call immediately
        $(attrValue).change(sumOfFunc);
        sumOfFunc.call();

        return this;
    };

    /**
     * Function that binds the 'roundBy' behavior
     * @param attrValue
     */
    var roundByCallback = function(attrValue){

        // Round it right away
        $(this).val( _roundBy($(this).val(), attrValue) );

        // Create the 'onchange' event
        var onChange = function(){
            $.dataDash(this).setValOrHtml( _roundBy($.dataDash(this).getValOrHtml(), attrValue), true );
        };

        $(this).change(onChange);

        var unbindCallback = function(ctx, onChange){
            return function(){
                $.dataDash(ctx).unbind(onChange);
            };
        }(this, onChange);

        return unbindCallback;
    };

    /**
     * Separate number by commas
     * @param number
     * @returns {string}
     * @private
     */
    var _addCommas = function(number){
        return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    };

    /**
     * Get the decimal part of a number
     * @param number
     * @returns {string}
     * @private
     */
    var _getDecimalPart = function(number){
        var match = number.match(/[^\.]*[\.]([\w\W]*)/);
        return match ? ("." + match[1]) : "";
    };

    /**
     * Function that binds the 'commaSeparated' behavior
     */
    var commaSeparatedCallback = function(){
        var onChange = function(){

            // Get the value and then translate it into comma separated form
            var val = $.dataDash(this).getValOrHtml();
            var comma_separated = _addCommas(parseInt(val,10)) + _getDecimalPart(val);

            // Set the new value
            $.dataDash(this).setValOrHtml(comma_separated, true);

            // Backup the old value
            if(typeof(val)!="undefined"){
                $.dataDash(this).backupValue(val);
            }
        };

        // Bind to change event and also call it right away
        $(this).change(onChange);
        onChange.call(this);
    };

    // Register these four behaviors
    dataDash.registerBehavior("productOf", productOfCallback);
    dataDash.registerBehavior("sumOf", sumOfCallback);
    dataDash.registerBehavior("roundBy", roundByCallback);
    dataDash.registerBehavior("shorthand", shorthandFormCallback);
    dataDash.registerBehavior("commaSeparated", commaSeparatedCallback);

}($.dataDash));
<commit_msg>Call the roundBy callback right away<commit_after>(function(dataDash){

    /**
     * Round a value to certain decimal places
     * @param value
     * @param factor
     * @returns {number}
     */
    var _roundBy = function(value, factor){
        return +(parseFloat(value).toFixed(factor)) || 0;
    };

    /**
     * Translate a number to exponential form (e.g.: 1.67e10)
     * @param val
     * @private
     */
    var _toExponential = function(val){
        val += "";
        var e_index = val.indexOf("e+");

        // If it's already in exponential, strip out the plus sign
        if(e_index >= 0){
            var exponent_part = "";
            for(var i=e_index+2; i<val.length; i++){
                exponent_part += val[i];
            }
            val = val[0] + "." + val[2] + val[3] + "e" + exponent_part;
        } else {
            val = val[0] + "." + val[1] + val[2] + "e" + (val.length - 1);
        }

        return val;
    };

    /**
     * Convert number to negative exponential form
     * @param val
     * @private
     */
    var _toNegativeExponential = function(val){
        // Less than 0.000001 uses exponential form
        if(val!==0){
            val = val + "";
            if(val.indexOf("e") < 0){
                for(var i=0 ; i<val.length; i++){
                    if(val[i] !== 0 && val[i] !== "."){
                        break;
                    }
                }

                var negExp = -(i - 2);
                var out = val[i];
                if(val[i+1]) out += "." + val[i+1];
                if(val[i+2]) out += val[i+2];

                val = out + "e" + negExp;
            } else {
                var e_index = val.indexOf("e");
                var exponent_part = "";
                for(var i2=e_index+2; i2<val.length; i2++){
                    exponent_part += val[i2];
                }

                var output = val[0];
                if(val[1]=="."){
                    output += "." + val[2];
                    if(val[3]){
                        output += val[3];
                    }
                }

                val = output + "e-" + exponent_part;
            }
        }

        return val;
    };

    /**
     * For numbers less than zero, leave only three trailing digits
     * @param val
     * @private
     */
    var _toShorthandLessThanZero = function(val){

        // Anything else less than 1 rounds to maximum three digits
        val = val + "";
        var i = val.length - 1;
        var trailing_chars = 0;
        for( ; i>=0; i--){
            if(val[i]=="0")
                break;
            trailing_chars++;
        }

        if(trailing_chars<=3){
            val = val;
        } else {
            val = val.substr(0, val.length - trailing_chars + 3);
        }

        return val;
    };

    /**
     * Convert value to shorthand form
     * @param val {number}
     * @returns {string}  Shorthand form
     * @private
     */
    var _toShorthand = function(val){
        val = parseFloat(val) || 0;

        // Use an absolute value, we'll restore the sign at the end
        var isNegative = val < 0;
        val = Math.abs(val);

        if(val >= 1000000000000){
            val = _toExponential(val);
        } else if(val >= Math.pow(10,9)){
            val = _roundBy(val / 1000000000, 2) + "b";
        } else if(val >= Math.pow(10,6)){
            val = _roundBy(val / 1000000, 2) + "m";
        } else if (val < 0.000001){
            val = _toNegativeExponential(val);
        } else if(val < 1){
            val = _toShorthandLessThanZero(val);
        } else {
            val = _roundBy(val, 2);
        }

        // Return the value with the sign restored
        return (isNegative ? "-" : "") + val;
    };

    /**
     * Callback that binds the 'shorthand' behavior
     */
    var shorthandFormCallback = function(){
        var makeShorthandCallback = function(ctx){
            return function(e, val){

                val = val || (e && e.data);

                // Get the current value of the element
                var curr_value = $.dataDash(ctx).getValOrHtml();

                // Set the value to the shorthand form
                $.dataDash(ctx).setValOrHtml(_toShorthand(curr_value), true);

                // If it's an event callback, backup the value that the element was set to
                if(typeof(val)!="undefined"){
                    $.dataDash(ctx).backupValue(val);
                }
            };
        }(this);

        $.dataDash(this).change(makeShorthandCallback);
        makeShorthandCallback();
    };

    /**
     * 'productOf' behavior that is bound to element(s)
     * @param attrValue {string} Value of 'data-dg-productOf' which is used as a CSS selector
     * @returns {*}
     */
    var productOfCallback = function(attrValue){

        // Whenever any elements targeted by attrValue change, update the product of this
        var prodOfFunc = function(ctx){
            return function(){

                // Product starts at 1, multiply each value one-by-one
                var product = 1;
                $(attrValue).each(function(idx, element){
                    product = product * parseFloat($.dataDash(element).getValOrHtml() || 1);
                });

                // Set the new value
                ctx.setValOrHtml(product);
            };
        }(this);

        // Bind to change event but also call immediately
        $(attrValue).change(prodOfFunc);
        prodOfFunc.call();

        return this;
    };

    /**
     * 'sumOf' behavior that is bound to element(s)
     * @param attrValue {string} Value of 'data-dg-sumOf' which is used as a CSS selector
     * @returns {*}
     */
    var sumOfCallback = function(attrValue){

        // Whenever any elements targeted by attrValue change, update the product of this
        var sumOfFunc = function(ctx){
            return function(){

                // Sum starts at 0, multiply each value one-by-one
                var sum = 0;
                $(attrValue).each(function(idx, element){
                    sum += parseFloat($.dataDash(element).getValOrHtml() || 0);
                });

                // Set the new value
                ctx.setValOrHtml(sum);
            };
        }(this);

        // Bind to change event but also call immediately
        $(attrValue).change(sumOfFunc);
        sumOfFunc.call();

        return this;
    };

    /**
     * Function that binds the 'roundBy' behavior
     * @param attrValue
     */
    var roundByCallback = function(attrValue){

        // Round it right away
        $(this).val( _roundBy($(this).val(), attrValue) );

        // Create the 'onchange' event
        var onChange = function(){
            $.dataDash(this).setValOrHtml( _roundBy($.dataDash(this).getValOrHtml(), attrValue), true );
        };

        $(this).change(onChange);

        var unbindCallback = function(ctx, onChange){
            return function(){
                $.dataDash(ctx).unbind(onChange);
            };
        }(this, onChange);

        onChange.call($(this));

        return unbindCallback;
    };

    /**
     * Separate number by commas
     * @param number
     * @returns {string}
     * @private
     */
    var _addCommas = function(number){
        return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    };

    /**
     * Get the decimal part of a number
     * @param number
     * @returns {string}
     * @private
     */
    var _getDecimalPart = function(number){
        var match = number.match(/[^\.]*[\.]([\w\W]*)/);
        return match ? ("." + match[1]) : "";
    };

    /**
     * Function that binds the 'commaSeparated' behavior
     */
    var commaSeparatedCallback = function(){
        var onChange = function(){

            // Get the value and then translate it into comma separated form
            var val = $.dataDash(this).getValOrHtml();
            var comma_separated = _addCommas(parseInt(val,10)) + _getDecimalPart(val);

            // Set the new value
            $.dataDash(this).setValOrHtml(comma_separated, true);

            // Backup the old value
            if(typeof(val)!="undefined"){
                $.dataDash(this).backupValue(val);
            }
        };

        // Bind to change event and also call it right away
        $(this).change(onChange);
        onChange.call(this);
    };

    // Register these four behaviors
    dataDash.registerBehavior("productOf", productOfCallback);
    dataDash.registerBehavior("sumOf", sumOfCallback);
    dataDash.registerBehavior("roundBy", roundByCallback);
    dataDash.registerBehavior("shorthand", shorthandFormCallback);
    dataDash.registerBehavior("commaSeparated", commaSeparatedCallback);

}($.dataDash));
<|endoftext|>


<commit_before>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */
(function(scope) {

  var whenPolymerReady = scope.whenPolymerReady;

  function importElements(elementOrFragment, callback) {
    if (elementOrFragment) {
      var ports = elementOrFragment.querySelectorAll('link[rel=import]');
      // normalize url...
      for (var i=0, l=ports.length, p; (i<l) && (p=ports[i]); i++) {
        p.href = p.href;
      }
      document.head.appendChild(elementOrFragment);
      whenPolymerReady(callback);
    } else if (callback) {
      callback();
    }
  }

  function importUrls(urls, callback) {
    if (urls && urls.length) {
        var frag = document.createDocumentFragment();
        for (var i=0, l=urls.length, url, link; (i<l) && (url=urls[i]); i++) {
          link = document.createElement('link');
          link.rel = 'import';
          link.href = url;
          frag.appendChild(link);
        }
        importElements(frag, callback);
    } else if (callback) {
      callback();
    }
  }

  // exports
  scope.import = importUrls;
  scope.importElements = importElements;

})(Polymer);
<commit_msg>remove path fixup in Polymer.importElements: use Platform.urlResolver.resolveTemplate | resolveDom to fix paths before using importElements.<commit_after>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */
(function(scope) {

  var whenPolymerReady = scope.whenPolymerReady;

  function importElements(elementOrFragment, callback) {
    if (elementOrFragment) {
      document.head.appendChild(elementOrFragment);
      whenPolymerReady(callback);
    } else if (callback) {
      callback();
    }
  }

  function importUrls(urls, callback) {
    if (urls && urls.length) {
        var frag = document.createDocumentFragment();
        for (var i=0, l=urls.length, url, link; (i<l) && (url=urls[i]); i++) {
          link = document.createElement('link');
          link.rel = 'import';
          link.href = url;
          frag.appendChild(link);
        }
        importElements(frag, callback);
    } else if (callback) {
      callback();
    }
  }

  // exports
  scope.import = importUrls;
  scope.importElements = importElements;

})(Polymer);
<|endoftext|>