<commit_before>/*!
 * OS.js - JavaScript Operating System
 *
 * Copyright (c) 2011-2015, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */
(function(API, Utils, VFS, GUI) {
  'use strict';

  /////////////////////////////////////////////////////////////////////////////
  // HELPERS
  /////////////////////////////////////////////////////////////////////////////

  function getChildView(el) {
    return el.children[0];
  }

  function buildChildView(el) {
    var type = el.getAttribute('data-type') || 'list-view';
    if ( !type.match(/^gui\-/) ) {
      type = 'gui-' + type;
    }

    var nel = new GUI.ElementDataView(GUI.Helpers.createElement(type, {'draggable': true, 'draggable-type': 'file'}));
    GUI.Elements[type].build(nel.$element);

    nel.on('select', function(ev) {
      el.dispatchEvent(new CustomEvent('_select', {detail: ev.detail}));
    });
    nel.on('activate', function(ev) {
      el.dispatchEvent(new CustomEvent('_activate', {detail: ev.detail}));
    });
    nel.on('contextmenu', function(ev) {
      if ( !el.hasAttribute('data-has-contextmenu') || el.hasAttribute('data-has-contextmenu') === 'false' ) {
        new GUI.Element(el).fn('contextmenu', [ev]);
      }
      el.dispatchEvent(new CustomEvent('_contextmenu', {detail: ev.detail}));
    });

    if ( type === 'gui-list-view' ) {
      nel.set('zebra', true);
      nel.set('columns', [
        {label: API._('LBL_FILENAME'), grow: 1, shrink: 1},
        {label: API._('LBL_MIME'), basis: '100px', grow: 0, shrink: 0, textalign: 'right'},
        {label: API._('LBL_SIZE'), basis: '120px', grow: 0, shrink: 0, textalign: 'right'}
      ]);
    } else if ( type === 'gui-tree-view' ) {
      nel.on('expand', function(ev) {
        el.dispatchEvent(new CustomEvent('_expand', {detail: ev.detail}));
      });
    }

    el.appendChild(nel.$element);
  }

  function scandir(tagName, dir, opts, cb, oncreate) {
    var file = new VFS.File(dir);
    file.type  = 'dir';

    var scanopts = {
      backlink:           opts.backlink,
      showDotFiles:       opts.dotfiles === true,
      showFileExtensions: opts.extensions === true,
      mimeFilter:         opts.filter || [],
      typeFilter:         opts.filetype || null
    };

    VFS.scandir(file, function(error, result) {
      if ( error ) { cb(error); return; }

      var list = [];
      var summary = {size: 0, directories: 0, files: 0, hidden: 0};

      function isHidden(iter) {
        return (iter.filename || '').substr(0) === '.';
      }

      (result || []).forEach(function(iter) {
        list.push(oncreate(iter));

        summary.size += iter.size || 0;
        summary.directories += iter.type === 'dir' ? 1 : 0;
        summary.files += iter.type !== 'dir' ? 1 : 0;
        summary.hidden += isHidden(iter) ? 1 : 0;
      });

      cb(false, list, summary);
    }, scanopts);
  }

  function readdir(el, dir, done, sopts) {
    sopts = sopts || {};

    var vfsOptions = Utils.cloneObject(OSjs.Core.getSettingsManager().get('VFS') || {});
    var scandirOptions = vfsOptions.scandir || {};

    var target = getChildView(el);
    var tagName = target.tagName.toLowerCase();
    el.setAttribute('data-path', dir);

    var opts = {filter: null, backlink: sopts.backlink};
    function setOption(s, d, c, cc) {
      if ( el.hasAttribute(s) ) {
        opts[d] = c(el.getAttribute(s));
      } else {
        opts[d] = (cc || function() {})();
      }
    }
    setOption('data-dotfiles', 'dotfiles', function(val) {
      return val === 'true';
    }, function() {
      return scandirOptions.showHiddenFiles === true;
    });
    setOption('data-extensions', 'extensions', function(val) {
      return val === 'true';
    }, function() {
      return scandirOptions.showFileExtensions === true;
    });
    setOption('data-filetype', 'filetype', function(val) {
      return val;
    });

    try {
      opts.filter = JSON.parse(el.getAttribute('data-filter'));
    } catch ( e ) {
    }

    scandir(tagName, dir, opts, function(error, result, summary) {
      done(error, result, summary);
    }, function(iter) {
      var mimeConfig = API.getConfig('MIME.mapping');

      function removeExtension(str) {
        if ( opts.extensions === false ) {
          var ext = Utils.filext(str);
          if ( ext ) {
            ext = '.' + ext;
            if ( mimeConfig[ext] ) {
              str = str.substr(0, str.length - ext.length);
            }
          }
        }
        return str;
      }

      function _getIcon(iter, size) {
        if ( iter.icon && typeof iter.icon === 'object' ) {
          return API.getIcon(iter.icon.filename, size, iter.icon.application);
        }

        var icon = 'status/gtk-dialog-question.png';
        return API.getFileIcon(iter, size, icon);
      }

      function _createEntry() {
        var row = {
          value: iter,
          id: iter.id || removeExtension(iter.filename),
          label: iter.filename,
          tooltip: tooltip,
          icon: _getIcon(iter, tagName === 'gui-icon-view' ? '32x32' : '16x16')
        };

        if ( tagName === 'gui-tree-view' && iter.type === 'dir' ) {
          if ( iter.filename !== '..' ) {
            row.entries = [{
              label: 'Loading...'
            }];
          }
        }

        return row;
      }

      var filesize = iter.size ? Utils.humanFileSize(iter.size) : '';
      var tooltip = Utils.format('{0}\n{1}\n{2} {3}', iter.type.toUpperCase(), iter.filename, filesize, iter.mime || '');
      if ( tagName === 'gui-icon-view' || tagName === 'gui-tree-view' ) {
        return _createEntry();
      }

      return {
        value: iter,
        id: iter.id || iter.filename,
        tooltip: tooltip,
        columns: [
          {label: removeExtension(iter.filename), icon: _getIcon(iter)},
          {label: iter.mime, textalign: 'right'},
          {label: filesize, textalign: 'right'}
        ]
      };
    });
  }

  /////////////////////////////////////////////////////////////////////////////
  // EXPORTS
  /////////////////////////////////////////////////////////////////////////////

  /**
   * Element: 'gui-file-view'
   *
   * Abstraction layer for displaying files within Icon-, Tree- or List Views
   *
   * Events:
   *  select        When an entry was selected (click) => fn(ev)
   *  activate      When an entry was activated (doubleclick) => fn(ev)
   *
   * Parameters:
   *  type          String      Child type
   *  filter        Array       MIME Filters
   *  dotfiles      boolean     Show dotfiles (default=true)
   *  extensions    boolean     Show file extensions (default=true)
   *
   * Actions:
   *  chdir(args)   Change directory (args = {path: '', done: function() })
   *
   * @api OSjs.GUI.Elements.gui-file-view
   * @see OSjs.GUI.Elements.gui-list-view
   * @see OSjs.GUI.Elements.gui-tree-view
   * @see OSjs.GUI.Elements.gui-icon-view
   * @class
   */
  GUI.Elements['gui-file-view'] = {
    bind: function(el, evName, callback, params) {
      if ( (['activate', 'select', 'contextmenu']).indexOf(evName) !== -1 ) {
        evName = '_' + evName;
      }

      if ( evName === '_contextmenu' ) {
        el.setAttribute('data-has-contextmenu', 'true');
      }

      Utils.$bind(el, evName, callback.bind(new GUI.Element(el)), params);
    },
    set: function(el, param, value, arg) {
      if ( param === 'type' ) {
        var firstChild = el.children[0];
        if ( firstChild && firstChild.tagName.toLowerCase() === value ) {
          return true;
        }

        Utils.$empty(el);
        el.setAttribute('data-type', value);
        Utils.$bind(el, '_expand', function(ev) {
          var target = ev.detail.element;
          if ( target.getAttribute('data-was-rendered') ) {
            return;
          }

          if ( ev.detail.expanded ) {
            var view = new GUI.ElementDataView(getChildView(el));
            var entry = ev.detail.entries[0].data;
            target.setAttribute('data-was-rendered', String(true));
            readdir(el, entry.path, function(error, result, summary) {
              if ( !error ) {
                target.querySelectorAll('gui-tree-view-entry').forEach(function(e) {
                  Utils.$remove(e);

                  view.add({
                    entries: result,
                    parentNode: target
                  });
                });
              }
            }, {backlink: false});
          }
        });
        buildChildView(el);

        if ( typeof arg === 'undefined' || arg === true ) {
          GUI.Elements['gui-file-view'].call(el, 'chdir', {
            path: el.getAttribute('data-path')
          });
        }
        return true;
      } else if ( (['filter', 'dotfiles', 'filetype', 'extensions']).indexOf(param) >= 0 ) {
        GUI.Helpers.setProperty(el, param, value);
        return true;
      }

      var target = getChildView(el);
      if ( target ) {
        var tagName = target.tagName.toLowerCase();
        GUI.Elements[tagName].set(target, param, value, arg);
        return true;
      }

      return false;
    },
    build: function(el) {
      buildChildView(el);
    },
    values: function(el) {
      var target = getChildView(el);
      if ( target ) {
        var tagName = target.tagName.toLowerCase();
        return GUI.Elements[tagName].values(target);
      }
      return null;
    },

    contextmenu: function(ev) {
      var vfsOptions = OSjs.Core.getSettingsManager().instance('VFS');
      var scandirOptions = (vfsOptions.get('scandir') || {});

      function setOption(opt, toggle) {
        var opts = {scandir: {}};
        opts.scandir[opt] = toggle;
        vfsOptions.set(null, opts, true);
      }

      API.createMenu([
        {
          title: 'Show Hidden Files', // FIXME: Locale
          type: 'checkbox',
          checked: scandirOptions.showHiddenFiles === true,
          onClick: function() {
            setOption('showHiddenFiles', !scandirOptions.showHiddenFiles);
            API.blurMenu(); // FIXME: This should not be needed!
          }
        },
        {
          title: 'Show File Extensions', // FIXME: Locale
          type: 'checkbox',
          checked: scandirOptions.showFileExtensions === true,
          onClick: function() {
            setOption('showFileExtensions', !scandirOptions.showFileExtensions);
            API.blurMenu(); // FIXME: This should not be needed!
          }
        }
      ], ev);
    },

    call: function(el, method, args) {
      args = args || {};
      args.done = args.done || function() {};

      var target = getChildView(el);

      if ( target ) {
        var tagName = target.tagName.toLowerCase();

        if ( method === 'chdir' ) {
          var t = new GUI.ElementDataView(target);
          var dir = args.path || OSjs.API.getDefaultPath();

          readdir(el, dir, function(error, result, summary) {
            if ( error ) {
              API.error(API._('ERR_VFSMODULE_XHR_ERROR'), API._('ERR_VFSMODULE_SCANDIR_FMT', dir), error);
            } else {
              t.clear();
              t.add(result);
            }
            args.done(error, summary);
          });
          return;
        }

        GUI.Elements[tagName].call(target, method, args);
      }
    }
  };

})(OSjs.API, OSjs.Utils, OSjs.VFS, OSjs.GUI);
<commit_msg>GUI: FileView no longer shows sizes for folders<commit_after>/*!
 * OS.js - JavaScript Operating System
 *
 * Copyright (c) 2011-2015, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */
