<commit_before>'use babel';

import path from 'path';
import fs from 'fs-plus';
import { CompositeDisposable } from 'atom';

import ItemView from './item-view.js';
import FileIcons from './file-icons.js';

export default class ItemController {
  constructor(parent, item, index) {
    this.parent = parent;
    this.item   = item;
    this.index  = index;

    this.destoyed = false;
    this.path     = this.getItemPath();
    this.realpath = this.path;
    this.repo     = null;
    this.pending  = false;

    this.showPending = atom.config.get('tree-view-panes.showPendingItems');
    this.showStatus  = atom.config.get('tree-view-panes.showGitStatus');

    this.view = new ItemView(['icon-file']);
    this.updateTitle();
    this.updatePath();
    this.updateIcon();
    this.updateModified();
    this.view.setPending(this.pending);
    this.view.setVisibility(!this.pending || this.showPending);

    // item observation
    this.itemSub = new CompositeDisposable();
    if (typeof this.item.onDidChangeTitle === 'function') {
      this.itemSub.add(this.item.onDidChangeTitle(() => {
        this.updateTitle();
      }));
    }
    if (typeof this.item.onDidChangePath === 'function') {
      this.itemSub.add(this.item.onDidChangePath(() => {
        this.path     = this.getItemPath();
        this.realpath = this.path;
        this.updatePath();
        this.updateIcon();
        this.fetchRealpath();
        this.fetchRepo();
      }));
    }
    if (typeof this.item.onDidChangeModified === 'function') {
      this.itemSub.add(this.item.onDidChangeModified(() => {
        this.updateModified();
      }));
    }

    // repository observation
    this.repoSub = null;

    // config observation
    this.configSub = new CompositeDisposable();
    this.configSub.add(atom.config.observe(
      'tree-view-panes.showPendingItems',
      showPendingItems => {
        this.showPending = showPendingItems;
        this.view.setVisibility(!this.pending || this.showPending);
      }
    ));
    this.configSub.add(atom.config.observe(
      'tree-view-panes.showGitStatus',
      showStatus => {
        this.showStatus = showStatus;
        this.updateStatus();
      }
    ));
    this.configSub.add(atom.config.observe(
      'tree-view.showOnRightSide',
      () => {
        this.view.resetTooltip();
      }
    ));

    // commands observation
    this.commandsSub = new CompositeDisposable();
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:close-item',
      () => { this.parent.closeItem(this.item); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:close-other-items',
      () => { this.parent.closeItemsExcept(this.item); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-up',
      () => { this.parent.pane.splitUp({ items: this.copyItem() }); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-down',
      () => { this.parent.pane.splitDown({ items: this.copyItem() }); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-left',
      () => { this.parent.pane.splitLeft({ items: this.copyItem() }); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-right',
      () => { this.parent.pane.splitRight({ items: this.copyItem() }); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-up-and-move',
      () => {
        const pane = this.parent.pane.splitUp();
        this.parent.pane.moveItemToPane(this.item, pane, 0);
      }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-down-and-move',
      () => {
        const pane = this.parent.pane.splitDown();
        this.parent.pane.moveItemToPane(this.item, pane, 0);
      }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-left-and-move',
      () => {
        const pane = this.parent.pane.splitLeft();
        this.parent.pane.moveItemToPane(this.item, pane, 0);
      }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-right-and-move',
      () => {
        const pane = this.parent.pane.splitRight();
        this.parent.pane.moveItemToPane(this.item, pane, 0);
      }
    ));

    // DOM events
    this.onClick = () => {
      this.parent.activateItem(this.item);
    };
    this.onDragStart = event => {
      event.stopPropagation();
      this.parent.activateItem(this.item);
      // set data
      event.dataTransfer.setData('tree-view-panes-event', 'true');
      event.dataTransfer.setData('sortable-index', this.index);
      event.dataTransfer.setData('from-pane-index', this.parent.index);
      event.dataTransfer.setData('from-window-id', atom.getCurrentWindow().id);
      // set dragging appearance
      event.dataTransfer.effectAllowed = 'move';
      const dragImage = this.view.nameElement.cloneNode(true);
      dragImage.style.position = 'absolute';
      dragImage.style.top      = '0';
      dragImage.style.left     = '0';
      document.body.appendChild(dragImage);
      window.requestAnimationFrame(() => {
        document.body.removeChild(dragImage);
      });
      event.dataTransfer.setDragImage(dragImage, 0, 0);
    };
    this.onDragOver = event => {
      if (!event.dataTransfer.getData('tree-view-panes-event')) {
        return;
      }
      event.stopPropagation();
      event.preventDefault();
      this.view.setDragOver(true);
    };
    this.onDragEnter = event => {
      if (!event.dataTransfer.getData('tree-view-panes-event')) {
        return;
      }
      event.stopPropagation();
      event.preventDefault();
      this.view.setDragOver(true);
    };
    this.onDragLeave = event => {
      if (!event.dataTransfer.getData('tree-view-panes-event')) {
        return;
      }
      event.stopPropagation();
      event.preventDefault();
      this.view.setDragOver(false);
    };
    this.onDrop = event => {
      if (!event.dataTransfer.getData('tree-view-panes-event')) {
        return;
      }
      event.stopPropagation();
      event.preventDefault();
      this.view.setDragOver(false);
      // get data
      const fromWindowId = parseInt(
        event.dataTransfer.getData('from-window-id')
      );
      const fromPaneIndex = parseInt(
        event.dataTransfer.getData('from-pane-index')
      );
      const fromIndex = parseInt(
        event.dataTransfer.getData('sortable-index')
      );
      // dropping from other window is (currently) not supported
      if (fromWindowId !== atom.getCurrentWindow().id) {
        return;
      }
      // find controllers
      const fromPaneCtrler = this.parent.parent.getPaneControllerAt(
        fromPaneIndex
      );
      if (!fromPaneCtrler) {
        return;
      }
      const itemCtrler = fromPaneCtrler.getItemControllerAt(fromIndex);
      if (!itemCtrler) {
        return;
      }
      // move item
      if (fromPaneCtrler === this.parent && itemCtrler === this) {
        return;
      }
      else {
        const toIndex = fromPaneCtrler === this.parent
          && itemCtrler.index <= this.index
          ? this.index
          : this.index + 1;
        fromPaneCtrler.moveItem(itemCtrler.item, this.parent.pane, toIndex);
      }
    };
    this.onCloseButtonClick = () => {
      this.parent.destroyItem(this.item);
    };
    this.view.element.addEventListener('click', this.onClick);
    this.view.element.addEventListener('dragstart', this.onDragStart);
    this.view.element.addEventListener('dragover', this.onDragOver);
    this.view.element.addEventListener('dragenter', this.onDragEnter);
    this.view.element.addEventListener('dragleave', this.onDragLeave);
    this.view.element.addEventListener('drop', this.onDrop);
    this.view.closeButtonElement.addEventListener(
      'click',
      this.onCloseButtonClick
    );

    // fetch realpath and repository
    this.fetchRealpath();
    this.fetchRepo();
  }

  getItemPath() {
    return typeof this.item.getPath === 'function'
      ? this.item.getPath()
      : undefined;
  }

  fetchRealpath() {
    if (!this.path) {
      return;
    }
    fs.realpath(this.path, {}, (error, realpath) => {
      if (error || this.destoyed) {
        return;
      }
      this.realpath = realpath;
      if (this.path !== this.realpath) {
        this.updateStatus();
      }
    });
  }

  fetchRepo() {
    // discard old repo
    if (this.repo || this.repoSub) {
      this.repoSub.dispose();
      this.repoSub = null;
      this.repo    = null;
    }
    // get new repo
    if (!this.path) {
      return;
    }
    const directories = atom.project.getDirectories();
    for (const directory of directories) {
      if (directory.contains(this.path)) {
        atom.project.repositoryForDirectory(directory).then(repo => {
          if (this.destoyed) {
            return;
          }
          if (!repo) {
            this.updateStatus();
            return;
          }
          this.repo = repo;
          this.updateStatus();
          // repository observation
          this.repoSub = new CompositeDisposable();
          this.repoSub.add(repo.onDidChangeStatus(event => {
            if (event.path === this.path || event.path === this.realpath) {
              this.updateStatus();
            }
          }));
          this.repoSub.add(repo.onDidChangeStatuses(() => {
            this.updateStatus();
          }));
        });
        return;
      }
    }
  }

  setIndex(index) {
    if (index !== this.index) {
      this.view.resetTooltip();
    }
    this.index = index;
  }

  setActive(active) {
    this.view.setActive(active);
  }

  setPending(pending) {
    this.pending = pending;
    this.view.setPending(this.pending);
    this.view.setVisibility(!this.pending || this.showPending);
  }

  updateTitle() {
    const title = typeof this.item.getLongTitle === 'function'
      ? this.item.getLongTitle()
      : typeof this.item.getTitle === 'function'
        ? this.item.getTitle()
        : 'Unknown';
    this.view.setTitle(title);
  }

  updatePath() {
    if (this.path) {
      this.view.setName(path.basename(this.path));
      this.view.setPath(this.path);
    }
    else {
      this.view.setName(undefined);
      this.view.setPath(undefined);
    }
  }

  updateIcon() {
    if (typeof this.item.getIconName === 'function') {
      this.view.setIconClass([`icon-${this.item.getIconName()}`]);
    }
    else {
      if (this.path) {
        const iconClass = FileIcons.getIconClassForPath(this.path);
        if (Array.isArray(iconClass)) {
          this.view.setIconClass(iconClass);
        }
        else {
          this.view.setIconClass(iconClass.toString().split(/\s+/));
        }
      }
      else {
        this.view.setIconClass(['icon-file']);
      }
    }
  }

  updateModified() {
    if (typeof this.item.isModified === 'function') {
      this.view.setModified(this.item.isModified());
    }
    else {
      this.view.setModified(false);
    }
  }

  updateStatus() {
    if (this.showStatus) {
      if (this.repo) {
        if (this.repo.isPathIgnored(this.path)) {
          this.view.setStatus('status-ignored');
        }
        else {
          const status = this.repo.getCachedPathStatus(this.path);
          if (this.repo.isStatusModified(status)) {
            this.view.setStatus('status-modified');
          }
          else if (this.repo.isStatusNew(status)) {
            this.view.setStatus('status-added');
          }
          else {
            this.view.setStatus(undefined);
          }
        }
      }
      else {
        this.view.setStatus(undefined);
      }
    }
    else {
      this.view.setStatus(undefined);
    }
  }

  copyItem() {
    if (typeof this.item.copy === 'function') {
      return [this.item.copy()];
    }
    else if (this.parent.pane.deserializerManager
      && typeof this.item.serialize === 'function') {
      return [
        this.parent.pane.deserializerManager.deserialize(this.item.serialize())
      ];
    }
    else {
      return [];
    }
  }

  destroy() {
    this.itemSub.dispose();
    if (this.repoSub) {
      this.repoSub.dispose();
    }
    this.configSub.dispose();
    this.commandsSub.dispose();
    this.view.element.removeEventListener('click', this.onClick);
    this.view.element.removeEventListener('dragstart', this.onDragStart);
    this.view.element.removeEventListener('dragover', this.onDragOver);
    this.view.element.removeEventListener('dragenter', this.onDragEnter);
    this.view.element.removeEventListener('dragleave', this.onDragLeave);
    this.view.element.removeEventListener('drop', this.onDrop);
    this.view.closeButtonElement.removeEventListener(
      'click',
      this.onCloseButtonClick
    );

    this.view.destroy();

    this.destoyed = true;
  }
}
<commit_msg>Fix titles of other items are not updated on renaming<commit_after>'use babel';

import path from 'path';
import fs from 'fs-plus';
import { CompositeDisposable } from 'atom';

import ItemView from './item-view.js';
import FileIcons from './file-icons.js';

export default class ItemController {
  constructor(parent, item, index) {
    this.parent = parent;
    this.item   = item;
    this.index  = index;

    this.destoyed = false;
    this.path     = this.getItemPath();
    this.realpath = this.path;
    this.repo     = null;
    this.pending  = false;

    this.showPending = atom.config.get('tree-view-panes.showPendingItems');
    this.showStatus  = atom.config.get('tree-view-panes.showGitStatus');

    this.view = new ItemView(['icon-file']);
    this.updateTitle();
    this.updatePath();
    this.updateIcon();
    this.updateModified();
    this.view.setPending(this.pending);
    this.view.setVisibility(!this.pending || this.showPending);

    // item observation
    this.itemSub = new CompositeDisposable();
    if (typeof this.item.onDidChangeTitle === 'function') {
      this.itemSub.add(this.item.onDidChangeTitle(() => {
        this.parent.parent.updateItemTitles();
      }));
    }
    if (typeof this.item.onDidChangePath === 'function') {
      this.itemSub.add(this.item.onDidChangePath(() => {
        this.path     = this.getItemPath();
        this.realpath = this.path;
        this.updatePath();
        this.updateIcon();
        this.fetchRealpath();
        this.fetchRepo();
      }));
    }
    if (typeof this.item.onDidChangeModified === 'function') {
      this.itemSub.add(this.item.onDidChangeModified(() => {
        this.updateModified();
      }));
    }

    // repository observation
    this.repoSub = null;

    // config observation
    this.configSub = new CompositeDisposable();
    this.configSub.add(atom.config.observe(
      'tree-view-panes.showPendingItems',
      showPendingItems => {
        this.showPending = showPendingItems;
        this.view.setVisibility(!this.pending || this.showPending);
      }
    ));
    this.configSub.add(atom.config.observe(
      'tree-view-panes.showGitStatus',
      showStatus => {
        this.showStatus = showStatus;
        this.updateStatus();
      }
    ));
    this.configSub.add(atom.config.observe(
      'tree-view.showOnRightSide',
      () => {
        this.view.resetTooltip();
      }
    ));

    // commands observation
    this.commandsSub = new CompositeDisposable();
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:close-item',
      () => { this.parent.closeItem(this.item); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:close-other-items',
      () => { this.parent.closeItemsExcept(this.item); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-up',
      () => { this.parent.pane.splitUp({ items: this.copyItem() }); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-down',
      () => { this.parent.pane.splitDown({ items: this.copyItem() }); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-left',
      () => { this.parent.pane.splitLeft({ items: this.copyItem() }); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-right',
      () => { this.parent.pane.splitRight({ items: this.copyItem() }); }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-up-and-move',
      () => {
        const pane = this.parent.pane.splitUp();
        this.parent.pane.moveItemToPane(this.item, pane, 0);
      }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-down-and-move',
      () => {
        const pane = this.parent.pane.splitDown();
        this.parent.pane.moveItemToPane(this.item, pane, 0);
      }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-left-and-move',
      () => {
        const pane = this.parent.pane.splitLeft();
        this.parent.pane.moveItemToPane(this.item, pane, 0);
      }
    ));
    this.commandsSub.add(atom.commands.add(
      this.view.element,
      'tree-view-panes:split-right-and-move',
      () => {
        const pane = this.parent.pane.splitRight();
        this.parent.pane.moveItemToPane(this.item, pane, 0);
      }
    ));

    // DOM events
    this.onClick = () => {
      this.parent.activateItem(this.item);
    };
    this.onDragStart = event => {
      event.stopPropagation();
      this.parent.activateItem(this.item);
      // set data
      event.dataTransfer.setData('tree-view-panes-event', 'true');
      event.dataTransfer.setData('sortable-index', this.index);
      event.dataTransfer.setData('from-pane-index', this.parent.index);
      event.dataTransfer.setData('from-window-id', atom.getCurrentWindow().id);
      // set dragging appearance
      event.dataTransfer.effectAllowed = 'move';
      const dragImage = this.view.nameElement.cloneNode(true);
      dragImage.style.position = 'absolute';
      dragImage.style.top      = '0';
      dragImage.style.left     = '0';
      document.body.appendChild(dragImage);
      window.requestAnimationFrame(() => {
        document.body.removeChild(dragImage);
      });
      event.dataTransfer.setDragImage(dragImage, 0, 0);
    };
    this.onDragOver = event => {
      if (!event.dataTransfer.getData('tree-view-panes-event')) {
        return;
      }
      event.stopPropagation();
      event.preventDefault();
      this.view.setDragOver(true);
    };
    this.onDragEnter = event => {
      if (!event.dataTransfer.getData('tree-view-panes-event')) {
        return;
      }
      event.stopPropagation();
      event.preventDefault();
      this.view.setDragOver(true);
    };
    this.onDragLeave = event => {
      if (!event.dataTransfer.getData('tree-view-panes-event')) {
        return;
      }
      event.stopPropagation();
      event.preventDefault();
      this.view.setDragOver(false);
    };
    this.onDrop = event => {
      if (!event.dataTransfer.getData('tree-view-panes-event')) {
        return;
      }
      event.stopPropagation();
      event.preventDefault();
      this.view.setDragOver(false);
      // get data
      const fromWindowId = parseInt(
        event.dataTransfer.getData('from-window-id')
      );
      const fromPaneIndex = parseInt(
        event.dataTransfer.getData('from-pane-index')
      );
      const fromIndex = parseInt(
        event.dataTransfer.getData('sortable-index')
      );
      // dropping from other window is (currently) not supported
      if (fromWindowId !== atom.getCurrentWindow().id) {
        return;
      }
      // find controllers
      const fromPaneCtrler = this.parent.parent.getPaneControllerAt(
        fromPaneIndex
      );
      if (!fromPaneCtrler) {
        return;
      }
      const itemCtrler = fromPaneCtrler.getItemControllerAt(fromIndex);
      if (!itemCtrler) {
        return;
      }
      // move item
      if (fromPaneCtrler === this.parent && itemCtrler === this) {
        return;
      }
      else {
        const toIndex = fromPaneCtrler === this.parent
          && itemCtrler.index <= this.index
          ? this.index
          : this.index + 1;
        fromPaneCtrler.moveItem(itemCtrler.item, this.parent.pane, toIndex);
      }
    };
    this.onCloseButtonClick = () => {
      this.parent.destroyItem(this.item);
    };
    this.view.element.addEventListener('click', this.onClick);
    this.view.element.addEventListener('dragstart', this.onDragStart);
    this.view.element.addEventListener('dragover', this.onDragOver);
    this.view.element.addEventListener('dragenter', this.onDragEnter);
    this.view.element.addEventListener('dragleave', this.onDragLeave);
    this.view.element.addEventListener('drop', this.onDrop);
    this.view.closeButtonElement.addEventListener(
      'click',
      this.onCloseButtonClick
    );

    // fetch realpath and repository
    this.fetchRealpath();
    this.fetchRepo();
  }

  getItemPath() {
    return typeof this.item.getPath === 'function'
      ? this.item.getPath()
      : undefined;
  }

  fetchRealpath() {
    if (!this.path) {
      return;
    }
    fs.realpath(this.path, {}, (error, realpath) => {
      if (error || this.destoyed) {
        return;
      }
      this.realpath = realpath;
      if (this.path !== this.realpath) {
        this.updateStatus();
      }
    });
  }

  fetchRepo() {
    // discard old repo
    if (this.repo || this.repoSub) {
      this.repoSub.dispose();
      this.repoSub = null;
      this.repo    = null;
    }
    // get new repo
    if (!this.path) {
      return;
    }
    const directories = atom.project.getDirectories();
    for (const directory of directories) {
      if (directory.contains(this.path)) {
        atom.project.repositoryForDirectory(directory).then(repo => {
          if (this.destoyed) {
            return;
          }
          if (!repo) {
            this.updateStatus();
            return;
          }
          this.repo = repo;
          this.updateStatus();
          // repository observation
          this.repoSub = new CompositeDisposable();
          this.repoSub.add(repo.onDidChangeStatus(event => {
            if (event.path === this.path || event.path === this.realpath) {
              this.updateStatus();
            }
          }));
          this.repoSub.add(repo.onDidChangeStatuses(() => {
            this.updateStatus();
          }));
        });
        return;
      }
    }
  }

  setIndex(index) {
    if (index !== this.index) {
      this.view.resetTooltip();
    }
    this.index = index;
  }

  setActive(active) {
    this.view.setActive(active);
  }

  setPending(pending) {
    this.pending = pending;
    this.view.setPending(this.pending);
    this.view.setVisibility(!this.pending || this.showPending);
  }

  updateTitle() {
    const title = typeof this.item.getLongTitle === 'function'
      ? this.item.getLongTitle()
      : typeof this.item.getTitle === 'function'
        ? this.item.getTitle()
        : 'Unknown';
    this.view.setTitle(title);
  }

  updatePath() {
    if (this.path) {
      this.view.setName(path.basename(this.path));
      this.view.setPath(this.path);
    }
    else {
      this.view.setName(undefined);
      this.view.setPath(undefined);
    }
  }

  updateIcon() {
    if (typeof this.item.getIconName === 'function') {
      this.view.setIconClass([`icon-${this.item.getIconName()}`]);
    }
    else {
      if (this.path) {
        const iconClass = FileIcons.getIconClassForPath(this.path);
        if (Array.isArray(iconClass)) {
          this.view.setIconClass(iconClass);
        }
        else {
          this.view.setIconClass(iconClass.toString().split(/\s+/));
        }
      }
      else {
        this.view.setIconClass(['icon-file']);
      }
    }
  }

  updateModified() {
    if (typeof this.item.isModified === 'function') {
      this.view.setModified(this.item.isModified());
    }
    else {
      this.view.setModified(false);
    }
  }

  updateStatus() {
    if (this.showStatus) {
      if (this.repo) {
        if (this.repo.isPathIgnored(this.path)) {
          this.view.setStatus('status-ignored');
        }
        else {
          const status = this.repo.getCachedPathStatus(this.path);
          if (this.repo.isStatusModified(status)) {
            this.view.setStatus('status-modified');
          }
          else if (this.repo.isStatusNew(status)) {
            this.view.setStatus('status-added');
          }
          else {
            this.view.setStatus(undefined);
          }
        }
      }
      else {
        this.view.setStatus(undefined);
      }
    }
    else {
      this.view.setStatus(undefined);
    }
  }

  copyItem() {
    if (typeof this.item.copy === 'function') {
      return [this.item.copy()];
    }
    else if (this.parent.pane.deserializerManager
      && typeof this.item.serialize === 'function') {
      return [
        this.parent.pane.deserializerManager.deserialize(this.item.serialize())
      ];
    }
    else {
      return [];
    }
  }

  destroy() {
    this.itemSub.dispose();
    if (this.repoSub) {
      this.repoSub.dispose();
    }
    this.configSub.dispose();
    this.commandsSub.dispose();
    this.view.element.removeEventListener('click', this.onClick);
    this.view.element.removeEventListener('dragstart', this.onDragStart);
    this.view.element.removeEventListener('dragover', this.onDragOver);
    this.view.element.removeEventListener('dragenter', this.onDragEnter);
    this.view.element.removeEventListener('dragleave', this.onDragLeave);
    this.view.element.removeEventListener('drop', this.onDrop);
    this.view.closeButtonElement.removeEventListener(
      'click',
      this.onCloseButtonClick
    );

    this.view.destroy();

    this.destoyed = true;
  }
}
<|endoftext|>


<commit_before>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version).to.exist;
        expect(npmPackage.version).to.exist;

        if (!expect(ioPackage.common.version).to.be.equal(npmPackage.version)) {
            console.log('ERROR: Version numbers in package.json and io-package.json differ!!');
        }

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
        }

        expect(ioPackage.common.authors).to.exist;
        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length).to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0]).to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors).to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('Testing for set authors field in io-package skipped because template adapter');
        }
        done();
    });
});
<commit_msg>update basic package-file testing<commit_after>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        expect(fileContentReadme.indexOf('## License'), 'The README.md needs to have a section ## License').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## Changelog').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## License').to.be.below(fileContentReadme.indexOf('## License'));
        done();
    });
});
<|endoftext|>


