<commit_before>/** Lint messages, find missing messages and those that are unused */

const { readFileSync, statSync } = require('fs')
const glob = require('glob')

// the IMPORT expression can be quite slow, so use a fast expression to pre-test if this is even a candidate
const IS_IMPORT = /import.*from '[^ ]+\/messages'/
// This will split up the import statement into the default and named imports. The named imports,
// if present, will be the output of group 2, which can be parsed by the regular expression below.
// You cannot have repeated capturing groups in a regex, http://stackoverflow.com/questions/3537878
// The default import name will be either group 1 or 3 depending on whether it comes before or after
// the named imports.
const IMPORT = /import ([a-zA-Z0-9_$]+)?,? ?(\{ ?(?:[a-zA-Z0-9_$]+(?: as [a-zA-Z0-9_$]+)?,? ?)* ?\})?,? ?([a-zA-Z0-9_$]+)? from '[^ ]+\/messages'/
// global regex, exec multiple times on same string to get all named imports. Has the source on the
// first group and the name (if applicable) on the second.
const NAMED_IMPORTS = /([a-zA-Z0-9_$]+)(?: as ([a-zA-Z0-9_$]+))?/g

// parse a line to determine if it is an import of messages
function parseImportLine (line) {
  if (IS_IMPORT.test(line)) {
    // could be either depending on whether default import was before or after named imports
    const [, default0, named, default1] = IMPORT.exec(line)
    const defaultImport = default0 || default1
    const namedImports = []
    if (named) {
      let next
      while ((next = NAMED_IMPORTS.exec(named)) != null) {
        const [, src, importedAs] = next
        namedImports.push([src, importedAs || src]) // if no alternate name, use default name
      }
    }

    return [defaultImport, namedImports]
  } else {
    return null
  }
}

/** Lint a file against messages. Exported for testing */
function lintFileContents (messages, js) {
  // what was messages imported as
  let importedAtRootAs = false
  let importedMembersAs
  let importedMembersLookup = new Map()

  let rootMatcher, namedMatcher

  // TODO handle importing members, e.g. import { analysis } from messages

  const foundMessages = []

  let lineNumber = 0 // first increment lands at 0

  for (const line of js.split('\n')) {
    lineNumber++
    const parsedImport = parseImportLine(line)
    if (parsedImport) {
      [importedAtRootAs, importedMembersAs] = parsedImport
      // make sure we don't catch things like display_messages by making sure there's a diff char before
      rootMatcher = new RegExp(`[^a-zA-Z0-9_$]${importedAtRootAs}\\.([^ ,\\(\\)\\[}]+)`, 'g')
      namedMatcher = new RegExp(`[^a-zA-Z0-9_$](${importedMembersAs.map(a => a[1]).join('|')})\\.([^ ,\\(\\)\\[}]+)`, 'g')
      importedMembersAs.forEach(([member, importedAs]) => importedMembersLookup.set(importedAs, member))
    } else if (importedAtRootAs || importedMembersAs) {
      let result
      // each subsequent call gets next match
      if (importedAtRootAs) {
        while ((result = rootMatcher.exec(line)) != null) {
          foundMessages.push([result[1], lineNumber])
        }
      }

      // do the same for imported members
      if (importedMembersAs.length > 0) {
        while ((result = namedMatcher.exec(line)) != null) {
          // map back to the names in the messages file
          foundMessages.push([`${importedMembersLookup.get(result[1])}.${result[2]}`, lineNumber])
        }
      }
    }
  }

  // filter to only the missing ones
  return foundMessages.filter(([message, lineNumber]) => {
    let current = messages
    for (const sub of message.split('.')) {
      current = current[sub]
      if (current == null) {
        return true // something in the chain is undefined
      }
    }

    return false
  })
}

module.exports = {
  lint: function (files, messages) {
    const allFiles = [].concat(
      ...files.map((file) => {
        if (statSync(file).isDirectory()) {
          // TODO what if file is already slash-terminated?
          return glob.sync(`${file}/**/*.js`)
        } else {
          return file
        }
      })
    )

    const missing = [].concat(...allFiles
      .map(filename => {
        return lintFileContents(messages, readFileSync(filename, 'utf8'))
          .map(([message, line]) => [message, filename, line])
      }))

    return missing
  },
  lintFileContents,
  parseImportLine
}
<commit_msg>feat(messages): check that paths exist, add warning if they do not.<commit_after>/** Lint messages, find missing messages and those that are unused */

const { readFileSync, statSync, existsSync } = require('fs')
const glob = require('glob')

// the IMPORT expression can be quite slow, so use a fast expression to pre-test if this is even a candidate
const IS_IMPORT = /import.*from '[^ ]+\/messages'/
// This will split up the import statement into the default and named imports. The named imports,
// if present, will be the output of group 2, which can be parsed by the regular expression below.
// You cannot have repeated capturing groups in a regex, http://stackoverflow.com/questions/3537878
// The default import name will be either group 1 or 3 depending on whether it comes before or after
// the named imports.
const IMPORT = /import ([a-zA-Z0-9_$]+)?,? ?(\{ ?(?:[a-zA-Z0-9_$]+(?: as [a-zA-Z0-9_$]+)?,? ?)* ?\})?,? ?([a-zA-Z0-9_$]+)? from '[^ ]+\/messages'/
// global regex, exec multiple times on same string to get all named imports. Has the source on the
// first group and the name (if applicable) on the second.
const NAMED_IMPORTS = /([a-zA-Z0-9_$]+)(?: as ([a-zA-Z0-9_$]+))?/g

// parse a line to determine if it is an import of messages
function parseImportLine (line) {
  if (IS_IMPORT.test(line)) {
    // could be either depending on whether default import was before or after named imports
    const [, default0, named, default1] = IMPORT.exec(line)
    const defaultImport = default0 || default1
    const namedImports = []
    if (named) {
      let next
      while ((next = NAMED_IMPORTS.exec(named)) != null) {
        const [, src, importedAs] = next
        namedImports.push([src, importedAs || src]) // if no alternate name, use default name
      }
    }

    return [defaultImport, namedImports]
  } else {
    return null
  }
}

/** Lint a file against messages. Exported for testing */
function lintFileContents (messages, js) {
  // what was messages imported as
  let importedAtRootAs = false
  let importedMembersAs
  let importedMembersLookup = new Map()

  let rootMatcher, namedMatcher

  // TODO handle importing members, e.g. import { analysis } from messages

  const foundMessages = []

  let lineNumber = 0 // first increment lands at 0

  for (const line of js.split('\n')) {
    lineNumber++
    const parsedImport = parseImportLine(line)
    if (parsedImport) {
      [importedAtRootAs, importedMembersAs] = parsedImport
      // make sure we don't catch things like display_messages by making sure there's a diff char before
      rootMatcher = new RegExp(`[^a-zA-Z0-9_$]${importedAtRootAs}\\.([^ ,\\(\\)\\[}]+)`, 'g')
      namedMatcher = new RegExp(`[^a-zA-Z0-9_$](${importedMembersAs.map(a => a[1]).join('|')})\\.([^ ,\\(\\)\\[}]+)`, 'g')
      importedMembersAs.forEach(([member, importedAs]) => importedMembersLookup.set(importedAs, member))
    } else if (importedAtRootAs || importedMembersAs) {
      let result
      // each subsequent call gets next match
      if (importedAtRootAs) {
        while ((result = rootMatcher.exec(line)) != null) {
          foundMessages.push([result[1], lineNumber])
        }
      }

      // do the same for imported members
      if (importedMembersAs.length > 0) {
        while ((result = namedMatcher.exec(line)) != null) {
          // map back to the names in the messages file
          foundMessages.push([`${importedMembersLookup.get(result[1])}.${result[2]}`, lineNumber])
        }
      }
    }
  }

  // filter to only the missing ones
  return foundMessages.filter(([message, lineNumber]) => {
    let current = messages
    for (const sub of message.split('.')) {
      current = current[sub]
      if (current == null) {
        return true // something in the chain is undefined
      }
    }

    return false
  })
}

module.exports = {
  lint: function (files, messages) {
    const missingFiles = files.filter(file => !existsSync(file))
    if (missingFiles.length > 0) {
      console.log('some files were not found:')
      missingFiles.forEach(f => console.log(` - ${f}`))
      process.exit(1)
    }

    const allFiles = [].concat(
      ...files.map((file) => {
        if (statSync(file).isDirectory()) {
          // TODO what if file is already slash-terminated?
          return glob.sync(`${file}/**/*.js`)
        } else {
          return file
        }
      })
    )

    const missing = [].concat(...allFiles
      .map(filename => {
        return lintFileContents(messages, readFileSync(filename, 'utf8'))
          .map(([message, line]) => [message, filename, line])
      }))

    return missing
  },
  lintFileContents,
  parseImportLine
}
<|endoftext|>


<commit_before>'use babel';

import { CompositeDisposable } from 'atom';
import CreateProjectView from './create-project-view';
import DeviceSelectView from './device-select-view';
import PortSelectView from './port-select-view';

path = require('path');
fs = require('fs-extra');

export default class ControlPanelView {
  createProjectView: null;
  devSelectView: null;
  portSelectView: null;
  panel: null;

  imgLogo: null;
  btnNewProject: null;
  btnOpenProject: null;
  btnBuildProject: null;
  btnCleanProject: null;
  btnProject: null;
  btnCloseProject: null;
  btnDevSelect: null;
  textDevLibVer: null;
  btnUpdateLib: null;
  btnPortSelect: null;
  btnHide: null;

  currentProjectPath: null;
  buildTarget: null;