(function(API, Utils, VFS, GUI) {
  'use strict';

  /////////////////////////////////////////////////////////////////////////////
  // HELPERS
  /////////////////////////////////////////////////////////////////////////////

  function getChildView(el) {
    return el.children[0];
  }

  function buildChildView(el) {
    var type = el.getAttribute('data-type') || 'list-view';
    if ( !type.match(/^gui\-/) ) {
      type = 'gui-' + type;
    }

    var nel = new GUI.ElementDataView(GUI.Helpers.createElement(type, {'draggable': true, 'draggable-type': 'file'}));
    GUI.Elements[type].build(nel.$element);

    nel.on('select', function(ev) {
      el.dispatchEvent(new CustomEvent('_select', {detail: ev.detail}));
    });
    nel.on('activate', function(ev) {
      el.dispatchEvent(new CustomEvent('_activate', {detail: ev.detail}));
    });
    nel.on('contextmenu', function(ev) {
      if ( !el.hasAttribute('data-has-contextmenu') || el.hasAttribute('data-has-contextmenu') === 'false' ) {
        new GUI.Element(el).fn('contextmenu', [ev]);
      }
      el.dispatchEvent(new CustomEvent('_contextmenu', {detail: ev.detail}));
    });

    if ( type === 'gui-list-view' ) {
      nel.set('zebra', true);
      nel.set('columns', [
        {label: API._('LBL_FILENAME'), grow: 1, shrink: 1},
        {label: API._('LBL_MIME'), basis: '100px', grow: 0, shrink: 0, textalign: 'right'},
        {label: API._('LBL_SIZE'), basis: '120px', grow: 0, shrink: 0, textalign: 'right'}
      ]);
    } else if ( type === 'gui-tree-view' ) {
      nel.on('expand', function(ev) {
        el.dispatchEvent(new CustomEvent('_expand', {detail: ev.detail}));
      });
    }

    el.appendChild(nel.$element);
  }

  function scandir(tagName, dir, opts, cb, oncreate) {
    var file = new VFS.File(dir);
    file.type  = 'dir';

    var scanopts = {
      backlink:           opts.backlink,
      showDotFiles:       opts.dotfiles === true,
      showFileExtensions: opts.extensions === true,
      mimeFilter:         opts.filter || [],
      typeFilter:         opts.filetype || null
    };

    VFS.scandir(file, function(error, result) {
      if ( error ) { cb(error); return; }

      var list = [];
      var summary = {size: 0, directories: 0, files: 0, hidden: 0};

      function isHidden(iter) {
        return (iter.filename || '').substr(0) === '.';
      }

      (result || []).forEach(function(iter) {
        list.push(oncreate(iter));

        summary.size += iter.size || 0;
        summary.directories += iter.type === 'dir' ? 1 : 0;
        summary.files += iter.type !== 'dir' ? 1 : 0;
        summary.hidden += isHidden(iter) ? 1 : 0;
      });

      cb(false, list, summary);
    }, scanopts);
  }

  function readdir(el, dir, done, sopts) {
    sopts = sopts || {};

    var vfsOptions = Utils.cloneObject(OSjs.Core.getSettingsManager().get('VFS') || {});
    var scandirOptions = vfsOptions.scandir || {};

    var target = getChildView(el);
    var tagName = target.tagName.toLowerCase();
    el.setAttribute('data-path', dir);

    var opts = {filter: null, backlink: sopts.backlink};
    function setOption(s, d, c, cc) {
      if ( el.hasAttribute(s) ) {
        opts[d] = c(el.getAttribute(s));
      } else {
        opts[d] = (cc || function() {})();
      }
    }
    setOption('data-dotfiles', 'dotfiles', function(val) {
      return val === 'true';
    }, function() {
      return scandirOptions.showHiddenFiles === true;
    });
    setOption('data-extensions', 'extensions', function(val) {
      return val === 'true';
    }, function() {
      return scandirOptions.showFileExtensions === true;
    });
    setOption('data-filetype', 'filetype', function(val) {
      return val;
    });

    try {
      opts.filter = JSON.parse(el.getAttribute('data-filter'));
    } catch ( e ) {
    }

    scandir(tagName, dir, opts, function(error, result, summary) {
      done(error, result, summary);
    }, function(iter) {
      var mimeConfig = API.getConfig('MIME.mapping');

      function removeExtension(str) {
        if ( opts.extensions === false ) {
          var ext = Utils.filext(str);
          if ( ext ) {
            ext = '.' + ext;
            if ( mimeConfig[ext] ) {
              str = str.substr(0, str.length - ext.length);
            }
          }
        }
        return str;
      }

      function _getIcon(iter, size) {
        if ( iter.icon && typeof iter.icon === 'object' ) {
          return API.getIcon(iter.icon.filename, size, iter.icon.application);
        }

        var icon = 'status/gtk-dialog-question.png';
        return API.getFileIcon(iter, size, icon);
      }

      function _createEntry() {
        var row = {
          value: iter,
          id: iter.id || removeExtension(iter.filename),
          label: iter.filename,
          tooltip: tooltip,
          icon: _getIcon(iter, tagName === 'gui-icon-view' ? '32x32' : '16x16')
        };

        if ( tagName === 'gui-tree-view' && iter.type === 'dir' ) {
          if ( iter.filename !== '..' ) {
            row.entries = [{
              label: 'Loading...'
            }];
          }
        }

        return row;
      }

      var filesize = '';
      if ( iter.type !== 'dir' && iter.size ) {
        filesize = Utils.humanFileSize(iter.size);
      }

      var tooltip = Utils.format('{0}\n{1}\n{2} {3}', iter.type.toUpperCase(), iter.filename, filesize, iter.mime || '');
      if ( tagName === 'gui-icon-view' || tagName === 'gui-tree-view' ) {
        return _createEntry();
      }

      return {
        value: iter,
        id: iter.id || iter.filename,
        tooltip: tooltip,
        columns: [
          {label: removeExtension(iter.filename), icon: _getIcon(iter)},
          {label: iter.mime, textalign: 'right'},
          {label: filesize, textalign: 'right'}
        ]
      };
    });
  }

  /////////////////////////////////////////////////////////////////////////////
  // EXPORTS
  /////////////////////////////////////////////////////////////////////////////

  /**
   * Element: 'gui-file-view'
   *
   * Abstraction layer for displaying files within Icon-, Tree- or List Views
   *
   * Events:
   *  select        When an entry was selected (click) => fn(ev)
   *  activate      When an entry was activated (doubleclick) => fn(ev)
   *
   * Parameters:
   *  type          String      Child type
   *  filter        Array       MIME Filters
   *  dotfiles      boolean     Show dotfiles (default=true)
   *  extensions    boolean     Show file extensions (default=true)
   *
   * Actions:
   *  chdir(args)   Change directory (args = {path: '', done: function() })
   *
   * @api OSjs.GUI.Elements.gui-file-view
   * @see OSjs.GUI.Elements.gui-list-view
   * @see OSjs.GUI.Elements.gui-tree-view
   * @see OSjs.GUI.Elements.gui-icon-view
   * @class
   */
  GUI.Elements['gui-file-view'] = {
    bind: function(el, evName, callback, params) {
      if ( (['activate', 'select', 'contextmenu']).indexOf(evName) !== -1 ) {
        evName = '_' + evName;
      }

      if ( evName === '_contextmenu' ) {
        el.setAttribute('data-has-contextmenu', 'true');
      }

      Utils.$bind(el, evName, callback.bind(new GUI.Element(el)), params);
    },
    set: function(el, param, value, arg) {
      if ( param === 'type' ) {
        var firstChild = el.children[0];
        if ( firstChild && firstChild.tagName.toLowerCase() === value ) {
          return true;
        }

        Utils.$empty(el);
        el.setAttribute('data-type', value);
        Utils.$bind(el, '_expand', function(ev) {
          var target = ev.detail.element;
          if ( target.getAttribute('data-was-rendered') ) {
            return;
          }

          if ( ev.detail.expanded ) {
            var view = new GUI.ElementDataView(getChildView(el));
            var entry = ev.detail.entries[0].data;
            target.setAttribute('data-was-rendered', String(true));
            readdir(el, entry.path, function(error, result, summary) {
              if ( !error ) {
                target.querySelectorAll('gui-tree-view-entry').forEach(function(e) {
                  Utils.$remove(e);

                  view.add({
                    entries: result,
                    parentNode: target
                  });
                });
              }
            }, {backlink: false});
          }
        });
        buildChildView(el);

        if ( typeof arg === 'undefined' || arg === true ) {
          GUI.Elements['gui-file-view'].call(el, 'chdir', {
            path: el.getAttribute('data-path')
          });
        }
        return true;
      } else if ( (['filter', 'dotfiles', 'filetype', 'extensions']).indexOf(param) >= 0 ) {
        GUI.Helpers.setProperty(el, param, value);
        return true;
      }

      var target = getChildView(el);
      if ( target ) {
        var tagName = target.tagName.toLowerCase();
        GUI.Elements[tagName].set(target, param, value, arg);
        return true;
      }

      return false;
    },
    build: function(el) {
      buildChildView(el);
    },
    values: function(el) {
      var target = getChildView(el);
      if ( target ) {
        var tagName = target.tagName.toLowerCase();
        return GUI.Elements[tagName].values(target);
      }
      return null;
    },

    contextmenu: function(ev) {
      var vfsOptions = OSjs.Core.getSettingsManager().instance('VFS');
      var scandirOptions = (vfsOptions.get('scandir') || {});

      function setOption(opt, toggle) {
        var opts = {scandir: {}};
        opts.scandir[opt] = toggle;
        vfsOptions.set(null, opts, true);
      }

      API.createMenu([
        {
          title: 'Show Hidden Files', // FIXME: Locale
          type: 'checkbox',
          checked: scandirOptions.showHiddenFiles === true,
          onClick: function() {
            setOption('showHiddenFiles', !scandirOptions.showHiddenFiles);
            API.blurMenu(); // FIXME: This should not be needed!
          }
        },
        {
          title: 'Show File Extensions', // FIXME: Locale
          type: 'checkbox',
          checked: scandirOptions.showFileExtensions === true,
          onClick: function() {
            setOption('showFileExtensions', !scandirOptions.showFileExtensions);
            API.blurMenu(); // FIXME: This should not be needed!
          }
        }
      ], ev);
    },

    call: function(el, method, args) {
      args = args || {};
      args.done = args.done || function() {};

      var target = getChildView(el);

      if ( target ) {
        var tagName = target.tagName.toLowerCase();

        if ( method === 'chdir' ) {
          var t = new GUI.ElementDataView(target);
          var dir = args.path || OSjs.API.getDefaultPath();

          readdir(el, dir, function(error, result, summary) {
            if ( error ) {
              API.error(API._('ERR_VFSMODULE_XHR_ERROR'), API._('ERR_VFSMODULE_SCANDIR_FMT', dir), error);
            } else {
              t.clear();
              t.add(result);
            }
            args.done(error, summary);
          });
          return;
        }

        GUI.Elements[tagName].call(target, method, args);
      }
    }
  };

})(OSjs.API, OSjs.Utils, OSjs.VFS, OSjs.GUI);
<|endoftext|>


