<commit_before>'use strict';

angular.module('mean.icu.ui.projectdetails', []).controller('ProjectDetailsController', ProjectDetailsController);

function ProjectDetailsController($scope, $rootScope, entity, people, tasks, projects, tags, $timeout, context, $state, ProjectsService, ActivitiesService, PermissionsService, EntityService, $stateParams, me, $window) {

  // ==================================================== init ==================================================== //

  if($state.$current.url.source.includes('search') || $state.$current.url.source.includes('projects')) {
    $scope.item = entity || context.entity;
  }
  else {
    $scope.item = context.entity || entity;
  }

  if(!$scope.item) {
    $state.go('main.projects.byentity', {
      entity: context.entityName,
      entityId: context.entityId
    });
  }
  else if($scope.item && ($state.current.name === 'main.projects.all.details' || $state.current.name === 'main.search.project' || $state.current.name === 'main.projects.byentity.details')) {
    $state.go('.activities');
  }

  $scope.items = projects.data || projects;

  $scope.editorOptions = {
    theme: 'bootstrap',
    buttons: ['bold', 'italic', 'underline', 'anchor', 'quote', 'orderedlist', 'unorderedlist']
  };
  $scope.statuses = ['new', 'assigned', 'in-progress', 'canceled', 'completed', 'archived'];

  $scope.me = me;
  $scope.tags = tags;

  let currentState = $state.current.name;

  // backup for previous changes - for updates
  var backupEntity = JSON.parse(JSON.stringify($scope.item));

  $scope.people = people.data || people;
  if($scope.people && $scope.people[Object.keys($scope.people).length - 1].name !== 'no select') {
    var newPeople = {
      name: 'no select'
    };
    $scope.people.push(_(newPeople).clone());
  }
  for(var i = 0; i < $scope.people.length; i++) {
    if($scope.people[i] && ($scope.people[i].job == undefined || $scope.people[i].job == null)) {
      $scope.people[i].job = $scope.people[i].name;
    }
  }

  ProjectsService.getStarred().then(function(starred) {
    $scope.item.star = _(starred).any(function(s) {
      return s._id === $scope.item._id;
    });
  });

  // ==================================================== onChanges ==================================================== //

  function navigateToDetails(project) {
    $scope.detailsState = context.entityName === 'all' ? 'main.projects.all.details' : 'main.projects.byentity.details';

    $state.go($scope.detailsState, {
      id: project._id,
      entity: context.entityName,
      entityId: context.entityId,
      starred: $stateParams.starred
    }, {
      reload: true
    });
  }

  $scope.onStar = function(value) {
    ProjectsService.star($scope.item).then(function() {
    navigateToDetails($scope.item);
    // "$scope.item.star" will be change in 'ProjectsService.star' function
    });
  };

  $scope.onAssign = function(value) {
    $scope.item.assign = value;
    $scope.updateAndNotify($scope.item);
  };

  $scope.onDateDue = function(value) {
    $scope.item.due = value;
    if(context.entityName === 'discussion') {
      $scope.item.discussion = context.entityId;
    }

    ProjectsService.updateDue($scope.item, backupEntity).then(function (result) {
      backupEntity = JSON.parse(JSON.stringify($scope.item));
      ActivitiesService.data.push(result);
    });

    ProjectsService.update($scope.item).then(function(result) {
      if(context.entityName === 'project') {
        var projId = result.project ? result.project._id : undefined;
        if(projId !== context.entityId) {
          $state.go('main.projects.byentity', {
            entity: context.entityName,
            entityId: context.entityId
          }, {
            reload: true
          });
        }
      }
    });
  };

  $scope.onStatus = function(value) {
    $scope.item.status = value;
    $scope.update($scope.item, {
      name: 'status'
    });
  };

  $scope.onColor = function(value) {
    $scope.update($scope.item, value);
  };

  $scope.onWantToCreateRoom = function() {
    $scope.item.WantRoom = true;
    $scope.update($scope.item, context);

    ProjectsService.WantToCreateRoom($scope.item).then(function(data) {
      navigateToDetails($scope.item);
      if(data.roomName) {
        $window.open(window.config.rocketChat.uri + '/group/', data.roomName);
        return true;
      }
      else {
        return false;
      }
    });
  };

  $scope.onTags = function(value) {
    $scope.item.tags = value;
    $scope.update($scope.item, {name: 'tag'});
  };

  // ==================================================== Menu events ==================================================== //

  $scope.recycle = function() {
    ProjectsService.removeFromParent($scope.item).then(()=>{
      EntityService.recycle('projects', $scope.item._id).then(function() {
        let clonedEntity = JSON.parse(JSON.stringify($scope.item));
        clonedEntity.status = 'Recycled';
        // just for activity status
        ProjectsService.updateStatus(clonedEntity, $scope.item).then(function(result) {
          ActivitiesService.data.push(result);
        });

        refreshList();
        if(currentState.indexOf('search') !== -1) {
          $state.go(currentState, {
            entity: context.entityName,
            entityId: context.entityId
          }, {
            reload: true,
            query: $stateParams.query
          });
        }
        else {
          $state.go('main.projects.all', {
            entity: 'all',
          }, {
            reload: true
          });
        }
      });
    }
    );
  };

  $scope.recycleRestore = function() {
    ProjectsService.addToParent($scope.item).then(()=>{
      EntityService.recycleRestore('projects', $scope.item._id).then(function() {
        let clonedEntity = JSON.parse(JSON.stringify($scope.item));
        clonedEntity.status = 'un-deleted';
        // just for activity status
        ProjectsService.updateStatus(clonedEntity, $scope.item).then(function(result) {
          ActivitiesService.data.push(result);
        });
        refreshList();

        var state = currentState.indexOf('search') !== -1 ? $state.current.name : 'main.projects.all';
        $state.go(state, {
          entity: context.entityName,
          entityId: context.entityId
        }, {
          reload: true
        });
      });
    }
    );
  };

  $scope.menuItems = [
    {
      label: 'recycleProject',
      fa: 'fa-times-circle',
      display: !$scope.item.hasOwnProperty('recycled'),
      action: $scope.recycle
    }, {
      label: 'unrecycleProject',
      fa: 'fa-times-circle',
      display: $scope.item.hasOwnProperty('recycled'),
      action: $scope.recycleRestore,
    }
  ];

  // ==================================================== $watch: title / desc ==================================================== //

  $scope.$watch('item.title', function(nVal, oVal) {
    if(nVal !== oVal && oVal) {
      var newContext = {
        name: 'title',
        oldVal: oVal,
        newVal: nVal,
        action: 'renamed'
      };
      $scope.delayedUpdate($scope.item, newContext);
      ProjectsService.currentProjectName = $scope.item.title;
    }
  });

  var nText, oText;
  $scope.$watch('item.description', function(nVal, oVal) {
    nText = nVal ? nVal.replace(/<(?:.|\n)*?>/gm, '') : '';
    oText = oVal ? oVal.replace(/<(?:.|\n)*?>/gm, '') : '';
    if(nText != oText && oText) {
      var newContext = {
        name: 'description',
        oldVal: oVal,
        newVal: nVal,
        action: 'renamed'
      };
      $scope.delayedUpdate($scope.item, newContext);
    }
  });

  // ==================================================== Update  ==================================================== //

  $scope.updateAndNotify = function(project) {
    project.status = $scope.statuses[1];

    if(context.entityName === 'discussion') {
      project.discussion = context.entityId;
    }

    if(project.assign === undefined || project.assign === null) {
      delete project['assign'];
    }
    else {
      // check the assignee is not a watcher already
      let filtered = project.watchers.filter(watcher=>{
        return watcher._id == project.assign;
      }
      );

      // add assignee as watcher
      if(filtered.length == 0) {
        project.watchers.push(project.assign);
      }
    }

    ProjectsService.update(project).then(function(result) {
      if(context.entityName === 'project') {
        var projId = result.project ? result.project._id : undefined;
        if(projId !== context.entityId) {
          $state.go('main.projects.byentity', {
            entity: context.entityName,
            entityId: context.entityId
          }, {
            reload: true
          });
        }
      }

      ProjectsService.assign(project, me, backupEntity).then(function(res) {
        backupEntity = JSON.parse(JSON.stringify(result));
        ActivitiesService.data.push(res);
      });
    });

  };

  function refreshList() {
    $rootScope.$broadcast('refreshList');
  }

  $scope.update = function(item, type) {
    if(type.name === 'color') {
      item.color = context.newVal;
    }
    ProjectsService.update(item, context).then(function(res) {
      if(ProjectsService.selected && res._id === ProjectsService.selected._id) {
        if(type === 'title') {
          ProjectsService.selected.title = res.title;
        }
      }
      switch (type) {
      case 'status':
        if(context.entityName === 'discussion') {
          item.discussion = context.entityId;
        }

        ProjectsService.updateStatus(item, backupEntity).then(function(result) {
          backupEntity = JSON.parse(JSON.stringify($scope.item));
          ActivitiesService.data = ActivitiesService.data || [];
          ActivitiesService.data.push(result);
        });
        break;

      case 'color':
        ProjectsService.updateColor(item).then(function(result) {
          backupEntity = JSON.parse(JSON.stringify($scope.item));
          ActivitiesService.data = ActivitiesService.data || [];
          ActivitiesService.data.push(result);
        });
        break;
      case 'title':
      case 'description':
        ProjectsService.updateTitle(item, backupEntity, type).then(function(result) {
          backupEntity = JSON.parse(JSON.stringify($scope.item));
          ActivitiesService.data = ActivitiesService.data || [];
          ActivitiesService.data.push(result);
          refreshList();
        });
        break;
      }
    });
  };

  $scope.delayedUpdate = _.debounce($scope.update, 2000);

  // ==================================================== Buttons ==================================================== //

  $scope.updateStatusForApproval = function() {
    let context = {
      action: 'updated',
      name: 'status',
      type: 'project'
    };
    $scope.item.status = 'waiting-approval';
    $scope.update(entity, context);
  };

  // ==================================================== Template ==================================================== //

  $scope.saveTemplate = function(newTemplate) {
    return ProjectsService.saveTemplate($stateParams.id, newTemplate);
  };

  $scope.deleteTemplate = function(id) {
    return ProjectsService.deleteTemplate(id);
  };

  $scope.implementTemplate = function(id) {
    return ProjectsService.template2subProjects(id, {
      projectId: $stateParams.id
    }).then(function(result) {
      for(var i = result.length - 1; i >= 0; i--) {
        result[i].isNew = true;
      }
      $timeout(function() {
        for(var i = result.length - 1; i >= 0; i--) {
          result[i].isNew = false;
        }
      }, 5000);
      var tmp = $scope.item.subProjects.pop();
      $scope.item.subProjects = $scope.item.subProjects.concat(result);
      $scope.item.subProjects.push(tmp);
    });
  };
  // ==================================================== havePermissions ==================================================== //

  $scope.enableRecycled = true;
  $scope.isRecycled = $scope.item.hasOwnProperty('recycled');

  $scope.permsToSee = function() {
    return PermissionsService.haveAnyPerms($scope.item);
  };

  $scope.havePermissions = function(type, enableRecycled) {
    enableRecycled = enableRecycled || !$scope.isRecycled;
    return PermissionsService.havePermissions($scope.item, type) && enableRecycled;
  };

  $scope.haveEditiorsPermissions = function() {
    return PermissionsService.haveEditorsPerms($scope.item);
  };

}
<commit_msg>fixed color saving in projects https://github.com/linnovate/root/issues/1220<commit_after>'use strict';