  constructor(serializedState) {
    // Create root element
    this.element = document.createElement('div');
    this.element.classList.add('nola-sdk');
    this.element.classList.add('nola-sdk-tool-bar');

    this.imgLogo = document.createElement('img');
    this.imgLogo.src = 'atom://nola-sdk/images/A.png';
    this.imgLogo.height = 30;
    this.element.appendChild(this.imgLogo);

    this.btnNewProject = document.createElement('button');
    this.btnNewProject.classList.add('btn');
    this.btnNewProject.classList.add('tool-bar-btn');
    this.btnNewProject.classList.add('icon');
    this.btnNewProject.classList.add('icon-file');
    this.element.appendChild(this.btnNewProject);

    this.btnOpenProject = document.createElement('button');
    this.btnOpenProject.classList.add('btn');
    this.btnOpenProject.classList.add('tool-bar-btn');
    this.btnOpenProject.classList.add('icon');
    this.btnOpenProject.classList.add('icon-file-directory');
    this.element.appendChild(this.btnOpenProject);

    this.btnProject = document.createElement('button');
    this.btnProject.classList.add('btn');
    this.btnProject.classList.add('tool-bar-btn');
    this.btnProject.textContent = 'Please create or open project.';
    this.element.appendChild(this.btnProject);

    this.btnCloseProject = document.createElement('button');
    this.btnCloseProject.classList.add('btn');
    this.btnCloseProject.classList.add('tool-bar-btn');
    this.btnCloseProject.classList.add('icon');
    this.btnCloseProject.classList.add('icon-x');
    this.element.appendChild(this.btnCloseProject);

    this.btnDevSelect = document.createElement('button');
    this.btnDevSelect.classList.add('btn');
    this.btnDevSelect.classList.add('tool-bar-btn');
    this.btnDevSelect.classList.add('icon');
    this.btnDevSelect.classList.add('icon-circuit-board');
    this.btnDevSelect.textContent = ' Select your device.';
    this.btnDevSelect.disabled = true;
    this.element.appendChild(this.btnDevSelect);

    this.textDevLibVer = document.createElement('code');
    this.textDevLibVer.textContent = '';
    this.element.appendChild(this.textDevLibVer);

    this.btnUpdateLib = document.createElement('button');
    this.btnUpdateLib.classList.add('btn');
    this.btnUpdateLib.classList.add('tool-bar-btn');
    this.btnUpdateLib.classList.add('icon');
    this.btnUpdateLib.classList.add('icon-desktop-download');
    this.element.appendChild(this.btnUpdateLib);

    this.btnPortSelect = document.createElement('button');
    this.btnPortSelect.classList.add('btn');
    this.btnPortSelect.classList.add('tool-bar-btn');
    this.btnPortSelect.classList.add('icon');
    this.btnPortSelect.classList.add('icon-plug');
    this.btnPortSelect.textContent = ' None';
    this.element.appendChild(this.btnPortSelect);

    this.btnBuildProject = document.createElement('button');
    this.btnBuildProject.classList.add('btn');
    this.btnBuildProject.classList.add('tool-bar-btn');
    this.btnBuildProject.classList.add('icon');
    this.btnBuildProject.classList.add('icon-triangle-right');
    this.btnBuildProject.disabled = true;
    this.element.appendChild(this.btnBuildProject);

    this.btnCleanProject = document.createElement('button');
    this.btnCleanProject.classList.add('btn');
    this.btnCleanProject.classList.add('tool-bar-btn');
    this.btnCleanProject.classList.add('icon');
    this.btnCleanProject.classList.add('icon-trashcan');
    this.btnCleanProject.disabled = true;
    this.element.appendChild(this.btnCleanProject);

    this.btnHide = document.createElement('button');
    this.btnHide.classList.add('btn');
    this.btnHide.classList.add('tool-bar-btn');
    this.btnHide.classList.add('icon');
    this.btnHide.classList.add('icon-triangle-up');
    this.btnHide.classList.add('pull-right');
    this.element.appendChild(this.btnHide);

    this.panel = atom.workspace.addTopPanel({
      item: this.element,
      visible: false,
    });

    this.createProjectView = new CreateProjectView(serializedState, this);
    this.devSelectView = new DeviceSelectView(serializedState, this);
    this.portSelectView = new PortSelectView(serializedState, this);

    this.btnNewProject.addEventListener('click', this);
    this.btnOpenProject.addEventListener('click', this);
    this.btnProject.addEventListener('click', this);
    this.btnCloseProject.addEventListener('click', this);
    this.btnDevSelect.addEventListener('click', this);
    this.btnUpdateLib.addEventListener('click', this);
    this.btnPortSelect.addEventListener('click', this);
    this.btnBuildProject.addEventListener('click', this);
    this.btnCleanProject.addEventListener('click', this);
    this.btnHide.addEventListener('click', this);

    this.subscriptions = new CompositeDisposable();
    this.subscriptions.add(atom.commands.add('atom-workspace', {
      'nola-sdk:createProject': () => this.createProject(),
      'nola-sdk:closeProject': () => this.closeProject(),
      'nola-sdk:buildProject': () => this.buildProject()
    }));
  }

  handleEvent(event) {
    if (event.target == this.btnNewProject && event.type == 'click') {
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'nola-sdk:createProject');
    } else if (event.target == this.btnOpenProject && event.type == 'click') {
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'nola-sdk:openProject');
    } else if (event.target == this.btnProject && this.currentProjectPath != undefined && event.type == 'click') {
      atom.project.addPath(this.currentProjectPath);
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'tree-view:show');
      atom.workspace.open(this.currentProjectPath + path.sep + 'main.cpp');
    } else if (event.target == this.btnCloseProject && event.type == 'click') {
      this.closeProject();
    } else if (event.target == this.btnDevSelect && event.type == 'click') {
      this.devSelectView.toggle();
    } else if (event.target == this.btnPortSelect && event.type == 'click') {
      this.portSelectView.toggle();
    } else if (event.target == this.btnUpdateLib && event.type == 'click') {
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'nola-sdk:updateSdk');
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'nola-sdk:checkToolchain');
    } else if (event.target == this.btnBuildProject && event.type == 'click') {
      this.buildProject();
    } else if (event.target == this.btnCleanProject && event.type == 'click') {
      this.cleanProject();
    } else if (event.target == this.btnHide && event.type == 'click') {
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'nola-sdk:hideControlPanel');
    }
  }

  refreshLibVer() {
    if (this.devSelectView != undefined && this.devSelectView.curDev != undefined) {
      this.textDevLibVer.textContent = this.devSelectView.curDev.libVersion;
    }
  }

  show() {
    if (this.panel.isVisible() == false) {
      this.panel.show();
    }
  }

  hide() {
    if (this.panel.isVisible()) {
      this.panel.hide();
    }
  }

  destroy() {
    this.element.remove();
  }

  setProject(projectPath) {
    if (projectPath != null) {
      this.currentProjectPath = projectPath;
      this.btnProject.textContent = 'Project: ' + path.basename(projectPath);
      this.devSelectView.loadDevice();
      atom.project.addPath(projectPath);
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'tree-view:show');
      atom.workspace.open(this.currentProjectPath + path.sep + 'main.cpp');
      this.btnDevSelect.disabled = false;
      this.btnCloseProject.disabled = false;
      this.btnBuildProject.disabled = false;
      this.btnCleanProject.disabled = false;
      this.refreshBuild();
    } else {
      if (this.currentProjectPath != undefined) {
        var editors = atom.workspace.getTextEditors();
        var projectEditors = [];
        var detailedMessage = '';
        for (var i in editors) {
          if (editors[i].getPath() != undefined && editors[i].getPath().indexOf(this.currentProjectPath) == 0) {
            projectEditors.push(editors[i]);
            detailedMessage += editors[i].getTitle() + '\n';
          }
        }

        if (projectEditors.length > 0) {
          const buttons = [ 'Cancel', 'No', 'Yes' ];
          var answer = atom.confirm({
            message: 'Do you want to close all files of the project?',
            detailedMessage: detailedMessage,
            buttons: buttons,
          });

          if (buttons[answer] == 'Cancel') {
            return;
          } else if (buttons[answer] == 'Yes') {
            for (var i in projectEditors) {
              const buttonsSave = [ 'No', 'Yes' ];
              if (projectEditors[i].isModified()) {
                var answerSave = atom.confirm({
                  message: '\'' + projectEditors[i] + '\' has changes, do you want to save them?',
                  detailedMessage: 'Your changes will be lost if you close this item without saving.',
                  buttons: buttonsSave,
                });

                if (buttonsSave[answerSave] == 'Yes') {
                  projectEditors[i].save();
                }
              }
              projectEditors[i].destroy();
            }
          }
        }

        atom.project.removePath(this.currentProjectPath);
        this.btnProject.textContent = 'Please create or open project.';
        this.btnDevSelect.textContent = ' Select your device.';
        this.textDevLibVer.textContent = '';
      }
      this.currentProjectPath = null;
      this.btnCloseProject.disabled = true;
      this.btnDevSelect.disabled = true;
      this.btnBuildProject.disabled = true;
      this.btnCleanProject.disabled = true;
    }
  }

  createProject() {
    this.createProjectView.show();
  }

  closeProject() {
    this.setProject(null);
  }

  buildProject() {
    if (this.currentProjectPath == undefined) {
      return;
    }

    const mainPath = this.currentProjectPath + path.sep + 'main.cpp';

    try {
      fs.statSync(mainPath);
    } catch(e) {
      atom.notifications.addWarning('No \'main.cpp\' found!', {
        detail: 'Make sure that the \'main.cpp\' exists in the current project directory.',
      });

      return;
    }

    var projectInfo;

    try {
      projectInfo = JSON.parse(fs.readFileSync(this.currentProjectPath + path.sep + 'Nol.A-project.json').toString());
    } catch (e) {
      atom.notifications.addWarning('No \'Nol.A-project.json\' found!', {
        detail: 'Make sure that the \'Nol.A-project.cpp\' exists in the current project directory.',
      });

      return;
    }

    if (projectInfo.board == undefined) {
      atom.notifications.addWarning('Target device is not specified!', {
        detail: 'Select your device. You can choose it by clicking the device select button on the control panel.',
      });
      return;
    }

    if (atom.config.get('nola-sdk.hwLibDevMode') == true) {
      var p = atom.config.get('nola-sdk.hwLibSourcePath');

      if (path.isAbsolute(p) == false) {
        atom.notifications.addWarning('The hardware library source path is not absolute.', {
          detail: `\'${p}\' is not an absolue path. The build is canceled.`
        });
        return;
      }

      projectInfo.hwLibSrc = p;
    }

    if (atom.config.get('nola-sdk.deviceDriverDevMode') == true) {
      var p = atom.config.get('nola-sdk.deviceDriverSourcePath');

      if (path.isAbsolute(p) == false) {
        atom.notifications.addWarning('The Device Driver source path is not absolute.', {
          detail: `\'${p}\' is not an absolue path. The build is canceled.`
        });
        return;
      }

      projectInfo.devDrvSrc = p;
    }

    this.buildTarget = mainPath;

    projectInfo.port = this.portSelectView.curPort.trim();

    var disp = atom.workspace.onDidOpen((event) => {
      if (this.buildTarget != undefined && this.buildTarget == event.uri) {
        atom.commands.dispatch(atom.views.getView(atom.workspace), 'build:trigger');
        disp.dispose();
      }
    });

    fs.mkdir(this.currentProjectPath + path.sep + 'build', (err) => {
      if (err && err.code !== 'EEXIST') throw err;
      fs.writeFile(
        this.currentProjectPath + path.sep + 'build' + path.sep + 'Nol.A-project.json',
        JSON.stringify(projectInfo, null, ' '),
        (err) => {
          if (err) throw err;
          atom.workspace.open(mainPath);
        }
      );
    });
  }

  cleanProject() {
    if (this.currentProjectPath == undefined) {
      return;
    }

    var hwLibSrcPath;

    if (atom.config.get('nola-sdk.hwLibDevMode') == true) {
      hwLibSrcPath = atom.config.get('nola-sdk.hwLibSourcePath');

      if (path.isAbsolute(hwLibSrcPath) == false) {
        hwLibSrcPath = '';
      }
    } else {
      hwLibSrcPath = '';
    }

    fs.remove(this.currentProjectPath + path.sep + 'build', () => {
      if (hwLibSrcPath == '') {
        atom.notifications.addInfo("Clean done!", {
          detail: 'Project: ' + this.currentProjectPath,
        });
      } else {
        fs.remove(hwLibSrcPath + path.sep + 'build' + path.sep + this.devSelectView.curDev.libType, () => {
          atom.notifications.addInfo("Clean done!", {
            detail: 'Project: ' + this.currentProjectPath + '\n' + 'Hardware library output files: ' + hwLibSrcPath + path.sep + 'build' + path.sep + this.devSelectView.curDev.libType,
          });
        });
      }
    });
  }

  refreshBuild() {
    var buildContext = [];

    if (this.devSelectView.curDev == undefined) {
      buildContext.push({
        'curdev':'undefined',
      });
    } else {
      buildContext.push({
        'curdev': this.devSelectView.curDev.libType,
      });
    }

    buildContext.push({
      'curport': this.portSelectView.curPort,
    });

    atom.config.set('nola-sdk.build', buildContext);
  }
}
<commit_msg>CS-253 Added passing the library version to the build system.<commit_after>'use babel';

import { CompositeDisposable } from 'atom';
import CreateProjectView from './create-project-view';
import DeviceSelectView from './device-select-view';
import PortSelectView from './port-select-view';

path = require('path');
fs = require('fs-extra');

export default class ControlPanelView {
  createProjectView: null;
  devSelectView: null;
  portSelectView: null;
  panel: null;

  imgLogo: null;
  btnNewProject: null;
  btnOpenProject: null;
  btnBuildProject: null;
  btnCleanProject: null;
  btnProject: null;
  btnCloseProject: null;
  btnDevSelect: null;
  textDevLibVer: null;
  btnUpdateLib: null;
  btnPortSelect: null;
  btnHide: null;

  currentProjectPath: null;
  buildTarget: null;