<commit_before>'use strict'

const logger = require('../logger')
const moment = require('moment')

/**
 * Remamps JSON data to reflect user visible names and also removes some of internal data
 * that are a part of JIRA JSON data by default
 * @param jiraFieldDefinitions definitions of JIRA fields
 */
const fieldNamesAndValues = function(issues, fieldDefinitions) {

  logger.debug(`Going to normalize field names for ${issues.length} issues`)
  issues.forEach(issue => {

    fieldDefinitions.forEach(field => {
      // check if this jira has field with current id and replace it with field name
      if(issue.fields && issue.fields[field.id] !== undefined) {
        const value = extractValueFromField(field, issue.fields[field.id])
        issue[field.name] = value
        delete issue.fields[field.id]
      }
    })

    // delete issue.fields object - it should be empty at this point
    if(issue.fields && Object.getOwnPropertyNames(issue.fields).length === 0) {
      delete issue.fields
    }

    delete issue.expand
  })

  logger.debug(`All issues ${issues.length} have now their fields altered`)
  return issues
}

const isSchemaTyped = function(fieldSchema) {

  if(!fieldSchema || !!!fieldSchema.schema || !fieldSchema.schema.type) {
    if(fieldSchema && (fieldSchema.id == 'issuekey' || fieldSchema.id === 'thumbnail')) {
      // this is expected, not to produce log message
      return false
    }
    logger.warn(`Unknown field schema ${JSON.stringify(fieldSchema, null, 2)}, passing original value as is`)
    return false
  }
  return true
}