angular.module('mean.icu.ui.projectdetails', []).controller('ProjectDetailsController', ProjectDetailsController);

function ProjectDetailsController($scope, $rootScope, entity, people, tasks, projects, tags, $timeout, context, $state, ProjectsService, ActivitiesService, PermissionsService, EntityService, $stateParams, me, $window) {

  // ==================================================== init ==================================================== //

  if($state.$current.url.source.includes('search') || $state.$current.url.source.includes('projects')) {
    $scope.item = entity || context.entity;
  }
  else {
    $scope.item = context.entity || entity;
  }

  if(!$scope.item) {
    $state.go('main.projects.byentity', {
      entity: context.entityName,
      entityId: context.entityId
    });
  }
  else if($scope.item && ($state.current.name === 'main.projects.all.details' || $state.current.name === 'main.search.project' || $state.current.name === 'main.projects.byentity.details')) {
    $state.go('.activities');
  }

  $scope.items = projects.data || projects;

  $scope.editorOptions = {
    theme: 'bootstrap',
    buttons: ['bold', 'italic', 'underline', 'anchor', 'quote', 'orderedlist', 'unorderedlist']
  };
  $scope.statuses = ['new', 'assigned', 'in-progress', 'canceled', 'completed', 'archived'];

  $scope.me = me;
  $scope.tags = tags;

  let currentState = $state.current.name;

  // backup for previous changes - for updates
  var backupEntity = JSON.parse(JSON.stringify($scope.item));

  $scope.people = people.data || people;
  if($scope.people && $scope.people[Object.keys($scope.people).length - 1].name !== 'no select') {
    var newPeople = {
      name: 'no select'
    };
    $scope.people.push(_(newPeople).clone());
  }
  for(var i = 0; i < $scope.people.length; i++) {
    if($scope.people[i] && ($scope.people[i].job == undefined || $scope.people[i].job == null)) {
      $scope.people[i].job = $scope.people[i].name;
    }
  }

  ProjectsService.getStarred().then(function(starred) {
    $scope.item.star = _(starred).any(function(s) {
      return s._id === $scope.item._id;
    });
  });

  // ==================================================== onChanges ==================================================== //

  function navigateToDetails(project) {
    $scope.detailsState = context.entityName === 'all' ? 'main.projects.all.details' : 'main.projects.byentity.details';

    $state.go($scope.detailsState, {
      id: project._id,
      entity: context.entityName,
      entityId: context.entityId,
      starred: $stateParams.starred
    }, {
      reload: true
    });
  }

  $scope.onStar = function(value) {
    ProjectsService.star($scope.item).then(function() {
    navigateToDetails($scope.item);
    // "$scope.item.star" will be change in 'ProjectsService.star' function
    });
  };

  $scope.onAssign = function(value) {
    $scope.item.assign = value;
    $scope.updateAndNotify($scope.item);
  };

  $scope.onDateDue = function(value) {
    $scope.item.due = value;
    if(context.entityName === 'discussion') {
      $scope.item.discussion = context.entityId;
    }

    ProjectsService.updateDue($scope.item, backupEntity).then(function (result) {
      backupEntity = JSON.parse(JSON.stringify($scope.item));
      ActivitiesService.data.push(result);
    });

    ProjectsService.update($scope.item).then(function(result) {
      if(context.entityName === 'project') {
        var projId = result.project ? result.project._id : undefined;
        if(projId !== context.entityId) {
          $state.go('main.projects.byentity', {
            entity: context.entityName,
            entityId: context.entityId
          }, {
            reload: true
          });
        }
      }
    });
  };

  $scope.onStatus = function(value) {
    $scope.item.status = value;
    $scope.update($scope.item, {
      name: 'status'
    });
  };

  $scope.onColor = function(value) {
    $scope.update($scope.item, value);
  };

  $scope.onWantToCreateRoom = function() {
    $scope.item.WantRoom = true;
    $scope.update($scope.item, context);

    ProjectsService.WantToCreateRoom($scope.item).then(function(data) {
      navigateToDetails($scope.item);
      if(data.roomName) {
        $window.open(window.config.rocketChat.uri + '/group/', data.roomName);
        return true;
      }
      else {
        return false;
      }
    });
  };

  $scope.onTags = function(value) {
    $scope.item.tags = value;
    $scope.update($scope.item, {name: 'tag'});
  };

  // ==================================================== Menu events ==================================================== //

  $scope.recycle = function() {
    ProjectsService.removeFromParent($scope.item).then(()=>{
      EntityService.recycle('projects', $scope.item._id).then(function() {
        let clonedEntity = JSON.parse(JSON.stringify($scope.item));
        clonedEntity.status = 'Recycled';
        // just for activity status
        ProjectsService.updateStatus(clonedEntity, $scope.item).then(function(result) {
          ActivitiesService.data.push(result);
        });

        refreshList();
        if(currentState.indexOf('search') !== -1) {
          $state.go(currentState, {
            entity: context.entityName,
            entityId: context.entityId
          }, {
            reload: true,
            query: $stateParams.query
          });
        }
        else {
          $state.go('main.projects.all', {
            entity: 'all',
          }, {
            reload: true
          });
        }
      });
    }
    );
  };

  $scope.recycleRestore = function() {
    ProjectsService.addToParent($scope.item).then(()=>{
      EntityService.recycleRestore('projects', $scope.item._id).then(function() {
        let clonedEntity = JSON.parse(JSON.stringify($scope.item));
        clonedEntity.status = 'un-deleted';
        // just for activity status
        ProjectsService.updateStatus(clonedEntity, $scope.item).then(function(result) {
          ActivitiesService.data.push(result);
        });
        refreshList();

        var state = currentState.indexOf('search') !== -1 ? $state.current.name : 'main.projects.all';
        $state.go(state, {
          entity: context.entityName,
          entityId: context.entityId
        }, {
          reload: true
        });
      });
    }
    );
  };

  $scope.menuItems = [
    {
      label: 'recycleProject',
      fa: 'fa-times-circle',
      display: !$scope.item.hasOwnProperty('recycled'),
      action: $scope.recycle
    }, {
      label: 'unrecycleProject',
      fa: 'fa-times-circle',
      display: $scope.item.hasOwnProperty('recycled'),
      action: $scope.recycleRestore,
    }
  ];

  // ==================================================== $watch: title / desc ==================================================== //

  $scope.$watch('item.title', function(nVal, oVal) {
    if(nVal !== oVal && oVal) {
      var newContext = {
        name: 'title',
        oldVal: oVal,
        newVal: nVal,
        action: 'renamed'
      };
      $scope.delayedUpdate($scope.item, newContext);
      ProjectsService.currentProjectName = $scope.item.title;
    }
  });

  var nText, oText;
  $scope.$watch('item.description', function(nVal, oVal) {
    nText = nVal ? nVal.replace(/<(?:.|\n)*?>/gm, '') : '';
    oText = oVal ? oVal.replace(/<(?:.|\n)*?>/gm, '') : '';
    if(nText != oText && oText) {
      var newContext = {
        name: 'description',
        oldVal: oVal,
        newVal: nVal,
        action: 'renamed'
      };
      $scope.delayedUpdate($scope.item, newContext);
    }
  });

  // ==================================================== Update  ==================================================== //

  $scope.updateAndNotify = function(project) {
    project.status = $scope.statuses[1];

    if(context.entityName === 'discussion') {
      project.discussion = context.entityId;
    }

    if(project.assign === undefined || project.assign === null) {
      delete project['assign'];
    }
    else {
      // check the assignee is not a watcher already
      let filtered = project.watchers.filter(watcher=>{
        return watcher._id == project.assign;
      }
      );

      // add assignee as watcher
      if(filtered.length == 0) {
        project.watchers.push(project.assign);
      }
    }

    ProjectsService.update(project).then(function(result) {
      if(context.entityName === 'project') {
        var projId = result.project ? result.project._id : undefined;
        if(projId !== context.entityId) {
          $state.go('main.projects.byentity', {
            entity: context.entityName,
            entityId: context.entityId
          }, {
            reload: true
          });
        }
      }

      ProjectsService.assign(project, me, backupEntity).then(function(res) {
        backupEntity = JSON.parse(JSON.stringify(result));
        ActivitiesService.data.push(res);
      });
    });

  };

  function refreshList() {
    $rootScope.$broadcast('refreshList');
  }

  $scope.update = function(item, type) {
    if(type.name === 'color') {
      item.color = type.newVal;
    }
    ProjectsService.update(item, context).then(function(res) {
      if(ProjectsService.selected && res._id === ProjectsService.selected._id) {
        if(type === 'title') {
          ProjectsService.selected.title = res.title;
        }
      }
      switch (type) {
      case 'status':
        if(context.entityName === 'discussion') {
          item.discussion = context.entityId;
        }

        ProjectsService.updateStatus(item, backupEntity).then(function(result) {
          backupEntity = JSON.parse(JSON.stringify($scope.item));
          ActivitiesService.data = ActivitiesService.data || [];
          ActivitiesService.data.push(result);
        });
        break;

      case 'color':
        ProjectsService.updateColor(item).then(function(result) {
          backupEntity = JSON.parse(JSON.stringify($scope.item));
          ActivitiesService.data = ActivitiesService.data || [];
          ActivitiesService.data.push(result);
        });
        break;
      case 'title':
      case 'description':
        ProjectsService.updateTitle(item, backupEntity, type).then(function(result) {
          backupEntity = JSON.parse(JSON.stringify($scope.item));
          ActivitiesService.data = ActivitiesService.data || [];
          ActivitiesService.data.push(result);
          refreshList();
        });
        break;
      }
    });
  };

  $scope.delayedUpdate = _.debounce($scope.update, 2000);

  // ==================================================== Buttons ==================================================== //

  $scope.updateStatusForApproval = function() {
    let context = {
      action: 'updated',
      name: 'status',
      type: 'project'
    };
    $scope.item.status = 'waiting-approval';
    $scope.update(entity, context);
  };

  // ==================================================== Template ==================================================== //

  $scope.saveTemplate = function(newTemplate) {
    return ProjectsService.saveTemplate($stateParams.id, newTemplate);
  };

  $scope.deleteTemplate = function(id) {
    return ProjectsService.deleteTemplate(id);
  };

  $scope.implementTemplate = function(id) {
    return ProjectsService.template2subProjects(id, {
      projectId: $stateParams.id
    }).then(function(result) {
      for(var i = result.length - 1; i >= 0; i--) {
        result[i].isNew = true;
      }
      $timeout(function() {
        for(var i = result.length - 1; i >= 0; i--) {
          result[i].isNew = false;
        }
      }, 5000);
      var tmp = $scope.item.subProjects.pop();
      $scope.item.subProjects = $scope.item.subProjects.concat(result);
      $scope.item.subProjects.push(tmp);
    });
  };
  // ==================================================== havePermissions ==================================================== //

  $scope.enableRecycled = true;
  $scope.isRecycled = $scope.item.hasOwnProperty('recycled');

  $scope.permsToSee = function() {
    return PermissionsService.haveAnyPerms($scope.item);
  };

  $scope.havePermissions = function(type, enableRecycled) {
    enableRecycled = enableRecycled || !$scope.isRecycled;
    return PermissionsService.havePermissions($scope.item, type) && enableRecycled;
  };

  $scope.haveEditiorsPermissions = function() {
    return PermissionsService.haveEditorsPerms($scope.item);
  };

}
<|endoftext|>