  constructor(serializedState) {
    // Create root element
    this.element = document.createElement('div');
    this.element.classList.add('nola-sdk');
    this.element.classList.add('nola-sdk-tool-bar');

    this.imgLogo = document.createElement('img');
    this.imgLogo.src = 'atom://nola-sdk/images/A.png';
    this.imgLogo.height = 30;
    this.element.appendChild(this.imgLogo);

    this.btnNewProject = document.createElement('button');
    this.btnNewProject.classList.add('btn');
    this.btnNewProject.classList.add('tool-bar-btn');
    this.btnNewProject.classList.add('icon');
    this.btnNewProject.classList.add('icon-file');
    this.element.appendChild(this.btnNewProject);

    this.btnOpenProject = document.createElement('button');
    this.btnOpenProject.classList.add('btn');
    this.btnOpenProject.classList.add('tool-bar-btn');
    this.btnOpenProject.classList.add('icon');
    this.btnOpenProject.classList.add('icon-file-directory');
    this.element.appendChild(this.btnOpenProject);

    this.btnProject = document.createElement('button');
    this.btnProject.classList.add('btn');
    this.btnProject.classList.add('tool-bar-btn');
    this.btnProject.textContent = 'Please create or open project.';
    this.element.appendChild(this.btnProject);

    this.btnCloseProject = document.createElement('button');
    this.btnCloseProject.classList.add('btn');
    this.btnCloseProject.classList.add('tool-bar-btn');
    this.btnCloseProject.classList.add('icon');
    this.btnCloseProject.classList.add('icon-x');
    this.element.appendChild(this.btnCloseProject);

    this.btnDevSelect = document.createElement('button');
    this.btnDevSelect.classList.add('btn');
    this.btnDevSelect.classList.add('tool-bar-btn');
    this.btnDevSelect.classList.add('icon');
    this.btnDevSelect.classList.add('icon-circuit-board');
    this.btnDevSelect.textContent = ' Select your device.';
    this.btnDevSelect.disabled = true;
    this.element.appendChild(this.btnDevSelect);

    this.textDevLibVer = document.createElement('code');
    this.textDevLibVer.textContent = '';
    this.element.appendChild(this.textDevLibVer);

    this.btnUpdateLib = document.createElement('button');
    this.btnUpdateLib.classList.add('btn');
    this.btnUpdateLib.classList.add('tool-bar-btn');
    this.btnUpdateLib.classList.add('icon');
    this.btnUpdateLib.classList.add('icon-desktop-download');
    this.element.appendChild(this.btnUpdateLib);

    this.btnPortSelect = document.createElement('button');
    this.btnPortSelect.classList.add('btn');
    this.btnPortSelect.classList.add('tool-bar-btn');
    this.btnPortSelect.classList.add('icon');
    this.btnPortSelect.classList.add('icon-plug');
    this.btnPortSelect.textContent = ' None';
    this.element.appendChild(this.btnPortSelect);

    this.btnBuildProject = document.createElement('button');
    this.btnBuildProject.classList.add('btn');
    this.btnBuildProject.classList.add('tool-bar-btn');
    this.btnBuildProject.classList.add('icon');
    this.btnBuildProject.classList.add('icon-triangle-right');
    this.btnBuildProject.disabled = true;
    this.element.appendChild(this.btnBuildProject);

    this.btnCleanProject = document.createElement('button');
    this.btnCleanProject.classList.add('btn');
    this.btnCleanProject.classList.add('tool-bar-btn');
    this.btnCleanProject.classList.add('icon');
    this.btnCleanProject.classList.add('icon-trashcan');
    this.btnCleanProject.disabled = true;
    this.element.appendChild(this.btnCleanProject);

    this.btnHide = document.createElement('button');
    this.btnHide.classList.add('btn');
    this.btnHide.classList.add('tool-bar-btn');
    this.btnHide.classList.add('icon');
    this.btnHide.classList.add('icon-triangle-up');
    this.btnHide.classList.add('pull-right');
    this.element.appendChild(this.btnHide);

    this.panel = atom.workspace.addTopPanel({
      item: this.element,
      visible: false,
    });

    this.createProjectView = new CreateProjectView(serializedState, this);
    this.devSelectView = new DeviceSelectView(serializedState, this);
    this.portSelectView = new PortSelectView(serializedState, this);

    this.btnNewProject.addEventListener('click', this);
    this.btnOpenProject.addEventListener('click', this);
    this.btnProject.addEventListener('click', this);
    this.btnCloseProject.addEventListener('click', this);
    this.btnDevSelect.addEventListener('click', this);
    this.btnUpdateLib.addEventListener('click', this);
    this.btnPortSelect.addEventListener('click', this);
    this.btnBuildProject.addEventListener('click', this);
    this.btnCleanProject.addEventListener('click', this);
    this.btnHide.addEventListener('click', this);

    this.subscriptions = new CompositeDisposable();
    this.subscriptions.add(atom.commands.add('atom-workspace', {
      'nola-sdk:createProject': () => this.createProject(),
      'nola-sdk:closeProject': () => this.closeProject(),
      'nola-sdk:buildProject': () => this.buildProject()
    }));
  }

  handleEvent(event) {
    if (event.target == this.btnNewProject && event.type == 'click') {
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'nola-sdk:createProject');
    } else if (event.target == this.btnOpenProject && event.type == 'click') {
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'nola-sdk:openProject');
    } else if (event.target == this.btnProject && this.currentProjectPath != undefined && event.type == 'click') {
      atom.project.addPath(this.currentProjectPath);
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'tree-view:show');
      atom.workspace.open(this.currentProjectPath + path.sep + 'main.cpp');
    } else if (event.target == this.btnCloseProject && event.type == 'click') {
      this.closeProject();
    } else if (event.target == this.btnDevSelect && event.type == 'click') {
      this.devSelectView.toggle();
    } else if (event.target == this.btnPortSelect && event.type == 'click') {
      this.portSelectView.toggle();
    } else if (event.target == this.btnUpdateLib && event.type == 'click') {
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'nola-sdk:updateSdk');
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'nola-sdk:checkToolchain');
    } else if (event.target == this.btnBuildProject && event.type == 'click') {
      this.buildProject();
    } else if (event.target == this.btnCleanProject && event.type == 'click') {
      this.cleanProject();
    } else if (event.target == this.btnHide && event.type == 'click') {
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'nola-sdk:hideControlPanel');
    }
  }

  refreshLibVer() {
    if (this.devSelectView != undefined && this.devSelectView.curDev != undefined) {
      this.textDevLibVer.textContent = this.devSelectView.curDev.libVersion;
    }
  }

  show() {
    if (this.panel.isVisible() == false) {
      this.panel.show();
    }
  }

  hide() {
    if (this.panel.isVisible()) {
      this.panel.hide();
    }
  }

  destroy() {
    this.element.remove();
  }

  setProject(projectPath) {
    if (projectPath != null) {
      this.currentProjectPath = projectPath;
      this.btnProject.textContent = 'Project: ' + path.basename(projectPath);
      this.devSelectView.loadDevice();
      atom.project.addPath(projectPath);
      atom.commands.dispatch(atom.views.getView(atom.workspace), 'tree-view:show');
      atom.workspace.open(this.currentProjectPath + path.sep + 'main.cpp');
      this.btnDevSelect.disabled = false;
      this.btnCloseProject.disabled = false;
      this.btnBuildProject.disabled = false;
      this.btnCleanProject.disabled = false;
      this.refreshBuild();
    } else {
      if (this.currentProjectPath != undefined) {
        var editors = atom.workspace.getTextEditors();
        var projectEditors = [];
        var detailedMessage = '';
        for (var i in editors) {
          if (editors[i].getPath() != undefined && editors[i].getPath().indexOf(this.currentProjectPath) == 0) {
            projectEditors.push(editors[i]);
            detailedMessage += editors[i].getTitle() + '\n';
          }
        }

        if (projectEditors.length > 0) {
          const buttons = [ 'Cancel', 'No', 'Yes' ];
          var answer = atom.confirm({
            message: 'Do you want to close all files of the project?',
            detailedMessage: detailedMessage,
            buttons: buttons,
          });

          if (buttons[answer] == 'Cancel') {
            return;
          } else if (buttons[answer] == 'Yes') {
            for (var i in projectEditors) {
              const buttonsSave = [ 'No', 'Yes' ];
              if (projectEditors[i].isModified()) {
                var answerSave = atom.confirm({
                  message: '\'' + projectEditors[i] + '\' has changes, do you want to save them?',
                  detailedMessage: 'Your changes will be lost if you close this item without saving.',
                  buttons: buttonsSave,
                });

                if (buttonsSave[answerSave] == 'Yes') {
                  projectEditors[i].save();
                }
              }
              projectEditors[i].destroy();
            }
          }
        }

        atom.project.removePath(this.currentProjectPath);
        this.btnProject.textContent = 'Please create or open project.';
        this.btnDevSelect.textContent = ' Select your device.';
        this.textDevLibVer.textContent = '';
      }
      this.currentProjectPath = null;
      this.btnCloseProject.disabled = true;
      this.btnDevSelect.disabled = true;
      this.btnBuildProject.disabled = true;
      this.btnCleanProject.disabled = true;
    }
  }

  createProject() {
    this.createProjectView.show();
  }

  closeProject() {
    this.setProject(null);
  }

  buildProject() {
    if (this.currentProjectPath == undefined) {
      return;
    }

    const mainPath = this.currentProjectPath + path.sep + 'main.cpp';

    try {
      fs.statSync(mainPath);
    } catch(e) {
      atom.notifications.addWarning('No \'main.cpp\' found!', {
        detail: 'Make sure that the \'main.cpp\' exists in the current project directory.',
      });

      return;
    }

    var projectInfo;

    try {
      projectInfo = JSON.parse(fs.readFileSync(this.currentProjectPath + path.sep + 'Nol.A-project.json').toString());
    } catch (e) {
      atom.notifications.addWarning('No \'Nol.A-project.json\' found!', {
        detail: 'Make sure that the \'Nol.A-project.cpp\' exists in the current project directory.',
      });

      return;
    }

    if (projectInfo.board == undefined) {
      atom.notifications.addWarning('Target device is not specified!', {
        detail: 'Select your device. You can choose it by clicking the device select button on the control panel.',
      });
      return;
    }

    if (atom.config.get('nola-sdk.hwLibDevMode') == true) {
      var p = atom.config.get('nola-sdk.hwLibSourcePath');

      if (path.isAbsolute(p) == false) {
        atom.notifications.addWarning('The hardware library source path is not absolute.', {
          detail: `\'${p}\' is not an absolue path. The build is canceled.`
        });
        return;
      }

      projectInfo.hwLibSrc = p;
    }

    if (atom.config.get('nola-sdk.deviceDriverDevMode') == true) {
      var p = atom.config.get('nola-sdk.deviceDriverSourcePath');

      if (path.isAbsolute(p) == false) {
        atom.notifications.addWarning('The Device Driver source path is not absolute.', {
          detail: `\'${p}\' is not an absolue path. The build is canceled.`
        });
        return;
      }

      projectInfo.devDrvSrc = p;
    }

    this.buildTarget = mainPath;

    projectInfo.port = this.portSelectView.curPort.trim();
    projectInfo.ver = this.devSelectView.curDev.libVersion;

    var disp = atom.workspace.onDidOpen((event) => {
      if (this.buildTarget != undefined && this.buildTarget == event.uri) {
        atom.commands.dispatch(atom.views.getView(atom.workspace), 'build:trigger');
        disp.dispose();
      }
    });

    fs.mkdir(this.currentProjectPath + path.sep + 'build', (err) => {
      if (err && err.code !== 'EEXIST') throw err;
      fs.writeFile(
        this.currentProjectPath + path.sep + 'build' + path.sep + 'Nol.A-project.json',
        JSON.stringify(projectInfo, null, ' '),
        (err) => {
          if (err) throw err;
          atom.workspace.open(mainPath);
        }
      );
    });
  }

  cleanProject() {
    if (this.currentProjectPath == undefined) {
      return;
    }

    var hwLibSrcPath;

    if (atom.config.get('nola-sdk.hwLibDevMode') == true) {
      hwLibSrcPath = atom.config.get('nola-sdk.hwLibSourcePath');

      if (path.isAbsolute(hwLibSrcPath) == false) {
        hwLibSrcPath = '';
      }
    } else {
      hwLibSrcPath = '';
    }

    fs.remove(this.currentProjectPath + path.sep + 'build', () => {
      if (hwLibSrcPath == '') {
        atom.notifications.addInfo("Clean done!", {
          detail: 'Project: ' + this.currentProjectPath,
        });
      } else {
        fs.remove(hwLibSrcPath + path.sep + 'build' + path.sep + this.devSelectView.curDev.libType, () => {
          atom.notifications.addInfo("Clean done!", {
            detail: 'Project: ' + this.currentProjectPath + '\n' + 'Hardware library output files: ' + hwLibSrcPath + path.sep + 'build' + path.sep + this.devSelectView.curDev.libType,
          });
        });
      }
    });
  }

  refreshBuild() {
    var buildContext = [];

    if (this.devSelectView.curDev == undefined) {
      buildContext.push({
        'curdev':'undefined',
      });
    } else {
      buildContext.push({
        'curdev': this.devSelectView.curDev.libType,
      });
    }

    buildContext.push({
      'curport': this.portSelectView.curPort,
    });

    atom.config.set('nola-sdk.build', buildContext);
  }
}
<|endoftext|>


