<commit_before>export { PassThrough_FiltersArray_BiasesArray };
export { PassThrough_FiltersArray_BiasesArray_Bag };
export { PassThrough };

import * as TwoTensors from "../../util/TwoTensors.js";
import { PadInfoCalculator } from "./Depthwise_PadInfoCalculator.js";

/**
 * A depthwise convolution and bias which just pass the input to output.
 *
 * It is usually used in passing the higher half channels of the input to output (for achieving ShuffleNetV2_ByMopbileNetV1's body/tail).
 *
 * Note: Although depthwise (and pointwise) convolution could be past-through, the activation function will destroy the past-through
 * result. Using Pointwise_FiltersArray_BiasesArray may be better to handle this issue.
 *
 *
 * @member {number} filterValue
 *   The value used as the pass-through depthwise convolution filter. Default is 1. If there will be no activation function after this
 * pass-through operation, value 1 is enough. However, if there wiil be an activation function, this past-through result might be
 * destroyed by the activation function. In order to alleviate this issue, a non-one filter value should be used. For example, if
 * every input value's range is [ 0,255 ] and RELU6 will be used as activation function, using 0.015625 (= 1 / 64 ) as filterValue is
 * appropriate because input values will be shrinked from [ 0, 255 ] into [ 0, 3.984375 ] which will still be kept linear by RELU6.
 *
 * @member {number} biasValue
 *   The value used as the pass-through bias (used only if ( bBias == true ) ). Default is 0. If there will be no activation function
 * after this pass-through operation, value 0 is enough. However, if there wiil be an activation function, this past-through result
 * might be destroyed by the activation function. In order to alleviate this issue, a non-zero bias value should be used. For example,
 * if every input value's range is [ -2, +2 ] and RELU6 will be used as activation function, using +2 as biasValue is appropriate
 * because input values will be shifted from [ -2, +2 ] into [ 0, 4 ] which will still be kept linear by RELU6.
 *
 * @member {number[]} filtersShape
 *   The shape of the pass-through filters array.
 *
 * @member {number[]} biasesShape
 *   The shape of the pass-through biases array.
 *
 * @member {number[]} filtersArray
 *   The pass-through filters array.
 *
 * @member {number[]} biasesArray
 *   The pass-through biases array.
 *
 * @see PadInfoCalculator
 */
let PassThrough_FiltersArray_BiasesArray = ( Base = Object ) => class extends PadInfoCalculator( Base ) {

  /**
   */
  constructor(
    inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
    bBias, filterValue = 1, biasValue = 0 ) {

    super( inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad );

    this.bBias = bBias;
    this.filterValue = filterValue;
    this.biasValue = biasValue;

    this.filtersShape = [ this.filterHeight, this.filterWidth, this.inputChannelCount, this.channelMultiplier ];
    this.filtersArray = this.generate_PassThrough_FiltersArray( filterValue );

    if ( this.bBias ) {
      this.biasesShape =  [ 1, 1, this.outputChannelCount ];
      this.biasesArray = new Array( this.outputChannelCount );
      this.biasesArray.fill( biasValue );
    }

  }

}

/**
 * A pool for PassThrough_FiltersArray_BiasesArray with various parameters. It could reduce re-creating them of same parameters again
 * and again to improve performance.
 *
 */
class PassThrough_FiltersArray_BiasesArray_Bag extends MultiLayerMap.Bag {

  //constructor() {
  //  super();
  //}

  /**
   *
   */
  get_by_nPassThroughStyleId(
    inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
    nPassThroughStyleId ) {

    const thePassThroughStyleInfo = ValueDesc.PassThroughStyle.Singleton.getInfoById( nPassThroughStyleId );
    return this.get_by_filterValue_biasValue(
      inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
      thePassThroughStyleInfo.filterValue, thePassThroughStyleInfo.biasValue );
  }

  /**
   *
   */
  get_by_filterValue_biasValue(
    inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
    bBias, filterValue = 1, biasValue = 0 ) {

    return this.get_or_create_by_arguments1_etc( PassThrough_FiltersArray_BiasesArray_Bag.create_by,
      inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
      bBias, filterValue, biasValue );
  }

  /** */
  static create_by(
    inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
    bBias, filterValue, biasValue ) {

    return new ( Depthwise.PassThrough_FiltersArray_BiasesArray() )(
      inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
      bBias, filterValue, biasValue );
  }

}

/**
 * A depthwise convolution and bias which just pass the input to output.
 *
 * It is usually used in passing the higher half channels of the input to output (for achieving ShuffleNetV2_ByMopbileNetV1's body/tail).
 *
 *
 * @see PassThrough_FiltersArray_BiasesArray
 * @see PadInfoCalculator
 * @see TwoTensors.filtersTensor4d_biasesTensor3d
 */
class PassThrough extends PassThrough_FiltersArray_BiasesArray( PadInfoCalculator( TwoTensors.filtersTensor4d_biasesTensor3d() ) ) {

  /**
   */
  constructor(
    inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
    bBias, filterValue = 1, biasValue = 0 ) {

    super( inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
      bBias, filterValue, biasValue );

    this.filtersTensor4d = tf.tensor4d( this.filtersArray, this.filtersShape );

    if ( this.bBias ) {
      this.biasesTensor3d = tf.tensor3d( this.biasesArray, this.biasesShape );
    }

    this.bInitOk = true;
  }

}

<commit_msg>Update Depthwise_PassThrough.js<commit_after>export { PassThrough_FiltersArray_BiasesArray };
export { PassThrough_FiltersArray_BiasesArray_Bag };
export { PassThrough };

import * as TwoTensors from "../../util/TwoTensors.js";
import { PadInfoCalculator } from "./Depthwise_PadInfoCalculator.js";

/**
 * A depthwise convolution and bias which just pass the input to output.
 *
 * It is usually used in passing the higher half channels of the input to output (for achieving ShuffleNetV2_ByMopbileNetV1's body/tail).
 *
 * Note: Although depthwise (and pointwise) convolution could be past-through, the activation function will destroy the past-through
 * result. Using Pointwise_FiltersArray_BiasesArray may be better to handle this issue.
 *
 *
 * @member {number} filterValue
 *   The value used as the pass-through depthwise convolution filter. Default is 1. If there will be no activation function after this
 * pass-through operation, value 1 is enough. However, if there wiil be an activation function, this past-through result might be
 * destroyed by the activation function. In order to alleviate this issue, a non-one filter value should be used. For example, if
 * every input value's range is [ 0,255 ] and RELU6 will be used as activation function, using 0.015625 (= 1 / 64 ) as filterValue is
 * appropriate because input values will be shrinked from [ 0, 255 ] into [ 0, 3.984375 ] which will still be kept linear by RELU6.
 *
 * @member {number} biasValue
 *   The value used as the pass-through bias (used only if ( bBias == true ) ). Default is 0. If there will be no activation function
 * after this pass-through operation, value 0 is enough. However, if there wiil be an activation function, this past-through result
 * might be destroyed by the activation function. In order to alleviate this issue, a non-zero bias value should be used. For example,
 * if every input value's range is [ -2, +2 ] and RELU6 will be used as activation function, using +2 as biasValue is appropriate
 * because input values will be shifted from [ -2, +2 ] into [ 0, 4 ] which will still be kept linear by RELU6.
 *
 * @member {number[]} filtersShape
 *   The shape of the pass-through filters array.
 *
 * @member {number[]} biasesShape
 *   The shape of the pass-through biases array.
 *
 * @member {number[]} filtersArray
 *   The pass-through filters array.
 *
 * @member {number[]} biasesArray
 *   The pass-through biases array.
 *
 * @see PadInfoCalculator
 */
let PassThrough_FiltersArray_BiasesArray = ( Base = Object ) => class extends PadInfoCalculator( Base ) {

  /**
   */
  constructor(
    inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
    bBias, filterValue = 1, biasValue = 0 ) {

    super( inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad );

    this.bBias = bBias;
    this.filterValue = filterValue;
    this.biasValue = biasValue;

    this.filtersShape = [ this.filterHeight, this.filterWidth, this.inputChannelCount, this.channelMultiplier ];
    this.filtersArray = this.generate_PassThrough_FiltersArray( filterValue );

    if ( this.bBias ) {
      this.biasesShape =  [ 1, 1, this.outputChannelCount ];
      this.biasesArray = new Array( this.outputChannelCount );
      this.biasesArray.fill( biasValue );
    }

  }

}

/**
 * A pool for PassThrough_FiltersArray_BiasesArray with various parameters. It could reduce re-creating them of same parameters again
 * and again to improve performance.
 *
 */
class PassThrough_FiltersArray_BiasesArray_Bag extends MultiLayerMap.Bag {

  //constructor() {
  //  super();
  //}

  /**
   *
   */
  get_by_PassThroughStyleId(
    inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
    nPassThroughStyleId ) {

    const thePassThroughStyleInfo = ValueDesc.PassThroughStyle.Singleton.getInfoById( nPassThroughStyleId );
    return this.get_by_filterValue_biasValue(
      inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
      thePassThroughStyleInfo.filterValue, thePassThroughStyleInfo.biasValue );
  }

  /**
   *
   */
  get_by_filterValue_biasValue(
    inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
    bBias, filterValue = 1, biasValue = 0 ) {

    return this.get_or_create_by_arguments1_etc( PassThrough_FiltersArray_BiasesArray_Bag.create_by,
      inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
      bBias, filterValue, biasValue );
  }

  /** */
  static create_by(
    inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
    bBias, filterValue, biasValue ) {

    return new ( Depthwise.PassThrough_FiltersArray_BiasesArray() )(
      inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
      bBias, filterValue, biasValue );
  }

}

/**
 * A depthwise convolution and bias which just pass the input to output.
 *
 * It is usually used in passing the higher half channels of the input to output (for achieving ShuffleNetV2_ByMopbileNetV1's body/tail).
 *
 *
 * @see PassThrough_FiltersArray_BiasesArray
 * @see PadInfoCalculator
 * @see TwoTensors.filtersTensor4d_biasesTensor3d
 */
class PassThrough extends PassThrough_FiltersArray_BiasesArray( PadInfoCalculator( TwoTensors.filtersTensor4d_biasesTensor3d() ) ) {

  /**
   */
  constructor(
    inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
    bBias, filterValue = 1, biasValue = 0 ) {

    super( inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth, stridesPad,
      bBias, filterValue, biasValue );

    this.filtersTensor4d = tf.tensor4d( this.filtersArray, this.filtersShape );

    if ( this.bBias ) {
      this.biasesTensor3d = tf.tensor3d( this.biasesArray, this.biasesShape );
    }

    this.bInitOk = true;
  }

}

<|endoftext|>