const extractValueFromField = function(fieldSchema, value) {

  if(!isSchemaTyped(fieldSchema)) {
    return value
  }

  switch(fieldSchema.schema.type) {
    case 'user':
      return value ? value.displayName : null
    case 'array':
      return value ? value.map(v => {
        return extractValueFromField( {
          schema: {
            type: fieldSchema.schema.items
          }
        }, v)
      }) : []
    case 'datetime':
    case 'date':
        return value ? moment.parseZone(value) : null
    case 'project':
    case 'priority':
    case 'status':
    case 'resolution':
    case 'issuetype':
    case 'component':
    case 'version':
      return value ? value.name : null
    case 'issuelinks':
      return value ? (() => {
        // figure out what kind of issuelink we are processing
        let link
        if(!!!value.inwardIssue && !!!value.outwardIssue) {
          link = value
        }
        else {
          link = value.inwardIssue ? value.inwardIssue : value.outwardIssue
        }
        return link ? link.key : null
      })() : null
    default:
      return value ? value : null
  }
}

const extractValueFromString = function(fieldSchema, value) {

  if(!isSchemaTyped(fieldSchema)) {
    return value
  }

  switch(fieldSchema.schema.type) {
    case 'user':
      return value ? value : null
    case 'array':
      return value ? value.split(',').map(v => {
        return extractValueFromString( {
          schema: {
            type: fieldSchema.schema.items
          }
        }, v.trim())
      }) : []
    case 'datetime':
    case 'date':
          return value ? moment.parseZone(value) : null
    case 'project':
      return value ? value : null
    case 'priority':
    case 'status':
    case 'resolution':
    case 'issuetype':
    case 'component':
    case 'version':
      return value ? value : null
    case 'issuelinks':
      // link is represented in full text, such as This issue follows up on ABC-XYZ. Extract just the key
      return value ? value.split(' ').pop() : null
    default:
      return value ? value : null
  }

}

const describeFields = function(fieldDefinitions) {

  const describeField = function(fieldSchema) {
    if(!isSchemaTyped(fieldSchema)) {
      return ['text', 'Unknown description']
    }

    switch(fieldSchema.schema.type) {
      case 'user':
        return ['text', 'Real user name']
      case 'array':
        const desc =  ['array of '].concat(
          describeField({
            schema: {
              type: fieldSchema.schema.items
            }
          })
        )
        return [desc[0] + desc[1], desc[2]]
      case 'datetime':
        return ['datetime', 'Date time value, such as YYYY-MM-DD HH:MM']
      case 'date':
        return ['date', 'Date value, such as YYYY-MM-DD']
      case 'project':
        return ['text', 'Project key in JIRA']
      case 'priority':
        return ['text', 'Proct priority']
      case 'status':
        return ['text', 'Status of the issue']
      case 'resolution':
        return ['text', 'Resolution of the issue']
      case 'issuetype':
        return ['text', 'Type of issue']
      case 'component':
        return ['text', 'Component associated with the issue']
      case 'version':
        return ['text', 'Version associated with the issue']
      case 'issuelinks':
        return ['text', 'Keys of linked issue, such as PROJECT-123']
      default:
        return ['text', 'Unknown description']
    }
  }

  return fieldDefinitions.reduce((acc, field) => {
    acc.push([field.name].concat(describeField(field)))
    return acc
  }, [])
}

module.exports = {
  fieldNamesAndValues,
  extractValueFromField,
  extractValueFromString,
  describeFields
}
<commit_msg>Updated to store issue link type in DB<commit_after>'use strict'

const logger = require('../logger')
const moment = require('moment')

/**
 * Remamps JSON data to reflect user visible names and also removes some of internal data
 * that are a part of JIRA JSON data by default
 * @param jiraFieldDefinitions definitions of JIRA fields
 */