<commit_before>// @flow

function deleteCache (path: string) {
  delete require.cache[path]
}

// This plugin flushes require.cache after emitting the files. Providing 'hot reloading' of server files.
export default class ChunkNamesPlugin {
  prevAssets: null | {[string]: {existsAt: string}}
  constructor () {
    this.prevAssets = null
  }
  apply (compiler: any) {
    compiler.hooks.afterEmit.tapAsync('NextJsRequireCacheHotReloader', (compilation, callback) => {
      const { assets } = compilation

      if (this.prevAssets) {
        for (const f of Object.keys(assets)) {
          deleteCache(assets[f].existsAt)
        }
        for (const f of Object.keys(this.prevAssets)) {
          if (!assets[f]) {
            deleteCache(this.prevAssets[f].existsAt)
          }
        }
      }
      this.prevAssets = assets

      callback()
    })
  }
}
<commit_msg>Rename class to NextJsRequireCacheHotReloader<commit_after>// @flow

function deleteCache (path: string) {
  delete require.cache[path]
}

// This plugin flushes require.cache after emitting the files. Providing 'hot reloading' of server files.
export default class NextJsRequireCacheHotReloader {
  prevAssets: null | {[string]: {existsAt: string}}
  constructor () {
    this.prevAssets = null
  }
  apply (compiler: any) {
    compiler.hooks.afterEmit.tapAsync('NextJsRequireCacheHotReloader', (compilation, callback) => {
      const { assets } = compilation

      if (this.prevAssets) {
        for (const f of Object.keys(assets)) {
          deleteCache(assets[f].existsAt)
        }
        for (const f of Object.keys(this.prevAssets)) {
          if (!assets[f]) {
            deleteCache(this.prevAssets[f].existsAt)
          }
        }
      }
      this.prevAssets = assets

      callback()
    })
  }
}
<|endoftext|>


<commit_before>const opcua = require("node-opcua");
const path = require("path");
// Create a new instance of vantage.
const Vorpal = require("vorpal");
const vorpal_repl = require("vorpal-repl");

const server_certificate_file = path.join(__dirname,"../certificates/discoveryServer_selfsigned_cert_2048.pem");
const server_certificate_privatekey_file  = path.join(__dirname,"../certificates/discoveryServer_key_2048.pem");

const discoveryServer = new opcua.OPCUADiscoveryServer({
    // register
    // port: 4840,
    certificateFile: server_certificate_file,
    privateKeyFile: server_certificate_privatekey_file,

});
discoveryServer.start(function(err) {

    if (err) {
        console.log("Error , cannot start LDS ", err.message);
        console.log("Make sure that a LocalDiscoveryServer is not already running");
        return;

    }
    console.log("discovery server started on port ",discoveryServer.endpoints[0].port);
    console.log("CTRL+C to stop");

// Add the command "foo", which logs "bar".
    const vorpal = new Vorpal();
    vorpal
        .command("info")
        .description("display list of registered servers.")
        .action(function(args, callback) {

            this.log(discoveryServer.serverInfo);
            // xx this.log(discoveryServer.endpoints[0]);

            const servers = Object.keys(discoveryServer.registered_servers);
            this.log("number of registered servers : ", servers.length);

            for (const serverKey of servers) {
                const server = discoveryServer.registered_servers[serverKey];
                this.log("key =" , serverKey);
                this.log(server.toString());

            }
            callback();
        });
        vorpal.delimiter("local-discovery-server$").use(vorpal_repl).show();

});
<commit_msg>add shebang section<commit_after>#!/usr/bin/env node
const opcua = require("node-opcua");
const path = require("path");
// Create a new instance of vantage.
const Vorpal = require("vorpal");
const vorpal_repl = require("vorpal-repl");

const server_certificate_file = path.join(__dirname,"../certificates/discoveryServer_selfsigned_cert_2048.pem");
const server_certificate_privatekey_file  = path.join(__dirname,"../certificates/discoveryServer_key_2048.pem");

const discoveryServer = new opcua.OPCUADiscoveryServer({
    // register
    // port: 4840,
    certificateFile: server_certificate_file,
    privateKeyFile: server_certificate_privatekey_file,

});
discoveryServer.start(function(err) {

    if (err) {
        console.log("Error , cannot start LDS ", err.message);
        console.log("Make sure that a LocalDiscoveryServer is not already running");
        return;

    }
    console.log("discovery server started on port ",discoveryServer.endpoints[0].port);
    console.log("CTRL+C to stop");

// Add the command "foo", which logs "bar".
    const vorpal = new Vorpal();
    vorpal
        .command("info")
        .description("display list of registered servers.")
        .action(function(args, callback) {

            this.log(discoveryServer.serverInfo);
            // xx this.log(discoveryServer.endpoints[0]);

            const servers = Object.keys(discoveryServer.registered_servers);
            this.log("number of registered servers : ", servers.length);

            for (const serverKey of servers) {
                const server = discoveryServer.registered_servers[serverKey];
                this.log("key =" , serverKey);
                this.log(server.toString());

            }
            callback();
        });
        vorpal.delimiter("local-discovery-server$").use(vorpal_repl).show();

});
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.HTMLBars.makeBoundHelper(function(value, options) {
  var escapedSrc = Ember.Handlebars.Utils.escapeExpression(options.src),
    escapedBase = Ember.Handlebars.Utils.escapeExpression(options.base);

    if(escapedSrc.charAt(0) === '/'){
      escapedSrc = escapedSrc.substring(1, escapedSrc.length);
    }

    if(escapedBase.slice(-1) === '/'){
      escapedBase = escapedBase.substring(0, escapedBase.length - 1);
    }
    else if(escapedBase.lastIndexOf('/') > 'http://'.length)
    {
      escapedBase = escapedBase.substring(0, escapedBase.lastIndexOf('/'));
    }
    var url = escapedSrc;
    if (url.indexOf('data:') !== 0) {
      if(url.indexOf('http') === -1){
        url = escapedBase + '/'+ escapedSrc;
      }
    }

  return new Ember.Handlebars.SafeString('');
});
<commit_msg>update for nonrelative URLs<commit_after>import Ember from 'ember';

export default Ember.HTMLBars.makeBoundHelper(function(value, options) {
  var escapedSrc = Ember.Handlebars.Utils.escapeExpression(options.src),
    escapedBase = Ember.Handlebars.Utils.escapeExpression(options.base);
  /*adding in this fix for URLs from wrong path, but need to make sure it works with mastodon.social for rebuild */
    var pathArray = escapedBase.split( '/' );
    var protocol = pathArray[0];
    var host = pathArray[2];
    escapedBase = protocol + '//' + host;

    if(escapedSrc.charAt(0) === '/'){
      escapedSrc = escapedSrc.substring(1, escapedSrc.length);
    }

    if(escapedBase.slice(-1) === '/'){
      escapedBase = escapedBase.substring(0, escapedBase.length - 1);
    }
    else if(escapedBase.lastIndexOf('/') > 'http://'.length)
    {
      escapedBase = escapedBase.substring(0, escapedBase.lastIndexOf('/'));
    }
    var url = escapedSrc;
    if (url.indexOf('data:') !== 0) {
      if(url.indexOf('http') === -1){
        url = escapedBase + '/'+ escapedSrc;
      }
    }

  return new Ember.Handlebars.SafeString('');
});
<|endoftext|>


<commit_before>import * as delaney  from '../dsymbols/delaney';