<commit_before>angular.module('home', [
  'utils'
])

.controller('homeController', [
  '$scope',
  '$http',
  '$state',
  '$stateParams',
  '$location',
  'fileTransfer',
  'linkGeneration',
  'webRTC',
  'packetHandlers',
  function($scope, $http, $state, $stateParams, $location, fileTransfer, linkGeneration, webRTC, packetHandlers) {
    console.log('home controller loaded');

    fileTransfer.myItems = [];
    fileTransfer.conn = [];

    var disconnectingSenderId = null;
    var generateLink = function() {
      $scope.hash = linkGeneration.guid();
      $stateParams.test = $scope.hash;
      $location.path('/' + $scope.hash);
    };

    document.getElementById('filesId').addEventListener('change', function() {

      var files = this.files;
      for (var i = 0; i < files.length; i++) {
        if (fileTransfer.myItems.indexOf(files[i]) > -1) {
          continue;
        }
        files[i].beenSent = false;
        fileTransfer.myItems.push(files[i]);
      }

      if (!fileTransfer.peer) {

        fileTransfer.peer = webRTC.createPeer();
        console.log('SENDER peer created');
        fileTransfer.peer.on('open', function(id) {
          disconnectingSenderId = id;
          // TODO: create special link to send with post in data
          $http({
              method: 'POST',
              url: '/api/webrtc/users',
              data: {
                userId: id,
                hash: $scope.hash
              }
            })
            .then(function(result) {
              console.log('SENDER\'s POST response', result.data);
            });
        });

        fileTransfer.peer.on('connection', function(conn) {
          // TODO: add file inside call to send
          fileTransfer.conn.push(conn);
          console.log('peerJS connection object', conn);

          setTimeout(function() {
            fileTransfer.conn.forEach(function(connection) {
              for (var i = 0; i < fileTransfer.myItems.length; i++) {
                if (!fileTransfer.myItems[i].beenSent) {
                  fileTransfer.myItems[i].beenSent = true;
                  console.log('files offered');
                  connection.send({
                    name: fileTransfer.myItems[i].name,
                    size: fileTransfer.myItems[i].size,
                    type: 'file-offer'
                  });
                }
              }
            });
          }, 1800);

          conn.on('data', function(data) {
            if (data.type === 'file-accepted') {
              packetHandlers.accepted(data, conn, $scope);
            } else if (data.type === 'file-offer') {
              packetHandlers.offer(data, conn);
            } else if (data.type === 'file-chunk') {
              packetHandlers.chunk(data, fileTransfer);
            }
          });
        });
        generateLink();
      }

      window.onbeforeunload = function() {
        return ("Your connection will end");
      };

      window.addEventListener('beforeunload', function() {
        console.log("DISCONNECTED")
        $http({
          method: 'POST',
          url: '/api/webrtc/deleteSenderObject',
          data: {
            userId: disconnectingSenderId
          }
        })
      });

    });

    $scope.testParams = $stateParams;

  }
]);
<commit_msg>[fix] Fix notification box, no longer popping up on exiting window to homeController.js<commit_after>angular.module('home', [
  'utils'
])

.controller('homeController', [
  '$scope',
  '$http',
  '$state',
  '$stateParams',
  '$location',
  'fileTransfer',
  'linkGeneration',
  'webRTC',
  'packetHandlers',
  function($scope, $http, $state, $stateParams, $location, fileTransfer, linkGeneration, webRTC, packetHandlers) {
    console.log('home controller loaded');

    fileTransfer.myItems = [];
    fileTransfer.conn = [];

    var disconnectingSenderId = null;
    var generateLink = function() {
      $scope.hash = linkGeneration.guid();
      $stateParams.test = $scope.hash;
      $location.path('/' + $scope.hash);
    };

    document.getElementById('filesId').addEventListener('change', function() {

      var files = this.files;
      for (var i = 0; i < files.length; i++) {
        if (fileTransfer.myItems.indexOf(files[i]) > -1) {
          continue;
        }
        files[i].beenSent = false;
        fileTransfer.myItems.push(files[i]);
      }

      if (!fileTransfer.peer) {

        fileTransfer.peer = webRTC.createPeer();
        console.log('SENDER peer created');
        fileTransfer.peer.on('open', function(id) {
          disconnectingSenderId = id;
          // TODO: create special link to send with post in data
          $http({
              method: 'POST',
              url: '/api/webrtc/users',
              data: {
                userId: id,
                hash: $scope.hash
              }
            })
            .then(function(result) {
              console.log('SENDER\'s POST response', result.data);
            });
        });

        fileTransfer.peer.on('connection', function(conn) {
          // TODO: add file inside call to send
          fileTransfer.conn.push(conn);
          console.log('peerJS connection object', conn);

          setTimeout(function() {
            fileTransfer.conn.forEach(function(connection) {
              for (var i = 0; i < fileTransfer.myItems.length; i++) {
                if (!fileTransfer.myItems[i].beenSent) {
                  fileTransfer.myItems[i].beenSent = true;
                  console.log('files offered');
                  connection.send({
                    name: fileTransfer.myItems[i].name,
                    size: fileTransfer.myItems[i].size,
                    type: 'file-offer'
                  });
                }
              }
            });
          }, 1800);

          conn.on('data', function(data) {
            if (data.type === 'file-accepted') {
              packetHandlers.accepted(data, conn, $scope);
            } else if (data.type === 'file-offer') {
              packetHandlers.offer(data, conn);
            } else if (data.type === 'file-chunk') {
              packetHandlers.chunk(data, fileTransfer);
            }
          });
        });
        generateLink();
      }

      window.onbeforeunload = function(e) {
        e.preventDefault();
        //stops notification from showing
      }

      window.addEventListener('beforeunload', function() {
        console.log("DISCONNECTED")
        $http({
          method: 'POST',
          url: '/api/webrtc/deleteSenderObject',
          data: {
            userId: disconnectingSenderId
          }
        })
      });

    });

    $scope.testParams = $stateParams;

  }
]);<|endoftext|>


<commit_before>export { HTMLTable_Operator as Operator };

import * as Pool from "../../util/Pool.js";
import * as Recyclable from "../../util/Recyclable.js";

/**
 * Append table row into a HTMLTable.
 *
 *
 * @member {string} htmlTableElementId
 *   The HTML table element id for displaying data.
 *
 * @member {number} digitsCount
 *   For number data, it will be converted to text by toFix() with digitsCount (i.e.
 * the number of digits to appear after the decimal point).
 */
class HTMLTable_Operator extends Recyclable.Root {

  /**
   * Used as default HTMLTable.Operator provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "HTMLTable.Operator.Pool",
    HTMLTable_Operator, HTMLTable_Operator.setAsConstructor );

  /** */
  constructor( htmlTableElementId, digitsCount = 4 ) {
    super();
    HTMLTable_Operator.setAsConstructor_self.call( this,
      htmlTableElementId, digitsCount );
  }

  /** @override */
  static setAsConstructor( htmlTableElementId, digitsCount ) {
    super.setAsConstructor();
    HTMLTable_Operator.setAsConstructor_self.call( this,
      htmlTableElementId, digitsCount );
    return this;
  }

  /** @override */
  static setAsConstructor_self( htmlTableElementId, digitsCount ) {
    this.htmlTableElementId = htmlTableElementId;
    this.digitsCount = digitsCount;
  }

  /** @override */
  disposeResources() {
    this.digitsCount = undefined;
    this.htmlTableElementId = undefined;
    this.htmlTableElement = undefined;
    super.disposeResources();
  }

  /** If .htmlTableElement undefined, preare it by .htmlTableElementId.  */
  Table_ensure() {
    if ( this.htmlTableElement )
      return;
    if ( !document )
      return;
    if ( !this.htmlTableElementId )
      return;
    this.htmlTableElement = document.getElementById( this.htmlTableElementId );
  }

  /** Ensure table header. */
  TableHeader_ensure() {
    this.Table_ensure();
    if ( this.htmlTableElement.tHead )
      return;
    this.htmlTableElement.createTHead();
  }

  /* Ensure table body. */
  TableBody_ensure() {
    this.Table_ensure();
    if ( this.htmlTableElement.tBodies.length > 0 )
      return;
    this.htmlTableElement.createTBody();
  }

  /**
   * @return {boolean}
   *   Return true, if the table header already has content.
   */
  Header_hasChild() {
    this.TableHeader_ensure();
    if ( this.htmlTableElement.tHead.childElementCount > 0 )
      return true;
    return false;
  }

  /**
   * @param {string[]|number[]} dataArray
   *   Append the data as the last row of the table header.
   */
  Header_addRow( dataArray ) {
    this.TableHeader_ensure();
    HTMLTable_Operator.Section_addRow.call( this,
      this.htmlTableElement.tHead,
      "th", // Table header always uses "th".
      dataArray );
  }

  /**
   * @param {string[]|number[]} dataArray
   *   Append the data as the last row of the table body.
   */
  Body_addRow( dataArray ) {
    this.TableBody_ensure();
    HTMLTable_Operator.Section_addRow.call( this,
      this.htmlTableElement.tBodies[ 0 ],
      "td", // Table body mainly uses "td" (except first column).
      dataArray );
  }

  /**
   * @param {Node} htmlNode
   *   The HTML DOM Node which will the new row will be inserted. For HTML table,
   * it could be .tHead or .tBodies or .tFoot.
   *
   * @param {string} th_OR_td  "th" for table header, "td" for table body.
   *   "th" for table header cell, "td" for table data cell.
   *
   * @param {string[]|number[]} dataArray
   *   The data to be displaye
   */
  static Section_addRow( htmlNode, th_OR_td, dataArray ) {
    let oneLine = document.createElement( "tr" );

    let cellElementName;
    let textAlign;
    let data, dataText;
    for ( let i = 0; i < dataArray.length; ++i ) {
      data = dataArray[ i ];

      if ( typeof data === "number" ) {
        textAlign = "right";
        dataText = data.toFixed( this.digitsCount );
      } else {
        textAlign = "left";
        dataText = data;
      }

      if ( 0 == i )
        cellElementName = "th"; // First column always use
      else
        cellElementName = th_OR_td;

      let oneCell = document.createElement( cellElementName );
      oneCell.style.textAlign = textAlign;

      oneCell.appendChild( document.createTextNode( dataText ) );
      oneLine.appendChild( oneCell );
    }

    htmlNode.appendChild( oneLine );
  }

}
<commit_msg>Table header always align to center.<commit_after>export { HTMLTable_Operator as Operator };

import * as Pool from "../../util/Pool.js";
import * as Recyclable from "../../util/Recyclable.js";