const fieldNamesAndValues = function(issues, fieldDefinitions) {

  logger.debug(`Going to normalize field names for ${issues.length} issues`)
  issues.forEach(issue => {

    fieldDefinitions.forEach(field => {
      // check if this jira has field with current id and replace it with field name
      if(issue.fields && issue.fields[field.id] !== undefined) {
        const value = extractValueFromField(field, issue.fields[field.id])
        issue[field.name] = value
        delete issue.fields[field.id]
      }
    })

    // delete issue.fields object - it should be empty at this point
    if(issue.fields && Object.getOwnPropertyNames(issue.fields).length === 0) {
      delete issue.fields
    }

    delete issue.expand
  })

  logger.debug(`All issues ${issues.length} have now their fields altered`)
  return issues
}

const isSchemaTyped = function(fieldSchema) {

  if(!fieldSchema || !!!fieldSchema.schema || !fieldSchema.schema.type) {
    if(fieldSchema && (fieldSchema.id == 'issuekey' || fieldSchema.id === 'thumbnail')) {
      // this is expected, not to produce log message
      return false
    }
    logger.warn(`Unknown field schema ${JSON.stringify(fieldSchema, null, 2)}, passing original value as is`)
    return false
  }
  return true
}

const extractValueFromField = function(fieldSchema, value) {

  if(!isSchemaTyped(fieldSchema)) {
    return value
  }

  switch(fieldSchema.schema.type) {
    case 'user':
      return value ? value.displayName : null
    case 'array':
      return value ? value.map(v => {
        return extractValueFromField( {
          schema: {
            type: fieldSchema.schema.items
          }
        }, v)
      }) : []
    case 'datetime':
    case 'date':
        return value ? moment.parseZone(value) : null
    case 'project':
    case 'priority':
    case 'status':
    case 'resolution':
    case 'issuetype':
    case 'component':
    case 'version':
      return value ? value.name : null
    case 'issuelinks':
      return value ? (() => {
        // figure out what kind of issuelink we are processing
        let link
        if(!!!value.inwardIssue && !!!value.outwardIssue) {
          link = value
        }
        else {
          link = value.inwardIssue ? value.inwardIssue : value.outwardIssue
        }
        return link ? {key: link.key, type: value.type ? value.type.name : null } : null
      })() : null
    default:
      return value ? value : null
  }
}

const extractValueFromString = function(fieldSchema, value) {

  if(!isSchemaTyped(fieldSchema)) {
    return value
  }

  switch(fieldSchema.schema.type) {
    case 'user':
      return value ? value : null
    case 'array':
      return value ? value.split(',').map(v => {
        return extractValueFromString( {
          schema: {
            type: fieldSchema.schema.items
          }
        }, v.trim())
      }) : []
    case 'datetime':
    case 'date':
          return value ? moment.parseZone(value) : null
    case 'project':
      return value ? value : null
    case 'priority':
    case 'status':
    case 'resolution':
    case 'issuetype':
    case 'component':
    case 'version':
      return value ? value : null
    case 'issuelinks':
      if(!value) {
        return null
      }
      const parsed = value.split(' ')
      return {
        key: parsed.shift(),
        type: parsed.join(' ')
      }
    default:
      return value ? value : null
  }

}

const describeFields = function(fieldDefinitions) {

  const describeField = function(fieldSchema) {
    if(!isSchemaTyped(fieldSchema)) {
      return ['text', 'Unknown description']
    }

    switch(fieldSchema.schema.type) {
      case 'user':
        return ['text', 'Real user name']
      case 'array':
        const desc =  ['array of '].concat(
          describeField({
            schema: {
              type: fieldSchema.schema.items
            }
          })
        )
        return [desc[0] + desc[1], desc[2]]
      case 'datetime':
        return ['datetime', 'Date time value, such as YYYY-MM-DD HH:MM']
      case 'date':
        return ['date', 'Date value, such as YYYY-MM-DD']
      case 'project':
        return ['text', 'Project key in JIRA']
      case 'priority':
        return ['text', 'Proct priority']
      case 'status':
        return ['text', 'Status of the issue']
      case 'resolution':
        return ['text', 'Resolution of the issue']
      case 'issuetype':
        return ['text', 'Type of issue']
      case 'component':
        return ['text', 'Component associated with the issue']
      case 'version':
        return ['text', 'Version associated with the issue']
      case 'issuelinks':
        return ['key, type', 'Issue key associated with the link and type of link, such as Duplicate']
      default:
        return ['text', 'Unknown description']
    }
  }

  return fieldDefinitions.reduce((acc, field) => {
    acc.push([field.name].concat(describeField(field)))
    return acc
  }, [])
}

module.exports = {
  fieldNamesAndValues,
  extractValueFromField,
  extractValueFromString,
  describeFields
}
<|endoftext|>


<commit_before>
var key = "";
var challenge = "";
var count = 0;
var isEntered = false;
var cResponse = "";
var vowels = "AEIOU";
var siteNames = ['google', 'facebook', 'youtube', 'baidu', 'yahoo', 'amazon', 'wikipedia', 'qq', 'twitter', 'google', 'taobao', 'live', 'sina', 'linkedin', 'yahoo', 'weibo', 'ebay', 'google', 'yandex', 'hao123', 'vk', 'bing', 'google', 'msn', 'instagram', 'amazon', 'aliexpress', 'google', 'apple', 'blogspot', 'pinterest', 'ask', 'wordpress', 'tmall', 'google', 'reddit', 'google', 'mail', 'paypal', 'onclickads', 'tumblr', 'sohu', 'google', 'imgur', 'microsoft',  'google', 'google', 'imdb', 'gmw', 'netflix', 'fc2', 'amazon', '360', 'googleadservices', 'go', 'alibaba', 'stackoverflow', 'google', 'google', 'craigslist', 'ok', 'google', 'tianya', 'rakuten', 'amazon', 'blogger', 'naver', 'espn', 'google', 'soso', 'cnn', 'outbrain', 'nicovideo', 'kat', 'google', 'dropbox', 'bbc', 'flipkart', 'github', 'diply', 'googleusercontent', 'adcash', 'xinhuanet', 'amazon', 'google', 'google', 'ebay', 'google', 'popads', 'dailymotion', 'pixnet', 'nytimes', 'ebay', 'sogou', 'booking', 'bbc', 'jd', '163', 'dailymail', 'livedoor', 'adobe', 'wikia', 'adnetworkperformance', 'chase', 'china', 'indiatimes', 'uol', 'china', 'coccoc', 'huffingtonpost', 'google', 'alipay', 'directrev', 'buzzfeed', 'dmm', 'youku', 'google', 'amazon', 'cntv', 'blogspot', 'google', 'google', 'ameblo', 'google', 'amazon', 'microsoftonline', 'theguardian', 'amazonaws', 'bankofamerica', 'google', 'chinadaily', 'walmart', 'slideshare', 'cnet', 'etsy', 'daum', 'yelp', 'ettoday', 'globo', 'twitch', 'tudou', 'stackexchange', 'aol', 'quora', 'whatsapp', 'indeed', 'flickr', 'weather', 'google', 'tradeadexchange', 'office', 'amazon', 'naver', 'redtube', 'soundcloud', 'adf', 'ilividnewtab', 'snapdeal', 'reimageplus', 'bp', 'tubecup', 'forbes', 'wellsfargo', 'douban', 'zillow', 'office365', 'google', 'vice', 'gmail', 'leboncoin', 'google', 'godaddy', 'ikea', 'salesforce', 'vimeo', 'google', 'kakaku', 'detail', 'target', 'goo', 'about', 'tripadvisor', 'livejournal', 'avito', 'bestbuy', 'allegro', 'foxnews', 'wordpress', 'feedly', 'theladbible', 'themeforest', 'adplxmd', 'deviantart', '9gag', 'w3schools', 'nfl', 'washingtonpost', 'nih', 'wikihow', 'doublepimp', 'files', 'businessinsider', 'google', 'skype', 'gfycat', 'trackingclick', 'taboola', 'telegraph', 'softonic', 'google', 'avg', 'mozilla', 'nametests', 'mediafire', 'onet', 'americanexpress', 'pixiv', 'mystart', 'zol', 'ups', 'google', 'people', 'wix', 'amazon', 'hclips', 'homedepot', 'archive', 'doorblog', 'huanqiu', 'weebly', 'google', 'secureserver', 'usps', 'google', 'comcast', 'akamaihd', 'force', 'steamcommunity', 'wikimedia', 'bitauto', 'zhihu', 'addthis', 'ndtv', 'google', 'google', 'ebay-kleinanzeigen', 'mercadolivre', 'shutterstock', 'gamer', 'loading-delivery2', 'terrapops', 'xywy', 'detik', 'ifeng', 'web', 'bilibili', 'tlbb8', 'google', 'popcash', 'github', 'bild', 'usatoday', 'mailchimp', 'steampowered', 'sourceforge', 'orange', 'answers', 'hdfcbank', 'uptodown', 'fbcdn', 'gmx', 'xfinity', 'speedtest', 'dmm', 'varzesh3', 'google', 'webmd', 'wordreference', 'pconline', 'google', 'att', 'hootsuite', 'rambler', 'groupon', 'stumbleupon', 'terraclicks', 'goodreads', 'life', 'spiegel', 'bloomberg', 'wp', 'livejasmin', 'capitalone', 'icicibank', 'blog', 'youm7', 'google', 'caijing', 't-online', 'fedex', 'google', 'engadget', 'haiwainet', 'amazon', 'mashable', 'thesaurus', 'adidas', 'spotify', 'blogfa', 'nownews', '2ch', 'samsung', 'wsj', 'xuite', 'accuweather', 'watsons', 'pandora', 'ign', 'udn', 'gsmarena', 'mama', 'google', 'spaceshipads', 'bet365', 'seznam', 'paytm', 'chaoshi', 'badoo', 'media', 'verizonwireless', 'styletv', 'mlb', 'extratorrent', 'hulu', 'youth', 'ebay', 'abs-cbnnews', 'google', 'reuters', '1905', 'dell', 'chaturbate', 'livedoor', 'kaskus', 'zendesk', 'google', 'rediff', '39', 'bleacherreport', '1688', 'ijreview', 'trello', 'putlocker', 'twimg', 'likes', 'oeeee', 'onlinesbi', 'tistory', 'reference', 'jabong', 'rt', 'google', 'sahibinden', 'smzdm', 'mydomainadvisor', 'google', 'quikr', 'iqiyi', 'icloud', 'milliyet', 'impress', 'mega', 'yaolan', 'warmportrait', 'ask', 'macys', 'google', 'rutracker', 'evernote', 'infusionsoft', 'enet', 'google', 'haosou', 'theverge', 'baike', 'kickstarter', 'cbssports', 'slickdeals', 'google', 'kouclo', 'ce', 'lady8844', 'thefreedictionary', 'kohls', 'eksisozluk', 'ebay', 'liveinternet', 'oracle', 'google', 'babytree', 'tube8', 'gameforge', 'google', 'ebay', 'hurriyet', '4shared', 'ppomppu', 'elpais', 'meetup', 'repubblica', 'chinatimes', 'blogimg', 'ewt', 'taleo', 'teepr', 'goal', 'scribd', 'libero', 'newegg', 'photobucket', 'gizmodo', 'list-manage', 'eastday', 'lifehacker', 'marca', 'olx', 'yandex', 'sberbank', 'neobux', 'buzzfil', 'qunar', 'google', 'ltn', 'livedoor', 'onedio', 'slack', 'citi', 'uploaded', 'ameba', 'stockstar', 'vid', 'time', 'torrentz', 'fiverr', 'naukri', 'cloudfront', 'espncricinfo', 'lowes', 'kompas', 'gap', 'aparat', 'free', 'cnzz', 'xe', 'disqus', 'techcrunch', 'independent', '4dsply', 'xda-developers', 'retailmenot', 'pinimg', 'savefrom', 'liputan6', 'hotels', 'hm', 'admtpmp127', 'kinopoisk', 'battle', 'justdial', 'nbcnews', 'youboy', 'bhaskar', 'nordstrom', 'shopclues', 'mobile', 'gmarket', 'nyaa', 'timeanddate', 'surveymonkey', 'gamefaqs', 'autohome', 'zippyshare', 'lenovo', 'corriere', 'wunderground', 'rbc', 'expedia', 'albawabhnews', 'tabelog', 'freegameszonetab', 'google'];