<commit_before>/* -*- js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80; */
"use strict";

require("sockjs");
let Sock = window.SockJS,
    {addMethod} = require("genfun"),
    {clone, init} = require("../../lib/proto"),
    _ = require("lodash"),
    can = require("../../shims/can");

/**
 * Chatlog Model
 */
let Chatlog = clone();

/*
 * Init
 */
addMethod(init, [Chatlog], function(log, url) {
  initSocket(log, url);
  initModelList(log);
});

function initSocket(log, url) {
  log.socket = new Sock(url);
  log.socket.onopen = _.partial(onOpen, log);
  log.socket.onmessage = _.partial(onMessage, log);
  // TODO - this is probably a pretty naive way to go about reconnecting...
  log.socket.onclose = _.partial(initSocket, log);
}

function initModelList(log) {
  log.lines = new LogLine.List([]);
}

function onOpen(log) {
  addEntry(log, {entryType: "system", text: "Connected"});
}

function addEntry(log, entryInfo) {
  log.lines.push(new LogLine(entryInfo));
}

function onMessage(log, message) {
  addEntry(log, JSON.parse(message.data));
}

function addLine(log, line) {
  log.socket.send(JSON.stringify({entryType: "line", text: line}));
}

/*
 * Canjs Model
 */
var LogLine = can.Model.extend({},{});

module.exports.Chatlog = Chatlog;
module.exports.addLine = addLine;
<commit_msg>No need for any arguments to can.Model.extend<commit_after>/* -*- js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80; */
"use strict";

require("sockjs");
let Sock = window.SockJS,
    {addMethod} = require("genfun"),
    {clone, init} = require("../../lib/proto"),
    _ = require("lodash"),
    can = require("../../shims/can");

/**
 * Chatlog Model
 */
let Chatlog = clone();

/*
 * Init
 */
addMethod(init, [Chatlog], function(log, url) {
  initSocket(log, url);
  initModelList(log);
});

function initSocket(log, url) {
  log.socket = new Sock(url);
  log.socket.onopen = _.partial(onOpen, log);
  log.socket.onmessage = _.partial(onMessage, log);
  // TODO - this is probably a pretty naive way to go about reconnecting...
  log.socket.onclose = _.partial(initSocket, log);
}

function initModelList(log) {
  log.lines = new LogLine.List([]);
}

function onOpen(log) {
  addEntry(log, {entryType: "system", text: "Connected"});
}

function addEntry(log, entryInfo) {
  log.lines.push(new LogLine(entryInfo));
}

function onMessage(log, message) {
  addEntry(log, JSON.parse(message.data));
}

function addLine(log, line) {
  log.socket.send(JSON.stringify({entryType: "line", text: line}));
}

/*
 * Canjs Model
 */
var LogLine = can.Model.extend();

module.exports.Chatlog = Chatlog;
module.exports.addLine = addLine;
<|endoftext|>


<commit_before>import _ from 'lodash'

let baseFieldMixin = {
  props: {
    contextId: {
      type: String,
      default: ''
    },
    objectId: {
      type: String,
      default: ''
    },
    properties: {
      type: Object,
      required: true
    },
    required: {
      type: Boolean,
      required: true
    },
    display: {
      type: Object,
      required: true
    }
  },
  computed: {
    icon () {
      if (this.display.icon) {
        return _.get(this.properties.field, 'icon', '')
      }
      return ''
    },
    label () {
      if (this.display.label) {
        return this.$t(_.get(this.properties.field, 'label', ''))
      }
      return ''
    },
    labelWidth () {
      return _.get(this.display, 'labelWidth', 3)
    },
    helper () {
      return this.$t(_.get(this.properties.field, 'helper', ''))
    },
    hasError () {
      return !_.isEmpty(this.error)
    },
    errorLabel () {
      return this.error
    }
  },
  data () {
    return {
      // The model to used for data binding with the field
      model: this.emptyModel(),
      // The error message
      error: ''
    }
  },
  methods: {
    emptyModel () {
      return ''
    },
    isEmpty () {
      return _.isEqual(this.model, this.emptyModel())
    },
    value () {
      return this.model
    },
    fill (value) {
      this.model = value
    },
    clear () {
      this.fill(_.get(this.properties, 'default', this.emptyModel()))
    },
    validate () {
      this.error = ''
    },
    invalidate (error) {
      this.error = error
    },
    getMode () {
      if (this.objectId) return 'update'
      return 'create'
    },
    onChanged () {
      // Tell the form that this field has a new value.
      // Consequently the form will validate or invalidate the field
      // Warning: This method must be called once the form is mounted
      // We need to force a refresh so that the model is correctly updated by Vuejs
      this.$nextTick().then(() => this.$emit('field-changed', this.properties.name, this.model))
    },
    apply (object, field) {
      // To be overloaded if you need to perform specific operations before the form has been submitted
      // By default simply set the current value on the given object field to apply the form
      _.set(object, field, this.value())
    },
    submitted (object, field) {
      // To be overloaded if you need to perform specific operations after the form has been submitted
    }
  }
}

export default baseFieldMixin
<commit_msg>Added support for custom error labels in fields<commit_after>import _ from 'lodash'

let baseFieldMixin = {
  props: {
    contextId: {
      type: String,
      default: ''
    },
    objectId: {
      type: String,
      default: ''
    },
    properties: {
      type: Object,
      required: true
    },
    required: {
      type: Boolean,
      required: true
    },
    display: {
      type: Object,
      required: true
    }
  },
  computed: {
    icon () {
      if (this.display.icon) {
        return _.get(this.properties.field, 'icon', '')
      }
      return ''
    },
    label () {
      if (this.display.label) {
        return this.$t(_.get(this.properties.field, 'label', ''))
      }
      return ''
    },
    labelWidth () {
      return _.get(this.display, 'labelWidth', 3)
    },
    helper () {
      return this.$t(_.get(this.properties.field, 'helper', ''))
    },
    hasError () {
      return !_.isEmpty(this.error)
    },
    errorLabel () {
      // Check for overriden error label
      const error = _.get(this.properties.field, 'errorLabel', '')
      // If not use default validator error messages
      return (error ? this.$t(error) : this.error)
    }
  },
  data () {
    return {
      // The model to used for data binding with the field
      model: this.emptyModel(),
      // The error message
      error: ''
    }
  },
  methods: {
    emptyModel () {
      return ''
    },
    isEmpty () {
      return _.isEqual(this.model, this.emptyModel())
    },
    value () {
      return this.model
    },
    fill (value) {
      this.model = value
    },
    clear () {
      this.fill(_.get(this.properties, 'default', this.emptyModel()))
    },
    validate () {
      this.error = ''
    },
    invalidate (error) {
      this.error = error
    },
    getMode () {
      if (this.objectId) return 'update'
      return 'create'
    },
    onChanged () {
      // Tell the form that this field has a new value.
      // Consequently the form will validate or invalidate the field
      // Warning: This method must be called once the form is mounted
      // We need to force a refresh so that the model is correctly updated by Vuejs
      this.$nextTick().then(() => this.$emit('field-changed', this.properties.name, this.model))
    },
    apply (object, field) {
      // To be overloaded if you need to perform specific operations before the form has been submitted
      // By default simply set the current value on the given object field to apply the form
      _.set(object, field, this.value())
    },
    submitted (object, field) {
      // To be overloaded if you need to perform specific operations after the form has been submitted
    }
  }
}