/**
 * Append table row into a HTMLTable.
 *
 *
 * @member {string} htmlTableElementId
 *   The HTML table element id for displaying data.
 *
 * @member {number} digitsCount
 *   For number data, it will be converted to text by toFix() with digitsCount (i.e.
 * the number of digits to appear after the decimal point).
 */
class HTMLTable_Operator extends Recyclable.Root {

  /**
   * Used as default HTMLTable.Operator provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "HTMLTable.Operator.Pool",
    HTMLTable_Operator, HTMLTable_Operator.setAsConstructor );

  /** */
  constructor( htmlTableElementId, digitsCount = 4 ) {
    super();
    HTMLTable_Operator.setAsConstructor_self.call( this,
      htmlTableElementId, digitsCount );
  }

  /** @override */
  static setAsConstructor( htmlTableElementId, digitsCount ) {
    super.setAsConstructor();
    HTMLTable_Operator.setAsConstructor_self.call( this,
      htmlTableElementId, digitsCount );
    return this;
  }

  /** @override */
  static setAsConstructor_self( htmlTableElementId, digitsCount ) {
    this.htmlTableElementId = htmlTableElementId;
    this.digitsCount = digitsCount;
  }

  /** @override */
  disposeResources() {
    this.digitsCount = undefined;
    this.htmlTableElementId = undefined;
    this.htmlTableElement = undefined;
    super.disposeResources();
  }

  /** If .htmlTableElement undefined, preare it by .htmlTableElementId.  */
  Table_ensure() {
    if ( this.htmlTableElement )
      return;
    if ( !document )
      return;
    if ( !this.htmlTableElementId )
      return;
    this.htmlTableElement = document.getElementById( this.htmlTableElementId );
  }

  /** Ensure table header. */
  TableHeader_ensure() {
    this.Table_ensure();
    if ( this.htmlTableElement.tHead )
      return;
    this.htmlTableElement.createTHead();
  }

  /* Ensure table body. */
  TableBody_ensure() {
    this.Table_ensure();
    if ( this.htmlTableElement.tBodies.length > 0 )
      return;
    this.htmlTableElement.createTBody();
  }

  /**
   * @return {boolean}
   *   Return true, if the table header already has content.
   */
  Header_hasChild() {
    this.TableHeader_ensure();
    if ( this.htmlTableElement.tHead.childElementCount > 0 )
      return true;
    return false;
  }

  /**
   * @param {string[]|number[]} dataArray
   *   Append the data as the last row of the table header.
   */
  Header_addRow( dataArray ) {
    this.TableHeader_ensure();
    HTMLTable_Operator.Section_addRow.call( this,
      this.htmlTableElement.tHead,
      "th", // Table header always uses "th".
      dataArray );
  }

  /**
   * @param {string[]|number[]} dataArray
   *   Append the data as the last row of the table body.
   */
  Body_addRow( dataArray ) {
    this.TableBody_ensure();
    HTMLTable_Operator.Section_addRow.call( this,
      this.htmlTableElement.tBodies[ 0 ],
      "td", // Table body mainly uses "td" (except first column).
      dataArray );
  }

  /**
   * @param {Node} htmlNode
   *   The HTML DOM Node which will the new row will be inserted. For HTML table,
   * it could be .tHead or .tBodies or .tFoot.
   *
   * @param {string} th_OR_td  "th" for table header, "td" for table body.
   *   "th" for table header cell, "td" for table data cell.
   *
   * @param {string[]|number[]} dataArray
   *   The data to be displaye
   */
  static Section_addRow( htmlNode, th_OR_td, dataArray ) {
    let oneLine = document.createElement( "tr" );

    let cellElementName;
    let textAlign;
    let data, dataText;
    for ( let i = 0; i < dataArray.length; ++i ) {
      data = dataArray[ i ];

      if ( typeof data === "number" ) {
        textAlign = "right";
        dataText = data.toFixed( this.digitsCount );
      } else {
        textAlign = "left";
        dataText = data;
      }

      if ( 0 == i )
        cellElementName = "th"; // First column always use
      else
        cellElementName = th_OR_td;

      if ( htmlNode === this.htmlTableElement.tHead )
        textAlign = "center"; // c

      let oneCell = document.createElement( cellElementName );
      oneCell.style.textAlign = textAlign;

      oneCell.appendChild( document.createTextNode( dataText ) );
      oneLine.appendChild( oneCell );
    }

    htmlNode.appendChild( oneLine );
  }

}
<|endoftext|>


<commit_before>//Quote of the hour
  //changes every hour
(function () {
  'use strict';

  var React = require('react');
  var ReactRouter = require('react-router');
  var Link = ReactRouter.Link;

  var Navbar = React.createClass({

    render: function () {
      return (

            <Link to="/" className="navbar-brand">

            </Link>

<Link to="/">Home</Link>

<Link to="/article">Article</Link>

<Link to="/howitworks">How It Works</Link>

<Link to="/about">About Us</Link>

      );
    }
  });

  module.exports = Navbar;
})()
<commit_msg>Remove duplicate navbar<commit_after><|endoftext|>


<commit_before>import * as NetProgress from "../NetProgress.js";
import * as tdTextExtracter from "../../util/tdTextExtracter.js";
import * as Versus from "./Versus.js";

export { NetProgress, Base };

/**
 * Download differential evolution summary and individual versus (entity vs entity) from network (a publish html of Google Sheets).
 *
 * The format of differential evolution summary page is the following:
 *
 *
 *   PopulationSize
 *   EntityWeightCount
 *   EntityChromosomeCount
 *   gid|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|...
 *   gid|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|...
 *   gid|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|...
 *     :
 *     :
 *
 *
 * The PopulationSize represents how many entities in the differential evolution.
 * The EntityChromosomeCount represents How many chromsomes in one entity.
 * The ChromosomeWeightCount represents how many weights in one chromsome.
 *
 * The gid is the Google Sheet's id which will be used to form the url when download every individual versus.
 * Every gid contains one or more versus which are separated by vertical bar (|).
 * A versus contains versus id (EntityNo_ParentGenerationNo_OffspringGenerationNo) and its WinCount which are separated by colon (:).
 * A versus id contains EntityNo, ParentGenerationNo, OffspringGenerationNo which are separated by underline (_).
 *
 *
 */
class Base {

  /**
   *
   */
  constructor() {

    // Regular expression for splitting gid and every versus.
    this.gid_Versus_SplitRegExp = RegExp( "|", "g" );

    // Regular expression for splitting versus id and win count
    this.VersusId_WinCount_SplittingRegExp = RegExp( ":", "g" );

    // Regular expression for splitting ids of entity, parent generation, offspring generation.
    this.EntityNo_ParentGenerationNo_OffspringGenerationNo_SplittingRegExp = RegExp( "_", "g" );

    // Regular expression for replacing the "nnn" of "gid=nnn" inside the published web page URL.
    this.gidReplacingRegExp = RegExp( "(gid=)(\d+)", "g" );
  }

  /**
   * Fetch and extract.
   *
   * @param summaryURL
   *   The published (should be html, not tsv, not csv) web page URL of the summary sheet of the differential evolution Google Sheets. For example:
   * "https://docs.google.com/spreadsheets/d/e/2PACX-1vSzA4SXUR5VyPmJ1cLEkNMiJgfb28zzgp4HtwoBlumIIOTkL_y7mgPldqaGtsunIq5eTu5QndluyFcV/pubhtml?gid=0&single=true".
   * The "gid=0" inside the URL will be replaced with different number when downloading other published sheet.
   */
  async downloadSummary( summaryURL, progress ) {

    // Why using published html web page instead of tsv (or csv)? This is because Google Sheets' published html web page support cross-origin
    // resource sharing (CORS) while its published web page tsv (or csv) does not.
    this.summaryURL = summaryURL;

    let response = await fetch( this.summaryURL );

    let lineMatches = tdTextExtracter.Base.createIterator( response.text() ); // Only capture group 1 will be used.
    let lineMatch;

    if ( ( lineMatch = lineMatches.next() ).done )
      return;

    this.PopulationSize = Number.parseInt( lineMatch.value[ 1 ], 10 );

    if ( ( lineMatch = lineMatches.next() ).done )
      return;

    this.EntityChromosomeCount = Number.parseInt( lineMatch.value[ 1 ], 10 );

    if ( ( lineMatch = lineMatches.next() ).done )
      return;

    this.ChromosomeWeightCount = Number.parseInt( lineMatch.value[ 1 ], 10 );
    this.EntityWeightCount = this.EntityChromosomeCount * this.ChromosomeWeightCount; // So many weights in one entity.

    this.gid_versus_array = [];
    while ( !( lineMatch = lineMatch.next() ).done ) {

      let versus_string_array = lineMatch.value[ 1 ].split( this.gid_Versus_SplitRegExp ); // Split the text of a td tag.
      if ( versus_string_array.length <= 1 )
        continue; // At least, should be 2. The first one is gid, the second (and after) are versus ids (with win counts)

      // Got gid.
      let gid_versus = {
        gid: versus_string_array[ 0 ], // In fact, element 0 is gid.
        versus: new Array( versus_string_array.length - 1 ) // All other elements are versus ids (with win counts).
      };

      this.gid_versus_array.push( gid_versus );

      // Parse every versus (i.e. EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount)
      for ( let i = 1; i < versus_string_array.length; ++i ) {
        let versus_parts = versus_string_array[ i ].split( this.VersusId_WinCount_SplittingRegExp );

        // Got winCount.
        let versus = { winCount: Number.parseInt( versus_parts[ 1 ], 10 ) };
        gid_versus.versus[ i - 1 ] = versus;

        let versusId = versus_parts[ 0 ];
        let versusId_parts = versusId.split( this.EntityNo_ParentGenerationNo_OffspringGenerationNo_SplittingRegExp );

        // Got id of entity, parentGeneration, offspringGeneration.
        versus.entityNo = versusId_parts[ 0 ];
        versus.parentGenerationNo = versusId_parts[ 1 ];
        versus.offspringGenerationNo = versusId_parts[ 2 ];
      }
    }

//!!! ...unfinished... report progress.
  }

  downloadEntity( progress ) {

//!!! ...unfinished... Which gid number should be used.
//    let gid = ???;
    let replaceContext = `$1${gid}`;
    let url = this.summaryURL.replace( this.gidReplacingRegExp, replaceContext );

    // Parent and offspring.
  }

}
<commit_msg>Update Summary.js<commit_after>import * as NetProgress from "../NetProgress.js";
import * as tdTextExtracter from "../../util/tdTextExtracter.js";
import * as Versus from "./Versus.js";

export { NetProgress, Base };