function checker() {
    if(key == "") {
        alert("Make sure to submit your key!");
        return;
    }
    animate();
}
function animate() {
  cTime = 0;
  boldChallengeChar(0);
  for(x = 0; x < challenge.length; x++) {
    index = key.indexOf(challenge.substring(x,x+1));

    if( index != -1) {

      resultIndex = findNextLetterIndex(index+1,key);
      (function(cTime,x) {
          setTimeout(
            function() { boldChallengeChar(x); },
            1000 * (cTime)
         );
      })(cTime,x);

      animateKey(resultIndex,cTime);
      cTime += resultIndex+1;
    }
  }
}
function animateKey(index,pause) {

  for (z = 0; z < index; z++) {
    (function(z,pause) {
        setTimeout(
           function() {italicsKeyChar(z)},
           1000 * (z + pause)
       );
    })(z,pause);
  }

(function(index,pause) {
        setTimeout(
            function() { boldKeyChar(index); },
           1000 * (index+ pause)
        );
    })(index,pause);
}
function findNextLetterIndex(index,key) {
  var isFound = false;
  while(!isFound) {
    if (index >= key.length) {
      index = 0;
      }
    if (vowels.indexOf(key.substring(index,index+1)) != -1) {
      index +=1;
      if (index >= key.length) {
      index = 0;
      }
    } else {
      isFound = true
    }
  }
  return index
}
function italicsKeyChar(i) {
  w4 = key.substring(0,i);
  w4 += key.substring(i,i+1).italics();
  w4 += key.substring(i+1,key.length);
  document.getElementById("keyData").innerHTML = w4;
}
function boldKeyChar(i) {
  w3 = key.substring(0,i);
  w3 += key.substring(i,i+1).bold();
  w3 += key.substring(i+1,key.length);
  document.getElementById("keyData").innerHTML = w3;
}
function boldChallengeChar(i) {
  w2 = challenge.substring(0,i);
    w2 += challenge.substring(i,i+1).bold();
    w2 += challenge.substring(i+1,challenge.length);
    document.getElementById("challengeData").innerHTML = w2;
}
function emailUs() {
    window.open('mailto:test@gatech.edu');
}
function findNextLetter(index,key) {
  var isFound = false;
  while(!isFound) {

    if (index >= key.length - 1) {
      index = 0;
      }

    if (vowels.indexOf(key.substring(index,index+1)) != -1) {
      index +=1;
      if (index >= key.length - 1) {
      index = 0;
      }
    } else {
      isFound = true
    }
  }
  return key.substring(index,index+1);
}
function findResponseLength(challenge,key) {
  for (i = 0; i < challenge.length; i++) {
    var index = key.indexOf(challenge.substring(i,i+1));
    if( index != -1) {
      count +=1;
      cResponse += findNextLetter(index+1,key);
    }
  }
  return count;
}
function getChallenge(){
    var index = Math.floor((Math.random() * siteNames.length - 1));
    var challenges = siteNames[index].toUpperCase();
    var text = document.createElement('p');
    text.innerHTML = "The challenge is " + challenges +"";
    document.getElementById("challengeDiv").appendChild(text);
    challenge = challenges;

}