<commit_before>var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) {
    $scope.answer_is_show = false;
    $scope.user_answer = "";
    $scope.input_class = "";
    $scope.show_btn_text = "Show";
    $scope.is_options = false;
    $scope.is_game = true;
    $scope.from = 0
    $scope.to = 10;
    $scope.options_class = "";
    $scope.game_class = "active";
    $scope.minus_button_text = "+";
    $scope.user_answer1 = "";

    $scope.get_minus_button_text = function(){
      return $scope.minus_button_text;
    }

    $scope.get_game_class = function(){
      return $scope.game_class;
    }

    $scope.get_options_class = function(){
      return $scope.options_class;
    }

    $scope.get_show_btn_text = function(){
      return $scope.show_btn_text;
    }

    $scope.get_input_class = function(){
      return $scope.input_class;
    }

    $scope.show_answer = function(){
      $scope.answer_is_show = !$scope.answer_is_show;
      if ($scope.show_btn_text == "Show") {
        $scope.show_btn_text = "Hide";
      } else {
        $scope.show_btn_text = "Show";
      }
    }
    $scope.check_answer = function(){
      // console.log($scope.answer);
      // console.log($scope.user_answer);
      if($scope.user_answer1 == $scope.answer){
        $scope.input_class = "";
        $scope.is_correct = "True";
        $scope.answer_is_show = false;
        $scope.genExp();
      } else {
        $scope.is_correct = "False";
        $scope.input_class = "red-border";
      }
      $scope.user_answer = "";
      $scope.minus_button_text = '+';
    }

    $scope.get_exp = function(){
      return $scope.exp;
    }

    $scope.check_enter = function(event) {
      if(event.key == "Enter"){
        if($scope.minus_button_text == '-'){
          $scope.user_answer1 = "-" + $scope.user_answer;
        } else {
          $scope.user_answer1 = $scope.user_answer;
        }
        $scope.check_answer();
      } else if(event.key == '-'){
        event.preventDefault();
        $scope.minus_answer();
      }
    }

    $scope.minus_answer = function(){
      if($scope.minus_button_text == '+'){
        $scope.user_answer1 = '-' + $scope.user_answer;
        $scope.minus_button_text = '-';
      } else {
        $scope.user_answer1 = $scope.user_answer;
        $scope.minus_button_text = '+';
      }
    }

    $scope.genExp = function(){
      symbs = ['+', '-', '*', '/'];

      var first = Math.floor((Math.random() * $scope.to) + $scope.from);
      var second = Math.floor((Math.random() * $scope.to) + $scope.from);
      var symb = symbs[Math.floor(Math.random() * symbs.length)];

      if (symb == '+') {
        $scope.answer = first + second;
      } else if(symb == '-') {
        $scope.answer = first - second;
      } else if(symb == '*') {
        $scope.answer = first * second;
      } else if(symb == '/') {
        while (true) {
          if (second != 0) {
            $scope.answer = first / second;
            break;
          } else {
            first = Math.floor((Math.random() * $scope.to) + $scope.from);
            second = Math.floor((Math.random() * $scope.to) + $scope.from);
          }
        }
      }
      $scope.answer = +$scope.answer.toFixed(2);
      $scope.exp = first + ' ' + symb + ' ' + second;
    }

    $scope.game = function(){
      $scope.is_options = false;
      $scope.is_game = true;
      $scope.options_class = "";
      $scope.game_class = "active";
    }

    $scope.options = function(){
      $scope.is_options = true;
      $scope.is_game = false;
      $scope.options_class = "active";
      $scope.game_class = "";
    }

    $scope.save_changes = function(){
      $scope.genExp(parseInt($scope.from), parseInt($scope.to));
    }
});
<commit_msg>fix bug with minus on mobile phone<commit_after>var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) {
    $scope.answer_is_show = false;
    $scope.user_answer = "";
    $scope.input_class = "";
    $scope.show_btn_text = "Show";
    $scope.is_options = false;
    $scope.is_game = true;
    $scope.from = 0
    $scope.to = 10;
    $scope.options_class = "";
    $scope.game_class = "active";
    $scope.minus_button_text = "+";
    $scope.user_answer1 = "";

    $scope.get_minus_button_text = function(){
      return $scope.minus_button_text;
    }

    $scope.get_game_class = function(){
      return $scope.game_class;
    }

    $scope.get_options_class = function(){
      return $scope.options_class;
    }

    $scope.get_show_btn_text = function(){
      return $scope.show_btn_text;
    }

    $scope.get_input_class = function(){
      return $scope.input_class;
    }

    $scope.show_answer = function(){
      $scope.answer_is_show = !$scope.answer_is_show;
      if ($scope.show_btn_text == "Show") {
        $scope.show_btn_text = "Hide";
      } else {
        $scope.show_btn_text = "Show";
      }
    }
    $scope.check_answer = function(){
      console.log($scope.answer);
      console.log($scope.user_answer1);
      if($scope.user_answer1 == "" + $scope.answer){
        $scope.input_class = "";
        $scope.answer_is_show = false;
        $scope.genExp();
      } else {
        $scope.input_class = "red-border";
      }

      $scope.user_answer = "";
      $scope.minus_button_text = '+';
    }

    $scope.get_exp = function(){
      return $scope.exp;
    }

    $scope.check_enter = function(event) {
      if(event.key == "Enter"){
        if($scope.minus_button_text == '-'){
          $scope.user_answer1 = "-" + $scope.user_answer;
        } else {
          $scope.user_answer1 = $scope.user_answer;
        }
        $scope.check_answer();
      } else if(event.key == '-'){
        event.preventDefault();
        $scope.minus_answer();
      }
    }

    $scope.minus_answer = function(){
      if($scope.minus_button_text == '+'){
        $scope.user_answer1 = '-' + $scope.user_answer;
        $scope.minus_button_text = '-';
      } else {
        $scope.user_answer1 = $scope.user_answer;
        $scope.minus_button_text = '+';
      }
    }

    $scope.genExp = function(){
      symbs = ['+', '-', '*', '/'];

      var first = Math.floor((Math.random() * $scope.to) + $scope.from);
      var second = Math.floor((Math.random() * $scope.to) + $scope.from);
      var symb = symbs[Math.floor(Math.random() * symbs.length)];

      if (symb == '+') {
        $scope.answer = first + second;
      } else if(symb == '-') {
        $scope.answer = first - second;
      } else if(symb == '*') {
        $scope.answer = first * second;
      } else if(symb == '/') {
        while (true) {
          if (second != 0) {
            $scope.answer = first / second;
            break;
          } else {
            first = Math.floor((Math.random() * $scope.to) + $scope.from);
            second = Math.floor((Math.random() * $scope.to) + $scope.from);
          }
        }
      }
      $scope.answer = +$scope.answer.toFixed(2);
      $scope.exp = first + ' ' + symb + ' ' + second;
    }

    $scope.game = function(){
      $scope.is_options = false;
      $scope.is_game = true;
      $scope.options_class = "";
      $scope.game_class = "active";
    }

    $scope.options = function(){
      $scope.is_options = true;
      $scope.is_game = false;
      $scope.options_class = "active";
      $scope.game_class = "";
    }

    $scope.save_changes = function(){
      $scope.genExp(parseInt($scope.from), parseInt($scope.to));
    }
});
<|endoftext|>