/**
 * Download differential evolution summary and individual versus (entity vs entity) from network (a publish html of Google Sheets).
 *
 * The format of differential evolution summary page is the following:
 *
 *
 *   PopulationSize
 *   EntityWeightCount
 *   EntityChromosomeCount
 *   gid|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|...
 *   gid|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|...
 *   gid|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|...
 *     :
 *     :
 *
 *
 * The PopulationSize represents how many entities in the differential evolution.
 * The EntityChromosomeCount represents How many chromsomes in one entity.
 * The ChromosomeWeightCount represents how many weights in one chromsome.
 *
 * The gid is the Google Sheet's id which will be used to form the url when download every individual versus.
 * Every gid contains one or more versus which are separated by vertical bar (|).
 * A versus contains versus id (EntityNo_ParentGenerationNo_OffspringGenerationNo) and its WinCount which are separated by colon (:).
 * A versus id contains EntityNo, ParentGenerationNo, OffspringGenerationNo which are separated by underline (_).
 *
 *
 */
class Base {

  /**
   *
   */
  constructor() {

    // Regular expression for splitting gid and every versus.
    this.gid_Versus_SplittingRegExp = RegExp( "|", "g" );

    // Regular expression for splitting versus id and win count
    this.VersusId_WinCount_SplittingRegExp = RegExp( ":", "g" );

    // Regular expression for splitting ids of entity, parent generation, offspring generation.
    this.EntityNo_ParentGenerationNo_OffspringGenerationNo_SplittingRegExp = RegExp( "_", "g" );

    // Regular expression for replacing the "nnn" of "gid=nnn" inside the published web page URL.
    this.gidReplacingRegExp = RegExp( "(gid=)(\d+)", "g" );
  }

  /**
   * Fetch and extract.
   *
   * @param summaryURL
   *   The published (should be html, not tsv, not csv) web page URL of the summary sheet of the differential evolution Google Sheets. For example:
   * "https://docs.google.com/spreadsheets/d/e/2PACX-1vSzA4SXUR5VyPmJ1cLEkNMiJgfb28zzgp4HtwoBlumIIOTkL_y7mgPldqaGtsunIq5eTu5QndluyFcV/pubhtml?gid=0&single=true".
   * The "gid=0" inside the URL will be replaced with different number when downloading other published sheet.
   */
  async downloadSummary( summaryURL, progress ) {

    // Why using published html web page instead of tsv (or csv)? This is because Google Sheets' published html web page support cross-origin
    // resource sharing (CORS) while its published web page tsv (or csv) does not.
    this.summaryURL = summaryURL;

    let response = await fetch( this.summaryURL );

    let lineMatches = tdTextExtracter.Base.createIterator( response.text() ); // Only capture group 1 will be used.
    let lineMatch;

    if ( ( lineMatch = lineMatches.next() ).done )
      return;

    // 1.
    this.PopulationSize = Number.parseInt( lineMatch.value[ 1 ], 10 );

    if ( ( lineMatch = lineMatches.next() ).done )
      return;

    // 2.
    this.EntityChromosomeCount = Number.parseInt( lineMatch.value[ 1 ], 10 );

    if ( ( lineMatch = lineMatches.next() ).done )
      return;

    // 3.
    this.ChromosomeWeightCount = Number.parseInt( lineMatch.value[ 1 ], 10 );
    this.EntityWeightCount = this.EntityChromosomeCount * this.ChromosomeWeightCount; // There are how many weights in one entity.

    // 4. Parse every gid and their corresponding versus ids (with win counts).
    this.gid_versus_array = [];
    while ( !( lineMatch = lineMatch.next() ).done ) {

      // Split the text of a td tag.
      //
      //   gid|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount|...
      //
      // They are separated by vertical bar (|).
      let versus_string_array = lineMatch.value[ 1 ].split( this.gid_Versus_SplittingRegExp );
      if ( versus_string_array.length <= 1 )
        continue; // At least, should be 2. The first one is gid, the second (and after) are versus ids (with win counts)

      // 4.1 Got gid.
      let gid_versus = {
        gid: versus_string_array[ 0 ], // Element 0 is gid.
        versus: new Array( versus_string_array.length - 1 ) // All other elements are versus ids (with win counts).
      };

      this.gid_versus_array.push( gid_versus );

      // 4.2 Parse every versus.
      for ( let i = 1; i < versus_string_array.length; ++i ) {

        // Split the versus id and win count.
        //
        //   EntityNo_ParentGenerationNo_OffspringGenerationNo:WinCount
        //
        // They are separated by colon (:).
        let versus_parts = versus_string_array[ i ].split( this.VersusId_WinCount_SplittingRegExp );

        // 4.2.1 Got versus id and win count.
        let versus = { versusId: versus_parts[ 0 ], winCount: Number.parseInt( versus_parts[ 1 ], 10 ) };
        gid_versus.versus[ i - 1 ] = versus;

        // Split the versus id inside.
        //
        //   EntityNo_ParentGenerationNo_OffspringGenerationNo
        //
        // They are separated by underline (_).
        let versusId_parts = versus.versusId.split( this.EntityNo_ParentGenerationNo_OffspringGenerationNo_SplittingRegExp );

        // 4.2.2 Got id of entity, parentGeneration, offspringGeneration.
        versus.entityNo = versusId_parts[ 0 ];
        versus.parentGenerationNo = versusId_parts[ 1 ];
        versus.offspringGenerationNo = versusId_parts[ 2 ];
      }
    }

//!!! ...unfinished... report progress.
  }

  downloadEntity( progress ) {

//!!! ...unfinished... Which gid number should be used.
//    let gid = ???;
    let replaceContext = `$1${gid}`;
    let url = this.summaryURL.replace( this.gidReplacingRegExp, replaceContext );

    // Parent and offspring.
  }

}
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var request = require('request');
var cheerio = require('cheerio');
var favicon = require('favicon');

var Site = mongoose.model('site');

module.exports.get = function(site, discord, cb) {
    Site.find({name:site}, function(err, sites) {
        if (err) return console.log(err);

        var siteData = sites[0];

        if (siteData.profileType) {
            console.log('Profile option found!');

            if (siteData.profileType=='website') getWebsiteProfile(site,cb);
            if (siteData.profileType=='favicon') getFavicon(site,cb);
            if (siteData.profileType=='discord') discord.getProfile(site,cb);
        } else {
            console.log('No profile option found. Setting option to default...');
            Site.update({name:site}, {
                profileType: 'website'
            }, function(err) {
                if (err) return console.log(err);

                getWebsiteProfile(site, cb);
            });
        }
    });
}

function getWebsiteProfile(site, cb) {
    request('https://neocities.org/site/'+site, function(err, response, body) {
        if (err) return console.log(err);

        var $ = cheerio.load(body);
        cb('https://neocities.org'+$('.screenshot').attr('style').replace('background-image:url(','').replace(');',''));
    });
}
function getFavicon(site, cb) {
    favicon('https://'+site+'.neocities.org', function(err, url) {
        if (err) return console.log(err);
        cb(url);
    });
}<commit_msg>Fixed some favicon urls not being the full url<commit_after>var mongoose = require('mongoose');
var request = require('request');
var cheerio = require('cheerio');
var favicon = require('favicon');

var Site = mongoose.model('site');

module.exports.get = function(site, discord, cb) {
    Site.find({name:site}, function(err, sites) {
        if (err) return console.log(err);

        var siteData = sites[0];

        if (siteData.profileType) {
            console.log('Profile option found!');

            if (siteData.profileType=='website') getWebsiteProfile(site,cb);
            if (siteData.profileType=='favicon') getFavicon(site,cb);
            if (siteData.profileType=='discord') discord.getProfile(site,cb);
        } else {
            console.log('No profile option found. Setting option to default...');
            Site.update({name:site}, {
                profileType: 'website'
            }, function(err) {
                if (err) return console.log(err);

                getWebsiteProfile(site, cb);
            });
        }
    });
}

function getWebsiteProfile(site, cb) {
    request('https://neocities.org/site/'+site, function(err, response, body) {
        if (err) return console.log(err);

        var $ = cheerio.load(body);
        cb('https://neocities.org'+$('.screenshot').attr('style').replace('background-image:url(','').replace(');',''));
    });
}
function getFavicon(site, cb) {
    favicon('https://'+site+'.neocities.org', function(err, url) {
        if (err) return console.log(err);
        if (url.indexOf('http')>-1) {
            cb(url);
        }
        else {
            if (url[0]=='/') {
                cb('https://'+site+'.neocities.org'+url);
            }
            else {
                cb('https://'+site+'.neocities.org/'+url);
            }
        }
    });
}<|endoftext|>


<commit_before>var FacebookStrategy = require('passport-facebook').Strategy;

exports.strategy = function (core) {
  return new FacebookStrategy({
      clientID: core.config.passport.FACEBOOK_APP_ID,
      clientSecret: core.config.passport.FACEBOOK_APP_SECRET,
      callbackURL: core.config.hostUrl + 'auth/facebook/callback'
    },
    function (accessToken, refreshToken, profile, done) {
      console.log('==============');
      console.log(profile);
      console.log('==============');
      var email = profile.emails[0].value;
      if (email) {
        core.model.Users.processOAuthProfile(email,done);
      } else {
        return done(new Error('There is something strange instead of user profile'));
      }
    });
};

exports.routes = function(passport,core){
  core.app.get('/auth/facebook', passport.authenticate('facebook'));
  core.app.get('/auth/facebook/callback', passport.authenticate('facebook', { successRedirect: '/', failureRedirect: '/' }));
};<commit_msg>[fix] - auth facebook works<commit_after>var FacebookStrategy = require('passport-facebook').Strategy;

exports.strategy = function (core) {
  return new FacebookStrategy({
      clientID: core.config.passport.FACEBOOK_APP_ID,
      clientSecret: core.config.passport.FACEBOOK_APP_SECRET,
      callbackURL: core.config.hostUrl + 'auth/facebook/callback',
      passReqToCallback: true
    },
    function (request, accessToken, refreshToken, profile, done) {
//    console.log('==============AUTH VIA FACEBOOK');
//    console.log(profile);
//    console.log('==============');
      if (profile.provider === 'facebook' && profile.id) {
        if (request.user) {
          //attaching github profile
          request.user.setKeyChain('facebook', profile.id, function (err) {
            if (err) {
              throw err;
            }
            request.flash('success', 'Your facebook profile has been attached to your account! You can authorize via facebook.com now!');
            core.model.Users.findOneByKeychain('facebook', profile.id, function (err, userFound) {
              done(err, userFound);
            });
          });
        } else {
          core.model.Users.findOneByKeychain('facebook', profile.id, function (err, userFound) {
            if (err) {
              done(err);
            } else {
              if (userFound) {
                done(null, userFound);
              } else {
                request.flash('error', 'Unable to signin via facebook.com! Please, register with username, email and password and than attach your facebook profile to it!');
                done(null, false);
              }
            }
          });
        }
      } else {
        return done(new Error('There is something strange instead of user profile!'));
      }
    });
};