export default baseFieldMixin
<|endoftext|>


<commit_before>/*jslint nomen: true, browser:true*/
/*global define */

define(['jquery', 'jstools/tools', 'jstools/geoTools'], function ($, tools, geoTools) {

    function TestTask(parentDiv, params) {

        this.parentDiv = parentDiv;
        this.params = params;

        this._mainDiv = null;
        this._object = null;
        this._target = null;
        this._taskDeff = null;
        this._lastTaskDeff = null;
        this._closeEnoughTime = null;
        this._startTime = null;
    }

    TestTask.prototype = {

        maxDist: 1,

        minTime: 500,

        _createObject: function () {
            var objDiv = $("
"),
                size = 28;
            objDiv.css({
                position: 'absolute',
                width: size,
                height: size,
                "border-radius": size,
                "background-color": "#25A0DD",
            });
            return objDiv;
        },

        _targetWrongCss: {
            "border-color": "rgb(108, 207, 255)",
            "background-color": "rgba(108, 207, 255, 0.1)",
            "border-width": 2
        },

        _targetGoodCss: {
            // "border-color": "25A0DD",
            "background-color": "rgba(108, 207, 255, 0.2)",
            "border-width": 4
        },

        _setTargetSelected: function (selected) {
            this._target.css(selected ? this._targetGoodCss : this._targetWrongCss);
            tools.centerOf(this._target, this._positions().target);
        },

        _createTarget: function () {
            var targetDiv = $("
"),
                size = 34;
            targetDiv.css(this._targetWrongCss);
            targetDiv.css({
                position: 'absolute',
                width: size,
                height: size,
                "border-radius": size,
                "border-style": "solid",
            });
            return targetDiv;
        },

        _createMainDiv: function () {
            return $('

');
        },

        _positions: function () {
            var dir = this.params.values.direction,
                width = this._mainDiv.width(),
                height = this._mainDiv.height();
            if (dir == "right") {
                return {
                    object: [width / 5, height / 2],
                    target: [width * 4 / 5, height / 2]
                };
            } else if (dir == "left") {
                return {
                    target: [width / 5, height / 2],
                    object: [width * 4 / 5, height / 2]
                };
            } else if (dir == "top") {
                return {
                    target: [width / 2, height / 5],
                    object: [width / 2, height * 4 / 5]
                };
            } else if (dir == "bottom") {
                return {
                    object: [width / 2, height / 5],
                    target: [width / 2, height * 4 / 5]
                };
            }
        },

        _closeEnough: function () {
            var objCenter = tools.centerOf(this._object),
                targetCenter = tools.centerOf(this._target),
                dist = geoTools.dist(objCenter, targetCenter);
            console.log('dist: ' + dist);
            return dist < this.maxDist;
        },

        _updateCloseEnoughTimer: function () {
            var that = this;
            if (that._closeEnough()) {
                if (!that._closeEnoughTime) {
                    that._closeEnoughTime = setTimeout(function () {
                        that._resolve();
                    }, that.minTime);
                    that._setTargetSelected(true);
                }
            } else {
                if (that._closeEnoughTime) {
                    that._setTargetSelected(false);
                    clearTimeout(this._closeEnoughTime);
                    that._closeEnoughTime = null;
                }
            }
        },

        get started() {
            return this._taskDeff !== null;
        },

        get completed() {
            return this._taskDeff && this._taskDeff.state != 'pending ';
        },

        start: function (callback) {
            if (this._taskDeff) {
                throw "Task already started.";
            }
            this._taskDeff = $.Deferred();
            this._startTime = new Date().getTime();

            // create the target if needed
            this._mainDiv = this._createMainDiv();
            this._object = this._object || this._createObject();
            this._target = this._target || this._createTarget();

            this._mainDiv.appendTo(this.parentDiv);
            this._target.appendTo(this._mainDiv);
            this._object.appendTo(this._mainDiv);

            var positions = this._positions();
            tools.centerOf(this._object, positions.object);
            tools.centerOf(this._target, positions.target);

            var dragging = false,
                lastPosition = null,
                that = this;
            this._mainDiv.on({
                mousedown: function (evt) {
                    lastPosition = [evt.pageX, evt.pageY];
                    dragging = true;
                    evt.preventDefault();
                },
                mousemove: function (evt) {
                    if (dragging) {
                        var thisPosition = [evt.pageX, evt.pageY],
                            diff = [thisPosition[0] - lastPosition[0], thisPosition[1] - lastPosition[1]];
                        tools.move(that._object, diff);
                        that._updateCloseEnoughTimer();
                        lastPosition = thisPosition;
                        evt.preventDefault();
                    }
                },
                mouseup: function (evt) {
                    if (dragging) {
                        dragging = false;
                        evt.preventDefault();
                    }
                }
            });

            this._taskDeff.done(function () {
                that._mainDiv.remove();
                that._taskDeff = null;
            });
            this._taskDeff.done(callback);
            return this._taskDeff.promise();

        },

        _resolve: function () {
            var results = {
                duration: new Date().getTime() - this._startTime
            };
            this._taskDeff.resolveWith(this, [results]);
        },

    };

    return TestTask;

});<commit_msg>Target is now always at the same distance from the object.<commit_after>/*jslint nomen: true, browser:true*/
/*global define */

define(['jquery', 'jstools/tools', 'jstools/geoTools'], function ($, tools, geoTools) {

    function TestTask(parentDiv, params) {

        this.parentDiv = parentDiv;
        this.params = params;

        this._mainDiv = null;
        this._object = null;
        this._target = null;
        this._taskDeff = null;
        this._lastTaskDeff = null;
        this._closeEnoughTime = null;
        this._startTime = null;

        this.targetDist = params.target_dist || this.DEFAULT_TARGET_DIST;
        this.maxDist = params.max_dist || this.DEFAULT_MAX_DIST;
        this.minTime = params.min_time || this.DEFAULT_MIN_TIME;
    }

    TestTask.prototype = {

        DEFAULT_TARGET_DIST: 600,

        DEFAULT_MAX_DIST: 2,

        DEFAULT_MIN_TIME: 500,

        _createObject: function () {
            var objDiv = $("
"),
                size = 28;
            objDiv.css({
                position: 'absolute',
                width: size,
                height: size,
                "border-radius": size,
                "background-color": "#25A0DD",
            });
            return objDiv;
        },

        _targetWrongCss: {
            "border-color": "rgb(108, 207, 255)",
            "background-color": "rgba(108, 207, 255, 0.1)",
            "border-width": 2
        },

        _targetGoodCss: {
            // "border-color": "25A0DD",
            "background-color": "rgba(108, 207, 255, 0.2)",
            "border-width": 4
        },

        _setTargetSelected: function (selected) {
            this._target.css(selected ? this._targetGoodCss : this._targetWrongCss);
            tools.centerOf(this._target, this._positions().target);
        },

        _createTarget: function () {
            var targetDiv = $("
"),
                size = 34;
            targetDiv.css(this._targetWrongCss);
            targetDiv.css({
                position: 'absolute',
                width: size,
                height: size,
                "border-radius": size,
                "border-style": "solid",
            });
            return targetDiv;
        },

        _createMainDiv: function () {
            return $('

');
        },

        _positions: function () {
            var dir = this.params.values.direction,
                center = tools.centerOf(this._mainDiv),
                centerDist = this.targetDist / 2;
            if (dir == "right") {
                return {
                    object: [center[0] - centerDist, center[1]],
                    target: [center[0] + centerDist, center[1]]
                };
            } else if (dir == "left") {
                return {
                    object: [center[0] + centerDist, center[1]],
                    target: [center[0] - centerDist, center[1]]
                };
            } else if (dir == "top") {
                return {
                    object: [center[0], center[1] + centerDist],
                    target: [center[0], center[1] - centerDist]
                };
            } else if (dir == "bottom") {
                return {
                    object: [center[0], center[1] - centerDist],
                    target: [center[0], center[1] + centerDist]
                };
            }
        },

        _closeEnough: function () {
            var objCenter = tools.centerOf(this._object),
                targetCenter = tools.centerOf(this._target),
                dist = geoTools.dist(objCenter, targetCenter);
            console.log('dist: ' + dist);
            return dist < this.maxDist;
        },

        _updateCloseEnoughTimer: function () {
            var that = this;
            if (that._closeEnough()) {
                if (!that._closeEnoughTime) {
                    that._closeEnoughTime = setTimeout(function () {
                        that._resolve();
                    }, that.minTime);
                    that._setTargetSelected(true);
                }
            } else {
                if (that._closeEnoughTime) {
                    that._setTargetSelected(false);
                    clearTimeout(this._closeEnoughTime);
                    that._closeEnoughTime = null;
                }
            }
        },

        get started() {
            return this._taskDeff !== null;
        },

        get completed() {
            return this._taskDeff && this._taskDeff.state != 'pending ';
        },

        start: function (callback) {
            if (this._taskDeff) {
                throw "Task already started.";
            }
            this._taskDeff = $.Deferred();
            this._startTime = new Date().getTime();

            // create the target if needed
            this._mainDiv = this._createMainDiv();
            this._object = this._object || this._createObject();
            this._target = this._target || this._createTarget();

            this._mainDiv.appendTo(this.parentDiv);
            this._target.appendTo(this._mainDiv);
            this._object.appendTo(this._mainDiv);

            var positions = this._positions();
            tools.centerOf(this._object, positions.object);
            tools.centerOf(this._target, positions.target);

            var dragging = false,
                lastPosition = null,
                that = this;
            this._mainDiv.on({
                mousedown: function (evt) {
                    lastPosition = [evt.pageX, evt.pageY];
                    dragging = true;
                    evt.preventDefault();
                },
                mousemove: function (evt) {
                    if (dragging) {
                        var thisPosition = [evt.pageX, evt.pageY],
                            diff = [thisPosition[0] - lastPosition[0], thisPosition[1] - lastPosition[1]];
                        tools.move(that._object, diff);
                        that._updateCloseEnoughTimer();
                        lastPosition = thisPosition;
                        evt.preventDefault();
                    }
                },
                mouseup: function (evt) {
                    if (dragging) {
                        dragging = false;
                        evt.preventDefault();
                    }
                }
            });

            this._taskDeff.done(function () {
                that._mainDiv.remove();
                that._taskDeff = null;
            });
            this._taskDeff.done(callback);
            return this._taskDeff.promise();

        },

        _resolve: function () {
            var results = {
                duration: new Date().getTime() - this._startTime
            };
            this._taskDeff.resolveWith(this, [results]);
        },

    };

    return TestTask;

});<|endoftext|>


<commit_before>/* global app:true, io:false */

var socket;
var myname;
var block_id;
var blockData;
var ledData;
var imageData;

(function() {
  'use strict';

  //var blockdata = [];
  //var qs = new Querystring();
  //var block_id = qs.get("myBlock");

  socket = io.connect();
  socket.on('connect', function(){
  	socket.emit('/replay/#join');
  });

  socket.on('/replay/#postdata', function(data){
  	blockData = [];
	blockData.push(data[0]); // time
	blockData.push(data[1]); // owner
	blockData.push(data[2]); // experiment id
	blockData.push(data[3]); // pattern id

	// image dir = 171.65.102.132:3001/blockid/

	ledData = data[4];

	console.log(blockData);
	console.log(ledData);
  });

  socket.on('/replay/#postimglist', function(data){
	imageData = [];
	data.forEach(function(filename){
	    var res = filename.split(".");
	    var convertDate = new Date(res[0]);
	    imageData.push(convertDate.getTime());
	    imageData.push(filename);
	});
	console.log(imageData);
  });

  socket.on('/replay/#newUser', function(user) {
      myname = user;
      console.log('>>> DB connected' + block_id);
  });

  socket.on('message', function (message) {
  	console.log(message);
  });

  socket.on('disconnect', function() {
	console.log('>>> DB disconnected');
  });

  app = app || {};

  app.Reset = Backbone.Model.extend({
    defaults: {
      success: false,
      errors: [],
      errfor: {},
      blockid: undefined,
      confitm: ''
    },
    url: function(){
      return '/account/replay/' + this.get('block_id') +'/';
    }
  });

  /*app.BlocksView = Backbone.View.extend({
    el: '#blocks_nav',
    template: _.template( $('#tmpl-blocks_nav').html() ),
    events: {
      'click .btn-prev': 'reqPrev',
      'click .btn-now': 'reqNow',
      'click .btn-next': 'reqNext'
    },
    initialize: function() {
      this.model = new app.Blocks();
      this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template( this.model.attributes));
    },
    reqPrev: function() {
      currenttime.setHours(currenttime.getHours() - 1);
      callBlocks(currenttime);
    },
    reqNow: function() {
      currenttime = new Date();
      callBlocks(currenttime);
    },
    reqNext: function() {
      currenttime.setHours(currenttime.getHours() + 1);
      callBlocks(currenttime);
    }
  });*/

  app.Router = Backbone.Router.extend({
    routes: {
      'account/replay/': 'default',
      'account/replay/load/:block/': 'load'
    },
    default: function(){
      console.log(" >>default view, nothing loaded");
    },
    load: function(block) {
      console.log(">> loading block "+block);
      block_id = block;
      socket.emit('/replay/#callblock', { targetBlock: block});
    }
  });

  $(document).ready(function() {
    //app.blocksView = new app.BlocksView();
    app.router = new app.Router();
    Backbone.history.start({ pushState: true });
  });

}());
<commit_msg>image list<commit_after>/* global app:true, io:false */

var socket;
var myname;
var block_id;
var blockData;
var ledData;
var imageData;

(function() {
  'use strict';

  //var blockdata = [];
  //var qs = new Querystring();
  //var block_id = qs.get("myBlock");

  socket = io.connect();
  socket.on('connect', function(){
  	socket.emit('/replay/#join');
  });

  socket.on('/replay/#postdata', function(data){
  	blockData = [];
	blockData.push(data[0]); // time
	blockData.push(data[1]); // owner
	blockData.push(data[2]); // experiment id
	blockData.push(data[3]); // pattern id

	// image dir = 171.65.102.132:3001/blockid/
	ledData = _.partition(data[4], isOdd);
	ledData = data[4];

	console.log(blockData);
	console.log(ledData);
  });

  socket.on('/replay/#postimglist', function(data){
	imageData = [];
	data.forEach(function(filename){
	    var res = filename.split(".");
	    var convertDate = new Date(res[0]);
	    imageData.push(convertDate.getTime());
	    imageData.push(filename);
	});
	console.log(imageData);
  });

  socket.on('/replay/#newUser', function(user) {
      myname = user;
      console.log('>>> DB connected' + block_id);
  });

  socket.on('message', function (message) {
  	console.log(message);
  });

  socket.on('disconnect', function() {
	console.log('>>> DB disconnected');
  });

  app = app || {};

  app.Reset = Backbone.Model.extend({
    defaults: {
      success: false,
      errors: [],
      errfor: {},
      blockid: undefined,
      confitm: ''
    },
    url: function(){
      return '/account/replay/' + this.get('block_id') +'/';
    }
  });

  /*app.BlocksView = Backbone.View.extend({
    el: '#blocks_nav',
    template: _.template( $('#tmpl-blocks_nav').html() ),
    events: {
      'click .btn-prev': 'reqPrev',
      'click .btn-now': 'reqNow',
      'click .btn-next': 'reqNext'
    },
    initialize: function() {
      this.model = new app.Blocks();
      this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template( this.model.attributes));
    },
    reqPrev: function() {
      currenttime.setHours(currenttime.getHours() - 1);
      callBlocks(currenttime);
    },
    reqNow: function() {
      currenttime = new Date();
      callBlocks(currenttime);
    },
    reqNext: function() {
      currenttime.setHours(currenttime.getHours() + 1);
      callBlocks(currenttime);
    }
  });*/

  app.Router = Backbone.Router.extend({
    routes: {
      'account/replay/': 'default',
      'account/replay/load/:block/': 'load'
    },
    default: function(){
      console.log(" >>default view, nothing loaded");
    },
    load: function(block) {
      console.log(">> loading block "+block);
      block_id = block;
      socket.emit('/replay/#callblock', { targetBlock: block});
    }
  });

  $(document).ready(function() {
    //app.blocksView = new app.BlocksView();
    app.router = new app.Router();
    Backbone.history.start({ pushState: true });
  });

}());
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var twilio = require('twilio');
var firebase = require('firebase');
var _ = require('lodash');

var config = require('./helpers/config');
var handle_error = require('./helpers/error_handler');
var utils = require('./helpers/utils');

var urls = utils.urls;
var http = require('http');

var ConsistentHashing = require('consistent-hashing');
var cons = new ConsistentHashing(["server_1", "server_2", "server_3"]);
var map_to_num = {};
map_to_num["server_1"] = '8071';
map_to_num["server_2"] = '8071';
map_to_num["server_3"] = '8071';

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

var get_fwd_number = function(request, response) {
  var twiml = new twilio.TwimlResponse();
  var sender = request.body['From'];
  var msg = request.body['Body'];
  var key = sender+msg
  var server = cons.getNode(key);
  var options = {
    hostname: '104.131.27.67',
    port: map_to_num[server],
    path: '/sms',
    method: 'POST',
    headers: {
      'MessageLength': msg.length
    }
  };
  console.log('reached here')
  var req = http.request(options, (res) => {
    console.log(`STATUS: ${res.statusCode}`);
    console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
    res.setEncoding('utf8');
  });
  console.log(msg)
  req.write(msg);
  req.end();
}

var app = express();
app.use(bodyParser.urlencoded({
  extended: true
}));

app.post('/sms', twilio.webhook(config.TWILIO_AUTH_TOKEN), get_fwd_number);

app.get('/', function(req, res) {
  res.send('Hello World!');
});

var server = app.listen(80, function() {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Refuge listening at http://%s:%s', host, port);

});
<commit_msg>fixed bug<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var twilio = require('twilio');
var firebase = require('firebase');
var _ = require('lodash');

var config = require('./helpers/config');
var handle_error = require('./helpers/error_handler');
var utils = require('./helpers/utils');

var urls = utils.urls;
var http = require('http');

var ConsistentHashing = require('consistent-hashing');
var cons = new ConsistentHashing(["server_1", "server_2", "server_3"]);
var map_to_num = {};
map_to_num["server_1"] = '8071';
map_to_num["server_2"] = '8071';
map_to_num["server_3"] = '8071';

var get_fwd_number = function(request, response) {
  var twiml = new twilio.TwimlResponse();
  var sender = request.body['From'];
  var msg = request.body['Body'];
  var key = sender+msg
  var server = cons.getNode(key);
  var options = {
    hostname: '104.131.27.67',
    port: map_to_num[server],
    path: '/sms',
    method: 'POST',
    headers: {
      'MessageLength': msg.length
    }
  };
  console.log('reached here')
  var req = http.request(options, (res) => {
    console.log(`STATUS: ${res.statusCode}`);
    console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
    res.setEncoding('utf8');
  });
  console.log(msg)
  req.write(msg);
  req.end();
}

var app = express();
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});
app.post('/sms', twilio.webhook(config.TWILIO_AUTH_TOKEN), get_fwd_number);

app.get('/', function(req, res) {
  res.send('Hello World!');
});

var server = app.listen(80, function() {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Refuge listening at http://%s:%s', host, port);

});
<|endoftext|>


<commit_before>"use strict"

// Wraps a net socket to give a simpler interface to Connection objects
// This object has two listeners (inside them, "this" refers to the wrapper object):
// onmessage(message: Buffer)
// onclose()
// And two methods:
// close()
// send(metadata: Buffer, data: Buffer)
function NetWrapper(socket) {
	var that = this
	this._socket = socket

	socket.once("finish", function () {
		that.onclose.call(that)
		that.ondata = null
		that.onclose = null
	})

	// Ignore errors
	socket.once("error", function () {})

	var cache = new Buffer(0)
	socket.on("readable", function () {
		var data = socket.read(), state, length, message
		if (!data) return
		cache = Buffer.concat([cache, data], cache.length+data.length)

		// Try to read messages
		while (true) {
			state = {buffer: cache, offset: 0}
			try {
				length = inflateData.readUint(state)
			} catch (e) {
				// We need to wait for more data
				if (!(e instanceof RangeError))
					that._protocolError()
				break
			}
			if (cache.length >= state.offset+length) {
				message = cache.slice(state.offset, state.offset+length)
				cache = cache.slice(state.offset+length)
				that.onmessage.call(that, message)
			} else
				break
		}
		if (cache.length > Context._maxBufferLength)
			// Buffer overflow
			that._socket.destroy()
	})
}

module.exports = NetWrapper
var Data = require("./Data.js")
var inflateData = require("./inflateData.js")
var Context = require("./Context.js")

NetWrapper.prototype.close = function () {
	this._socket.end()
}

NetWrapper.prototype.send = function (metadata, data) {
	var length = new Data().addUint(metadata.length+data.length).toBuffer()
	this._socket.write(length)
	this._socket.write(metadata)
	this._socket.write(data)
}
<commit_msg>Error with closed connections<commit_after>"use strict"

// Wraps a net socket to give a simpler interface to Connection objects
// This object has two listeners (inside them, "this" refers to the wrapper object):
// onmessage(message: Buffer)
// onclose()
// And two methods:
// close()
// send(metadata: Buffer, data: Buffer)
function NetWrapper(socket) {
	var that = this
	this._socket = socket

	socket.once("finish", function () {
		that.onclose.call(that)
		that.ondata = null
		that.onclose = null
	})

	// Ignore errors
	socket.on("error", function () {})

	var cache = new Buffer(0)
	socket.on("readable", function () {
		var data = socket.read(), state, length, message
		if (!data) return
		cache = Buffer.concat([cache, data], cache.length+data.length)

		// Try to read messages
		while (true) {
			state = {buffer: cache, offset: 0}
			try {
				length = inflateData.readUint(state)
			} catch (e) {
				// We need to wait for more data
				if (!(e instanceof RangeError))
					that._protocolError()
				break
			}
			if (cache.length >= state.offset+length) {
				message = cache.slice(state.offset, state.offset+length)
				cache = cache.slice(state.offset+length)
				that.onmessage.call(that, message)
			} else
				break
		}
		if (cache.length > Context._maxBufferLength)
			// Buffer overflow
			that._socket.destroy()
	})
}

module.exports = NetWrapper
var Data = require("./Data.js")
var inflateData = require("./inflateData.js")
var Context = require("./Context.js")

NetWrapper.prototype.close = function () {
	this._socket.end()
}

NetWrapper.prototype.send = function (metadata, data) {
	var length = new Data().addUint(metadata.length+data.length).toBuffer()
	this._socket.write(length)
	this._socket.write(metadata)
	this._socket.write(data)
}
<|endoftext|>


<commit_before>
// @require ../init.js

(function ( _ ) {

  /* CLONE DEEP */ // Much smaller than lodash's implementation

  _.cloneDeep = function ( obj ) {

    if ( obj === null || typeof ( obj ) !== 'object' || _.isElement ( obj ) || '__is_cloning__' in obj ) return obj;

    const dupe = obj instanceof Date ? new obj.constructor () : obj.constructor ();

    for ( let key in obj ) {

      if ( !obj.hasOwnProperty ( key ) ) continue;

      obj['__is_cloning__'] = true;

      dupe[key] = _.cloneDeep ( obj[key] );

      delete obj['__is_cloning__'];

    }

    return dupe;

  };

}( window.__svelto_lodash ));
<commit_msg>cloneDeep: improved support for regexes and jQuery objs<commit_after>
// @require ../init.js

(function ( _ ) {

  /* CLONE DEEP */ // Much smaller than lodash's implementation

  _.cloneDeep = function ( obj ) {

    if ( obj === null || typeof ( obj ) !== 'object' || _.isElement ( obj ) || _.isRegExp ( obj ) || 'jquery' in obj || '__is_cloning__' in obj ) return obj;

    const dupe = obj instanceof Date ? new obj.constructor () : obj.constructor ();

    for ( let key in obj ) {

      if ( !obj.hasOwnProperty ( key ) ) continue;

      obj['__is_cloning__'] = true;

      dupe[key] = _.cloneDeep ( obj[key] );

      delete obj['__is_cloning__'];

    }

    return dupe;

  };

}( window.__svelto_lodash ));
<|endoftext|>


<commit_before>var exec= require('child_process').exec;
var tt = 0;
var cmd ='./nodejs_app/nodeon.sh & tt=$!' ;

var t=exec(cmd,function (error,stdout, stderr){
	tt=stdout.replace('\r\n','');
});

exec("./nodejs_app/nodeoff.sh");
console.log(tt);
if(tt=0)
return 0;
else return 1;
<commit_msg>Update testsA.js<commit_after>var exec= require('child_process').exec;
var tt = 0;
var cmd ='./nodejs_app/nodeon.sh & tt=$!' ;

var t=exec(cmd,function (error,stdout, stderr){
	tt=stdout.replace('\r\n','');
});

exec("./nodejs_app/nodeoff.sh");

if(tt=0)
return 0;
else return 1;
console.log(tt);
<|endoftext|>


<commit_before>import { inject } from 'aurelia-framework';
import { json } from 'aurelia-fetch-client';
import { ValidationControllerFactory, ValidationRules, Validator, validateTrigger } from 'aurelia-validation';
import { App } from '../app';
import { FormValidator } from '../classes/FormValidator';

const commonUtils = require('../commons/utils');

@inject(App, ValidationControllerFactory, Validator)
export class VolunteerOpps {
  controller = null;
  validator = null;

  constructor(app, controllerFactory, validator) {
    this.app = app;
    this.selectedTalents = [];
    this.selectedWorks = [];
    this.newEvent = true;
    this.showCheckboxes = commonUtils.showCheckboxes;
    this.validator2 = new FormValidator(validator, results => this.updateCanSubmit2(results));
    this.controller2 = controllerFactory.createForCurrentScope(this.validator2);
    this.controller2.validateTrigger = validateTrigger.changeOrBlur;
    this.canSubmit2 = false;
    this.newAddress = false;
    this.charity = {};
    this.voOpp = {};
    this.showVolunteers = false;
    this.events = [];
  }

  async activate() {
    this.counter = 1;
    this.canSubmit2 = false;
    this.showVolunteers = false;
    this.uid = this.app.auth.getTokenPayload().sub;
    this.user = await this.app.appState.getUser(this.uid);
    this.app.role = this.user.userType;
    const currentUrl = (window.location.href);
    this.charityID = currentUrl.substring(currentUrl.indexOf('vol-ops/') + 8);
    const res = await this.app.httpClient.fetch(`/volopp/${this.charityID}`);
    this.events = await res.json();
    await this.makeDataTable();
  }

  makeDataTable() {
    if (this.events.length > 0) {
      this.events = commonUtils.fixDates(this.events);
      this.app.buildPTag(this.events, 'voWorkTypes', 'voWorkTypeOther ', 'workHtml');
      this.app.buildPTag(this.events, 'voTalentTypes', 'voTalentTypeOther', 'talentHtml');
      this.checkScheduled();
      commonUtils.markPast(this.events, commonUtils.formatDate);
    }
    this.findCharity();
    this.talents = ['music', 'athletics', 'childcare', 'mechanics', 'construction', 'computers', 'communication', 'chess playing', 'listening'];
    this.works = ['hashbrown slinging', 'nail hammering', 'leaf removal', 'floor mopping', 'counseling', 'visitation'];
    this.talents.sort();
    this.talents.push('other');
    this.works.sort();
    this.works.push('other');
    this.today = new Date().toISOString().split('T')[0];
    this.minEndDate = this.today;
    this.maxStartDate = '';
  }

  async checkScheduled() {
    for (const i of this.events) {
      i.voNumPeopleScheduled = 0;
      for (const j of i.voPeopleScheduled) {
        try {
          this.app.httpClient.fetch(`/user/${j}`);
        } catch (err) {
          // user does not exist, remove it from voPeopleScheduled and update this event, then run make data makeDataTable
          // console.log('user does not exist');
          i.voPeopleScheduled = i.voPeopleScheduled.filter(e => e !== j);
          this.app.updateById('/volopp/', i._id, i);
          return this.makeDataTable();
        }
      }
      i.voNumPeopleScheduled = i.voPeopleScheduled.length;
    }
    return null;
  }

  async viewPeople(thisevent) {
    this.showVolunteers = true;
    let res, person;
    this.allPeople = [];
    for (let i = 0; i < thisevent.voPeopleScheduled.length; i += 1) {
      res = this.app.httpClient.fetch(`/user/${thisevent.voPeopleScheduled[i]}`);
      // console.log(res);
      person = res.json();
      this.allPeople.push(person);
    }
    this.eventTitle = thisevent.voName;
    const display = document.getElementById('showvolunteers');
    display.scrollIntoView();
  }

  selectDate(dtype) {
    if (dtype === 'start-date') {
      this.minEndDate = this.voOpp.voStartDate;
    } else {
      this.maxStartDate = this.voOpp.voEndDate;
    }
  }

  async findCharity() {
    const res2 = await this.app.httpClient.fetch(`/charity/find/${this.charityID}`);
    this.charity = await res2.json();
    this.voOpp.voCharityName = this.charity.charityName;
    this.voOpp.voStreet = this.charity.charityStreet;
    this.voOpp.voCity = this.charity.charityCity;
    this.voOpp.voState = this.charity.charityState;
    this.voOpp.voZipCode = this.charity.charityZipCode;
    this.voOpp.voCharityTypes = this.charity.charityTypes;
    /* istanbul ignore else */
    if (this.charity.charityTypeOther !== '') {
      const index = this.voOpp.voCharityTypes.indexOf('other');
      /* istanbul ignore else */
      if (index > -1) {
        this.voOpp.voCharityTypes.splice(index, 1);
      }
      this.voOpp.voCharityTypes.push(this.charity.charityTypeOther);
    }
  }

  scheduleEvent() {
    this.voOpp.voStatus = 'new';
    this.app.httpClient.fetch('/volopp/create', { method: 'post', body: json(this.voOpp) })
      .then(() => {
        this.voOpp = {};
        document.getElementById('eventHeader').scrollIntoView();
        this.activate();
      });
  }

  showUpdateEvent(thisEvent, type) {
    if (type === 'update') {
      this.newEvent = false;
      this.canSubmit2 = false;
      document.getElementById('topSection').style.display = 'none';
      this.voOpp = thisEvent;
    }
    this.app.selectPickedChange(this.voOpp, this, 'voTalentTypes', 'voTalentTypeOther', 'talentOther');
    this.app.selectPickedChange(this.voOpp, this, 'voWorkTypes', 'voWorkTypeOther', 'workOther');
    // this.updateCanSubmit2([{result: {valid: false}}]);
    const nub = document.getElementById('updateScheduleEvent');
    if (nub !== null) {
      nub.style.display = 'none';
    }
    this.setupValidation2();
    this.controller2.validate();
  }

  showNewEvent() {
    this.voOpp = {
      voName: '',
      voCharityId: this.charityID,
      voNumPeopleNeeded: 1,
      voDescription: '',
      voWorkTypes: [],
      voTalentTypes: [],
      voWorkTypeOther: '',
      voTalentTypeOther: '',
      voStartDate: null,
      voStartTime: '',
      voEndDate: null,
      voEndTime: '',
      voContactName: this.user.name,
      voContactEmail: this.user.email,
      voContactPhone: this.user.userPhone
    };
    this.voOpp.voCharityName = this.charity.charityName;
    this.voOpp.voStreet = this.charity.charityStreet;
    this.voOpp.voCity = this.charity.charityCity;
    this.voOpp.voState = this.charity.charityState;
    this.voOpp.voZipCode = this.charity.charityZipCode;
    this.newEvent = true;
    const topSection = document.getElementById('topSection');
    topSection.style.display = 'block';
    topSection.scrollIntoView();
    this.showUpdateEvent(null, 'new');
  }

  cancelEvent(theEvent) {
    this.voOpp = theEvent;
    this.updateEvent('cancel');
    if (this.voOpp.voDescription !== undefined) {
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
The Charity Has Reactivated This Event'
        + '
', '');
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
The Charity Has Updated Details About'
        + ' This Event
', '');
      this.voOpp.voDescription = `
The Charity Has Cancelled This Event

${this.voOpp.voDescription}`;
    }
  }

  reactivateEvent(theEvent) {
    this.voOpp = theEvent;
    if (this.voOpp.voDescription !== undefined) {
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
'
        + 'The Charity Has Updated Details About This Event
', '');
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
The Charity Has Cancelled This '
        + 'Event
', '
The Charity Has Reactivated This Event
');
    }
    this.updateEvent('reactivate');
  }

  async updateEvent(updateType) {
    this.voOpp.voStatus = updateType;
    if (updateType === 'update') {
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
'
        + 'The Charity Has Updated Details About This Event
', '');
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
'
        + 'The Charity Has Updated Details About This Event
', '');
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
'
        + 'The Charity Has Reactivated This Event
', '');
      this.voOpp.voDescription = `
The Charity Has Updated Details About This Event

${this.voOpp.voDescription}`;
    }
    await this.app.updateById('/volopp/', this.voOpp._id, this.voOpp);
    if (process.env.NODE_ENV !== 'test') {
      window.location.reload();
    }
    // this.activate();
  }

  async deleteEvent(thisEventId) {
    await fetch;
    this.app.httpClient.fetch(`/volopp/${thisEventId}`, { method: 'delete' })
      .then(() => {
        this.activate();
      });
  }

  updateCanSubmit2(validationResults) {
    let valid = true;
    const nub = document.getElementsByClassName('updateButton')[0];
    if (nub !== undefined) nub.style.display = 'none';
    for (const result of validationResults) {
      if (result.valid === false) {
        valid = false;
        break;
      }
    }
    this.canSubmit2 = valid;
    if (this.canSubmit2) {
      if (this.counter !== 1 || !this.updateEvent) {
        nub.style.display = 'block';
      }
      this.counter += 1;
    }
    return this.canSubmit2;
  }

  /* istanbul ignore next */
  setupValidation2() {
    ValidationRules
      .ensure('voContactPhone').matches(/\b[2-9]\d{9}\b/).withMessage('10 digits only')
      .ensure('voContactEmail').email()
      .ensure('voName').required().withMessage('Event Name is required').maxLength(40)
      .ensure('voNumPeopleNeeded').required().withMessage('How Many Volunteers please')
      .ensure('voStartTime').required().withMessage('Event Start time is required')
      .ensure('voEndTime').required().withMessage('Event End time is required')
      .satisfies(val => (this.voOpp.voEndDate > this.voOpp.voStartDate || commonUtils.compareTime(val, this.voOpp.voStartTime)))
      .ensure('voStartDate').required().withMessage('Event Start Date is required')
      .ensure('voEndDate').required().withMessage('Event End Date is required')
      .ensure('voZipCode').required().withMessage('5-digit Zipcode is required').matches(/\b\d{5}\b/)
      .ensure('voCity').required().withMessage('Event City is required').matches(/[^0-9]+/).maxLength(30)
      .ensure('voStreet').required().withMessage('Event Street Address is required').maxLength(40)
      .ensure('voState').required().withMessage('Event State is required')
      .on(this.voOpp);
  }

  onlyPositive() {
    if (this.voOpp.voNumPeopleNeeded < 1) {
      this.voOpp.voNumPeopleNeeded = 1;
    }
  }

  selectPickChange(type) {
    this.selectedTalents = this.voOpp.voTalentTypes;
    this.selectedWorks = this.voOpp.voWorkTypes;
    if (type === 'work') {
      this.app.selectPickedChange(this.user, this, 'selectedWorks', 'volWorkOther', 'workOther', true, 'volWorkPrefs');
    }
    if (type === 'talents') {
      this.app.selectPickedChange(this.user, this, 'selectedTalents', 'volTalentOther', 'talentOther', true, 'volTalents');
    }
  }

  clickaChooAndChaa(position) {
    const element = document.querySelector(`#${position} input`);
    element.click();
  }

  attached() {
    this.showNewEvent();
    this.setupValidation2();
  }
}
<commit_msg>fix date endtime validation and checkbox selection bug<commit_after>import { inject } from 'aurelia-framework';
import { json } from 'aurelia-fetch-client';
import { ValidationControllerFactory, ValidationRules, Validator, validateTrigger } from 'aurelia-validation';
import { App } from '../app';
import { FormValidator } from '../classes/FormValidator';

const commonUtils = require('../commons/utils');

@inject(App, ValidationControllerFactory, Validator)
export class VolunteerOpps {
  controller = null;
  validator = null;

  constructor(app, controllerFactory, validator) {
    this.app = app;
    this.selectedTalents = [];
    this.selectedWorks = [];
    this.newEvent = true;
    this.showCheckboxes = commonUtils.showCheckboxes;
    this.validator2 = new FormValidator(validator, results => this.updateCanSubmit2(results));
    this.controller2 = controllerFactory.createForCurrentScope(this.validator2);
    this.controller2.validateTrigger = validateTrigger.changeOrBlur;
    this.canSubmit2 = false;
    this.newAddress = false;
    this.charity = {};
    this.voOpp = {};
    this.showVolunteers = false;
    this.events = [];
  }

  async activate() {
    this.counter = 1;
    this.canSubmit2 = false;
    this.showVolunteers = false;
    this.uid = this.app.auth.getTokenPayload().sub;
    this.user = await this.app.appState.getUser(this.uid);
    this.app.role = this.user.userType;
    const currentUrl = (window.location.href);
    this.charityID = currentUrl.substring(currentUrl.indexOf('vol-ops/') + 8);
    const res = await this.app.httpClient.fetch(`/volopp/${this.charityID}`);
    this.events = await res.json();
    await this.makeDataTable();
  }

  makeDataTable() {
    if (this.events.length > 0) {
      this.events = commonUtils.fixDates(this.events);
      this.app.buildPTag(this.events, 'voWorkTypes', 'voWorkTypeOther ', 'workHtml');
      this.app.buildPTag(this.events, 'voTalentTypes', 'voTalentTypeOther', 'talentHtml');
      this.checkScheduled();
      commonUtils.markPast(this.events, commonUtils.formatDate);
    }
    this.findCharity();
    this.talents = ['music', 'athletics', 'childcare', 'mechanics', 'construction', 'computers', 'communication', 'chess playing', 'listening'];
    this.works = ['hashbrown slinging', 'nail hammering', 'leaf removal', 'floor mopping', 'counseling', 'visitation'];
    this.talents.sort();
    this.talents.push('other');
    this.works.sort();
    this.works.push('other');
    this.today = new Date().toISOString().split('T')[0];
    this.minEndDate = this.today;
    this.maxStartDate = '';
  }

  async checkScheduled() {
    for (const i of this.events) {
      i.voNumPeopleScheduled = 0;
      for (const j of i.voPeopleScheduled) {
        try {
          this.app.httpClient.fetch(`/user/${j}`);
        } catch (err) {
          // user does not exist, remove it from voPeopleScheduled and update this event, then run make data makeDataTable
          // console.log('user does not exist');
          i.voPeopleScheduled = i.voPeopleScheduled.filter(e => e !== j);
          this.app.updateById('/volopp/', i._id, i);
          return this.makeDataTable();
        }
      }
      i.voNumPeopleScheduled = i.voPeopleScheduled.length;
    }
    return null;
  }

  async viewPeople(thisevent) {
    this.showVolunteers = true;
    let res, person;
    this.allPeople = [];
    for (let i = 0; i < thisevent.voPeopleScheduled.length; i += 1) {
      res = this.app.httpClient.fetch(`/user/${thisevent.voPeopleScheduled[i]}`);
      // console.log(res);
      person = res.json();
      this.allPeople.push(person);
    }
    this.eventTitle = thisevent.voName;
    const display = document.getElementById('showvolunteers');
    display.scrollIntoView();
  }

  selectDate(dtype) {
    if (dtype === 'start-date') {
      this.minEndDate = this.voOpp.voStartDate;
    } else {
      this.maxStartDate = this.voOpp.voEndDate;
    }
  }

  async findCharity() {
    const res2 = await this.app.httpClient.fetch(`/charity/find/${this.charityID}`);
    this.charity = await res2.json();
    this.voOpp.voCharityName = this.charity.charityName;
    this.voOpp.voStreet = this.charity.charityStreet;
    this.voOpp.voCity = this.charity.charityCity;
    this.voOpp.voState = this.charity.charityState;
    this.voOpp.voZipCode = this.charity.charityZipCode;
    this.voOpp.voCharityTypes = this.charity.charityTypes;
    /* istanbul ignore else */
    if (this.charity.charityTypeOther !== '') {
      const index = this.voOpp.voCharityTypes.indexOf('other');
      /* istanbul ignore else */
      if (index > -1) {
        this.voOpp.voCharityTypes.splice(index, 1);
      }
      this.voOpp.voCharityTypes.push(this.charity.charityTypeOther);
    }
  }

  scheduleEvent() {
    this.voOpp.voStatus = 'new';
    this.app.httpClient.fetch('/volopp/create', { method: 'post', body: json(this.voOpp) })
      .then(() => {
        this.showNewEvent();
        document.getElementById('eventHeader').scrollIntoView();
        this.activate();
      });
  }

  showUpdateEvent(thisEvent, type) {
    if (type === 'update') {
      this.newEvent = false;
      this.canSubmit2 = false;
      document.getElementById('topSection').style.display = 'none';
      this.voOpp = thisEvent;
    }
    this.app.selectPickedChange(this.voOpp, this, 'voTalentTypes', 'voTalentTypeOther', 'talentOther');
    this.app.selectPickedChange(this.voOpp, this, 'voWorkTypes', 'voWorkTypeOther', 'workOther');
    // this.updateCanSubmit2([{result: {valid: false}}]);
    const nub = document.getElementById('updateScheduleEvent');
    if (nub !== null) {
      nub.style.display = 'none';
    }
    this.setupValidation2();
    this.controller2.validate();
  }

  showNewEvent() {
    this.voOpp = {
      voName: '',
      voCharityId: this.charityID,
      voNumPeopleNeeded: 1,
      voDescription: '',
      voWorkTypes: [],
      voTalentTypes: [],
      voWorkTypeOther: '',
      voTalentTypeOther: '',
      voStartDate: null,
      voStartTime: '',
      voEndDate: null,
      voEndTime: '',
      voContactName: this.user.name,
      voContactEmail: this.user.email,
      voContactPhone: this.user.userPhone
    };
    this.voOpp.voCharityName = this.charity.charityName;
    this.voOpp.voStreet = this.charity.charityStreet;
    this.voOpp.voCity = this.charity.charityCity;
    this.voOpp.voState = this.charity.charityState;
    this.voOpp.voZipCode = this.charity.charityZipCode;
    this.newEvent = true;
    const topSection = document.getElementById('topSection');
    topSection.style.display = 'block';
    topSection.scrollIntoView();
    this.showUpdateEvent(null, 'new');
  }

  cancelEvent(theEvent) {
    this.voOpp = theEvent;
    this.updateEvent('cancel');
    if (this.voOpp.voDescription !== undefined) {
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
The Charity Has Reactivated This Event'
        + '
', '');
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
The Charity Has Updated Details About'
        + ' This Event
', '');
      this.voOpp.voDescription = `
The Charity Has Cancelled This Event

${this.voOpp.voDescription}`;
    }
  }

  reactivateEvent(theEvent) {
    this.voOpp = theEvent;
    if (this.voOpp.voDescription !== undefined) {
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
'
        + 'The Charity Has Updated Details About This Event
', '');
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
The Charity Has Cancelled This '
        + 'Event
', '
The Charity Has Reactivated This Event
');
    }
    this.updateEvent('reactivate');
  }

  async updateEvent(updateType) {
    this.voOpp.voStatus = updateType;
    if (updateType === 'update') {
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
'
        + 'The Charity Has Updated Details About This Event
', '');
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
'
        + 'The Charity Has Updated Details About This Event
', '');
      this.voOpp.voDescription = this.voOpp.voDescription.replace('
'
        + 'The Charity Has Reactivated This Event
', '');
      this.voOpp.voDescription = `
The Charity Has Updated Details About This Event

${this.voOpp.voDescription}`;
    }
    await this.app.updateById('/volopp/', this.voOpp._id, this.voOpp);
    if (process.env.NODE_ENV !== 'test') {
      window.location.reload();
    }
    // this.activate();
  }

  async deleteEvent(thisEventId) {
    await fetch;
    this.app.httpClient.fetch(`/volopp/${thisEventId}`, { method: 'delete' })
      .then(() => {
        this.activate();
      });
  }

  updateCanSubmit2(validationResults) {
    let valid = true;
    const nub = document.getElementsByClassName('updateButton')[0];
    if (nub !== undefined) nub.style.display = 'none';
    for (const result of validationResults) {
      if (result.valid === false) {
        valid = false;
        break;
      }
    }
    this.canSubmit2 = valid;
    if (this.canSubmit2) {
      if (this.counter !== 1 || !this.updateEvent) {
        nub.style.display = 'block';
      }
      this.counter += 1;
    }
    return this.canSubmit2;
  }

  /* istanbul ignore next */
  setupValidation2() {
    ValidationRules
      .ensure('voContactPhone').matches(/\b[2-9]\d{9}\b/).withMessage('10 digits only')
      .ensure('voContactEmail').email()
      .ensure('voName').required().withMessage('Event Name is required').maxLength(40)
      .ensure('voNumPeopleNeeded').required().withMessage('How Many Volunteers please')
      .ensure('voStartTime').required().withMessage('Event Start time is required')
      .ensure('voEndTime').required().withMessage('Event End time is required')
      .satisfies(val => (this.voOpp.voEndDate > this.voOpp.voStartDate || commonUtils.compareTime(val, this.voOpp.voStartTime)))
      .withMessage('End time must be after start time')
      .ensure('voStartDate').required().withMessage('Event Start Date is required')
      .ensure('voEndDate').required().withMessage('Event End Date is required')
      .ensure('voZipCode').required().withMessage('5-digit Zipcode is required').matches(/\b\d{5}\b/)
      .ensure('voCity').required().withMessage('Event City is required').matches(/[^0-9]+/).maxLength(30)
      .ensure('voStreet').required().withMessage('Event Street Address is required').maxLength(40)
      .ensure('voState').required().withMessage('Event State is required')
      .on(this.voOpp);
  }

  onlyPositive() {
    if (this.voOpp.voNumPeopleNeeded < 1) {
      this.voOpp.voNumPeopleNeeded = 1;
    }
  }

  selectPickChange(type) {
    this.selectedTalents = this.voOpp.voTalentTypes;
    this.selectedWorks = this.voOpp.voWorkTypes;
    if (type === 'work') {
      this.app.selectPickedChange(this.user, this, 'selectedWorks', 'volWorkOther', 'workOther', true, 'volWorkPrefs');
    }
    if (type === 'talents') {
      this.app.selectPickedChange(this.user, this, 'selectedTalents', 'volTalentOther', 'talentOther', true, 'volTalents');
    }
  }

  clickaChooAndChaa(position) {
    const element = document.querySelector(`#${position} input`);
    element.click();
  }

  attached() {
    this.showNewEvent();
    this.setupValidation2();
  }
}
<|endoftext|>


<commit_before>var t = 0;
const exec = require('child_process').exec;
exec('node nodejs_app/app.js', (error, stdout, stderr) => {
  if (error) {
    console.error(`exec error: ${error}`);
	t =1;
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.log(`stderr: ${stderr}`);
});
return t;
<commit_msg>Update testsA.js<commit_after>var t = 0;
const exec = require('child_process').exec;
exec('node nodejs_app/app.js', (error, stdout, stderr) {
  if (error) {
    console.error(`exec error: ${error}`);
	t =1;
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.log(`stderr: ${stderr}`);
});
return t;
<|endoftext|>