function respond() {
  key = document.getElementById("firstWord").value + document.getElementById("secondWord").value + document.getElementById("thirdWord").value;
  key = key.toUpperCase();
  if(key == "") {
      alert("Please enter words");
      return;
  }
  if (!isEntered) {
    count = findResponseLength(challenge,key);
    cResponse += "aB7!";
    //Change to one text box
    //make sure to read from the changed input field
    //
    var textbox = document.createElement('input');
    textbox.type = 'text';
    textbox.id = ("inputBox");
    textbox.class = "form-control";
    document.getElementById('checks').appendChild(textbox);

    isEntered = true;
    document.getElementById('bt').innerHTML = "Click to verify";
  } else {
    var uResponse = "";

     uResponse +=  document.getElementById(("inputBox")).value.toUpperCase();

    if(uResponse == cResponse) {
      alert("correct");
      document.getElementById(("inputBox")).remove();
      document.getElementById('bt').innerHTML = "Ready?";
        count = 0;
        isEntered = false;
        cResponse = "";
        getChallenge();

    } else {
      alert("looking for " + cResponse + " your response was " + uResponse);
    }

  }

}
<commit_msg>fixed checking code<commit_after>
var key = "";
var challenge = "";
var count = 0;
var isEntered = false;
var cResponse = "";
var vowels = "AEIOU";
var siteNames = ['google', 'facebook', 'youtube', 'baidu', 'yahoo', 'amazon', 'wikipedia', 'qq', 'twitter', 'google', 'taobao', 'live', 'sina', 'linkedin', 'yahoo', 'weibo', 'ebay', 'google', 'yandex', 'hao123', 'vk', 'bing', 'google', 'msn', 'instagram', 'amazon', 'aliexpress', 'google', 'apple', 'blogspot', 'pinterest', 'ask', 'wordpress', 'tmall', 'google', 'reddit', 'google', 'mail', 'paypal', 'onclickads', 'tumblr', 'sohu', 'google', 'imgur', 'microsoft',  'google', 'google', 'imdb', 'gmw', 'netflix', 'fc2', 'amazon', '360', 'googleadservices', 'go', 'alibaba', 'stackoverflow', 'google', 'google', 'craigslist', 'ok', 'google', 'tianya', 'rakuten', 'amazon', 'blogger', 'naver', 'espn', 'google', 'soso', 'cnn', 'outbrain', 'nicovideo', 'kat', 'google', 'dropbox', 'bbc', 'flipkart', 'github', 'diply', 'googleusercontent', 'adcash', 'xinhuanet', 'amazon', 'google', 'google', 'ebay', 'google', 'popads', 'dailymotion', 'pixnet', 'nytimes', 'ebay', 'sogou', 'booking', 'bbc', 'jd', '163', 'dailymail', 'livedoor', 'adobe', 'wikia', 'adnetworkperformance', 'chase', 'china', 'indiatimes', 'uol', 'china', 'coccoc', 'huffingtonpost', 'google', 'alipay', 'directrev', 'buzzfeed', 'dmm', 'youku', 'google', 'amazon', 'cntv', 'blogspot', 'google', 'google', 'ameblo', 'google', 'amazon', 'microsoftonline', 'theguardian', 'amazonaws', 'bankofamerica', 'google', 'chinadaily', 'walmart', 'slideshare', 'cnet', 'etsy', 'daum', 'yelp', 'ettoday', 'globo', 'twitch', 'tudou', 'stackexchange', 'aol', 'quora', 'whatsapp', 'indeed', 'flickr', 'weather', 'google', 'tradeadexchange', 'office', 'amazon', 'naver', 'redtube', 'soundcloud', 'adf', 'ilividnewtab', 'snapdeal', 'reimageplus', 'bp', 'tubecup', 'forbes', 'wellsfargo', 'douban', 'zillow', 'office365', 'google', 'vice', 'gmail', 'leboncoin', 'google', 'godaddy', 'ikea', 'salesforce', 'vimeo', 'google', 'kakaku', 'detail', 'target', 'goo', 'about', 'tripadvisor', 'livejournal', 'avito', 'bestbuy', 'allegro', 'foxnews', 'wordpress', 'feedly', 'theladbible', 'themeforest', 'adplxmd', 'deviantart', '9gag', 'w3schools', 'nfl', 'washingtonpost', 'nih', 'wikihow', 'doublepimp', 'files', 'businessinsider', 'google', 'skype', 'gfycat', 'trackingclick', 'taboola', 'telegraph', 'softonic', 'google', 'avg', 'mozilla', 'nametests', 'mediafire', 'onet', 'americanexpress', 'pixiv', 'mystart', 'zol', 'ups', 'google', 'people', 'wix', 'amazon', 'hclips', 'homedepot', 'archive', 'doorblog', 'huanqiu', 'weebly', 'google', 'secureserver', 'usps', 'google', 'comcast', 'akamaihd', 'force', 'steamcommunity', 'wikimedia', 'bitauto', 'zhihu', 'addthis', 'ndtv', 'google', 'google', 'ebay-kleinanzeigen', 'mercadolivre', 'shutterstock', 'gamer', 'loading-delivery2', 'terrapops', 'xywy', 'detik', 'ifeng', 'web', 'bilibili', 'tlbb8', 'google', 'popcash', 'github', 'bild', 'usatoday', 'mailchimp', 'steampowered', 'sourceforge', 'orange', 'answers', 'hdfcbank', 'uptodown', 'fbcdn', 'gmx', 'xfinity', 'speedtest', 'dmm', 'varzesh3', 'google', 'webmd', 'wordreference', 'pconline', 'google', 'att', 'hootsuite', 'rambler', 'groupon', 'stumbleupon', 'terraclicks', 'goodreads', 'life', 'spiegel', 'bloomberg', 'wp', 'livejasmin', 'capitalone', 'icicibank', 'blog', 'youm7', 'google', 'caijing', 't-online', 'fedex', 'google', 'engadget', 'haiwainet', 'amazon', 'mashable', 'thesaurus', 'adidas', 'spotify', 'blogfa', 'nownews', '2ch', 'samsung', 'wsj', 'xuite', 'accuweather', 'watsons', 'pandora', 'ign', 'udn', 'gsmarena', 'mama', 'google', 'spaceshipads', 'bet365', 'seznam', 'paytm', 'chaoshi', 'badoo', 'media', 'verizonwireless', 'styletv', 'mlb', 'extratorrent', 'hulu', 'youth', 'ebay', 'abs-cbnnews', 'google', 'reuters', '1905', 'dell', 'chaturbate', 'livedoor', 'kaskus', 'zendesk', 'google', 'rediff', '39', 'bleacherreport', '1688', 'ijreview', 'trello', 'putlocker', 'twimg', 'likes', 'oeeee', 'onlinesbi', 'tistory', 'reference', 'jabong', 'rt', 'google', 'sahibinden', 'smzdm', 'mydomainadvisor', 'google', 'quikr', 'iqiyi', 'icloud', 'milliyet', 'impress', 'mega', 'yaolan', 'warmportrait', 'ask', 'macys', 'google', 'rutracker', 'evernote', 'infusionsoft', 'enet', 'google', 'haosou', 'theverge', 'baike', 'kickstarter', 'cbssports', 'slickdeals', 'google', 'kouclo', 'ce', 'lady8844', 'thefreedictionary', 'kohls', 'eksisozluk', 'ebay', 'liveinternet', 'oracle', 'google', 'babytree', 'tube8', 'gameforge', 'google', 'ebay', 'hurriyet', '4shared', 'ppomppu', 'elpais', 'meetup', 'repubblica', 'chinatimes', 'blogimg', 'ewt', 'taleo', 'teepr', 'goal', 'scribd', 'libero', 'newegg', 'photobucket', 'gizmodo', 'list-manage', 'eastday', 'lifehacker', 'marca', 'olx', 'yandex', 'sberbank', 'neobux', 'buzzfil', 'qunar', 'google', 'ltn', 'livedoor', 'onedio', 'slack', 'citi', 'uploaded', 'ameba', 'stockstar', 'vid', 'time', 'torrentz', 'fiverr', 'naukri', 'cloudfront', 'espncricinfo', 'lowes', 'kompas', 'gap', 'aparat', 'free', 'cnzz', 'xe', 'disqus', 'techcrunch', 'independent', '4dsply', 'xda-developers', 'retailmenot', 'pinimg', 'savefrom', 'liputan6', 'hotels', 'hm', 'admtpmp127', 'kinopoisk', 'battle', 'justdial', 'nbcnews', 'youboy', 'bhaskar', 'nordstrom', 'shopclues', 'mobile', 'gmarket', 'nyaa', 'timeanddate', 'surveymonkey', 'gamefaqs', 'autohome', 'zippyshare', 'lenovo', 'corriere', 'wunderground', 'rbc', 'expedia', 'albawabhnews', 'tabelog', 'freegameszonetab', 'google'];

function checker() {
    if(key == "") {
        alert("Make sure to submit your key!");
        return;
    }
    animate();
}
function animate() {
  cTime = 0;
  boldChallengeChar(0);
  for(x = 0; x < challenge.length; x++) {
    index = key.indexOf(challenge.substring(x,x+1));

    if( index != -1) {

      resultIndex = findNextLetterIndex(index+1,key);
      (function(cTime,x) {
          setTimeout(
            function() { boldChallengeChar(x); },
            1000 * (cTime)
         );
      })(cTime,x);

      animateKey(resultIndex,cTime);
      cTime += resultIndex+1;
    }
  }
}
function animateKey(index,pause) {

  for (z = 0; z < index; z++) {
    (function(z,pause) {
        setTimeout(
           function() {italicsKeyChar(z)},
           1000 * (z + pause)
       );
    })(z,pause);
  }

(function(index,pause) {
        setTimeout(
            function() { boldKeyChar(index); },
           1000 * (index+ pause)
        );
    })(index,pause);
}
function findNextLetterIndex(index,key) {
  var isFound = false;
  while(!isFound) {
    if (index >= key.length) {
      index = 0;
      }
    if (vowels.indexOf(key.substring(index,index+1)) != -1) {
      index +=1;
      if (index >= key.length) {
      index = 0;
      }
    } else {
      isFound = true
    }
  }
  return index
}
function italicsKeyChar(i) {
  w4 = key.substring(0,i);
  w4 += key.substring(i,i+1).italics();
  w4 += key.substring(i+1,key.length);
  document.getElementById("keyData").innerHTML = w4;
}
function boldKeyChar(i) {
  w3 = key.substring(0,i);
  w3 += key.substring(i,i+1).bold();
  w3 += key.substring(i+1,key.length);
  document.getElementById("keyData").innerHTML = w3;
}
function boldChallengeChar(i) {
  w2 = challenge.substring(0,i);
    w2 += challenge.substring(i,i+1).bold();
    w2 += challenge.substring(i+1,challenge.length);
    document.getElementById("challengeData").innerHTML = w2;
}
function emailUs() {
    window.open('mailto:test@gatech.edu');
}
function findNextLetter(index,key) {
  var isFound = false;
  while(!isFound) {

    if (index >= key.length - 1) {
      index = 0;
      }

    if (vowels.indexOf(key.substring(index,index+1)) != -1) {
      index +=1;
      if (index >= key.length - 1) {
      index = 0;
      }
    } else {
      isFound = true
    }
  }
  return key.substring(index,index+1);
}
function findResponseLength(challenge,key) {
  for (i = 0; i < challenge.length; i++) {
    var index = key.indexOf(challenge.substring(i,i+1));
    if( index != -1) {
      count +=1;
      cResponse += findNextLetter(index+1,key);
    }
  }
  return count;
}
function getChallenge(){
    var index = Math.floor((Math.random() * siteNames.length - 1));
    var challenges = siteNames[index].toUpperCase();
    var text = document.createElement('p');
    text.innerHTML = "The challenge is " + challenges +"";
    document.getElementById("challengeDiv").appendChild(text);
    challenge = challenges;

}

function respond() {
  key = document.getElementById("firstWord").value + document.getElementById("secondWord").value + document.getElementById("thirdWord").value;
  key = key.toUpperCase();
  if(key == "") {
      alert("Please enter words");
      return;
  }
  if (!isEntered) {
    count = findResponseLength(challenge,key);
     cResponse+= "aB7!";
    //Change to one text box
    //make sure to read from the changed input field
    //
    var textbox = document.createElement('input');
    textbox.type = 'text';
    textbox.id = ("inputBox");
    textbox.class = "form-control";
    document.getElementById('checks').appendChild(textbox);

    isEntered = true;
    document.getElementById('bt').innerHTML = "Click to verify";
  } else {
    var uResponse = "";

     uResponse +=  document.getElementById(("inputBox")).value;

    if(uResponse == cResponse) {
      alert("correct");
      document.getElementById(("inputBox")).remove();
      document.getElementById('bt').innerHTML = "Ready?";
        count = 0;
        isEntered = false;
        cResponse = "";
        getChallenge();

    } else {
      alert("looking for " + cResponse + " your response was " + uResponse);
    }

  }

}
<|endoftext|>


<commit_before>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        if (fileContentReadme.indexOf('## License') === -1) {
            console.log('Warning: The README.md should have a section ## License');
            console.log();
        }
        if (fileContentReadme.indexOf('## Changelog') === -1) {
            console.log('Warning: The README.md should have a section ## Changelog');
            console.log();
        }
        done();
    });
});
<commit_msg>update basic package-file testing<commit_after>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        var licenseFileExists = fs.existsSync(__dirname + '/../LICENSE');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        if (fileContentReadme.indexOf('## Changelog') === -1) {
            console.log('Warning: The README.md should have a section ## Changelog');
            console.log();
        }
        expect((licenseFileExists || fileContentReadme.indexOf('## License') !== -1), 'A LICENSE must exist as LICENSE file or as part of the README.md').to.be.true;
        if (!licenseFileExists) {
            console.log('Warning: The License should also exist as LICENSE file');
            console.log();
        }
        if (fileContentReadme.indexOf('## License') === -1) {
            console.log('Warning: The README.md should also have a section ## License to be shown in Admin3');
            console.log();
        }
        done();
    });
});
<|endoftext|>