exports.routes = function (passport, core) {
  core.app.get('/auth/facebook', passport.authenticate('facebook'));
  core.app.get('/auth/facebook/callback', passport.authenticate('facebook', { successRedirect: '/', failureRedirect: '/' }));
};

<|endoftext|>


<commit_before>/**
 * Created by huanli<klx211@gmail.com> on 1/6/15.
 *
 * Variable prefixes' meanings:
 * -------------------------------------------------------------------------
 * --- The prefix of a variable's name reveals the type of data it holds ---
 * -------------------------------------------------------------------------
 *
 * a: Array
 * b: Boolean
 * d: DOM
 * f: Function
 * l: List(an array-like object)
 * n: Number
 * o: Object
 * r: Regular expression
 * s: String
 * x: More than one type
 *  : Special case or NOT my code
 *
 * *** These prefixes can be concatenated to indicate that the variable can
 *         hold the specified types of data ***
 */

(function () {

    'use strict';

    if (typeof jQuery === 'undefined') {

        throw 'k-draggable: jQuery must be present in order for the k-draggable directive to work correctly.';
    }
    /**
     * All the event subjects that will be emitted during the process of dragging.
     *
     * @author Kevin Li<klx211@gmail.com>
     * @type {Object}
     */
    var kDraggableEvents = {
            DRAG_START: 'kDraggableDragStart',
            DRAG_END: 'kDraggableDragEnd'
        },
        /**
         * All the class name constants.
         *
         * @author Kevin Li<klx211@gmail.com>
         * @type {Object}
         */
        kDraggableClassNames = {
            DRAGGABLE: 'k-draggable',
            DRAGGING: 'k-dragging',
            HANDLE: 'k-handle'
        };

    angular
        .module('kl.draggable', [])
        .constant('kDraggableEvents', kDraggableEvents)
        .constant('kDraggableClassNames', kDraggableClassNames)
        .factory('kDraggableService', kDraggableService)
        .directive('kDraggable', kDraggable);

    kDraggableService.$inject = [
        '$compile'
    ];

    kDraggable.$inject = [
        'kDraggableEvents',
        'kDraggableClassNames',
        '$document'
    ];

    function kDraggableService($compile) {

        return {
            makeDraggable: makeDraggable
        };

        /**
         * Make an HTML element draggable based on the configuration provided.
         *
         * @author Kevin Li<klx211@gmail.com>
         * @param {Object} oConfig A configuration object to make an HTML element draggable.
         * {
         *     xDraggable: {string|jQuery|Node}, Required. The jQuery selector of the target draggable HTML element, or
         *                                      a jQuery wrapper object of the target draggable HTML element, or the
         *                                      target draggable HTML element itself.
         *     sHandleSelector: {string}, Optional. The jQuery selector for the handle HTML element.
         *     bWithAlt: {boolean} Optional. Whether the Alt key should be held down during dragging.
         * }
         * @throws Will throw an error if the configuration object is absent.
         * @throws Will throw an error if the target draggable element's selector or itself is absent in the
         * configuration object.
         * @throws Will throw an error if the target draggable element selector or the jQuery object did not match any
         * element or matched more than one elements.
         */
        function makeDraggable(oConfig) {

            if (!angular.isObject(oConfig)) {

                throw 'k-draggable: The configuration object must be provided.';

            } else if (!angular.isString(oConfig.xDraggable) && !(oConfig.xDraggable instanceof jQuery) &&
                oConfig.xDraggable.nodeType !== Node.ELEMENT_NODE) {
                // A valid target draggable selector is absent,
                // it's not a jQuery object,
                // it's not a regular HTML element.

                throw 'k-draggable: The selector for selecting the target draggable HTML element, or a jQuery ' +
                'wrapper object of the target draggable HTML element, or the target draggable HTML element itself ' +
                'must be provided.';

            } else {

                var jqDraggable = angular.element(oConfig.xDraggable),
                    sHandleSelector = angular.isString(oConfig.sHandleSelector) && oConfig.sHandleSelector.length > 0 ?
                        oConfig.sHandleSelector : '';

                if (jqDraggable.length !== 1) {

                    throw 'k-draggable: No draggable element or more than one draggable elements were found.';

                } else {

                    jqDraggable.attr('k-draggable', sHandleSelector);

                    if (oConfig.bWithAlt === true) {

                        jqDraggable.attr('with-alt', '');
                    }
                    $compile(jqDraggable)(jqDraggable.scope());
                }

            }
        }
    }

    function kDraggable(kDE, kDCN, $document) {

        return {
            link: function (scope, element, attrs) {

                scope.bWithAlt = !angular.isUndefined(attrs.withAlt);

                element.addClass(kDCN.DRAGGABLE);

                var sHandleSelector = attrs.kDraggable,
                    jqHandleElement;

                if (angular.isString(sHandleSelector) && sHandleSelector.length > 0) {

                    jqHandleElement = element.find(sHandleSelector);

                    if (jqHandleElement.length > 0) {

                        if (!scope.bWithAlt) {

                            jqHandleElement.addClass(kDCN.HANDLE);
                        }

                    } else {

                        throw 'k-draggable: The selector `' + sHandleSelector +
                        '` does not match any HTML element who is a descendant of ' +
                        element;
                    }
                } else {

                    if (!scope.bWithAlt) {

                        element.addClass(kDCN.HANDLE);
                    }
                }

                registerListeners(scope, element, jqHandleElement);
            },
            restrict: 'AC',
            scope: {}
        };

        /**
         * Register all the necessary listeners for dragging an HTML element.
         *
         * @author Kevin Li<klx211@gmail.com>
         * @param {Object} oScope The directive's scope object.
         * @param {jQuery} jqDraggableElement The HTML element which is wrapped by jQuery and is to be dragged.
         * @param {jQuery} jqHE The HTML element which is wrapped by jQuery and is the handle for dragging.
         */
        function registerListeners(oScope, jqDraggableElement, jqHE) {

            jqHE = jqHE || jqDraggableElement;

            if (oScope.bWithAlt) {

                $document
                    .on('keydown', function (oEvent) {

                        if (oEvent.keyCode === 18) {
                            // The Alt key
                            jqHE.addClass(kDCN.HANDLE);
                        }
                    })
                    .on('keyup', function (oEvent) {

                        if (oEvent.keyCode === 18) {
                            // The Alt key
                            jqHE.removeClass(kDCN.HANDLE);
                        }
                    });
            }
            jqHE.on('mousedown', onMousedown);
            /**
             * The event handler of the mousedown event.
             *
             * @author Kevin Li<klx211@gmail.com>
             * @param {Object} oEvent The jQuery's event object.
             */
            function onMousedown(oEvent) {

                if (oEvent.target === this ||
                    jqHE === jqDraggableElement && jqDraggableElement.find(oEvent.target).length > 0) {
                    // The HTML element on which the mousedown event is triggered must be the handle element itself,
                    // instead of any children of the handle element.
                    // If the handle element is just the draggable element itself, the HTML element on which the
                    // mousedown event is triggered must be a descendant of the draggable element.

                    if (oScope.bWithAlt && oEvent.altKey || !oScope.bWithAlt) {
                        // The Alt key must be held down in order to start dragging,
                        // and the Alt key is indeed held down,
                        // or the Alt key is not required to start dragging.

                        oEvent.stopPropagation();
                        oEvent.preventDefault();
                        /**
                         * The value of left property of the HTML element to be dragged when the mouse button is held
                         * down.
                         *
                         * @author Kevin Li<klx211@gmail.com>
                         * @type {number}
                         */
                        var nElementLeft = jqDraggableElement.position().left,
                            /**
                             * The value of top property of the HTML element to be dragged when the mouse button is held
                             * down.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @type {number}
                             */
                            nElementTop = jqDraggableElement.position().top,
                            /**
                             * The X position of the mouse cursor when the mouse button is held down.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @type {number}
                             */
                            nMouseX = oEvent.pageX,
                            /**
                             * The Y position of the mouse cursor when the mouse button is held down.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @type {number}
                             */
                            nMouseY = oEvent.pageY,
                            /**
                             * A counter to tell whether it's the first time to move the mouse after the mouse button is
                             * held down.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @type {number}
                             */
                            nCounter = 0,
                            /**
                             * The event handler of the mousemove event.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @param {Object} oEvent The jQuery's event object.
                             */
                            onMousemove = function (oEvent) {

                                if (nCounter === 0) {

                                    // This is the first move of the mouse after the mouse button is held down.
                                    nCounter += 1;
                                    oScope.$emit(kDE.DRAG_START);
                                }

                                jqDraggableElement.css({
                                    left: nElementLeft + (oEvent.pageX - nMouseX),
                                    top: nElementTop + (oEvent.pageY - nMouseY)
                                });
                            },
                            /**
                             * The event handler of the mouseup event.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @param {Object} oEvent The jQuery's event object.
                             */
                            onMouseup = function (oEvent) {

                                $document
                                    .off('mousemove', onMousemove)
                                    .off('mouseup', onMouseup);

                                // Remove the box shadows so that it looks like the HTML element has just been put down.
                                jqDraggableElement.removeClass(kDCN.DRAGGING);

                                // Reset the counter when the mouse button is released.
                                nCounter = 0;
                                oScope.$emit(kDE.DRAG_END);
                            },
                            onKeyup = function (oEvent) {

                                oEvent.preventDefault();
                                oEvent.stopPropagation();

                                if (oEvent.keyCode === 18) {
                                    // The Alt key
                                    $document
                                        .trigger(jQuery.Event('mouseup'))
                                        .off('keyup', onKeyup);
                                }
                            };

                        if (oScope.bWithAlt) {
                            // The Alt key must be held down in order to start dragging,
                            $document.on('keyup', onKeyup);
                        }
                        // Add box shadows so that it looks like the HTML element has just been lifted up.
                        jqDraggableElement.addClass(kDCN.DRAGGING);

                        $document
                            .on('mousemove', onMousemove)
                            .on('mouseup', onMouseup);
                    }
                }
            }
        }
    }

}());<commit_msg> * Renamed two variables.<commit_after>/**
 * Created by huanli<klx211@gmail.com> on 1/6/15.
 *
 * Variable prefixes' meanings:
 * -------------------------------------------------------------------------
 * --- The prefix of a variable's name reveals the type of data it holds ---
 * -------------------------------------------------------------------------
 *
 * a: Array
 * b: Boolean
 * d: DOM
 * f: Function
 * l: List(an array-like object)
 * n: Number
 * o: Object
 * r: Regular expression
 * s: String
 * x: More than one type
 *  : Special case or NOT my code
 *
 * *** These prefixes can be concatenated to indicate that the variable can
 *         hold the specified types of data ***
 */