export default function* symbols(text) {
  let i = 0;
  let buffer = [];
  let attributes = {};

  for (const line of text.split(/\r?\n/)) {
    const lineNr = ++i;
    const m = line.match(/\s*#\s*@\s*(.*)/);

    if (m && m[1]) {
      const fields = m[1].trim().split(/\s+/);
      attributes[fields[0]] = fields.slice(1).join(' ');
    }
    else {
      const content = line.replace(/[#>].*/, '').trim()
      buffer.push(content);
      if (line.match(/>/)) {
        yield Object.assign(
          attributes,
          { type: 'tiling',
            symbol: delaney.parse(buffer.join(' ') + '>')
          }
        );
        attributes = {};
        buffer = [];
      }
    }
  }
};

if (require.main == module) {
  const text = `
#@ name test
<1.1:
1:
1,1,1:
4,4
>

    <1:1,1,1:6,3>
`;

  for (const s of symbols(text))
    console.log(JSON.stringify(s));
}
<commit_msg>io/ds: some code tweaks; record start and end lines in output<commit_after>import { parse } from '../dsymbols/delaney';

export default function* symbols(text) {
  const type = 'tiling';

  let lineNr = 0;
  let startLine = null;
  let buffer = [];
  let attributes = {};

  for (const line of text.split(/\r?\n/)) {
    lineNr++;

    const match = line.match(/\s*#\s*@\s*(.*)/);

    if (match && match[1]) {
      if (startLine == null)
        startLine = lineNr;

      const fields = match[1].trim().split(/\s+/);
      attributes[fields[0]] = fields.slice(1).join(' ');
    }
    else {
      buffer.push(line.replace(/[#>].*/, '').trim());

      if (line.match(/</) && startLine == null)
        startLine = lineNr

      if (line.match(/>/)) {
        const symbol = parse(buffer.join(' ') + '>');
        const endLine = lineNr;

        yield Object.assign(attributes, { type, symbol, startLine, endLine });

        attributes = {};
        buffer = [];
        startLine = null;
      }
    }
  }
};

if (require.main == module) {
  const text = `
#@ name test
<1.1:
1:
1,1,1:
4,4
>

    <1:1,1,1:6,3>
`;

  for (const s of symbols(text)) {
    for (const k of Object.keys(s))
      console.log(`${k}: ${s[k]}`);
    console.log();
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2020, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.ui.form.on('Document Naming Rule', {
	refresh: function(frm) {
		frm.trigger('document_type');
		if (!frm.doc.__islocal) frm.trigger("add_button");
	},
	document_type: (frm) => {
		// update the select field options with fieldnames
		if (frm.doc.document_type) {
			frappe.model.with_doctype(frm.doc.document_type, () => {
				let fieldnames = frappe.get_meta(frm.doc.document_type).fields
					.filter((d) => {
						return frappe.model.no_value_type.indexOf(d.fieldtype) === -1;
					}).map((d) => {
						return {label: `${d.label} (${d.fieldname})`, value: d.fieldname};
					});
				frm.fields_dict.conditions.grid.update_docfield_property(
					'field', 'options', fieldnames
				);
			});
		}
	},
	add_button: (frm) => {
		frm.add_custom_button(__('Update Counter'), function() {

			const fields = [{
				fieldtype: 'Data',
				fieldname: 'new_counter',
				label: __('New Counter'),
				default: frm.doc.counter,
				reqd: 1,
				description: __('Warning: Updating counter may lead to document name conflicts if not done properly')
			}];

			let primary_action_label = __('Save');

			let primary_action = (fields) => {
				frappe.call({
					method: 'frappe.core.doctype.document_naming_rule.document_naming_rule.update_current',
					args: {
						name: frm.doc.name,
						new_counter: fields.new_counter
					},
					callback: function() {
						frm.set_value("counter",  fields.new_counter);
						dialog.hide();
					}
				});
			};

			var dialog = new frappe.ui.Dialog({
				title: __('Update Counter Value for Prefix: {0}', [frm.doc.prefix]),
				fields,
				primary_action_label,
				primary_action
			});

			dialog.show();

		});
	}
});
<commit_msg>Update frappe/core/doctype/document_naming_rule/document_naming_rule.js<commit_after>// Copyright (c) 2020, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.ui.form.on('Document Naming Rule', {
	refresh: function(frm) {
		frm.trigger('document_type');
		if (!frm.doc.__islocal) frm.trigger("add_button");
	},
	document_type: (frm) => {
		// update the select field options with fieldnames
		if (frm.doc.document_type) {
			frappe.model.with_doctype(frm.doc.document_type, () => {
				let fieldnames = frappe.get_meta(frm.doc.document_type).fields
					.filter((d) => {
						return frappe.model.no_value_type.indexOf(d.fieldtype) === -1;
					}).map((d) => {
						return {label: `${d.label} (${d.fieldname})`, value: d.fieldname};
					});
				frm.fields_dict.conditions.grid.update_docfield_property(
					'field', 'options', fieldnames
				);
			});
		}
	},
	add_button: (frm) => {
		frm.add_custom_button(__('Update Counter'), function() {

			const fields = [{
				fieldtype: 'Data',
				fieldname: 'new_counter',
				label: __('New Counter'),
				default: frm.doc.counter,
				reqd: 1,
				description: __('Warning: Updating counter may lead to document name conflicts if not done properly')
			}];

			let primary_action_label = __('Save');

			let primary_action = (fields) => {
				frappe.call({
					method: 'frappe.core.doctype.document_naming_rule.document_naming_rule.update_current',
					args: {
						name: frm.doc.name,
						new_counter: fields.new_counter
					},
					callback: function() {
						frm.set_value("counter",  fields.new_counter);
						dialog.hide();
					}
				});
			};

			const dialog = new frappe.ui.Dialog({
				title: __('Update Counter Value for Prefix: {0}', [frm.doc.prefix]),
				fields,
				primary_action_label,
				primary_action
			});

			dialog.show();

		});
	}
});
<|endoftext|>


<commit_before>function getNumberFeatureTypes(features) {
  featuresNew = [];
  var found = 0;
  for(i = 0; i < features.length; i++) {
   found = 0;
   for(j = 0; j < featuresNew.length; j++) {
    if (featuresNew[j] == features[i].type) {
     found = 1;
    }
   }
   if (found == 0) {
    featuresNew.push(features[i].type);
   }
  }
  return featuresNew.length;
 }

function update(data) {

    var divWidth = $('.svg-container').width(),
        svg = d3.select("."+data.id);

    var chart = genomeChart().svgWidth(divWidth);

    svg.datum(data)
       .call(chart);

}

/* genome chart closure */
function genomeChart() {

    var svgWidth = 400,
        svgHeight = 245,
        margin = {top: 3, right: 60, bottom: 42, left: 60},
        width = svgWidth - margin.left - margin.right,
        height = svgHeight - margin.top - margin.bottom,
        height_block = 20, vpad_block = 5;

    function chart(selection) {
        // GENOME CHART FUNCTION
        selection.each(function (data) {

            // tooltip (needs to be initialized)
            var tip = d3.tip()
                 .attr('class', 'd3-tip')
                 .html(function(d) { return d.name + ": " + (+d.location[0][0] + 1) + ", " + d.location[0][1]; });

            // outer chart with genometric zoom upon resizing
            var svg = d3.select(this)
                .attr("preserveAspectRatio", "xMinYMin meet")
                .attr("viewBox", "0 0 " + svgWidth + " " + svgHeight);

            // internal chart, only the bars
            var vis = svg.append("g")
                 .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            // add tooltip
            vis.call(tip);

            var genome = data.genome,
                id = data.id,
                features = genome.features;

            var x = d3.scale.linear()
                 .domain([-50, genome.len + 50])
                 .range([20, width - 20]);

            var xAxis = d3.svg.axis()
                .scale(x)
                .orient("bottom");

            // add axis to the chart
            var xAxisObj = vis.append("g")
                              .attr("class", "d3-axis")
                              .attr("transform", "translate(0," + height + ")")
                              .call(xAxis)

            xAxisObj.append("text")
                    .attr("x", width / 2)
                    .attr("y", 40)
                    .style("text-anchor", "middle")
                    .text("Position [bp]");

            // add the rest of the rectangle box
            xAxisObj.append("line")
             .attr({"class": "bBox",
                    "x1": x(-50), "x2": x(-50),
                    "y1": 0, "y2": -height});
            xAxisObj.append("line")
             .attr({"class": "bBox",
                    "x1": x(genome.len + 50), "x2": x(genome.len + 50),
                    "y1": 0, "y2": -height});
            xAxisObj.append("line")
             .attr({"class": "bBox",
                    "x1": x(-50), "x2": x(genome.len + 50),
                    "y1": -height, "y2": -height});

            function getFeatureGroup(groupname) {
                var group = [];
                var gname = "";
                var tmpfea;
                for(i = 0; i < features.length; i++) {
                 gname = features[i].type
                 if (gname == groupname) {
                  group.push(features[i]);
                 } else if (gname + '-single' == groupname) {
                  if (['vpu', 'vpr', 'nef', 'vif'].indexOf(features[i].name) != -1) {
                   group.push(features[i]);
                  }
                 } else if (gname + '-exon1' == groupname) {
                  if (['rev', 'tat'].indexOf(features[i].name) != -1) {
                   tmpfea = {"name": features[i].name + ' exon 1',
                             "type": "gene",
                             "location": [features[i].location[0]]};
                   group.push(tmpfea);
                  }
                 } else if (gname + '-exon2' == groupname) {
                  if (['rev', 'tat'].indexOf(features[i].name) != -1) {
                   tmpfea = {"name": features[i].name + ' exon 2',
                             "type": "gene",
                             "location": [features[i].location[1]]};
                   group.push(tmpfea);
                  }
                 }
                }
                return group;
            }

            function height_feature(feature) {
                if (feature.type == "fragment")
                    return height_fragment(feature);
                else if ((feature.type == "protein") | (feature.type == "gene"))
                    return height_inframe(feature);
                else
                    return 0;
            }

            function height_fragment(fragment) {
                var fn = +(fragment.name[1]);
                var height = vpad_block;
                if ((fn % 2) == 0)
                    height += height_block + vpad_block;
                return height;
            }

            function height_inframe(feature) {
                var frame;
                if (['tat exon 2', 'rev exon 2'].indexOf(feature.name) != -1)
                    frame = (+(feature.location[0][1]) - (+genome.framestart)) % 3;
               else
                 frame = (+(feature.location[0][0]) - (+genome.framestart)) % 3;
               return frame * (height_block + vpad_block);
            }

            function moverFeature(d) {
                // change color
                var rect = d3.select("#" + d.name.replace(/[ ']/g, "-") + "rect");

                rect.style("fill", "darkred");

                // show tooltip
                tip.show(d);

                // show line connecting the exons
                var exons = [];
                if (d.name.indexOf('exon 1') != -1)
                    exons = ["exon-1", "exon-2"];
                else if (d.name.indexOf('exon 2') != -1)
                    exons = ["exon-2", "exon-1"];

                if (exons.length > 0) {
                    var rect2 = d3.select("#" + d.name.replace(/[ ']/g, "-").replace(exons[0], exons[1]) + "rect");
                    var d2 = rect2.data()[0];
                    var box2 = d3.select('#' + d.name.replace(/[ ']/g, "-").replace(exons[0], exons[1]) + "-box");
                    // FIXME: rewrite (?): we extract the y coordinate from the affine transformation STRING!
                    var boxy = +(d3.select(this).attr("transform").split(",")[1].split(")")[0]);
                    var box2y = +(box2.attr("transform").split(",")[1].split(")")[0]);

                    vis.append('line')
                        .attr("class", "exon-line")
                        .attr("x1", 0.5 * (x(d.location[0][1]) + x(d.location[0][0])))
                        .attr("x2", 0.5 * (x(d2.location[0][1]) + x(d2.location[0][0])))
                        .attr("y1", boxy + 0.5 * height_block)
                        .attr("y2", box2y + 0.5 * height_block)
                        .style("opacity", 0.7)
                        .style("stroke", "darkred")
                        .style("stroke-width", 2);
                }
            }

            function moutFeature(d) {
                // change color back
                d3.select("#" + d.name.replace(/[ ']/g, "-") + "rect")
                    .style("fill", "steelblue");

                // hide tooltip
                tip.hide(d);

                // hide exon line
                if ((d.name.indexOf('exon 1') != -1) | (d.name.indexOf('exon 2') != -1))
                  vis.selectAll(".exon-line").remove();
            }

            function plot_group(groupname, dy) {
                var group = getFeatureGroup(groupname);
                var fea = vis.selectAll()
                    .data(group)
                    .enter()
                    .append("g")
                    .attr("class", "featurebox " + groupname)
                    .attr("id", function(d) { return d.name.replace(/[ ']/g, "-") + "-box"; })
                    .attr("transform", function(d) { return "translate(" + x(d.location[0][0]) + "," + (dy + height_feature(d)) + ")";})
                    .on('mouseover', moverFeature)
                    .on('mouseout', moutFeature);

                var fearect = fea.append("rect")
                    .attr("class", "featurerect")
                    .attr("id", function(d) { return d.name.replace(/[ ']/g, "-") + "rect"; })
                    .attr("x", 0)
                    .attr("y", 0)
                    .attr("width", function(d) { return x(d.location[0][1]) - x(d.location[0][0]); })
                    .attr("height", 20)
                    .style("fill", "steelblue")
                    .style("fill-opacity", 0.5)
                    .style("stroke-width", 1)
                    .style("stroke", "black");

                // show text only of longer things (that's why we have a tooltip)
                fea.append("text")
                    .attr("x", function(d) { return 0.5 * (x(d.location[0][1]) - x(d.location[0][0])); })
                    .attr("y", 15)
                    .text(function(d) {
                        if ((d.location[0][1] - d.location[0][0]) > 350)
                            return d.name;
                        else
                            return "";
                    })
                    .style("text-anchor", "middle");
            }

            plot_group("fragment", 0);
            plot_group("protein", 75);
            plot_group("gene-single", 75);
            plot_group("gene-exon1", 75);
            plot_group("gene-exon2", 75);
            plot_group("RNA_structure", 170);
            plot_group("other", 170);

        });

    }

    chart.margin = function (_) {
        if (!arguments.length) return margin;
        margin = _;
        width = svgWidth - margin.left - margin.right;
        height = svgHeight - margin.top - margin.bottom;
        return chart;
    };

    chart.svgWidth = function (_) {
        if (!arguments.length) return width;
        svgWidth = _;
        width = svgWidth - margin.left - margin.right;
        return chart;
    };

    chart.svgHeight = function (_) {
        if (!arguments.length) return height;
        svgHeight = _;
        height = svgHeight - margin.top - margin.bottom;
        return chart;
    };

    return chart;

}
<commit_msg>genome has zoom (no transitions)<commit_after>function getNumberFeatureTypes(features) {
  featuresNew = [];
  var found = 0;
  for(i = 0; i < features.length; i++) {
   found = 0;
   for(j = 0; j < featuresNew.length; j++) {
    if (featuresNew[j] == features[i].type) {
     found = 1;
    }
   }
   if (found == 0) {
    featuresNew.push(features[i].type);
   }
  }
  return featuresNew.length;
 }

function update(data) {

    var divWidth = $('.svg-container').width(),
        svg = d3.select("."+data.id);

    var chart = genomeChart().svgWidth(divWidth);

    svg.datum(data)
       .call(chart);

}

/* genome chart closure */
function genomeChart() {

    var svgWidth = 400,
        svgHeight = 245,
        margin = {top: 3, right: 60, bottom: 42, left: 60},
        width = svgWidth - margin.left - margin.right,
        height = svgHeight - margin.top - margin.bottom,
        heightBlock = 20, vpadBlock = 5;

    function chart(selection) {
        // GENOME CHART FUNCTION
        selection.each(function (data) {

            // tooltip (needs to be initialized)
            var tip = d3.tip()
                 .attr('class', 'd3-tip')
                 .html(function(d) { return d.name + ": " + (+d.location[0][0] + 1) + ", " + d.location[0][1]; });

            // outer chart with genometric zoom upon resizing
            var svg = d3.select(this)
                .attr("preserveAspectRatio", "xMinYMin meet")
                .attr("viewBox", "0 0 " + svgWidth + " " + svgHeight);

            // internal chart, only the bars
            var vis = svg.append("g")
                 .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            // add tooltip
            vis.call(tip);

            var genome = data.genome,
                id = data.id,
                features = genome.features;

            var x = d3.scale.linear()
                 .domain([-50, genome.len + 50])
                 .range([20, width - 20]);

            var xAxis = d3.svg.axis()
                .scale(x)
                .orient("bottom");

            // add axis to the chart
            var xAxisObj = vis.append("g")
                              .attr("class", "d3-axis")
                              .attr("transform", "translate(0," + height + ")")
                              .call(xAxis)

            xAxisObj.append("text")
                    .attr("x", width / 2)
                    .attr("y", 40)
                    .style("text-anchor", "middle")
                    .text("Position [bp]");

            // add the rest of the rectangle box
            xAxisObj.append("line")
             .attr({"class": "bBox",
                    "x1": x(-50), "x2": x(-50),
                    "y1": 0, "y2": -height});
            xAxisObj.append("line")
             .attr({"class": "bBox",
                    "x1": x(genome.len + 50), "x2": x(genome.len + 50),
                    "y1": 0, "y2": -height});
            xAxisObj.append("line")
             .attr({"class": "bBox",
                    "x1": x(-50), "x2": x(genome.len + 50),
                    "y1": -height, "y2": -height});

            // plot the various bars
            plotAllFeatures();

            function plotAllFeatures() {
                plotFeatureGroup("fragment", 0);
                plotFeatureGroup("protein", 75);
                plotFeatureGroup("gene-single", 75);
                plotFeatureGroup("gene-exon1", 75);
                plotFeatureGroup("gene-exon2", 75);
                plotFeatureGroup("RNA_structure", 170);
                plotFeatureGroup("other", 170);
            }

            function clickFeature(d) {
                var self = d3.select(this);

                // TODO: use transitions, but they have to be simultaneous which requires some Chinese-boxing

                if (!(self.classed("zoomed"))) {
                    var start = d.location[0][0],
                        end = d.location[0][1];

                    // delete boxes fully outside of window
                    vis.selectAll(".featurebox")
                        .filter(function(dOther) { return (dOther.location[0][0] >= end) | (dOther.location[0][1] <= start); })
                        .remove();

                    // in case exon lines are being shown, stop
                    vis.selectAll(".exon-line").remove();

                    // change the x scale
                    var boxWidth = end - start,
                        scalePad = 0.005 * boxWidth;
                    x.domain([-scalePad + start, end + scalePad]);
                    xAxis.scale(x);
                    xAxisObj.call(xAxis);

                    // move, resize, and recenter boxes
                    function zoomIn(d) {
                        var self = d3.select(this);
                            openLeft = d.location[0][0] < start,
                            openRight = d.location[0][1] > end,
                            startSelf = d3.max([start, d.location[0][0]]),
                            endSelf = d3.min([end, d.location[0][1]]);

                        // move feature group
                        var boxy = +(self.attr("transform").split(",")[1].split(")")[0]);
                        self.attr("transform", "translate(" + x(startSelf) + "," + boxy + ")");

                        // resize rectangle
                        self.select("rect")
                            .attr("width", x(endSelf) - x(startSelf));

                        // leave borders open for features that are not fully in the zoom
                        // NOTE: this is a VERY DIRTY trick due to lacking SVG features
                        if (openLeft & (!openRight))
                            self.select("rect")
                                .attr("stroke-dasharray",
                                      self.select("rect").attr("width") +
                                      ", 0, " +
                                      self.select("rect").attr("height") +
                                      ", 0, " +
                                      self.select("rect").attr("width") +
                                      ", " +
                                      self.select("rect").attr("height")
                                     );
                        if (openRight & (!openLeft))
                            self.select("rect")
                                .attr("stroke-dasharray",
                                      self.select("rect").attr("width") +
                                      ", " +
                                      self.select("rect").attr("height") +
                                      ", " +
                                      self.select("rect").attr("width") +
                                      ", 0, " +
                                      self.select("rect").attr("height")
                                     );
                        if (openRight & openLeft)
                            self.select("rect")
                                .attr("stroke-dasharray",
                                      self.select("rect").attr("width") +
                                      ", " +
                                      self.select("rect").attr("height") +
                                      ", " +
                                      self.select("rect").attr("width") +
                                      ", " +
                                      self.select("rect").attr("height")
                                     );

                        // center text
                        self.select("text")
                            .attr("x", 0.5 * (x(endSelf) - x(startSelf)));

                        self.classed("zoomed", true);

                    }
                    vis.selectAll(".featurebox")
                        .each(zoomIn);

                } else {
                    // Restoring could be done more stylish, but it's ok
                    vis.selectAll(".featurebox").remove();

                    // restore the x scale
                    x.domain([-50, genome.len + 50]);
                    xAxis.scale(x);
                    xAxisObj.call(xAxis);

                    plotAllFeatures();
                }
            }

            function moverFeature(d) {
                // change color
                var rect = d3.select("#" + d.name.replace(/[ ']/g, "-") + "rect");

                rect.style("fill", "darkred");

                // show tooltip
                tip.show(d);

                // show line connecting the exons
                var exons = [];
                if (d.name.indexOf('exon 1') != -1)
                    exons = ["exon-1", "exon-2"];
                else if (d.name.indexOf('exon 2') != -1)
                    exons = ["exon-2", "exon-1"];

                if (exons.length > 0) {
                    var rect2 = d3.select("#" + d.name.replace(/[ ']/g, "-").replace(exons[0], exons[1]) + "rect");
                    // within zoom views, the other exon might be missing
                    if (rect2.empty())
                        return;

                    var d2 = rect2.data()[0];
                    var box2 = d3.select('#' + d.name.replace(/[ ']/g, "-").replace(exons[0], exons[1]) + "-box");
                    // NOTE: we extract the y coordinate from the affine transformation STRING!
                    var boxy = +(d3.select(this).attr("transform").split(",")[1].split(")")[0]);
                    var box2y = +(box2.attr("transform").split(",")[1].split(")")[0]);

                    vis.append('line')
                        .attr("class", "exon-line")
                        .attr("x1", 0.5 * (x(d.location[0][1]) + x(d.location[0][0])))
                        .attr("x2", 0.5 * (x(d2.location[0][1]) + x(d2.location[0][0])))
                        .attr("y1", boxy + 0.5 * heightBlock)
                        .attr("y2", box2y + 0.5 * heightBlock)
                        .style("opacity", 0.7)
                        .style("stroke", "darkred")
                        .style("stroke-width", 2);

                }
            }

            function moutFeature(d) {
                // change color back
                d3.select("#" + d.name.replace(/[ ']/g, "-") + "rect")
                    .style("fill", "steelblue");

                // hide tooltip
                tip.hide(d);

                // hide exon line
                if ((d.name.indexOf('exon 1') != -1) | (d.name.indexOf('exon 2') != -1))
                  vis.selectAll(".exon-line").remove();
            }

            function plotFeatureGroup(groupname, dy) {
                var group = getFeatureGroup(groupname);
                var fea = vis.selectAll("." + groupname)
                    .data(group)
                    .enter()
                    .append("g")
                    .attr("class", "featurebox " + groupname)
                    .attr("id", function(d) { return d.name.replace(/[ ']/g, "-") + "-box"; })
                    .attr("transform", function(d) { return "translate(" + x(d.location[0][0]) +
                          "," + (dy + heightFeature(d)) + ")"; })
                    .on('mouseover', moverFeature)
                    .on('mouseout', moutFeature)
                    .on("click", function() { d3.event.stopPropagation(); })
                    .on('click.zoom', clickFeature);

                var fearect = fea.append("rect")
                    .attr("class", "featurerect")
                    .attr("id", function(d) { return d.name.replace(/[ ']/g, "-") + "rect"; })
                    .attr("x", 0)
                    .attr("y", 0)
                    .attr("width", function(d) { return x(d.location[0][1]) - x(d.location[0][0]); })
                    .attr("height", 20)
                    .style("fill", "steelblue")
                    .style("fill-opacity", 0.5)
                    .style("stroke-width", 1)
                    .style("stroke", "black");

                // show text only of longer things (that's why we have a tooltip)
                // FIXME: use a criterion that is more zoom-friendly
                fea.append("text")
                    .attr("x", function(d) { return 0.5 * (x(d.location[0][1]) - x(d.location[0][0])); })
                    .attr("y", 15)
                    .text(function(d) {
                        if ((d.location[0][1] - d.location[0][0]) > 350)
                            return d.name;
                        else
                            return "";
                    })
                    .style("text-anchor", "middle");
            }

            function getFeatureGroup(groupname) {
                var group = [];
                var gname = "";
                var tmpfea;
                for(i = 0; i < features.length; i++) {
                 gname = features[i].type
                 if (gname == groupname) {
                  group.push(features[i]);
                 } else if (gname + '-single' == groupname) {
                  if (['vpu', 'vpr', 'nef', 'vif'].indexOf(features[i].name) != -1) {
                   group.push(features[i]);
                  }
                 } else if (gname + '-exon1' == groupname) {
                  if (['rev', 'tat'].indexOf(features[i].name) != -1) {
                   tmpfea = {"name": features[i].name + ' exon 1',
                             "type": "gene",
                             "location": [features[i].location[0]]};
                   group.push(tmpfea);
                  }
                 } else if (gname + '-exon2' == groupname) {
                  if (['rev', 'tat'].indexOf(features[i].name) != -1) {
                   tmpfea = {"name": features[i].name + ' exon 2',
                             "type": "gene",
                             "location": [features[i].location[1]]};
                   group.push(tmpfea);
                  }
                 }
                }
                return group;
            }

            function heightFeature(feature) {
                if (feature.type == "fragment")
                    return heightFragment(feature);
                else if ((feature.type == "protein") | (feature.type == "gene"))
                    return heightInframe(feature);
                else
                    return 0;

                function heightFragment(fragment) {
                    var fn = +(fragment.name[1]);
                    var height = vpadBlock;
                    if ((fn % 2) == 0)
                        height += heightBlock + vpadBlock;
                    return height;
                }

                function heightInframe(feature) {
                    var frame;
                    if (['tat exon 2', 'rev exon 2'].indexOf(feature.name) != -1)
                        frame = (+(feature.location[0][1]) - (+genome.framestart)) % 3;
                   else
                     frame = (+(feature.location[0][0]) - (+genome.framestart)) % 3;
                   return frame * (heightBlock + vpadBlock);
                }

            }

        });

    }

    chart.margin = function (_) {
        if (!arguments.length) return margin;
        margin = _;
        width = svgWidth - margin.left - margin.right;
        height = svgHeight - margin.top - margin.bottom;
        return chart;
    };

    chart.svgWidth = function (_) {
        if (!arguments.length) return width;
        svgWidth = _;
        width = svgWidth - margin.left - margin.right;
        return chart;
    };

    chart.svgHeight = function (_) {
        if (!arguments.length) return height;
        svgHeight = _;
        height = svgHeight - margin.top - margin.bottom;
        return chart;
    };

    return chart;

}
<|endoftext|>


<commit_before>'use strict'
var util = require('util')
var _ = require('lodash')
var zepto = require('zepto-browserify')
var Controller = require('./controller')
var Query = require('./Query')

var $ = zepto.$

var KEYCODES = {
  ENTER: 13,
  TAB: 9
}

module.exports = exports = EntriesController

function EntriesController () {
  Controller.apply(this, arguments)
  this.entryViewList = []
  this.active = false
}
util.inherits(EntriesController, Controller)
_.mixin(EntriesController, Controller)

EntriesController.prototype.attach = function (el) {
  var _this = this
  Controller.prototype.attach.call(this, el)
  var view = this.$el
  view.on('keydown', function (evt) {
    _this.onKeydown(evt)
  })
  var input = this.$el.find('input')
  input.on('input', this.onInputChange.bind(this))
  input.focus()
}

EntriesController.prototype.onKeydown = function (evt) {
  var input = this.$el.find('input')
  switch (evt.keyCode) {
    case KEYCODES.TAB:
      if (document.activeElement === input[0]) {
        input.blur()
      } else {
        input.focus()
      }
      evt.preventDefault()
      break
    case KEYCODES.ENTER:
      var val = input.val()
      if (!val) return
      var Model = this.model
      var entry = new Model({
        title: val
      })
      this.addEntry(entry)
      input.val('')
      // TODO: Why doesn't this fire automatticaly? trigger?
      this.onInputChange({srcElement: input[0]})
      break
  }
}

EntriesController.prototype.addEntry = function (entry) {
  var ModelView = this.modelView
  var entryView = new ModelView(entry)
  entryView.on('click:tag', this.addTagToQuery.bind(this))
  var list = this.$el.find('.animus-entry-list')
  list.prepend(entryView.$el)
  this.entryViewList.push(entryView)
}

/**
 * If the tag is not already part of the query, add it.
 *
 * @param {String} tag
 */

EntriesController.prototype.addTagToQuery = function (tag) {
  console.log(tag)
  var input = this.$el.find('input')
  var val = input.val()
  var query = new Query(val)
  if (!query.hasTag(tag)) {
    // Add tag to query
    input.val(val + tag)
  } else {
    // Tags only have [#a-zA-Z], so don't worry about escaping regex
    var replacingTagRe = new RegExp(tag, 'g')
    var newVal = val.replace(replacingTagRe, '')
    input.val(newVal)
  }
  input.focus()
  // TODO: Why doesn't this fire automatticaly? trigger?
  this.onInputChange({srcElement: input[0]})
}

/**
 * Callback for the InputChange Event.
 *
 * @param {Event} evt
 */
EntriesController.prototype.onInputChange = function (evt) {
  var input = evt.srcElement
  var query = new Query(input.value)
  var entryView
  for (var i = 0; i < this.entryViewList.length; ++i) {
    entryView = this.entryViewList[i]
    entryView.applyQuery(query)
  }
  this.entryViewList = _.sortByOrder(this.entryViewList, ['matchScore'], [false])
  var ul = this.$el.find('ul').remove()
  for (i = 0; i < this.entryViewList.length; ++i) {
    entryView = this.entryViewList[i]
    ul.append(entryView.$el)
  }
  this.$el.append(ul)
  $(input)[query.title ? 'addClass' : 'removeClass']('has-content')
}
<commit_msg>fixes #11, new entries are added to the beginning of the entryListView array<commit_after>'use strict'
var util = require('util')
var _ = require('lodash')
var zepto = require('zepto-browserify')
var Controller = require('./controller')
var Query = require('./Query')

var $ = zepto.$

var KEYCODES = {
  ENTER: 13,
  TAB: 9
}

module.exports = exports = EntriesController

function EntriesController () {
  Controller.apply(this, arguments)
  this.entryViewList = []
  this.active = false
}
util.inherits(EntriesController, Controller)
_.mixin(EntriesController, Controller)

EntriesController.prototype.attach = function (el) {
  var _this = this
  Controller.prototype.attach.call(this, el)
  var view = this.$el
  view.on('keydown', function (evt) {
    _this.onKeydown(evt)
  })
  var input = this.$el.find('input')
  input.on('input', this.onInputChange.bind(this))
  input.focus()
}

EntriesController.prototype.onKeydown = function (evt) {
  var input = this.$el.find('input')
  switch (evt.keyCode) {
    case KEYCODES.TAB:
      if (document.activeElement === input[0]) {
        input.blur()
      } else {
        input.focus()
      }
      evt.preventDefault()
      break
    case KEYCODES.ENTER:
      var val = input.val()
      if (!val) return
      var Model = this.model
      var entry = new Model({
        title: val
      })
      this.addEntry(entry)
      input.val('')
      // TODO: Why doesn't this fire automatticaly? trigger?
      this.onInputChange({srcElement: input[0]})
      break
  }
}

EntriesController.prototype.addEntry = function (entry) {
  var ModelView = this.modelView
  var entryView = new ModelView(entry)
  entryView.on('click:tag', this.addTagToQuery.bind(this))
  var list = this.$el.find('.animus-entry-list')
  list.prepend(entryView.$el)
  this.entryViewList.unshift(entryView)
}

/**
 * If the tag is not already part of the query, add it.
 *
 * @param {String} tag
 */

EntriesController.prototype.addTagToQuery = function (tag) {
  console.log(tag)
  var input = this.$el.find('input')
  var val = input.val()
  var query = new Query(val)
  if (!query.hasTag(tag)) {
    // Add tag to query
    input.val(val + tag)
  } else {
    // Tags only have [#a-zA-Z], so don't worry about escaping regex
    var replacingTagRe = new RegExp(tag, 'g')
    var newVal = val.replace(replacingTagRe, '')
    input.val(newVal)
  }
  input.focus()
  // TODO: Why doesn't this fire automatticaly? trigger?
  this.onInputChange({srcElement: input[0]})
}

/**
 * Callback for the InputChange Event.
 *
 * @param {Event} evt
 */
EntriesController.prototype.onInputChange = function (evt) {
  var input = evt.srcElement
  var query = new Query(input.value)
  var entryView
  for (var i = 0; i < this.entryViewList.length; ++i) {
    entryView = this.entryViewList[i]
    entryView.applyQuery(query)
  }
  this.entryViewList = _.sortByOrder(this.entryViewList, ['matchScore'], [false])
  var ul = this.$el.find('ul').remove()
  for (i = 0; i < this.entryViewList.length; ++i) {
    entryView = this.entryViewList[i]
    ul.append(entryView.$el)
  }
  this.$el.append(ul)
  $(input)[query.title ? 'addClass' : 'removeClass']('has-content')
}
<|endoftext|>


<commit_before>"use strict";

angular.module('backAnd.controllers')
    .controller('tableController', ['$scope', 'Global', 'tableService', 'configService', '$http',
        function($scope, Global, tableService, configService, $http) {

            $scope.global = Global;

            $scope.$watch('tableName', function() {
                if ($scope.tableName)
                    $scope.getConfigDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);

            });

            // All of the configurations will be part of the directive and we can change things
            // like default page size in when we call the directive

            $scope.filterOptions = {
                filterText: '',
                useExternalFilter: true
            };

            $scope.showColumnMenu = true;
            $scope.showMenu = true;

            /*Enables display of the filterbox in the column menu.
            If both showColumnMenu and showFilter are false the menu button will not display.*/
            $scope.showFilter = true;

            $scope.activateFilter = function() {
              var searchText = $scope.searchText || null;
              $scope.getData(searchText);
              };

            $scope.totalServerItems = 0;

            $scope.pagingOptions = {
                pageSizes: [20, 50, 100, 500],
                pageSize: 0,
                currentPage: 1
            };
            // if ($scope.options) {
            //     if ($scope.options.pageSizes) {
            //         $scope.pagingOptions.pageSizes = $scope.options.pageSizes;
            //         if ($scope.options.pageSize)
            //             $scope.pagingOptions.pageSize = $scope.options.pageSize;
            //     }
            // };

            var isSort = true;
            $scope.sortOptions = {};
            $scope.$on('ngGridEventSorted', function(event, sortInfo) {
                // don't call getPagedDataAsync here cos this function
                // is called multiple times for the same update.
                $scope.sortOptions = {
                    fieldName: sortInfo.columns[0].displayName,
                    order: sortInfo.directions[0]
                };
            });

            $scope.dataTable = {
                columnDefs: 'columns',
                data: 'dataFill',
                enablePaging: true,
                showFooter: true,
                useExternalSorting: true,
                sortOptions: $scope.sortOptions,
                totalServerItems: 'totalServerItems',
                pagingOptions: $scope.pagingOptions
            };

            // This is the call to get the data based on the table
            // and receives arguments of page size and page number
            // should look into creating a table directive that receives
            // arguments eg table name, and paging information

            $scope.getConfigDataAsync = function(pageSize, page) {
                $scope.isLoad = true;

                // Request to get the field information about the table
                // This config call needs to be separated into a separate function
                // that is only called once
                configService.queryjsonp({
                    // Need to change this to handle multiple tables on the same page
                    table: $scope.tableName
                }, function(data) {
                    $scope.config = data.fields;
                    $scope.columns = [];
                    $scope.pagingOptions.pageSize = data.design.rowsperPage;

                    // We are adding columns and its custom filter to the table based on type
                    // this will also need to be changed to handle multiple tables on the same page
                    angular.forEach($scope.config, function(con) {
                        console.log(con.columnWidth);
                        $scope.columns.push({
                            cellFilter: con.type,
                            displayName: con.displayName,
                            width: con.columnWidth,
                            cellTemplate: '
{{row.entity[col.displayName]}}
'
                        });
                    });
                    $scope.getData()

                });

            };

            $scope.getData = function(searchText) {
                $scope.isLoad = true;

                if(searchText == 'undefined') searchText == null;
                // We are requesting data for the specific page of the table.
                var sortString = '[' + JSON.stringify($scope.sortOptions) + ']';
                tableService.queryjsonp({
                    // This will also need to be adjusted to deal with mutiple tables on the same page
                    table: $scope.tableName,
                    pageSize: $scope.pagingOptions.pageSize,
                    pageNumber: $scope.pagingOptions.currentPage,
                    sort : sortString,
                    search: searchText

                }, function(largeLoad) {

                    // We have received table data and add the data to the scope
                    $scope.dataFill = largeLoad.data;
                    $scope.totalServerItems = largeLoad.totalRows;

                    // apply changes
                    /* if (!$scope.$$phase) {
                        $scope.$apply();
                    }*/
                    $scope.isLoad = false;

                });

            }

            $scope.$watch('pagingOptions', function(newVal, oldVal) {
                if (newVal !== oldVal) {
                    $scope.getData();
                }
            }, true);

            $scope.$watch('filterOptions', function(newVal, oldVal) {
                if (newVal !== oldVal) {
                    $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
                }
            }, true);

            $scope.$watch('sortOptions', function(newVal, oldVal) {
                if (isSort && newVal !== oldVal) {
                    $scope.getData();
                    isSort = false;
                    $scope.setIsSort();
                 }
             }, true);

            $scope.setIsSort = function() {
              setTimeout(function(){isSort = true;}, 1500);
            }

             // this is the intitialization of the table data above
             $scope.$on('loadData', function() {
                $scope.getConfigDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
             });

         }
     ]);

<commit_msg>fix hide columns<commit_after>"use strict";

angular.module('backAnd.controllers')
    .controller('tableController', ['$scope', 'Global', 'tableService', 'configService', '$http',
        function($scope, Global, tableService, configService, $http) {

            $scope.global = Global;

            // Read the configuration of the current view
            $scope.$watch('tableName', function() {
                if ($scope.tableName)
                    $scope.getConfigDataAsync();

            });

            // All of the configurations will be part of the directive and we can change things
            // like default page size in when we call the directive

            $scope.filterOptions = {
                filterText: '',
                useExternalFilter: true
            };

            $scope.showColumnMenu = true;
            $scope.showMenu = true;

            /*Enables display of the filterbox in the column menu.
            If both showColumnMenu and showFilter are false the menu button will not display.*/
            $scope.showFilter = true;

            $scope.activateFilter = function() {
              var searchText = $scope.searchText || null;
              $scope.getData(searchText);
              };

            $scope.totalServerItems = 0;

            $scope.pagingOptions = {
                pageSizes: [20, 50, 100, 500],
                pageSize: 0,
                currentPage: 1
            };
            // if ($scope.options) {
            //     if ($scope.options.pageSizes) {
            //         $scope.pagingOptions.pageSizes = $scope.options.pageSizes;
            //         if ($scope.options.pageSize)
            //             $scope.pagingOptions.pageSize = $scope.options.pageSize;
            //     }
            // };

            var isSort = true;
            $scope.sortOptions = {};
            $scope.$on('ngGridEventSorted', function(event, sortInfo) {
                // don't call getPagedDataAsync here cos this function
                // is called multiple times for the same update.
                $scope.sortOptions = {
                    fieldName: sortInfo.columns[0].displayName,
                    order: sortInfo.directions[0]
                };
            });

            $scope.dataTable = {
                columnDefs: 'columns',
                data: 'dataFill',
                enablePaging: true,
                showFooter: true,
                useExternalSorting: true,
                sortOptions: $scope.sortOptions,
                totalServerItems: 'totalServerItems',
                pagingOptions: $scope.pagingOptions
            };

            // This is the call to get the data based on the table
            // and receives arguments of page size and page number
            // should look into creating a table directive that receives
            // arguments eg table name, and paging information

            $scope.getConfigDataAsync = function() {
                $scope.isLoad = true;

                // Request to get the field information about the table
                // This config call needs to be separated into a separate function
                // that is only called once
                configService.queryjsonp({
                    // Need to change this to handle multiple tables on the same page
                    table: $scope.tableName
                }, function(data) {
                    $scope.config = data.fields;
                    $scope.columns = [];
                    $scope.pagingOptions.pageSize = data.design.rowsperPage;

                    // We are adding columns and its custom filter to the table based on type
                    // this will also need to be changed to handle multiple tables on the same page
                    angular.forEach($scope.config, function (col) {
                        if (col.donotDisplayinGrid && col.type != 'MultiSelect') {
                            $scope.columns.push({
                                cellFilter: col.type,
                                displayName: col.displayName,
                                width: col.columnWidth,
                                cellTemplate: '
{{row.entity["' + col.name + '"]}}
'
                            });
                        }
                    });
                    $scope.getData()

                });

            };

            $scope.getData = function(searchText) {
                $scope.isLoad = true;

                if(searchText == 'undefined') searchText == null;
                // We are requesting data for the specific page of the table.
                var sortString = '[' + JSON.stringify($scope.sortOptions) + ']';
                tableService.queryjsonp({
                    // This will also need to be adjusted to deal with mutiple tables on the same page
                    table: $scope.tableName,
                    pageSize: $scope.pagingOptions.pageSize,
                    pageNumber: $scope.pagingOptions.currentPage,
                    sort : sortString,
                    search: searchText

                }, function(largeLoad) {

                    // We have received table data and add the data to the scope
                    $scope.dataFill = largeLoad.data;
                    $scope.totalServerItems = largeLoad.totalRows;

                    // apply changes
                    /* if (!$scope.$$phase) {
                        $scope.$apply();
                    }*/
                    $scope.isLoad = false;

                });

            }

            $scope.$watch('pagingOptions', function(newVal, oldVal) {
                if (newVal !== oldVal) {
                    $scope.getData();
                }
            }, true);

            $scope.$watch('filterOptions', function(newVal, oldVal) {
                if (newVal !== oldVal) {
                    $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
                }
            }, true);

            $scope.$watch('sortOptions', function(newVal, oldVal) {
                if (isSort && newVal !== oldVal) {
                    $scope.getData();
                    isSort = false;
                    $scope.setIsSort();
                 }
             }, true);

            $scope.setIsSort = function() {
              setTimeout(function(){isSort = true;}, 1500);
            }

             // this is the intitialization of the table data above
             $scope.$on('loadData', function() {
                $scope.getConfigDataAsync();
             });

         }
     ]);

<|endoftext|>


<commit_before>Object.defineProperty(window, 'isChromium', {
  get() { return !!window.chrome; },
  enumerable: true,
  configurable: true,
});

Object.defineProperty(window, 'isSafari', {
  get() { return navigator.userAgent.includes('Safari'); },
  enumerable: true,
  configurable: true,
});

Object.defineProperty(window, 'isFirefox', {
  get() { return navigator.userAgent.includes('Firefox'); },
  enumerable: true,
  configurable: true,
});

function browserCheck() {
  if (!window.isChromium) {
    const willWork = window.isSafari || window.isFirefox;
    const popup = document.getElementById(willWork ? 'browser-partially-supported' : 'browser-unsupported');
    if (willWork) {
      popup.getElementsByTagName('button')[0].addEventListener('click', () => {
        popup.style.transform = 'translateY(100%)';
        setTimeout(() => { popup.style.display = 'none'; }, 400);
      });
    }
    // Show popup
    popup.style.display = 'block';
    setTimeout(() => popup.classList.add('visible'));
  }
}
window.browserCheck = browserCheck;
<commit_msg>Clean up browser check<commit_after>Object.defineProperty(window, 'isChromium', {
  get() { return !!window.chrome; },
  enumerable: true,
  configurable: true,
});

Object.defineProperty(window, 'isSafari', {
  get() { return navigator.userAgent.includes('Safari'); },
  enumerable: true,
  configurable: true,
});

Object.defineProperty(window, 'isFirefox', {
  get() { return navigator.userAgent.includes('Firefox'); },
  enumerable: true,
  configurable: true,
});

function browserCheck() {
  if (!window.isChromium) {
    const willWork = window.isSafari || window.isFirefox;
    // Different popups if the browser is partially supported or entirely unsupported
    const popup = document.getElementById(willWork ? 'browser-partially-supported' : 'browser-unsupported');
    // Only the "partially supported" popup can be dismissed
    if (willWork) {
      popup.getElementsByTagName('button')[0].addEventListener('click', () => {
        popup.style.transform = 'translateY(100%)';
        // Wait for animation to finish before derendering
        setTimeout(() => { popup.style.display = 'none'; }, 400);
      });
    }
    // Show popup (animation will automatically play when element is displayed)
    popup.style.display = 'block';
  }
}
window.browserCheck = browserCheck;
<|endoftext|>


<commit_before>////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.")
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
     if (move === 'rock') {
        return 'rock';
    } else if (move === 'paper') {
        return 'paper';
    } else if (move === 'scissors') {
        return 'scissors';
    } else {
        return getInput();
	}
}

function getComputerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `randomPlay()`.
    if (move === 'rock') {
        return 'rock';
    } else if (move === 'paper') {
        return 'paper';
    } else if (move === 'scissors') {
        return 'scissors';
    } else {
        return randomPlay();
	}
}

function getWinner(playerMove, computerMove) {
    var winner;
	while (playerMove === 'rock') {
	if (computerMove === 'rock') {
		winner = 'tie';
	} else if (computerMove === 'paper') {
		winner = 'computer';
	} else if (computerMove === 'scissors') {
		winner = 'player';
		}
		return winner;
	}
	while (playerMove === 'paper') {
	if (computerMove === 'rock') {
		winner = 'player';
	} else if (computerMove === 'paper') {
		winner = 'tie';
	} else if (computerMove === 'scissors') {
		winner = 'computer';
		}
		return winner;
	}
	while (playerMove === 'scissors') {
	if (computerMove === 'rock') {
		winner = 'computer';
	} else if (computerMove === 'paper') {
		winner = 'player';
	} else if (computerMove === 'scissors') {
		winner = 'tie';
		}
		return winner;
	}

}

function playToFive() {
  console.log('Let\'s play Rock Paper Scissors');
  var playerWins = 0;
  var computerWins = 0;
  while ((playerWins < 5) && (computerWins < 5)) {
    var playerMove = getPlayerMove(getInput());
    var computerMove = getComputerMove(randomPlay());
    var winner = getWinner(playerMove, computerMove);

    if (winner === 'player') {
      console.log('Player chose ' + playerMove + ' while Computer chose ' + computerMove);
      playerWins += 1;
    }

    else if (winner === 'computer') {
    console.log('Player chose ' + playerMove + ' while Computer chose ' + computerMove);
       computerWins += 1;
    } else {

    return console.log('Player chose ' + playerMove + ' while Computer chose ' + computerMove);
    }
    console.log('The score is currently ' + playerWins + ' to ' + computerWins);
  return [playerWins, computerWins];
}
}

playToFive ();

/* Below are 3 additional versions of playToFive, none of which I’ve been able to get to work so far.
/* Also, I assume playToFive is meant to build on getWinner, which is meant to build on getPlayerMove and getComputerMove, but I’m having trouble connecting them all without assigning the return values to variables… */

//VERSION 1

function playToFive() {
  console.log('Let\'s play Rock Paper Scissors');
  var playerWins = 0;
  var computerWins = 0;
  for (playerWins = 0; playerWins < 5; playerWins += 1) {
      for (computerWins = 0; computerWins < 5; computerWins += 1) {
    if (winnerIsPlayer()){
    console.log('Player chose ' + playerMove + ' while Computer chose ' + computerMove);
   console.log('The score is currently ' + playerWins + ' to ' + computerWins);
	   return (playerWins === 1);
    }
    else if (winnerIsComputer()){
    console.log('Player chose ' + playerMove + ' while Computer chose ' + computerMove);
   console.log('The score is currently ' + playerWins + ' to ' + computerWins);
	return (computerWins === 1);
    }
  return [playerWins, computerWins];
  }
  }
}

function winnerIsPlayer() {
	return playerWinsRock() || playerWinsPaper() || playerWinsScissors();
	}

function winnerIsComputer() {
	return computerWinsRock() || computerWinsPaper()|| computerWinsScissors();
	}

function playerWinsRock() {
	return (playerMove === ‘rock’) && (computerMove === ‘scissors’);
	}

function playerWinsPaper() {
	return (playerMove === ‘paper’) && (computerMove === ‘rock’);
	}

function playerWinsScissors() {
	return (playerMove === ‘scissors’) && (computerMove === ‘paper’);
	}

function computerWinsRock() {
	return (computerMove === ‘rock’) && (playerMove === ‘scissors’);
	}

function computerWinsPaper() {
	return (computerMove === ‘paper’) && (playerMove === ‘rock’);
	}

function computerWinsScissors() {
	return (computerMove === ‘scissors’) && (playerMove === ‘paper’);
	}

/* I think the above version of playToFive could operate independently of the getWinner function above, but it makes logical sense to me, whereas I don’t think my attempt at incorporating getWinner function (below) would work. */

/*
/* VERSION 2- Here is a version that works if I assign return values in getWinner and getPlayerMove, getComputerMove variables (ex: return (winner = ‘tie’);  ) */
function playToFive() {
  console.log('Let\'s play Rock Paper Scissors');
  var playerWins = 0;
  var computerWins = 0;
  for (playerWins = 0; playerWins < 5; playerWins += 1) {
      for (computerWins = 0; computerWins < 5; computerWins += 1) {
	if (winner === ‘player’) {
 		return playerWins += 1;
	}
	if (winner === ‘computer’) {
	    return computerWins += 1;
	}
	console.log('Player chose ' + playerMove + ' while Computer chose ' + computerMove);
   console.log('The score is currently ' + playerWins + ' to ' + computerWins);
  return [playerWins, computerWins];
  }
  }
} */

/*
// VERSION 3- here is a version of playToFive that attempts to incorporate getWinner function
function playToFive() {
    console.log("Let's play Rock, Paper, Scissors");
    var playerWins = 0;
    var computerWins = 0;
    for ((playerWins < 5) && (computerWins < 5)) {
    //not sure while is allowed within a function.
    if (winnerIsPlayer()){
	playerWins += 1;
    }
    if (winnerIsComputer()){
	computerWins += 1;
    }
   console.log('Player chose ' + playerMove + ' while Computer chose ' + computerMove);
   console.log('The score is currently ' + playerWins + ' to ' + computerWins + ‘\n’);
	return [playerWins, computerWins];
  }
}

function winnerIsPlayer() {
	return ‘player’;
	// if getWinner = “player” (not sure of syntax)
	}

function winnerIsComputer() {
	return ‘computer’;
	// if getWinner = “computer” (not sure of syntax)
}
   */
*/

<commit_msg>simplified getComputerMove, getPlayerMove and got playToFive to work by removing return from final else statement & putting return outside while loop<commit_after>////////////////////////////////////////////////
/*   Provided Code - Please Don't Edit   */
////////////////////////////////////////////////
'use strict';

function getInput() {
    console.log("Please choose either 'rock', 'paper', or 'scissors'.")
    return prompt();
}
function randomPlay() {
    var randomNumber = Math.random();
    if (randomNumber < 0.33) {
        return "rock";
    } else if (randomNumber < 0.66) {
        return "paper";
    } else {
        return "scissors";
    }
}
////////////////////////////////////////////////
/*           Write Your Code Below            */
////////////////////////////////////////////////

function getPlayerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `getInput()`.
    return move || getInput();
}

function getComputerMove(move) {
    // Write an expression that operates on a variable called `move`
    // If a `move` has a value, your expression should evaluate to that value.
    // However, if `move` is not specified / is null, your expression should equal `randomPlay()`.
   return move || getInput();
}

function getWinner(playerMove, computerMove) {
    var winner;
    while (playerMove === 'rock') {
	if (computerMove === 'rock') {
		winner = 'tie';
	} else if (computerMove === 'paper') {
		winner = 'computer';
	} else if (computerMove === 'scissors') {
		winner = 'player';
		}
		return winner;
	}
	while (playerMove === 'paper') {
	if (computerMove === 'rock') {
		winner = 'player';
	} else if (computerMove === 'paper') {
		winner = 'tie';
	} else if (computerMove === 'scissors') {
		winner = 'computer';
		}
		return winner;
	}
	while (playerMove === 'scissors') {
	if (computerMove === 'rock') {
		winner = 'computer';
	} else if (computerMove === 'paper') {
		winner = 'player';
	} else if (computerMove === 'scissors') {
		winner = 'tie';
		}
		return winner;
	}

}

function playToFive() {
  console.log('Let\'s play Rock Paper Scissors');
  var playerWins = 0;
  var computerWins = 0;
  while ((playerWins < 5) && (computerWins < 5)) {
    var playerMove = getPlayerMove(getInput());
    var computerMove = getComputerMove(randomPlay());
    var winner = getWinner(playerMove, computerMove);

    if (winner === 'player') {
      playerWins++;
      console.log('Player chose ' + playerMove + ' while Computer chose ' + computerMove);
    }

    else if (winner === 'computer') {
    computerWins++;
    console.log('Player chose ' + playerMove + ' while Computer chose ' + computerMove);
    } else {
    console.log('Player chose ' + playerMove + ' while Computer chose ' + computerMove);
    }
    console.log('The score is currently ' + playerWins + ' to ' + computerWins);

}
return [playerWins, computerWins];
}

playToFive ();

<|endoftext|>