<commit_before>
var path = require('path');
var q = global.require('q');
var handlebars = global.require('handlebars');
var module_manager = require('ljswitchboard-module_manager');
var modbus_map = require('ljswitchboard-modbus_map').getConstants();
var fs = require('fs');

var EventEmitter = require('events').EventEmitter;
var util = require('util');

function createFileBrowser() {
    // var chooser = $('#file-dialog-hidden');
 //    chooser.off('change');
 //    chooser.one('change', function(evt) {
 //        var fileLoc = $(this).val();
 //        console.log('Selected File', fileLoc);
 //        self.updateSelectedFWFile(fileLoc);
 //        // $('#file-loc-input').val(fileLoc);
 //    });

 //    chooser.trigger('click');

    this.fileBrowserDialog = undefined;
    this.fileSaveDialog = undefined;

    this.eventList = {
        FILE_SELECTED: 'FILE_SELECTED',
    };
    this.initialize = function(bundle) {
        var defered = q.defer();

        self.fileBrowserDialog = $('#file-dialog-hidden');
        self.fileSaveDialog = $('#file-save-dialog-hidden');

        defered.resolve(bundle);
        return defered.promise;
    };

    var innerBrowseForFile = function() {
        self.fileBrowserDialog.off('change');
        self.fileBrowserDialog.one('change', function(evt) {
            var fileLoc = $(this).val();
            self.emit(self.eventList.FILE_SELECTED, fileLoc);
            // Reset the selected value to empty
            $(this).val('');
        });

        self.fileBrowserDialog.trigger('click');
    };
    this.browseForFile = function() {
        setTimeout(innerBrowseForFile, 1);
    };
    var self = this;
}
util.inherits(createFileBrowser, EventEmitter);

var FILE_BROWSER = new createFileBrowser();<commit_msg>Added the file-browsing option to filter visible files by file type.<commit_after>
var path = require('path');
var q = global.require('q');
var handlebars = global.require('handlebars');
var module_manager = require('ljswitchboard-module_manager');
var modbus_map = require('ljswitchboard-modbus_map').getConstants();
var fs = require('fs');

var EventEmitter = require('events').EventEmitter;
var util = require('util');

function createFileBrowser() {
    // var chooser = $('#file-dialog-hidden');
 //    chooser.off('change');
 //    chooser.one('change', function(evt) {
 //        var fileLoc = $(this).val();
 //        console.log('Selected File', fileLoc);
 //        self.updateSelectedFWFile(fileLoc);
 //        // $('#file-loc-input').val(fileLoc);
 //    });

 //    chooser.trigger('click');

    this.fileBrowserDialog = undefined;
    this.fileSaveDialog = undefined;

    this.eventList = {
        FILE_SELECTED: 'FILE_SELECTED',
    };
    this.initialize = function(bundle) {
        var defered = q.defer();

        self.fileBrowserDialog = $('#file-dialog-hidden');
        self.fileSaveDialog = $('#file-save-dialog-hidden');

        defered.resolve(bundle);
        return defered.promise;
    };

    var innerBrowseForFile = function() {
        self.fileBrowserDialog.off('change');
        self.fileBrowserDialog.one('change', function(evt) {
            var fileLoc = $(this).val();
            self.emit(self.eventList.FILE_SELECTED, fileLoc);
            // Reset the selected value to empty
            $(this).val('');
        });

        self.fileBrowserDialog.trigger('click');
    };
    this.browseForFile = function(options) {
        var fileFilters = '';
        if(options) {
            if(options.filters) {
                fileFilters = options.filters.toString();
            }
        }
        // Configuring as per:
        // https://github.com/nwjs/nw.js/wiki/File-dialogs

        // Configure file-filters
        self.fileBrowserDialog.attr('accept', fileFilters);

        setTimeout(innerBrowseForFile, 1);
    };
    var self = this;
}
util.inherits(createFileBrowser, EventEmitter);

var FILE_BROWSER = new createFileBrowser();<|endoftext|>


<commit_before>'use strict';

angular.module('pw.canvas-painter')
	.directive('pwCanvas', function () {
		return {
			restrict: 'AE',
			scope: {
				options: '=',
				version: '='
			},
			templateUrl: '../templates/canvas.html',
			link: function postLink(scope, elm) {

				var isTouch = !!('ontouchstart' in window);

				var PAINT_START = isTouch ? 'touchstart' : 'mousedown';
				var PAINT_MOVE = isTouch ? 'touchmove' : 'mousemove';
				var PAINT_END = isTouch ? 'touchend' : 'mouseup';

				//set default options
				var options = scope.options;
				options.canvasId = options.customCanvasId || 'pwCanvasMain';
				options.tmpCanvasId = options.customCanvasId ? (options.canvasId + 'Tmp') : 'pwCanvasTmp';
				options.width = options.width || 400;
				options.height = options.height || 300;
				options.backgroundColor = options.backgroundColor || '#fff';
				options.color = options.color || '#000';
				options.undoEnabled = options.undoEnabled || false;
				options.opacity = options.opacity || 0.9;
				options.lineWidth = options.lineWidth || 1;
				options.undo = options.undo || false;
				options.imageSrc = options.imageSrc || false;

				// background image
				if(options.imageSrc){
					var image = new Image();
					image.onload = function(){
						ctx.drawImage(this, 0, 0);
					};
					image.src = options.imageSrc;
				}

				//undo
				if(options.undo){
					var undoCache = [];
					scope.$watch(function(){
						return undoCache.length;
					}, function(newVal){
						scope.version = newVal;
					});

					scope.$watch('version', function(newVal){
						if(newVal < 0){
							scope.version = 0;
							return;
						}
						if(newVal >= undoCache.length){
							scope.version = undoCache.length;
							return;
						}
						undo(newVal);
					});
				}

				//create canvas and context
				var canvas = document.createElement('canvas');
				canvas.id = options.canvasId;
				var canvasTmp = document.createElement('canvas');
				canvasTmp.id = options.tmpCanvasId;
				angular.element(canvasTmp).css({
					position: 'absolute',
					top: 0,
					left: 0
				});
				elm.find('div').append(canvas);
				elm.find('div').append(canvasTmp);
				var ctx = canvas.getContext('2d');
				var ctxTmp = canvasTmp.getContext('2d');

				//inti variables
				var point = {x: 0, y: 0};
				var ppts = [];

				//set canvas size
				canvas.width = canvasTmp.width = options.width;
				canvas.height = canvasTmp.height = options.height;

				//set context style
				ctx.fillStyle = options.backgroundColor;
				ctx.fillRect(0, 0, canvas.width, canvas.height);
				ctxTmp.globalAlpha = options.opacity;
				ctxTmp.lineJoin = ctxTmp.lineCap = 'round';
				ctxTmp.lineWidth = 10;
				ctxTmp.strokeStyle = options.color;

				//Watch options
				scope.$watch('options.lineWidth', function(newValue){
					if(typeof newValue === 'string'){
						newValue = parseInt(newValue, 10);
					}
					if(newValue && typeof newValue === 'number'){
						ctxTmp.lineWidth = options.lineWidth = newValue;
					}
				});

				scope.$watch('options.color', function(newValue){
					if(newValue){
						//ctx.fillStyle = newValue;
						ctxTmp.strokeStyle = ctxTmp.fillStyle = newValue;
					}
				});

				scope.$watch('options.opacity', function(newValue){
					if(newValue){
						ctxTmp.globalAlpha = newValue;
					}
				});

				/* var clearCanvas = function(){
				 ctx.clearRect(0, 0, canvasTmp.width, canvasTmp.height);
				 ctxTmp.clearRect(0, 0, canvasTmp.width, canvasTmp.height);
				 };*/

			 var getOffset = function( elem ) {
					 var offsetTop = 0;
			     var offsetLeft = 0;
			     do {
			       if ( !isNaN( elem.offsetLeft ) )
			       {
								 offsetTop += elem.offsetTop;
			           offsetLeft += elem.offsetLeft;
			       }
						 elem = elem.offsetParent;
			     } while( elem );
			     return {
							left:offsetLeft,
						 	top: offsetTop
					 };
			 };

				var setPointFromEvent = function(point, e) {
					if(isTouch){
						point.x = e.changedTouches[0].pageX - getOffset(e.target).left;
						point.y = e.changedTouches[0].pageY - getOffset(e.target).top;
					} else {
						point.x = e.offsetX !== undefined ? e.offsetX : e.layerX;
						point.y = e.offsetY !== undefined ? e.offsetY : e.layerY;
					}
				};

				var paint = function (e){
					if(e){
						e.preventDefault();
						setPointFromEvent(point, e);
					}

					// Saving all the points in an array
					ppts.push({x: point.x, y: point.y});

					if (ppts.length === 3) {
						var b = ppts[0];
						ctxTmp.beginPath();
						ctxTmp.arc(b.x, b.y, ctxTmp.lineWidth / 2, 0, Math.PI * 2, !0);
						ctxTmp.fill();
						ctxTmp.closePath();
						return;
					}

					// Tmp canvas is always cleared up before drawing.
					ctxTmp.clearRect(0, 0, canvasTmp.width, canvasTmp.height);

					ctxTmp.beginPath();
					ctxTmp.moveTo(ppts[0].x, ppts[0].y);

					for (var i = 1; i < ppts.length - 2; i++) {
						var c = (ppts[i].x + ppts[i + 1].x) / 2;
						var d = (ppts[i].y + ppts[i + 1].y) / 2;
						ctxTmp.quadraticCurveTo(ppts[i].x, ppts[i].y, c, d);
					}

					// For the last 2 points
					ctxTmp.quadraticCurveTo(
						ppts[i].x,
						ppts[i].y,
						ppts[i + 1].x,
						ppts[i + 1].y
					);
					ctxTmp.stroke();
				};

				var copyTmpImage = function(){
					if(options.undo){
						scope.$apply(function(){
							undoCache.push(ctx.getImageData(0, 0, canvasTmp.width, canvasTmp.height));
							if(angular.isNumber(options.undo) && options.undo > 0){
								undoCache = undoCache.slice(-1 * options.undo);
							}
						});
					}
					canvasTmp.removeEventListener(PAINT_MOVE, paint, false);
					ctx.drawImage(canvasTmp, 0, 0);
					ctxTmp.clearRect(0, 0, canvasTmp.width, canvasTmp.height);
					ppts = [];
				};

				var startTmpImage = function(e){
					e.preventDefault();
					canvasTmp.addEventListener(PAINT_MOVE, paint, false);

					setPointFromEvent(point, e);
					ppts.push({x: point.x, y: point.y});
					ppts.push({x: point.x, y: point.y});

					paint();
				};

				var initListeners = function(){
					canvasTmp.addEventListener(PAINT_START, startTmpImage, false);
					canvasTmp.addEventListener('mouseenter', function(e){
						// If the mouse is down when it enters the canvas, start a path
						if(e.which === 1){
							startTmpImage(e);
						}
					}, false);
					canvasTmp.addEventListener(PAINT_END, copyTmpImage, false);
					canvasTmp.addEventListener('mouseleave', function(e){
						// If the mouse is down when it leaves the canvas, end the path
						if(e.which === 1){
							copyTmpImage(e);
						}
					}, false);
				};
				initListeners();

				var undo = function(version){
					if(undoCache.length > 0){
						ctx.putImageData(undoCache[version], 0, 0);
						undoCache = undoCache.slice(0,version);
					}
				};

			}
		};
	});