(function () {

    'use strict';

    if (typeof jQuery === 'undefined') {

        throw 'k-draggable: jQuery must be present in order for the k-draggable directive to work correctly.';
    }
    /**
     * All the event subjects that will be emitted during the process of dragging.
     *
     * @author Kevin Li<klx211@gmail.com>
     * @type {Object}
     */
    var kDraggableEvents = {
            DRAG_START: 'kDraggableDragStart',
            DRAG_END: 'kDraggableDragEnd'
        },
        /**
         * All the class name constants.
         *
         * @author Kevin Li<klx211@gmail.com>
         * @type {Object}
         */
        kDraggableClassNames = {
            DRAGGABLE: 'k-draggable',
            DRAGGING: 'k-dragging',
            HANDLE: 'k-handle'
        };

    angular
        .module('kl.draggable', [])
        .constant('kDraggableEvents', kDraggableEvents)
        .constant('kDraggableClassNames', kDraggableClassNames)
        .factory('kDraggableService', kDraggableService)
        .directive('kDraggable', kDraggable);

    kDraggableService.$inject = [
        '$compile'
    ];

    kDraggable.$inject = [
        'kDraggableEvents',
        'kDraggableClassNames',
        '$document'
    ];

    function kDraggableService($compile) {

        return {
            makeDraggable: makeDraggable
        };

        /**
         * Make an HTML element draggable based on the configuration provided.
         *
         * @author Kevin Li<klx211@gmail.com>
         * @param {Object} oConfig A configuration object to make an HTML element draggable.
         * {
         *     xDraggable: {string|jQuery|Node}, Required. The jQuery selector of the target draggable HTML element, or
         *                                      a jQuery wrapper object of the target draggable HTML element, or the
         *                                      target draggable HTML element itself.
         *     sDragHandle: {string}, Optional. The jQuery selector for the handle HTML element.
         *     bWithAlt: {boolean} Optional. Whether the Alt key should be held down during dragging.
         * }
         * @throws Will throw an error if the configuration object is absent.
         * @throws Will throw an error if the target draggable element's selector or itself is absent in the
         * configuration object.
         * @throws Will throw an error if the target draggable element selector or the jQuery object did not match any
         * element or matched more than one elements.
         */
        function makeDraggable(oConfig) {

            if (!angular.isObject(oConfig)) {

                throw 'k-draggable: The configuration object must be provided.';

            } else if (!angular.isString(oConfig.xDraggable) &&
                !(oConfig.xDraggable instanceof jQuery) &&
                oConfig.xDraggable.nodeType !== Node.ELEMENT_NODE) {
                // It's not a string,
                // it's not a jQuery object,
                // it's not a regular HTML element.

                throw 'k-draggable: The selector for selecting the target draggable HTML element, or a jQuery ' +
                'wrapper object of the target draggable HTML element, or the target draggable HTML element itself ' +
                'must be provided.';

            } else {

                var jqDraggable = angular.element(oConfig.xDraggable),
                    sDragHandle = angular.isString(oConfig.sDragHandle) && oConfig.sDragHandle.length > 0 ?
                        oConfig.sDragHandle : '';

                if (jqDraggable.length !== 1) {

                    throw 'k-draggable: No draggable element or more than one draggable elements were found.';

                } else {

                    jqDraggable.attr('k-draggable', sDragHandle);

                    if (oConfig.bWithAlt === true) {

                        jqDraggable.attr('with-alt', '');
                    }
                    $compile(jqDraggable)(jqDraggable.scope());
                }

            }
        }
    }

    function kDraggable(kDE, kDCN, $document) {

        return {
            link: function (scope, element, attrs) {

                scope.bWithAlt = !angular.isUndefined(attrs.withAlt);

                element.addClass(kDCN.DRAGGABLE);

                var sDragHandle = attrs.kDraggable,
                    jqHandleElement;

                if (angular.isString(sDragHandle) && sDragHandle.length > 0) {

                    jqHandleElement = element.find(sDragHandle);

                    if (jqHandleElement.length > 0) {

                        if (!scope.bWithAlt) {

                            jqHandleElement.addClass(kDCN.HANDLE);
                        }

                    } else {

                        throw 'k-draggable: The selector `' + sDragHandle +
                        '` does not match any HTML element who is a descendant of ' +
                        element;
                    }
                } else {

                    if (!scope.bWithAlt) {

                        element.addClass(kDCN.HANDLE);
                    }
                }

                registerListeners(scope, element, jqHandleElement);
            },
            restrict: 'AC',
            scope: {}
        };

        /**
         * Register all the necessary listeners for dragging an HTML element.
         *
         * @author Kevin Li<klx211@gmail.com>
         * @param {Object} oScope The directive's scope object.
         * @param {jQuery} jqDraggableElement The HTML element which is wrapped by jQuery and is to be dragged.
         * @param {jQuery} jqHE The HTML element which is wrapped by jQuery and is the handle for dragging.
         */
        function registerListeners(oScope, jqDraggableElement, jqHE) {

            jqHE = jqHE || jqDraggableElement;

            if (oScope.bWithAlt) {

                $document
                    .on('keydown', function (oEvent) {

                        if (oEvent.keyCode === 18) {
                            // The Alt key
                            jqHE.addClass(kDCN.HANDLE);
                        }
                    })
                    .on('keyup', function (oEvent) {

                        if (oEvent.keyCode === 18) {
                            // The Alt key
                            jqHE.removeClass(kDCN.HANDLE);
                        }
                    });
            }
            jqHE.on('mousedown', onMousedown);
            /**
             * The event handler of the mousedown event.
             *
             * @author Kevin Li<klx211@gmail.com>
             * @param {Object} oEvent The jQuery's event object.
             */
            function onMousedown(oEvent) {

                if (oEvent.target === this ||
                    jqHE === jqDraggableElement && jqDraggableElement.find(oEvent.target).length > 0) {
                    // The HTML element on which the mousedown event is triggered must be the handle element itself,
                    // instead of any children of the handle element.
                    // If the handle element is just the draggable element itself, the HTML element on which the
                    // mousedown event is triggered must be a descendant of the draggable element.

                    if (oScope.bWithAlt && oEvent.altKey || !oScope.bWithAlt) {
                        // The Alt key must be held down in order to start dragging,
                        // and the Alt key is indeed held down,
                        // or the Alt key is not required to start dragging.

                        oEvent.stopPropagation();
                        oEvent.preventDefault();
                        /**
                         * The value of left property of the HTML element to be dragged when the mouse button is held
                         * down.
                         *
                         * @author Kevin Li<klx211@gmail.com>
                         * @type {number}
                         */
                        var nElementLeft = jqDraggableElement.position().left,
                            /**
                             * The value of top property of the HTML element to be dragged when the mouse button is held
                             * down.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @type {number}
                             */
                            nElementTop = jqDraggableElement.position().top,
                            /**
                             * The X position of the mouse cursor when the mouse button is held down.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @type {number}
                             */
                            nMouseX = oEvent.pageX,
                            /**
                             * The Y position of the mouse cursor when the mouse button is held down.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @type {number}
                             */
                            nMouseY = oEvent.pageY,
                            /**
                             * A counter to tell whether it's the first time to move the mouse after the mouse button is
                             * held down.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @type {number}
                             */
                            nCounter = 0,
                            /**
                             * The event handler of the mousemove event.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @param {Object} oEvent The jQuery's event object.
                             */
                            onMousemove = function (oEvent) {

                                if (nCounter === 0) {

                                    // This is the first move of the mouse after the mouse button is held down.
                                    nCounter += 1;
                                    oScope.$emit(kDE.DRAG_START);
                                }

                                jqDraggableElement.css({
                                    left: nElementLeft + (oEvent.pageX - nMouseX),
                                    top: nElementTop + (oEvent.pageY - nMouseY)
                                });
                            },
                            /**
                             * The event handler of the mouseup event.
                             *
                             * @author Kevin Li<klx211@gmail.com>
                             * @param {Object} oEvent The jQuery's event object.
                             */
                            onMouseup = function (oEvent) {

                                $document
                                    .off('mousemove', onMousemove)
                                    .off('mouseup', onMouseup);

                                // Remove the box shadows so that it looks like the HTML element has just been put down.
                                jqDraggableElement.removeClass(kDCN.DRAGGING);

                                // Reset the counter when the mouse button is released.
                                nCounter = 0;
                                oScope.$emit(kDE.DRAG_END);
                            },
                            onKeyup = function (oEvent) {

                                oEvent.preventDefault();
                                oEvent.stopPropagation();

                                if (oEvent.keyCode === 18) {
                                    // The Alt key
                                    $document
                                        .trigger(jQuery.Event('mouseup'))
                                        .off('keyup', onKeyup);
                                }
                            };

                        if (oScope.bWithAlt) {
                            // The Alt key must be held down in order to start dragging,
                            $document.on('keyup', onKeyup);
                        }
                        // Add box shadows so that it looks like the HTML element has just been lifted up.
                        jqDraggableElement.addClass(kDCN.DRAGGING);

                        $document
                            .on('mousemove', onMousemove)
                            .on('mouseup', onMouseup);
                    }
                }
            }
        }
    }

}());<|endoftext|>


<commit_before>var stream = require('stream');
var util = require('util');
var promise = require('rsvp');
var gh = require('../github/repos');

function Repos( data ) {
  this._data = data;
  stream.Transform.call(this, { objectMode: true });
}

Repos.supported = gh.Repos.supported;

util.inherits(Repos, stream.Transform);

Repos.prototype._transform = function(line, encode, done) {
  var user, repos;

  user = line.toString();

  var repos = new gh.Repos(user);

  repos[this._data]().then(function(data) {
    this.push(data.join("\n"));
  }.bind(this)).catch(function(error) {
    console.log( error.stack );
  });
};

module.exports = Repos;
<commit_msg>remove stack print<commit_after>var stream = require('stream');
var util = require('util');
var promise = require('rsvp');
var gh = require('../github/repos');

function Repos( data ) {
  this._data = data;
  stream.Transform.call(this, { objectMode: true });
}

Repos.supported = gh.Repos.supported;

util.inherits(Repos, stream.Transform);

Repos.prototype._transform = function(line, encode, done) {
  var user, repos;

  user = line.toString();

  var repos = new gh.Repos(user);

  repos[this._data]().then(function(data) {
    this.push(data.join("\n"));
  }.bind(this));
};