<commit_before>(function() {
  'use strict';
  angular.module('MagicSearch', ['ui.bootstrap'])
  /**
   * @ngdoc directive
   * @name MagicSearch:magicOverrides
   * @description
   * A directive to modify / extend Magic Search functionality for use in
   * Horizon.
   * 1. The base magic search widget makes Foundation (a responsive front-end
   * framework) specific calls in showMenu and hideMenu.  In Horizon we use
   * Bootstrap, therefore we need to override those methods.
   *
   * 2.  Added 'facetsChanged' listener so we can notify base magic search
   * widget that new facets are available so they will be picked up.  (Use
   * if your table has dynamic facets)
   *
   * 3.  To support the distinguishment between server & client side facets
   * overrode methods removeFacet & initfacets to emit 'checkFacets' event
   * so implementors can add propterty isServer to facets.  (what keys the
   * facet icon and color difference)
   *
   * 4.  Overrode initfacets to fix refresh / bookmark issue where facets
   * menu wasn't removing facets that were already on url.
   *
   * @restrict A
   * @scope
   *
   * @example
   * ```
   * <div class="magic-search" magic-overrides>
   * ```
   */
  .directive('magicOverrides', function() {
    return {
      restrict: 'A',
      controller: ['$scope', '$timeout',
        function($scope, $timeout) {
          // showMenu and hideMenu depend on foundation's dropdown. They need
          // to be modified to work with another dropdown implementation.
          // For bootstrap, they are not needed at all.
          $scope.showMenu = function() {
            $timeout(function() {
              $scope.isMenuOpen = true;
            });
          };
          $scope.hideMenu = function() {
            $timeout(function() {
              $scope.isMenuOpen = false;
            });
          };
          $scope.isMenuOpen = false;

          // Add ability to update facet
          // Broadcast event when fact options are returned via ajax.
          // Should magic_search.js absorb this?
          $scope.$on('facetsChanged', function() {
            $timeout(function() {
              $scope.currentSearch = [];
              $scope.initSearch();
            });
          });

          // Override magic_search.js initFacets to fix browswer refresh issue
          // and to emit('checkFacets') to flag facets as isServer
          $scope.initFacets = function() {
            // set facets selected and remove them from facetsObj
            var initialFacets = window.location.search;
            if (initialFacets.indexOf('?') === 0) {
              initialFacets = initialFacets.slice(1);
            }
            initialFacets = initialFacets.split('&');
            if (initialFacets.length > 1 || initialFacets[0].length > 0) {
              $timeout(function() {
                $scope.strings.prompt = '';
              });
            }
            angular.forEach(initialFacets, function(facet, idx) {
              var facetParts = facet.split('=');
              angular.forEach($scope.facetsObj, function(value, idx) {
                if (value.name == facetParts[0]) {
                  if (value.options === undefined) {
                    $scope.currentSearch.push({
                      'name': facet,
                      'label': [value.label, facetParts[1]]
                    });

                    // for refresh case, need to remove facets that were bookmarked/
                    // current when broswer refresh was clicked
                    $scope.deleteFacetEntirely(facetParts);

                  } else {
                    angular.forEach(value.options, function(option, idx) {
                      if (option.key == facetParts[1]) {
                        $scope.currentSearch.push({
                          'name': facet,
                          'label': [value.label, option.label]
                        });
                        if (value.singleton === true) {
                          $scope.deleteFacetEntirely(facetParts);
                        } else {
                          $scope.deleteFacetSelection(facetParts);
                        }
                      }
                    });
                  }
                }
              });
            });
            if ($scope.textSearch !== undefined) {
              $scope.currentSearch.push({
                'name': 'text=' + $scope.textSearch,
                'label': [$scope.strings.text, $scope.textSearch]
              });
            }
            $scope.filteredObj = $scope.facetsObj;

            // broadcast to check facets for serverside
            $scope.$emit('checkFacets', $scope.currentSearch);
          };

          // Override magic_search.js removeFacet to emit('checkFacets')
          // to flag facets as isServer after removing facet and
          // either update filter or search
          $scope.removeFacet = function($index, $event) {
            var removed = $scope.currentSearch[$index].name;
            $scope.currentSearch.splice($index, 1);
            if ($scope.facetSelected === undefined) {
              $scope.emitQuery(removed);
            } else {
              $scope.resetState();
              $('.search-input').val('');
            }
            if ($scope.currentSearch.length === 0) {
              $scope.strings.prompt = $scope.promptString;
            }
            // re-init to restore facets cleanly
            $scope.facetsObj = $scope.copyFacets($scope.facetsSave);
            $scope.currentSearch = [];
            $scope.initFacets();

            // broadcast to check facets for serverside
            $scope.$emit('checkFacets', $scope.currentSearch);
          };

        }
      ]
    }; // end of return
  }); // end of directive
})();<commit_msg>Add description & example for isServer property in Magic Search<commit_after>(function() {
  'use strict';
  angular.module('MagicSearch', ['ui.bootstrap'])
  /**
   * @ngdoc directive
   * @name MagicSearch:magicOverrides
   * @description
   * A directive to modify / extend Magic Search functionality for use in
   * Horizon.
   * 1. The base Magic Search widget makes Foundation (a responsive front-end
   * framework) specific calls in showMenu and hideMenu.  In Horizon we use
   * Bootstrap, therefore we need to override those methods.
   *
   * 2.  Added 'facetsChanged' listener so we can notify base Magic Search
   * widget that new facets are available so they will be picked up.  (Use
   * if your table has dynamic facets)
   *
   * 3.  Due to the current inconsistencies in the APIs, where some support
   * filtering and others do not, we wanted a way to distinguish client-side
   * filtering (searching the visible subset) vs server-side filtering
   * (another server filter query).
   *
   * To support this distinguishment we overrode methods removeFacet &
   * initfacets to emit 'checkFacets' event so implementers can add property
   * 'isServer' to facets (what triggers the facet icon and color difference).
   *
   * Each table that incorporates Magic Search is responsible for adding
   * property 'isServer' to their facets as they have the intimate knowledge
   * of the API supplying the table data.  The setting of this property needs
   * to be done in the Magic Search supporting JavaScript for each table.
   *
   * Example:
   * // Set property 'isServer' on facets that you want to render as server
   * // facet (server icon, lighter grey color).  Note: If the property
   * // 'isServer' is not set, then facet renders with client icon and darker
   * // grey color.
   * scope.$on('checkFacets', function(event, currentSearch) {
   *   angular.forEach(currentSearch, function(facet) {
   *     if (apiVersion < 3) {
   *       facet.isServer = true;
   *     }
   *   });
   * });
   *
   * 4.  Overrode initfacets to fix refresh / bookmark issue where facets
   * menu wasn't removing facets that were already on url.
   *
   * @restrict A
   * @scope
   *
   * @example
   * ```
   * <div class="magic-search" magic-overrides>
   * ```
   */
  .directive('magicOverrides', function() {
    return {
      restrict: 'A',
      controller: ['$scope', '$timeout',
        function($scope, $timeout) {
          // showMenu and hideMenu depend on foundation's dropdown. They need
          // to be modified to work with another dropdown implementation.
          // For bootstrap, they are not needed at all.
          $scope.showMenu = function() {
            $timeout(function() {
              $scope.isMenuOpen = true;
            });
          };
          $scope.hideMenu = function() {
            $timeout(function() {
              $scope.isMenuOpen = false;
            });
          };
          $scope.isMenuOpen = false;

          // Add ability to update facet
          // Broadcast event when fact options are returned via ajax.
          // Should magic_search.js absorb this?
          $scope.$on('facetsChanged', function() {
            $timeout(function() {
              $scope.currentSearch = [];
              $scope.initSearch();
            });
          });

          // Override magic_search.js initFacets to fix browswer refresh issue
          // and to emit('checkFacets') to flag facets as isServer
          $scope.initFacets = function() {
            // set facets selected and remove them from facetsObj
            var initialFacets = window.location.search;
            if (initialFacets.indexOf('?') === 0) {
              initialFacets = initialFacets.slice(1);
            }
            initialFacets = initialFacets.split('&');
            if (initialFacets.length > 1 || initialFacets[0].length > 0) {
              $timeout(function() {
                $scope.strings.prompt = '';
              });
            }
            angular.forEach(initialFacets, function(facet, idx) {
              var facetParts = facet.split('=');
              angular.forEach($scope.facetsObj, function(value, idx) {
                if (value.name == facetParts[0]) {
                  if (value.options === undefined) {
                    $scope.currentSearch.push({
                      'name': facet,
                      'label': [value.label, facetParts[1]]
                    });

                    // for refresh case, need to remove facets that were bookmarked/
                    // current when broswer refresh was clicked
                    $scope.deleteFacetEntirely(facetParts);

                  } else {
                    angular.forEach(value.options, function(option, idx) {
                      if (option.key == facetParts[1]) {
                        $scope.currentSearch.push({
                          'name': facet,
                          'label': [value.label, option.label]
                        });
                        if (value.singleton === true) {
                          $scope.deleteFacetEntirely(facetParts);
                        } else {
                          $scope.deleteFacetSelection(facetParts);
                        }
                      }
                    });
                  }
                }
              });
            });
            if ($scope.textSearch !== undefined) {
              $scope.currentSearch.push({
                'name': 'text=' + $scope.textSearch,
                'label': [$scope.strings.text, $scope.textSearch]
              });
            }
            $scope.filteredObj = $scope.facetsObj;

            // broadcast to check facets for serverside
            $scope.$emit('checkFacets', $scope.currentSearch);
          };

          // Override magic_search.js removeFacet to emit('checkFacets')
          // to flag facets as isServer after removing facet and
          // either update filter or search
          $scope.removeFacet = function($index, $event) {
            var removed = $scope.currentSearch[$index].name;
            $scope.currentSearch.splice($index, 1);
            if ($scope.facetSelected === undefined) {
              $scope.emitQuery(removed);
            } else {
              $scope.resetState();
              $('.search-input').val('');
            }
            if ($scope.currentSearch.length === 0) {
              $scope.strings.prompt = $scope.promptString;
            }
            // re-init to restore facets cleanly
            $scope.facetsObj = $scope.copyFacets($scope.facetsSave);
            $scope.currentSearch = [];
            $scope.initFacets();

            // broadcast to check facets for serverside
            $scope.$emit('checkFacets', $scope.currentSearch);
          };

        }
      ]
    }; // end of return
  }); // end of directive
})();<|endoftext|>


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

'use strict';