<commit_msg>Add mouseenter/mouseleave listener only when not in touch mode<commit_after>'use strict';

angular.module('pw.canvas-painter')
	.directive('pwCanvas', function () {
		return {
			restrict: 'AE',
			scope: {
				options: '=',
				version: '='
			},
			templateUrl: '../templates/canvas.html',
			link: function postLink(scope, elm) {

				var isTouch = !!('ontouchstart' in window);

				var PAINT_START = isTouch ? 'touchstart' : 'mousedown';
				var PAINT_MOVE = isTouch ? 'touchmove' : 'mousemove';
				var PAINT_END = isTouch ? 'touchend' : 'mouseup';

				//set default options
				var options = scope.options;
				options.canvasId = options.customCanvasId || 'pwCanvasMain';
				options.tmpCanvasId = options.customCanvasId ? (options.canvasId + 'Tmp') : 'pwCanvasTmp';
				options.width = options.width || 400;
				options.height = options.height || 300;
				options.backgroundColor = options.backgroundColor || '#fff';
				options.color = options.color || '#000';
				options.undoEnabled = options.undoEnabled || false;
				options.opacity = options.opacity || 0.9;
				options.lineWidth = options.lineWidth || 1;
				options.undo = options.undo || false;
				options.imageSrc = options.imageSrc || false;

				// background image
				if(options.imageSrc){
					var image = new Image();
					image.onload = function(){
						ctx.drawImage(this, 0, 0);
					};
					image.src = options.imageSrc;
				}

				//undo
				if(options.undo){
					var undoCache = [];
					scope.$watch(function(){
						return undoCache.length;
					}, function(newVal){
						scope.version = newVal;
					});

					scope.$watch('version', function(newVal){
						if(newVal < 0){
							scope.version = 0;
							return;
						}
						if(newVal >= undoCache.length){
							scope.version = undoCache.length;
							return;
						}
						undo(newVal);
					});
				}

				//create canvas and context
				var canvas = document.createElement('canvas');
				canvas.id = options.canvasId;
				var canvasTmp = document.createElement('canvas');
				canvasTmp.id = options.tmpCanvasId;
				angular.element(canvasTmp).css({
					position: 'absolute',
					top: 0,
					left: 0
				});
				elm.find('div').append(canvas);
				elm.find('div').append(canvasTmp);
				var ctx = canvas.getContext('2d');
				var ctxTmp = canvasTmp.getContext('2d');

				//inti variables
				var point = {x: 0, y: 0};
				var ppts = [];

				//set canvas size
				canvas.width = canvasTmp.width = options.width;
				canvas.height = canvasTmp.height = options.height;

				//set context style
				ctx.fillStyle = options.backgroundColor;
				ctx.fillRect(0, 0, canvas.width, canvas.height);
				ctxTmp.globalAlpha = options.opacity;
				ctxTmp.lineJoin = ctxTmp.lineCap = 'round';
				ctxTmp.lineWidth = 10;
				ctxTmp.strokeStyle = options.color;

				//Watch options
				scope.$watch('options.lineWidth', function(newValue){
					if(typeof newValue === 'string'){
						newValue = parseInt(newValue, 10);
					}
					if(newValue && typeof newValue === 'number'){
						ctxTmp.lineWidth = options.lineWidth = newValue;
					}
				});

				scope.$watch('options.color', function(newValue){
					if(newValue){
						//ctx.fillStyle = newValue;
						ctxTmp.strokeStyle = ctxTmp.fillStyle = newValue;
					}
				});

				scope.$watch('options.opacity', function(newValue){
					if(newValue){
						ctxTmp.globalAlpha = newValue;
					}
				});

				/* var clearCanvas = function(){
				 ctx.clearRect(0, 0, canvasTmp.width, canvasTmp.height);
				 ctxTmp.clearRect(0, 0, canvasTmp.width, canvasTmp.height);
				 };*/

			 var getOffset = function( elem ) {
					 var offsetTop = 0;
			     var offsetLeft = 0;
			     do {
			       if ( !isNaN( elem.offsetLeft ) )
			       {
								 offsetTop += elem.offsetTop;
			           offsetLeft += elem.offsetLeft;
			       }
						 elem = elem.offsetParent;
			     } while( elem );
			     return {
							left:offsetLeft,
						 	top: offsetTop
					 };
			 };

				var setPointFromEvent = function(point, e) {
					if(isTouch){
						point.x = e.changedTouches[0].pageX - getOffset(e.target).left;
						point.y = e.changedTouches[0].pageY - getOffset(e.target).top;
					} else {
						point.x = e.offsetX !== undefined ? e.offsetX : e.layerX;
						point.y = e.offsetY !== undefined ? e.offsetY : e.layerY;
					}
				};

				var paint = function (e){
					if(e){
						e.preventDefault();
						setPointFromEvent(point, e);
					}

					// Saving all the points in an array
					ppts.push({x: point.x, y: point.y});

					if (ppts.length === 3) {
						var b = ppts[0];
						ctxTmp.beginPath();
						ctxTmp.arc(b.x, b.y, ctxTmp.lineWidth / 2, 0, Math.PI * 2, !0);
						ctxTmp.fill();
						ctxTmp.closePath();
						return;
					}

					// Tmp canvas is always cleared up before drawing.
					ctxTmp.clearRect(0, 0, canvasTmp.width, canvasTmp.height);

					ctxTmp.beginPath();
					ctxTmp.moveTo(ppts[0].x, ppts[0].y);

					for (var i = 1; i < ppts.length - 2; i++) {
						var c = (ppts[i].x + ppts[i + 1].x) / 2;
						var d = (ppts[i].y + ppts[i + 1].y) / 2;
						ctxTmp.quadraticCurveTo(ppts[i].x, ppts[i].y, c, d);
					}

					// For the last 2 points
					ctxTmp.quadraticCurveTo(
						ppts[i].x,
						ppts[i].y,
						ppts[i + 1].x,
						ppts[i + 1].y
					);
					ctxTmp.stroke();
				};

				var copyTmpImage = function(){
					if(options.undo){
						scope.$apply(function(){
							undoCache.push(ctx.getImageData(0, 0, canvasTmp.width, canvasTmp.height));
							if(angular.isNumber(options.undo) && options.undo > 0){
								undoCache = undoCache.slice(-1 * options.undo);
							}
						});
					}
					canvasTmp.removeEventListener(PAINT_MOVE, paint, false);
					ctx.drawImage(canvasTmp, 0, 0);
					ctxTmp.clearRect(0, 0, canvasTmp.width, canvasTmp.height);
					ppts = [];
				};

				var startTmpImage = function(e){
					e.preventDefault();
					canvasTmp.addEventListener(PAINT_MOVE, paint, false);

					setPointFromEvent(point, e);
					ppts.push({x: point.x, y: point.y});
					ppts.push({x: point.x, y: point.y});

					paint();
				};

				var initListeners = function(){
					canvasTmp.addEventListener(PAINT_START, startTmpImage, false);
					canvasTmp.addEventListener(PAINT_END, copyTmpImage, false);

					if(!isTouch){
						canvasTmp.addEventListener('mouseenter', function(e){
							// If the mouse is down when it enters the canvas, start a path
							if(e.which === 1){
								startTmpImage(e);
							}
						}, false);
						canvasTmp.addEventListener('mouseleave', function(e){
							// If the mouse is down when it leaves the canvas, end the path
							if(e.which === 1){
								copyTmpImage(e);
							}
						}, false);
					}
				};
				initListeners();

				var undo = function(version){
					if(undoCache.length > 0){
						ctx.putImageData(undoCache[version], 0, 0);
						undoCache = undoCache.slice(0,version);
					}
				};

			}
		};
	});
<|endoftext|>