module.exports = Repos;
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
  getBlankQuest,
  getQuestFromProps,
  getQuizStatefromQuest
} from '../../libs/quizHelper'
import RaisedButton from 'material-ui/RaisedButton'
import FlatButton from 'material-ui/FlatButton'
import TextField from 'material-ui/TextField'
import Snackbar from 'material-ui/Snackbar'
import './bubble.css'

const getFloatingLabelText = form => {
  switch (form) {
    case 'subject':
      return 'Subject'
    case 'category':
      return 'Category'
    case 'question':
      return 'Question'
    case 'choice_0':
      return 'Answer'
    case 'choice_1':
      return 'Choice 1'
    case 'choice_2':
      return 'Choice 2'
    default:
      return form
  }
}

class QuizInput extends Component {
  constructor (props, context) {
    super(props, context)
    let quest = getQuestFromProps(props.quest)
    this.state = getQuizStatefromQuest(quest)
  }

  handleSubmit = e => {
    const { newQuiz, onSave } = this.props

    // Save quiz
    const {
      subject,
      category,
      question,
      choice_0,
      choice_1,
      choice_2
    } = this.state
    onSave({ subject, category, question, choice_0, choice_1, choice_2 })

    if (newQuiz) {
      this.setState(getBlankQuest())
    }
  }

  handleChange = e => {
    this.setState({ [e.target.name]: e.target.value })
  }

  handleDoubleClick = form => {
    this.setState({ isEditing: { [form]: true } })
  }

  handleBlur = form => {
    const { newQuiz, onSave } = this.props
    if (!newQuiz) {
      let keys = form.split('_')
      let quiz = keys[0] === 'choice'
        ? { [keys[1]]: this.state[form] }
        : { [form]: this.state[form] }
      let isChoice = keys[0] === 'choice'
      onSave(quiz, isChoice)
      this.setState({ isEditing: { [form]: false } })
    }
  }

  handleRequestClose = () => {
    this.setState({
      open: false
    })
  }

  renderForm (form, autoFocus) {
    const { newQuiz } = this.props

    if (this.state.isEditing[form] || newQuiz) {
      return (

          <TextField
            ref={form}
            type='text'
            name={form}
            floatingLabelText={getFloatingLabelText(form)}
            // defaultValue={this.state[form]}
            value={this.state[form]}
            autoFocus={autoFocus || this.state.isEditing[form]}
            onChange={this.handleChange}
            onBlur={() => this.handleBlur(form)}
          />

      )
    } else if (form.indexOf('choice') > -1) {
      return (

          <FlatButton
            label={this.state[form]}
            onTouchTap={() => this.handleDoubleClick(form)}
            style={{
              maxWidth: '260px',
              width: '100%',
              margin: '0px',
              borderRadius: '25px',
              marginLeft: '5%',
              marginRight: '5%',
              borderStyle: 'solid',
              borderWidth: 'thin',
              borderColor: 'darkgrey'
            }}
          />

      )
    } else {
      return (

 this.handleDoubleClick(form)}
          >

              {getFloatingLabelText(form)}: {this.state[form]}

      )
    }
  }

  renderSubmitButton () {
    const { newQuiz } = this.props
    if (newQuiz) {
      return (

          <RaisedButton
            type='submit'
            label='Submit'
            primary
            onTouchTap={this.handleSubmit}
          />
          <Snackbar
            open={this.state.open}
            message='Quiz added'
            autoHideDuration={4000}
            onRequestClose={this.handleRequestClose}
          />

      )
    }
  }

  render () {
    const { idx, newQuiz } = this.props
    const autoFocus = true
    return (

        {idx &&
#{idx}
}
        {this.renderForm('subject', autoFocus)}
        {this.renderForm('category')}
        {this.renderForm('question')}
        {this.renderForm('choice_0')}
        {this.renderForm('choice_1')}
        {this.renderForm('choice_2')}
        {newQuiz && this.renderSubmitButton()}

    )
  }
}

QuizInput.propTypes = {
  idx: PropTypes.number,
  onSave: PropTypes.func.isRequired,
  quest: PropTypes.object,
  newQuiz: PropTypes.bool
}

export default QuizInput
<commit_msg>Add margin left and rigth<commit_after>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
  getBlankQuest,
  getQuestFromProps,
  getQuizStatefromQuest
} from '../../libs/quizHelper'
import RaisedButton from 'material-ui/RaisedButton'
import FlatButton from 'material-ui/FlatButton'
import TextField from 'material-ui/TextField'
import Snackbar from 'material-ui/Snackbar'
import './bubble.css'

const getFloatingLabelText = form => {
  switch (form) {
    case 'subject':
      return 'Subject'
    case 'category':
      return 'Category'
    case 'question':
      return 'Question'
    case 'choice_0':
      return 'Answer'
    case 'choice_1':
      return 'Choice 1'
    case 'choice_2':
      return 'Choice 2'
    default:
      return form
  }
}

class QuizInput extends Component {
  constructor (props, context) {
    super(props, context)
    let quest = getQuestFromProps(props.quest)
    this.state = getQuizStatefromQuest(quest)
  }

  handleSubmit = e => {
    const { newQuiz, onSave } = this.props

    // Save quiz
    const {
      subject,
      category,
      question,
      choice_0,
      choice_1,
      choice_2
    } = this.state
    onSave({ subject, category, question, choice_0, choice_1, choice_2 })

    if (newQuiz) {
      this.setState(getBlankQuest())
    }
  }

  handleChange = e => {
    this.setState({ [e.target.name]: e.target.value })
  }

  handleDoubleClick = form => {
    this.setState({ isEditing: { [form]: true } })
  }

  handleBlur = form => {
    const { newQuiz, onSave } = this.props
    if (!newQuiz) {
      let keys = form.split('_')
      let quiz = keys[0] === 'choice'
        ? { [keys[1]]: this.state[form] }
        : { [form]: this.state[form] }
      let isChoice = keys[0] === 'choice'
      onSave(quiz, isChoice)
      this.setState({ isEditing: { [form]: false } })
    }
  }

  handleRequestClose = () => {
    this.setState({
      open: false
    })
  }

  renderForm (form, autoFocus) {
    const { newQuiz } = this.props

    if (this.state.isEditing[form] || newQuiz) {
      return (

          <TextField
            ref={form}
            type='text'
            name={form}
            floatingLabelText={getFloatingLabelText(form)}
            // defaultValue={this.state[form]}
            value={this.state[form]}
            autoFocus={autoFocus || this.state.isEditing[form]}
            onChange={this.handleChange}
            onBlur={() => this.handleBlur(form)}
          />

      )
    } else if (form.indexOf('choice') > -1) {
      return (

          <FlatButton
            label={this.state[form]}
            onTouchTap={() => this.handleDoubleClick(form)}
            style={{
              maxWidth: '260px',
              width: '100%',
              margin: '0px',
              borderRadius: '25px',
              marginLeft: '5%',
              marginRight: '5%',
              borderStyle: 'solid',
              borderWidth: 'thin',
              borderColor: 'darkgrey'
            }}
          />

      )
    } else {
      return (

 this.handleDoubleClick(form)}
          >

              {getFloatingLabelText(form)}: {this.state[form]}

      )
    }
  }

  renderSubmitButton () {
    const { newQuiz } = this.props
    if (newQuiz) {
      return (

          <RaisedButton
            type='submit'
            label='Submit'
            primary
            onTouchTap={this.handleSubmit}
          />
          <Snackbar
            open={this.state.open}
            message='Quiz added'
            autoHideDuration={4000}
            onRequestClose={this.handleRequestClose}
          />

      )
    }
  }

  render () {
    const { idx, newQuiz } = this.props
    const autoFocus = true
    return (

        {idx &&
#{idx}
}
        {this.renderForm('subject', autoFocus)}
        {this.renderForm('category')}
        {this.renderForm('question')}
        {this.renderForm('choice_0')}
        {this.renderForm('choice_1')}
        {this.renderForm('choice_2')}
        {newQuiz && this.renderSubmitButton()}

    )
  }
}

QuizInput.propTypes = {
  idx: PropTypes.number,
  onSave: PropTypes.func.isRequired,
  quest: PropTypes.object,
  newQuiz: PropTypes.bool
}

export default QuizInput
<|endoftext|>


<commit_before>var mandrill = require('node-mandrill')
var templates = require('../templates')
var t = require('../translations').t
var log = require('debug')('democracyos:notifier:transports')

function setupMandrill(token) {
  if (!token || 'string' != typeof token) {
    throw new Error('Undefined or invalid mandrill API token')
  }

  log('Initializing mandrill with token "%s"', token)
  return mandrill(token)
}

function sendMandrill(opts, callback) {
  var to = resolveRecipient(opts.to)
  var from = opts.from || { email: 'noreply@democracyos.org', name: 'The DemocracyOS team' }

  // get mail body from jade template
  templates.jade(opts.template, opts.vars, function (err, body) {
    if (err) return callback(err);

    log('Sending email for "%s" job', opts.template)

    mandrill('/messages/send', {
      message: {
        to: to,
        from_email: from.email,
        from_name: from.name,
        subject: t('templates.' + opts.template + '.subject'),
        html: body
      }
    }, function (err, response) {
      if (err) log('Mandrill API error: %s', err)
      else log('Mandrill send successful: %s', response)

      if (callback) callback(err)
    })
  })
}

function resolveRecipient(obj) {
  if (Array.isArray(obj)) return obj
  if ('object' === typeof obj) return [obj]
  if ('string' === typeof obj) return { email: obj }

  throw new Error('Invalid or undefined recipient object')
}

/**
 * Module exports
 */
var exports = module.exports = function transports(config) {

  // setup mandrill
  mandrill = setupMandrill(config.mandrillToken)
  exports.mail = sendMandrill
}
<commit_msg>Update log usage<commit_after>var mandrill = require('node-mandrill')
var templates = require('../templates')
var t = require('../translations').t
var log = require('debug')('democracyos:notifier:transports')

function setupMandrill(token) {
  if (!token || 'string' != typeof token) {
    throw new Error('Undefined or invalid mandrill API token')
  }

  log('Initializing mandrill with token "%s"', token)
  return mandrill(token)
}

function sendMandrill(opts, callback) {
  var to = resolveRecipient(opts.to)
  var from = opts.from || { email: 'noreply@democracyos.org', name: 'The DemocracyOS team' }

  // get mail body from jade template
  templates.jade(opts.template, opts.vars, function (err, body) {
    if (err) return callback(err);

    log('Sending email for "%s" job', opts.template)

    mandrill('/messages/send', {
      message: {
        to: to,
        from_email: from.email,
        from_name: from.name,
        subject: t('templates.' + opts.template + '.subject'),
        html: body
      }
    }, function (err, response) {
      if (err) log('Mandrill API error: %j', err)
      else log('Mandrill send successful: %j', response)

      if (callback) callback(err)
    })
  })
}