// conversation variables
var conversation_result, is_wating = false, methods = {
	chatbot: function () {
		var $chatInput = $('.chat-window--message-input'),
		$jsonPanel = $('#json-panel .base--textarea'),
		$loading = $('.loader'),
		$mic = $('.ui-button-microphone');

		$chatInput.keyup(function(event){
			if(event.keyCode === 13) {
				var inputText = $(this).val();
				converse(inputText);
			}
		});

		/**
		 * Convert response context to car command
		 */
		var contextToCommand = function(conversation_result){
			var direction = '';
			var entities = conversation_result.entities;
			var intents = conversation_result.intents;
			for(var index in intents){
				var intent = intents[index];
				if(intent.confidence > 0.7 && intent.intent === 'move'){
					for(var key in entities){
						var entity = entities[key];
						if(entity.entity === 'direction') {
							switch(entity.value) {
							case 'right':
								direction = 'd';
								break;
							case 'forward':
								direction = 'w';
								break;
							case 'backward':
								direction = 's';
								break;
							case 'left':
								direction = 'a';
								break;
							}
							break;
						}
					}
					break;
				}
			}
			return direction;
		};

		/**
		 * Synthesize
		 */
		var synthesize = function(val) {
			var audio = new Audio();
			audio.src = 'Synthesize?text=' + val;
			audio.play();
		};

		/**
		 * Perform conversation
		 */
		var converse = function(userText) {
			if (is_wating) {
				return;
			}
			is_wating = true;
		    $loading.show();
		    // $chatInput.hide();

		    // check if the user typed text or not
		    if (typeof(userText) !== undefined && $.trim(userText) !== '')
		      submitMessage(userText);

		    // build the conversation parameters
		    var params = { message : userText };

		    if (conversation_result) {
		    	params.context = JSON.stringify(conversation_result.context);
		    }

		    $.ajax({
		    	url:'Talk',
		    	method: 'POST',
		    	data: params
		    }).done(function onSucess(response) {
		    	is_wating = false;
		    	conversation_result = JSON.parse(response);

		        $chatInput.val(''); // clear the text input

		        $jsonPanel.html(JSON.stringify(conversation_result, null, 2));

		        var texts = conversation_result.output ? conversation_result.output.text : [];
		        if(texts.length == 0){
		        	talk('WATSON', 'Sorry, I did not understand what you just said.');
		        	return;
		        }
		        var response = texts.join('
'); // <br/> is

		        $chatInput.show();
		        $chatInput[0].focus();

		        synthesize(response);

		        talk('WATSON', response); // show

		        var command = contextToCommand(conversation_result);
		        onSendingCommand(command);
		      })
		      .fail(function onError(error) {
		        talk('WATSON', error.responseJSON ? error.responseJSON.error : error.statusText);
		        is_wating = false;
		      })
		      .always(function always(){
		        $loading.hide();
		        scrollChatToBottom();
		        $chatInput.focus();
		      });
		};

		/**
		 * Scroll with animation
		 */
		var scrollChatToBottom = function() {
			var element = $('.chat-box--pane');
			element.animate({
				scrollTop: element[0].scrollHeight
			}, 420);
		};

		/**
		 * Scroll to input
		 */
		var scrollToInput = function() {
			var element = $('.chat-window--message-input');
			$('body, html').animate({
				scrollTop: (element.offset().top - window.innerHeight + element[0].offsetHeight) + 20 + 'px'
			});
		};

		/**
		 * Generate HTML to chat
		 */
		var talk = function(origin, text, format) {
			if(!format){
				format = 'html';
			}
			var $chatBox = $('.chat-box--item_' + origin).first().clone();
			var $loading = $('.loader');
			if(format == 'text')
				$chatBox.find('p').html($('
').html(text).text());
			else
				$chatBox.find('p').html($('
').html(text).html());

			$chatBox.insertBefore($loading);
			setTimeout(function() {
				$chatBox.removeClass('chat-box--item_HIDDEN');
			}, 100);
		};

		/**
		 * Send message to the service
		 */
		var submitMessage = function(text) {
			talk('YOU', text);
			scrollChatToBottom();
			clearInput();
		};

		/**
		 * Clear contents in the input
		 */
		var clearInput = function() {
			$('.chat-window--message-input').val('');
		};

		/**
		 * Tab switching
		 */
		$('.tab-panels--tab').click(function(e){
			e.preventDefault();
			var self = $(this);
			var inputGroup = self.closest('.tab-panels');
			var idName = null;
			inputGroup.find('.active').removeClass('active');
			self.addClass('active');
			idName = self.attr('href');
			$(idName).addClass('active');
		});

		/**
		 * Speech recognition UI
		 */
		var changeUIState = function(isSpeaking) {
			if (isSpeaking) {
				$loading.show();
				$mic.addClass('active');
				$mic.val('Speaking...');
			} else {
				$loading.hide();
				$mic.removeClass('active');
				$mic.val('Speak');
			}
		};

		/**
		 * Inovking Speech recognition
		 */
		var recognize = function(token) {
			return WatsonSpeech.SpeechToText.recognizeMicrophone({
				token : token,
				objectMode : true
			});
		};

		/**
		 * Obtain token of Speech services
		 */
		var initToken = function(val) {
			return $.ajax({
				url : 'Token',
				data : {
					category : val
				}
			});
		};

		var isSpeaking = false, stream = null, ttsToken = '', sttToken = '';

		$mic.on('click', function(evt){
			if(isSpeaking && stream){
				stream.stop();
				isSpeaking = false;
				changeUIState(isSpeaking);
			}
			else {
				if(isSpeaking){
					return;
				}

				stream = recognize(sttToken);
				isSpeaking = true;
				changeUIState(isSpeaking);

				stream.on('data', function(data) {
					console.log('data:');
					console.log(data);
					var transcript = data.alternatives[0].transcript;
					$('.ui-transcription').html('
'+transcript+'
');

					if(data.hasOwnProperty('final') && data['final']){
						isSpeaking = false;
						changeUIState(isSpeaking);
						stream.stop();
						converse(transcript);
						$('.ui-transcription').text('');
					}
				});
				stream.on('error', function(err) {
					console.log(err);
					isSpeaking = false;
					changeUIState(isSpeaking);
				});
				stream.on('close', function(err) {
					console.log(err);
					isSpeaking = false;
					changeUIState(isSpeaking);
				});
				stream.on('connection-close', function(err) {
					console.log(err);
					isSpeaking = false;
					changeUIState(isSpeaking);
				});
			}
		});

		initToken('stt').then(function(t) {
			sttToken = t;
			converse('Hi Watson');
			var userAgent = window.navigator.userAgent.toLowerCase();
			if(userAgent.indexOf('chrome') != -1 || userAgent.indexOf('firefox') != -1){
				$mic.show();
			}
		});
		scrollToInput();

		// car control
		var socket = io.connect(carServiceHost);

		socket.on("message", function (data) {
			console.log("socket data: " + data);
		});

		var onSendingCommand = function(command){
			if(command === '') {
				return;
			}
			console.log(command);
			socket.emit("String", command);
		};
		var keyToCommand = function(key){
			var direction = '';
			switch(key){

			case 'ArrowUp':
				direction = 'w';
				break;

			case 'ArrowLeft':
				direction = 'a';
				break;

			case 'ArrowDown':
				direction = 's';
				break;

			case 'ArrowRight':
				direction = 'd';
				break;
			}
			return direction;
		};

		var keys = $('.car-controller a');
		keys.on('click', function(evt){
			var command = $(this).attr('ref');
			// call Socket-IO
			onSendingCommand(command);
		});

		$(document).on('keyup', function(evt){
			var command = keyToCommand(evt.key);
			onSendingCommand(command);
			keys.removeClass('active');
		});
		$(document).on('keydown', function(evt){
			var command = keyToCommand(evt.key);
			if(command === ''){
				return;
			}
			keys.parent().find('[ref='+command+']').addClass('active');
		});
	}
};

$(document).ready(methods.chatbot);<commit_msg>Update talk-to-watson.js<commit_after>/**
 * Copyright 2016 IBM Corp. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

// conversation variables
var conversation_result, is_wating = false, methods = {
	chatbot: function () {
		var $chatInput = $('.chat-window--message-input'),
		$jsonPanel = $('#json-panel .base--textarea'),
		$loading = $('.loader');
		//$mic = $('.ui-button-microphone');

		$chatInput.keyup(function(event){
			if(event.keyCode === 13) {
				var inputText = $(this).val();
				converse(inputText);
			}
		});

		/**
		 * Convert response context to car command
		 */
		/**var contextToCommand = function(conversation_result){
			var direction = '';
			var entities = conversation_result.entities;
			var intents = conversation_result.intents;
			for(var index in intents){
				var intent = intents[index];
				if(intent.confidence > 0.7 && intent.intent === 'move'){
					for(var key in entities){
						var entity = entities[key];
						if(entity.entity === 'direction') {
							switch(entity.value) {
							case 'right':
								direction = 'd';
								break;
							case 'forward':
								direction = 'w';
								break;
							case 'backward':
								direction = 's';
								break;
							case 'left':
								direction = 'a';
								break;
							}
							break;
						}
					}
					break;
				}
			}
			return direction;
		};
*/
		/**
		 * Synthesize
		 */
		/**		var synthesize = function(val) {
			var audio = new Audio();
			audio.src = 'Synthesize?text=' + val;
			audio.play();
		};
*/
		/**
		 * Perform conversation
		 */
		var converse = function(userText) {
			if (is_wating) {
				return;
			}
			is_wating = true;
		    $loading.show();
		    // $chatInput.hide();

		    // check if the user typed text or not
		    if (typeof(userText) !== undefined && $.trim(userText) !== '')
		      submitMessage(userText);

		    // build the conversation parameters
		    var params = { message : userText };

		    if (conversation_result) {
		    	params.context = JSON.stringify(conversation_result.context);
		    }

		    $.ajax({
		    	url:'Talk',
		    	method: 'POST',
		    	data: params
		    }).done(function onSucess(response) {
		    	is_wating = false;
		    	conversation_result = JSON.parse(response);

		        $chatInput.val(''); // clear the text input

		        $jsonPanel.html(JSON.stringify(conversation_result, null, 2));

		        var texts = conversation_result.output ? conversation_result.output.text : [];
		        if(texts.length == 0){
		        	talk('WATSON', 'Sorry, I did not understand what you just said.');
		        	return;
		        }
		        var response = texts.join('
'); // <br/> is

		        $chatInput.show();
		        $chatInput[0].focus();

		        //synthesize(response);

		        talk('WATSON', response); // show

		        //var command = contextToCommand(conversation_result);
		        //onSendingCommand(command);
		      })
		      .fail(function onError(error) {
		        talk('WATSON', error.responseJSON ? error.responseJSON.error : error.statusText);
		        is_wating = false;
		      })
		      .always(function always(){
		        $loading.hide();
		        scrollChatToBottom();
		        $chatInput.focus();
		      });
		};

		/**
		 * Scroll with animation
		 */
		var scrollChatToBottom = function() {
			var element = $('.chat-box--pane');
			element.animate({
				scrollTop: element[0].scrollHeight
			}, 420);
		};

		/**
		 * Scroll to input
		 */
		var scrollToInput = function() {
			var element = $('.chat-window--message-input');
			$('body, html').animate({
				scrollTop: (element.offset().top - window.innerHeight + element[0].offsetHeight) + 20 + 'px'
			});
		};

		/**
		 * Generate HTML to chat
		 */
		var talk = function(origin, text, format) {
			if(!format){
				format = 'html';
			}
			var $chatBox = $('.chat-box--item_' + origin).first().clone();
			var $loading = $('.loader');
			if(format == 'text')
				$chatBox.find('p').html($('
').html(text).text());
			else
				$chatBox.find('p').html($('
').html(text).html());

			$chatBox.insertBefore($loading);
			setTimeout(function() {
				$chatBox.removeClass('chat-box--item_HIDDEN');
			}, 100);
		};

		/**
		 * Send message to the service
		 */
		var submitMessage = function(text) {
			talk('YOU', text);
			scrollChatToBottom();
			clearInput();
		};

		/**
		 * Clear contents in the input
		 */
		var clearInput = function() {
			$('.chat-window--message-input').val('');
		};

		/**
		 * Tab switching
		 */
		$('.tab-panels--tab').click(function(e){
			e.preventDefault();
			var self = $(this);
			var inputGroup = self.closest('.tab-panels');
			var idName = null;
			inputGroup.find('.active').removeClass('active');
			self.addClass('active');
			idName = self.attr('href');
			$(idName).addClass('active');
		});

		/**
		 * Speech recognition UI
		 */
		/**		var changeUIState = function(isSpeaking) {
			if (isSpeaking) {
				$loading.show();
				$mic.addClass('active');
				$mic.val('Speaking...');
			} else {
				$loading.hide();
				$mic.removeClass('active');
				$mic.val('Speak');
			}
		};*/

		/**
		 * Inovking Speech recognition
		 */
		/**var recognize = function(token) {
			return WatsonSpeech.SpeechToText.recognizeMicrophone({
				token : token,
				objectMode : true
			});
		};
*/
		/**
		 * Obtain token of Speech services
		 */
		/**var initToken = function(val) {
			return $.ajax({
				url : 'Token',
				data : {
					category : val
				}
			});
		};
*/
		var isSpeaking = false, stream = null, ttsToken = '', sttToken = '';

		/**$mic.on('click', function(evt){
			if(isSpeaking && stream){
				stream.stop();
				isSpeaking = false;
				changeUIState(isSpeaking);
			}
			else {
				if(isSpeaking){
					return;
				}

				stream = recognize(sttToken);
				isSpeaking = true;
				changeUIState(isSpeaking);

				stream.on('data', function(data) {
					console.log('data:');
					console.log(data);
					var transcript = data.alternatives[0].transcript;
					$('.ui-transcription').html('
'+transcript+'
');

					if(data.hasOwnProperty('final') && data['final']){
						isSpeaking = false;
						changeUIState(isSpeaking);
						stream.stop();
						converse(transcript);
						$('.ui-transcription').text('');
					}
				});
				stream.on('error', function(err) {
					console.log(err);
					isSpeaking = false;
					changeUIState(isSpeaking);
				});
				stream.on('close', function(err) {
					console.log(err);
					isSpeaking = false;
					changeUIState(isSpeaking);
				});
				stream.on('connection-close', function(err) {
					console.log(err);
					isSpeaking = false;
					changeUIState(isSpeaking);
				});
			}
		});

		initToken('stt').then(function(t) {
			sttToken = t;
			converse('Hi Watson');
			var userAgent = window.navigator.userAgent.toLowerCase();
			if(userAgent.indexOf('chrome') != -1 || userAgent.indexOf('firefox') != -1){
				$mic.show();
			}
		});
		*/
		converse('Hi Watson');
		scrollToInput();

		// car control
		/**		var socket = io.connect(carServiceHost);

		socket.on("message", function (data) {
			console.log("socket data: " + data);
		});

		var onSendingCommand = function(command){
			if(command === '') {
				return;
			}
			console.log(command);
			socket.emit("String", command);
		};
		var keyToCommand = function(key){
			var direction = '';
			switch(key){

			case 'ArrowUp':
				direction = 'w';
				break;

			case 'ArrowLeft':
				direction = 'a';
				break;

			case 'ArrowDown':
				direction = 's';
				break;

			case 'ArrowRight':
				direction = 'd';
				break;
			}
			return direction;
		};

		var keys = $('.car-controller a');
		keys.on('click', function(evt){
			var command = $(this).attr('ref');
			// call Socket-IO
			onSendingCommand(command);
		});

		$(document).on('keyup', function(evt){
			var command = keyToCommand(evt.key);
			onSendingCommand(command);
			keys.removeClass('active');
		});
		$(document).on('keydown', function(evt){
			var command = keyToCommand(evt.key);
			if(command === ''){
				return;
			}
			keys.parent().find('[ref='+command+']').addClass('active');
		});
		*/
	}
};

$(document).ready(methods.chatbot);
<|endoftext|>


<commit_before>/*jslint browser: true*/

( function( $, vui ) {

	$.widget( "vui.vui_moreless", {

		options: {
			height: '4em',
			lineHeight: 'normal',
			title: {
				more: "more",
				less: "less"
			},
			color: '#FAFAFA'
		},

		_$moreblur: null,
		_$moreless: null,
		_$morelink: null,

		_accessibileButton: function( title, iconClass ) {
			var me = this;
			me._$morelink.empty();
			me._$morelink.append( '' );
			if( !this.options.accessible ) {
				me._$morelink.attr( 'aria-hidden', 'true' );
				me._$morelink.append( title );
			} else {
				me._$morelink.attr( 'aria-role', 'button' );
				title = $( '' + title + '' );
				me._$morelink.append( title );
			}
		},

		_create: function() {
			var me = this;

			me._$moreless = $( this.element );
			me._$morelink = $( '
' );
			me._$moreless.after(  me._$morelink );

			me.options.title.more = me._$moreless.attr( 'data-moreless-moretitle' ) !== undefined ? me._$moreless.attr( 'data-moreless-moretitle' ) : me.options.title.more;
			me.options.title.less = me._$moreless.attr( 'data-moreless-lesstitle' ) !== undefined ? me._$moreless.attr( 'data-moreless-lesstitle' ) : me.options.title.less;
			me.options.accessible = me._$moreless.attr( 'data-moreless-accessible' ) !== undefined && me._$moreless.attr( 'data-moreless-accessible' ) !== "False"? true : false;
			me.options.color = me._$moreless.attr( 'data-moreless-blurcolor' ) !== undefined ? me._$moreless.attr( 'data-moreless-blurcolor' ) : me.options.color;

			var lineHeight =  me._$moreless.attr( 'data-moreless-lineHeight' ) !== undefined ? me._$moreless.attr( 'data-moreless-lineHeight' ) : me.options.lineHeight;
			me._$moreless.css( 'line-height', lineHeight );

			$breakafter =  me._$moreless.find( '.vui-moreless-breakafter' );
			var height = 0;

			if( $breakafter.length ) {
				$breakafter = $( $breakafter[0] );
				//determine hieght based on bottom on node with breakafter class
				height = ( $breakafter.position().top - me._$moreless.position().top ) + $breakafter.get( 0 ).scrollHeight;

			} else {
				height = me._$moreless.attr( 'data-moreless-height' ) !== undefined ? me._$moreless.attr( 'data-moreless-height' ) : me.options.height;

				if( height.indexOf( '%' ) > -1 ) { //convert percent to px to prevent loss of transition
					height = parseInt( ( me._$moreless.get( 0 ).scrollHeight * ( parseInt( height, 10 ) / 100 ) ) + 0.5, 10 );
				}

				me._$moreblur = $( '
');
				me.BlurColor( me.options.color );
				me._$moreless.after( me._$moreblur );
			}

			me._$moreless.height( height );

			me._accessibileButton( me.options.title.more, 'vui-icon-cheverondownblue' );

			me._$morelink.on( 'click', function( e ) {
				me._switchMoreLess( height );
			} );

			me._$morelink.on( 'keypress', function( e ) {
				var keyCode = e.keyCode || e.which;

				if( keyCode === 13 ) {
					me._switchMoreLess( height );
				}
			} );

			var isTab = false;

			$( document ).keydown( function( e ) {
				var keyCode = e.keyCode || e.which;

				if( keyCode === 9 ) {
					isTab = true;
				} else {
					isTab = false;
				}
			} );

			me._$moreless.focusin( function( event ) {
				if( ! me._$moreless.hasClass( 'vui-moreless-more' ) && isTab ) {
					me._$moreless.get( 0 ).scrollTop = 0;
					me._$morelink.focus();
					isTab = false;
				}
			} );
			me._hideShowMore();
			$(window).load(function() { //chrome is returning a height of 0, need to wait for window to load to get correct height information
				me._hideShowMore();
			} );
		},

		_hexToRgb: function( inHex) {
			if( inHex.indexOf('#') > -1 ) {
				inHex = inHex.substring(1);
			}
			// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
			if (inHex.length === 3) {
				var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
				inHex = inHex.replace(shorthandRegex, function (m, r, g, b) {
					return r + r + g + g + b + b;
				} );
			}

			var bigint = parseInt( inHex, 16);
			var r = (bigint >> 16) & 255;
			var g = (bigint >> 8) & 255;
			var b = bigint & 255;

			return {
				red: r,
				green: g,
				blue: b
			};
		},

		_hideShowMore: function() {
			var me = this;
			if( me._$moreless &&
				!me._$moreless.hasClass( 'vui-moreless-more' ) &&
				me._$moreless.height() >=  me._$moreless.get( 0 ).scrollHeight ) {

				var lastchild = me._$moreless.children().last();
				var h = ( lastchild.position().top  - me._$moreless.position().top ) + lastchild.get(0).scrollHeight;
				me._$moreless.height( h );
				me._$morelink.css( 'display', 'none' );

				if( me._$moreblur ) {
					me._$moreblur.css( 'display', 'none' );
				}
			}
		},

		_switchMoreLess: function( inHeight ) {
			var me = this;
			if( me._$moreless.hasClass( 'vui-moreless-more' ) ) {
				me._$moreless.removeClass( 'vui-moreless-more' );
				if( me._$moreblur ) {
					me._$moreblur.css( 'display', 'block' );
				}
				me._$moreless.css( 'height', inHeight );
				me._accessibileButton(  me.options.title.more, 'vui-icon-cheverondownblue' );
				me._$moreless.trigger( 'vui-moreless-collapse' );
			} else {
				me._$moreless.addClass( 'vui-moreless-more' );
				if( me._$moreblur ) {
					me._$moreblur.css( 'display', 'none' );
				}
				me._$moreless.css( 'height',  me._$moreless.get( 0 ).scrollHeight );
				me._accessibileButton( this.options.title.less, 'vui-icon-cheveronupblue' );
				me._$moreless.trigger( 'vui-moreless-expand' );
			}
		},

		BlurColor: function( inColor ) {
			var me = this;
			if( me._$moreblur !== null ) {
				var rgba0 = 'rgba( 250, 250, 250, 0)';
				var rgba1 = 'rgba( 250, 250, 250, 1)';

				if( inColor.indexOf( '#' ) > -1 ) {
					var rgb = me._hexToRgb( inColor );
					rgba0 = 'rgba(' + rgb.red + ',' + rgb.green + ',' + rgb.blue + ', 0)';
					rgba1 = 'rgba(' + rgb.red + ',' + rgb.green + ',' + rgb.blue + ', 1)';
				}
				var moz = '-moz-linear-gradient(top, ' + rgba0 + ' 0%, '+ rgba1 + ' 100%)';
				var webkit1 = '-webkit-gradient(linear, left top, left bottom, color-stop(0%, ' + rgba0 + '), color-stop(100%, '+ rgba1 + '))'; /* Chrome,Safari4+ */
				var webkit2 = '-webkit-linear-gradient(top, ' + rgba0 + ' 0%, ' + rgba1 + '100%)'; /* Chrome10+,Safari5.1+ */
				var o = '-o-linear-gradient(top, ' + rgba0 + ' 0%, ' + rgba1 + ' 100%)'; /* Opera 11.10+ */
				var ms = '-ms-linear-gradient(top, ' + rgba0 + ' 0%, '+ rgba1 + ' 100%)';/* IE10+ */
				var general = 'linear-gradient(to bottom, ' + rgba0 + ' 0%, ' + rgba1 + ' 100%)';/* W3C */

				me._$moreblur.css( { 'background': 'transparent' } )
					.css( { 'background': moz } )
					.css( { 'background': webkit1 } )
					.css( { 'background': webkit2 } )
					.css( { 'background': o } )
					.css( { 'background': ms } )
					.css( { 'background': general } );
			}
		},

		isExpanded: function( node ) {
			return $( node ).hasClass( 'vui-moreless-more' );
		},

		Refresh: function( inColor ){
			if( inColor !== null ) {
				this.BlurColor( inColor );
			}
			this._hideShowMore();
		}

	} );

	vui.addClassInitializer(
		'vui-moreless',
		function( node ) {
			$( node ).vui_moreless();
		}
	);

} )( window.jQuery, window.vui );<commit_msg>check for vui within each control and require it or thrown an error<commit_after>/*jslint browser: true*/

( function( $, vui ) {

	// Check if the provided vui global is defined, otherwise try to require it if
	// we're in a CommonJS environment; otherwise we'll just fail out
	if( vui === undefined ) {
		if( typeof require === 'function' ) {
			vui = require('../../vui');
		} else {
			throw new Error('load vui first');
		}
	}

	$.widget( "vui.vui_moreless", {

		options: {
			height: '4em',
			lineHeight: 'normal',
			title: {
				more: "more",
				less: "less"
			},
			color: '#FAFAFA'
		},

		_$moreblur: null,
		_$moreless: null,
		_$morelink: null,

		_accessibileButton: function( title, iconClass ) {
			var me = this;
			me._$morelink.empty();
			me._$morelink.append( '' );
			if( !this.options.accessible ) {
				me._$morelink.attr( 'aria-hidden', 'true' );
				me._$morelink.append( title );
			} else {
				me._$morelink.attr( 'aria-role', 'button' );
				title = $( '' + title + '' );
				me._$morelink.append( title );
			}
		},

		_create: function() {
			var me = this;

			me._$moreless = $( this.element );
			me._$morelink = $( '
' );
			me._$moreless.after(  me._$morelink );

			me.options.title.more = me._$moreless.attr( 'data-moreless-moretitle' ) !== undefined ? me._$moreless.attr( 'data-moreless-moretitle' ) : me.options.title.more;
			me.options.title.less = me._$moreless.attr( 'data-moreless-lesstitle' ) !== undefined ? me._$moreless.attr( 'data-moreless-lesstitle' ) : me.options.title.less;
			me.options.accessible = me._$moreless.attr( 'data-moreless-accessible' ) !== undefined && me._$moreless.attr( 'data-moreless-accessible' ) !== "False"? true : false;
			me.options.color = me._$moreless.attr( 'data-moreless-blurcolor' ) !== undefined ? me._$moreless.attr( 'data-moreless-blurcolor' ) : me.options.color;

			var lineHeight =  me._$moreless.attr( 'data-moreless-lineHeight' ) !== undefined ? me._$moreless.attr( 'data-moreless-lineHeight' ) : me.options.lineHeight;
			me._$moreless.css( 'line-height', lineHeight );

			$breakafter =  me._$moreless.find( '.vui-moreless-breakafter' );
			var height = 0;

			if( $breakafter.length ) {
				$breakafter = $( $breakafter[0] );
				//determine hieght based on bottom on node with breakafter class
				height = ( $breakafter.position().top - me._$moreless.position().top ) + $breakafter.get( 0 ).scrollHeight;

			} else {
				height = me._$moreless.attr( 'data-moreless-height' ) !== undefined ? me._$moreless.attr( 'data-moreless-height' ) : me.options.height;

				if( height.indexOf( '%' ) > -1 ) { //convert percent to px to prevent loss of transition
					height = parseInt( ( me._$moreless.get( 0 ).scrollHeight * ( parseInt( height, 10 ) / 100 ) ) + 0.5, 10 );
				}

				me._$moreblur = $( '
');
				me.BlurColor( me.options.color );
				me._$moreless.after( me._$moreblur );
			}

			me._$moreless.height( height );

			me._accessibileButton( me.options.title.more, 'vui-icon-cheverondownblue' );

			me._$morelink.on( 'click', function( e ) {
				me._switchMoreLess( height );
			} );

			me._$morelink.on( 'keypress', function( e ) {
				var keyCode = e.keyCode || e.which;

				if( keyCode === 13 ) {
					me._switchMoreLess( height );
				}
			} );

			var isTab = false;

			$( document ).keydown( function( e ) {
				var keyCode = e.keyCode || e.which;

				if( keyCode === 9 ) {
					isTab = true;
				} else {
					isTab = false;
				}
			} );

			me._$moreless.focusin( function( event ) {
				if( ! me._$moreless.hasClass( 'vui-moreless-more' ) && isTab ) {
					me._$moreless.get( 0 ).scrollTop = 0;
					me._$morelink.focus();
					isTab = false;
				}
			} );
			me._hideShowMore();
			$(window).load(function() { //chrome is returning a height of 0, need to wait for window to load to get correct height information
				me._hideShowMore();
			} );
		},

		_hexToRgb: function( inHex) {
			if( inHex.indexOf('#') > -1 ) {
				inHex = inHex.substring(1);
			}
			// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
			if (inHex.length === 3) {
				var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
				inHex = inHex.replace(shorthandRegex, function (m, r, g, b) {
					return r + r + g + g + b + b;
				} );
			}

			var bigint = parseInt( inHex, 16);
			var r = (bigint >> 16) & 255;
			var g = (bigint >> 8) & 255;
			var b = bigint & 255;

			return {
				red: r,
				green: g,
				blue: b
			};
		},

		_hideShowMore: function() {
			var me = this;
			if( me._$moreless &&
				!me._$moreless.hasClass( 'vui-moreless-more' ) &&
				me._$moreless.height() >=  me._$moreless.get( 0 ).scrollHeight ) {

				var lastchild = me._$moreless.children().last();
				var h = ( lastchild.position().top  - me._$moreless.position().top ) + lastchild.get(0).scrollHeight;
				me._$moreless.height( h );
				me._$morelink.css( 'display', 'none' );

				if( me._$moreblur ) {
					me._$moreblur.css( 'display', 'none' );
				}
			}
		},

		_switchMoreLess: function( inHeight ) {
			var me = this;
			if( me._$moreless.hasClass( 'vui-moreless-more' ) ) {
				me._$moreless.removeClass( 'vui-moreless-more' );
				if( me._$moreblur ) {
					me._$moreblur.css( 'display', 'block' );
				}
				me._$moreless.css( 'height', inHeight );
				me._accessibileButton(  me.options.title.more, 'vui-icon-cheverondownblue' );
				me._$moreless.trigger( 'vui-moreless-collapse' );
			} else {
				me._$moreless.addClass( 'vui-moreless-more' );
				if( me._$moreblur ) {
					me._$moreblur.css( 'display', 'none' );
				}
				me._$moreless.css( 'height',  me._$moreless.get( 0 ).scrollHeight );
				me._accessibileButton( this.options.title.less, 'vui-icon-cheveronupblue' );
				me._$moreless.trigger( 'vui-moreless-expand' );
			}
		},

		BlurColor: function( inColor ) {
			var me = this;
			if( me._$moreblur !== null ) {
				var rgba0 = 'rgba( 250, 250, 250, 0)';
				var rgba1 = 'rgba( 250, 250, 250, 1)';

				if( inColor.indexOf( '#' ) > -1 ) {
					var rgb = me._hexToRgb( inColor );
					rgba0 = 'rgba(' + rgb.red + ',' + rgb.green + ',' + rgb.blue + ', 0)';
					rgba1 = 'rgba(' + rgb.red + ',' + rgb.green + ',' + rgb.blue + ', 1)';
				}
				var moz = '-moz-linear-gradient(top, ' + rgba0 + ' 0%, '+ rgba1 + ' 100%)';
				var webkit1 = '-webkit-gradient(linear, left top, left bottom, color-stop(0%, ' + rgba0 + '), color-stop(100%, '+ rgba1 + '))'; /* Chrome,Safari4+ */
				var webkit2 = '-webkit-linear-gradient(top, ' + rgba0 + ' 0%, ' + rgba1 + '100%)'; /* Chrome10+,Safari5.1+ */
				var o = '-o-linear-gradient(top, ' + rgba0 + ' 0%, ' + rgba1 + ' 100%)'; /* Opera 11.10+ */
				var ms = '-ms-linear-gradient(top, ' + rgba0 + ' 0%, '+ rgba1 + ' 100%)';/* IE10+ */
				var general = 'linear-gradient(to bottom, ' + rgba0 + ' 0%, ' + rgba1 + ' 100%)';/* W3C */

				me._$moreblur.css( { 'background': 'transparent' } )
					.css( { 'background': moz } )
					.css( { 'background': webkit1 } )
					.css( { 'background': webkit2 } )
					.css( { 'background': o } )
					.css( { 'background': ms } )
					.css( { 'background': general } );
			}
		},

		isExpanded: function( node ) {
			return $( node ).hasClass( 'vui-moreless-more' );
		},

		Refresh: function( inColor ){
			if( inColor !== null ) {
				this.BlurColor( inColor );
			}
			this._hideShowMore();
		}

	} );

	vui.addClassInitializer(
		'vui-moreless',
		function( node ) {
			$( node ).vui_moreless();
		}
	);

} )( window.jQuery, window.vui );<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Grid, Row, Col, Panel } from 'react-bootstrap';
import PrettyJSON from '../../components/PrettyJSON';
import EventListItem from './EventListItem';
import AnnouncementsList from './AnnouncementsList';
import moment from 'moment';

import Countdown from './Countdown';
export default class Homepage extends Component {
  loadData = () => {
    this.props.loadEvents();
    this.props.loadAnnouncements();
  };
  componentDidMount = () => {
    this.loadData();
    setInterval(() => { this.loadData(); }, 10000);
  };

  render () {
    let announcementsList = this.props.announcements.announcements ? this.props.announcements.announcements : [];
    let eventList = this.props.events.events === null
      ? null
      : this.props.events.events.map(event => ({
        ...event,
        begin: moment(event.begin),
        end: moment(event.end),
        day: moment(event.begin).day()
      }));

    let fri = eventList ? eventList.filter(event => event.day === 5) : [];
    let sat = eventList ? eventList.filter(event => event.day === 6) : [];
    let sun = eventList ? eventList.filter(event => event.day === 0) : [];

    return (

        <Grid fluid>
          <Row className='show-grid'>

            <Col sm={12} md={12} lg={12}>

BoilerMake IV

            </Col>
            <Col sm={3} md={3} lg={3}>

Schedule

                {/* <button onClick={this.loadData}>Reload Data</button> */}
                <EventListItem title='Friday, Jan 20' events={fri} />
                <EventListItem title='Saturday, Jan 21' events={sat} />
                <EventListItem title='Sunday, Jan 22' events={sun} />
                {/* <PrettyJSON data={eventList} /> */}

            </Col>
            <Col sm={6} md={6} lg={6}>

General Info

<Countdown date={new Date('2017/01/20 21:30:00')} label='until hacking begins' />

Event Map

            </Col>
            <Col sm={3} md={3} lg={3}>

Announcements

                <AnnouncementsList announcements={announcementsList} />

Help

Wifi: BoilerMake | TBD

Slack: boilermake2017.slack.com

Messenger: boilermake

Email: team@boilermake.org

We will be offering complimentary showers and towels during the following timeframes:
                  Friday till midnight, Saturday from 8am-midnight, and after 10am on Sunday.

            </Col>
          </Row>
        </Grid>

);
  }
}
<commit_msg>no message<commit_after>import React, { Component } from 'react';
import { Grid, Row, Col, Panel } from 'react-bootstrap';
import PrettyJSON from '../../components/PrettyJSON';
import EventListItem from './EventListItem';
import AnnouncementsList from './AnnouncementsList';
import moment from 'moment';

import Countdown from './Countdown';
export default class Homepage extends Component {
  loadData = () => {
    this.props.loadEvents();
    this.props.loadAnnouncements();
  };
  componentDidMount = () => {
    this.loadData();
    setInterval(() => { this.loadData(); }, 10000);
  };

  render () {
    let announcementsList = this.props.announcements.announcements ? this.props.announcements.announcements : [];
    let eventList = this.props.events.events === null
      ? null
      : this.props.events.events.map(event => ({
        ...event,
        begin: moment(event.begin),
        end: moment(event.end),
        day: moment(event.begin).day()
      }));

    let fri = eventList ? eventList.filter(event => event.day === 5) : [];
    let sat = eventList ? eventList.filter(event => event.day === 6) : [];
    let sun = eventList ? eventList.filter(event => event.day === 0) : [];

    return (

        <Grid fluid>
          <Row className='show-grid'>

            <Col sm={12} md={12} lg={12}>

BoilerMake IV

            </Col>
            <Col sm={3} md={3} lg={3}>

Schedule

                {/* <button onClick={this.loadData}>Reload Data</button> */}
                <EventListItem title='Friday, Jan 20' events={fri} />
                <EventListItem title='Saturday, Jan 21' events={sat} />
                <EventListItem title='Sunday, Jan 22' events={sun} />
                {/* <PrettyJSON data={eventList} /> */}

            </Col>
            <Col sm={6} md={6} lg={6}>

General Info

<Countdown date={new Date('2017/01/20 21:30:00')} label='until hacking begins' />

Event Map

            </Col>
            <Col sm={3} md={3} lg={3}>

Announcements

                <AnnouncementsList announcements={announcementsList} />

Help

Wifi: BoilerMake | TBD

Slack: boilermake2017.slack.com

Messenger: boilermake

Email: team@boilermake.org

We will be offering complimentary showers and towels during the following timeframes:
                  Friday till midnight, Saturday from 8am-midnight, and after 10am on Sunday.

            </Col>
          </Row>
        </Grid>

);
  }
}
<|endoftext|>


<commit_before>import Twitter from 'twitter'
import storage from 'electron-json-storage-sync'
import { credentials, keys } from '../../../constants'

const oauthInfo = storage.get(keys.OAUTH_TOKEN)

// TODO: oauthInfo get failure
const client = new Twitter({
  consumer_key: credentials.CONSUMER_KEY,
  consumer_secret: credentials.CONSUMER_SECRET,
  access_token_key: oauthInfo.data.oauth_access_token,
  access_token_secret: oauthInfo.data.oauth_access_token_secret
})

const params = {
  include_entities: true,
  tweet_mode: 'extended'
}

const state = {
  timeline: [],
  mentions: [],
  favorites: []
}

const mutations = {
  ADD_TIMELINE (state, tweets) {
    state.timeline = tweets
  },
  ADD_MENTIONS (state, tweets) {
    state.mentions = tweets
  },
  ADD_FAVORITES (state, tweets) {
    state.favorites = tweets
  }
}

const actions = {
  fetchTimeline ({ commit }) {
    fetchTweets('statuses/home_timeline')
      .then((tweets) => {
        commit('ADD_TIMELINE', tweets)
      })
  },
  fetchMentions ({ commit }) {
    fetchTweets('statuses/mentions_timeline')
      .then((tweets) => {
        commit('ADD_MENTIONS', tweets)
      })
  },
  fetchFavorites ({ commit }) {
    fetchTweets('favorites/list')
      .then((tweets) => {
        commit('ADD_FAVORITES', tweets)
      })
  }
}

function fetchTweets (endpoint) {
  return new Promise((resolve, reject) => {
    client.get(endpoint, params, (err, tweets, res) => {
      if (!err) {
        resolve(tweets)
      } else {
        reject(err)
      }
    })
  })
}

export default {
  state,
  mutations,
  actions
}
<commit_msg>Add query param if timeline fetch next time<commit_after>import Twitter from 'twitter'
import storage from 'electron-json-storage-sync'
import { credentials, keys } from '../../../constants'

const oauthInfo = storage.get(keys.OAUTH_TOKEN)

// TODO: oauthInfo get failure
const client = new Twitter({
  consumer_key: credentials.CONSUMER_KEY,
  consumer_secret: credentials.CONSUMER_SECRET,
  access_token_key: oauthInfo.data.oauth_access_token,
  access_token_secret: oauthInfo.data.oauth_access_token_secret
})

const getDefaultParams = {
  include_entities: true,
  tweet_mode: 'extended'
}

const state = {
  timeline: [],
  mentions: [],
  favorites: []
}

const mutations = {
  ADD_TIMELINE (state, tweets) {
    state.timeline = tweets.concat(state.timeline)
  },
  ADD_MENTIONS (state, tweets) {
    state.mentions = tweets
  },
  ADD_FAVORITES (state, tweets) {
    state.favorites = tweets
  }
}

const actions = {
  fetchTimeline ({ commit }) {
    let params = getDefaultParams
    if (state.timeline.length > 0) {
      params.since_id = state.timeline[0].id_str
    }
    fetchTweets('statuses/home_timeline', params)
      .then((tweets) => {
        commit('ADD_TIMELINE', tweets)
      })
  },
  fetchMentions ({ commit }) {
    fetchTweets('statuses/mentions_timeline', getDefaultParams)
      .then((tweets) => {
        commit('ADD_MENTIONS', tweets)
      })
  },
  fetchFavorites ({ commit }) {
    fetchTweets('favorites/list', getDefaultParams)
      .then((tweets) => {
        commit('ADD_FAVORITES', tweets)
      })
  }
}

function fetchTweets (endpoint, params) {
  return new Promise((resolve, reject) => {
    client.get(endpoint, params, (err, tweets, res) => {
      if (!err) {
        resolve(tweets)
      } else {
        reject(err)
      }
    })
  })
}

export default {
  state,
  mutations,
  actions
}
<|endoftext|>