function resolveRecipient(obj) {
  if (Array.isArray(obj)) return obj
  if ('object' === typeof obj) return [obj]
  if ('string' === typeof obj) return { email: obj }

  throw new Error('Invalid or undefined recipient object')
}

/**
 * Module exports
 */
var exports = module.exports = function transports(config) {

  // setup mandrill
  mandrill = setupMandrill(config.mandrillToken)
  exports.mail = sendMandrill
}
<|endoftext|>


<commit_before>import $ from 'jquery';
import _ from 'underscore';

import AccessWidget from 'girder/views/widgets/AccessWidget';
import CollectionModel from 'girder/models/CollectionModel';
import EditCollectionWidget from 'girder/views/widgets/EditCollectionWidget';
import FolderModel from 'girder/models/FolderModel';
import HierarchyWidget from 'girder/views/widgets/HierarchyWidget';
import router from 'girder/router';
import View from 'girder/views/View';
import { AccessType } from 'girder/constants';
import { cancelRestRequests } from 'girder/rest';
import { confirm } from 'girder/dialog';
import { renderMarkdown } from 'girder/misc';
import events from 'girder/events';

import CollectionPageTemplate from 'girder/templates/body/collectionPage.pug';

import 'girder/stylesheets/body/collectionPage.styl';

import 'bootstrap/js/dropdown';

/**
 * This view shows a single collection's page.
 */
var CollectionView = View.extend({
    events: {
        'click .g-edit-collection': 'editCollection',
        'click .g-collection-access-control': 'editAccess',
        'click .g-delete-collection': function () {
            confirm({
                text: 'Are you sure you want to delete the collection ' +
                      this.model.escape('name') + '?',
                yesText: 'Delete',
                escapedHtml: true,
                confirmCallback: _.bind(function () {
                    this.model.on('g:deleted', function () {
                        events.trigger('g:alert', {
                            icon: 'ok',
                            text: 'Collection deleted.',
                            type: 'success',
                            timeout: 4000
                        });
                        router.navigate('collections', {trigger: true});
                    }).destroy();
                }, this)
            });
        }
    },

    initialize: function (settings) {
        cancelRestRequests('fetch');

        this.upload = settings.upload || false;
        this.access = settings.access || false;
        this.edit = settings.edit || false;
        this.folderAccess = settings.folderAccess || false;
        this.folderCreate = settings.folderCreate || false;
        this.folderEdit = settings.folderEdit || false;
        this.itemCreate = settings.itemCreate || false;

        // If collection model is already passed, there is no need to fetch.
        if (settings.collection) {
            this.model = settings.collection;

            if (settings.folderId) {
                this.folder = new FolderModel();
                this.folder.set({
                    _id: settings.folderId
                }).on('g:fetched', function () {
                    this.render();
                }, this).on('g:error', function () {
                    this.folder = null;
                    this.render();
                }, this).fetch();
            } else {
                this.render();
            }
        } else if (settings.id) {
            this.model = new CollectionModel();
            this.model.set('_id', settings.id);

            this.model.on('g:fetched', function () {
                this.render();
            }, this).fetch();
        }
    },

    editCollection: function () {
        var container = $('#g-dialog-container');

        if (!this.editCollectionWidget) {
            this.editCollectionWidget = new EditCollectionWidget({
                el: container,
                model: this.model,
                parentView: this
            }).on('g:saved', function () {
                this.render();
            }, this);
        }
        this.editCollectionWidget.render();
    },

    render: function () {
        this.$el.html(CollectionPageTemplate({
            collection: this.model,
            AccessType: AccessType,
            renderMarkdown: renderMarkdown
        }));

        if (!this.hierarchyWidget) {
            // The HierarchyWidget will self-render when instantiated
            this.hierarchyWidget = new HierarchyWidget({
                el: this.$('.g-collection-hierarchy-container'),
                parentModel: this.folder || this.model,
                upload: this.upload,
                folderAccess: this.folderAccess,
                folderEdit: this.folderEdit,
                folderCreate: this.folderCreate,
                itemCreate: this.itemCreate,
                parentView: this
            }).on('g:setCurrentModel', () => {
                // When a user descends into the hierarchy, hide the collection
                // actions list to avoid confusion.
                this.$('.g-collection-header .g-collection-actions-button').hide();
            });
        } else {
            this.hierarchyWidget
                .setElement(this.$('.g-collection-hierarchy-container'))
                .render();
        }

        this.upload = false;
        this.folderAccess = false;
        this.folderEdit = false;
        this.folderCreate = false;
        this.itemCreate = false;

        if (this.edit) {
            this.editCollection();
        } else if (this.access) {
            this.editAccess();
        }

        return this;
    },

    editAccess: function () {
        new AccessWidget({
            el: $('#g-dialog-container'),
            modelType: 'collection',
            model: this.model,
            parentView: this
        }).on('g:accessListSaved', function (params) {
            if (params.recurse) {
                this.hierarchyWidget.refreshFolderList();
            }
        }, this);
    }
}, {
    /**
     * Helper function for fetching the user and rendering the view with
     * an arbitrary set of extra parameters.
     */
    fetchAndInit: function (cid, params) {
        var collection = new CollectionModel();
        collection.set({ _id: cid }).on('g:fetched', function () {
            events.trigger('g:navigateTo', CollectionView, _.extend({
                collection: collection
            }, params || {}));
        }, this).fetch();
    }
});

export default CollectionView;
<commit_msg>Client: Upgrade 'Action button' of collectionView<commit_after>import $ from 'jquery';
import _ from 'underscore';

import AccessWidget from 'girder/views/widgets/AccessWidget';
import CollectionModel from 'girder/models/CollectionModel';
import EditCollectionWidget from 'girder/views/widgets/EditCollectionWidget';
import FolderModel from 'girder/models/FolderModel';
import HierarchyWidget from 'girder/views/widgets/HierarchyWidget';
import router from 'girder/router';
import View from 'girder/views/View';
import { AccessType } from 'girder/constants';
import { cancelRestRequests } from 'girder/rest';
import { confirm } from 'girder/dialog';
import { renderMarkdown, formatSize } from 'girder/misc';
import events from 'girder/events';

import CollectionPageTemplate from 'girder/templates/body/collectionPage.pug';

import 'girder/stylesheets/body/collectionPage.styl';

import 'bootstrap/js/dropdown';

/**
 * This view shows a single collection's page.
 */
var CollectionView = View.extend({
    events: {
        'click .g-edit-collection': 'editCollection',
        'click .g-collection-access-control': 'editAccess',
        'click .g-delete-collection': function () {
            confirm({
                text: 'Are you sure you want to delete the collection ' +
                      this.model.escape('name') + '?',
                yesText: 'Delete',
                escapedHtml: true,
                additionalText: '' + this.model.escape('name') + '' +
                                ' contains ' + this.model.escape('nFolders') +
                                ' folders taking up ' +
                                formatSize(this.model.escape('size')) + '',
                msgConfirmation: true,
                name: this.model.escape('name'),
                confirmCallback: _.bind(function () {
                    this.model.on('g:deleted', function () {
                        events.trigger('g:alert', {
                            icon: 'ok',
                            text: 'Collection deleted.',
                            type: 'success',
                            timeout: 4000
                        });
                        router.navigate('collections', {trigger: true});
                    }).destroy();
                }, this)
            });
        }
    },

    initialize: function (settings) {
        cancelRestRequests('fetch');

        this.upload = settings.upload || false;
        this.access = settings.access || false;
        this.edit = settings.edit || false;
        this.folderAccess = settings.folderAccess || false;
        this.folderCreate = settings.folderCreate || false;
        this.folderEdit = settings.folderEdit || false;
        this.itemCreate = settings.itemCreate || false;

        // If collection model is already passed, there is no need to fetch.
        if (settings.collection) {
            this.model = settings.collection;

            if (settings.folderId) {
                this.folder = new FolderModel();
                this.folder.set({
                    _id: settings.folderId
                }).on('g:fetched', function () {
                    this.render();
                }, this).on('g:error', function () {
                    this.folder = null;
                    this.render();
                }, this).fetch();
            } else {
                this.render();
            }
        } else if (settings.id) {
            this.model = new CollectionModel();
            this.model.set('_id', settings.id);

            this.model.on('g:fetched', function () {
                this.render();
            }, this).fetch();
        }
    },

    editCollection: function () {
        var container = $('#g-dialog-container');

        if (!this.editCollectionWidget) {
            this.editCollectionWidget = new EditCollectionWidget({
                el: container,
                model: this.model,
                parentView: this
            }).on('g:saved', function () {
                this.render();
            }, this);
        }
        this.editCollectionWidget.render();
    },

    render: function () {
        this.$el.html(CollectionPageTemplate({
            collection: this.model,
            AccessType: AccessType,
            renderMarkdown: renderMarkdown
        }));

        if (!this.hierarchyWidget) {
            // The HierarchyWidget will self-render when instantiated
            this.hierarchyWidget = new HierarchyWidget({
                el: this.$('.g-collection-hierarchy-container'),
                parentModel: this.folder || this.model,
                upload: this.upload,
                folderAccess: this.folderAccess,
                folderEdit: this.folderEdit,
                folderCreate: this.folderCreate,
                itemCreate: this.itemCreate,
                parentView: this
            }).on('g:setCurrentModel', () => {
                // When a user descends into the hierarchy, hide the collection
                // actions list to avoid confusion.
                this.$('.g-collection-header .g-collection-actions-button').hide();
            });
        } else {
            this.hierarchyWidget
                .setElement(this.$('.g-collection-hierarchy-container'))
                .render();
        }

        this.upload = false;
        this.folderAccess = false;
        this.folderEdit = false;
        this.folderCreate = false;
        this.itemCreate = false;

        if (this.edit) {
            this.editCollection();
        } else if (this.access) {
            this.editAccess();
        }

        return this;
    },

    editAccess: function () {
        new AccessWidget({
            el: $('#g-dialog-container'),
            modelType: 'collection',
            model: this.model,
            parentView: this
        }).on('g:accessListSaved', function (params) {
            if (params.recurse) {
                this.hierarchyWidget.refreshFolderList();
            }
        }, this);
    }
}, {
    /**
     * Helper function for fetching the user and rendering the view with
     * an arbitrary set of extra parameters.
     */
    fetchAndInit: function (cid, params) {
        var collection = new CollectionModel();
        collection.set({ _id: cid }).on('g:fetched', function () {
            events.trigger('g:navigateTo', CollectionView, _.extend({
                collection: collection
            }, params || {}));
        }, this).fetch();
    }
});

export default CollectionView;
<|endoftext|>